Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

4224 lines
139 KiB

  1. #include "priv.h"
  2. #include "sccls.h"
  3. #include "shlobj.h"
  4. #include <tchar.h>
  5. #ifndef UNIX
  6. #include <webcheck.h>
  7. #else
  8. #include <subsmgr.h>
  9. #endif
  10. #include "resource.h"
  11. #include "mshtml.h" // for IHTMLElement
  12. #include "mlang.h" // fo char conversion
  13. #include <advpub.h> // for IE activesetup GUID
  14. #include "winineti.h" // For name of a mutex used in IsWininetLoadedAnywhere()
  15. #include "htregmng.h"
  16. #include <ntverp.h>
  17. #include <platform.h>
  18. #include <mobsync.h>
  19. #include <mobsyncp.h>
  20. #include <winuser.h>
  21. #include <mluisupp.h>
  22. #include "shdocfl.h"
  23. #include <shlwapip.h>
  24. #include "inetnot.h"
  25. #include <shfolder.h>
  26. #include "..\inc\brutil.cpp"
  27. STDAPI CDelegateMalloc_Create(void *pv, SIZE_T cbSize, WORD wOuter, IMalloc **ppmalloc);
  28. const VARIANT c_vaEmpty = {0};
  29. const TCHAR c_szRegKeyTypedURLs[] = TEXT("Software\\Microsoft\\Internet Explorer\\TypedURLs");
  30. #define DM_SESSIONCOUNT 0
  31. int g_cxIcon = 0;
  32. int g_cyIcon = 0;
  33. int g_cxSmIcon = 0;
  34. int g_cySmIcon = 0;
  35. const DISPPARAMS c_dispparamsNoArgs = {NULL, NULL, 0, 0};
  36. const LARGE_INTEGER c_li0 = { 0, 0 };
  37. const ITEMIDLIST s_idlNULL = { 0 } ;
  38. // 07.28.2000 - Moved from urlhist.cpp since its used in two places now.
  39. #ifdef UNICODE
  40. #define SHGETFOLDERPATH "SHGetFolderPathW"
  41. #else
  42. #define SHGETFOLDERPATH "SHGetFolderPathA"
  43. #endif
  44. #undef SHGetFolderPath
  45. typedef HRESULT (*PFNSHGETFOLDERPATH)(HWND hwnd, int csidl, HANDLE hToken, DWORD dwFlags, LPTSTR pszPath);
  46. PFNSHGETFOLDERPATH g_pfnGetFolderPath = NULL;
  47. HRESULT SHGetFolderPathD(HWND hwnd, int csidl, HANDLE hToken, DWORD dwFlags, LPTSTR pszPath)
  48. {
  49. if (!g_pfnGetFolderPath)
  50. {
  51. // note, this is already loaded so this LoadLibray() is fast
  52. HMODULE hmod = LoadLibrary(TEXT("shell32.dll"));
  53. g_pfnGetFolderPath = (PFNSHGETFOLDERPATH)GetProcAddress(hmod, SHGETFOLDERPATH);
  54. // not there, must be downlevel shell32, use shfolder.dll instead
  55. if (!g_pfnGetFolderPath)
  56. {
  57. hmod = LoadLibrary(TEXT("shfolder.dll"));
  58. g_pfnGetFolderPath = (PFNSHGETFOLDERPATH)GetProcAddress(hmod, SHGETFOLDERPATH);
  59. }
  60. // note, we leak the hmod, for shell32/shfolder that is OK
  61. }
  62. HRESULT hr;
  63. if (g_pfnGetFolderPath)
  64. hr = g_pfnGetFolderPath(hwnd, csidl, hToken, dwFlags, pszPath);
  65. else
  66. {
  67. *pszPath = 0;
  68. hr = E_FAIL;
  69. }
  70. return hr;
  71. }
  72. int InitColorDepth(void)
  73. {
  74. static int s_lrFlags = 0; // Flags passed to LoadImage
  75. if (s_lrFlags == 0)
  76. {
  77. int nColorRes, nIconDepth = 0;
  78. HKEY hkey;
  79. // Determine the color depth so we can load the best image
  80. // (This code was stolen from FileIconInit in shell32)
  81. // Get the user preferred icon size (and color depth) from the
  82. // registry.
  83. //
  84. if (NO_ERROR == RegOpenKey(HKEY_CURRENT_USER, REGSTR_PATH_METRICS, &hkey))
  85. {
  86. nIconDepth = SHRegGetIntW(hkey, L"Shell Icon Bpp", nIconDepth);
  87. RegCloseKey(hkey);
  88. }
  89. nColorRes = GetCurColorRes();
  90. if (nIconDepth > nColorRes)
  91. nIconDepth = 0;
  92. if (nColorRes <= 8)
  93. nIconDepth = 0; // wouldn't have worked anyway
  94. if (nColorRes > 4 && nIconDepth <= 4)
  95. s_lrFlags = LR_VGACOLOR;
  96. else
  97. s_lrFlags = LR_DEFAULTCOLOR;
  98. }
  99. return s_lrFlags;
  100. }
  101. HICON g_hiconSplat = NULL;
  102. HICON g_hiconSplatSm = NULL; // small version
  103. void LoadCommonIcons(void)
  104. {
  105. if (NULL == g_hiconSplat)
  106. {
  107. // Use LoadLibraryEx so we don't load code pages
  108. HINSTANCE hinst = LoadLibrary(TEXT("url.dll"));
  109. if (hinst)
  110. {
  111. int lrFlags = InitColorDepth();
  112. g_hiconSplat = (HICON)LoadImage(hinst, MAKEINTRESOURCE(IDI_URL_SPLAT), IMAGE_ICON, g_cxIcon, g_cyIcon, lrFlags);
  113. g_hiconSplatSm = (HICON)LoadImage(hinst, MAKEINTRESOURCE(IDI_URL_SPLAT), IMAGE_ICON, g_cxSmIcon, g_cySmIcon, lrFlags);
  114. FreeLibrary(hinst);
  115. }
  116. }
  117. }
  118. STDAPI_(BOOL) UrlHitsNetW(LPCWSTR pszURL)
  119. {
  120. BOOL fResult;
  121. // Handle the easy ones on our own and call URLMON for the others.
  122. switch (GetUrlScheme(pszURL))
  123. {
  124. case URL_SCHEME_FILE:
  125. case URL_SCHEME_RES:
  126. // DSheldon - What about UNC and WebDav?
  127. fResult = FALSE;
  128. break;
  129. case URL_SCHEME_HTTP:
  130. case URL_SCHEME_HTTPS:
  131. case URL_SCHEME_FTP:
  132. case URL_SCHEME_GOPHER:
  133. case URL_SCHEME_TELNET:
  134. case URL_SCHEME_WAIS:
  135. fResult = TRUE;
  136. break;
  137. default:
  138. {
  139. DWORD fHitsNet;
  140. DWORD dwSize;
  141. fResult = SUCCEEDED(CoInternetQueryInfo(
  142. pszURL, QUERY_USES_NETWORK,
  143. 0, &fHitsNet, sizeof(fHitsNet), &dwSize, 0)) && fHitsNet;
  144. }
  145. }
  146. return fResult;
  147. }
  148. STDAPI_(BOOL) CallCoInternetQueryInfo(LPCTSTR pszURL, QUERYOPTION QueryOption)
  149. {
  150. DWORD fRetVal;
  151. DWORD dwSize;
  152. return SUCCEEDED(CoInternetQueryInfo(
  153. pszURL, QueryOption,
  154. 0, &fRetVal, sizeof(fRetVal), &dwSize, 0)) && fRetVal;
  155. }
  156. // see if a given URL is in the cache
  157. STDAPI_(BOOL) UrlIsInCache(LPCTSTR pszURL)
  158. {
  159. return CallCoInternetQueryInfo(pszURL, QUERY_IS_CACHED);
  160. }
  161. // see if a given URL is in the cache OR if it is mapped
  162. STDAPI_(BOOL) UrlIsMappedOrInCache(LPCTSTR pszURL)
  163. {
  164. return CallCoInternetQueryInfo(pszURL, QUERY_IS_CACHED_OR_MAPPED);
  165. }
  166. BOOL IsFileUrlW(LPCWSTR pcwzUrl)
  167. {
  168. return (GetUrlSchemeW(pcwzUrl) == URL_SCHEME_FILE);
  169. }
  170. BOOL IsFileUrl(LPCSTR psz)
  171. {
  172. return (GetUrlSchemeA(psz) == URL_SCHEME_FILE);
  173. }
  174. BOOL PathIsFilePath(LPCWSTR lpszPath)
  175. {
  176. if ((lpszPath[0] == TEXT('\\')) || (lpszPath[0] != TEXT('\0') && lpszPath[1] == TEXT(':')))
  177. return TRUE;
  178. return IsFileUrlW(lpszPath);
  179. }
  180. BOOL IsSubscribableW(LPCWSTR pszUrl)
  181. {
  182. // FEATURE: this should be method on the subscription mgr interface - zekel
  183. DWORD dwScheme = GetUrlSchemeW(pszUrl);
  184. return (dwScheme == URL_SCHEME_HTTP) || (dwScheme == URL_SCHEME_HTTPS);
  185. }
  186. DWORD SHRandom(void)
  187. {
  188. GUID guid;
  189. DWORD dw;
  190. CoCreateGuid(&guid);
  191. HashData((LPBYTE)&guid, SIZEOF(guid), (LPBYTE)&dw, SIZEOF(dw));
  192. return dw;
  193. }
  194. // See if we are hosted by IE (explorer.exe or iexplore.exe)
  195. BOOL IsInternetExplorerApp()
  196. {
  197. if ((g_fBrowserOnlyProcess) || // if in iexplore.exe process,
  198. (GetModuleHandle(TEXT("EXPLORER.EXE")))) // or explorer.exe process,
  199. {
  200. return TRUE; // then we are IE
  201. }
  202. return FALSE;
  203. }
  204. BOOL IsTopFrameBrowser(IServiceProvider *psp, IUnknown *punk)
  205. {
  206. IShellBrowser *psb;
  207. ASSERT(psp);
  208. ASSERT(punk);
  209. BOOL fRet = FALSE;
  210. if (SUCCEEDED(psp->QueryService(SID_STopFrameBrowser, IID_PPV_ARG(IShellBrowser, &psb))))
  211. {
  212. fRet = IsSameObject(psb, punk);
  213. psb->Release();
  214. }
  215. return fRet;
  216. }
  217. STDAPI_(BSTR) LoadBSTR(UINT uID)
  218. {
  219. WCHAR wszBuf[MAX_PATH];
  220. if (MLLoadStringW(uID, wszBuf, ARRAYSIZE(wszBuf)))
  221. {
  222. return SysAllocString(wszBuf);
  223. }
  224. return NULL;
  225. }
  226. BOOL StringIsUTF8W(LPCWSTR pwz, DWORD cb)
  227. {
  228. BOOL fRC = FALSE;
  229. WCHAR *pb;
  230. WCHAR b;
  231. DWORD dwCnt;
  232. DWORD dwUTF8Cnt;
  233. if (!pwz || !(*pwz) || cb == 0)
  234. return(FALSE);
  235. pb = (WCHAR*)pwz;
  236. while(cb-- && *pb)
  237. {
  238. if (*pb > 255) // Non ansi so bail
  239. return(FALSE);
  240. if ((*pb & 0xc0) == 0xc0) // bit pattern starts with 11
  241. {
  242. dwCnt = dwUTF8Cnt = 0;
  243. b = *pb;
  244. while((b & 0xc0) == 0xc0)
  245. {
  246. dwCnt++;
  247. if ((*(pb+dwCnt) & 0xc0) == 0x80) // bits at dwCnt bytes from current offset in str aren't 10
  248. dwUTF8Cnt++;
  249. b = (b << 1) & 0xff;
  250. }
  251. if (dwCnt == dwUTF8Cnt)
  252. fRC = TRUE; // Found UTF8 encoded chars
  253. pb += ++dwCnt;
  254. }
  255. else
  256. {
  257. pb++;
  258. }
  259. }
  260. return(fRC);
  261. }
  262. BOOL UTF8Enabled(void)
  263. {
  264. static DWORD dwIE = URL_ENCODING_NONE;
  265. DWORD dwOutLen = sizeof(DWORD);
  266. if (dwIE == URL_ENCODING_NONE)
  267. UrlMkGetSessionOption(URLMON_OPTION_URL_ENCODING, &dwIE, sizeof(DWORD), &dwOutLen, NULL);
  268. return dwIE == URL_ENCODING_ENABLE_UTF8;
  269. }
  270. //
  271. // PrepareURLForDisplay
  272. //
  273. // Decodes without stripping file:// prefix
  274. //
  275. #undef PrepareURLForDisplay
  276. BOOL PrepareURLForDisplayW(LPCWSTR pwz, LPWSTR pwzOut, LPDWORD pcbOut)
  277. {
  278. if (PathIsFilePath(pwz))
  279. {
  280. if (IsFileUrlW(pwz))
  281. return SUCCEEDED(PathCreateFromUrlW(pwz, pwzOut, pcbOut, 0));
  282. StrCpyNW(pwzOut, pwz, *pcbOut);
  283. *pcbOut = lstrlenW(pwzOut);
  284. return TRUE;
  285. }
  286. BOOL fRet = SUCCEEDED(UrlUnescapeW((LPWSTR)pwz, pwzOut, pcbOut, 0));
  287. if (fRet)
  288. {
  289. SHCleanupUrlForDisplay(pwzOut);
  290. }
  291. return fRet;
  292. }
  293. // ****************************************************************************
  294. // BEGIN - MOVE TO SHLWAPI
  295. //
  296. // TODO (grzegorz): move this code to shlwapi.dll
  297. // ****************************************************************************
  298. #define QUERY L'?'
  299. #define POUND L'#'
  300. #define HEX_ESCAPE L'%'
  301. #define TERMSTR(pch) *(pch) = L'\0'
  302. BOOL IsHex(WCHAR ch)
  303. {
  304. return ( (ch >= TEXT('0') && ch <= TEXT('9'))
  305. || (ch >= TEXT('A') && ch <= TEXT('F'))
  306. || (ch >= TEXT('a') && ch <= TEXT('f')));
  307. }
  308. WORD HexToWord(WCHAR ch)
  309. {
  310. if(ch >= TEXT('0') && ch <= TEXT('9'))
  311. return (WORD) ch - TEXT('0');
  312. if(ch >= TEXT('A') && ch <= TEXT('F'))
  313. return (WORD) ch - TEXT('A') + 10;
  314. if(ch >= TEXT('a') && ch <= TEXT('f'))
  315. return (WORD) ch - TEXT('a') + 10;
  316. ASSERT(FALSE); //we have tried to use a non-hex number
  317. return (WORD) -1;
  318. }
  319. inline BOOL IsEscapedOctetW(LPCWSTR pch)
  320. {
  321. return (pch[0] == HEX_ESCAPE && IsHex(pch[1]) && IsHex(pch[2])) ? TRUE : FALSE;
  322. }
  323. WCHAR TranslateEscapedOctetW(LPCWSTR pch)
  324. {
  325. WCHAR ch;
  326. ASSERT(IsEscapedOctetW(pch));
  327. pch++;
  328. ch = (WCHAR) HexToWord(*pch++) * 16; // hi nibble
  329. ch += HexToWord(*pch); // lo nibble
  330. return ch;
  331. }
  332. HRESULT CopyOutW(PSHSTRW pstr, LPWSTR psz, LPDWORD pcch)
  333. {
  334. HRESULT hr = S_OK;
  335. DWORD cch;
  336. ASSERT(pstr);
  337. ASSERT(psz);
  338. ASSERT(pcch);
  339. cch = pstr->GetLen();
  340. if ((*pcch > cch) && psz)
  341. StrCpyNW(psz, pstr->GetStr(), cch + 1);
  342. else
  343. hr = E_POINTER;
  344. *pcch = cch + (FAILED(hr) ? 1 : 0);
  345. return hr;
  346. }
  347. HRESULT ShdocvwUrlUnescapeInplaceW(LPWSTR psz, DWORD dwFlags, UINT uiCP)
  348. {
  349. WCHAR *pchSrc = psz;
  350. WCHAR *pchDst = psz;
  351. HRESULT hr = S_OK;
  352. while (*pchSrc)
  353. {
  354. if ((*pchSrc == POUND || *pchSrc == QUERY) && (dwFlags & URL_DONT_ESCAPE_EXTRA_INFO))
  355. {
  356. StrCpyNW(pchDst, pchSrc, lstrlenW(pchSrc));
  357. pchDst += lstrlenW(pchDst);
  358. break;
  359. }
  360. if (IsEscapedOctetW(pchSrc))
  361. {
  362. int cchAnsi = 0;
  363. int cchDst;
  364. SHSTRA strAnsi;
  365. LPSTR pchDstAnsi;
  366. hr = strAnsi.SetStr(pchDst);
  367. if (FAILED(hr))
  368. return hr;
  369. else
  370. pchDstAnsi = strAnsi.GetInplaceStr();
  371. while (*pchSrc && IsEscapedOctetW(pchSrc))
  372. {
  373. WCHAR ch = TranslateEscapedOctetW(pchSrc);
  374. *pchDstAnsi++ = LOBYTE(ch);
  375. pchSrc += 3; // enuff for "%XX"
  376. cchAnsi++;
  377. }
  378. if (cchAnsi)
  379. {
  380. TERMSTR(pchDstAnsi);
  381. // we have min 2 extra chars in pchDst to use, so we can pass cchAnsi + 1
  382. cchDst = SHAnsiToUnicodeCP(uiCP, strAnsi, pchDst, cchAnsi + 1);
  383. pchDst += cchDst - 1;
  384. }
  385. }
  386. else
  387. {
  388. *pchDst++ = *pchSrc++;
  389. }
  390. }
  391. TERMSTR(pchDst);
  392. return hr;
  393. }
  394. HRESULT ShdocvwUrlUnescapeW(LPWSTR pszUrl, LPWSTR pszOut, LPDWORD pcchOut, DWORD dwFlags, UINT uiCP)
  395. {
  396. RIPMSG(pszUrl && IS_VALID_STRING_PTRW(pszUrl, -1), "ShdocvwUrlUnescapeW: Caller passed invalid pszUrl");
  397. if (dwFlags & URL_UNESCAPE_INPLACE)
  398. {
  399. return ShdocvwUrlUnescapeInplaceW(pszUrl, dwFlags, uiCP);
  400. }
  401. RIPMSG(NULL != pcchOut && IS_VALID_WRITE_PTR(pcchOut, DWORD), "ShdocvwUrlUnescapeW: Caller passed invalid pcchOut");
  402. RIPMSG(pszOut && (NULL == pcchOut || IS_VALID_WRITE_BUFFER(pszOut, WCHAR, *pcchOut)), "ShdocvwUrlUnescapeW: Caller passed invalid pszOut");
  403. if ( !pszUrl
  404. || !pcchOut
  405. || !*pcchOut
  406. || !pszOut)
  407. {
  408. return E_INVALIDARG;
  409. }
  410. SHSTRW str;
  411. HRESULT hr = str.SetStr(pszUrl);
  412. if (SUCCEEDED(hr))
  413. {
  414. ShdocvwUrlUnescapeInplaceW(str.GetInplaceStr(), dwFlags, uiCP);
  415. hr = CopyOutW(&str, pszOut, pcchOut);
  416. }
  417. return hr;
  418. }
  419. // ****************************************************************************
  420. // END - MOVE TO SHLWAPI
  421. // ****************************************************************************
  422. //
  423. // PrepareURLForDisplayUTF8W
  424. //
  425. // pwz - [In] UTF8 encoded string like "%e6%aa%e4%a6.doc".
  426. // pwzOut - [Out] UTF8 decoded string.
  427. // pcchOut - [In/Out] Count of characters in pwzOut on input. Number of chars copies to pwzOut on output
  428. // including the terminating null.
  429. // fUTF8Enabled - [In] Flag to indicated whether UTF8 is enabled.
  430. // uiCP - [In] Codepage used to convert escaped characters, when fUTF8Enabled is false
  431. //
  432. // pwz and pwzOut can be the same buffer.
  433. //
  434. // Returns:
  435. // S_OK upon success.
  436. // E_FAIL for failure.
  437. // ERROR_BUFFER_OVERFLOW if the number of converted chars is greater than the passed in size of output buffer.
  438. //
  439. // Note: If UTF8 is not enabled or the string does not contain UTF8 the output string will be unescaped
  440. // and will return S_OK.
  441. //
  442. HRESULT _PrepareURLForDisplayUTF8W(LPCWSTR pwz, LPWSTR pwzOut, LPDWORD pcchOut, BOOL fUTF8Enabled, UINT uiCP)
  443. {
  444. HRESULT hr = E_FAIL;
  445. DWORD cch;
  446. DWORD cch1;
  447. CHAR szBuf[MAX_URL_STRING];
  448. CHAR *pszBuf = szBuf;
  449. if (!pwz || !pwzOut || !pcchOut)
  450. {
  451. if (pcchOut)
  452. *pcchOut = 0;
  453. return(hr);
  454. }
  455. cch = *pcchOut;
  456. cch1 = ARRAYSIZE(szBuf);
  457. if (uiCP != (UINT)-1)
  458. hr = ShdocvwUrlUnescapeW((LPWSTR)pwz, pwzOut, pcchOut, 0, fUTF8Enabled ? CP_UTF8 : uiCP);
  459. else
  460. {
  461. hr = UrlUnescapeW((LPWSTR)pwz, pwzOut, pcchOut, 0);
  462. if (SUCCEEDED(hr))
  463. {
  464. if (fUTF8Enabled && StringIsUTF8W(pwzOut, cch))
  465. {
  466. if (*pcchOut > ARRAYSIZE(szBuf)) // Internal buffer not big enough so alloc one
  467. {
  468. if ((pszBuf = (CHAR *)LocalAlloc(LPTR, ((*pcchOut)+1) * sizeof(CHAR))) == NULL)
  469. {
  470. *pcchOut = 0;
  471. return(E_OUTOFMEMORY);
  472. }
  473. cch1 = *pcchOut;
  474. }
  475. // Compress wide string
  476. CHAR *pIn = (CHAR *)pwzOut;
  477. CHAR *pOut = pszBuf;
  478. while((*pIn != '\0') || (*(pIn+1) != '\0') && --cch1)
  479. {
  480. if (*pIn != '\0')
  481. {
  482. *pOut = *pIn;
  483. pOut++;
  484. }
  485. pIn++;
  486. }
  487. *pOut = '\0';
  488. // Convert to UTF8 wide string
  489. if ((cch1 = SHAnsiToUnicodeCP(CP_UTF8, pszBuf, pwzOut, cch)) != 0)
  490. {
  491. hr = S_OK;
  492. *pcchOut = cch1;
  493. }
  494. // SHAnsiToUnicode doesn't tell us if it has truncated the convertion to fit the output buffer
  495. RIPMSG(cch1 != cch, "_PrepareURLForDisplayUTF8W: Passed in size of out buf equal to converted size; buffer might be truncated");
  496. if ((pszBuf != NULL) && (pszBuf != szBuf))
  497. {
  498. LocalFree((CHAR *)pszBuf);
  499. pszBuf = NULL;
  500. }
  501. }
  502. else
  503. {
  504. hr = S_OK;;
  505. }
  506. }
  507. }
  508. if (SUCCEEDED(hr))
  509. {
  510. SHCleanupUrlForDisplay(pwzOut);
  511. }
  512. return(hr);
  513. }
  514. HRESULT PrepareURLForDisplayUTF8W(LPCWSTR pwz, LPWSTR pwzOut, LPDWORD pcchOut, BOOL fUTF8Enabled)
  515. {
  516. return _PrepareURLForDisplayUTF8W(pwz, pwzOut, pcchOut, fUTF8Enabled, (UINT)-1);
  517. }
  518. //
  519. // PrepareURLForExternalApp -
  520. //
  521. // Decodes and strips, if needed, file:// prefix
  522. //
  523. // APPCOMPAT - for IE30 compatibility reasons, we have to Unescape all Urls - zekel - 1-JUL-97
  524. // before passing them to an APP. this does limit their use, but
  525. // people already depend on this behavior. specifically MS Chat.
  526. BOOL PrepareURLForExternalApp (LPCWSTR psz, LPWSTR pszOut, LPDWORD pcchOut)
  527. {
  528. if (IsFileUrlW(psz))
  529. return SUCCEEDED(PathCreateFromUrl(psz, pszOut, pcchOut, 0));
  530. else
  531. return SUCCEEDED(UrlUnescape((LPWSTR)psz, pszOut, pcchOut, 0));
  532. }
  533. SHDOCAPI
  534. IURLQualifyWithContext(
  535. IN LPCWSTR pcszURL,
  536. IN DWORD dwFlags, // UQF_*
  537. IN DWORD cchTranslatedURL,
  538. OUT LPWSTR pszTranslatedURL,
  539. LPBOOL pbWasSearchURL,
  540. LPBOOL pbWasCorrected,
  541. ISearchContext * pSC);
  542. BOOL ParseURLFromOutsideSourceWithContextW (LPCWSTR psz, LPWSTR pszOut, LPDWORD pcchOut, LPBOOL pbWasSearchURL, ISearchContext * pSC)
  543. {
  544. // This is our hardest case. Users and outside applications might
  545. // type fully-escaped, partially-escaped, or unescaped URLs at us.
  546. // We need to handle all these correctly. This API will attempt to
  547. // determine what sort of URL we've got, and provide us a returned URL
  548. // that is guaranteed to be FULLY escaped.
  549. IURLQualifyWithContext(psz, UQF_DEFAULT, *pcchOut, pszOut, pbWasSearchURL, NULL, pSC);
  550. //
  551. // go ahead and canonicalize this appropriately
  552. //
  553. if (FAILED(UrlCanonicalize(pszOut, pszOut, pcchOut, URL_ESCAPE_SPACES_ONLY)))
  554. {
  555. //
  556. // we cant resize from here.
  557. // NOTE UrlCan will return E_POINTER if it is an insufficient buffer
  558. //
  559. TraceMsg(DM_ERROR, "sdv PUFOS:UC() failed.");
  560. return FALSE;
  561. }
  562. return TRUE;
  563. } // ParseURLFromOutsideSource
  564. BOOL ParseURLFromOutsideSourceW (LPCWSTR psz, LPWSTR pszOut, LPDWORD pcchOut, LPBOOL pbWasSearchURL)
  565. {
  566. return ParseURLFromOutsideSourceWithContextW(psz, pszOut, pcchOut, pbWasSearchURL, NULL);
  567. } // ParseURLFromOutsideSource
  568. BOOL ParseURLFromOutsideSourceA (LPCSTR psz, LPSTR pszOut, LPDWORD pcchOut, LPBOOL pbWasSearchURL)
  569. {
  570. SHSTRW strw;
  571. DWORD cch ;
  572. ASSERT(psz);
  573. ASSERT(pszOut);
  574. ASSERT(pcchOut && *pcchOut);
  575. //
  576. // WARNING: we arent guaranteed to have the correct cch's here - zekel - 27-jan-97
  577. // but for now this is adequate.
  578. //
  579. if (SUCCEEDED(strw.SetStr(psz)) && SUCCEEDED(strw.SetSize(cch = *pcchOut)) &&
  580. ParseURLFromOutsideSourceW(strw, strw.GetInplaceStr(), pcchOut, pbWasSearchURL))
  581. {
  582. return SHUnicodeToAnsi((LPCWSTR)strw, pszOut, cch);
  583. }
  584. return FALSE;
  585. }
  586. int DPA_ILFreeCallback(void * p, void * d)
  587. {
  588. Pidl_Set((LPITEMIDLIST*)&p, NULL);
  589. return 1;
  590. }
  591. void _DeletePidlDPA(HDPA hdpa)
  592. {
  593. DPA_DestroyCallback(hdpa, (PFNDPAENUMCALLBACK)DPA_ILFreeCallback, 0);
  594. hdpa = NULL;
  595. }
  596. BOOL _InitComCtl32()
  597. {
  598. static BOOL fInitialized = FALSE;
  599. if (!fInitialized)
  600. {
  601. INITCOMMONCONTROLSEX icc;
  602. icc.dwSize = sizeof(INITCOMMONCONTROLSEX);
  603. icc.dwICC = ICC_USEREX_CLASSES | ICC_COOL_CLASSES | ICC_INTERNET_CLASSES | ICC_PAGESCROLLER_CLASS | ICC_NATIVEFNTCTL_CLASS;
  604. fInitialized = InitCommonControlsEx(&icc);
  605. }
  606. return fInitialized;
  607. }
  608. #ifndef ALPHA_WARNING_IS_DUMB
  609. #pragma message("building with alpha warning enabled")
  610. void AlphaWarning(HWND hwnd)
  611. {
  612. static BOOL fShown = FALSE;
  613. TCHAR szTemp[265];
  614. TCHAR szFull[2048];
  615. szFull[0] = TEXT('\0');
  616. int i = IDS_ALPHAWARNING;
  617. if (fShown)
  618. return;
  619. fShown = TRUE;
  620. while(MLLoadShellLangString (i++, szTemp, ARRAYSIZE(szTemp))) {
  621. StrCatBuff(szFull, szTemp, ARRAYSIZE(szFull));
  622. }
  623. MessageBox(hwnd, szFull, TEXT("Internet Explorer"), MB_ICONINFORMATION | MB_OK);
  624. }
  625. #endif
  626. #define DM_NAV TF_SHDNAVIGATE
  627. #define DM_ZONE TF_SHDNAVIGATE
  628. #define DM_IEDDE DM_TRACE
  629. #define DM_CANCELMODE 0
  630. #define DM_UIWINDOW 0
  631. #define DM_ENABLEMODELESS 0
  632. #define DM_EXPLORERMENU 0
  633. #define DM_BACKFORWARD 0
  634. #define DM_PROTOCOL 0
  635. #define DM_ITBAR 0
  636. #define DM_STARTUP 0
  637. #define DM_AUTOLIFE 0
  638. #define DM_PALETTE 0
  639. PFNSHCHANGENOTIFYREGISTER g_pfnSHChangeNotifyRegister = NULL;
  640. PFNSHCHANGENOTIFYDEREGISTER g_pfnSHChangeNotifyDeregister = NULL;
  641. BOOL g_fNewNotify = FALSE; // Are we using classic mode (W95 or new mode?
  642. BOOL CALLBACK AddPropSheetPage(HPROPSHEETPAGE hpage, LPARAM lParam)
  643. {
  644. PROPSHEETHEADER * ppsh = (PROPSHEETHEADER *)lParam;
  645. if (ppsh->nPages < MAX_PAGES)
  646. {
  647. ppsh->phpage[ppsh->nPages++] = hpage;
  648. return TRUE;
  649. }
  650. return FALSE;
  651. }
  652. BOOL SHIsRegisteredClient(LPCTSTR pszClient)
  653. {
  654. LONG cbSize = 0;
  655. TCHAR szKey[80];
  656. wnsprintf(szKey, ARRAYSIZE(szKey), TEXT("Software\\Clients\\%s"), pszClient);
  657. return (RegQueryValue(HKEY_LOCAL_MACHINE, szKey, NULL, &cbSize) == ERROR_SUCCESS) &&
  658. (cbSize > sizeof(TCHAR));
  659. }
  660. // Exporting by ordinal is not available on UNIX.
  661. // But we have all these symbols exported because it's UNIX default.
  662. #ifdef UNIX
  663. #define GET_PRIVATE_PROC_ADDRESS(_hinst, _fname, _ord) GetProcAddress(_hinst, _fname)
  664. #else
  665. #define GET_PRIVATE_PROC_ADDRESS(_hinst, _fname, _ord) GetProcAddress(_hinst, _ord)
  666. #endif
  667. ULONG RegisterNotify(HWND hwnd, UINT nMsg, LPCITEMIDLIST pidl, DWORD dwEvents, UINT uFlags, BOOL fRecursive)
  668. {
  669. SHChangeNotifyEntry fsne;
  670. // See if we need to still figure out which version of SHChange Notify to call?
  671. if (g_pfnSHChangeNotifyDeregister == NULL)
  672. {
  673. HMODULE hmodShell32 = ::GetModuleHandle(TEXT("SHELL32"));
  674. if (!hmodShell32)
  675. return 0; // Nothing registered...
  676. g_pfnSHChangeNotifyRegister = (PFNSHCHANGENOTIFYREGISTER)GET_PRIVATE_PROC_ADDRESS(hmodShell32,
  677. "NTSHChangeNotifyRegister",
  678. (LPSTR)640);
  679. if (g_pfnSHChangeNotifyRegister && (WhichPlatform() == PLATFORM_INTEGRATED))
  680. {
  681. g_pfnSHChangeNotifyDeregister = (PFNSHCHANGENOTIFYDEREGISTER)GET_PRIVATE_PROC_ADDRESS(hmodShell32,
  682. "NTSHChangeNotifyDeregister",
  683. (LPSTR)641);
  684. g_fNewNotify = TRUE;
  685. }
  686. else
  687. {
  688. g_pfnSHChangeNotifyRegister = (PFNSHCHANGENOTIFYREGISTER)GET_PRIVATE_PROC_ADDRESS(hmodShell32,
  689. "SHChangeNotifyRegister",
  690. (LPSTR)2);
  691. g_pfnSHChangeNotifyDeregister = (PFNSHCHANGENOTIFYDEREGISTER)GET_PRIVATE_PROC_ADDRESS(hmodShell32,
  692. "SHChangeNotifyDeregister",
  693. (LPSTR)4);
  694. }
  695. if (g_pfnSHChangeNotifyDeregister == NULL)
  696. return 0; // Could not get either to work...
  697. }
  698. uFlags |= SHCNRF_ShellLevel | SHCNRF_InterruptLevel;
  699. if (g_fNewNotify)
  700. uFlags |= SHCNRF_NewDelivery;
  701. fsne.fRecursive = fRecursive;
  702. fsne.pidl = pidl;
  703. return g_pfnSHChangeNotifyRegister(hwnd, uFlags, dwEvents, nMsg, 1, &fsne);
  704. }
  705. //----------------------------------------------------------------------------
  706. // Just like shells SHRestricted() only this put up a message if the restricion
  707. // is in effect.
  708. // REARCHITECT: this function is identical to shell32's SHIsRestricted
  709. BOOL SHIsRestricted(HWND hwnd, RESTRICTIONS rest)
  710. {
  711. if (SHRestricted(rest))
  712. {
  713. ULONG_PTR uCookie = 0;
  714. SHActivateContext(&uCookie);
  715. SHRestrictedMessageBox(hwnd);
  716. if (uCookie)
  717. {
  718. SHDeactivateContext(uCookie);
  719. }
  720. return TRUE;
  721. }
  722. return FALSE;
  723. }
  724. BOOL SHIsRestricted2W(HWND hwnd, BROWSER_RESTRICTIONS rest, LPCWSTR pwzUrl, DWORD dwReserved)
  725. {
  726. if (SHRestricted2W(rest, pwzUrl, dwReserved))
  727. {
  728. ULONG_PTR uCookie = 0;
  729. SHActivateContext(&uCookie);
  730. SHRestrictedMessageBox(hwnd);
  731. if (uCookie)
  732. {
  733. SHDeactivateContext(uCookie);
  734. }
  735. return TRUE;
  736. }
  737. return FALSE;
  738. }
  739. BOOL ViewIDFromViewMode(UINT uViewMode, SHELLVIEWID *pvid)
  740. {
  741. switch (uViewMode)
  742. {
  743. case FVM_ICON:
  744. *pvid = VID_LargeIcons;
  745. break;
  746. case FVM_SMALLICON:
  747. *pvid = VID_SmallIcons;
  748. break;
  749. case FVM_LIST:
  750. *pvid = VID_List;
  751. break;
  752. case FVM_DETAILS:
  753. *pvid = VID_Details;
  754. break;
  755. case FVM_THUMBNAIL:
  756. *pvid = VID_Thumbnails;
  757. break;
  758. case FVM_TILE:
  759. *pvid = VID_Tile;
  760. break;
  761. default:
  762. *pvid = VID_LargeIcons;
  763. return(FALSE);
  764. }
  765. return(TRUE);
  766. }
  767. HIMAGELIST g_himlSysSmall = NULL;
  768. HIMAGELIST g_himlSysLarge = NULL;
  769. void _InitSysImageLists()
  770. {
  771. if (!g_himlSysSmall)
  772. {
  773. Shell_GetImageLists(&g_himlSysLarge, &g_himlSysSmall);
  774. ImageList_GetIconSize(g_himlSysLarge, &g_cxIcon, &g_cyIcon);
  775. ImageList_GetIconSize(g_himlSysSmall, &g_cxSmIcon, &g_cySmIcon);
  776. }
  777. }
  778. // Copied from shell32 (was _ILCreate), which does not export this.
  779. // The fsmenu code needs this function.
  780. STDAPI_(LPITEMIDLIST) IEILCreate(UINT cbSize)
  781. {
  782. LPITEMIDLIST pidl = (LPITEMIDLIST)SHAlloc(cbSize);
  783. if (pidl)
  784. memset(pidl, 0, cbSize); // needed for external task allicator
  785. return pidl;
  786. }
  787. DWORD CommonDragEnter(IDataObject *pdtobj, DWORD grfKeyState, POINTL pt)
  788. {
  789. DWORD dwEffect = DROPEFFECT_NONE;
  790. FORMATETC fmte = {CF_HDROP, NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL};
  791. if (pdtobj->QueryGetData(&fmte) == S_OK)
  792. dwEffect = DROPEFFECT_COPY | DROPEFFECT_LINK;
  793. else
  794. {
  795. InitClipboardFormats();
  796. fmte.cfFormat = g_cfHIDA;
  797. if (pdtobj->QueryGetData(&fmte) == S_OK)
  798. dwEffect = DROPEFFECT_LINK;
  799. else {
  800. fmte.cfFormat = g_cfURL;
  801. if (pdtobj->QueryGetData(&fmte) == S_OK)
  802. dwEffect = DROPEFFECT_LINK | DROPEFFECT_COPY | DROPEFFECT_MOVE;
  803. }
  804. }
  805. return dwEffect;
  806. }
  807. // MapNbspToSp
  808. //
  809. // Purpose:
  810. // dsheldon: nbsp == Non-breaking space
  811. // Unicode character code point 0x00a0 is designated to HTML
  812. // entity &nbsp, but some windows code pages don't have code
  813. // point that can map from 0x00a0. In the most occasion in the
  814. // shell, NBSP is just a space when it's rendered so we can
  815. // replace it with 0x0020 safely.
  816. // This function takes lpwszIn as a string that has
  817. // non-displayable characters in it, and tries to translate
  818. // it again after removing NBSP (00a0) from it.
  819. // returns S_OK if this re-translation is successful.
  820. //
  821. #define nbsp 0x00a0
  822. HRESULT SHMapNbspToSp(LPCWSTR lpwszIn, LPSTR lpszOut, int cbszOut)
  823. {
  824. BOOL fFoundNbsp = FALSE;
  825. BOOL fNotDisplayable = TRUE; // assumes FAIL
  826. LPWSTR pwsz, p;
  827. if (!lpwszIn || !lpszOut || cbszOut == 0)
  828. return E_FAIL;
  829. ASSERT(IS_VALID_STRING_PTRW(lpwszIn, -1));
  830. ASSERT(IS_VALID_WRITE_BUFFER(lpszOut, TCHAR, cbszOut));
  831. int cch = lstrlenW(lpwszIn) + 1;
  832. pwsz = (LPWSTR)LocalAlloc(LPTR, cch * sizeof(WCHAR));
  833. if (pwsz)
  834. {
  835. StrCpyNW(pwsz, lpwszIn, cch);
  836. p = pwsz;
  837. while (*p)
  838. {
  839. if (*p== nbsp)
  840. {
  841. *p= 0x0020; // replace with space
  842. if (!fFoundNbsp)
  843. fFoundNbsp = TRUE;
  844. }
  845. p++;
  846. }
  847. // don't call WC2MB unless we found Nbsp - for perf reason
  848. if (fFoundNbsp)
  849. {
  850. int iret = WideCharToMultiByte(CP_ACP, 0, pwsz, -1, lpszOut,
  851. cbszOut, NULL, &fNotDisplayable);
  852. if (!fNotDisplayable && iret == 0)
  853. {
  854. // truncated. make it dbcs safe.
  855. SHTruncateString(lpszOut, cbszOut);
  856. }
  857. }
  858. LocalFree((LOCALHANDLE)pwsz);
  859. pwsz = NULL;
  860. }
  861. return (fFoundNbsp && !fNotDisplayable) ? S_OK : S_FALSE;
  862. }
  863. #undef nbsp
  864. int PropBag_ReadInt4(IPropertyBag* pPropBag, LPWSTR pszKey, int iDefault)
  865. {
  866. SHPropertyBag_ReadInt(pPropBag, pszKey, &iDefault);
  867. return iDefault;
  868. }
  869. HRESULT _SetPreferredDropEffect(IDataObject *pdtobj, DWORD dwEffect)
  870. {
  871. InitClipboardFormats();
  872. HRESULT hres = E_OUTOFMEMORY;
  873. DWORD *pdw = (DWORD *)GlobalAlloc(GPTR, sizeof(DWORD));
  874. if (pdw)
  875. {
  876. STGMEDIUM medium;
  877. FORMATETC fmte = {g_cfPreferredEffect, NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL};
  878. *pdw = dwEffect;
  879. medium.tymed = TYMED_HGLOBAL;
  880. medium.hGlobal = pdw;
  881. medium.pUnkForRelease = NULL;
  882. hres = pdtobj->SetData(&fmte, &medium, TRUE);
  883. if (FAILED(hres))
  884. {
  885. GlobalFree((HGLOBAL)pdw);
  886. pdw = NULL;
  887. }
  888. }
  889. return hres;
  890. }
  891. HRESULT DragDrop(HWND hwnd, IShellFolder * psfParent, LPCITEMIDLIST pidl, DWORD dwPrefEffect, DWORD *pdwEffect)
  892. {
  893. HRESULT hres = E_FAIL;
  894. LPCITEMIDLIST pidlChild;
  895. if (!psfParent)
  896. IEBindToParentFolder(pidl, &psfParent, &pidlChild);
  897. else
  898. {
  899. pidlChild = pidl;
  900. psfParent->AddRef();
  901. }
  902. if (psfParent)
  903. {
  904. DWORD dwAttrib = DROPEFFECT_MOVE | DROPEFFECT_COPY | DROPEFFECT_LINK;
  905. psfParent->GetAttributesOf(1, &pidlChild, &dwAttrib);
  906. IDataObject *pdtobj;
  907. hres = psfParent->GetUIObjectOf(NULL, 1, &pidlChild, IID_IDataObject, NULL, (void**)&pdtobj);
  908. if (SUCCEEDED(hres))
  909. {
  910. DWORD dwEffect = (DROPEFFECT_MOVE | DROPEFFECT_COPY | DROPEFFECT_LINK) & dwAttrib;
  911. if (dwPrefEffect)
  912. {
  913. //win95 shell32 doesn't know about preferred drop effect, so make it the only effect
  914. if (IsOS(OS_WIN95ORGREATER) && (WhichPlatform() == PLATFORM_BROWSERONLY))
  915. {
  916. dwEffect = DROPEFFECT_LINK & dwAttrib;
  917. }
  918. else if (dwPrefEffect & dwEffect)
  919. {
  920. _SetPreferredDropEffect(pdtobj, dwPrefEffect);
  921. }
  922. }
  923. ASSERT(dwEffect);
  924. // Win95 Browser Only - the shell32 in this process doesn't know
  925. // ole is loaded, even though it is.
  926. SHLoadOLE(SHELLNOTIFY_OLELOADED);
  927. IDragSourceHelper* pDragImages;
  928. if (SUCCEEDED(CoCreateInstance(CLSID_DragDropHelper, NULL, CLSCTX_INPROC_SERVER, IID_PPV_ARG(IDragSourceHelper, &pDragImages))))
  929. {
  930. pDragImages->InitializeFromWindow(hwnd, 0, pdtobj);
  931. pDragImages->Release();
  932. }
  933. hres = SHDoDragDrop(hwnd, pdtobj, NULL, dwEffect, &dwEffect);
  934. if (pdwEffect)
  935. *pdwEffect = dwEffect;
  936. pdtobj->Release();
  937. }
  938. psfParent->Release();
  939. }
  940. return hres;
  941. }
  942. #define IEICONTYPE_GETFILEINFO 0x00000001
  943. #define IEICONTYPE_DEFAULTICON 0x00000002
  944. typedef struct tagIEICONS
  945. {
  946. int nDefaultIcon;
  947. int nIEIcon;
  948. LPCTSTR szFile;
  949. LPCTSTR szFileExt;
  950. int nIconResourceNum;
  951. LPCTSTR szCLSID;
  952. DWORD dwType;
  953. } IEICONS;
  954. IEICONS g_IEIcons[] = {
  955. {-1, -1, TEXT("MSHTML.DLL"), TEXT(".htm"), 1, NULL, IEICONTYPE_GETFILEINFO},
  956. {-1, -1, TEXT("URL.DLL"), TEXT("http\\DefaultIcon"), 0, TEXT("{FBF23B42-E3F0-101B-8488-00AA003E56F8}"), IEICONTYPE_DEFAULTICON}
  957. };
  958. //This function returns the IE icon regardless of the which browser is default
  959. void _GenerateIEIcons(void)
  960. {
  961. int nIndex;
  962. for (nIndex = 0; nIndex < ARRAYSIZE(g_IEIcons); nIndex++)
  963. {
  964. SHFILEINFO sfi;
  965. TCHAR szModule[MAX_PATH];
  966. HMODULE hmod = GetModuleHandle(g_IEIcons[nIndex].szFile);
  967. if (hmod)
  968. {
  969. GetModuleFileName(hmod, szModule, ARRAYSIZE(szModule));
  970. }
  971. else
  972. { //HACKHACK : This is a hack to get the mstml
  973. TCHAR szKey[GUIDSTR_MAX * 4];
  974. TCHAR szGuid[GUIDSTR_MAX];
  975. //The CLSID used here belongs to MS HTML Generic Page. If someone changes the guid then we
  976. // are tossed.
  977. if (!g_IEIcons[nIndex].szCLSID)
  978. SHStringFromGUID(CLSID_HTMLDocument, szGuid, GUIDSTR_MAX);
  979. wnsprintf(szKey, ARRAYSIZE(szKey), TEXT("CLSID\\%s\\InProcServer32"), g_IEIcons[nIndex].szCLSID ? g_IEIcons[nIndex].szCLSID : szGuid);
  980. long cb = SIZEOF(szModule);
  981. RegQueryValue(HKEY_CLASSES_ROOT, szKey, szModule, &cb);
  982. }
  983. g_IEIcons[nIndex].nIEIcon = Shell_GetCachedImageIndex(szModule, g_IEIcons[nIndex].nIconResourceNum, 0);
  984. switch(g_IEIcons[nIndex].dwType)
  985. {
  986. case IEICONTYPE_GETFILEINFO:
  987. sfi.iIcon = 0;
  988. StrCpyN(szModule, TEXT("c:\\notexist"), ARRAYSIZE(szModule));
  989. StrCatBuff(szModule, g_IEIcons[nIndex].szFileExt, ARRAYSIZE(szModule));
  990. SHGetFileInfo(szModule, FILE_ATTRIBUTE_NORMAL, &sfi, sizeof(sfi), SHGFI_SYSICONINDEX | SHGFI_USEFILEATTRIBUTES);
  991. g_IEIcons[nIndex].nDefaultIcon = sfi.iIcon;
  992. break;
  993. case IEICONTYPE_DEFAULTICON:
  994. {
  995. TCHAR szPath[MAX_PATH];
  996. DWORD cbSize = SIZEOF(szPath);
  997. SHGetValue(HKEY_CLASSES_ROOT, g_IEIcons[nIndex].szFileExt, TEXT(""), NULL, szPath, &cbSize);
  998. g_IEIcons[nIndex].nDefaultIcon = Shell_GetCachedImageIndex(szPath, PathParseIconLocation(szPath), 0);
  999. }
  1000. break;
  1001. }
  1002. }
  1003. }
  1004. int IEMapPIDLToSystemImageListIndex(IShellFolder *psfParent, LPCITEMIDLIST pidlChild, int *piSelectedImage)
  1005. {
  1006. int nIndex;
  1007. int nIcon = SHMapPIDLToSystemImageListIndex(psfParent, pidlChild, piSelectedImage);
  1008. if (-1 == g_IEIcons[0].nDefaultIcon)
  1009. _GenerateIEIcons();
  1010. for (nIndex = 0; nIndex < ARRAYSIZE(g_IEIcons); nIndex++)
  1011. {
  1012. if ((nIcon == g_IEIcons[nIndex].nDefaultIcon) ||
  1013. (piSelectedImage && *piSelectedImage == g_IEIcons[nIndex].nDefaultIcon))
  1014. {
  1015. nIcon = g_IEIcons[nIndex].nIEIcon;
  1016. if (piSelectedImage)
  1017. *piSelectedImage = nIcon;
  1018. break;
  1019. }
  1020. }
  1021. return nIcon;
  1022. }
  1023. void IEInvalidateImageList(void)
  1024. {
  1025. g_IEIcons[0].nDefaultIcon = -1;
  1026. }
  1027. int _GetIEHTMLImageIndex()
  1028. {
  1029. if (-1 == g_IEIcons[0].nDefaultIcon)
  1030. _GenerateIEIcons();
  1031. return g_IEIcons[0].nIEIcon;
  1032. }
  1033. // Checks to see if any process at all
  1034. // has loaded wininet
  1035. static BOOL g_fWininetLoadedSomeplace = FALSE;
  1036. BOOL IsWininetLoadedAnywhere()
  1037. {
  1038. HANDLE hMutex = NULL;
  1039. BOOL fRet;
  1040. if (g_fWininetLoadedSomeplace)
  1041. return TRUE;
  1042. //
  1043. // Use OpenMutexA so it works on W95.
  1044. // wininet is ansi and created this mutex with CreateMutexA
  1045. hMutex = OpenMutexA(SYNCHRONIZE, FALSE, WININET_STARTUP_MUTEX);
  1046. if (hMutex)
  1047. {
  1048. fRet = TRUE;
  1049. g_fWininetLoadedSomeplace = TRUE;
  1050. CloseHandle(hMutex);
  1051. }
  1052. else
  1053. {
  1054. fRet = FALSE;
  1055. }
  1056. return fRet;
  1057. }
  1058. // Checks if global state is offline
  1059. BOOL SHIsGlobalOffline(void)
  1060. {
  1061. DWORD dwState = 0, dwSize = sizeof(DWORD);
  1062. BOOL fRet = FALSE;
  1063. if (!IsWininetLoadedAnywhere())
  1064. return FALSE;
  1065. // Since wininet is already loaded someplace
  1066. // We have to load wininet to check if offline
  1067. if (InternetQueryOptionA(NULL, INTERNET_OPTION_CONNECTED_STATE, &dwState,
  1068. &dwSize))
  1069. {
  1070. if (dwState & INTERNET_STATE_DISCONNECTED_BY_USER)
  1071. fRet = TRUE;
  1072. }
  1073. return fRet;
  1074. }
  1075. void SetGlobalOffline(BOOL fOffline)
  1076. {
  1077. INTERNET_CONNECTED_INFO ci = {0};
  1078. if (fOffline) {
  1079. ci.dwConnectedState = INTERNET_STATE_DISCONNECTED_BY_USER;
  1080. ci.dwFlags = ISO_FORCE_DISCONNECTED;
  1081. } else {
  1082. ci.dwConnectedState = INTERNET_STATE_CONNECTED;
  1083. }
  1084. InternetSetOption(NULL, INTERNET_OPTION_CONNECTED_STATE, &ci, sizeof(ci));
  1085. }
  1086. // This API is documented and is called by apps outside
  1087. // the shell such as OE
  1088. STDAPI_(void) SetShellOfflineState(BOOL fPutOffline)
  1089. {
  1090. BOOL fWasOffline = SHIsGlobalOffline();
  1091. if (fWasOffline != fPutOffline)
  1092. {
  1093. SetGlobalOffline(fPutOffline); // Set the state
  1094. // Tell all browser windows to update their title
  1095. SendShellIEBroadcastMessage(WM_WININICHANGE,0,0, 1000);
  1096. }
  1097. }
  1098. BOOL GetHistoryFolderPath(LPTSTR pszPath, int cchPath)
  1099. {
  1100. INTERNET_CACHE_CONFIG_INFO cci;
  1101. DWORD cbcci = sizeof(INTERNET_CACHE_CONFIG_INFO);
  1102. if (GetUrlCacheConfigInfo(&cci, &cbcci, CACHE_CONFIG_HISTORY_PATHS_FC))
  1103. {
  1104. StrCpyN(pszPath, cci.CachePaths[0].CachePath, cchPath);
  1105. return TRUE;
  1106. }
  1107. return FALSE;
  1108. }
  1109. // in:
  1110. // pidlRoot root part of pidl.
  1111. // pidl equal to or child below pidlRoot
  1112. // pszKey root key to store stuff under, should match pidlRoot
  1113. // grfMode read/write
  1114. //
  1115. // example:
  1116. // pidlRoot = c:\win\favorites
  1117. // pidl = c:\win\favorites\channels
  1118. // pszKey = "MenuOrder\Favorites"
  1119. // result -> stream comes from HKCU\...\MenuOrder\Favorites\channels
  1120. //
  1121. IStream * OpenPidlOrderStream(LPCITEMIDLIST pidlRoot, LPCITEMIDLIST pidl, LPCSTR pszKey, DWORD grfMode)
  1122. {
  1123. LPITEMIDLIST pidlAlloc = NULL;
  1124. TCHAR szRegPath[MAX_URL_STRING];
  1125. TCHAR szKey[MAXIMUM_SUB_KEY_LENGTH];
  1126. SHAnsiToTChar(pszKey, szKey, ARRAYSIZE(szKey));
  1127. StrCpyN(szRegPath, TEXT("Software\\Microsoft\\Windows\\CurrentVersion\\Explorer"), ARRAYSIZE(szRegPath));
  1128. StrCatBuff(szRegPath, szKey, ARRAYSIZE(szRegPath));
  1129. // deal with ordinal vs true pidls
  1130. if (HIWORD(pidlRoot) == 0)
  1131. {
  1132. // Sundown: coercion to int since we are assuming ordinal pidl
  1133. SHGetSpecialFolderLocation(NULL, PtrToLong(pidlRoot), &pidlAlloc);
  1134. pidlRoot = pidlAlloc;
  1135. }
  1136. // build a reg key from the names of the items below the pidlRoot folder. we do
  1137. // this because IEGetDisplayName(SFGAO_FORPARSING) has a bug for file system
  1138. // junctions (channel contents) that returns garbage path names.
  1139. if (pidlRoot)
  1140. {
  1141. LPITEMIDLIST pidlCopy = ILClone(pidl);
  1142. if (pidlCopy)
  1143. {
  1144. LPCITEMIDLIST pidlTail = ILFindChild(pidlRoot, pidlCopy);
  1145. if (pidlTail)
  1146. {
  1147. LPITEMIDLIST pidlNext;
  1148. for (pidlNext = ILGetNext(pidlTail); pidlNext; pidlNext = ILGetNext(pidlNext))
  1149. {
  1150. WORD cbSave = pidlNext->mkid.cb;
  1151. pidlNext->mkid.cb = 0;
  1152. IShellFolder *psf;
  1153. LPCITEMIDLIST pidlChild;
  1154. // we do a full bind every time, we could skip this for sub items
  1155. // and bind from this point down but this code is simpler and binds
  1156. // aren't that bad...
  1157. if (SUCCEEDED(IEBindToParentFolder(pidlCopy, &psf, &pidlChild)))
  1158. {
  1159. LPWSTR pszName;
  1160. if (SUCCEEDED(DisplayNameOfAsOLESTR(psf, pidlChild, SHGDN_NORMAL, &pszName)))
  1161. {
  1162. StrCatBuff(szRegPath, TEXT("\\"), ARRAYSIZE(szRegPath));
  1163. StrCatBuff(szRegPath, pszName, ARRAYSIZE(szRegPath));
  1164. CoTaskMemFree(pszName);
  1165. }
  1166. psf->Release();
  1167. }
  1168. pidlNext->mkid.cb = cbSave;
  1169. }
  1170. }
  1171. ILFree(pidlCopy);
  1172. }
  1173. if (pidlAlloc)
  1174. ILFree(pidlAlloc);
  1175. return SHOpenRegStream(HKEY_CURRENT_USER, szRegPath, TEXT("Order"), grfMode);
  1176. }
  1177. return NULL;
  1178. }
  1179. /**********************************************************************
  1180. * SHRestricted2
  1181. *
  1182. * These are new restrictions that apply to browser only and integrated
  1183. * mode. (Since we're not changing shell32 in browser only mode, we
  1184. * need to duplicate the functionality.)
  1185. *
  1186. * FEATURE: What window will listen to the WM_WININICHANGE
  1187. * lParam="Policy" message and invalidate the cache?
  1188. * Remember not to cache the per zone values.
  1189. \**********************************************************************/
  1190. // The ZAW compliant policy location.
  1191. const TCHAR c_szInfodeliveryBase[] = TEXT("Software\\Policies\\Microsoft\\Internet Explorer\\Infodelivery");
  1192. const TCHAR c_szInfodeliveryKey[] = TEXT("Restrictions");
  1193. // The normal policy location.
  1194. const TCHAR c_szExplorerBase[] = TEXT("Software\\Microsoft\\Windows\\CurrentVersion\\Policies");
  1195. const TCHAR c_szExplorerKey[] = TEXT("Explorer");
  1196. // The browser policy location that SP2 used
  1197. const TCHAR c_szBrowserBase[] = TEXT("Software\\Policies\\Microsoft\\Internet Explorer");
  1198. const TCHAR c_szBrowserKey[] = TEXT("Restrictions");
  1199. const TCHAR c_szToolbarKey[] = TEXT("Toolbars\\Restrictions");
  1200. const SHRESTRICTIONITEMS c_rgRestrictionItems[] =
  1201. {
  1202. // explorer restrictions
  1203. { REST_NOTOOLBARCUSTOMIZE, c_szExplorerKey, TEXT("NoToolbarCustomize") },
  1204. { REST_NOBANDCUSTOMIZE, c_szExplorerKey, TEXT("NoBandCustomize") },
  1205. { REST_SMALLICONS, c_szExplorerKey, TEXT("SmallIcons") },
  1206. { REST_LOCKICONSIZE, c_szExplorerKey, TEXT("LockIconSize") },
  1207. { REST_SPECIFYDEFAULTBUTTONS, c_szExplorerKey, TEXT("SpecifyDefaultButtons") },
  1208. { REST_BTN_BACK, c_szExplorerKey, TEXT("Btn_Back") },
  1209. { REST_BTN_FORWARD, c_szExplorerKey, TEXT("Btn_Forward") },
  1210. { REST_BTN_STOPDOWNLOAD, c_szExplorerKey, TEXT("Btn_Stop") },
  1211. { REST_BTN_REFRESH, c_szExplorerKey, TEXT("Btn_Refresh") },
  1212. { REST_BTN_HOME, c_szExplorerKey, TEXT("Btn_Home") },
  1213. { REST_BTN_SEARCH, c_szExplorerKey, TEXT("Btn_Search") },
  1214. { REST_BTN_HISTORY, c_szExplorerKey, TEXT("Btn_History") },
  1215. { REST_BTN_FAVORITES, c_szExplorerKey, TEXT("Btn_Favorites") },
  1216. { REST_BTN_ALLFOLDERS, c_szExplorerKey, TEXT("Btn_Folders") },
  1217. { REST_BTN_THEATER, c_szExplorerKey, TEXT("Btn_Fullscreen") },
  1218. { REST_BTN_TOOLS, c_szExplorerKey, TEXT("Btn_Tools") },
  1219. { REST_BTN_MAIL, c_szExplorerKey, TEXT("Btn_MailNews") },
  1220. { REST_BTN_FONTS, c_szExplorerKey, TEXT("Btn_Size") },
  1221. { REST_BTN_PRINT, c_szExplorerKey, TEXT("Btn_Print") },
  1222. { REST_BTN_EDIT, c_szExplorerKey, TEXT("Btn_Edit") },
  1223. { REST_BTN_DISCUSSIONS, c_szExplorerKey, TEXT("Btn_Discussions") },
  1224. { REST_BTN_CUT, c_szExplorerKey, TEXT("Btn_Cut") },
  1225. { REST_BTN_COPY, c_szExplorerKey, TEXT("Btn_Copy") },
  1226. { REST_BTN_PASTE, c_szExplorerKey, TEXT("Btn_Paste") },
  1227. { REST_BTN_ENCODING, c_szExplorerKey, TEXT("Btn_Encoding") },
  1228. { REST_BTN_PRINTPREVIEW, c_szExplorerKey, TEXT("Btn_PrintPreview") },
  1229. { REST_NoUserAssist, c_szExplorerKey, TEXT("NoInstrumentation"), },
  1230. { REST_NoWindowsUpdate, c_szExplorerKey, TEXT("NoWindowsUpdate"), },
  1231. { REST_NoExpandedNewMenu, c_szExplorerKey, TEXT("NoExpandedNewMenu"), },
  1232. { REST_BTN_MEDIABAR, c_szExplorerKey, TEXT("Btn_Media"), },
  1233. // ported from SP1
  1234. { REST_NOFILEURL, c_szExplorerKey, TEXT("NoFileUrl"), },
  1235. // infodelivery restrictions
  1236. { REST_NoChannelUI, c_szInfodeliveryKey, TEXT("NoChannelUI") },
  1237. { REST_NoAddingChannels, c_szInfodeliveryKey, TEXT("NoAddingChannels") },
  1238. { REST_NoEditingChannels, c_szInfodeliveryKey, TEXT("NoEditingChannels") },
  1239. { REST_NoRemovingChannels, c_szInfodeliveryKey, TEXT("NoRemovingChannels") },
  1240. { REST_NoAddingSubscriptions, c_szInfodeliveryKey, TEXT("NoAddingSubscriptions") },
  1241. { REST_NoEditingSubscriptions, c_szInfodeliveryKey, TEXT("NoEditingSubscriptions") },
  1242. { REST_NoRemovingSubscriptions, c_szInfodeliveryKey, TEXT("NoRemovingSubscriptions") },
  1243. { REST_NoChannelLogging, c_szInfodeliveryKey, TEXT("NoChannelLogging") },
  1244. { REST_NoManualUpdates, c_szInfodeliveryKey, TEXT("NoManualUpdates") },
  1245. { REST_NoScheduledUpdates, c_szInfodeliveryKey, TEXT("NoScheduledUpdates") },
  1246. { REST_NoUnattendedDialing, c_szInfodeliveryKey, TEXT("NoUnattendedDialing") },
  1247. { REST_NoChannelContent, c_szInfodeliveryKey, TEXT("NoChannelContent") },
  1248. { REST_NoSubscriptionContent, c_szInfodeliveryKey, TEXT("NoSubscriptionContent") },
  1249. { REST_NoEditingScheduleGroups, c_szInfodeliveryKey, TEXT("NoEditingScheduleGroups") },
  1250. { REST_MaxChannelSize, c_szInfodeliveryKey, TEXT("MaxChannelSize") },
  1251. { REST_MaxSubscriptionSize, c_szInfodeliveryKey, TEXT("MaxSubscriptionSize") },
  1252. { REST_MaxChannelCount, c_szInfodeliveryKey, TEXT("MaxChannelCount") },
  1253. { REST_MaxSubscriptionCount, c_szInfodeliveryKey, TEXT("MaxSubscriptionCount") },
  1254. { REST_MinUpdateInterval, c_szInfodeliveryKey, TEXT("MinUpdateInterval") },
  1255. { REST_UpdateExcludeBegin, c_szInfodeliveryKey, TEXT("UpdateExcludeBegin") },
  1256. { REST_UpdateExcludeEnd, c_szInfodeliveryKey, TEXT("UpdateExcludeEnd") },
  1257. { REST_UpdateInNewProcess, c_szInfodeliveryKey, TEXT("UpdateInNewProcess") },
  1258. { REST_MaxWebcrawlLevels, c_szInfodeliveryKey, TEXT("MaxWebcrawlLevels") },
  1259. { REST_MaxChannelLevels, c_szInfodeliveryKey, TEXT("MaxChannelLevels") },
  1260. { REST_NoSubscriptionPasswords, c_szInfodeliveryKey, TEXT("NoSubscriptionPasswords")},
  1261. { REST_NoBrowserSaveWebComplete,c_szInfodeliveryKey, TEXT("NoBrowserSaveWebComplete") },
  1262. { REST_NoSearchCustomization, c_szInfodeliveryKey, TEXT("NoSearchCustomization"), },
  1263. { REST_NoSplash, c_szInfodeliveryKey, TEXT("NoSplash"), },
  1264. // browser restrictions ported from SP2
  1265. { REST_NoFileOpen, c_szBrowserKey, TEXT("NoFileOpen"), },
  1266. { REST_NoFileNew, c_szBrowserKey, TEXT("NoFileNew"), },
  1267. { REST_NoBrowserSaveAs , c_szBrowserKey, TEXT("NoBrowserSaveAs"), },
  1268. { REST_NoBrowserOptions, c_szBrowserKey, TEXT("NoBrowserOptions"), },
  1269. { REST_NoFavorites, c_szBrowserKey, TEXT("NoFavorites"), },
  1270. { REST_NoSelectDownloadDir, c_szBrowserKey, TEXT("NoSelectDownloadDir"), },
  1271. { REST_NoBrowserContextMenu, c_szBrowserKey, TEXT("NoBrowserContextMenu"), },
  1272. { REST_NoBrowserClose, c_szBrowserKey, TEXT("NoBrowserClose"), },
  1273. { REST_NoOpeninNewWnd, c_szBrowserKey, TEXT("NoOpeninNewWnd"), },
  1274. { REST_NoTheaterMode, c_szBrowserKey, TEXT("NoTheaterMode"), },
  1275. { REST_NoFindFiles, c_szBrowserKey, TEXT("NoFindFiles"), },
  1276. { REST_NoViewSource, c_szBrowserKey, TEXT("NoViewSource"), },
  1277. { REST_GoMenu, c_szBrowserKey, TEXT("RestGoMenu"), },
  1278. { REST_NoToolbarOptions, c_szToolbarKey, TEXT("NoToolbarOptions"), },
  1279. { REST_AlwaysPromptWhenDownload,c_szBrowserKey, TEXT("AlwaysPromptWhenDownload"),},
  1280. { REST_NoHelpItem_TipOfTheDay, c_szBrowserKey, TEXT("NoHelpItemTipOfTheDay"), },
  1281. { REST_NoHelpItem_NetscapeHelp, c_szBrowserKey, TEXT("NoHelpItemNetscapeHelp"), },
  1282. { REST_NoHelpItem_Tutorial, c_szBrowserKey, TEXT("NoHelpItemTutorial"), },
  1283. { REST_NoHelpItem_SendFeedback, c_szBrowserKey, TEXT("NoHelpItemSendFeedback"), },
  1284. { REST_NoNavButtons, c_szBrowserKey, TEXT("NoNavButtons"), },
  1285. { REST_NoHelpMenu, c_szBrowserKey, TEXT("NoHelpMenu"), },
  1286. { REST_NoBrowserBars, c_szBrowserKey, TEXT("NoBrowserBars"), },
  1287. { REST_NoToolBar, c_szToolbarKey, TEXT("NoToolBar"), },
  1288. { REST_NoAddressBar, c_szToolbarKey, TEXT("NoAddressBar"), },
  1289. { REST_NoLinksBar, c_szToolbarKey, TEXT("NoLinksBar"), },
  1290. { REST_NoPrinting, c_szBrowserKey, TEXT("NoPrinting") },
  1291. { REST_No_LaunchMediaBar, c_szBrowserKey, TEXT("No_LaunchMediaBar") },
  1292. { REST_No_MediaBarOnlineContent, c_szBrowserKey, TEXT("No_MediaBarOnlineContent") },
  1293. {0, NULL, NULL},
  1294. };
  1295. typedef struct {
  1296. BROWSER_RESTRICTIONS rest;
  1297. DWORD dwAction;
  1298. } ACTIONITEM;
  1299. // SECURITY WARNING:
  1300. //
  1301. // Using url-based restrictions is a potential security risk with SHRestricted2W as implemented:
  1302. // you need a site to find the app-provided SID_SInternetSecurityManager
  1303. // implementation, and this API does not take one.
  1304. // Fortunately the only restrictions that get this treatment are the channel restrictions
  1305. // which are really Policy decisions. These only affect some explorer-only UI.
  1306. //
  1307. const ACTIONITEM c_ActionItems[] = {
  1308. { REST_NoAddingChannels, URLACTION_INFODELIVERY_NO_ADDING_CHANNELS },
  1309. { REST_NoEditingChannels, URLACTION_INFODELIVERY_NO_EDITING_CHANNELS },
  1310. { REST_NoRemovingChannels, URLACTION_INFODELIVERY_NO_REMOVING_CHANNELS },
  1311. { REST_NoAddingSubscriptions, URLACTION_INFODELIVERY_NO_ADDING_SUBSCRIPTIONS },
  1312. { REST_NoEditingSubscriptions, URLACTION_INFODELIVERY_NO_EDITING_SUBSCRIPTIONS },
  1313. { REST_NoRemovingSubscriptions, URLACTION_INFODELIVERY_NO_REMOVING_SUBSCRIPTIONS },
  1314. { REST_NoChannelLogging, URLACTION_INFODELIVERY_NO_CHANNEL_LOGGING },
  1315. };
  1316. #define REST_WITHACTION_FIRST REST_NoAddingChannels
  1317. #define REST_WITHACTION_LAST REST_NoChannelLogging
  1318. #define RESTRICTIONMAX (c_rgRestrictionItems[ARRAYSIZE(c_rgRestrictionItems) - 1].rest)
  1319. DWORD g_rgRestrictionItemValues[ARRAYSIZE(c_rgRestrictionItems)];
  1320. DWORD SHRestricted2W(BROWSER_RESTRICTIONS rest, LPCWSTR pwzUrl, DWORD dwReserved)
  1321. {
  1322. // Validate restriction and dwReserved
  1323. if (dwReserved)
  1324. {
  1325. RIPMSG(0, "SHRestricted2W: Invalid dwReserved");
  1326. return 0;
  1327. }
  1328. if (!(InRange(rest, REST_EXPLORER_FIRST, REST_EXPLORER_LAST))
  1329. && !(InRange(rest, REST_INFO_FIRST, REST_INFO_LAST))
  1330. && !(InRange(rest, REST_BROWSER_FIRST, REST_BROWSER_LAST)))
  1331. {
  1332. RIPMSG(0, "SHRestricted2W: Invalid browser restriction");
  1333. return 0;
  1334. }
  1335. // See if the restriction is in place in the URL zone
  1336. // FEATURE: Should we assert on NULL URLs if the restriction is per zone?
  1337. // It might be reasonable to query the global setting.
  1338. if (pwzUrl && InRange(rest, REST_WITHACTION_FIRST, REST_WITHACTION_LAST))
  1339. {
  1340. // Compute the index into the table
  1341. int index = rest - REST_WITHACTION_FIRST;
  1342. ASSERT(c_ActionItems[index].dwAction);
  1343. IInternetSecurityManager *pism;
  1344. HRESULT hr = CoCreateInstance(CLSID_InternetSecurityManager, NULL, CLSCTX_INPROC_SERVER,
  1345. IID_PPV_ARG(IInternetSecurityManager, &pism));
  1346. if (SUCCEEDED(hr))
  1347. {
  1348. DWORD dwPolicy = 0;
  1349. DWORD dwContext = 0;
  1350. hr = pism->ProcessUrlAction(pwzUrl,
  1351. c_ActionItems[index].dwAction,
  1352. (BYTE *)&dwPolicy,
  1353. sizeof(dwPolicy),
  1354. (BYTE *)&dwContext,
  1355. sizeof(dwContext),
  1356. PUAF_NOUI,
  1357. 0);
  1358. pism->Release();
  1359. if (SUCCEEDED(hr))
  1360. {
  1361. if (GetUrlPolicyPermissions(dwPolicy) == URLPOLICY_ALLOW)
  1362. return 0;
  1363. else
  1364. return 1; // restrict for query and disallow
  1365. }
  1366. }
  1367. }
  1368. // The cache may be invalid. Check first! We have to use
  1369. // a global named semaphore in case this function is called
  1370. // from a process other than the shell process. (And we're
  1371. // sharing the same count between shell32 and shdocvw.)
  1372. static HANDLE hRestrictions = NULL;
  1373. static long lRestrictionCount = -1;
  1374. if (hRestrictions == NULL)
  1375. hRestrictions = SHGlobalCounterCreate(GUID_Restrictions);
  1376. long lGlobalCount = SHGlobalCounterGetValue(hRestrictions);
  1377. if (lGlobalCount != lRestrictionCount)
  1378. {
  1379. memset((LPBYTE)g_rgRestrictionItemValues, (BYTE)-1, SIZEOF(g_rgRestrictionItemValues));
  1380. lRestrictionCount = lGlobalCount;
  1381. }
  1382. LPCWSTR pszBaseKey;
  1383. if (InRange(rest, REST_EXPLORER_FIRST, REST_EXPLORER_LAST))
  1384. pszBaseKey = c_szExplorerBase;
  1385. else
  1386. {
  1387. if (InRange(rest, REST_BROWSER_FIRST, REST_BROWSER_LAST))
  1388. pszBaseKey = c_szBrowserBase;
  1389. else
  1390. pszBaseKey = c_szInfodeliveryBase;
  1391. }
  1392. return SHRestrictionLookup(rest, pszBaseKey, c_rgRestrictionItems, g_rgRestrictionItemValues);
  1393. }
  1394. DWORD SHRestricted2A(BROWSER_RESTRICTIONS rest, LPCSTR pszUrl, DWORD dwReserved)
  1395. {
  1396. if (pszUrl)
  1397. {
  1398. WCHAR wzUrl[MAX_URL_STRING];
  1399. ASSERT(ARRAYSIZE(wzUrl) > lstrlenA(pszUrl)); // We only work for Urls of MAX_URL_STRING or shorter.
  1400. AnsiToUnicode(pszUrl, wzUrl, ARRAYSIZE(wzUrl));
  1401. return SHRestricted2W(rest, wzUrl, dwReserved);
  1402. }
  1403. else
  1404. {
  1405. return SHRestricted2W(rest, NULL, dwReserved);
  1406. }
  1407. }
  1408. /**********************************************************************
  1409. *
  1410. \**********************************************************************/
  1411. #define MAX_SUBSTR_SIZE 100
  1412. typedef struct tagURLSub
  1413. {
  1414. LPCTSTR szTag;
  1415. DWORD dwType;
  1416. } URLSUB;
  1417. const static URLSUB c_UrlSub[] = {
  1418. {TEXT("{SUB_PRD}"), URLSUB_PRD},
  1419. {TEXT("{SUB_PVER}"), URLSUB_PVER},
  1420. {TEXT("{SUB_OS}"), URLSUB_OS},
  1421. {TEXT("{SUB_OVER}"), URLSUB_OVER},
  1422. {TEXT("{SUB_OLCID}"), URLSUB_OLCID},
  1423. {TEXT("{SUB_CLCID}"), URLSUB_CLCID},
  1424. {TEXT("{SUB_CLSID}"), URLSUB_CLCID}, // legacy support (do NOT use "SUB_CLSID" in new URLs)
  1425. {TEXT("{SUB_RFC1766}"), URLSUB_RFC1766}
  1426. };
  1427. void GetWebLocaleAsRFC1766(LPTSTR pszLocale, int cchLocale)
  1428. {
  1429. LCID lcid;
  1430. TCHAR szValue[MAX_PATH];
  1431. DWORD cbVal = sizeof(szValue);
  1432. DWORD dwType;
  1433. ASSERT(NULL != pszLocale);
  1434. *pszLocale = TEXT('\0');
  1435. if ((SHGetValue(HKEY_CURRENT_USER, REGSTR_PATH_INTERNATIONAL,
  1436. REGSTR_VAL_ACCEPT_LANGUAGE,
  1437. &dwType, szValue, &cbVal) == ERROR_SUCCESS) &&
  1438. (REG_SZ == dwType))
  1439. {
  1440. TCHAR *psz = szValue;
  1441. // Use the first one we find so terminate at the comma or semicolon
  1442. while (*psz && (*psz != TEXT(',')) && (*psz != TEXT(';')))
  1443. {
  1444. psz = CharNext(psz);
  1445. }
  1446. *psz = TEXT('\0');
  1447. // If it's user defined, this will fail and we will fall back
  1448. // to the system default.
  1449. if (SUCCEEDED(Rfc1766ToLcid(&lcid, szValue)))
  1450. {
  1451. StrCpyN(pszLocale, szValue, cchLocale);
  1452. }
  1453. }
  1454. if (TEXT('\0') == *pszLocale)
  1455. {
  1456. // No entry in the registry or it's a user defined header.
  1457. // Either way we fall back to the system default.
  1458. LcidToRfc1766(GetUserDefaultLCID(), pszLocale, cchLocale);
  1459. }
  1460. }
  1461. HRESULT URLSubstitution(LPCWSTR pszUrlIn, LPWSTR pszUrlOut, DWORD cchSize, DWORD dwSubstitutions)
  1462. {
  1463. HRESULT hr = S_OK;
  1464. DWORD dwIndex;
  1465. WCHAR szTempUrl[MAX_URL_STRING];
  1466. ASSERT(cchSize <= ARRAYSIZE(szTempUrl)); // We will truncate anything longer than MAX_URL_STRING
  1467. StrCpyNW(szTempUrl, pszUrlIn, ARRAYSIZE(szTempUrl));
  1468. for (dwIndex = 0; dwIndex < ARRAYSIZE(c_UrlSub); dwIndex++)
  1469. {
  1470. // dsheldon - This will loop indefinitely as long as we keep finding instances of the substitution
  1471. // string. We break the loop when pszTag == NULL.
  1472. while (IsFlagSet(dwSubstitutions, c_UrlSub[dwIndex].dwType))
  1473. {
  1474. LPWSTR pszTag = StrStr(szTempUrl, c_UrlSub[dwIndex].szTag);
  1475. if (pszTag)
  1476. {
  1477. TCHAR szCopyUrl[MAX_URL_STRING];
  1478. TCHAR szSubStr[MAX_SUBSTR_SIZE]; // The Substitution
  1479. // Copy URL Before Substitution.
  1480. StrCpyN(szCopyUrl, szTempUrl, (int)(pszTag-szTempUrl+1));
  1481. pszTag += lstrlen(c_UrlSub[dwIndex].szTag);
  1482. switch (c_UrlSub[dwIndex].dwType)
  1483. {
  1484. case URLSUB_PRD:
  1485. MLLoadString(IDS_SUBSTR_PRD, szSubStr, ARRAYSIZE(szSubStr));
  1486. break;
  1487. case URLSUB_PVER:
  1488. MLLoadString(IDS_SUBSTR_PVER, szSubStr, ARRAYSIZE(szSubStr));
  1489. break;
  1490. case URLSUB_OS:
  1491. {
  1492. LPCTSTR pszWin95 = _T("95"); // Windows 95
  1493. LPCTSTR pszWin98 = _T("98"); // Windows 98 (Memphis)
  1494. LPCTSTR pszWinME = _T("ME"); // Windows Millenium
  1495. LPCTSTR pszWinNT4 = _T("N4"); // Windows NT 4
  1496. LPCTSTR pszWinNT5 = _T("N5"); // Windows 2000
  1497. LPCTSTR pszWinNT6 = _T("N6"); // Windows XP (Whistler)
  1498. LPCTSTR pszUnknown = _T(""); // error
  1499. LPCTSTR psz = pszUnknown;
  1500. if (IsOS(OS_WINDOWS))
  1501. {
  1502. if (IsOS(OS_MILLENNIUMORGREATER))
  1503. psz = pszWinME;
  1504. else if (IsOS(OS_WIN98ORGREATER))
  1505. psz = pszWin98;
  1506. else if (IsOS(OS_WIN95ORGREATER))
  1507. psz = pszWin95;
  1508. else
  1509. {
  1510. ASSERT(FALSE); // What OS is this?
  1511. }
  1512. }
  1513. else if (IsOS(OS_NT))
  1514. {
  1515. if (IsOS(OS_WHISTLERORGREATER))
  1516. psz = pszWinNT6;
  1517. else if (IsOS(OS_WIN2000ORGREATER))
  1518. psz = pszWinNT5;
  1519. else if (IsOS(OS_NT4ORGREATER))
  1520. psz = pszWinNT4;
  1521. else
  1522. {
  1523. ASSERT(FALSE); // What OS is this?
  1524. }
  1525. }
  1526. else
  1527. {
  1528. ASSERT(FALSE); // What OS is this?
  1529. }
  1530. StrCpyN(szSubStr, psz, ARRAYSIZE(szSubStr));
  1531. }
  1532. break;
  1533. case URLSUB_OVER:
  1534. {
  1535. LPCTSTR pszVersion_5_1 = _T("5.1"); // Version 5.1 (Whistler)
  1536. LPCTSTR pszUnknown = _T(""); // error
  1537. LPCTSTR psz = pszUnknown;
  1538. if (IsOS(OS_WINDOWS))
  1539. {
  1540. ASSERT(FALSE); // Not supported under Windows Millenium or lesser.
  1541. }
  1542. else if (IsOS(OS_NT))
  1543. {
  1544. if (IsOS(OS_WHISTLERORGREATER))
  1545. psz = pszVersion_5_1;
  1546. else
  1547. {
  1548. ASSERT(FALSE); // Not supported under Windows 2000 or lesser.
  1549. }
  1550. }
  1551. else
  1552. {
  1553. ASSERT(FALSE); // What OS is this?
  1554. }
  1555. StrCpyN(szSubStr, psz, ARRAYSIZE(szSubStr));
  1556. }
  1557. break;
  1558. case URLSUB_OLCID:
  1559. wnsprintf(szSubStr, ARRAYSIZE(szSubStr), _T("%#04lx"), GetSystemDefaultLCID());
  1560. break;
  1561. case URLSUB_CLCID:
  1562. wnsprintf(szSubStr, ARRAYSIZE(szSubStr), _T("%#04lx"), GetUserDefaultLCID());
  1563. break;
  1564. case URLSUB_RFC1766:
  1565. GetWebLocaleAsRFC1766(szSubStr, ARRAYSIZE(szSubStr));
  1566. break;
  1567. default:
  1568. szSubStr[0] = TEXT('\0');
  1569. ASSERT(FALSE); // Not Impl.
  1570. hr = E_NOTIMPL;
  1571. break;
  1572. }
  1573. // Add the Substitution String to the end (will become the middle)
  1574. StrCatBuff(szCopyUrl, szSubStr, ARRAYSIZE(szCopyUrl));
  1575. // Add the rest of the URL after the substitution substring.
  1576. StrCatBuff(szCopyUrl, pszTag, ARRAYSIZE(szCopyUrl));
  1577. StrCpyN(szTempUrl, szCopyUrl, ARRAYSIZE(szTempUrl));
  1578. }
  1579. else
  1580. break; // This will allow us to replace all the occurances of this string.
  1581. }
  1582. }
  1583. StrCpyN(pszUrlOut, szTempUrl, cchSize);
  1584. return hr;
  1585. }
  1586. // inetcpl.cpl uses this.
  1587. STDAPI URLSubRegQueryA(LPCSTR pszKey, LPCSTR pszValue, BOOL fUseHKCU,
  1588. LPSTR pszUrlOut, DWORD cchSizeOut, DWORD dwSubstitutions)
  1589. {
  1590. HRESULT hr;
  1591. TCHAR szKey[MAX_PATH];
  1592. TCHAR szValue[MAX_PATH];
  1593. TCHAR szUrlOut[MAX_URL_STRING];
  1594. AnsiToTChar(pszKey, szKey, ARRAYSIZE(szKey));
  1595. AnsiToTChar(pszValue, szValue, ARRAYSIZE(szValue));
  1596. hr = URLSubRegQueryW(szKey, szValue, fUseHKCU, szUrlOut, ARRAYSIZE(szUrlOut), dwSubstitutions);
  1597. TCharToAnsi(szUrlOut, pszUrlOut, cchSizeOut);
  1598. return hr;
  1599. }
  1600. HRESULT URLSubRegQueryW(LPCWSTR pszKey, LPCWSTR pszValue, BOOL fUseHKCU,
  1601. LPWSTR pszUrlOut, DWORD cchSizeOut, DWORD dwSubstitutions)
  1602. {
  1603. HRESULT hr = E_FAIL;
  1604. WCHAR szTempUrl[MAX_URL_STRING];
  1605. DWORD ccbSize = sizeof(szTempUrl);
  1606. if (ERROR_SUCCESS == SHRegGetUSValueW(pszKey, pszValue, NULL, szTempUrl,
  1607. &ccbSize, !fUseHKCU, NULL, NULL))
  1608. {
  1609. hr = URLSubstitution(szTempUrl, pszUrlOut, cchSizeOut, dwSubstitutions);
  1610. }
  1611. return hr;
  1612. }
  1613. // note that anyone inside shdocvw should pass hInst==NULL to
  1614. // ensure that pluggable UI works correctly. anyone outside of shdocvw
  1615. // must pass an hInst for their appropriate resource dll
  1616. HRESULT URLSubLoadString(HINSTANCE hInst, UINT idRes, LPWSTR pszUrlOut,
  1617. DWORD cchSizeOut, DWORD dwSubstitutions)
  1618. {
  1619. HRESULT hr = E_FAIL;
  1620. WCHAR szTempUrl[MAX_URL_STRING];
  1621. int nStrLen;
  1622. nStrLen = 0;
  1623. if (hInst == NULL)
  1624. {
  1625. // this is for internal users who want pluggable UI to work
  1626. nStrLen = MLLoadStringW(idRes, szTempUrl, ARRAYSIZE(szTempUrl));
  1627. }
  1628. else
  1629. {
  1630. // this is for external users who use us to load some
  1631. // of their own resources but whom we can't change (like shell32)
  1632. nStrLen = LoadStringWrap(hInst, idRes, szTempUrl, ARRAYSIZE(szTempUrl));
  1633. }
  1634. if (nStrLen > 0)
  1635. {
  1636. hr = URLSubstitution(szTempUrl, pszUrlOut, cchSizeOut, dwSubstitutions);
  1637. }
  1638. return hr;
  1639. }
  1640. /**********************************************************************\
  1641. ILIsUrlChild() will find pidls that exist under "Desktop\The Internet"
  1642. section of the Shell Name Space. This function includes those items
  1643. and file system items that have a "txt/html.
  1644. \**********************************************************************/
  1645. BOOL ILIsWeb(LPCITEMIDLIST pidl)
  1646. {
  1647. BOOL fIsWeb = FALSE;
  1648. if (pidl)
  1649. {
  1650. if (IsURLChild(pidl, TRUE))
  1651. fIsWeb = TRUE;
  1652. else
  1653. {
  1654. TCHAR szPath[MAX_PATH];
  1655. fIsWeb = (!ILIsRooted(pidl)
  1656. && SUCCEEDED(SHGetPathFromIDList(pidl, szPath))
  1657. && (PathIsHTMLFile(szPath) ||
  1658. PathIsContentType(szPath, TEXT("text/xml"))));
  1659. }
  1660. }
  1661. return fIsWeb;
  1662. }
  1663. //
  1664. // in:
  1665. // pidlTo
  1666. STDAPI CreateLinkToPidl(LPCITEMIDLIST pidlTo, LPCTSTR pszDir, LPCTSTR pszTitle, LPTSTR pszOut, int cchOut)
  1667. {
  1668. HRESULT hr = E_FAIL;
  1669. TCHAR szPathDest[MAX_URL_STRING];
  1670. BOOL fCopyLnk;
  1671. if (SHGetNewLinkInfo((LPCTSTR)pidlTo, pszDir, szPathDest, &fCopyLnk, SHGNLI_PIDL))
  1672. {
  1673. IShellLinkA *pslA; // Use A version for W95.
  1674. if (SUCCEEDED(CoCreateInstance(CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER, IID_PPV_ARG(IShellLinkA, &pslA))))
  1675. {
  1676. TCHAR szPathSrc[MAX_URL_STRING];
  1677. DWORD dwAttributes = SFGAO_FILESYSTEM | SFGAO_FOLDER;
  1678. SHGetNameAndFlags(pidlTo, SHGDN_FORPARSING | SHGDN_FORADDRESSBAR, szPathSrc, ARRAYSIZE(szPathSrc), &dwAttributes);
  1679. if (fCopyLnk)
  1680. {
  1681. if (((dwAttributes & (SFGAO_FILESYSTEM | SFGAO_FOLDER)) == SFGAO_FILESYSTEM) && CopyFile(szPathSrc, szPathDest, TRUE))
  1682. {
  1683. SHChangeNotify(SHCNE_CREATE, SHCNF_PATH, szPathDest, NULL);
  1684. SHChangeNotify(SHCNE_FREESPACE, SHCNF_PATH, szPathDest, NULL);
  1685. hr = S_OK;
  1686. }
  1687. else
  1688. {
  1689. // load the source object that will be "copied" below (with the ::Save call)
  1690. SAFERELEASE(pslA);
  1691. hr = SHGetUIObjectFromFullPIDL(pidlTo, NULL, IID_PPV_ARG(IShellLinkA, &pslA));
  1692. // this pslA is released at the end of the topmost if
  1693. if (SUCCEEDED(hr))
  1694. {
  1695. IPersistFile *ppf;
  1696. hr = pslA->QueryInterface(IID_PPV_ARG(IPersistFile, &ppf));
  1697. if (SUCCEEDED(hr))
  1698. {
  1699. hr = ppf->Save(szPathDest, TRUE);
  1700. ppf->Release();
  1701. }
  1702. }
  1703. }
  1704. }
  1705. else
  1706. {
  1707. pslA->SetIDList(pidlTo);
  1708. // make sure the working directory is set to the same
  1709. // directory as the app (or document).
  1710. //
  1711. // dont do this for non-FS pidls (ie control panel)
  1712. if (SFGAO_FILESYSTEM == (dwAttributes & SFGAO_FILESYSTEM | SFGAO_FOLDER))
  1713. {
  1714. ASSERT(!PathIsRelative(szPathSrc));
  1715. PathRemoveFileSpec(szPathSrc);
  1716. // Try to get the W version.
  1717. IShellLinkW* pslW;
  1718. if (SUCCEEDED(pslA->QueryInterface(IID_PPV_ARG(IShellLinkW, &pslW))))
  1719. {
  1720. pslW->SetWorkingDirectory(szPathSrc);
  1721. pslW->Release();
  1722. }
  1723. else
  1724. {
  1725. CHAR szPathSrcA[MAX_URL_STRING];
  1726. SHUnicodeToAnsi(szPathSrc, szPathSrcA, ARRAYSIZE(szPathSrcA));
  1727. pslA->SetWorkingDirectory(szPathSrcA);
  1728. }
  1729. }
  1730. IPersistFile *ppf;
  1731. hr = pslA->QueryInterface(IID_PPV_ARG(IPersistFile, &ppf));
  1732. if (SUCCEEDED(hr))
  1733. {
  1734. if (pszTitle && pszTitle[0])
  1735. {
  1736. PathRemoveFileSpec(szPathDest);
  1737. PathAppend(szPathDest, pszTitle);
  1738. StrCatBuff(szPathDest, TEXT(".lnk"), ARRAYSIZE(szPathDest));
  1739. }
  1740. hr = ppf->Save(szPathDest, TRUE);
  1741. if (pszOut)
  1742. {
  1743. StrCpyN(pszOut, szPathDest, cchOut);
  1744. }
  1745. ppf->Release();
  1746. }
  1747. }
  1748. SAFERELEASE(pslA);
  1749. }
  1750. }
  1751. return hr;
  1752. }
  1753. VOID CleanExploits(PWSTR psz)
  1754. {
  1755. while (*psz)
  1756. {
  1757. if (*psz<L' ')
  1758. {
  1759. *psz = L' ';
  1760. }
  1761. psz++;
  1762. }
  1763. }
  1764. HRESULT FormatUrlForDisplay(LPWSTR pwzURL, LPWSTR pwzFriendly, UINT cchBuf, LPWSTR pwzFrom, UINT cbFrom, BOOL fSeperate, DWORD dwCodePage, PWSTR pwzCachedFileName)
  1765. {
  1766. const DWORD dwMaxPathLen = 32;
  1767. const DWORD dwMaxHostLen = 32;
  1768. const DWORD dwMaxTemplateLen = 64;
  1769. const DWORD dwElipsisLen = 3;
  1770. const CHAR rgchElipsis[] = "...";
  1771. const WCHAR rgwchElipsis[] = L"...";
  1772. HRESULT hrRC = E_FAIL;
  1773. HRESULT hr;
  1774. if (pwzURL==NULL || pwzFriendly==NULL)
  1775. return E_POINTER;
  1776. *pwzFriendly = '\0';
  1777. if (!*pwzURL)
  1778. return S_OK;
  1779. if (!cchBuf)
  1780. return E_FAIL;
  1781. // Wininet can't deal with code pages other than CP_ACP so convert the URL ourself and call InterCrackUrlA
  1782. URL_COMPONENTSA urlComp;
  1783. CHAR rgchScheme[INTERNET_MAX_SCHEME_LENGTH];
  1784. CHAR rgchHostName[INTERNET_MAX_HOST_NAME_LENGTH];
  1785. CHAR rgchUrlPath[MAX_PATH];
  1786. CHAR rgchCanonicalUrl[MAX_URL_STRING];
  1787. LPSTR pszURL;
  1788. DWORD dwLen;
  1789. dwLen = MAX_URL_STRING * 2;
  1790. if ((pszURL = (LPSTR)LocalAlloc(LPTR, dwLen * sizeof(CHAR))) != NULL)
  1791. {
  1792. SHUnicodeToAnsiCP(dwCodePage, pwzURL, pszURL, dwLen);
  1793. dwLen = ARRAYSIZE(rgchCanonicalUrl);
  1794. hr = UrlCanonicalizeA(pszURL, rgchCanonicalUrl, &dwLen, 0);
  1795. if (SUCCEEDED(hr))
  1796. {
  1797. ZeroMemory(&urlComp, sizeof(urlComp));
  1798. urlComp.dwStructSize = sizeof(urlComp);
  1799. urlComp.lpszHostName = rgchHostName;
  1800. urlComp.dwHostNameLength = ARRAYSIZE(rgchHostName);
  1801. urlComp.lpszUrlPath = rgchUrlPath;
  1802. urlComp.dwUrlPathLength = ARRAYSIZE(rgchUrlPath);
  1803. urlComp.lpszScheme = rgchScheme;
  1804. urlComp.dwSchemeLength = ARRAYSIZE(rgchScheme);
  1805. hr = InternetCrackUrlA(rgchCanonicalUrl, lstrlenA(rgchCanonicalUrl), 0, &urlComp);
  1806. if (SUCCEEDED(hr))
  1807. {
  1808. DWORD dwPathLen = lstrlenA(rgchUrlPath);
  1809. DWORD dwHostLen = lstrlenA(rgchHostName);
  1810. DWORD dwSchemeLen = lstrlenA(rgchScheme);
  1811. CHAR rgchHostForDisplay[INTERNET_MAX_HOST_NAME_LENGTH];
  1812. CHAR rgchPathForDisplay[MAX_PATH];
  1813. ZeroMemory(rgchHostForDisplay, sizeof(rgchHostForDisplay));
  1814. ZeroMemory(rgchPathForDisplay, sizeof(rgchPathForDisplay));
  1815. if (dwHostLen>dwMaxHostLen)
  1816. {
  1817. DWORD dwOverFlow = dwHostLen - dwMaxHostLen + dwElipsisLen + 1;
  1818. wnsprintfA(rgchHostForDisplay, ARRAYSIZE(rgchHostForDisplay), "%s%s", rgchElipsis, rgchHostName+dwOverFlow);
  1819. dwHostLen = dwMaxHostLen;
  1820. }
  1821. else
  1822. StrCpyNA(rgchHostForDisplay, rgchHostName, ARRAYSIZE(rgchHostForDisplay));
  1823. if (dwPathLen>dwMaxPathLen)
  1824. {
  1825. DWORD dwOverFlow = dwPathLen - dwMaxPathLen + dwElipsisLen;
  1826. wnsprintfA(rgchPathForDisplay, ARRAYSIZE(rgchPathForDisplay), "/%s%s", rgchElipsis, rgchUrlPath+dwOverFlow);
  1827. dwPathLen = dwMaxPathLen;
  1828. }
  1829. else
  1830. StrCpyNA(rgchPathForDisplay, rgchUrlPath, ARRAYSIZE(rgchPathForDisplay));
  1831. WCHAR rgwchScheme[INTERNET_MAX_SCHEME_LENGTH];
  1832. WCHAR rgwchHostForDisplay[INTERNET_MAX_HOST_NAME_LENGTH];
  1833. WCHAR rgwchPathForDisplay[MAX_PATH];
  1834. WCHAR rgwchUrlPath[MAX_PATH];
  1835. SHAnsiToUnicodeCP(dwCodePage, rgchScheme, rgwchScheme, ARRAYSIZE(rgwchScheme));
  1836. SHAnsiToUnicodeCP(dwCodePage, rgchHostForDisplay, rgwchHostForDisplay, ARRAYSIZE(rgwchHostForDisplay));
  1837. SHAnsiToUnicodeCP(dwCodePage, rgchPathForDisplay, rgwchPathForDisplay, ARRAYSIZE(rgwchPathForDisplay));
  1838. SHAnsiToUnicodeCP(dwCodePage, rgchUrlPath, rgwchUrlPath, ARRAYSIZE(rgwchUrlPath));
  1839. if (pwzCachedFileName && *pwzCachedFileName)
  1840. {
  1841. WCHAR szUrlPath[MAX_PATH];
  1842. DWORD cc = ARRAYSIZE(rgchUrlPath);
  1843. if (FAILED(_PrepareURLForDisplayUTF8W(pwzCachedFileName, szUrlPath, &cc, TRUE, dwCodePage)))
  1844. {
  1845. StrCpyNW(szUrlPath, pwzCachedFileName, ARRAYSIZE(szUrlPath));
  1846. }
  1847. CleanExploits(szUrlPath);
  1848. dwPathLen = lstrlenW(szUrlPath);
  1849. if (dwPathLen>dwMaxPathLen)
  1850. {
  1851. DWORD dwOverFlow = dwPathLen - dwMaxPathLen + dwElipsisLen;
  1852. wnsprintfW(rgwchPathForDisplay, ARRAYSIZE(rgwchPathForDisplay), L"/%s%s", rgwchElipsis, szUrlPath+dwOverFlow);
  1853. dwPathLen = dwMaxPathLen;
  1854. }
  1855. else
  1856. StrCpyNW(rgwchPathForDisplay, szUrlPath, ARRAYSIZE(rgwchPathForDisplay));
  1857. }
  1858. if (fSeperate)
  1859. {
  1860. // Format string as "X from Y"
  1861. WCHAR rgwchTemplate[dwMaxTemplateLen];
  1862. WCHAR *pwzFileName = PathFindFileNameW(rgwchPathForDisplay);
  1863. DWORD dwCount;
  1864. //
  1865. // remove cache decoration goop to map ie5setup[1].exe to ie5setup.exe
  1866. //
  1867. PathUndecorateW(pwzFileName);
  1868. ZeroMemory(rgwchTemplate, sizeof(rgwchTemplate));
  1869. dwCount = MLLoadString(IDS_TARGETFILE, rgwchTemplate, ARRAYSIZE(rgwchTemplate));
  1870. if (dwCount > 0)
  1871. {
  1872. if (urlComp.nScheme == INTERNET_SCHEME_FILE)
  1873. {
  1874. StrCpyNW(rgwchHostForDisplay, rgwchUrlPath, ARRAYSIZE(rgwchHostForDisplay));
  1875. PathRemoveFileSpecW(rgwchHostForDisplay);
  1876. }
  1877. if (dwPathLen+lstrlenW(rgwchTemplate)+dwHostLen <= cchBuf)
  1878. {
  1879. //avoid formatting the string as "X from " in the event internetcrackurl fails us
  1880. if (rgwchHostForDisplay[0] != TEXT('\0'))
  1881. {
  1882. // if necessary return host separately
  1883. if (pwzFrom && cbFrom)
  1884. {
  1885. StrCpyNW(pwzFriendly, pwzFileName, cchBuf);
  1886. StrCpyNW(pwzFrom, rgwchHostForDisplay, cbFrom);
  1887. }
  1888. else
  1889. _FormatMessage(rgwchTemplate, pwzFriendly, cchBuf, pwzFileName, rgwchHostForDisplay);
  1890. }
  1891. else //hostname is blank, just use filename
  1892. StrCpyNW(pwzFriendly, pwzFileName, cchBuf);
  1893. hrRC = S_OK;
  1894. }
  1895. }
  1896. }
  1897. else // !fSeperate
  1898. {
  1899. if (3+dwPathLen+dwHostLen+dwSchemeLen < cchBuf)
  1900. {
  1901. wnsprintf(pwzFriendly, cchBuf, TEXT("%ws://%ws%ws"), rgwchScheme, rgwchHostForDisplay, rgwchPathForDisplay);
  1902. hrRC = S_OK;
  1903. }
  1904. }
  1905. }
  1906. }
  1907. LocalFree(pszURL);
  1908. pszURL = NULL;
  1909. }
  1910. return(hrRC);
  1911. }
  1912. BOOL __cdecl _FormatMessage(LPCWSTR szTemplate, LPWSTR szBuf, UINT cchBuf, ...)
  1913. {
  1914. BOOL fRet;
  1915. va_list ArgList;
  1916. va_start(ArgList, cchBuf);
  1917. fRet = FormatMessage(FORMAT_MESSAGE_FROM_STRING, szTemplate, 0, 0, szBuf, cchBuf, &ArgList);
  1918. va_end(ArgList);
  1919. return fRet;
  1920. }
  1921. // Navigate to a given Url (wszUrl) using IE. Returns an error if IE does not exist.
  1922. // fNewWindow = TRUE ==> A new window is compulsory
  1923. // fNewWindow = FALSE ==> Do not launch a new window if one already is open.
  1924. HRESULT NavToUrlUsingIEW(LPCWSTR wszUrl, BOOL fNewWindow)
  1925. {
  1926. HRESULT hr = S_OK;
  1927. if (!EVAL(wszUrl))
  1928. return E_INVALIDARG;
  1929. if (IsIEDefaultBrowser() && !fNewWindow)
  1930. {
  1931. // ShellExecute navigates to the Url using the same browser window,
  1932. // if one is already open.
  1933. SHELLEXECUTEINFOW sei = {0};
  1934. sei.cbSize = sizeof(sei);
  1935. sei.lpFile = wszUrl;
  1936. sei.nShow = SW_SHOWNORMAL;
  1937. ShellExecuteExW(&sei);
  1938. }
  1939. else
  1940. {
  1941. IWebBrowser2 *pwb2;
  1942. hr = CoCreateInstance(CLSID_InternetExplorer, NULL,
  1943. CLSCTX_LOCAL_SERVER, IID_PPV_ARG(IWebBrowser2, &pwb2));
  1944. if (SUCCEEDED(hr))
  1945. {
  1946. BSTR bstrUrl = SysAllocString(wszUrl);
  1947. if (bstrUrl)
  1948. {
  1949. VARIANT varURL;
  1950. varURL.vt = VT_BSTR;
  1951. varURL.bstrVal = bstrUrl;
  1952. VARIANT varFlags;
  1953. varFlags.vt = VT_I4;
  1954. varFlags.lVal = 0;
  1955. hr = pwb2->Navigate2(&varURL, &varFlags, PVAREMPTY, PVAREMPTY, PVAREMPTY);
  1956. ASSERT(SUCCEEDED(hr)); // mikesh sez there's no way for Navigate2 to fail
  1957. hr = pwb2->put_Visible( TRUE );
  1958. SysFreeString(bstrUrl);
  1959. }
  1960. else
  1961. hr = E_OUTOFMEMORY;
  1962. pwb2->Release();
  1963. }
  1964. }
  1965. return hr;
  1966. }
  1967. HRESULT NavToUrlUsingIEA(LPCSTR szUrl, BOOL fNewWindow)
  1968. {
  1969. WCHAR wszUrl[INTERNET_MAX_URL_LENGTH];
  1970. AnsiToUnicode(szUrl, wszUrl, ARRAYSIZE(wszUrl));
  1971. return NavToUrlUsingIEW(wszUrl, fNewWindow);
  1972. }
  1973. UINT g_cfURL = 0;
  1974. UINT g_cfURLW = 0;
  1975. UINT g_cfFileDescA = 0;
  1976. UINT g_cfFileContents = 0;
  1977. UINT g_cfPreferredEffect = 0;
  1978. UINT g_cfPerformedEffect = 0;
  1979. UINT g_cfTargetCLSID = 0;
  1980. UINT g_cfHIDA = 0;
  1981. UINT g_cfFileDescW = 0;
  1982. void InitClipboardFormats()
  1983. {
  1984. if (g_cfURL == 0)
  1985. {
  1986. g_cfURL = RegisterClipboardFormat(CFSTR_SHELLURL);
  1987. g_cfURLW = RegisterClipboardFormat(CFSTR_INETURLW);
  1988. g_cfFileDescA = RegisterClipboardFormat(CFSTR_FILEDESCRIPTORA);
  1989. g_cfFileContents = RegisterClipboardFormat(CFSTR_FILECONTENTS);
  1990. g_cfPreferredEffect = RegisterClipboardFormat(CFSTR_PREFERREDDROPEFFECT);
  1991. g_cfPerformedEffect = RegisterClipboardFormat(CFSTR_PERFORMEDDROPEFFECT);
  1992. g_cfTargetCLSID = RegisterClipboardFormat(CFSTR_TARGETCLSID);
  1993. g_cfHIDA = RegisterClipboardFormat(CFSTR_SHELLIDLIST);
  1994. g_cfFileDescW = RegisterClipboardFormat(CFSTR_FILEDESCRIPTORW);
  1995. }
  1996. }
  1997. // FEATURE [raymondc] use SHGlobalCounter
  1998. // We need to use a cross process browser count.
  1999. // We use a named semaphore.
  2000. //
  2001. EXTERN_C HANDLE g_hSemBrowserCount = NULL;
  2002. #define SESSION_COUNT_SEMAPHORE_NAME _T("_ie_sessioncount")
  2003. HANDLE GetSessionCountSemaphoreHandle()
  2004. {
  2005. if (!g_hSemBrowserCount)
  2006. {
  2007. g_hSemBrowserCount = SHGlobalCounterCreateNamed( SESSION_COUNT_SEMAPHORE_NAME, 0 );
  2008. }
  2009. ASSERT( g_hSemBrowserCount );
  2010. return g_hSemBrowserCount;
  2011. }
  2012. LONG GetSessionCount()
  2013. {
  2014. LONG lPrevCount = 0x7FFFFFFF;
  2015. HANDLE hSem = GetSessionCountSemaphoreHandle();
  2016. ASSERT(hSem);
  2017. if (hSem)
  2018. {
  2019. ReleaseSemaphore(hSem, 1, &lPrevCount);
  2020. WaitForSingleObject(hSem, 0);
  2021. }
  2022. return lPrevCount;
  2023. }
  2024. LONG IncrementSessionCount()
  2025. {
  2026. LONG lPrevCount = 0x7FFFFFFF;
  2027. HANDLE hSem = GetSessionCountSemaphoreHandle();
  2028. ASSERT(hSem);
  2029. if (hSem)
  2030. {
  2031. ReleaseSemaphore(hSem, 1, &lPrevCount);
  2032. }
  2033. return lPrevCount;
  2034. }
  2035. LONG DecrementSessionCount()
  2036. {
  2037. LONG lPrevCount = 0x7FFFFFFF;
  2038. HANDLE hSem = GetSessionCountSemaphoreHandle();
  2039. ASSERT(hSem);
  2040. if (hSem)
  2041. {
  2042. ReleaseSemaphore(hSem, 1, &lPrevCount); // increment first to make sure deadlock
  2043. // never occurs
  2044. ASSERT(lPrevCount > 0);
  2045. if (lPrevCount > 0)
  2046. {
  2047. WaitForSingleObject(hSem, 0);
  2048. WaitForSingleObject(hSem, 0);
  2049. lPrevCount--;
  2050. }
  2051. else
  2052. {
  2053. // Oops - Looks like a bug !
  2054. // Just return it back to normal and leave
  2055. WaitForSingleObject(hSem, 0);
  2056. }
  2057. }
  2058. return lPrevCount;
  2059. }
  2060. //
  2061. // The following is the message that autodial monitors expect to receive
  2062. // when it's a good time to hang up
  2063. //
  2064. #define WM_IEXPLORER_EXITING (WM_USER + 103)
  2065. long SetQueryNetSessionCount(enum SessionOp Op)
  2066. {
  2067. long lCount = 0;
  2068. switch(Op) {
  2069. case SESSION_QUERY:
  2070. lCount = GetSessionCount();
  2071. TraceMsg(DM_SESSIONCOUNT, "SetQueryNetSessionCount SessionCount=%d (query)", lCount);
  2072. break;
  2073. case SESSION_INCREMENT_NODEFAULTBROWSERCHECK:
  2074. case SESSION_INCREMENT:
  2075. lCount = IncrementSessionCount();
  2076. TraceMsg(DM_SESSIONCOUNT, "SetQueryNetSessionCount SessionCount=%d (incr)", lCount);
  2077. if ((PLATFORM_INTEGRATED == WhichPlatform()))
  2078. {
  2079. // Weird name here... But in integrated mode we make every new browser window
  2080. // look like a new session wrt how we use the cache. Basically this is the way things appear to the
  2081. // user. This effects the way we look for new pages vs doing an if modified
  2082. // since. The ie3/ie4 switch says "look for new pages on each session start"
  2083. // but wininet folks implemented this as a end session name. Woops.
  2084. // Note that things like authentication etc aren't reset by this, but rather
  2085. // only when all browsers are closed via the INTERNET_OPTION_END_BROWSER_SESSION option.
  2086. InternetSetOption(NULL, INTERNET_OPTION_RESET_URLCACHE_SESSION, NULL, 0);
  2087. }
  2088. if (!lCount && (Op == SESSION_INCREMENT))
  2089. {
  2090. // this forces a reload of the title
  2091. DetectAndFixAssociations();
  2092. }
  2093. break;
  2094. case SESSION_DECREMENT:
  2095. lCount = DecrementSessionCount();
  2096. TraceMsg(DM_SESSIONCOUNT, "SetQueryNetSessionCount SessionCount=%d (decr)", lCount);
  2097. if (!lCount) {
  2098. // if we've closed all the net browsers, we need to flush the cache
  2099. InternetSetOption(NULL, INTERNET_OPTION_END_BROWSER_SESSION, NULL, 0);
  2100. InternetSetOption(NULL, INTERNET_OPTION_RESET_URLCACHE_SESSION, NULL, 0);
  2101. // flush the Java VM cache too (if the Java VM is loaded in this process
  2102. // and we're in integrated mode)
  2103. if (WhichPlatform() == PLATFORM_INTEGRATED)
  2104. {
  2105. HMODULE hmod = GetModuleHandle(TEXT("msjava.dll"));
  2106. if (hmod)
  2107. {
  2108. typedef HRESULT (*PFNNOTIFYBROWSERSHUTDOWN)(void *);
  2109. FARPROC fp = GetProcAddress(hmod, "NotifyBrowserShutdown");
  2110. if (fp)
  2111. {
  2112. HRESULT hr = ((PFNNOTIFYBROWSERSHUTDOWN)fp)(NULL);
  2113. ASSERT(SUCCEEDED(hr));
  2114. }
  2115. }
  2116. }
  2117. // Inform dial monitor that it's a good time to hang up
  2118. HWND hwndMonitorWnd = FindWindow(TEXT("MS_AutodialMonitor"),NULL);
  2119. if (hwndMonitorWnd) {
  2120. PostMessage(hwndMonitorWnd,WM_IEXPLORER_EXITING,0,0);
  2121. }
  2122. hwndMonitorWnd = FindWindow(TEXT("MS_WebcheckMonitor"),NULL);
  2123. if (hwndMonitorWnd) {
  2124. PostMessage(hwndMonitorWnd,WM_IEXPLORER_EXITING,0,0);
  2125. }
  2126. // reset offline mode on all platforms except Win2K.
  2127. OSVERSIONINFOA vi;
  2128. vi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOA);
  2129. GetVersionExA(&vi);
  2130. if ( vi.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS ||
  2131. vi.dwMajorVersion < 5)
  2132. {
  2133. // wininet is loaded - tell it to go online
  2134. INTERNET_CONNECTED_INFO ci = {0};
  2135. ci.dwConnectedState = INTERNET_STATE_CONNECTED;
  2136. InternetSetOption(NULL, INTERNET_OPTION_CONNECTED_STATE, &ci, sizeof(ci));
  2137. }
  2138. }
  2139. break;
  2140. }
  2141. return lCount;
  2142. }
  2143. #ifdef DEBUG
  2144. //---------------------------------------------------------------------------
  2145. // Copy the exception info so we can get debug info for Raised exceptions
  2146. // which don't go through the debugger.
  2147. void _CopyExceptionInfo(LPEXCEPTION_POINTERS pep)
  2148. {
  2149. PEXCEPTION_RECORD per;
  2150. per = pep->ExceptionRecord;
  2151. TraceMsg(DM_ERROR, "Exception %x at %#08x.", per->ExceptionCode, per->ExceptionAddress);
  2152. if (per->ExceptionCode == EXCEPTION_ACCESS_VIOLATION)
  2153. {
  2154. // If the first param is 1 then this was a write.
  2155. // If the first param is 0 then this was a read.
  2156. if (per->ExceptionInformation[0])
  2157. {
  2158. TraceMsg(DM_ERROR, "Invalid write to %#08x.", per->ExceptionInformation[1]);
  2159. }
  2160. else
  2161. {
  2162. TraceMsg(DM_ERROR, "Invalid read of %#08x.", per->ExceptionInformation[1]);
  2163. }
  2164. }
  2165. }
  2166. #else
  2167. #define _CopyExceptionInfo(x) TRUE
  2168. #endif
  2169. int WELCallback(void * p, void * pData)
  2170. {
  2171. STATURL* pstat = (STATURL*)p;
  2172. if (pstat->pwcsUrl) {
  2173. OleFree(pstat->pwcsUrl);
  2174. }
  2175. return 1;
  2176. }
  2177. int CALLBACK WELCompare(void * p1, void * p2, LPARAM lParam)
  2178. {
  2179. HDSA hdsa = (HDSA)lParam;
  2180. // Sundown: coercion to long because parameter is an index
  2181. STATURL* pstat1 = (STATURL*)DSA_GetItemPtr(hdsa, PtrToLong(p1));
  2182. STATURL* pstat2 = (STATURL*)DSA_GetItemPtr(hdsa, PtrToLong(p2));
  2183. if (pstat1 && pstat2) {
  2184. return CompareFileTime(&pstat2->ftLastVisited, &pstat1->ftLastVisited);
  2185. }
  2186. ASSERT(0);
  2187. return 0;
  2188. }
  2189. #define MACRO_STR(x) #x
  2190. #define VERSION_HEADER_STR "Microsoft Internet Explorer 5.0 Error Log -- " \
  2191. MACRO_STR(VER_MAJOR_PRODUCTVER) "." \
  2192. MACRO_STR(VER_MINOR_PRODUCTVER) "." \
  2193. MACRO_STR(VER_PRODUCTBUILD) "." \
  2194. MACRO_STR(VER_PRODUCTBUILD_QFE) "\r\n"
  2195. SHDOCAPI_(void) IEWriteErrorLog(const EXCEPTION_RECORD* pexr)
  2196. {
  2197. HANDLE hfile = INVALID_HANDLE_VALUE;
  2198. _try
  2199. {
  2200. TCHAR szWindows[MAX_PATH];
  2201. GetWindowsDirectory(szWindows, ARRAYSIZE(szWindows));
  2202. PathAppend(szWindows, TEXT("IE4 Error Log.txt"));
  2203. HANDLE hfile = CreateFile(szWindows, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
  2204. if (hfile != INVALID_HANDLE_VALUE)
  2205. {
  2206. const static CHAR c_szCRLF[] = "\r\n";
  2207. DWORD cbWritten;
  2208. CHAR szBuf[MAX_URL_STRING];
  2209. // Write the title and product version.
  2210. WriteFile(hfile, VERSION_HEADER_STR, lstrlenA(VERSION_HEADER_STR), &cbWritten, NULL);
  2211. // Write the current time.
  2212. SYSTEMTIME st;
  2213. FILETIME ft;
  2214. GetSystemTime(&st);
  2215. SystemTimeToFileTime(&st, &ft);
  2216. SHFormatDateTimeA(&ft, NULL, szBuf, SIZECHARS(szBuf));
  2217. const static CHAR c_szCurrentTime[] = "CurrentTime: ";
  2218. WriteFile(hfile, c_szCurrentTime, SIZEOF(c_szCurrentTime)-1, &cbWritten, NULL);
  2219. WriteFile(hfile, szBuf, lstrlenA(szBuf), &cbWritten, NULL);
  2220. WriteFile(hfile, c_szCRLF, SIZEOF(c_szCRLF)-1, &cbWritten, NULL);
  2221. if (pexr) {
  2222. const static CHAR c_szExcCode[] = "Exception Info: Code=%x Flags=%x Address=%x\r\n";
  2223. const static CHAR c_szExcParam[] = "Exception Param:";
  2224. wnsprintfA(szBuf, ARRAYSIZE(szBuf), c_szExcCode, pexr->ExceptionCode, pexr->ExceptionFlags, pexr->ExceptionAddress);
  2225. WriteFile(hfile, szBuf, lstrlenA(szBuf), &cbWritten, NULL);
  2226. if (pexr->NumberParameters) {
  2227. WriteFile(hfile, c_szExcParam, SIZEOF(c_szExcParam)-1, &cbWritten, NULL);
  2228. for (UINT iParam=0; iParam<pexr->NumberParameters; iParam++) {
  2229. wnsprintfA(szBuf, ARRAYSIZE(szBuf), " %x", pexr->ExceptionInformation[iParam]);
  2230. WriteFile(hfile, szBuf, lstrlenA(szBuf), &cbWritten, NULL);
  2231. }
  2232. }
  2233. WriteFile(hfile, c_szCRLF, SIZEOF(c_szCRLF)-1, &cbWritten, NULL);
  2234. WriteFile(hfile, c_szCRLF, SIZEOF(c_szCRLF)-1, &cbWritten, NULL);
  2235. }
  2236. IUrlHistoryStg* pUrlHistStg;
  2237. HRESULT hres = CoCreateInstance(CLSID_CUrlHistory, NULL, CLSCTX_INPROC_SERVER,
  2238. IID_PPV_ARG(IUrlHistoryStg, &pUrlHistStg));
  2239. if (SUCCEEDED(hres))
  2240. {
  2241. IEnumSTATURL* penum;
  2242. hres = pUrlHistStg->EnumUrls(&penum);
  2243. if (SUCCEEDED(hres))
  2244. {
  2245. // Allocate DSA for an array of STATURL
  2246. HDSA hdsa = DSA_Create(SIZEOF(STATURL), 32);
  2247. if (hdsa)
  2248. {
  2249. // Allocate DPA for sorting
  2250. HDPA hdpa = DPA_Create(32);
  2251. if (hdpa)
  2252. {
  2253. STATURL stat;
  2254. stat.cbSize = SIZEOF(stat.cbSize);
  2255. while(penum->Next(1, &stat, NULL)==S_OK && stat.pwcsUrl)
  2256. {
  2257. DSA_AppendItem(hdsa, &stat);
  2258. DPA_AppendPtr(hdpa, IntToPtr(DSA_GetItemCount(hdsa)-1));
  2259. }
  2260. DPA_Sort(hdpa, WELCompare, (LPARAM)hdsa);
  2261. for (int i=0; i<10 && i<DPA_GetPtrCount(hdpa) ; i++)
  2262. {
  2263. // Sundown: typecast to long is OK
  2264. STATURL* pstat = (STATURL*)DSA_GetItemPtr(hdsa, PtrToLong(DPA_GetPtr(hdpa, i)));
  2265. if (pstat && pstat->pwcsUrl)
  2266. {
  2267. SHFormatDateTimeA(&pstat->ftLastVisited, NULL, szBuf, SIZECHARS(szBuf));
  2268. WriteFile(hfile, szBuf, lstrlenA(szBuf), &cbWritten, NULL);
  2269. const static TCHAR c_szColumn[] = TEXT(" -- ");
  2270. WriteFile(hfile, c_szColumn, SIZEOF(c_szColumn)-1, &cbWritten, NULL);
  2271. WideCharToMultiByte(CP_ACP, 0, pstat->pwcsUrl, -1,
  2272. szBuf, ARRAYSIZE(szBuf), NULL, NULL);
  2273. WriteFile(hfile, szBuf, lstrlenA(szBuf), &cbWritten, NULL);
  2274. WriteFile(hfile, c_szCRLF, SIZEOF(c_szCRLF)-1, &cbWritten, NULL);
  2275. }
  2276. else
  2277. {
  2278. ASSERT(0);
  2279. }
  2280. }
  2281. DPA_Destroy(hdpa);
  2282. hdpa = NULL;
  2283. }
  2284. DSA_DestroyCallback(hdsa, WELCallback, NULL);
  2285. hdsa = NULL;
  2286. }
  2287. penum->Release();
  2288. }
  2289. else
  2290. {
  2291. ASSERT(0);
  2292. }
  2293. pUrlHistStg->Release();
  2294. }
  2295. else
  2296. {
  2297. ASSERT(0);
  2298. }
  2299. CloseHandle( hfile );
  2300. hfile = INVALID_HANDLE_VALUE;
  2301. }
  2302. }
  2303. _except((SetErrorMode(SEM_NOGPFAULTERRORBOX),
  2304. _CopyExceptionInfo(GetExceptionInformation()),
  2305. UnhandledExceptionFilter(GetExceptionInformation())
  2306. ))
  2307. {
  2308. // We hit an exception while handling an exception.
  2309. // Do nothing; we have already displayed the error dialog box.
  2310. if (hfile != INVALID_HANDLE_VALUE) {
  2311. CloseHandle(hfile);
  2312. }
  2313. }
  2314. __endexcept
  2315. }
  2316. IStream* SHGetViewStream(LPCITEMIDLIST pidl, DWORD grfMode, LPCTSTR pszName, LPCTSTR pszStreamMRU, LPCTSTR pszStreams)
  2317. {
  2318. IStream *pstm = NULL;
  2319. static DWORD s_dwMRUSize = 0;
  2320. DWORD dwSize = sizeof(s_dwMRUSize);
  2321. if ((0 == s_dwMRUSize) &&
  2322. (ERROR_SUCCESS != SHGetValue(HKEY_CURRENT_USER, pszStreamMRU, TEXT("MRU Size"), NULL, (void *) &s_dwMRUSize, &dwSize)))
  2323. {
  2324. s_dwMRUSize = 200; // The default.
  2325. }
  2326. ASSERT(pidl);
  2327. // should be checked by caller - if this is not true we'll flush the
  2328. // MRU cache with internet pidls! FTP and other URL Shell Extension PIDLs
  2329. // that act like a folder and need similar persistence and fine. This
  2330. // is especially true because recently the cache size was increased from
  2331. // 30 or so to 200.
  2332. ASSERT(ILIsEqual(pidl, c_pidlURLRoot) || !IsBrowserFrameOptionsPidlSet(pidl, BFO_BROWSER_PERSIST_SETTINGS));
  2333. // Now lets try to save away the other information associated with view.
  2334. IMruDataList *pmru;
  2335. if (SUCCEEDED(SHCoCreateInstance(NULL, &CLSID_MruLongList, NULL, IID_PPV_ARG(IMruDataList, &pmru))))
  2336. {
  2337. if (SUCCEEDED(pmru->InitData(s_dwMRUSize, MRULISTF_USE_ILISEQUAL, HKEY_CURRENT_USER, pszStreamMRU, NULL)))
  2338. {
  2339. DWORD cbPidl = ILGetSize(pidl);
  2340. // need to walk the list
  2341. // and find this guy
  2342. int iIndex;
  2343. BOOL fFoundPidl = SUCCEEDED(pmru->FindData((const BYTE *)pidl, cbPidl, &iIndex));
  2344. // Did we find the item?
  2345. if (!fFoundPidl && ((grfMode & (STGM_READ|STGM_WRITE|STGM_READWRITE)) == STGM_READ))
  2346. {
  2347. // Do not create the stream if it does not exist and we are
  2348. // only reading
  2349. }
  2350. else
  2351. {
  2352. // Note that we always create the key here, since we have
  2353. // already checked whether we are just reading and the MRU
  2354. // thing does not exist
  2355. HKEY hkCabStreams = SHGetShellKey(SHELLKEY_HKCU_EXPLORER, pszStreams, TRUE);
  2356. if (hkCabStreams )
  2357. {
  2358. DWORD dwSlot;
  2359. if (SUCCEEDED(pmru->AddData((const BYTE *)pidl, cbPidl, &dwSlot)))
  2360. {
  2361. HKEY hkValues;
  2362. TCHAR szValue[32], szSubVal[64];
  2363. wnsprintf(szValue, ARRAYSIZE(szValue), TEXT("%d"), dwSlot);
  2364. if (!fFoundPidl && RegOpenKey(hkCabStreams, szValue, &hkValues) == ERROR_SUCCESS)
  2365. {
  2366. // This means that we have created a new MRU
  2367. // item for this PIDL, so clear out any
  2368. // information residing at this slot
  2369. // Note that we do not just delete the key,
  2370. // since that could fail if it has any sub-keys
  2371. DWORD dwType, dwSize = ARRAYSIZE(szSubVal);
  2372. while (RegEnumValue(hkValues, 0, szSubVal, &dwSize, NULL, &dwType, NULL, NULL) == ERROR_SUCCESS)
  2373. {
  2374. if (RegDeleteValue(hkValues, szSubVal) != ERROR_SUCCESS)
  2375. {
  2376. break;
  2377. }
  2378. }
  2379. RegCloseKey(hkValues);
  2380. }
  2381. pstm = OpenRegStream(hkCabStreams, szValue, pszName, grfMode);
  2382. }
  2383. RegCloseKey(hkCabStreams);
  2384. }
  2385. }
  2386. }
  2387. pmru->Release();
  2388. }
  2389. return pstm;
  2390. }
  2391. #define c_szExploreClass TEXT("ExploreWClass")
  2392. #define c_szIExploreClass TEXT("IEFrame")
  2393. #ifdef IE3CLASSNAME
  2394. #define c_szCabinetClass TEXT("IEFrame")
  2395. #else
  2396. #define c_szCabinetClass TEXT("CabinetWClass")
  2397. #endif
  2398. BOOL IsNamedWindow(HWND hwnd, LPCTSTR pszClass)
  2399. {
  2400. TCHAR szClass[32];
  2401. GetClassName(hwnd, szClass, ARRAYSIZE(szClass));
  2402. return StrCmp(szClass, pszClass) == 0;
  2403. }
  2404. BOOL IsExplorerWindow(HWND hwnd)
  2405. {
  2406. return IsNamedWindow(hwnd, c_szExploreClass);
  2407. }
  2408. BOOL IsFolderWindow(HWND hwnd)
  2409. {
  2410. TCHAR szClass[32];
  2411. GetClassName(hwnd, szClass, ARRAYSIZE(szClass));
  2412. return (StrCmp(szClass, c_szCabinetClass) == 0) || (StrCmp(szClass, c_szIExploreClass) == 0);
  2413. }
  2414. HRESULT _SendOrPostDispatchMessage(HWND hwnd, WPARAM wParam, LPARAM lParam, BOOL fPostMessage, BOOL fCheckFirst)
  2415. {
  2416. HRESULT hr = HRESULT_FROM_WIN32(ERROR_BUSY);
  2417. DWORD idProcess;
  2418. // in case of wParam = DSID_NAVIGATEIEBROWSER, lParam is LocalAlloced structure
  2419. // so we better make sure we are in process 'coz otherwise will fault
  2420. GetWindowThreadProcessId(hwnd, &idProcess);
  2421. if (idProcess == GetCurrentProcessId() && IsWindowEnabled(hwnd) && IsWindowVisible(hwnd))
  2422. {
  2423. if (!fPostMessage || fCheckFirst)
  2424. {
  2425. // sync or we are querying the windows readiness
  2426. ULONG_PTR result;
  2427. if (SendMessageTimeoutA(hwnd, WMC_DISPATCH, (fCheckFirst ? DSID_NOACTION : wParam),
  2428. lParam, SMTO_ABORTIFHUNG, 400, &result))
  2429. hr = (HRESULT) result;
  2430. }
  2431. // handle the post only if the window was ready
  2432. if (fPostMessage && (!fCheckFirst || SUCCEEDED(hr)))
  2433. hr = (PostMessage(hwnd, WMC_DISPATCH, wParam, lParam) ? S_OK : E_FAIL);
  2434. }
  2435. return hr;
  2436. }
  2437. //---------------------------------------------------------------------------
  2438. HRESULT FindBrowserWindowOfClass(LPCTSTR pszClass, WPARAM wParam, LPARAM lParam, BOOL fPostMessage, HWND* phwnd)
  2439. {
  2440. //If there is no window, assume the user is in the process of shutting down IE, and return E_FAIL
  2441. //Otherwise, if there is at least one window, start cycling through the windows until you find
  2442. //one that's not busy, and give it our message. If all are busy, return
  2443. //HRESULT_FROM_WIN32(ERROR_BUSY)
  2444. HWND hwnd = NULL;
  2445. HRESULT hr = E_FAIL;
  2446. while (FAILED(hr)
  2447. && (hwnd = FindWindowEx(NULL, hwnd, pszClass, NULL)) != NULL)
  2448. {
  2449. hr = _SendOrPostDispatchMessage(hwnd, wParam, lParam, fPostMessage, fPostMessage);
  2450. }
  2451. *phwnd = hwnd;
  2452. return hr;
  2453. }
  2454. //This common function gets called when the DDE engine doesn't seem to care in which window something
  2455. //happens. It returns in which window that something happened. 0 means all windows are busy.
  2456. //
  2457. //phwnd: a pointer the hwnd to which to send the message. <= 0 means any window will do.
  2458. // this is also an out parameter that specifies in which window it happened.
  2459. //fPostMessage: when doing navigations, we have to do a PostMessage instead of a SendMessageTimeout
  2460. // or a CoCreateInstance later on in CDocObjectHost::_BindFileMoniker will fail. So when
  2461. // this function is called from CDDEAuto_Navigate, we make this flag TRUE
  2462. HRESULT CDDEAuto_Common(WPARAM wParam, LPARAM lParam, HWND *phwnd, BOOL fPostMessage)
  2463. {
  2464. HRESULT hr = HRESULT_FROM_WIN32(ERROR_BUSY);
  2465. HWND hwnd;
  2466. //if we're told to go to a specific window
  2467. if (phwnd && (*phwnd != (HWND)-1))
  2468. {
  2469. hr = _SendOrPostDispatchMessage(*phwnd, wParam, lParam, fPostMessage, FALSE);
  2470. }
  2471. if (HRESULT_FROM_WIN32(ERROR_BUSY) == hr)
  2472. {
  2473. hr = FindBrowserWindowOfClass(c_szIExploreClass, wParam, lParam, fPostMessage, &hwnd);
  2474. if (!hwnd)
  2475. hr = FindBrowserWindowOfClass(c_szCabinetClass, wParam, lParam, fPostMessage, &hwnd);
  2476. if (phwnd)
  2477. *phwnd = hwnd;
  2478. }
  2479. return hr;
  2480. }
  2481. //
  2482. // Before changing the behavior of this function look at itemmenu.cpp in
  2483. // cdfview.
  2484. //
  2485. HRESULT CDDEAuto_Navigate(BSTR str, HWND *phwnd, long lLaunchNewWindow) // the long used to be for lTransID, but it was always ignored...
  2486. { // so I am using it to tell us if we want to absolutely create an new window or not...
  2487. DDENAVIGATESTRUCT *pddens = NULL;
  2488. HRESULT hres = E_FAIL;
  2489. if (phwnd == NULL)
  2490. return E_INVALIDARG;
  2491. pddens = new DDENAVIGATESTRUCT;
  2492. if (!pddens)
  2493. hres = E_OUTOFMEMORY;
  2494. else
  2495. {
  2496. pddens->wszUrl = StrDupW(str);
  2497. if (!pddens->wszUrl)
  2498. {
  2499. hres = E_OUTOFMEMORY;
  2500. }
  2501. else
  2502. {
  2503. // Don't do the navigate if *phwnd == 0, in that case we want to either
  2504. // create a new window or activate an existing one that already is viewing
  2505. // this URL.
  2506. if ((*phwnd != NULL) && !lLaunchNewWindow)
  2507. {
  2508. BOOL fForceWindowReuse = FALSE;
  2509. BSTR bstrUrl = NULL;
  2510. // If there is even a single window with a location
  2511. // you are basically assured that you cannot force a
  2512. // reuse of windows. essentially
  2513. // case 1 : only iexplore -nohome windows implies we want to force reuse
  2514. // case 2 : only windows that have a location - we don't want to force reuse
  2515. // just follow user's preference
  2516. // case 3: mix of iexplore -nohome windows and windows with location. we don't
  2517. // know what state we are in - don't force reuse
  2518. hres = CDDEAuto_get_LocationURL(&bstrUrl, *phwnd);
  2519. if (FAILED(hres) ||
  2520. (!bstrUrl) ||
  2521. (SUCCEEDED(hres) && (*bstrUrl == L'\0')))
  2522. {
  2523. fForceWindowReuse = TRUE;
  2524. }
  2525. if (bstrUrl)
  2526. SysFreeString(bstrUrl);
  2527. if ( !(GetAsyncKeyState(VK_SHIFT) < 0)
  2528. && (fForceWindowReuse || SHRegGetBoolUSValue(REGSTR_PATH_MAIN, TEXT("AllowWindowReuse"), FALSE, TRUE)))
  2529. {
  2530. hres = CDDEAuto_Common(DSID_NAVIGATEIEBROWSER, (LPARAM)pddens, phwnd, FALSE);
  2531. }
  2532. }
  2533. if (SUCCEEDED(hres) && (*phwnd != 0) && (*phwnd != (HWND)-1))
  2534. {
  2535. // We found an existing browser window and successfully sent the
  2536. // navigate message to it. Make the window foreground.
  2537. SetForegroundWindow(*phwnd);
  2538. if (IsIconic(*phwnd))
  2539. ShowWindowAsync(*phwnd, SW_RESTORE);
  2540. }
  2541. //
  2542. // If we are using whatever window and all the browser windows are busy
  2543. // (*phwnd == 0), or if there's no browser window opened (*phwnd == -1)
  2544. // or we are asked to create a new one, then take the official OLE automation
  2545. // route to start a new window.
  2546. //
  2547. if ((*phwnd == 0) ||
  2548. (*phwnd == (HWND)-1))
  2549. {
  2550. //WARNING: this route doesn't give us the ability to return the hwnd of the window
  2551. //in which the navigation took place (while we could - it's too hard and not worth it)
  2552. LPITEMIDLIST pidlNew;
  2553. hres = IECreateFromPathW(str, &pidlNew);
  2554. if (SUCCEEDED(hres))
  2555. {
  2556. if (!lLaunchNewWindow)
  2557. {
  2558. // See if there is already a browser viewing this URL, if so just
  2559. // make him foreground otherwise create a new browser.
  2560. hres = WinList_FindFolderWindow(pidlNew, NULL, phwnd, NULL);
  2561. }
  2562. else
  2563. {
  2564. // we don't look in the winlist if the caller explicitly wants a new window
  2565. hres = S_FALSE;
  2566. }
  2567. if (S_OK == hres)
  2568. {
  2569. ILFree(pidlNew);
  2570. SetForegroundWindow(*phwnd);
  2571. ShowWindow(*phwnd, SW_SHOWNORMAL);
  2572. }
  2573. else
  2574. {
  2575. SHOpenNewFrame(pidlNew, NULL, 0, COF_IEXPLORE);
  2576. }
  2577. }
  2578. }
  2579. }
  2580. // It will be set to NULL if we don't need to free it.
  2581. if (pddens)
  2582. {
  2583. if (pddens->wszUrl)
  2584. {
  2585. LocalFree(pddens->wszUrl);
  2586. pddens->wszUrl = NULL;
  2587. }
  2588. delete pddens;
  2589. }
  2590. }
  2591. return hres;
  2592. }
  2593. HRESULT CDDEAuto_get_LocationURL(BSTR * pstr, HWND hwnd)
  2594. {
  2595. return CDDEAuto_Common(DSID_GETLOCATIONURL, (LPARAM)pstr, &hwnd, FALSE);
  2596. }
  2597. HRESULT CDDEAuto_get_LocationTitle(BSTR * pstr, HWND hwnd)
  2598. {
  2599. return CDDEAuto_Common(DSID_GETLOCATIONTITLE, (LPARAM)pstr, &hwnd, FALSE);
  2600. }
  2601. HRESULT CDDEAuto_get_HWND(long * phwnd)
  2602. {
  2603. return CDDEAuto_Common(DSID_GETHWND, (LPARAM)phwnd, NULL, FALSE);
  2604. }
  2605. HRESULT CDDEAuto_Exit()
  2606. {
  2607. return CDDEAuto_Common(DSID_EXIT, (LPARAM)NULL, NULL, FALSE);
  2608. }
  2609. class CDelagateMalloc : public IMalloc
  2610. {
  2611. public:
  2612. // IUnknown
  2613. virtual STDMETHODIMP QueryInterface(REFIID,void **);
  2614. virtual STDMETHODIMP_(ULONG) AddRef(void);
  2615. virtual STDMETHODIMP_(ULONG) Release(void);
  2616. // IMalloc
  2617. virtual STDMETHODIMP_(void *) Alloc(SIZE_T cb);
  2618. virtual STDMETHODIMP_(void *) Realloc(void *pv, SIZE_T cb);
  2619. virtual STDMETHODIMP_(void) Free(void *pv);
  2620. virtual STDMETHODIMP_(SIZE_T) GetSize(void *pv);
  2621. virtual STDMETHODIMP_(int) DidAlloc(void *pv);
  2622. virtual STDMETHODIMP_(void) HeapMinimize();
  2623. private:
  2624. CDelagateMalloc(void *pv, SIZE_T cbSize, WORD wOuter);
  2625. ~CDelagateMalloc() {}
  2626. void* operator new(size_t cbClass, SIZE_T cbSize)
  2627. {
  2628. return ::operator new(cbClass + cbSize);
  2629. }
  2630. friend HRESULT CDelegateMalloc_Create(void *pv, SIZE_T cbSize, WORD wOuter, IMalloc **ppmalloc);
  2631. protected:
  2632. LONG _cRef;
  2633. WORD _wOuter; // delegate item outer signature
  2634. WORD _wUnused; // to allign
  2635. #ifdef DEBUG
  2636. UINT _cAllocs;
  2637. #endif
  2638. SIZE_T _cb;
  2639. BYTE _data[EMPTY_SIZE];
  2640. };
  2641. CDelagateMalloc::CDelagateMalloc(void *pv, SIZE_T cbSize, WORD wOuter)
  2642. {
  2643. _cRef = 1;
  2644. _wOuter = wOuter;
  2645. _cb = cbSize;
  2646. memcpy(_data, pv, _cb);
  2647. }
  2648. HRESULT CDelagateMalloc::QueryInterface(REFIID riid, void **ppvObj)
  2649. {
  2650. static const QITAB qit[] = {
  2651. QITABENT(CDelagateMalloc, IMalloc),
  2652. { 0 },
  2653. };
  2654. return QISearch(this, qit, riid, ppvObj);
  2655. }
  2656. ULONG CDelagateMalloc::AddRef()
  2657. {
  2658. return InterlockedIncrement(&_cRef);
  2659. }
  2660. ULONG CDelagateMalloc::Release()
  2661. {
  2662. ASSERT( 0 != _cRef );
  2663. ULONG cRef = InterlockedDecrement(&_cRef);
  2664. if ( 0 == cRef )
  2665. {
  2666. delete this;
  2667. }
  2668. return cRef;
  2669. }
  2670. void *CDelagateMalloc::Alloc(SIZE_T cb)
  2671. {
  2672. WORD cbActualSize = (WORD)(
  2673. SIZEOF(DELEGATEITEMID) - 1 + // header (-1 sizeof(rgb[0])
  2674. cb + // inner
  2675. _cb); // outer data
  2676. PDELEGATEITEMID pidl = (PDELEGATEITEMID)SHAlloc(cbActualSize + 2); // +2 for pidl term
  2677. if (pidl)
  2678. {
  2679. pidl->cbSize = cbActualSize;
  2680. pidl->wOuter = _wOuter;
  2681. pidl->cbInner = (WORD)cb;
  2682. memcpy(&pidl->rgb[cb], _data, _cb);
  2683. *(UNALIGNED WORD *)&(((BYTE *)pidl)[cbActualSize]) = 0;
  2684. #ifdef DEBUG
  2685. _cAllocs++;
  2686. #endif
  2687. }
  2688. return pidl;
  2689. }
  2690. void *CDelagateMalloc::Realloc(void *pv, SIZE_T cb)
  2691. {
  2692. return NULL;
  2693. }
  2694. void CDelagateMalloc::Free(void *pv)
  2695. {
  2696. SHFree(pv);
  2697. }
  2698. SIZE_T CDelagateMalloc::GetSize(void *pv)
  2699. {
  2700. return (SIZE_T)-1;
  2701. }
  2702. int CDelagateMalloc::DidAlloc(void *pv)
  2703. {
  2704. return -1;
  2705. }
  2706. void CDelagateMalloc::HeapMinimize()
  2707. {
  2708. }
  2709. STDAPI CDelegateMalloc_Create(void *pv, SIZE_T cbSize, WORD wOuter, IMalloc **ppmalloc)
  2710. {
  2711. CDelagateMalloc *pdm = new(cbSize) CDelagateMalloc(pv, cbSize, wOuter);
  2712. if (pdm)
  2713. {
  2714. HRESULT hres = pdm->QueryInterface(IID_PPV_ARG(IMalloc, ppmalloc));
  2715. pdm->Release();
  2716. return hres;
  2717. }
  2718. return E_OUTOFMEMORY;
  2719. }
  2720. //+-------------------------------------------------------------------------
  2721. // This function scans the head of an html document for the desired element
  2722. // with a particular attribute. If a match is found, the first occurance
  2723. // of that element is returned in punkDesired and S_OK is returned.
  2724. // Otherwise, E_FAIL is returned.
  2725. //
  2726. // Example: Find the first meta element with name="ProgID":
  2727. //
  2728. // SearchForElementInHead(pHTMLDoc, OLESTR("Name"), OLESTR("ProgId"),
  2729. // IID_IHTMLMetaElement, (IUnknown**)&pMetaElement);
  2730. //
  2731. //--------------------------------------------------------------------------
  2732. HRESULT SearchForElementInHead
  2733. (
  2734. IHTMLDocument2* pHTMLDocument, // [in] document to search
  2735. LPOLESTR pszAttribName, // [in] attribute to check for
  2736. LPOLESTR pszAttrib, // [in] value the attribute must have
  2737. REFIID iidDesired, // [in] element interface to return
  2738. IUnknown** ppunkDesired // [out] returned interface
  2739. )
  2740. {
  2741. ASSERT(NULL != pHTMLDocument);
  2742. ASSERT(NULL != pszAttribName);
  2743. ASSERT(NULL != pszAttrib);
  2744. ASSERT(NULL != ppunkDesired);
  2745. HRESULT hr = E_FAIL;
  2746. *ppunkDesired = NULL;
  2747. BSTR bstrAttribName = SysAllocString(pszAttribName);
  2748. if (NULL == bstrAttribName)
  2749. {
  2750. return E_OUTOFMEMORY;
  2751. }
  2752. //
  2753. // First get all document elements. Note that this is very fast in
  2754. // ie5 because the collection directly accesses the internal tree.
  2755. //
  2756. IHTMLElementCollection * pAllCollection;
  2757. if (SUCCEEDED(pHTMLDocument->get_all(&pAllCollection)))
  2758. {
  2759. IUnknown* punk;
  2760. IHTMLBodyElement* pBodyElement;
  2761. IHTMLFrameSetElement* pFrameSetElement;
  2762. IDispatch* pDispItem;
  2763. //
  2764. // Now we scan the document for the desired tags. Since we're only
  2765. // searching the head, and since Trident always creates a body tag
  2766. // (unless there is a frameset), we can stop looking when we hit the
  2767. // body or frameset.
  2768. //
  2769. // Note, the alternative of using pAllCollection->tags to return the
  2770. // collection of desired tags is likely more expensive because it will
  2771. // walk the whole tree (unless Trident optimizes this).
  2772. //
  2773. long lItemCnt;
  2774. VARIANT vEmpty;
  2775. V_VT(&vEmpty) = VT_EMPTY;
  2776. VARIANT vIndex;
  2777. V_VT(&vIndex) = VT_I4;
  2778. EVAL(SUCCEEDED(pAllCollection->get_length(&lItemCnt)));
  2779. for (long lItem = 0; lItem < lItemCnt; lItem++)
  2780. {
  2781. V_I4(&vIndex) = lItem;
  2782. if (S_OK == pAllCollection->item(vIndex, vEmpty, &pDispItem))
  2783. {
  2784. //
  2785. // First see if it's the desired element type
  2786. //
  2787. if (SUCCEEDED(pDispItem->QueryInterface(iidDesired, (void **)&punk)))
  2788. {
  2789. //
  2790. // Next see if it has the desired attribute
  2791. //
  2792. IHTMLElement* pElement;
  2793. if (SUCCEEDED(pDispItem->QueryInterface(IID_PPV_ARG(IHTMLElement, &pElement))))
  2794. {
  2795. VARIANT varAttrib;
  2796. V_VT(&varAttrib) = VT_EMPTY;
  2797. if (SUCCEEDED(pElement->getAttribute(bstrAttribName, FALSE, &varAttrib)) &&
  2798. (V_VT(&varAttrib) == VT_BSTR) && varAttrib.bstrVal &&
  2799. (StrCmpIW(varAttrib.bstrVal, pszAttrib) == 0) )
  2800. {
  2801. // Found it!
  2802. *ppunkDesired = punk;
  2803. punk = NULL;
  2804. hr = S_OK;
  2805. // Terminate the search;
  2806. lItem = lItemCnt;
  2807. }
  2808. pElement->Release();
  2809. VariantClear(&varAttrib);
  2810. }
  2811. if (punk)
  2812. punk->Release();
  2813. }
  2814. //
  2815. // Next check for the body tag
  2816. //
  2817. else if (SUCCEEDED(pDispItem->QueryInterface(IID_PPV_ARG(IHTMLBodyElement,&pBodyElement))))
  2818. {
  2819. // Found a body tag, so terminate the search
  2820. lItem = lItemCnt;
  2821. pBodyElement->Release();
  2822. }
  2823. //
  2824. // Finally, check for a frameset tag
  2825. //
  2826. else if (SUCCEEDED(pDispItem->QueryInterface(IID_PPV_ARG(IHTMLFrameSetElement, &pFrameSetElement))))
  2827. {
  2828. // Found a frameset tag, so terminate the search
  2829. lItem = lItemCnt;
  2830. pFrameSetElement->Release();
  2831. }
  2832. pDispItem->Release();
  2833. }
  2834. }
  2835. // Make sure that these don't have to be cleared (should not have been modified)
  2836. ASSERT(vEmpty.vt == VT_EMPTY);
  2837. ASSERT(vIndex.vt == VT_I4);
  2838. pAllCollection->Release();
  2839. }
  2840. SysFreeString(bstrAttribName);
  2841. return hr;
  2842. }
  2843. //+-------------------------------------------------------------------
  2844. // JITCoCreateInstance
  2845. //
  2846. // This function makes sure that the Option pack which
  2847. // has this class id is installed.
  2848. // It attempts to make sure that the Option pack corresponding
  2849. // to the current IE Build.
  2850. // If the feature does get installed correctly, it will
  2851. // attempt to CoCreate the specified CLSID
  2852. //
  2853. //+------------------------------------------------------------------
  2854. HRESULT JITCoCreateInstance(REFCLSID rclsid, IUnknown *pUnkOuter, DWORD dwClsContext, REFIID riid, void ** ppv, HWND hwndParent, DWORD dwJitFlags)
  2855. {
  2856. uCLSSPEC ucs;
  2857. QUERYCONTEXT qc = { 0 };
  2858. ucs.tyspec = TYSPEC_CLSID;
  2859. ucs.tagged_union.clsid = rclsid;
  2860. ASSERT((dwJitFlags & ~(FIEF_FLAG_FORCE_JITUI | FIEF_FLAG_PEEK)) == 0);
  2861. HRESULT hr = FaultInIEFeature(hwndParent, &ucs, &qc, dwJitFlags);
  2862. if (SUCCEEDED(hr))
  2863. {
  2864. hr = CoCreateInstance(rclsid, pUnkOuter, dwClsContext, riid, ppv);
  2865. }
  2866. return hr;
  2867. }
  2868. BOOL IsFeaturePotentiallyAvailable(REFCLSID rclsid)
  2869. {
  2870. uCLSSPEC ucs;
  2871. QUERYCONTEXT qc = { 0 };
  2872. ucs.tyspec = TYSPEC_CLSID;
  2873. ucs.tagged_union.clsid = rclsid;
  2874. return (FaultInIEFeature(NULL, &ucs, &qc, FIEF_FLAG_FORCE_JITUI | FIEF_FLAG_PEEK) != E_ACCESSDENIED);
  2875. }
  2876. BOOL CreateFromDesktop(PNEWFOLDERINFO pfi)
  2877. {
  2878. //
  2879. // APPCOMPAT:HACKHACK - we need to handle differences in the way we parse the command line
  2880. // on IE4 integrated. we should not be called by anybody but IE4's Explorer.exe
  2881. //
  2882. ASSERT(GetUIVersion() == 4);
  2883. if (!pfi->pidl)
  2884. {
  2885. if ((pfi->uFlags & (COF_ROOTCLASS | COF_NEWROOT)) || pfi->pidlRoot)
  2886. {
  2887. pfi->pidl = ILRootedCreateIDList(pfi->uFlags & COF_ROOTCLASS ? &pfi->clsid : NULL, pfi->pidlRoot);
  2888. pfi->uFlags &= ~(COF_ROOTCLASS | COF_NEWROOT);
  2889. ILFree(pfi->pidlRoot);
  2890. pfi->pidlRoot = NULL;
  2891. pfi->clsid = CLSID_NULL;
  2892. }
  2893. else if (!PathIsURLA(pfi->pszPath))
  2894. {
  2895. CHAR szTemp[MAX_PATH];
  2896. GetCurrentDirectoryA(ARRAYSIZE(szTemp), szTemp);
  2897. PathCombineA(szTemp, szTemp, pfi->pszPath);
  2898. Str_SetPtrA(&(pfi->pszPath), szTemp);
  2899. }
  2900. }
  2901. ASSERT(!(pfi->uFlags & (COF_ROOTCLASS | COF_NEWROOT)));
  2902. return SHCreateFromDesktop(pfi);
  2903. }
  2904. //*** IsVK_TABCycler -- is key a TAB-equivalent
  2905. // ENTRY/EXIT
  2906. // dir 0 if not a TAB, non-0 if a TAB
  2907. // NOTES
  2908. // NYI: -1 for shift+tab, 1 for tab
  2909. //
  2910. int IsVK_TABCycler(MSG *pMsg)
  2911. {
  2912. if (!pMsg)
  2913. return 0;
  2914. if (pMsg->message != WM_KEYDOWN)
  2915. return 0;
  2916. if (! (pMsg->wParam == VK_TAB || pMsg->wParam == VK_F6))
  2917. return 0;
  2918. return (GetKeyState(VK_SHIFT) < 0) ? -1 : 1;
  2919. }
  2920. // Review chrisny: this can be moved into an object easily to handle generic droptarget, dropcursor
  2921. // , autoscrool, etc. . .
  2922. void _DragEnter(HWND hwndTarget, const POINTL ptStart, IDataObject *pdtObject)
  2923. {
  2924. RECT rc;
  2925. POINT pt;
  2926. GetWindowRect(hwndTarget, &rc);
  2927. if (IS_WINDOW_RTL_MIRRORED(hwndTarget))
  2928. pt.x = rc.right - ptStart.x;
  2929. else
  2930. pt.x = ptStart.x - rc.left;
  2931. pt.y = ptStart.y - rc.top;
  2932. DAD_DragEnterEx2(hwndTarget, pt, pdtObject);
  2933. return;
  2934. }
  2935. void _DragMove(HWND hwndTarget, const POINTL ptStart)
  2936. {
  2937. RECT rc;
  2938. POINT pt;
  2939. GetWindowRect(hwndTarget, &rc);
  2940. if (IS_WINDOW_RTL_MIRRORED(hwndTarget))
  2941. pt.x = rc.right - ptStart.x;
  2942. else
  2943. pt.x = ptStart.x - rc.left;
  2944. pt.y = ptStart.y - rc.top;
  2945. DAD_DragMove(pt);
  2946. return;
  2947. }
  2948. STDAPI_(IBindCtx *) CreateBindCtxForUI(IUnknown * punkSite)
  2949. {
  2950. IBindCtx * pbc = NULL;
  2951. if (EVAL(punkSite && SUCCEEDED(CreateBindCtx(0, &pbc))))
  2952. {
  2953. if (FAILED(pbc->RegisterObjectParam(STR_DISPLAY_UI_DURING_BINDING, punkSite)))
  2954. {
  2955. // It failed
  2956. ATOMICRELEASE(pbc);
  2957. }
  2958. }
  2959. return pbc;
  2960. }
  2961. //
  2962. // Return the location of the internet cache
  2963. // HRESULT GetCacheLocation(
  2964. // dwSize no. of chars in pszCacheLocation
  2965. STDAPI GetCacheLocation(LPTSTR pszCacheLocation, DWORD cchCacheLocation)
  2966. {
  2967. HRESULT hr = S_OK;
  2968. DWORD dwLastErr;
  2969. LPINTERNET_CACHE_CONFIG_INFO lpCCI = NULL; // init to suppress bogus C4701 warning
  2970. DWORD dwCCISize = sizeof(INTERNET_CACHE_CONFIG_INFO);
  2971. BOOL fOnceErrored = FALSE;
  2972. while (TRUE)
  2973. {
  2974. if ((lpCCI = (LPINTERNET_CACHE_CONFIG_INFO) LocalAlloc(LPTR,
  2975. dwCCISize)) == NULL)
  2976. {
  2977. hr = E_OUTOFMEMORY;
  2978. goto cleanup;
  2979. }
  2980. if (!GetUrlCacheConfigInfo(lpCCI, &dwCCISize,
  2981. CACHE_CONFIG_CONTENT_PATHS_FC))
  2982. {
  2983. if ((dwLastErr = GetLastError()) != ERROR_INSUFFICIENT_BUFFER ||
  2984. fOnceErrored)
  2985. {
  2986. hr = HRESULT_FROM_WIN32(dwLastErr);
  2987. goto cleanup;
  2988. }
  2989. //
  2990. // We have insufficient buffer size; reallocate a buffer with the
  2991. // new dwCCISize set by GetUrlCacheConfigInfo
  2992. // Set fOnceErrored to TRUE so that we don't loop indefinitely
  2993. //
  2994. fOnceErrored = TRUE;
  2995. }
  2996. else
  2997. {
  2998. LPTSTR pszPath = lpCCI->CachePaths[0].CachePath;
  2999. INT iLen;
  3000. PathRemoveBackslash(pszPath);
  3001. iLen = lstrlen(pszPath) + 1; // + 1 is for the null char
  3002. if ((DWORD) iLen < cchCacheLocation)
  3003. {
  3004. StrCpyN(pszCacheLocation, pszPath, cchCacheLocation);
  3005. }
  3006. else
  3007. {
  3008. hr = HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER);
  3009. }
  3010. break;
  3011. }
  3012. LocalFree(lpCCI);
  3013. lpCCI = NULL;
  3014. }
  3015. cleanup:
  3016. if (lpCCI != NULL)
  3017. {
  3018. LocalFree(lpCCI);
  3019. lpCCI = NULL;
  3020. }
  3021. return hr;
  3022. }
  3023. STDAPI_(UINT) GetWheelMsg()
  3024. {
  3025. static UINT s_msgMSWheel = 0;
  3026. if (s_msgMSWheel == 0)
  3027. s_msgMSWheel = RegisterWindowMessage(TEXT("MSWHEEL_ROLLMSG"));
  3028. return s_msgMSWheel;
  3029. }
  3030. STDAPI StringToStrRet(LPCTSTR pString, STRRET *pstrret)
  3031. {
  3032. HRESULT hr = SHStrDup(pString, &pstrret->pOleStr);
  3033. if (SUCCEEDED(hr))
  3034. {
  3035. pstrret->uType = STRRET_WSTR;
  3036. }
  3037. return hr;
  3038. }
  3039. // these two functions are duplicated from browseui
  3040. HINSTANCE GetComctl32Hinst()
  3041. {
  3042. static HINSTANCE s_hinst = NULL;
  3043. if (!s_hinst)
  3044. s_hinst = GetModuleHandle(TEXT("comctl32.dll"));
  3045. return s_hinst;
  3046. }
  3047. // since we don't define the proper WINVER we do this ourselves
  3048. #ifndef IDC_HAND
  3049. #define IDC_HAND MAKEINTRESOURCE(32649)
  3050. #endif
  3051. STDAPI_(HCURSOR) LoadHandCursor(DWORD dwRes)
  3052. {
  3053. if (g_bRunOnNT5 || g_bRunOnMemphis)
  3054. {
  3055. HCURSOR hcur = LoadCursor(NULL, IDC_HAND); // from USER, system supplied
  3056. if (hcur)
  3057. return hcur;
  3058. }
  3059. return LoadCursor(GetComctl32Hinst(), IDC_HAND_INTERNAL);
  3060. }
  3061. //+-------------------------------------------------------------------------
  3062. // Returns true if this type of url may not be available when offline unless
  3063. // it is cached by wininet
  3064. //--------------------------------------------------------------------------
  3065. BOOL MayBeUnavailableOffline(LPTSTR pszUrl)
  3066. {
  3067. BOOL fRet = FALSE;
  3068. URL_COMPONENTS uc = {0};
  3069. uc.dwStructSize = sizeof(uc);
  3070. if (SUCCEEDED(InternetCrackUrl(pszUrl, 0, 0, &uc)))
  3071. {
  3072. fRet = uc.nScheme == INTERNET_SCHEME_HTTP ||
  3073. uc.nScheme == INTERNET_SCHEME_HTTPS ||
  3074. uc.nScheme == INTERNET_SCHEME_FTP ||
  3075. uc.nScheme == INTERNET_SCHEME_GOPHER;
  3076. }
  3077. return fRet;
  3078. }
  3079. //+-------------------------------------------------------------------------
  3080. // If the folder is a link, the associated URL is returned.
  3081. //--------------------------------------------------------------------------
  3082. HRESULT GetNavTargetName(IShellFolder* psf, LPCITEMIDLIST pidl, LPTSTR pszUrl, UINT cMaxChars)
  3083. {
  3084. LPITEMIDLIST pidlTarget;
  3085. HRESULT hr = SHGetNavigateTarget(psf, pidl, &pidlTarget, NULL);
  3086. if (SUCCEEDED(hr))
  3087. {
  3088. // Get the URL
  3089. // NOTE (andrewgu): ie5.5 b#109391 - if SHGDN_FORPARSING is used the result will be
  3090. // consitently the fully qualified path regardless of the protocol
  3091. hr = IEGetNameAndFlags(pidlTarget, SHGDN_FORPARSING, pszUrl, cMaxChars, NULL);
  3092. ILFree(pidlTarget);
  3093. }
  3094. else
  3095. *pszUrl = 0;
  3096. return hr;
  3097. }
  3098. //+-------------------------------------------------------------------------
  3099. // Returns info about whether this item is available offline. Returns E_FAIL
  3100. // if the item is not a link.
  3101. // if we navigate to this item
  3102. // (true if we're online, items in the cache or otherwise available)
  3103. // if item is a sticky cache entry
  3104. //--------------------------------------------------------------------------
  3105. // FEATURE: this should use an interface to bind to this information abstractly
  3106. // psf->GetUIObjectOf(IID_IAvailablility, ...);
  3107. HRESULT GetLinkInfo(IShellFolder* psf, LPCITEMIDLIST pidlItem, BOOL* pfAvailable, BOOL* pfSticky)
  3108. {
  3109. if (pfAvailable)
  3110. *pfAvailable = TRUE;
  3111. if (pfSticky)
  3112. *pfSticky = FALSE;
  3113. //
  3114. // See if it is a link. If it is not, then it can't be in the wininet cache and can't
  3115. // be pinned (sticky cache entry) or greyed (unavailable when offline)
  3116. //
  3117. WCHAR szUrl[MAX_URL_STRING];
  3118. DWORD dwFlags = 0;
  3119. HRESULT hr = GetNavTargetName(psf, pidlItem, szUrl, ARRAYSIZE(szUrl));
  3120. if (SUCCEEDED(hr))
  3121. {
  3122. CHAR szUrlAnsi[MAX_URL_STRING];
  3123. //
  3124. // Get the cache info for this item. Note that we use GetUrlCacheEntryInfoEx instead
  3125. // of GetUrlCacheEntryInfo because it follows any redirects that occured. This wacky
  3126. // api uses a variable length buffer, so we have to guess the size and retry if the
  3127. // call fails.
  3128. //
  3129. BOOL fInCache = FALSE;
  3130. WCHAR szBuf[512];
  3131. LPINTERNET_CACHE_ENTRY_INFOA pCE = (LPINTERNET_CACHE_ENTRY_INFOA)szBuf;
  3132. DWORD cbEntry = sizeof (szBuf);
  3133. SHTCharToAnsi(szUrl, szUrlAnsi, ARRAYSIZE(szUrlAnsi));
  3134. if (!(fInCache = GetUrlCacheEntryInfoExA(szUrlAnsi, pCE, &cbEntry, NULL, NULL, NULL, 0)))
  3135. {
  3136. if (GetLastError() == ERROR_INSUFFICIENT_BUFFER)
  3137. {
  3138. // We guessed too small for the buffer so allocate the correct size & retry
  3139. pCE = (LPINTERNET_CACHE_ENTRY_INFOA)LocalAlloc(LPTR, cbEntry);
  3140. if (pCE)
  3141. {
  3142. fInCache = GetUrlCacheEntryInfoExA(szUrlAnsi, pCE, &cbEntry, NULL, NULL, NULL, 0);
  3143. }
  3144. }
  3145. }
  3146. //
  3147. // If we are offline, see if the item is in the cache.
  3148. //
  3149. if (pfAvailable && SHIsGlobalOffline() && MayBeUnavailableOffline(szUrl) && !fInCache)
  3150. {
  3151. // Not available
  3152. *pfAvailable = FALSE;
  3153. }
  3154. //
  3155. // See if it's a sticky cache entry
  3156. //
  3157. if (pCE)
  3158. {
  3159. if (pfSticky && fInCache && (pCE->CacheEntryType & STICKY_CACHE_ENTRY))
  3160. {
  3161. *pfSticky = TRUE;
  3162. }
  3163. if ((TCHAR*)pCE != szBuf)
  3164. {
  3165. LocalFree(pCE);
  3166. pCE = NULL;
  3167. }
  3168. }
  3169. }
  3170. //
  3171. // Somebody is obviously interested in in the offline availability so listen
  3172. // to wininet for changes to the cache and rebroadcast as a SHChangeNotify
  3173. //
  3174. CWinInetNotify::GlobalEnable();
  3175. return hr;
  3176. }
  3177. //
  3178. // Converts all "&" into "&&" so that they show up
  3179. // in menus
  3180. //
  3181. void FixAmpersands(LPWSTR pszToFix, UINT cchMax)
  3182. {
  3183. ASSERT(pszToFix && cchMax > 0);
  3184. WCHAR szBuf[MAX_URL_STRING];
  3185. LPWSTR pszBuf = szBuf;
  3186. LPWSTR pszSrc = pszToFix;
  3187. UINT cch = 0;
  3188. while (*pszSrc && cch < ARRAYSIZE(szBuf)-2)
  3189. {
  3190. if (*pszSrc == '&')
  3191. {
  3192. *pszBuf++ = '&';
  3193. ++cch;
  3194. }
  3195. *pszBuf++ = *pszSrc++;
  3196. ++cch;
  3197. }
  3198. *pszBuf = 0;
  3199. StrCpyN(pszToFix, szBuf, cchMax);
  3200. }
  3201. BOOL IsInetcplRestricted(LPCWSTR pszCommand)
  3202. {
  3203. BOOL fDisabled = FALSE;
  3204. DWORD dwData, dwType;
  3205. DWORD dwSize = sizeof(dwData);
  3206. if (ERROR_SUCCESS == SHRegGetUSValue(TEXT("Software\\Policies\\Microsoft\\Internet Explorer\\Control Panel"),
  3207. pszCommand, &dwType, (void *)&dwData, &dwSize, FALSE, NULL, 0))
  3208. {
  3209. fDisabled = dwData;
  3210. }
  3211. return fDisabled;
  3212. }
  3213. BOOL HasExtendedChar(LPCWSTR pszQuery)
  3214. {
  3215. BOOL fNonAscii = FALSE;
  3216. for (LPCWSTR psz = pszQuery; *psz; psz++)
  3217. {
  3218. if (*psz > 0x7f)
  3219. {
  3220. fNonAscii = TRUE;
  3221. break;
  3222. }
  3223. }
  3224. return fNonAscii;
  3225. }
  3226. void ConvertToUtf8Escaped(LPWSTR pszUrl, int cch)
  3227. {
  3228. // Convert to utf8
  3229. char szBuf[MAX_URL_STRING];
  3230. SHUnicodeToAnsiCP(CP_UTF8, pszUrl, szBuf, ARRAYSIZE(szBuf));
  3231. // Escape the string into the original buffer
  3232. LPSTR pchIn;
  3233. LPWSTR pchOut = pszUrl;
  3234. WCHAR ch;
  3235. static const WCHAR hex[] = L"0123456789ABCDEF";
  3236. for (pchIn = szBuf; *pchIn && cch > 3; pchIn++)
  3237. {
  3238. ch = *pchIn;
  3239. if (ch > 0x7f)
  3240. {
  3241. cch -= 3;
  3242. *pchOut++ = L'%';
  3243. *pchOut++ = hex[(ch >> 4) & 15];
  3244. *pchOut++ = hex[ch & 15];
  3245. }
  3246. else
  3247. {
  3248. --cch;
  3249. *pchOut++ = *pchIn;
  3250. }
  3251. }
  3252. *pchOut = L'\0';
  3253. }
  3254. HRESULT IExtractIcon_GetIconLocation(
  3255. IUnknown *punk,
  3256. IN UINT uInFlags,
  3257. OUT LPTSTR pszIconFile,
  3258. IN UINT cchIconFile,
  3259. OUT PINT pniIcon,
  3260. OUT PUINT puOutFlags)
  3261. {
  3262. ASSERT(punk);
  3263. HRESULT hr;
  3264. if (g_fRunningOnNT)
  3265. {
  3266. IExtractIcon *pxi;
  3267. hr = punk->QueryInterface(IID_PPV_ARG(IExtractIcon, &pxi));
  3268. if (SUCCEEDED(hr))
  3269. {
  3270. hr = pxi->GetIconLocation(uInFlags, pszIconFile, cchIconFile, pniIcon, puOutFlags);
  3271. pxi->Release();
  3272. }
  3273. }
  3274. else
  3275. {
  3276. IExtractIconA *pxi;
  3277. hr = punk->QueryInterface(IID_PPV_ARG(IExtractIconA, &pxi));
  3278. if (SUCCEEDED(hr))
  3279. {
  3280. CHAR sz[MAX_PATH];
  3281. hr = pxi->GetIconLocation(uInFlags, sz, SIZECHARS(sz), pniIcon, puOutFlags);
  3282. if (SUCCEEDED(hr))
  3283. SHAnsiToTChar(sz, pszIconFile, cchIconFile);
  3284. pxi->Release();
  3285. }
  3286. }
  3287. return hr;
  3288. }
  3289. HRESULT IExtractIcon_Extract(
  3290. IUnknown *punk,
  3291. IN LPCTSTR pszIconFile,
  3292. IN UINT iIcon,
  3293. OUT HICON * phiconLarge,
  3294. OUT HICON * phiconSmall,
  3295. IN UINT ucIconSize)
  3296. {
  3297. ASSERT(punk);
  3298. HRESULT hr;
  3299. if (g_fRunningOnNT)
  3300. {
  3301. IExtractIcon *pxi;
  3302. hr = punk->QueryInterface(IID_PPV_ARG(IExtractIcon, &pxi));
  3303. if (SUCCEEDED(hr))
  3304. {
  3305. hr = pxi->Extract(pszIconFile, iIcon, phiconLarge, phiconSmall, ucIconSize);
  3306. pxi->Release();
  3307. }
  3308. }
  3309. else
  3310. {
  3311. IExtractIconA *pxi;
  3312. hr = punk->QueryInterface(IID_PPV_ARG(IExtractIconA, &pxi));
  3313. if (SUCCEEDED(hr))
  3314. {
  3315. CHAR sz[MAX_PATH];
  3316. SHTCharToAnsi(pszIconFile, sz, SIZECHARS(sz));
  3317. hr = pxi->Extract(sz, iIcon, phiconLarge, phiconSmall, ucIconSize);
  3318. pxi->Release();
  3319. }
  3320. }
  3321. return hr;
  3322. }
  3323. typedef EXECUTION_STATE (__stdcall *PFNSTES) (EXECUTION_STATE);
  3324. EXECUTION_STATE _SetThreadExecutionState(EXECUTION_STATE esFlags)
  3325. {
  3326. static PFNSTES _pfnSetThreadExecutionState = (PFNSTES)-1;
  3327. if (_pfnSetThreadExecutionState == (PFNSTES)-1)
  3328. _pfnSetThreadExecutionState = (PFNSTES)GetProcAddress(GetModuleHandleA("kernel32.dll"), "SetThreadExecutionState");
  3329. if (_pfnSetThreadExecutionState != (PFNSTES)NULL)
  3330. return(_pfnSetThreadExecutionState(esFlags));
  3331. else
  3332. return((EXECUTION_STATE)NULL);
  3333. }
  3334. HRESULT SHPathPrepareForWriteWrap(HWND hwnd, IUnknown *punkEnableModless, LPCTSTR pszPath, UINT wFunc, DWORD dwFlags)
  3335. {
  3336. HRESULT hr;
  3337. if (g_bRunOnNT5)
  3338. {
  3339. // NT5's version of the API is better.
  3340. hr = SHPathPrepareForWriteW(hwnd, punkEnableModless, pszPath, dwFlags);
  3341. }
  3342. else
  3343. {
  3344. hr = SHCheckDiskForMedia(hwnd, punkEnableModless, pszPath, wFunc);
  3345. }
  3346. return hr;
  3347. }
  3348. void GetPathOtherFormA(LPSTR lpszPath, LPSTR lpszNewPath, DWORD dwSize)
  3349. {
  3350. BOOL bQuotes = FALSE;
  3351. LPSTR szStart = lpszPath;
  3352. LPSTR szEnd = NULL;
  3353. LPSTR szNewStart = lpszNewPath;
  3354. ZeroMemory(lpszNewPath, dwSize);
  3355. // Cull out the starting and ending " because GetShortPathName does not
  3356. // like it.
  3357. if (*lpszPath == '"')
  3358. {
  3359. bQuotes = TRUE;
  3360. szStart = lpszPath + 1;
  3361. szEnd = lpszPath + lstrlenA(lpszPath) - 1; // Point to the last "
  3362. *szEnd = '\0';
  3363. szNewStart = lpszNewPath + 1; // So that we can insert the " in it.
  3364. dwSize = dwSize - 2; // for the two double quotes to be added.
  3365. }
  3366. if (GetShortPathNameA(szStart, szNewStart, dwSize) != 0)
  3367. {
  3368. if (StrCmpIA(szStart, szNewStart) == 0)
  3369. { // The original Path is a SFN. So NewPath needs to be LFN.
  3370. GetLongPathNameA((LPCSTR)szStart, szNewStart, dwSize);
  3371. }
  3372. }
  3373. // Now add the " to the NewPath so that it is in the expected form
  3374. if (bQuotes)
  3375. {
  3376. int len = 0;
  3377. // Fix the Original path.
  3378. *szEnd = '"';
  3379. // Fix the New path.
  3380. *lpszNewPath = '"'; // Insert " in the beginning.
  3381. len = lstrlenA(lpszNewPath);
  3382. *(lpszNewPath + len) = '"'; // Add the " in the end.
  3383. *(lpszNewPath + len + 1) = '\0'; // Terminate the string.
  3384. }
  3385. return;
  3386. }
  3387. int GetUrlSchemeFromPidl(LPCITEMIDLIST pidl)
  3388. {
  3389. ASSERT(pidl);
  3390. ASSERT(IsURLChild(pidl, FALSE));
  3391. int nRet = URL_SCHEME_INVALID;
  3392. WCHAR szUrl[MAX_URL_STRING];
  3393. if (SUCCEEDED(IEGetNameAndFlags(pidl, SHGDN_FORPARSING, szUrl,
  3394. ARRAYSIZE(szUrl), NULL)))
  3395. {
  3396. nRet = GetUrlScheme(szUrl);
  3397. }
  3398. return nRet;
  3399. }
  3400. //
  3401. // Check if it is safe to create a shortcut for the given url. Used by add
  3402. // to favorites code.
  3403. //
  3404. BOOL IEIsLinkSafe(HWND hwnd, LPCITEMIDLIST pidl, ILS_ACTION ilsFlag)
  3405. {
  3406. ASSERT(pidl);
  3407. BOOL fRet = TRUE;
  3408. if (IsURLChild(pidl, FALSE))
  3409. {
  3410. int nScheme = GetUrlSchemeFromPidl(pidl);
  3411. if (URL_SCHEME_JAVASCRIPT == nScheme || URL_SCHEME_VBSCRIPT == nScheme)
  3412. {
  3413. WCHAR szTitle[MAX_PATH];
  3414. WCHAR szText[MAX_PATH];
  3415. MLLoadString(IDS_SECURITYALERT, szTitle, ARRAYSIZE(szTitle));
  3416. MLLoadString(IDS_ADDTOFAV_WARNING + ilsFlag, szText,
  3417. ARRAYSIZE(szText));
  3418. ULONG_PTR uCookie = 0;
  3419. SHActivateContext(&uCookie);
  3420. fRet = (IDYES == MLShellMessageBox(hwnd, szText, szTitle, MB_YESNO |
  3421. MB_ICONWARNING | MB_APPLMODAL |
  3422. MB_DEFBUTTON2));
  3423. if (uCookie)
  3424. {
  3425. SHDeactivateContext(uCookie);
  3426. }
  3427. }
  3428. }
  3429. return fRet;
  3430. }
  3431. HRESULT GetSearchStyle(IServiceProvider * psp, LPDWORD pdwSearchStyle)
  3432. {
  3433. RIP(pdwSearchStyle != NULL);
  3434. HRESULT hr = E_FAIL;
  3435. // first see if there is an ISearchContext to get this information from
  3436. if (psp != NULL)
  3437. {
  3438. ISearchContext * pSC = NULL;
  3439. hr = psp->QueryService(SID_STopWindow, IID_PPV_ARG(ISearchContext, &pSC));
  3440. if (SUCCEEDED(hr))
  3441. {
  3442. RIP(pSC != NULL);
  3443. hr = pSC->GetSearchStyle(pdwSearchStyle);
  3444. pSC->Release();
  3445. }
  3446. }
  3447. // there wasn't a viable search context, so try the reg key
  3448. if (FAILED(hr))
  3449. {
  3450. DWORD dwType;
  3451. DWORD dwAutoSearch;
  3452. DWORD cb = sizeof(dwAutoSearch);
  3453. if (ERROR_SUCCESS == SHRegGetUSValue(REGSTR_PATH_MAIN, L"AutoSearch", &dwType, &dwAutoSearch, &cb, FALSE, NULL, 0))
  3454. {
  3455. *pdwSearchStyle = dwAutoSearch;
  3456. hr = S_OK;
  3457. }
  3458. }
  3459. // return a default value
  3460. if (FAILED(hr))
  3461. {
  3462. hr = S_FALSE;
  3463. // Default to "display results in search pane and go to most likely site"
  3464. *pdwSearchStyle = 3;
  3465. }
  3466. return hr;
  3467. }
  3468. BOOL AccessAllowed(IUnknown* punkSite, LPCWSTR pwszURL1, LPCWSTR pwszURL2)
  3469. {
  3470. BOOL fRet = FALSE;
  3471. if (pwszURL1 && pwszURL2)
  3472. {
  3473. IInternetSecurityManager *pSecMgr;
  3474. HRESULT hr = IUnknown_QueryService(punkSite, SID_SInternetSecurityManager, IID_PPV_ARG(IInternetSecurityManager, &pSecMgr));
  3475. if (FAILED(hr))
  3476. {
  3477. hr = CoCreateInstance(CLSID_InternetSecurityManager, NULL, CLSCTX_INPROC_SERVER, IID_PPV_ARG(IInternetSecurityManager, &pSecMgr));
  3478. }
  3479. if (SUCCEEDED(hr))
  3480. {
  3481. BYTE reqSid[MAX_SIZE_SECURITY_ID], docSid[MAX_SIZE_SECURITY_ID];
  3482. DWORD cbReqSid = ARRAYSIZE(reqSid);
  3483. DWORD cbDocSid = ARRAYSIZE(docSid);
  3484. if ( SUCCEEDED(pSecMgr->GetSecurityId(pwszURL1, reqSid, &cbReqSid, 0))
  3485. && SUCCEEDED(pSecMgr->GetSecurityId(pwszURL2, docSid, &cbDocSid, 0))
  3486. && (cbReqSid == cbDocSid)
  3487. && (memcmp(reqSid, docSid, cbReqSid) == 0))
  3488. {
  3489. fRet = TRUE;
  3490. }
  3491. pSecMgr->Release();
  3492. }
  3493. }
  3494. return fRet;
  3495. }
  3496. BOOL IsFrameWindow(IHTMLWindow2 * pHTMLWindow)
  3497. {
  3498. BOOL fIsFrame = FALSE;
  3499. HRESULT hr = E_FAIL;
  3500. IHTMLWindow2 * pParentWindow = NULL;
  3501. IHTMLWindow2 * pSelfWindow = NULL;
  3502. ASSERT(pHTMLWindow);
  3503. hr = pHTMLWindow->get_self(&pSelfWindow);
  3504. if (FAILED(hr) || (pSelfWindow == NULL))
  3505. {
  3506. goto cleanup;
  3507. }
  3508. hr = pHTMLWindow->get_parent(&pParentWindow);
  3509. if (FAILED(hr) || (pParentWindow == NULL))
  3510. {
  3511. goto cleanup;
  3512. }
  3513. if (!IsSameObject(pSelfWindow, pParentWindow))
  3514. {
  3515. fIsFrame = TRUE;
  3516. }
  3517. cleanup:
  3518. if (pSelfWindow)
  3519. {
  3520. pSelfWindow->Release();
  3521. }
  3522. if (pParentWindow)
  3523. {
  3524. pParentWindow->Release();
  3525. }
  3526. return fIsFrame;
  3527. }
  3528. // For compatability with the Win2k debug SHELL32.DLL, this function needs to exist at ordinal 161.
  3529. // It's fine for it to return FALSE.
  3530. STDAPI_(BOOL) GetLeakDetectionFunctionTable(void *pTable)
  3531. {
  3532. return FALSE;
  3533. }
  3534. STDAPI_(BOOL) IsCSIDLFolder(UINT csidl, LPCITEMIDLIST pidl)
  3535. {
  3536. BOOL bRet = FALSE;
  3537. TCHAR szPath[MAX_PATH];
  3538. if (SUCCEEDED(SHGetFolderPathD(NULL, csidl, NULL, 0, szPath)))
  3539. {
  3540. PathRemoveBackslash(szPath); // some platforms return version with slash on the end
  3541. TCHAR szFolder[MAX_PATH];
  3542. if (SUCCEEDED(SHGetNameAndFlags(pidl, SHGDN_FORPARSING, szFolder, ARRAYSIZE(szFolder), NULL)))
  3543. {
  3544. bRet = (StrCmpI(szFolder, szPath) == 0);
  3545. }
  3546. }
  3547. return bRet;
  3548. }
  3549. // Determines if the classic toolbar strips should be used, or the new
  3550. // Whistler toolbar strips.
  3551. //
  3552. // To use the new Whistler strips, the user must be running Whistler or later
  3553. // and have a display with greater than 256 colors.
  3554. STDAPI_(BOOL) SHUseClassicToolbarGlyphs (void)
  3555. {
  3556. BOOL bRet = TRUE;
  3557. if (SHGetCurColorRes() > 8)
  3558. {
  3559. if (GetUIVersion() > 5)
  3560. {
  3561. bRet = FALSE;
  3562. }
  3563. }
  3564. return bRet;
  3565. }