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

662 lines
23 KiB

  1. #include "priv.h"
  2. #include <shlobj.h>
  3. #include <shellp.h>
  4. #include <shdguid.h>
  5. #include "ids.h"
  6. #include <objbase.h>
  7. #include <wininet.h> // INTERNET_MAX_URL_LENGTH
  8. #include <shellp.h>
  9. #include <commctrl.h>
  10. #include <mluisupp.h>
  11. #include <inetcpl.h>
  12. #include <crypto\md5.h>
  13. #ifdef UNIX
  14. #include <urlmon.h>
  15. #endif
  16. // This will automatically be freed when the process shuts down.
  17. // Creating the ClassFactory for CLSID_InternetSecurityManager
  18. // is really slow, so we cache it because dragging and dropping
  19. // files does a lot of zone checking.
  20. IClassFactory * g_pcf = NULL;
  21. HRESULT _GetCachedZonesManager(REFIID riid, void **ppv)
  22. {
  23. HRESULT hr;
  24. if (!g_pcf)
  25. {
  26. CoGetClassObject(CLSID_InternetSecurityManager, CLSCTX_INPROC_SERVER, NULL, IID_IClassFactory, (void **)&g_pcf);
  27. SHPinDllOfCLSID(&CLSID_InternetSecurityManager);
  28. }
  29. if (g_pcf)
  30. {
  31. hr = g_pcf->CreateInstance(NULL, riid, ppv);
  32. }
  33. else
  34. {
  35. *ppv = NULL;
  36. hr = E_FAIL;
  37. }
  38. return hr;
  39. }
  40. /**********************************************************************\
  41. FUNCTION: ZoneCheckUrlExCacheW
  42. DESCRIPTION:
  43. Call IInternetSecurityManager::ProcessUrlAction using the
  44. cached one if available.
  45. pwszUrl - URL to check
  46. pdwPolicy - Receives resulting policy (optional)
  47. dwPolicySize - size of policy buffer (usually sizeof(DWORD))
  48. pdwContext - context (optional)
  49. dwContextSize - size of context buffer (usually sizeof(DWORD))
  50. dwActionType - ProcessUrlAction action type code
  51. dwFlags - Flags for ProcessUrlAction
  52. pisms - IInternetSecurityMgrSite to use during
  53. ProcessUrlAction (optional)
  54. ppismCache - (in/out) IInternetSecurityManager to use
  55. If ppismCache is NULL, then no cacheing is performed;
  56. we use a brand new IInternetSecurityManager.
  57. If ppismCache is non-null, then it used to cache an
  58. IInternetSecurityManager. If there is one there already, we
  59. use it. If there isn't one there already, we create one and
  60. save it there.
  61. Return S_OK if access is allowed. This function will return
  62. S_FALSE if access was not allowed.
  63. \**********************************************************************/
  64. LWSTDAPI ZoneCheckUrlExCacheW(LPCWSTR pwzUrl, DWORD * pdwPolicy, DWORD dwPolicySize, DWORD * pdwContext,
  65. DWORD dwContextSize, DWORD dwActionType, DWORD dwFlags, IInternetSecurityMgrSite * pisms, IInternetSecurityManager ** ppismCache)
  66. {
  67. HRESULT hr = E_INVALIDARG;
  68. if (pwzUrl)
  69. {
  70. IInternetSecurityManager *psim;
  71. if (ppismCache && *ppismCache)
  72. {
  73. hr = (*ppismCache)->QueryInterface(IID_PPV_ARG(IInternetSecurityManager, &psim));
  74. }
  75. else
  76. {
  77. hr = _GetCachedZonesManager(IID_PPV_ARG(IInternetSecurityManager, &psim));
  78. if (SUCCEEDED(hr) && ppismCache)
  79. psim->QueryInterface(IID_PPV_ARG(IInternetSecurityManager, ppismCache));
  80. }
  81. if (SUCCEEDED(hr))
  82. {
  83. DWORD dwPolicy = 0;
  84. DWORD dwContext = 0;
  85. if (pisms)
  86. psim->SetSecuritySite(pisms);
  87. hr = psim->ProcessUrlAction(pwzUrl, dwActionType,
  88. (BYTE *)(pdwPolicy ? pdwPolicy : &dwPolicy),
  89. (pdwPolicy ? dwPolicySize : sizeof(dwPolicy)),
  90. (BYTE *)(pdwContext ? pdwContext : &dwContext),
  91. (pdwContext ? dwContextSize : sizeof(dwContext)),
  92. dwFlags, 0);
  93. TraceMsg(TF_GENERAL, "ZoneCheckUrlExW(\"%ls\") IsFile=%s; NoUI=%s; dwActionType=0x%lx; dwFlags=0x%lx; hr=%lx>",
  94. pwzUrl, (dwFlags & PUAF_ISFILE) ? TEXT("Yes") : TEXT("No"),
  95. (dwFlags & PUAF_NOUI) ? TEXT("Yes") : TEXT("No"),
  96. dwActionType, dwFlags, hr);
  97. if (pisms)
  98. psim->SetSecuritySite(NULL);
  99. psim->Release();
  100. }
  101. }
  102. return hr;
  103. }
  104. /**********************************************************************\
  105. FUNCTION: ZoneCheckUrlExCacheA
  106. DESCRIPTION:
  107. ANSI version of ZoneCheckUrlExCacheW.
  108. Return S_OK if access is allowed. This function will return
  109. S_FALSE if access was not allowed.
  110. \**********************************************************************/
  111. LWSTDAPI ZoneCheckUrlExCacheA(LPCSTR pszUrl, DWORD * pdwPolicy, DWORD dwPolicySize, DWORD * pdwContext,
  112. DWORD dwContextSize, DWORD dwActionType, DWORD dwFlags, IInternetSecurityMgrSite * pisms, IInternetSecurityManager ** ppismCache)
  113. {
  114. WCHAR wzUrl[INTERNET_MAX_URL_LENGTH];
  115. ASSERT(ARRAYSIZE(wzUrl) > lstrlenA(pszUrl)); // We only work for Urls of INTERNET_MAX_URL_LENGTH or shorter.
  116. SHAnsiToUnicode(pszUrl, wzUrl, ARRAYSIZE(wzUrl));
  117. return ZoneCheckUrlExCacheW(wzUrl, pdwPolicy, dwPolicySize, pdwContext, dwContextSize, dwActionType, dwFlags, pisms, ppismCache);
  118. }
  119. /**********************************************************************\
  120. FUNCTION: ZoneCheckUrlExW
  121. DESCRIPTION:
  122. Just like ZoneCheckUrlExCacheW, except never caches.
  123. Return S_OK if access is allowed. This function will return
  124. S_FALSE if access was not allowed.
  125. \**********************************************************************/
  126. LWSTDAPI ZoneCheckUrlExW(LPCWSTR pwzUrl, DWORD * pdwPolicy, DWORD dwPolicySize, DWORD * pdwContext,
  127. DWORD dwContextSize, DWORD dwActionType, DWORD dwFlags, IInternetSecurityMgrSite * pisms)
  128. {
  129. return ZoneCheckUrlExCacheW(pwzUrl, pdwPolicy, dwPolicySize, pdwContext, dwContextSize, dwActionType, dwFlags, pisms, NULL);
  130. }
  131. /**********************************************************************\
  132. FUNCTION: ZoneCheckUrlExA
  133. DESCRIPTION:
  134. ANSI version of ZoneCheckUrlExW.
  135. Return S_OK if access is allowed. This function will return
  136. S_FALSE if access was not allowed.
  137. \**********************************************************************/
  138. LWSTDAPI ZoneCheckUrlExA(LPCSTR pszUrl, DWORD * pdwPolicy, DWORD dwPolicySize, DWORD * pdwContext, DWORD dwContextSize, DWORD dwActionType, DWORD dwFlags, IInternetSecurityMgrSite * pisms)
  139. {
  140. WCHAR wzUrl[INTERNET_MAX_URL_LENGTH];
  141. ASSERT(ARRAYSIZE(wzUrl) > lstrlenA(pszUrl)); // We only work for Urls of INTERNET_MAX_URL_LENGTH or shorter.
  142. SHAnsiToUnicode(pszUrl, wzUrl, ARRAYSIZE(wzUrl));
  143. return ZoneCheckUrlExW(wzUrl, pdwPolicy, dwPolicySize, pdwContext, dwContextSize, dwActionType, dwFlags, pisms);
  144. }
  145. /**********************************************************************\
  146. FUNCTION: ZoneCheckUrlW
  147. DESCRIPTION:
  148. Just like ZoneCheckUrlExW, except that no context or policy
  149. information are used.
  150. Return S_OK if access is allowed. This function will return
  151. S_FALSE if access was not allowed.
  152. \**********************************************************************/
  153. LWSTDAPI ZoneCheckUrlW(LPCWSTR pwzUrl, DWORD dwActionType, DWORD dwFlags, IInternetSecurityMgrSite * pisms)
  154. {
  155. return ZoneCheckUrlExW(pwzUrl, NULL, 0, NULL, 0, dwActionType, dwFlags, pisms);
  156. }
  157. /**********************************************************************\
  158. FUNCTION: ZoneCheckUrlA
  159. DESCRIPTION:
  160. ANSI version of ZoneCheckUrlW,
  161. Return S_OK if access is allowed. This function will return
  162. S_FALSE if access was not allowed.
  163. \**********************************************************************/
  164. LWSTDAPI ZoneCheckUrlA(LPCSTR pszUrl, DWORD dwActionType, DWORD dwFlags, IInternetSecurityMgrSite * pisms)
  165. {
  166. WCHAR wzUrl[INTERNET_MAX_URL_LENGTH];
  167. ASSERT(ARRAYSIZE(wzUrl) > lstrlenA(pszUrl)); // We only work for Urls of INTERNET_MAX_URL_LENGTH or shorter.
  168. SHAnsiToUnicode(pszUrl, wzUrl, ARRAYSIZE(wzUrl));
  169. return ZoneCheckUrlW(wzUrl, dwActionType, dwFlags, pisms);
  170. }
  171. /**********************************************************************\
  172. FUNCTION: ZoneCheckPathW
  173. DESCRIPTION:
  174. Just like ZoneCheckUrlW, except for filenames instead of URLs.
  175. Return S_OK if access is allowed. This function will return
  176. S_FALSE if access was not allowed.
  177. \**********************************************************************/
  178. LWSTDAPI ZoneCheckPathW(LPCWSTR pwzPath, DWORD dwActionType, DWORD dwFlags, IInternetSecurityMgrSite * pisms)
  179. {
  180. ASSERT(!PathIsRelativeW(pwzPath));
  181. return ZoneCheckUrlW(pwzPath, dwActionType, (dwFlags | PUAF_ISFILE), pisms);
  182. }
  183. /**********************************************************************\
  184. FUNCTION: ZoneCheckPathA
  185. DESCRIPTION:
  186. ANSI version of ZoneCheckPathW,
  187. Return S_OK if access is allowed. This function will return
  188. S_FALSE if access was not allowed.
  189. \**********************************************************************/
  190. LWSTDAPI ZoneCheckPathA(LPCSTR pszPath, DWORD dwActionType, DWORD dwFlags, IInternetSecurityMgrSite * pisms)
  191. {
  192. WCHAR wzPath[INTERNET_MAX_URL_LENGTH];
  193. ASSERT(ARRAYSIZE(wzPath) > lstrlenA(pszPath)); // We only work for Urls of INTERNET_MAX_URL_LENGTH or shorter.
  194. SHAnsiToUnicode(pszPath, wzPath, ARRAYSIZE(wzPath));
  195. return ZoneCheckPathW(wzPath, dwActionType, dwFlags, pisms);
  196. }
  197. /**********************************************************************\
  198. FUNCTION: ZoneCheckHostEx
  199. DESCRIPTION:
  200. Return S_OK if access is allowed. This function will return
  201. S_FALSE if access was not allowed.
  202. \**********************************************************************/
  203. LWSTDAPI ZoneCheckHostEx(IInternetHostSecurityManager * pihsm, DWORD * pdwPolicy, DWORD dwPolicySize, DWORD * pdwContext,
  204. DWORD dwContextSize, DWORD dwActionType, DWORD dwFlags)
  205. {
  206. HRESULT hr;
  207. DWORD dwPolicy = 0;
  208. DWORD dwContext = 0;
  209. ASSERT(IsFlagClear(dwFlags, PUAF_ISFILE)); // This flag is not appropriate here.
  210. if (!EVAL(pihsm))
  211. return E_INVALIDARG;
  212. hr = pihsm->ProcessUrlAction(dwActionType,
  213. (BYTE *)(pdwPolicy ? pdwPolicy : &dwPolicy),
  214. (pdwPolicy ? dwPolicySize : sizeof(dwPolicy)),
  215. (BYTE *)(pdwContext ? pdwContext : &dwContext),
  216. (pdwContext ? dwContextSize : sizeof(dwContext)),
  217. dwFlags, 0);
  218. TraceMsg(TF_GENERAL, "ZoneCheckHostEx() NoUI=%s; hr=%lx", (dwFlags & PUAF_NOUI) ? TEXT("Yes") : TEXT("No"), hr);
  219. return hr;
  220. }
  221. /**********************************************************************\
  222. FUNCTION: ZoneCheckHost
  223. DESCRIPTION:
  224. Return S_OK if access is allowed. This function will return
  225. S_FALSE if access was not allowed.
  226. \**********************************************************************/
  227. LWSTDAPI ZoneCheckHost(IInternetHostSecurityManager * pihsm, DWORD dwActionType, DWORD dwFlags)
  228. {
  229. return ZoneCheckHostEx(pihsm, NULL, 0, NULL, 0, dwActionType, dwFlags);
  230. }
  231. /**********************************************************************\
  232. FUNCTION: ZoneComputePaneSize
  233. DESCRIPTION:
  234. Computes the necessary size for the zones pane in a status bar.
  235. NOTES
  236. The longest zone is the following:
  237. Width of longest zone name +
  238. Width of " (Mixed)" +
  239. Width of small icon (SM_CXSMICON) +
  240. Width of gripper (SM_CXVSCROLL) +
  241. Four edges (4 * SM_CXEDGE)
  242. Why four edges? Because the rectangle is framed in a DrawEdge(),
  243. which adds two edges on the left and two on the right, for a total
  244. of four.
  245. We cache the results of the font measurements for performance.
  246. \**********************************************************************/
  247. #define ZONES_PANE_WIDTH 220 // Size to use if we are desperate
  248. int _ZoneComputePaneStringSize(HWND hwndStatus, HFONT hf)
  249. {
  250. HDC hdc = GetDC(hwndStatus);
  251. HFONT hfPrev = SelectFont(hdc, hf);
  252. SIZE siz, sizMixed;
  253. HRESULT hrInit, hr;
  254. int cxZone;
  255. ZONEATTRIBUTES za;
  256. // Start with the length of the phrase " (Mixed)"
  257. MLLoadStringW(IDS_MIXED, za.szDisplayName, ARRAYSIZE(za.szDisplayName));
  258. GetTextExtentPoint32W(hdc, za.szDisplayName, lstrlenW(za.szDisplayName), &sizMixed);
  259. cxZone = 0;
  260. hrInit = SHCoInitialize();
  261. IInternetZoneManager *pizm;
  262. hr = CoCreateInstance(CLSID_InternetZoneManager, NULL, CLSCTX_INPROC_SERVER, IID_IInternetZoneManager, (void **)&pizm);
  263. if (SUCCEEDED(hr)) {
  264. DWORD dwZoneEnum, dwZoneCount;
  265. hr = pizm->CreateZoneEnumerator(&dwZoneEnum, &dwZoneCount, 0);
  266. if (SUCCEEDED(hr)) {
  267. for (int nIndex=0; (DWORD)nIndex < dwZoneCount; nIndex++)
  268. {
  269. DWORD dwZone;
  270. za.cbSize = sizeof(ZONEATTRIBUTES);
  271. pizm->GetZoneAt(dwZoneEnum, nIndex, &dwZone);
  272. pizm->GetZoneAttributes(dwZone, &za);
  273. GetTextExtentPoint32W(hdc, za.szDisplayName, lstrlenW(za.szDisplayName), &siz);
  274. if (cxZone < siz.cx)
  275. cxZone = siz.cx;
  276. }
  277. pizm->DestroyZoneEnumerator(dwZoneEnum);
  278. }
  279. pizm->Release();
  280. }
  281. SHCoUninitialize(hrInit);
  282. SelectFont(hdc, hfPrev);
  283. ReleaseDC(hwndStatus, hdc);
  284. // If we couldn't get any zones, then use the panic value.
  285. if (cxZone == 0)
  286. return ZONES_PANE_WIDTH;
  287. else
  288. return cxZone + sizMixed.cx;
  289. }
  290. LOGFONT s_lfStatusBar; // status bar font (cached metrics)
  291. int s_cxMaxZoneText; // size of longest zone text (cached)
  292. LWSTDAPI_(int) ZoneComputePaneSize(HWND hwndStatus)
  293. {
  294. LOGFONT lf;
  295. HFONT hf = GetWindowFont(hwndStatus);
  296. GetObject(hf, sizeof(lf), &lf);
  297. // Warning: lf.lfFaceName is an ASCIIZ string, and there might be
  298. // uninitialized garbage there, so zero-fill it for consistency.
  299. UINT cchFaceName = lstrlen(lf.lfFaceName);
  300. ZeroMemory(&lf.lfFaceName[cchFaceName], sizeof(TCHAR) * (LF_FACESIZE - cchFaceName));
  301. if (memcmp(&lf, &s_lfStatusBar, sizeof(LOGFONT)) != 0)
  302. {
  303. ENTERCRITICAL;
  304. s_cxMaxZoneText = _ZoneComputePaneStringSize(hwndStatus, hf);
  305. s_lfStatusBar = lf; // Update the cache
  306. LEAVECRITICAL;
  307. }
  308. return s_cxMaxZoneText +
  309. GetSystemMetrics(SM_CXSMICON) +
  310. GetSystemMetrics(SM_CXVSCROLL) +
  311. GetSystemMetrics(SM_CXEDGE) * 4;
  312. }
  313. /**********************************************************************\
  314. FUNCTION: ZoneConfigure
  315. DESCRIPTION:
  316. Displays the Zones configuration control panel.
  317. pwszUrl is used to specify which zone is chosen as default.
  318. Inetcpl will choose the zone that the URL belongs to.
  319. \**********************************************************************/
  320. #define MAX_CPL_PAGES 16
  321. BOOL CALLBACK _ZoneAddPropSheetPage(HPROPSHEETPAGE hpage, LPARAM lParam)
  322. {
  323. PROPSHEETHEADER * ppsh = (PROPSHEETHEADER *)lParam;
  324. if (ppsh->nPages < MAX_CPL_PAGES)
  325. {
  326. ppsh->phpage[ppsh->nPages++] = hpage;
  327. return TRUE;
  328. }
  329. return FALSE;
  330. }
  331. LWSTDAPI_(void) ZoneConfigureW(HWND hwnd, LPCWSTR pwszUrl)
  332. {
  333. HMODULE hModInetCpl;
  334. if (hModInetCpl = LoadLibrary(TEXT("inetcpl.cpl")))
  335. {
  336. PFNADDINTERNETPROPERTYSHEETSEX pfnAddSheet = (PFNADDINTERNETPROPERTYSHEETSEX)GetProcAddress(hModInetCpl, STR_ADDINTERNETPROPSHEETSEX);
  337. if (pfnAddSheet)
  338. {
  339. IEPROPPAGEINFO iepi = {SIZEOF(iepi)};
  340. // Load the current url into the properties page
  341. CHAR szBufA[INTERNET_MAX_URL_LENGTH];
  342. SHUnicodeToAnsi(pwszUrl, szBufA, ARRAYSIZE(szBufA));
  343. iepi.pszCurrentURL = szBufA;
  344. PROPSHEETHEADER psh;
  345. HPROPSHEETPAGE rPages[MAX_CPL_PAGES];
  346. psh.dwSize = SIZEOF(psh);
  347. psh.dwFlags = PSH_PROPTITLE;
  348. psh.hInstance = MLGetHinst();
  349. psh.hwndParent = hwnd;
  350. psh.pszCaption = MAKEINTRESOURCE(IDS_INTERNETSECURITY);
  351. psh.nPages = 0;
  352. psh.nStartPage = 0;
  353. psh.phpage = rPages;
  354. // we just want the security page.
  355. iepi.dwFlags = INET_PAGE_SECURITY;
  356. pfnAddSheet(_ZoneAddPropSheetPage, (LPARAM)&psh, 0, 0, &iepi);
  357. //
  358. // Display the property sheet only if the "security" page was
  359. // successfully added (it will fail if an IEAK setting says so)
  360. //
  361. if (psh.nPages > 0)
  362. {
  363. PropertySheet(&psh);
  364. }
  365. else
  366. {
  367. SHRestrictedMessageBox(hwnd);
  368. }
  369. }
  370. FreeLibrary(hModInetCpl);
  371. }
  372. }
  373. /**********************************************************************\
  374. DESCRIPTION:
  375. Registers or validates an htt/htm template with the shell.
  376. The WebView customization wizard and the code that installs the default
  377. WebView templates calls this API to register the templates.
  378. The shell object model uses this API to grant privileges to execute
  379. unsafe method calls (e.g. SHELL.APPLICATION) to templates registered
  380. with this API. If they aren't registered, they can't call the unsafe methods.
  381. \**********************************************************************/
  382. #define REGSTR_TEMPLATE_REGISTRY (REGSTR_PATH_EXPLORER TEXT("\\TemplateRegistry"))
  383. #define REGSTR_VALUE_KEY (TEXT("Value"))
  384. BOOL GetTemplateValueFromReg(LPTSTR pszValue, DWORD *pdwValue)
  385. {
  386. DWORD cbValue = sizeof(DWORD);
  387. BOOL bSuccess;
  388. if (!(bSuccess = (ERROR_SUCCESS == SHGetValue(HKEY_LOCAL_MACHINE, REGSTR_TEMPLATE_REGISTRY, pszValue, NULL, pdwValue, &cbValue))))
  389. {
  390. cbValue = sizeof(DWORD);
  391. bSuccess = (ERROR_SUCCESS == SHGetValue(HKEY_CURRENT_USER, REGSTR_TEMPLATE_REGISTRY, pszValue, NULL, pdwValue, &cbValue));
  392. }
  393. return bSuccess;
  394. }
  395. BOOL SetTemplateValueInReg(LPTSTR pszValue, DWORD *pdwValue)
  396. {
  397. return ((ERROR_SUCCESS == SHSetValue(HKEY_LOCAL_MACHINE, REGSTR_TEMPLATE_REGISTRY, pszValue, REG_DWORD, pdwValue, sizeof(DWORD))) ||
  398. (ERROR_SUCCESS == SHSetValue(HKEY_CURRENT_USER, REGSTR_TEMPLATE_REGISTRY, pszValue, REG_DWORD, pdwValue, sizeof(DWORD))));
  399. }
  400. // pKey must point to MD5DIGESTLEN bytes.
  401. HRESULT GetTemplateInfoFromHandle(HANDLE h, UCHAR * pKey, DWORD *pdwSize)
  402. {
  403. HRESULT hres = E_FAIL;
  404. DWORD dwSize = GetFileSize(h, NULL);
  405. LPBYTE pFileBuff = (LPBYTE)LocalAlloc(0, dwSize);
  406. if (pFileBuff)
  407. {
  408. DWORD dwBytesRead;
  409. if (ReadFile(h, pFileBuff, dwSize, &dwBytesRead, NULL))
  410. {
  411. MD5_CTX md5;
  412. MD5Init(&md5);
  413. MD5Update(&md5, pFileBuff, dwBytesRead);
  414. MD5Final(&md5);
  415. memcpy(pKey, md5.digest, MD5DIGESTLEN);
  416. *pdwSize = dwSize;
  417. hres = S_OK;
  418. }
  419. LocalFree(pFileBuff);
  420. }
  421. else
  422. {
  423. hres = E_OUTOFMEMORY;
  424. }
  425. return hres;
  426. }
  427. // in:
  428. // pszPath URL or file system path
  429. // return:
  430. // S_OK if pszPath is in the local zone
  431. // E_ACCESSDENIED we are not in a local zone
  432. //
  433. // WARNING: Only use this from SHRegisterValidateTemplate
  434. // because this isn't good enough for general use.
  435. //
  436. // QUESTION:
  437. // It's not good enought to CoCreate IInternetSecurityManager
  438. // (done in _GetCachedZonesManager), because it needs
  439. // to be provided from the host via QueryService.
  440. // Outlook Express is one example that needs to over-ride
  441. // the default implementation. Right?
  442. // ANSWER:
  443. // Using this from SHRegisterValidateTemplate is OK
  444. // because the only callers are Explorer, which never
  445. // overrides the default zone behavior. (And the templates
  446. // are defview implementations which also don't need zone override.)
  447. //
  448. STDAPI SuperPrivate_ZoneCheckPath(LPCWSTR pszPath, DWORD dwZone)
  449. {
  450. HRESULT hr = E_ACCESSDENIED;
  451. IInternetSecurityManager *pSecMgr;
  452. if (SUCCEEDED(_GetCachedZonesManager(IID_PPV_ARG(IInternetSecurityManager, &pSecMgr))))
  453. {
  454. DWORD dwZoneID = URLZONE_UNTRUSTED;
  455. if (SUCCEEDED(pSecMgr->MapUrlToZone(pszPath, &dwZoneID, 0)))
  456. {
  457. if (dwZoneID == dwZone)
  458. {
  459. hr = S_OK; // we are good
  460. }
  461. }
  462. pSecMgr->Release();
  463. }
  464. return hr;
  465. }
  466. // this API takes a Win32 file path
  467. // in:
  468. // dwFlags SHRVT_ falgs in shlwapi.h
  469. // out:
  470. // S_OK happy
  471. LWSTDAPI SHRegisterValidateTemplate(LPCWSTR pszPath, DWORD dwFlags)
  472. {
  473. if ((dwFlags & SHRVT_VALID) != dwFlags)
  474. return E_INVALIDARG;
  475. HRESULT hr = S_OK;
  476. if (dwFlags & SHRVT_VALIDATE)
  477. {
  478. hr = SuperPrivate_ZoneCheckPath(pszPath, URLZONE_LOCAL_MACHINE);
  479. if (FAILED(hr) && (dwFlags & SHRVT_ALLOW_INTRANET))
  480. {
  481. hr = SuperPrivate_ZoneCheckPath(pszPath, URLZONE_INTRANET);
  482. }
  483. }
  484. if (S_OK == hr)
  485. {
  486. DWORD dwSize;
  487. UCHAR pKey[MD5DIGESTLEN];
  488. HANDLE hfile = CreateFileW(pszPath, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_FLAG_SEQUENTIAL_SCAN, NULL);
  489. if (INVALID_HANDLE_VALUE != hfile)
  490. {
  491. hr = GetTemplateInfoFromHandle(hfile, pKey, &dwSize);
  492. CloseHandle(hfile);
  493. }
  494. else
  495. hr = E_INVALIDARG;
  496. if (SUCCEEDED(hr))
  497. {
  498. BOOL bSuccess;
  499. TCHAR szTemplate[MAX_PATH];
  500. DWORD *pdw = (DWORD *)pKey;
  501. ASSERT(MD5DIGESTLEN == (4 * sizeof(DWORD)));
  502. StringCchPrintf(szTemplate, ARRAYSIZE(szTemplate), TEXT("%u%u%u%u"), pdw[0], pdw[1], pdw[2], pdw[3]);
  503. if (dwFlags & SHRVT_VALIDATE)
  504. {
  505. DWORD dwSizeReg;
  506. bSuccess = (GetTemplateValueFromReg(szTemplate, &dwSizeReg) && (dwSizeReg == dwSize));
  507. if (!bSuccess && (dwFlags & SHRVT_PROMPTUSER))
  508. {
  509. MSGBOXPARAMS mbp = {sizeof(MSGBOXPARAMS), NULL, g_hinst, MAKEINTRESOURCE(IDS_TEMPLATENOTSECURE), MAKEINTRESOURCE(IDS_SECURITY),
  510. MB_YESNO | MB_DEFBUTTON2 | MB_TASKMODAL | MB_USERICON, MAKEINTRESOURCE(IDI_SECURITY), 0, NULL, 0};
  511. // REARCHITECT: posting a msg box with NULL hwnd, this should
  512. // could use a site pointer to get an hwnd to go modal against
  513. // if one was provided to the API
  514. // Are we calling A or W MessageBoxIndirect and does this break on NT/9x?
  515. // Doesn't seem to, -justmann
  516. bSuccess = (MessageBoxIndirect(&mbp) == IDYES);
  517. if (bSuccess && (dwFlags & SHRVT_REGISTERIFPROMPTOK))
  518. SetTemplateValueInReg(szTemplate, &dwSize);
  519. }
  520. }
  521. else if (dwFlags & SHRVT_REGISTER)
  522. {
  523. bSuccess = SetTemplateValueInReg(szTemplate, &dwSize);
  524. }
  525. hr = bSuccess ? S_OK : E_ACCESSDENIED;
  526. }
  527. }
  528. return hr;
  529. }