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

Windows Kernel

Development Platform:

Visual C++

  1. /*
  2.  * url.cpp - IUniformResourceLocator implementation for InternetShortcut class.
  3.  */
  4. /* Headers
  5.  **********/
  6. #include "priv.h"
  7. #pragma hdrstop
  8. #define INC_OLE2
  9. #include "intshcut.h"
  10. /* Module Constants
  11.  *******************/
  12. const TCHAR c_szURLPrefixesKey[]        = TEXT("Software\Microsoft\Windows\CurrentVersion\URL\Prefixes");
  13. const TCHAR c_szDefaultURLPrefixKey[]   = TEXT("Software\Microsoft\Windows\CurrentVersion\URL\DefaultPrefix");
  14. // DPA array that holds the IURLSearchHook Pointers
  15. static HDPA g_hdpaHooks = NULL;
  16. // CURRENT_USER
  17. static const TCHAR c_szURLSearchHook[] = TSZIEPATH TEXT("\URLSearchHooks");
  18. /***************************** Private Functions *****************************/
  19. int DPA_DestroyURLSearchHooksCallback(LPVOID p, LPVOID d)
  20. {
  21.     IURLSearchHook * psuh = (IURLSearchHook *)p;
  22.     ASSERT(psuh);
  23.     ATOMICRELEASET(psuh, IURLSearchHook);
  24.     return 1; 
  25. }
  26. extern "C" {
  27.     
  28. void DestroyHdpaHooks()
  29. {
  30.     if (g_hdpaHooks)
  31.     {
  32.         ENTERCRITICAL;
  33.         //---------------------------- Critical Section -------------------------
  34.         HDPA hdpa = g_hdpaHooks;
  35.         g_hdpaHooks = NULL;
  36.         //-----------------------------------------------------------------------
  37.         LEAVECRITICAL;
  38.         if (hdpa)
  39.             DPA_DestroyCallback(hdpa, DPA_DestroyURLSearchHooksCallback, 0);
  40.     }
  41. }
  42. }
  43. HRESULT InvokeURLSearchHook(IURLSearchHook * pusHook, LPCTSTR pcszQuery, LPTSTR pszResult) 
  44. {
  45.     HRESULT hr = E_FAIL;
  46.     
  47.     ASSERT(pusHook);
  48.     WCHAR szSearchURL[MAX_URL_STRING]; 
  49.     SHTCharToUnicode(pcszQuery, szSearchURL, ARRAYSIZE(szSearchURL));
  50.         
  51.     hr = pusHook->Translate(szSearchURL, ARRAYSIZE(szSearchURL));
  52.             
  53.     // In case the URLSearchHook worked, convert result to TCHAR
  54.     // This includes two cases: S_OK and S_FALSE
  55.     if (SUCCEEDED(hr))
  56.     {
  57.         //BUGBUG: (dli) Assuming pszResult size = MAX_URL_STRING 
  58.         SHUnicodeToTChar(szSearchURL, pszResult, MAX_URL_STRING);
  59.     }
  60.     return hr;    
  61. }
  62. /* 
  63.  * Returns: 
  64.  * S_OK         Search handled completely, pszResult has the full URL to browse to. 
  65.  * 0x00000000   Stop running any further IURLSearchHooks and pass this URL back to 
  66.  *              the browser for browsing.
  67.  *
  68.  * S_FALSE      Query has been preprocessed, pszResult has the result of the preprocess, 
  69.  * 0x00000001   further search still needed. Go on executing the rest of the IURLSearchHooks 
  70.  *              The preprocessing steps can be: 1. replaced certain characters
  71.  *                                              2. added more hints 
  72.  *
  73.  * E_ABORT      Search handled completely, stop running any further IURLSearchHooks, 
  74.  * 0x80004004   but NO BROWSING NEEDED as a result, pszResult is a copy of pcszQuery. 
  75.  *              BUGBUG: This is not fully implemented, yet, making IURLQualify return this
  76.  *              involves too much change. 
  77.  * 
  78.  * E_FAIL       This Hook was unsuccessful. Search not handled at all, pcszQueryURL has the 
  79.  * 0x80004005   query string. Please go on running other IURLSearchHooks. 
  80.  * return
  81.  */
  82. HRESULT TryURLSearchHooks(LPCTSTR pcszQuery, LPTSTR pszResult)
  83. {
  84.     HRESULT hr = E_FAIL;
  85.     
  86.     TCHAR szNewQuery[MAX_URL_STRING];
  87.     StrCpyN(szNewQuery, pcszQuery, ARRAYSIZE(szNewQuery));
  88.     
  89.     int ihdpa;
  90.     for (ihdpa = 0; ihdpa < DPA_GetPtrCount(g_hdpaHooks); ihdpa++)
  91.     {
  92.         IURLSearchHook * pusHook;
  93.         pusHook = (IURLSearchHook *) DPA_GetPtr(g_hdpaHooks, ihdpa);
  94.         if (!pusHook)
  95.             return E_FAIL;
  96.         hr = InvokeURLSearchHook(pusHook, szNewQuery, pszResult);
  97.         if ((hr == S_OK) || (hr == E_ABORT))
  98.             break;
  99.         else if (hr == S_FALSE)
  100.             StrCpyN(szNewQuery, pszResult, ARRAYSIZE(szNewQuery));
  101.     }
  102.     return hr;
  103. }
  104. void InitURLSearchHooks()
  105. {
  106.     HDPA hdpa = DPA_Create(4);
  107.     
  108.     // We need to look in LOCAL_MACHINE if this registry entry doesn't exist in CURRENT_USER.
  109.     // The installer needs to install the values into LOCAL_MACHINE so they are accessable
  110.     // to all users.  Then anyone wanting to modify the value, will need to determine if they
  111.     // want to add it to a specific user's CURRENT_USER or modify the LOCAL_MACHINE value to 
  112.     // apply the change to all users.  (bryanst - #6722)
  113.     HUSKEY hkeyHooks;
  114.     if ((hdpa) && (SHRegOpenUSKey(c_szURLSearchHook, KEY_READ, NULL, &hkeyHooks, FALSE) == ERROR_SUCCESS))
  115.     {    
  116.         TCHAR szCLSID[GUIDSTR_MAX];
  117.         DWORD dwccCLSIDLen;
  118.         LONG lEnumReturn;
  119.         DWORD dwiValue = 0;
  120.         
  121.         do {
  122.             dwccCLSIDLen = ARRAYSIZE(szCLSID);
  123.             lEnumReturn = SHRegEnumUSValue(hkeyHooks, dwiValue, szCLSID, &dwccCLSIDLen, 
  124.                                        NULL, NULL, NULL, SHREGENUM_DEFAULT);
  125.             if (lEnumReturn == ERROR_SUCCESS)
  126.             {
  127.                 CLSID clsidHook;
  128.                 if (SUCCEEDED(SHCLSIDFromString(szCLSID, &clsidHook)))
  129.                 {
  130.                     IURLSearchHook * pusHook;
  131.                     HRESULT hr = CoCreateInstance(clsidHook, NULL, CLSCTX_INPROC_SERVER | CLSCTX_LOCAL_SERVER, 
  132.                                                   IID_IURLSearchHook, (LPVOID *)&pusHook);
  133.         
  134.                     if (SUCCEEDED(hr))
  135.                         DPA_AppendPtr(hdpa, pusHook);
  136.                 }   
  137.             }
  138.             dwiValue++;            
  139.         } while (lEnumReturn == ERROR_SUCCESS);
  140.         
  141.         SHRegCloseUSKey(hkeyHooks);
  142.     }
  143.     
  144.     ENTERCRITICAL;
  145.     //---------------------------- Critical Section --------------------------
  146.     if (!g_hdpaHooks)
  147.     {
  148.         g_hdpaHooks = hdpa;
  149.         hdpa = NULL;
  150.     }
  151.     //------------------------------------------------------------------------
  152.     LEAVECRITICAL;
  153.     
  154.     if (hdpa)
  155.         DPA_DestroyCallback(hdpa, DPA_DestroyURLSearchHooksCallback, 0);
  156. }
  157.     
  158. HRESULT ApplyURLSearch(LPCTSTR pcszQuery, LPTSTR pszTranslatedUrl)
  159. {
  160.     if (!g_hdpaHooks)
  161.         InitURLSearchHooks();   
  162.     
  163.     return TryURLSearchHooks(pcszQuery, pszTranslatedUrl);
  164. }
  165. /*----------------------------------------------------------
  166. Purpose: This function qualifies a string as a URL.  Strings
  167.          such as "www.foo.com" would have the scheme guessed
  168.          if the correct flags are given.  Local paths are 
  169.          converted to "file:" URLs.
  170.          pszTranslatedURL may point to the same buffer as 
  171.          pcszURL.
  172.          If the given string is already a URL (not necessarily
  173.          canonicalized, though), this function will not touch it, 
  174.          unless UQF_CANONICALIZE is set, in which case the string 
  175.          will be canonicalized.
  176. Returns: S_OK or S_FALSE means we filled in pszTranslatedURL.
  177.          S_OK means we altered the URL to qualify it too.
  178.          various failure codes too
  179. Cond:    --
  180. */
  181. SHDOCAPI
  182. IURLQualify(
  183.     IN  LPCWSTR pcszURL, 
  184.     IN  DWORD   dwFlags,         // UQF_*
  185.     OUT LPWSTR  pszTranslatedURL,
  186.     LPBOOL      pbWasSearchURL,
  187.     LPBOOL      pbWasCorrected)
  188. {
  189.     HRESULT hres = S_FALSE;
  190.     DWORD cchSize;
  191.     SHSTR strOut;
  192.     BOOL bWasCorrected = FALSE; 
  193.     ASSERT(IS_VALID_STRING_PTR(pcszURL, -1));
  194.     ASSERT(IS_VALID_WRITE_BUFFER(pszTranslatedURL, TCHAR, MAX_URL_STRING));
  195.     if (pbWasSearchURL)
  196.         *pbWasSearchURL = FALSE;
  197.     // Special cases: URLs of the form <drive>:<filename>
  198.     //                URLs of the form <filename>
  199.     // we'll assume that if the second character is a : or |, this is an url of
  200.     // that form, and we will guess "file://" for the prefix.
  201.     // we'll assume any url that begins with a single  is a file: url
  202.  
  203.     // NOTE: We do this here because these are cases where the protocol is 
  204.     // left off, and is likely to be incorrectly guessed, such as a 
  205.     // relative path dataftpdocs, would wrongly be turned 
  206.     // into "ftp://dataftpdocs".
  207.  
  208.     // Note: PathIsURL returns TRUE for non-canonicalized URLs too
  209.     if (PathIsURL(pcszURL))
  210.     {
  211.         LPCWSTR pcszTemp = pcszURL;
  212.         cchSize = MAX_URL_STRING;
  213.         if (IsFlagSet(dwFlags, UQF_AUTOCORRECT))
  214.         {
  215.             hres = UrlFixup(pcszURL, pszTranslatedURL, cchSize);
  216.             if (hres == S_OK)
  217.             {
  218.                 bWasCorrected = TRUE;
  219.                 pcszTemp = pszTranslatedURL;
  220.             }
  221.         }
  222.         if (dwFlags & UQF_CANONICALIZE)
  223.             hres = UrlCanonicalize(pcszTemp, pszTranslatedURL, &cchSize, 0);
  224.         else if (pszTranslatedURL != pcszTemp)
  225.             StrCpyN(pszTranslatedURL, pcszTemp, MAX_URL_STRING);
  226.         hres = S_OK;
  227.     }
  228.     else
  229.     {
  230.         // Look for file paths
  231.         if (IsFlagClear(dwFlags, UQF_IGNORE_FILEPATHS) && (
  232. #ifdef UNIX
  233.             pcszURL[0] == TEXT('/') ||
  234. #endif
  235.             pcszURL[1] == TEXT(':') || pcszURL[1] == TEXT('|') || pcszURL[0] == TEXT('\')))
  236.         {
  237.             hres = strOut.SetSize(MAX_PATH);
  238.             if(SUCCEEDED(hres))
  239.             {
  240.                 //  SHSTRs have a size granularity, so the size
  241.                 //  will be equal to or greater than what was set.
  242.                 //  this means we need to get it our self.
  243.                 DWORD cchOut = strOut.GetSize();
  244.                 TCHAR szCurrentDir[MAX_PATH];
  245.                 //
  246.                 //  BUGBUG - IE30 compatibility - zekel 8-Jan-97
  247.                 //  we need to GetCurrentDirectory() in order to
  248.                 //  put a default drive letter on the path
  249.                 //  if necessary.  
  250.                 //
  251.                 if(GetCurrentDirectory(ARRAYSIZE(szCurrentDir), szCurrentDir))
  252.                     PathCombine((LPTSTR)strOut, szCurrentDir, pcszURL);
  253.                 else
  254.                     hres = strOut.SetStr(pcszURL);
  255.                 if(SUCCEEDED(hres))
  256.                 {
  257.                     hres = UrlCreateFromPath((LPTSTR) strOut, (LPTSTR) strOut, &cchOut, 0);
  258.                     if (E_POINTER == hres && SUCCEEDED(hres = strOut.SetSize(cchOut)))
  259.                     {
  260.                         cchOut = strOut.GetSize();
  261.                         hres = UrlCreateFromPath((LPTSTR) strOut, (LPTSTR) strOut, &cchOut, 0);
  262.                     }
  263.                 }
  264.             }
  265.         }
  266.         else if (SUCCEEDED(hres = strOut.SetSize(MAX_URL_STRING)))
  267.         {
  268.             //  all the Apply*() below rely on MAX_URL_STRING
  269.             // No; begin processing general-case URLs.  Try to guess the
  270.             // protocol or resort to the default protocol.
  271.             DWORD cchOut = strOut.GetSize();
  272.             if (IsFlagSet(dwFlags, UQF_GUESS_PROTOCOL))
  273.                 hres = UrlApplyScheme(pcszURL, (LPTSTR) strOut, &cchOut, URL_APPLY_GUESSSCHEME);
  274.             //
  275.             // Try to auto-correct the protocol
  276.             //
  277.             if (hres == S_FALSE &&
  278.                 IsFlagSet(dwFlags, UQF_AUTOCORRECT))
  279.             {
  280.                 hres = UrlFixup(pcszURL, (LPTSTR)strOut, strOut.GetSize());
  281.                 bWasCorrected = (hres == S_OK);
  282.             }
  283.             if (hres == S_FALSE &&
  284.                 IsFlagSet(dwFlags, UQF_USE_DEFAULT_PROTOCOL)) 
  285.             {
  286.                 hres = ApplyURLSearch(pcszURL, (LPTSTR) strOut);
  287.                 if (SUCCEEDED(hres) && pbWasSearchURL) {
  288.                     *pbWasSearchURL = TRUE;
  289.                 }
  290.                 
  291.                 // If that fails, then tack on the default protocol
  292.                 if (FAILED(hres) || hres == S_FALSE)
  293.                 {
  294.                     cchOut = strOut.GetSize();
  295.                     hres = UrlApplyScheme(pcszURL, (LPTSTR) strOut, &cchOut, URL_APPLY_DEFAULT);
  296.                 }
  297.             }
  298.             // Did the above fail?
  299.             if (S_FALSE == hres)
  300.             {
  301.                 // Yes; return the real reason why the URL is bad
  302.                 hres = URL_E_INVALID_SYNTAX;
  303.             }
  304.             else if (dwFlags & UQF_CANONICALIZE)
  305.             {
  306.                 // No; canonicalize
  307.                 cchSize = strOut.GetSize();
  308.                 hres = UrlCanonicalize((LPTSTR)strOut, (LPTSTR)strOut, &cchSize, 0);
  309.             }
  310.         }
  311.         if (SUCCEEDED(hres))
  312.         {
  313.             StrCpyN(pszTranslatedURL, (LPTSTR) strOut, MAX_URL_STRING);
  314.         }
  315.     }
  316.     if (pbWasCorrected)
  317.         *pbWasCorrected = bWasCorrected;
  318.     return hres;
  319. }
  320. /***************************** Exported Functions ****************************/
  321. STDAPI
  322. URLQualifyA(
  323.     LPCSTR pszURL, 
  324.     DWORD  dwFlags,         // UQF_*
  325.     LPSTR *ppszOut)
  326. {
  327.     HRESULT hres;
  328.     ASSERT(IS_VALID_STRING_PTRA(pszURL, -1));
  329.     ASSERT(IS_VALID_WRITE_PTR(ppszOut, LPSTR));
  330.     *ppszOut = NULL;
  331.     WCHAR szTempTranslatedURL[MAX_URL_STRING];
  332.     WCHAR szURL[MAX_URL_STRING];
  333.     SHAnsiToUnicode(pszURL, szURL, ARRAYSIZE(szURL));
  334.     hres = IURLQualify(szURL, dwFlags, szTempTranslatedURL, NULL, NULL);
  335.     if (SUCCEEDED(hres))
  336.     {
  337.         CHAR szOut[MAX_URL_STRING];
  338.         SHUnicodeToAnsi(szTempTranslatedURL, szOut, ARRAYSIZE(szOut));
  339.         *ppszOut = StrDupA(szOut);
  340.         if (!*ppszOut)
  341.             hres = E_OUTOFMEMORY;
  342.     }
  343.     return hres;
  344. }
  345. STDAPI
  346. URLQualifyW(
  347.     LPCWSTR pszURL, 
  348.     DWORD  dwFlags,         // UQF_*
  349.     LPWSTR *ppszOut)
  350. {
  351.     HRESULT hres;
  352.     ASSERT(IS_VALID_STRING_PTRW(pszURL, -1));
  353.     ASSERT(IS_VALID_WRITE_PTR(ppszOut, LPWSTR));
  354.     WCHAR szTempTranslatedURL[MAX_URL_STRING];
  355.     hres = IURLQualify(pszURL, dwFlags, szTempTranslatedURL, NULL, NULL);
  356.     if (SUCCEEDED(hres))
  357.     {
  358.         *ppszOut = StrDup(szTempTranslatedURL);
  359.         if (!*ppszOut)
  360.             hres = E_OUTOFMEMORY;
  361.     }
  362.     return hres;
  363. }