Source code of Windows XP (NT5)
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.

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