url.cpp
Upload User: xhy777
Upload Date: 2007-02-14
Package Size: 24088k
Code Size: 22k
Category:

Windows Kernel

Development Platform:

Visual C++

  1. /*
  2.  * url.cpp - IUniformResourceLocator implementation for InternetShortcut class.
  3.  */
  4. /* Headers
  5.  **********/
  6. #include "project.hpp"
  7. #pragma hdrstop
  8. #include "assoc.h"
  9. #include "resource.h"
  10. /* Module Constants
  11.  *******************/
  12. #pragma data_seg(DATA_SEG_READ_ONLY)
  13. PRIVATE_DATA const char s_cszURLSeparator[]        = ":";
  14. PRIVATE_DATA const char s_cchURLSuffixSlash        = '/';
  15. PRIVATE_DATA const char s_cszURLPrefixesKey[]      = "Software\Microsoft\Windows\CurrentVersion\URL\Prefixes";
  16. PRIVATE_DATA const char s_cszDefaultURLPrefixKey[] = "Software\Microsoft\Windows\CurrentVersion\URL\DefaultPrefix";
  17. #pragma data_seg()
  18. /***************************** Private Functions *****************************/
  19. PRIVATE_CODE PCSTR SkipLeadingSlashes(PCSTR pcszURL)
  20. {
  21.    PCSTR pcszURLStart;
  22.    ASSERT(IS_VALID_STRING_PTR(pcszURL, CSTR));
  23.    // Skip two leading slashes.
  24.    if (pcszURL[0] == s_cchURLSuffixSlash &&
  25.        pcszURL[1] == s_cchURLSuffixSlash)
  26.    {
  27.       pcszURLStart = CharNext(pcszURL);
  28.       pcszURLStart = CharNext(pcszURLStart);
  29.    }
  30.    else
  31.       pcszURLStart = pcszURL;
  32.    ASSERT(IS_VALID_STRING_PTR(pcszURL, CSTR) &&
  33.           EVAL(IsStringContained(pcszURL, pcszURLStart)));
  34.    return(pcszURLStart);
  35. }
  36. PRIVATE_CODE HRESULT ApplyURLPrefix(PCSTR pcszURL, PSTR *ppszTranslatedURL)
  37. {
  38.    HRESULT hr = S_FALSE;
  39.    HKEY hkeyPrefixes;
  40.    ASSERT(IS_VALID_STRING_PTR(pcszURL, CSTR));
  41.    ASSERT(IS_VALID_WRITE_PTR(ppszTranslatedURL, PSTR));
  42.    *ppszTranslatedURL = NULL;
  43.    if (RegOpenKey(g_hkeyURLSettings, s_cszURLPrefixesKey, &hkeyPrefixes)
  44.        == ERROR_SUCCESS)
  45.    {
  46.       PCSTR pcszURLStart;
  47.       DWORD dwiValue;
  48.       char rgchValueName[MAX_PATH_LEN];
  49.       DWORD dwcbValueNameLen;
  50.       DWORD dwType;
  51.       char rgchPrefix[MAX_PATH_LEN];
  52.       DWORD dwcbPrefixLen;
  53.       pcszURLStart = SkipLeadingSlashes(pcszURL);
  54.       dwcbValueNameLen = sizeof(rgchValueName);
  55.       dwcbPrefixLen = sizeof(rgchPrefix);
  56.       for (dwiValue = 0;
  57.            RegEnumValue(hkeyPrefixes, dwiValue, rgchValueName,
  58.                         &dwcbValueNameLen, NULL, &dwType, (PBYTE)rgchPrefix,
  59.                         &dwcbPrefixLen) == ERROR_SUCCESS;
  60.            dwiValue++)
  61.       {
  62.          if (! lstrnicmp(pcszURLStart, rgchValueName, dwcbValueNameLen))
  63.          {
  64.             DWORD cbUrl = lstrlen(pcszURLStart);
  65.             // If the url==prefix, then we're calling the executable.
  66.             
  67.             if (cbUrl >= dwcbPrefixLen)
  68.             {
  69.                 // dwcbPrefixLen includes null terminator.
  70.                 *ppszTranslatedURL = new(char[dwcbPrefixLen + cbUrl]);
  71.                 if (*ppszTranslatedURL)
  72.                 {
  73.                    lstrcpy(*ppszTranslatedURL, rgchPrefix);
  74.                    lstrcat(*ppszTranslatedURL, pcszURLStart);
  75.                    // (+ 1) for null terminator.
  76.                    ASSERT(lstrlen(*ppszTranslatedURL) + 1 == (int)dwcbPrefixLen + lstrlen(pcszURLStart));
  77.                    hr = S_OK;
  78.                 }
  79.                 else
  80.                    hr = E_OUTOFMEMORY;
  81.             }
  82.             break;
  83.          }
  84.          dwcbValueNameLen = sizeof(rgchValueName);
  85.          dwcbPrefixLen = sizeof(rgchPrefix);
  86.       }
  87.       RegCloseKey(hkeyPrefixes);
  88.       switch (hr)
  89.       {
  90.          case S_OK:
  91.             TRACE_OUT(("ApplyURLPrefix(): Prefix %s prepended to prefix %s of %s to yield URL %s.",
  92.                        rgchValueName,
  93.                        rgchPrefix,
  94.                        pcszURL,
  95.                        *ppszTranslatedURL));
  96.             break;
  97.          case S_FALSE:
  98.             TRACE_OUT(("ApplyURLPrefix(): No matching prefix found for URL %s.",
  99.                        pcszURL));
  100.             break;
  101.          default:
  102.             ASSERT(hr == E_OUTOFMEMORY);
  103.             break;
  104.       }
  105.    }
  106.    else
  107.       TRACE_OUT(("ApplyURLPrefix(): No URL prefixes registered."));
  108.    ASSERT((hr == S_OK &&
  109.            IS_VALID_STRING_PTR(*ppszTranslatedURL, STR)) ||
  110.           ((hr == S_FALSE ||
  111.             hr == E_OUTOFMEMORY) &&
  112.            ! *ppszTranslatedURL));
  113.    return(hr);
  114. }
  115. PRIVATE_CODE HRESULT ApplyDefaultURLPrefix(PCSTR pcszURL,
  116.                                            PSTR *ppszTranslatedURL)
  117. {
  118.    HRESULT hr;
  119.    char rgchDefaultURLPrefix[MAX_PATH_LEN];
  120.    DWORD dwcbDefaultURLPrefixLen;
  121.    ASSERT(IS_VALID_STRING_PTR(pcszURL, CSTR));
  122.    ASSERT(IS_VALID_WRITE_PTR(ppszTranslatedURL, PSTR));
  123.    *ppszTranslatedURL = NULL;
  124.    dwcbDefaultURLPrefixLen = sizeof(rgchDefaultURLPrefix);
  125.    if (GetDefaultRegKeyValue(g_hkeyURLSettings, s_cszDefaultURLPrefixKey,
  126.                              rgchDefaultURLPrefix, &dwcbDefaultURLPrefixLen)
  127.        == ERROR_SUCCESS)
  128.    {
  129.       // (+ 1) for null terminator.
  130.       *ppszTranslatedURL = new(char[dwcbDefaultURLPrefixLen +
  131.                                     lstrlen(pcszURL) + 1]);
  132.       if (*ppszTranslatedURL)
  133.       {
  134.          PCSTR pcszURLStart;
  135.          pcszURLStart = SkipLeadingSlashes(pcszURL);
  136.          lstrcpy(*ppszTranslatedURL, rgchDefaultURLPrefix);
  137.          lstrcat(*ppszTranslatedURL, pcszURLStart);
  138.          // (+ 1) for null terminator.
  139.          ASSERT(lstrlen(*ppszTranslatedURL) + 1 == (int)dwcbDefaultURLPrefixLen + lstrlen(pcszURLStart));
  140.          hr = S_OK;
  141.       }
  142.       else
  143.          hr = E_OUTOFMEMORY;
  144.    }
  145.    else
  146.       hr = S_FALSE;
  147.    switch (hr)
  148.    {
  149.       case S_OK:
  150.          TRACE_OUT(("ApplyDefaultURLPrefix(): Default prefix %s prepended to %s to yield URL %s.",
  151.                     rgchDefaultURLPrefix,
  152.                     pcszURL,
  153.                     *ppszTranslatedURL));
  154.          break;
  155.       case S_FALSE:
  156.          TRACE_OUT(("ApplyDefaultURLPrefix(): No default URL prefix registered."));
  157.          break;
  158.       default:
  159.          ASSERT(hr == E_OUTOFMEMORY);
  160.          break;
  161.    }
  162.    ASSERT((hr == S_OK &&
  163.            IS_VALID_STRING_PTR(*ppszTranslatedURL, STR)) ||
  164.           ((hr == S_FALSE ||
  165.             hr == E_OUTOFMEMORY) &&
  166.            ! *ppszTranslatedURL));
  167.    return(hr);
  168. }
  169. PRIVATE_CODE HRESULT MyTranslateURL(PCSTR pcszURL, DWORD dwFlags,
  170.                                     PSTR *ppszTranslatedURL)
  171. {
  172.    HRESULT hr;
  173.    PARSEDURL pu;
  174.    ASSERT(IS_VALID_STRING_PTR(pcszURL, CSTR));
  175.    ASSERT(FLAGS_ARE_VALID(dwFlags, ALL_TRANSLATEURL_FLAGS));
  176.    ASSERT(IS_VALID_WRITE_PTR(ppszTranslatedURL, PSTR));
  177.    // Check URL syntax.
  178.    pu.cbSize = sizeof(pu);
  179.    if (ParseURL(pcszURL, &pu) == S_OK)
  180.    {
  181.       *ppszTranslatedURL = NULL;
  182.       hr = S_FALSE;
  183.    }
  184.    else
  185.    {
  186.       if (IS_FLAG_SET(dwFlags, TRANSLATEURL_FL_GUESS_PROTOCOL))
  187.          hr = ApplyURLPrefix(pcszURL, ppszTranslatedURL);
  188.       else
  189.          hr = S_FALSE;
  190.       if (hr == S_FALSE &&
  191.           IS_FLAG_SET(dwFlags, TRANSLATEURL_FL_USE_DEFAULT_PROTOCOL))
  192.          hr = ApplyDefaultURLPrefix(pcszURL, ppszTranslatedURL);
  193.    }
  194.    ASSERT((hr == S_OK &&
  195.            IS_VALID_STRING_PTR(*ppszTranslatedURL, STR)) ||
  196.           ((hr == S_FALSE ||
  197.             hr == E_OUTOFMEMORY) &&
  198.            ! *ppszTranslatedURL));
  199.    return(hr);
  200. }
  201. #ifdef DEBUG
  202. PRIVATE_CODE IsValidPCURLINVOKECOMMANDINFO(PCURLINVOKECOMMANDINFO pcurlici)
  203. {
  204.    return(IS_VALID_READ_PTR(pcurlici, CURLINVOKECOMMANDINFO) &&
  205.           EVAL(pcurlici->dwcbSize >= sizeof(*pcurlici)) &&
  206.           FLAGS_ARE_VALID(pcurlici->dwFlags, ALL_IURL_INVOKECOMMAND_FLAGS) &&
  207.           (IS_FLAG_CLEAR(pcurlici->dwFlags, IURL_INVOKECOMMAND_FL_ALLOW_UI) ||
  208.            IS_VALID_HANDLE(pcurlici->hwndParent, WND)) &&
  209.           (IS_FLAG_SET(pcurlici->dwFlags, IURL_INVOKECOMMAND_FL_USE_DEFAULT_VERB) ||
  210.            IS_VALID_STRING_PTR(pcurlici->pcszVerb, CSTR)));
  211. }
  212. #endif
  213. /********************************** Methods **********************************/
  214. HRESULT STDMETHODCALLTYPE InternetShortcut::RegisterProtocolHandler(
  215.                                                             HWND hwndParent,
  216.                                                             PSTR pszAppBuf,
  217.                                                             UINT ucAppBufLen)
  218. {
  219.    HRESULT hr;
  220.    DWORD dwFlags = 0;
  221.    DebugEntry(InternetShortcut::RegisterProtocolHandler);
  222.    ASSERT(! hwndParent ||
  223.           IS_VALID_HANDLE(hwndParent, WND));
  224.    ASSERT(IS_VALID_WRITE_BUFFER_PTR(pszAppBuf, STR, ucAppBufLen));
  225.    ASSERT(IS_VALID_STRING_PTR(m_pszURL, STR));
  226.    SET_FLAG(dwFlags, URLASSOCDLG_FL_REGISTER_ASSOC);
  227.    if (! m_pszFile)
  228.       SET_FLAG(dwFlags, URLASSOCDLG_FL_USE_DEFAULT_NAME);
  229.    hr = URLAssociationDialog(hwndParent, dwFlags, m_pszFile, m_pszURL,
  230.                              pszAppBuf, ucAppBufLen);
  231.    switch (hr)
  232.    {
  233.       case S_FALSE:
  234.          TRACE_OUT(("InternetShortcut::RegisterProtocolHandler(): One time execution of %s via %s requested.",
  235.                     m_pszURL,
  236.                     pszAppBuf));
  237.          break;
  238.       case S_OK:
  239.          TRACE_OUT(("InternetShortcut::RegisterProtocolHandler(): Protocol handler registered for %s.",
  240.                     m_pszURL));
  241.          break;
  242.       default:
  243.          ASSERT(FAILED(hr));
  244.          break;
  245.    }
  246.    ASSERT(! ucAppBufLen ||
  247.           (IS_VALID_STRING_PTR(pszAppBuf, STR) &&
  248.            (UINT)lstrlen(pszAppBuf) < ucAppBufLen));
  249.    DebugExitHRESULT(InternetShortcut::RegisterProtocolHandler, hr);
  250.    return(hr);
  251. }
  252. HRESULT STDMETHODCALLTYPE InternetShortcut::SetURL(PCSTR pcszURL,
  253.                                                    DWORD dwInFlags)
  254. {
  255.    HRESULT hr;
  256.    BOOL bChanged;
  257.    PSTR pszNewURL = NULL;
  258.    DebugEntry(InternetShortcut::SetURL);
  259.    ASSERT(IS_VALID_STRUCT_PTR(this, CInternetShortcut));
  260.    ASSERT(! pcszURL ||
  261.           IS_VALID_STRING_PTR(pcszURL, CSTR));
  262.    ASSERT(FLAGS_ARE_VALID(dwInFlags, ALL_IURL_SETURL_FLAGS));
  263.    bChanged = ! ((! pcszURL && ! m_pszURL) ||
  264.                  (pcszURL && m_pszURL &&
  265.                   ! lstrcmp(pcszURL, m_pszURL)));
  266.    if (bChanged && pcszURL)
  267.    {
  268.       DWORD dwTranslateURLFlags;
  269.       PSTR pszTranslatedURL;
  270.       dwTranslateURLFlags = 0;
  271.       if (IS_FLAG_SET(dwInFlags, IURL_SETURL_FL_GUESS_PROTOCOL))
  272.          SET_FLAG(dwTranslateURLFlags, TRANSLATEURL_FL_GUESS_PROTOCOL);
  273.       if (IS_FLAG_SET(dwInFlags, IURL_SETURL_FL_USE_DEFAULT_PROTOCOL))
  274.          SET_FLAG(dwTranslateURLFlags, TRANSLATEURL_FL_USE_DEFAULT_PROTOCOL);
  275.       hr = TranslateURL(pcszURL, dwTranslateURLFlags, &pszTranslatedURL);
  276.       if (SUCCEEDED(hr))
  277.       {
  278.          PCSTR pcszURLToUse;
  279.          // Still different?
  280.          if (hr == S_OK)
  281.          {
  282.             bChanged = (lstrcmp(pszTranslatedURL, m_pszURL) != 0);
  283.             pcszURLToUse = pszTranslatedURL;
  284.          }
  285.          else
  286.          {
  287.             ASSERT(hr == S_FALSE);
  288.             pcszURLToUse = pcszURL;
  289.          }
  290.          if (bChanged)
  291.          {
  292.             PARSEDURL pu;
  293.             // Validate URL syntax.
  294. pu.cbSize = sizeof(pu);
  295.             hr = ParseURL(pcszURLToUse, &pu);
  296.             if (hr == S_OK)
  297.             {
  298.                pszNewURL = new(char[lstrlen(pcszURLToUse) + 1]);
  299.                if (pszNewURL)
  300.                   lstrcpy(pszNewURL, pcszURLToUse);
  301.                else
  302.                   hr = E_OUTOFMEMORY;
  303.             }
  304.          }
  305.          else
  306.             hr = S_OK;
  307.       }
  308.       if (pszTranslatedURL)
  309.       {
  310.          LocalFree(pszTranslatedURL);
  311.          pszTranslatedURL = NULL;
  312.       }
  313.    }
  314.    else
  315.       hr = S_OK;
  316.    if (hr == S_OK)
  317.    {
  318.       if (bChanged)
  319.       {
  320.          if (m_pszURL)
  321.             delete m_pszURL;
  322.          m_pszURL = pszNewURL;
  323.          Dirty(TRUE);
  324.          TRACE_OUT(("InternetShortcut::SetURL(): Set URL to %s.",
  325.                     CHECK_STRING(m_pszURL)));
  326.       }
  327.       else
  328.          TRACE_OUT(("InternetShortcut::SetURL(): URL already %s.",
  329.                     CHECK_STRING(m_pszURL)));
  330.    }
  331.    ASSERT(IS_VALID_STRUCT_PTR(this, CInternetShortcut));
  332.    ASSERT(hr == S_OK ||
  333.           hr == E_OUTOFMEMORY ||
  334.           hr == URL_E_INVALID_SYNTAX);
  335.    DebugExitHRESULT(InternetShortcut::SetURL, hr);
  336.    return(hr);
  337. }
  338. HRESULT STDMETHODCALLTYPE InternetShortcut::GetURL(PSTR *ppszURL)
  339. {
  340.    HRESULT hr;
  341.    DebugEntry(InternetShortcut::GetURL);
  342.    ASSERT(IS_VALID_STRUCT_PTR(this, CInternetShortcut));
  343.    ASSERT(IS_VALID_WRITE_PTR(ppszURL, PSTR));
  344.    *ppszURL = NULL;
  345.    if (m_pszURL)
  346.    {
  347.       // (+ 1) for null terminator.
  348.       *ppszURL = (PSTR)SHAlloc(lstrlen(m_pszURL) + 1);
  349.       if (*ppszURL)
  350.       {
  351.          lstrcpy(*ppszURL, m_pszURL);
  352.          hr = S_OK;
  353.          TRACE_OUT(("InternetShortcut::GetURL(): Got URL %s.",
  354.                     *ppszURL));
  355.       }
  356.       else
  357.          hr = E_OUTOFMEMORY;
  358.    }
  359.    else
  360.       // No URL.
  361.       hr = S_FALSE;
  362.    ASSERT(IS_VALID_STRUCT_PTR(this, CInternetShortcut));
  363.    ASSERT((hr == S_OK &&
  364.            IS_VALID_STRING_PTR(*ppszURL, STR)) ||
  365.           ((hr == S_FALSE ||
  366.             hr == E_OUTOFMEMORY) &&
  367.            ! *ppszURL));
  368.    DebugExitHRESULT(InternetShortcut::GetURL, hr);
  369.    return(hr);
  370. }
  371. HRESULT STDMETHODCALLTYPE InternetShortcut::InvokeCommand(
  372.                                                 PURLINVOKECOMMANDINFO purlici)
  373. {
  374.    HRESULT hr = E_INVALIDARG;
  375.    char szOneShotApp[MAX_PATH_LEN];
  376.    BOOL bExecFailedWhine = FALSE;
  377.    DebugEntry(InternetShortcut::InvokeCommand);
  378.    ASSERT(IS_VALID_STRUCT_PTR(this, CInternetShortcut));
  379.    ASSERT(IS_VALID_STRUCT_PTR(purlici, CURLINVOKECOMMANDINFO));
  380.    if (purlici && EVAL(sizeof(*purlici) == purlici->dwcbSize))
  381.    {
  382.       if (m_pszURL)
  383.       {
  384.          PSTR pszProtocol;
  385.          hr = CopyURLProtocol(m_pszURL, &pszProtocol);
  386.          if (hr == S_OK)
  387.          {
  388.             hr = IsProtocolRegistered(pszProtocol);
  389.             if (hr == URL_E_UNREGISTERED_PROTOCOL &&
  390.                 IS_FLAG_SET(purlici->dwFlags, IURL_INVOKECOMMAND_FL_ALLOW_UI))
  391.             {
  392.                TRACE_OUT(("InternetShortcut::InvokeCommand(): Unregistered URL protocol %s.  Invoking URL protocol handler association dialog.",
  393.                           pszProtocol));
  394.                hr = RegisterProtocolHandler(purlici->hwndParent, szOneShotApp,
  395.                                             sizeof(szOneShotApp));
  396.             }
  397.             switch (hr)
  398.             {
  399.                case S_OK:
  400.                {
  401.                   SHELLEXECUTEINFO sei;
  402.                   char szDefaultVerb[MAX_PATH_LEN];
  403.                   // Execute URL via registered protocol handler.
  404.                   ZeroMemory(&sei, sizeof(sei));
  405.                   sei.fMask = (SEE_MASK_CLASSNAME | SEE_MASK_NO_HOOKS);
  406.                   if (IS_FLAG_CLEAR(purlici->dwFlags,
  407.                                     IURL_INVOKECOMMAND_FL_ALLOW_UI))
  408.                      SET_FLAG(sei.fMask, SEE_MASK_FLAG_NO_UI);
  409.                   if (IS_FLAG_CLEAR(purlici->dwFlags,
  410.                                     IURL_INVOKECOMMAND_FL_USE_DEFAULT_VERB))
  411.                      sei.lpVerb = purlici->pcszVerb;
  412.                   else
  413.                   {
  414.                      if (GetClassDefaultVerb(pszProtocol, szDefaultVerb,
  415.                                              sizeof(szDefaultVerb)))
  416.                         sei.lpVerb = szDefaultVerb;
  417.                      else
  418.                         ASSERT(! sei.lpVerb);
  419.                   }
  420.                   sei.cbSize = sizeof(sei);
  421.                   sei.hwnd = purlici->hwndParent;
  422.                   sei.lpFile = m_pszURL;
  423.                   sei.lpDirectory = m_pszWorkingDirectory;
  424.                   sei.nShow = m_nShowCmd;
  425.                   sei.lpClass = pszProtocol;
  426.                   TRACE_OUT(("InternetShortcut::InvokeCommand(): Invoking %s verb on URL %s.",
  427.                              sei.lpVerb ? sei.lpVerb : "open",
  428.                              sei.lpFile));
  429.                   hr = ShellExecuteEx(&sei) ? S_OK : IS_E_EXEC_FAILED;
  430.                   if (hr == S_OK)
  431.                      TRACE_OUT(("InternetShortcut::InvokeCommand(): ShellExecuteEx() via registered protcol handler succeeded for %s.",
  432.                                 m_pszURL));
  433.                   else
  434.                      WARNING_OUT(("InternetShortcut::InvokeCommand(): ShellExecuteEx() via registered protcol handler failed for %s.",
  435.                                   m_pszURL));
  436.                   break;
  437.                }
  438.                case S_FALSE:
  439.                   hr = MyExecute(szOneShotApp, m_pszURL, 0);
  440.                   switch (hr)
  441.                   {
  442.                      case E_FAIL:
  443.                         bExecFailedWhine = TRUE;
  444.                         hr = IS_E_EXEC_FAILED;
  445.                         break;
  446.                      default:
  447.                         break;
  448.                   }
  449.                   break;
  450.                default:
  451.                   ASSERT(FAILED(hr));
  452.                   break;
  453.             }
  454.             delete pszProtocol;
  455.             pszProtocol = NULL;
  456.          }
  457.       }
  458.       else
  459.          // No URL.  Not an error.
  460.          hr = S_FALSE;
  461.       if (FAILED(hr) &&
  462.           IS_FLAG_SET(purlici->dwFlags, IURL_INVOKECOMMAND_FL_ALLOW_UI))
  463.       {
  464.          int nResult;
  465.          switch (hr)
  466.          {
  467.             case IS_E_EXEC_FAILED:
  468.                if (bExecFailedWhine)
  469.                {
  470.                   ASSERT(IS_VALID_STRING_PTR(szOneShotApp, STR));
  471.                   if (MyMsgBox(purlici->hwndParent,
  472.                                MAKEINTRESOURCE(IDS_SHORTCUT_ERROR_TITLE),
  473.                                MAKEINTRESOURCE(IDS_EXEC_FAILED),
  474.                                (MB_OK | MB_ICONEXCLAMATION), &nResult,
  475.                                szOneShotApp)) {
  476.                      ASSERT(nResult == IDOK);
  477.                   }
  478.                }
  479.                break;
  480.             case URL_E_INVALID_SYNTAX:
  481.                ASSERT(IS_VALID_STRING_PTR(m_pszURL, STR));
  482.                if (MyMsgBox(purlici->hwndParent,
  483.                             MAKEINTRESOURCE(IDS_SHORTCUT_ERROR_TITLE),
  484.                             MAKEINTRESOURCE(IDS_EXEC_INVALID_SYNTAX),
  485.                             (MB_OK | MB_ICONEXCLAMATION), &nResult, m_pszURL)) {
  486.                   ASSERT(nResult == IDOK);
  487.                }
  488.                break;
  489.             case URL_E_UNREGISTERED_PROTOCOL:
  490.             {
  491.                PSTR pszProtocol;
  492.                ASSERT(IS_VALID_STRING_PTR(m_pszURL, STR));
  493.                if (CopyURLProtocol(m_pszURL, &pszProtocol) == S_OK)
  494.                {
  495.                   if (MyMsgBox(purlici->hwndParent,
  496.                                MAKEINTRESOURCE(IDS_SHORTCUT_ERROR_TITLE),
  497.                                MAKEINTRESOURCE(IDS_EXEC_UNREGISTERED_PROTOCOL),
  498.                                (MB_OK | MB_ICONEXCLAMATION), &nResult,
  499.                                pszProtocol)) {
  500.                      ASSERT(nResult == IDOK);
  501.                   }
  502.                   delete pszProtocol;
  503.                   pszProtocol = NULL;
  504.                }
  505.                break;
  506.             }
  507.             case E_OUTOFMEMORY:
  508.                if (MyMsgBox(purlici->hwndParent, MAKEINTRESOURCE(IDS_SHORTCUT_ERROR_TITLE),
  509.                             MAKEINTRESOURCE(IDS_EXEC_OUT_OF_MEMORY),
  510.                             (MB_OK | MB_ICONEXCLAMATION), &nResult)) {
  511.                   ASSERT(nResult == IDOK);
  512.                }
  513.                break;
  514.             default:
  515.                ASSERT(hr == E_ABORT);
  516.                break;
  517.          }
  518.       }
  519.    }
  520.    ASSERT(IS_VALID_STRUCT_PTR(this, CInternetShortcut));
  521.    ASSERT(hr == S_OK ||
  522.           hr == E_ABORT ||
  523.           hr == E_OUTOFMEMORY ||
  524.           hr == E_INVALIDARG ||
  525.           hr == URL_E_INVALID_SYNTAX ||
  526.           hr == URL_E_UNREGISTERED_PROTOCOL ||
  527.           hr == IS_E_EXEC_FAILED);
  528.    DebugExitHRESULT(InternetShortcut::InvokeCommand, hr);
  529.    return(hr);
  530. }
  531. /***************************** Exported Functions ****************************/
  532. INTSHCUTAPI HRESULT WINAPI TranslateURLA(PCSTR pcszURL, DWORD dwInFlags,
  533.                                          PSTR *ppszTranslatedURL)
  534. {
  535.    HRESULT hr;
  536.    DebugEntry(TranslateURLA);
  537.    *ppszTranslatedURL = NULL;
  538. #ifdef EXPV
  539.    /* Verify parameters. */
  540.    if (IS_VALID_STRING_PTR(pcszURL, CSTR) &&
  541.        IS_VALID_WRITE_PTR(ppszTranslatedURL, PSTR))
  542.    {
  543.       if (FLAGS_ARE_VALID(dwInFlags, ALL_TRANSLATEURL_FLAGS))
  544. #endif
  545.       {
  546.          PSTR pszTempTranslatedURL;
  547.          hr = MyTranslateURL(pcszURL, dwInFlags, &pszTempTranslatedURL);
  548.          if (hr == S_OK)
  549.          {
  550.             // (+ 1) for null terminator.
  551.             *ppszTranslatedURL = (PSTR)LocalAlloc(
  552.                                             LMEM_FIXED,
  553.                                             lstrlen(pszTempTranslatedURL) + 1);
  554.             if (*ppszTranslatedURL)
  555.             {
  556.                lstrcpy(*ppszTranslatedURL, pszTempTranslatedURL);
  557.                ASSERT(lstrlen(*ppszTranslatedURL) == lstrlen(pszTempTranslatedURL));
  558.             }
  559.             else
  560.                hr = E_OUTOFMEMORY;
  561.             delete pszTempTranslatedURL;
  562.             pszTempTranslatedURL = NULL;
  563.          }
  564.       }
  565. #ifdef EXPV
  566.       else
  567.          hr = E_FLAGS;
  568.    }
  569.    else
  570.       hr = E_POINTER;
  571. #endif
  572.    switch (hr)
  573.    {
  574.       case S_FALSE:
  575.          TRACE_OUT(("TranslateURLA(): URL %s does not require translation.",
  576.                     pcszURL));
  577.          break;
  578.       case S_OK:
  579.          TRACE_OUT(("TranslateURLA(): URL %s translated to URL %s.",
  580.                     pcszURL,
  581.                     *ppszTranslatedURL));
  582.          break;
  583.       default:
  584.          ASSERT(hr == E_OUTOFMEMORY ||
  585.                 hr == E_POINTER);
  586.          break;
  587.    }
  588.    ASSERT((hr == S_OK &&
  589.            IS_VALID_STRING_PTR(*ppszTranslatedURL, STR)) ||
  590.           ((hr == S_FALSE ||
  591.             hr == E_OUTOFMEMORY ||
  592.             hr == E_POINTER ||
  593.             hr == E_FLAGS) &&
  594.            ! *ppszTranslatedURL));
  595.    DebugExitHRESULT(TranslateURLA, hr);
  596.    return(hr);
  597. }
  598. #pragma warning(disable:4100) /* "unreferenced formal parameter" warning */
  599. INTSHCUTAPI HRESULT WINAPI TranslateURLW(PCWSTR pcszURL, DWORD dwInFlags,
  600.                                          PWSTR UNALIGNED *ppszTranslatedURL)
  601. {
  602.    HRESULT hr;
  603.    DebugEntry(TranslateURLW);
  604.    SetLastError(ERROR_NOT_SUPPORTED);
  605.    hr = E_NOTIMPL;
  606.    DebugExitHRESULT(TranslateURLW, hr);
  607.    return(hr);
  608. }
  609. #pragma warning(default:4100) /* "unreferenced formal parameter" warning */