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.

1739 lines
55 KiB

  1. //
  2. // Shell UI Control Class (CShellUIHelper)
  3. //
  4. // Sample code : shell\docs\shuiod.htm
  5. //
  6. // This is the source code of the ShellUI control class. You can put an instance
  7. // of ShellUI control on any HTML pages then
  8. //
  9. // The key thing is it always bring up some UI and never alter the system
  10. // silently (without the User's interaction). By doing this, we can expose
  11. // shell features as much as we want without worrying about the security
  12. // problem (which automation interface has).
  13. //
  14. // This control also allow us to provide many configuration type UI (such as
  15. // "Customize your IE page") as well as rich web-view on some folders
  16. // (especially control panel ;-) without paying the cost of data-binding.
  17. //
  18. #include "priv.h"
  19. #include "sccls.h"
  20. #ifndef UNIX
  21. #include <webcheck.h>
  22. #else
  23. #include <subsmgr.h>
  24. #endif
  25. #include "favorite.h"
  26. #include "caggunk.h"
  27. #include "resource.h"
  28. #include "channel.h"
  29. #include "chanmgr.h"
  30. #include "chanmgrp.h"
  31. #include "iforms.h"
  32. #include "dspsprt.h"
  33. #include "impexp.h" // needed for RunImportExportWizard()
  34. #include "iforms.h"
  35. //#include "cobjsafe.h" // CObjectSafety
  36. #include "shvocx.h" // WrapSpecialUrl()
  37. #include <mluisupp.h>
  38. #define REG_DESKCOMP_SCHEME TEXT("Software\\Microsoft\\Internet Explorer\\Desktop\\Scheme")
  39. #define REG_VAL_SCHEME_DISPLAY TEXT("Display")
  40. #define REG_VAL_GENERAL_WALLPAPER TEXT("Wallpaper")
  41. #define REG_VAL_GENERAL_TILEWALLPAPER TEXT("TileWallpaper")
  42. #define REG_DESKCOMP_GENERAL TEXT("Software\\Microsoft\\Internet Explorer\\Desktop%sGeneral")
  43. STDAPI SHAddSubscribeFavorite (HWND hwnd, LPCWSTR pwszURL, LPCWSTR pwszName, DWORD dwFlags,
  44. SUBSCRIPTIONTYPE subsType, SUBSCRIPTIONINFO* pInfo);
  45. // move it to shdocvw.h
  46. UINT IE_ErrorMsgBox(IShellBrowser* psb,
  47. HWND hwndOwner, HRESULT hrError, LPCWSTR szError, LPCTSTR pszURLparam,
  48. UINT idResource, UINT wFlags);
  49. #define DM_SHUIOC DM_TRACE
  50. LONG GetSearchFormatString(DWORD dwIndex, LPTSTR psz, DWORD cbpsz);
  51. HRESULT TargetQueryService(IUnknown *punk, REFIID riid, void **ppvObj);
  52. EXTERN_C const SA_BSTRGUID s_sstrSearch;
  53. EXTERN_C const SA_BSTRGUID s_sstrFailureUrl;
  54. class CShellUIHelper :
  55. public CAggregatedUnknown,
  56. public IObjectWithSite,
  57. public IObjectSafety,
  58. public IShellUIHelper, // dual, IDispatch
  59. public IDispatchEx,
  60. protected CImpIDispatch
  61. {
  62. // IUnknown
  63. STDMETHODIMP QueryInterface(REFIID riid, void ** ppvObj) { return CAggregatedUnknown::QueryInterface(riid, ppvObj);};
  64. STDMETHODIMP_(ULONG) AddRef(void) { return CAggregatedUnknown::AddRef();};
  65. STDMETHODIMP_(ULONG) Release(void) { return CAggregatedUnknown::Release();};
  66. // IObjectWithSite
  67. STDMETHODIMP SetSite(IUnknown *pUnkSite);
  68. STDMETHODIMP GetSite(REFIID riid, void **ppvSite);
  69. // IObjectSafety
  70. STDMETHOD(GetInterfaceSafetyOptions)(REFIID riid, DWORD *pdwSupportedOptions,
  71. DWORD *pdwEnabledOptions);
  72. STDMETHOD(SetInterfaceSafetyOptions)(REFIID riid, DWORD dwOptionSetMask,
  73. DWORD dwEnabledOptions);
  74. // IDispatch
  75. STDMETHODIMP GetTypeInfoCount(UINT * pctinfo);
  76. STDMETHODIMP GetTypeInfo(UINT itinfo, LCID lcid, ITypeInfo **pptinfo);
  77. STDMETHODIMP GetIDsOfNames(REFIID riid, OLECHAR **rgszNames, UINT cNames,
  78. LCID lcid, DISPID * rgdispid);
  79. STDMETHODIMP Invoke(DISPID dispidMember, REFIID riid, LCID lcid, WORD wFlags,
  80. DISPPARAMS * pdispparams, VARIANT * pvarResult,
  81. EXCEPINFO * pexcepinfo, UINT * puArgErr);
  82. // IDispatchEx
  83. STDMETHODIMP GetDispID(BSTR bstrName, DWORD grfdex, DISPID *pid);
  84. STDMETHODIMP InvokeEx(DISPID id, LCID lcid, WORD wFlags, DISPPARAMS *pdp,
  85. VARIANT *pvarRes, EXCEPINFO *pei,
  86. IServiceProvider *pspCaller);
  87. STDMETHODIMP DeleteMemberByName(BSTR bstr, DWORD grfdex);
  88. STDMETHODIMP DeleteMemberByDispID(DISPID id);
  89. STDMETHODIMP GetMemberProperties(DISPID id, DWORD grfdexFetch, DWORD *pgrfdex);
  90. STDMETHODIMP GetMemberName(DISPID id, BSTR *pbstrName);
  91. STDMETHODIMP GetNextDispID(DWORD grfdex, DISPID id, DISPID *pid);
  92. STDMETHODIMP GetNameSpaceParent(IUnknown **ppunk);
  93. // IShellUIHelper
  94. STDMETHODIMP Execute();
  95. STDMETHODIMP ResetSafeMode();
  96. STDMETHODIMP ResetFirstBootMode();
  97. STDMETHODIMP RefreshOfflineDesktop();
  98. STDMETHODIMP AddFavorite(BSTR strURL, VARIANT *Title);
  99. STDMETHODIMP AddChannel(BSTR bstrURL);
  100. STDMETHODIMP AddDesktopComponent(BSTR strURL, BSTR strType,
  101. VARIANT *Left, VARIANT *Top,
  102. VARIANT *Width, VARIANT *Height);
  103. STDMETHODIMP IsSubscribed(BSTR bstrURL, VARIANT_BOOL* pBool);
  104. STDMETHODIMP NavigateAndFind(BSTR URL, BSTR strQuery, VARIANT* varTargetFrame);
  105. STDMETHODIMP ImportExportFavorites(VARIANT_BOOL fImport, BSTR strImpExpPath);
  106. STDMETHODIMP AutoCompleteSaveForm(VARIANT *Form);
  107. STDMETHODIMP AutoScan(BSTR strSearch, BSTR strFailureUrl, VARIANT* pvarTargetFrame);
  108. STDMETHODIMP AutoCompleteAttach(VARIANT *Form);
  109. STDMETHODIMP ShowBrowserUI(BSTR bstrName, VARIANT *pvarIn, VARIANT *pvarOut);
  110. HRESULT v_InternalQueryInterface(REFIID riid, void ** ppvObj);
  111. CShellUIHelper(IUnknown* punkAgg);
  112. ~CShellUIHelper();
  113. inline IDispatch *GetExternalDispatch()
  114. {
  115. return _pExternalDispEx ? _pExternalDispEx : _pExternalDisp;
  116. }
  117. void SetExternalDispatch(IDispatch *pExternalDisp)
  118. {
  119. ATOMICRELEASE(_pExternalDisp);
  120. ATOMICRELEASE(_pExternalDispEx);
  121. // If we were passed an IDispatch to delegate to then we need to
  122. // see if it can do IDispatchEx so we can support it as well,
  123. // otherwise we just fall back to good ole IDispatch.
  124. if (pExternalDisp)
  125. {
  126. if (FAILED(pExternalDisp->QueryInterface(IID_IDispatchEx,
  127. (void **)&_pExternalDispEx)))
  128. {
  129. _pExternalDisp = pExternalDisp;
  130. _pExternalDisp->AddRef();
  131. }
  132. }
  133. }
  134. STDMETHODIMP ShowChannel(IChannelMgrPriv *pChMgrPriv, LPWSTR pwszURL, HWND hwnd);
  135. HWND _GetOwnerWindow();
  136. HRESULT _ConnectToTopLevelConnectionPoint(BOOL fConnect, IUnknown* punk);
  137. STDMETHODIMP _DoFindOnPage(IDispatch* pdisp);
  138. friend HRESULT CShellUIHelper_CreateInstance(IUnknown* punkOuter, IUnknown** ppunk, LPCOBJECTINFO poi);
  139. friend HRESULT CShellUIHelper_CreateInstance2(IUnknown** ppunk, REFIID riid,
  140. IUnknown *pSite, IDispatch *pExternalDisp);
  141. DWORD _dwSafety;
  142. // Cached pointers, hwnd
  143. IUnknown* _punkSite; // site pointer
  144. IDispatchEx* _pExternalDispEx;
  145. IDispatch* _pExternalDisp;
  146. DWORD _dwcpCookie;
  147. BOOL _fWaitingToFindText;
  148. BSTR _bstrQuery;
  149. VOID * _pvIntelliForms;
  150. };
  151. STDAPI CShellUIHelper_CreateInstance(IUnknown* punkOuter, IUnknown** ppunk, LPCOBJECTINFO poi)
  152. {
  153. HRESULT hres = E_OUTOFMEMORY;
  154. CShellUIHelper* psuo = new CShellUIHelper(punkOuter);
  155. if (psuo)
  156. {
  157. *ppunk = psuo->_GetInner();
  158. hres = S_OK;
  159. }
  160. return hres;
  161. }
  162. HRESULT CShellUIHelper_CreateInstance2(IUnknown** ppunk, REFIID riid,
  163. IUnknown *pSite, IDispatch *pExternalDisp)
  164. {
  165. HRESULT hres = E_OUTOFMEMORY;
  166. CShellUIHelper* psuo = new CShellUIHelper(NULL);
  167. if (psuo)
  168. {
  169. hres = psuo->QueryInterface(riid, (void **)ppunk);
  170. psuo->Release();
  171. if (SUCCEEDED(hres))
  172. {
  173. psuo->SetSite(pSite);
  174. psuo->SetExternalDispatch(pExternalDisp);
  175. }
  176. }
  177. return hres;
  178. }
  179. CShellUIHelper::CShellUIHelper(IUnknown* punkAgg) :
  180. CAggregatedUnknown(punkAgg),
  181. CImpIDispatch(LIBID_SHDocVw, 1, 1, IID_IShellUIHelper)
  182. {
  183. DllAddRef();
  184. _fWaitingToFindText = FALSE;
  185. _bstrQuery = NULL;
  186. }
  187. CShellUIHelper::~CShellUIHelper()
  188. {
  189. ReleaseIntelliForms(_pvIntelliForms);
  190. if (_punkSite)
  191. SetSite(NULL); // In case the parent did not clean it up.
  192. if (_bstrQuery)
  193. SysFreeString(_bstrQuery);
  194. ATOMICRELEASE(_pExternalDisp);
  195. ATOMICRELEASE(_pExternalDispEx);
  196. DllRelease();
  197. }
  198. HRESULT CShellUIHelper::v_InternalQueryInterface(REFIID riid, void ** ppvObj)
  199. {
  200. if (IsEqualIID(riid, IID_IDispatch) ||
  201. IsEqualIID(riid, IID_IShellUIHelper))
  202. {
  203. *ppvObj = SAFECAST(this, IShellUIHelper *);
  204. }
  205. else if (IsEqualIID(riid, IID_IObjectWithSite))
  206. {
  207. *ppvObj = SAFECAST(this, IObjectWithSite *);
  208. }
  209. else if (IsEqualIID(riid, IID_IObjectSafety))
  210. {
  211. *ppvObj = SAFECAST(this, IObjectSafety *);
  212. }
  213. else if (IsEqualIID(riid, IID_IDispatchEx))
  214. {
  215. *ppvObj = SAFECAST(this, IDispatchEx *);
  216. }
  217. else
  218. {
  219. *ppvObj = NULL;
  220. return E_NOINTERFACE;
  221. }
  222. AddRef();
  223. return S_OK;
  224. }
  225. HWND CShellUIHelper::_GetOwnerWindow()
  226. {
  227. HWND hwnd;
  228. HRESULT hres;
  229. // this deals with NULL _punkSite and zeros hwnd on failure
  230. IUnknown_GetWindow(_punkSite, &hwnd);
  231. if (!hwnd)
  232. {
  233. //
  234. // We get to this point if we are instantiated like this
  235. // in jscript:
  236. // foo = new ActiveXObject("Shell.UIControl");
  237. // or vbscript:
  238. // set foo = CreateObject("Shell.UIControl");
  239. //
  240. if (_punkSite)
  241. {
  242. IServiceProvider *pSP = NULL;
  243. IOleWindow *pOleWindow = NULL;
  244. hres = _punkSite->QueryInterface(IID_IServiceProvider, (void **)&pSP);
  245. if (SUCCEEDED(hres))
  246. {
  247. ASSERT(pSP);
  248. hres = pSP->QueryService(SID_SContainerDispatch, IID_IOleWindow,
  249. (void **)&pOleWindow);
  250. if (SUCCEEDED(hres))
  251. {
  252. pOleWindow->GetWindow(&hwnd);
  253. pOleWindow->Release();
  254. }
  255. pSP->Release();
  256. }
  257. }
  258. else
  259. {
  260. // It's either this or the functions we call should take NULL for HWNDs.
  261. hwnd = GetDesktopWindow();
  262. }
  263. }
  264. return hwnd;
  265. }
  266. HRESULT CShellUIHelper::_ConnectToTopLevelConnectionPoint(BOOL fConnect, IUnknown* punk)
  267. {
  268. HRESULT hr = E_INVALIDARG;
  269. IConnectionPointContainer* pcpContainer;
  270. IServiceProvider* psp;
  271. IServiceProvider* psp2;
  272. ASSERT(punk);
  273. if (punk)
  274. {
  275. hr = punk->QueryInterface(IID_PPV_ARG(IServiceProvider, &psp));
  276. if (SUCCEEDED(hr))
  277. {
  278. hr = psp->QueryService(SID_STopLevelBrowser, IID_IServiceProvider, (void**) &psp2);
  279. if (SUCCEEDED(hr))
  280. {
  281. hr = psp2->QueryService(SID_SWebBrowserApp, IID_IConnectionPointContainer, (void **)&pcpContainer);
  282. if (SUCCEEDED(hr))
  283. {
  284. //to avoid ambiguous reference
  285. IDispatch* pdispThis;
  286. this->QueryInterface(IID_IDispatch, (void **)&pdispThis);
  287. ASSERT(pdispThis);
  288. hr = ConnectToConnectionPoint(pdispThis, DIID_DWebBrowserEvents2, fConnect,
  289. pcpContainer, &_dwcpCookie, NULL);
  290. pcpContainer->Release();
  291. pdispThis->Release();
  292. }
  293. psp2->Release();
  294. }
  295. psp->Release();
  296. }
  297. }
  298. return hr;
  299. }
  300. HRESULT CShellUIHelper::SetSite(IUnknown *punkSite)
  301. {
  302. if (!_punkSite)
  303. {
  304. _ConnectToTopLevelConnectionPoint(TRUE, punkSite);
  305. }
  306. else
  307. {
  308. ASSERT(punkSite == NULL); //if we've already got _punkSite, we'd better be releasing the site
  309. _ConnectToTopLevelConnectionPoint(FALSE, _punkSite);
  310. ATOMICRELEASE(_punkSite);
  311. }
  312. _punkSite = punkSite;
  313. if (_punkSite)
  314. _punkSite->AddRef();
  315. return S_OK;
  316. }
  317. HRESULT CShellUIHelper::GetSite(REFIID riid, void **ppvSite)
  318. {
  319. TraceMsg(DM_SHUIOC, "SHUO::GetSite called");
  320. if (_punkSite)
  321. return _punkSite->QueryInterface(riid, ppvSite);
  322. *ppvSite = NULL;
  323. return E_FAIL;
  324. }
  325. STDMETHODIMP CShellUIHelper::GetInterfaceSafetyOptions(REFIID riid, DWORD *pdwSupportedOptions,
  326. DWORD *pdwEnabledOptions)
  327. {
  328. HRESULT hr = S_OK;
  329. if (!pdwSupportedOptions || !pdwEnabledOptions)
  330. return E_POINTER;
  331. if (IID_IDispatch == riid)
  332. {
  333. *pdwSupportedOptions = INTERFACESAFE_FOR_UNTRUSTED_CALLER;
  334. *pdwEnabledOptions = _dwSafety & INTERFACESAFE_FOR_UNTRUSTED_CALLER;
  335. }
  336. else
  337. {
  338. *pdwSupportedOptions = 0;
  339. *pdwEnabledOptions = 0;
  340. hr = E_NOINTERFACE;
  341. }
  342. return hr;
  343. }
  344. STDMETHODIMP CShellUIHelper::SetInterfaceSafetyOptions(REFIID riid, DWORD dwOptionSetMask,
  345. DWORD dwEnabledOptions)
  346. {
  347. HRESULT hr = S_OK;
  348. if (IID_IDispatch == riid)
  349. _dwSafety = dwOptionSetMask & dwEnabledOptions;
  350. else
  351. hr = E_NOINTERFACE;
  352. return hr;
  353. }
  354. struct SHUI_STRMAP
  355. {
  356. LPCTSTR psz;
  357. int id;
  358. };
  359. int _MapStringToId(LPCTSTR pszStr, const SHUI_STRMAP* const psmap, int cel, int idDefault)
  360. {
  361. if (pszStr)
  362. {
  363. for (int i=0; i<cel ; i++)
  364. {
  365. if (StrCmpI(psmap[i].psz, pszStr) == 0)
  366. {
  367. return psmap[i].id;
  368. }
  369. }
  370. }
  371. return idDefault;
  372. }
  373. LPCTSTR OptionalVariantToStr(VARIANT *pvar, LPTSTR pszBuf, UINT cchBuf)
  374. {
  375. if (pvar->vt == VT_BSTR && pvar->bstrVal)
  376. {
  377. SHUnicodeToTChar(pvar->bstrVal, pszBuf, cchBuf);
  378. return pszBuf;
  379. }
  380. *pszBuf = 0;
  381. return NULL;
  382. }
  383. int OptionalVariantToInt(VARIANT *pvar, int iDefault)
  384. {
  385. VARIANT v;
  386. VariantInit(&v);
  387. if (SUCCEEDED(VariantChangeType(&v, pvar, 0, VT_I4)))
  388. {
  389. iDefault = v.lVal;
  390. // VariantClear(&v); // not needed, VT_I4 has no allocs
  391. }
  392. return iDefault;
  393. }
  394. BOOL OptionalVariantToBool(VARIANT *pvar, BOOL fDefault)
  395. {
  396. VARIANT v;
  397. VariantInit(&v);
  398. if (SUCCEEDED(VariantChangeType(&v, pvar, 0, VT_BOOL)))
  399. {
  400. fDefault = v.boolVal;
  401. }
  402. return fDefault;
  403. }
  404. //------------------------------------------------------------------------
  405. STDMETHODIMP CShellUIHelper::AddFavorite(/* [in] */ BSTR strURL, /* [in][optional] */ VARIANT *Title)
  406. {
  407. HRESULT hres = S_OK;
  408. LPITEMIDLIST pidl;
  409. BSTR bstrTemp = NULL;
  410. if (IsSpecialUrl(strURL))
  411. {
  412. bstrTemp = SysAllocString(strURL);
  413. if (bstrTemp)
  414. {
  415. hres = WrapSpecialUrl(&bstrTemp);
  416. if (SUCCEEDED(hres))
  417. strURL = bstrTemp;
  418. }
  419. else
  420. hres = E_OUTOFMEMORY;
  421. }
  422. if (SUCCEEDED(hres))
  423. hres = IECreateFromPath(strURL, &pidl);
  424. if (SUCCEEDED(hres))
  425. {
  426. TCHAR szTitle[MAX_PATH];
  427. hres = ::AddToFavorites(_GetOwnerWindow(), pidl, OptionalVariantToStr(Title, szTitle, ARRAYSIZE(szTitle)), TRUE, NULL, NULL);
  428. ILFree(pidl);
  429. }
  430. if (bstrTemp)
  431. SysFreeString(bstrTemp);
  432. return hres;
  433. }
  434. //------------------------------------------------------------------------
  435. STDMETHODIMP CShellUIHelper::ShowChannel(IChannelMgrPriv *pChMgrPriv, LPWSTR pwszURL, HWND hwnd)
  436. {
  437. HRESULT hres = E_FAIL;
  438. IServiceProvider *pSP1 = NULL,
  439. *pSP2 = NULL;
  440. IWebBrowser2 *pWebBrowser2 = NULL;
  441. if (_punkSite)
  442. {
  443. hres = _punkSite->QueryInterface(IID_IServiceProvider, (void **)&pSP1);
  444. if (SUCCEEDED(hres))
  445. {
  446. ASSERT(pSP1);
  447. hres = pSP1->QueryService(SID_STopLevelBrowser,
  448. IID_IServiceProvider,
  449. (void**)&pSP2);
  450. if (SUCCEEDED(hres))
  451. {
  452. ASSERT(pSP2);
  453. hres = pSP2->QueryService(SID_SWebBrowserApp,
  454. IID_IWebBrowser2,
  455. (void**)&pWebBrowser2);
  456. ASSERT((SUCCEEDED(hres) && pWebBrowser2) || FAILED(hres));
  457. pSP2->Release();
  458. }
  459. pSP1->Release();
  460. }
  461. }
  462. if (FAILED(hres))
  463. {
  464. hres = CoCreateInstance(CLSID_InternetExplorer, NULL, CLSCTX_LOCAL_SERVER, IID_PPV_ARG(IWebBrowser2, &pWebBrowser2));
  465. }
  466. if (SUCCEEDED(hres))
  467. {
  468. ASSERT(pWebBrowser2);
  469. hres = pChMgrPriv->ShowChannel(pWebBrowser2, pwszURL, hwnd);
  470. pWebBrowser2->Release();
  471. }
  472. return hres;
  473. }
  474. STDMETHODIMP CShellUIHelper::AddChannel(BSTR bstrURL)
  475. {
  476. HRESULT hres;
  477. IChannelMgrPriv *pChMgrPriv;
  478. TCHAR szURL[MAX_URL_STRING];
  479. HWND hwnd;
  480. if (!bstrURL)
  481. {
  482. return E_INVALIDARG;
  483. }
  484. hwnd = _GetOwnerWindow();
  485. //
  486. // As long as the underlying functions choke on NULL HWNDs then we may as well
  487. // bail early.
  488. //
  489. if (hwnd)
  490. {
  491. if (!SHIsRestricted2W(hwnd, REST_NoChannelUI, NULL, 0) && !SHIsRestricted2W(hwnd, REST_NoAddingChannels, NULL, 0))
  492. {
  493. StrCpyNW(szURL, bstrURL, ARRAYSIZE(szURL));
  494. hres = JITCoCreateInstance(CLSID_ChannelMgr,
  495. NULL,
  496. CLSCTX_INPROC_SERVER,
  497. IID_IChannelMgrPriv,
  498. (void **)&pChMgrPriv,
  499. hwnd,
  500. FIEF_FLAG_FORCE_JITUI);
  501. if (S_OK == hres)
  502. {
  503. ASSERT(pChMgrPriv);
  504. hres = pChMgrPriv->AddAndSubscribe(hwnd, bstrURL, NULL);
  505. if (hres == S_OK)
  506. {
  507. hres = ShowChannel(pChMgrPriv, bstrURL, hwnd);
  508. }
  509. else if (FAILED(hres))
  510. {
  511. IE_ErrorMsgBox(NULL, hwnd, hres, NULL, szURL, IDS_CHANNEL_UNAVAILABLE, MB_OK| MB_ICONSTOP);
  512. hres = S_FALSE;
  513. }
  514. pChMgrPriv->Release();
  515. }
  516. else if (SUCCEEDED(hres))
  517. {
  518. hres = S_FALSE; // FAIL silently for now - throw dialog for indicating that reboot required if needed
  519. } else
  520. {
  521. IE_ErrorMsgBox(NULL, hwnd, hres, NULL, szURL, IDS_FAV_UNABLETOCREATE, MB_OK| MB_ICONSTOP);
  522. hres = S_FALSE;
  523. }
  524. }
  525. else
  526. {
  527. hres = S_FALSE; // Failure code results in a script error.
  528. }
  529. }
  530. else // !hwnd
  531. {
  532. hres = E_FAIL;
  533. }
  534. return hres;
  535. }
  536. // A lot like GetHTMLDoc2, but only cares about window.external
  537. STDMETHODIMP GetTopLevelBrowser(IUnknown *punk, IWebBrowser2 **ppwb2)
  538. {
  539. return IUnknown_QueryService(punk, SID_SWebBrowserApp, IID_PPV_ARG(IWebBrowser2, ppwb2));
  540. }
  541. STDMETHODIMP ZoneCheck(IUnknown *punkSite, BSTR bstrReqUrl)
  542. {
  543. HRESULT hr = E_ACCESSDENIED;
  544. // Return S_FALSE if we don't have a host site since we have no way of doing a
  545. // security check. This is as far as VB 5.0 apps get.
  546. if (!punkSite)
  547. return S_FALSE;
  548. // 1) Get an IHTMLDocument2 pointer
  549. // 2) Get URL from doc
  550. // 3) Create security manager
  551. // 4) Check if doc URL zone is local, if so everything's S_OK
  552. // 5) Otherwise, get and compare doc URL SID to requested URL SID
  553. IHTMLDocument2 *pHtmlDoc;
  554. if (SUCCEEDED(GetHTMLDoc2(punkSite, &pHtmlDoc)))
  555. {
  556. ASSERT(pHtmlDoc);
  557. BSTR bstrDocUrl;
  558. if (SUCCEEDED(pHtmlDoc->get_URL(&bstrDocUrl)))
  559. {
  560. ASSERT(bstrDocUrl);
  561. IInternetSecurityManager *pSecMgr;
  562. HRESULT hrTmp = IUnknown_QueryService(punkSite, SID_SInternetSecurityManager, IID_PPV_ARG(IInternetSecurityManager, &pSecMgr));
  563. if (FAILED(hrTmp))
  564. {
  565. hrTmp = CoCreateInstance(CLSID_InternetSecurityManager, NULL, CLSCTX_INPROC_SERVER, IID_PPV_ARG(IInternetSecurityManager, &pSecMgr));
  566. }
  567. if (SUCCEEDED(hrTmp))
  568. {
  569. ASSERT(pSecMgr);
  570. DWORD dwZoneID = URLZONE_UNTRUSTED;
  571. if (SUCCEEDED(pSecMgr->MapUrlToZone(bstrDocUrl, &dwZoneID, 0)))
  572. {
  573. if (dwZoneID == URLZONE_LOCAL_MACHINE)
  574. hr = S_OK;
  575. }
  576. if (hr != S_OK && bstrReqUrl)
  577. {
  578. BYTE reqSid[MAX_SIZE_SECURITY_ID], docSid[MAX_SIZE_SECURITY_ID];
  579. DWORD cbReqSid = ARRAYSIZE(reqSid);
  580. DWORD cbDocSid = ARRAYSIZE(docSid);
  581. if ( SUCCEEDED(pSecMgr->GetSecurityId(bstrReqUrl, reqSid, &cbReqSid, 0))
  582. && SUCCEEDED(pSecMgr->GetSecurityId(bstrDocUrl, docSid, &cbDocSid, 0))
  583. && (cbReqSid == cbDocSid)
  584. && (memcmp(reqSid, docSid, cbReqSid) == 0))
  585. {
  586. hr = S_OK;
  587. }
  588. }
  589. pSecMgr->Release();
  590. }
  591. SysFreeString(bstrDocUrl);
  592. }
  593. pHtmlDoc->Release();
  594. }
  595. else
  596. {
  597. // If we don't have an IHTMLDocument2 we aren't running in a browser that supports
  598. // our OM. We shouldn't block in this case since we could potentially
  599. // get here from other hosts (VB, WHS, etc.).
  600. hr = S_FALSE;
  601. }
  602. return hr;
  603. }
  604. // This function checks to see if a navigation is happening from either internet
  605. // or restricted url to LOCAL_MACHINE.
  606. BOOL CanNavigateToUrlWithLocalMachineCheck(IUnknown *punkSite, BSTR pchurltarget)
  607. {
  608. BOOL bCanNavigate = FALSE;
  609. // Get the DochostUI flags for the site.
  610. IDocHostUIHandler *pIDocHostUI;
  611. if (SUCCEEDED(punkSite->QueryInterface(IID_PPV_ARG(IDocHostUIHandler, &pIDocHostUI))))
  612. {
  613. DOCHOSTUIINFO dhInfo;
  614. if (SUCCEEDED(pIDocHostUI->GetHostInfo(&dhInfo)))
  615. {
  616. if (!(dhInfo.dwFlags & DOCHOSTUIFLAG_LOCAL_MACHINE_ACCESS_CHECK))
  617. bCanNavigate = TRUE;
  618. }
  619. pIDocHostUI->Release();
  620. }
  621. // If the DOCHOSTUIFLAG_LOCAL_MACHINE_ACCESS_CHECK is set or if we failed to
  622. // get the flags, do a check to see if the zone is elevated to local machine.
  623. if (!bCanNavigate)
  624. {
  625. // Get the site's url.
  626. IHTMLDocument2 *pHtmlDoc;
  627. if (SUCCEEDED(GetHTMLDoc2(punkSite, &pHtmlDoc)))
  628. {
  629. BSTR pchurlsource;
  630. if (SUCCEEDED(pHtmlDoc->get_URL(&pchurlsource)))
  631. {
  632. IInternetSecurityManager *pSecMgr;
  633. if (SUCCEEDED(IUnknown_QueryService(punkSite, SID_SInternetSecurityManager,
  634. IID_PPV_ARG(IInternetSecurityManager, &pSecMgr))) ||
  635. SUCCEEDED(CoCreateInstance(CLSID_InternetSecurityManager, NULL, CLSCTX_INPROC_SERVER,
  636. IID_PPV_ARG(IInternetSecurityManager, &pSecMgr))))
  637. {
  638. DWORD dwZoneIDSource = URLZONE_UNTRUSTED;
  639. DWORD dwZoneIDTarget = URLZONE_LOCAL_MACHINE;
  640. DWORD dwFlags = PUAF_DEFAULT;
  641. // Get zone of the source url.
  642. if (!pchurlsource || IsSpecialUrl(pchurlsource))
  643. {
  644. // Treat special Urls as restricted.
  645. dwZoneIDSource = URLZONE_UNTRUSTED;
  646. }
  647. else if (!SUCCEEDED(pSecMgr->MapUrlToZone(pchurlsource, &dwZoneIDSource, 0)))
  648. {
  649. // If MapUrlToZone fails, treat the url as restricted.
  650. dwZoneIDSource = URLZONE_UNTRUSTED;
  651. }
  652. // Get zone of the target url
  653. if (!SUCCEEDED(pSecMgr->MapUrlToZone(pchurltarget, &dwZoneIDTarget, 0)))
  654. {
  655. // If MapUrlToZone fails, treat the url as MyComputer. This is safe.
  656. dwZoneIDTarget = URLZONE_LOCAL_MACHINE;
  657. }
  658. // Check if there is a zone elevation.
  659. if ((dwZoneIDSource != URLZONE_INTERNET &&
  660. dwZoneIDSource != URLZONE_UNTRUSTED) ||
  661. dwZoneIDTarget != URLZONE_LOCAL_MACHINE)
  662. {
  663. // There is no zone elevation.
  664. bCanNavigate = TRUE;
  665. }
  666. pSecMgr->Release();
  667. }
  668. SysFreeString(pchurlsource);
  669. }
  670. pHtmlDoc->Release();
  671. }
  672. }
  673. return bCanNavigate;
  674. }
  675. STDMETHODIMP CShellUIHelper::IsSubscribed(BSTR bstrURL, VARIANT_BOOL* pBool)
  676. {
  677. HRESULT hr;
  678. if (!bstrURL || !pBool)
  679. {
  680. return E_INVALIDARG;
  681. }
  682. hr = ZoneCheck(_punkSite, bstrURL);
  683. if (SUCCEEDED(hr))
  684. {
  685. ISubscriptionMgr *pSubscriptionMgr;
  686. hr = CoCreateInstance(CLSID_SubscriptionMgr, NULL, CLSCTX_INPROC_SERVER,
  687. IID_PPV_ARG(ISubscriptionMgr, &pSubscriptionMgr));
  688. if (SUCCEEDED(hr))
  689. {
  690. ASSERT(pSubscriptionMgr);
  691. BOOL tmpBool;
  692. hr = pSubscriptionMgr->IsSubscribed(bstrURL, &tmpBool);
  693. *pBool = tmpBool ? VARIANT_TRUE : VARIANT_FALSE;
  694. pSubscriptionMgr->Release();
  695. }
  696. }
  697. return hr;
  698. }
  699. /****************************************************************************
  700. *
  701. * AddDesktopComponentA - Adds a component to the desktop
  702. *
  703. * ENTRY:
  704. * hwnd - the parent for all UI
  705. * pszUrlA - the URL of the component
  706. * iCompType - one of COMP_TYPE_*
  707. * iLeft, iTop, iWidth, iHeight - dimensions of the component
  708. * dwFlags - additional flags
  709. *
  710. * RETURNS:
  711. * TRUE on success
  712. *
  713. ****************************************************************************/
  714. BOOL AddDesktopComponentW(HWND hwnd, LPCWSTR pszUrl, int iCompType,
  715. int iLeft, int iTop, int iWidth, int iHeight,
  716. DWORD dwFlags)
  717. {
  718. COMPONENT Comp;
  719. BOOL fRet = FALSE;
  720. HRESULT hres;
  721. Comp.dwSize = sizeof(Comp);
  722. //
  723. // Build the pcomp structure.
  724. //
  725. Comp.dwID = -1;
  726. Comp.iComponentType = iCompType;
  727. Comp.fChecked = TRUE;
  728. Comp.fDirty = FALSE;
  729. Comp.fNoScroll = FALSE;
  730. Comp.dwSize = SIZEOF(Comp);
  731. Comp.cpPos.dwSize = SIZEOF(COMPPOS);
  732. Comp.cpPos.iLeft = iLeft;
  733. Comp.cpPos.iTop = iTop;
  734. Comp.cpPos.dwWidth = iWidth;
  735. Comp.cpPos.dwHeight = iHeight;
  736. Comp.cpPos.izIndex = COMPONENT_TOP;
  737. Comp.cpPos.fCanResize = TRUE;
  738. Comp.cpPos.fCanResizeX = TRUE;
  739. Comp.cpPos.fCanResizeY = TRUE;
  740. Comp.cpPos.iPreferredLeftPercent = 0;
  741. Comp.cpPos.iPreferredTopPercent = 0;
  742. StrCpyNW(Comp.wszSource, pszUrl, ARRAYSIZE(Comp.wszSource));
  743. StrCpyNW(Comp.wszSubscribedURL, pszUrl, ARRAYSIZE(Comp.wszSubscribedURL));
  744. StrCpyNW(Comp.wszFriendlyName, pszUrl, ARRAYSIZE(Comp.wszFriendlyName));
  745. Comp.dwCurItemState = IS_NORMAL;
  746. IActiveDesktop * piad;
  747. //
  748. // Add it to the system.
  749. //
  750. hres = CoCreateInstance(CLSID_ActiveDesktop, NULL, CLSCTX_INPROC_SERVER, IID_PPV_ARG(IActiveDesktop, &piad));
  751. if (SUCCEEDED(hres))
  752. {
  753. dwFlags |= DTI_ADDUI_POSITIONITEM;
  754. piad->AddDesktopItemWithUI(hwnd, &Comp, dwFlags);
  755. piad->Release();
  756. fRet = TRUE;
  757. }
  758. return fRet;
  759. }
  760. //------------------------------------------------------------------------
  761. STDMETHODIMP CShellUIHelper::AddDesktopComponent(BSTR strURL, BSTR strType,
  762. /* [optional, in] */ VARIANT *Left,
  763. /* [optional, in] */ VARIANT *Top,
  764. /* [optional, in] */ VARIANT *Width,
  765. /* [optional, in] */ VARIANT *Height)
  766. {
  767. #ifndef DISABLE_ACTIVEDESKTOP_FOR_UNIX
  768. HRESULT hres;
  769. int iType;
  770. if (StrCmpIW(strType, L"image")==0)
  771. {
  772. iType = COMP_TYPE_PICTURE;
  773. }
  774. else if (StrCmpIW(strType, L"website")==0)
  775. {
  776. iType = COMP_TYPE_WEBSITE;
  777. }
  778. else
  779. {
  780. iType = 0;
  781. }
  782. if (iType)
  783. {
  784. AddDesktopComponentW(_GetOwnerWindow(), strURL, iType,
  785. OptionalVariantToInt(Left, -1),
  786. OptionalVariantToInt(Top, -1),
  787. OptionalVariantToInt(Width, -1),
  788. OptionalVariantToInt(Height, -1),
  789. DTI_ADDUI_DISPSUBWIZARD);
  790. hres = S_OK;
  791. }
  792. else
  793. {
  794. hres = E_INVALIDARG;
  795. }
  796. return hres;
  797. #else // #ifndef DISABLE_ACTIVEDESKTOP_FOR_UNIX
  798. return E_INVALIDARG;
  799. #endif // #ifndef DISABLE_ACTIVEDESKTOP_FOR_UNIX
  800. }
  801. void RemoveDefaultWallpaper();
  802. STDMETHODIMP CShellUIHelper::ResetFirstBootMode()
  803. {
  804. #ifndef DISABLE_ACTIVEDESKTOP_FOR_UNIX
  805. if (MLShellMessageBox(
  806. _GetOwnerWindow(),
  807. MAKEINTRESOURCE(IDS_CONFIRM_RESETFLAG),
  808. MAKEINTRESOURCE(IDS_TITLE),
  809. MB_YESNO | MB_ICONQUESTION) == IDYES)
  810. {
  811. RemoveDefaultWallpaper();
  812. return S_OK;
  813. }
  814. #endif // #ifndef DISABLE_ACTIVEDESKTOP_FOR_UNIX
  815. return S_FALSE;
  816. }
  817. // Little helper function used to change the safemode state
  818. void SetSafeMode(DWORD dwFlags)
  819. {
  820. IActiveDesktopP * piadp;
  821. HRESULT hres = CoCreateInstance(CLSID_ActiveDesktop, NULL, CLSCTX_INPROC_SERVER, IID_PPV_ARG(IActiveDesktopP, &piadp));
  822. if (SUCCEEDED(hres))
  823. {
  824. piadp->SetSafeMode(dwFlags);
  825. piadp->Release();
  826. }
  827. }
  828. STDMETHODIMP CShellUIHelper::ResetSafeMode()
  829. {
  830. #ifndef DISABLE_ACTIVEDESKTOP_FOR_UNIX
  831. if ((ZoneCheck(_punkSite, NULL) == S_OK) || (MLShellMessageBox(
  832. _GetOwnerWindow(),
  833. MAKEINTRESOURCE(IDS_CONFIRM_RESET_SAFEMODE),
  834. MAKEINTRESOURCE(IDS_TITLE),
  835. MB_YESNO | MB_ICONQUESTION) == IDYES))
  836. {
  837. SetSafeMode(SSM_CLEAR | SSM_REFRESH);
  838. return S_OK;
  839. }
  840. #endif // #ifndef DISABLE_ACTIVEDESKTOP_FOR_UNIX
  841. return S_FALSE;
  842. }
  843. STDMETHODIMP CShellUIHelper::RefreshOfflineDesktop()
  844. {
  845. #ifndef DISABLE_ACTIVEDESKTOP_FOR_UNIX
  846. IADesktopP2 * piad;
  847. HRESULT hres = CoCreateInstance(CLSID_ActiveDesktop, NULL, CLSCTX_INPROC_SERVER, IID_PPV_ARG(IADesktopP2, &piad));
  848. if (SUCCEEDED(hres))
  849. {
  850. piad->UpdateAllDesktopSubscriptions();
  851. piad->Release();
  852. }
  853. #endif // #ifndef DISABLE_ACTIVEDESKTOP_FOR_UNIX
  854. return S_OK;
  855. }
  856. STDMETHODIMP CShellUIHelper::GetTypeInfoCount(UINT * pctinfo)
  857. {
  858. return E_NOTIMPL;
  859. }
  860. STDMETHODIMP CShellUIHelper::GetTypeInfo(UINT itinfo, LCID lcid, ITypeInfo **pptinfo)
  861. {
  862. return E_NOTIMPL;
  863. }
  864. STDMETHODIMP CShellUIHelper::GetIDsOfNames(REFIID riid, OLECHAR **rgszNames,
  865. UINT cNames, LCID lcid, DISPID * rgdispid)
  866. {
  867. HRESULT hr = E_FAIL;
  868. // First let our host get a crack at this method
  869. IDispatch *pDisp = GetExternalDispatch();
  870. if (pDisp)
  871. {
  872. hr = pDisp->GetIDsOfNames(riid, rgszNames, cNames, lcid, rgdispid);
  873. if (SUCCEEDED(hr))
  874. {
  875. if (rgdispid[0] > 0)
  876. {
  877. // Offset there dispid
  878. rgdispid[0] += DISPID_SHELLUIHELPERLAST;
  879. }
  880. }
  881. }
  882. if (FAILED(hr))
  883. {
  884. // Our host didn't support it so we'll see if it's one of ours.
  885. hr = CImpIDispatch::GetIDsOfNames(riid, rgszNames, cNames, lcid, rgdispid);
  886. }
  887. return hr;
  888. }
  889. HRESULT CShellUIHelper::Invoke(DISPID dispidMember, REFIID riid, LCID lcid, WORD wFlags,
  890. DISPPARAMS *pdispparams, VARIANT * pvarResult, EXCEPINFO *pexcepinfo, UINT *puArgErr)
  891. {
  892. HRESULT hr = DISP_E_MEMBERNOTFOUND;
  893. if ((dispidMember > 0) && (dispidMember <= DISPID_SHELLUIHELPERLAST))
  894. {
  895. hr = CImpIDispatch::Invoke(dispidMember, riid, lcid, wFlags, pdispparams,
  896. pvarResult, pexcepinfo, puArgErr);
  897. }
  898. else if (_fWaitingToFindText && (dispidMember == DISPID_DOCUMENTCOMPLETE))
  899. {
  900. ASSERT(pdispparams->rgvarg[1].vt == VT_DISPATCH);
  901. _fWaitingToFindText = FALSE;
  902. hr = _DoFindOnPage(pdispparams->rgvarg[1].pdispVal);
  903. }
  904. else
  905. {
  906. IDispatch *pDisp = GetExternalDispatch();
  907. if (pDisp)
  908. {
  909. if (dispidMember > 0)
  910. {
  911. // Fixup the offset we added in GetIDsOfNames
  912. dispidMember -= DISPID_SHELLUIHELPERLAST;
  913. }
  914. hr = pDisp->Invoke(dispidMember, riid, lcid, wFlags, pdispparams,
  915. pvarResult, pexcepinfo, puArgErr);
  916. }
  917. }
  918. return hr;
  919. }
  920. STDMETHODIMP CShellUIHelper::GetDispID(BSTR bstrName, DWORD grfdex, DISPID *pid)
  921. {
  922. HRESULT hr = E_FAIL;
  923. LCID lcid = GetSystemDefaultLCID();
  924. // First let our host get a crack at this method via IDispatchEx or IDispatch
  925. if (_pExternalDispEx)
  926. {
  927. hr = _pExternalDispEx->GetDispID(bstrName, grfdex, pid);
  928. }
  929. else if (_pExternalDisp)
  930. {
  931. hr = _pExternalDisp->GetIDsOfNames(IID_NULL, &bstrName, 1, lcid, pid);
  932. }
  933. if (SUCCEEDED(hr))
  934. {
  935. if (*pid > 0)
  936. {
  937. *pid += DISPID_SHELLUIHELPERLAST;
  938. }
  939. }
  940. else
  941. {
  942. // Our host didn't support it so we'll see if it's one of ours.
  943. hr = CImpIDispatch::GetIDsOfNames(IID_NULL, &bstrName, 1, lcid, pid);
  944. }
  945. return hr;
  946. }
  947. STDMETHODIMP CShellUIHelper::InvokeEx(DISPID id, LCID lcid, WORD wFlags, DISPPARAMS *pdp,
  948. VARIANT *pvarRes, EXCEPINFO *pei,
  949. IServiceProvider *pspCaller)
  950. {
  951. HRESULT hr = DISP_E_MEMBERNOTFOUND;
  952. UINT ArgErr; // inetsdk says this isn't used here
  953. // First see if it's ours
  954. if ((id > 0) && (id <= DISPID_SHELLUIHELPERLAST))
  955. {
  956. hr = CImpIDispatch::Invoke(id, IID_NULL, lcid, wFlags, pdp,
  957. pvarRes, pei, &ArgErr);
  958. }
  959. else
  960. {
  961. if (id > 0)
  962. {
  963. id -= DISPID_SHELLUIHELPERLAST;
  964. }
  965. // otherwise try external IDispatchEx
  966. if (_pExternalDispEx)
  967. {
  968. hr = _pExternalDispEx->InvokeEx(id, lcid, wFlags, pdp, pvarRes, pei, pspCaller);
  969. }
  970. // finally try the external IDispatch
  971. else if (_pExternalDisp)
  972. {
  973. hr = _pExternalDisp->Invoke(id, IID_NULL, lcid, wFlags, pdp,
  974. pvarRes, pei, &ArgErr);
  975. }
  976. }
  977. return hr;
  978. }
  979. STDMETHODIMP CShellUIHelper::DeleteMemberByName(BSTR bstr, DWORD grfdex)
  980. {
  981. HRESULT hr = E_NOTIMPL;
  982. if (_pExternalDispEx)
  983. {
  984. hr = _pExternalDispEx->DeleteMemberByName(bstr, grfdex);
  985. }
  986. return hr;
  987. }
  988. STDMETHODIMP CShellUIHelper::DeleteMemberByDispID(DISPID id)
  989. {
  990. HRESULT hr = E_NOTIMPL;
  991. if (_pExternalDispEx)
  992. {
  993. hr = _pExternalDispEx->DeleteMemberByDispID(id);
  994. }
  995. return hr;
  996. }
  997. STDMETHODIMP CShellUIHelper::GetMemberProperties(DISPID id, DWORD grfdexFetch, DWORD *pgrfdex)
  998. {
  999. HRESULT hr = E_NOTIMPL;
  1000. if (_pExternalDispEx)
  1001. {
  1002. hr = _pExternalDispEx->GetMemberProperties(id, grfdexFetch, pgrfdex);
  1003. }
  1004. return hr;
  1005. }
  1006. STDMETHODIMP CShellUIHelper::GetMemberName(DISPID id, BSTR *pbstrName)
  1007. {
  1008. HRESULT hr = E_NOTIMPL;
  1009. if (_pExternalDispEx)
  1010. {
  1011. hr = _pExternalDispEx->GetMemberName(id, pbstrName);
  1012. }
  1013. return hr;
  1014. }
  1015. STDMETHODIMP CShellUIHelper::GetNextDispID(DWORD grfdex, DISPID id, DISPID *pid)
  1016. {
  1017. HRESULT hr = E_NOTIMPL;
  1018. if (_pExternalDispEx)
  1019. {
  1020. hr = _pExternalDispEx->GetNextDispID(grfdex, id, pid);
  1021. }
  1022. return hr;
  1023. }
  1024. STDMETHODIMP CShellUIHelper::GetNameSpaceParent(IUnknown **ppunk)
  1025. {
  1026. HRESULT hr = E_NOTIMPL;
  1027. if (_pExternalDispEx)
  1028. {
  1029. hr = _pExternalDispEx->GetNameSpaceParent(ppunk);
  1030. }
  1031. return hr;
  1032. }
  1033. int GetIntFromReg(HKEY hKey,
  1034. LPCTSTR lpszSubkey,
  1035. LPCTSTR lpszNameValue,
  1036. int iDefault)
  1037. {
  1038. TCHAR szValue[20];
  1039. DWORD dwSizeofValueBuff = SIZEOF(szValue);
  1040. int iRetValue = iDefault;
  1041. DWORD dwType;
  1042. if ((SHGetValue(hKey, lpszSubkey, lpszNameValue, &dwType,(LPBYTE)szValue,
  1043. &dwSizeofValueBuff) == ERROR_SUCCESS) && dwSizeofValueBuff)
  1044. {
  1045. if (dwType == REG_SZ)
  1046. {
  1047. iRetValue = (int)StrToInt(szValue);
  1048. }
  1049. }
  1050. return iRetValue;
  1051. }
  1052. void GetRegLocation(LPTSTR lpszResult, DWORD cchResult, LPCTSTR lpszKey, LPCTSTR lpszScheme)
  1053. {
  1054. TCHAR szSubkey[MAX_PATH];
  1055. DWORD dwDataLength = sizeof(szSubkey) - 2 * sizeof(TCHAR);
  1056. DWORD dwType;
  1057. StrCpyN(szSubkey, TEXT("\\"), ARRAYSIZE(szSubkey));
  1058. if (lpszScheme)
  1059. StrCatBuff(szSubkey, lpszScheme, ARRAYSIZE(szSubkey));
  1060. else
  1061. SHGetValue(HKEY_CURRENT_USER, REG_DESKCOMP_SCHEME, REG_VAL_SCHEME_DISPLAY, &dwType,
  1062. (LPBYTE)(szSubkey) + sizeof(TCHAR), &dwDataLength);
  1063. if (szSubkey[1])
  1064. StrCatBuff(szSubkey, TEXT("\\"), ARRAYSIZE(szSubkey));
  1065. wnsprintf(lpszResult, cchResult, lpszKey, szSubkey);
  1066. }
  1067. #define c_szWallpaper REG_VAL_GENERAL_WALLPAPER
  1068. void RemoveDefaultWallpaper()
  1069. {
  1070. // Read the Wallpaper from the Old location.
  1071. TCHAR szOldWallpaper[MAX_PATH];
  1072. DWORD dwType;
  1073. DWORD dwSize = SIZEOF(szOldWallpaper);
  1074. if (SHGetValue(HKEY_CURRENT_USER, REGSTR_PATH_DESKTOP, c_szWallpaper, &dwType, szOldWallpaper, &dwSize) != ERROR_SUCCESS)
  1075. szOldWallpaper[0] = TEXT('\0');
  1076. // Read the wallpaper style
  1077. DWORD dwWallpaperStyle = GetIntFromReg(HKEY_CURRENT_USER, REGSTR_PATH_DESKTOP, REG_VAL_GENERAL_TILEWALLPAPER, WPSTYLE_TILE);
  1078. TCHAR szDeskcomp[MAX_PATH];
  1079. GetRegLocation(szDeskcomp, ARRAYSIZE(szDeskcomp), REG_DESKCOMP_GENERAL, NULL);
  1080. // Set the old wallpaper into the new location.
  1081. SHSetValue(HKEY_CURRENT_USER, szDeskcomp,
  1082. c_szWallpaper, REG_SZ, (LPBYTE)szOldWallpaper, SIZEOF(szOldWallpaper));
  1083. // 98/08/14 vtan: This used to write out a REG_DWORD. It should've
  1084. // written out a REG_SZ.
  1085. TCHAR szWallpaperStyle[2];
  1086. (TCHAR*)StrCpyN(szWallpaperStyle, TEXT("0"), ARRAYSIZE(szWallpaperStyle));
  1087. szWallpaperStyle[0] += static_cast<TCHAR>(dwWallpaperStyle & WPSTYLE_MAX);
  1088. // Set the old wallpaper style into the new location.
  1089. SHSetValue(HKEY_CURRENT_USER, szDeskcomp,
  1090. REG_VAL_GENERAL_TILEWALLPAPER, REG_SZ, (LPBYTE)szWallpaperStyle, SIZEOF(szWallpaperStyle));
  1091. // 98/08/14 vtan #196226: Moved the create instance of IActiveDesktop
  1092. // to here from entry of the function. When the instance is created the
  1093. // registry information is cached in the member variable data. The
  1094. // registry information for the wallpaper is then changed behind the
  1095. // object instance and ApplyChanges() is called on STALE information.
  1096. // By deferring the object instantiation to after the registry changes
  1097. // the changes are applied correctly.
  1098. IActiveDesktop * piad;
  1099. HRESULT hres = CoCreateInstance(CLSID_ActiveDesktop, NULL, CLSCTX_INPROC_SERVER, IID_PPV_ARG(IActiveDesktop, &piad));
  1100. if (SUCCEEDED(hres))
  1101. {
  1102. piad->ApplyChanges(AD_APPLY_FORCE | AD_APPLY_HTMLGEN | AD_APPLY_REFRESH);
  1103. piad->Release();
  1104. }
  1105. }
  1106. HRESULT GetTargetFrame(IUnknown* _punkSite, BSTR bstrFrame, IWebBrowser2** ppunkTargetFrame)
  1107. {
  1108. IWebBrowser2 * pwb2;
  1109. HRESULT hr = GetTopLevelBrowser(_punkSite, &pwb2);
  1110. *ppunkTargetFrame = NULL;
  1111. if (SUCCEEDED(hr))
  1112. {
  1113. ITargetFrame2 * pOurTargetFrame;
  1114. IUnknown * punkTargetFrame = NULL;
  1115. // See if there is an existing frame with the specified target name
  1116. hr = TargetQueryService(pwb2, IID_PPV_ARG(ITargetFrame2, &pOurTargetFrame));
  1117. if (SUCCEEDED(hr))
  1118. {
  1119. hr = pOurTargetFrame->FindFrame(bstrFrame, FINDFRAME_JUSTTESTEXISTENCE, &punkTargetFrame);
  1120. if (SUCCEEDED(hr) && punkTargetFrame) // SUCCEEDED with NULL punkTargetFrame implies bstrFrame is "_blank" (since we specified FINDFRAME_JUSTTESTEXISTENCE)
  1121. {
  1122. // yes, we found a frame with that name. QI for the automation
  1123. // interface on that frame.
  1124. hr = punkTargetFrame->QueryInterface(IID_PPV_ARG(IWebBrowser2, ppunkTargetFrame));
  1125. punkTargetFrame->Release();
  1126. }
  1127. pOurTargetFrame->Release();
  1128. }
  1129. pwb2->Release();
  1130. }
  1131. return hr;
  1132. }
  1133. // NavigateAndFind
  1134. // 1. navigate the specified target frame to the specified url
  1135. // 2. set _fWaitingToFindText so that on DocumentComplete,
  1136. // mimic the find dialog and select/highlight the specified text
  1137. STDMETHODIMP CShellUIHelper::NavigateAndFind(BSTR URL, BSTR strQuery, VARIANT* varTargetFrame)
  1138. {
  1139. HRESULT hr;
  1140. IWebBrowser2 * pwb2 = NULL;
  1141. BSTR bstrFrameSrc = NULL;
  1142. if (_bstrQuery)
  1143. SysFreeString(_bstrQuery);
  1144. _bstrQuery = SysAllocString(strQuery);
  1145. hr = IsSpecialUrl(URL) ? E_FAIL: S_OK;
  1146. // Security: Don't allow javascript on one web page
  1147. // to automatically execute in the zone
  1148. // of the target frame URL.
  1149. if (SUCCEEDED(hr) && varTargetFrame && (varTargetFrame->vt == VT_BSTR) && varTargetFrame->bstrVal)
  1150. {
  1151. hr = GetTargetFrame(_punkSite, varTargetFrame->bstrVal, &pwb2); // GetTargetFrame can return NULL pwb2 on S_OK (when bstrVal is "_blank")
  1152. if (SUCCEEDED(hr) && pwb2)
  1153. {
  1154. hr = pwb2->get_LocationURL(&bstrFrameSrc);
  1155. if (SUCCEEDED(hr))
  1156. {
  1157. IHTMLDocument2 *pHtmlDoc;
  1158. if (SUCCEEDED(GetHTMLDoc2(_punkSite, &pHtmlDoc)))
  1159. {
  1160. BSTR bstrDocUrl;
  1161. if (SUCCEEDED(pHtmlDoc->get_URL(&bstrDocUrl)))
  1162. {
  1163. hr = AccessAllowed(_punkSite, bstrDocUrl, bstrFrameSrc) ? S_OK : E_ACCESSDENIED;
  1164. if(!IsSpecialUrl(URL) && hr == E_ACCESSDENIED)
  1165. {
  1166. // For non-script navigates check policy
  1167. DWORD dwPolicy = 0;
  1168. DWORD dwContext = 0;
  1169. if( SUCCEEDED(ZoneCheckUrlEx(bstrDocUrl, &dwPolicy, sizeof(dwPolicy), &dwContext,
  1170. sizeof(dwContext), URLACTION_HTML_SUBFRAME_NAVIGATE, 0, NULL)) &&
  1171. GetUrlPolicyPermissions(dwPolicy) == URLPOLICY_ALLOW)
  1172. {
  1173. hr = S_OK;
  1174. }
  1175. }
  1176. SysFreeString(bstrDocUrl);
  1177. }
  1178. pHtmlDoc->Release();
  1179. }
  1180. SysFreeString(bstrFrameSrc);
  1181. }
  1182. pwb2->Release();
  1183. pwb2 = NULL;
  1184. }
  1185. }
  1186. // Don't allow access to MyComputer zone from non-MyComputer zone.
  1187. if (SUCCEEDED(hr) && !CanNavigateToUrlWithLocalMachineCheck(_punkSite, URL))
  1188. hr = E_ACCESSDENIED;
  1189. if (SUCCEEDED(hr))
  1190. hr = GetTopLevelBrowser(_punkSite, &pwb2);
  1191. if (SUCCEEDED(hr))
  1192. {
  1193. _fWaitingToFindText = TRUE;
  1194. pwb2->Navigate(URL, PVAREMPTY, varTargetFrame, PVAREMPTY, PVAREMPTY);
  1195. pwb2->Release();
  1196. }
  1197. //script runtime error protection
  1198. return SUCCEEDED(hr) ? S_OK : S_FALSE;
  1199. }
  1200. // AutoScan
  1201. //
  1202. // Takes the search string and tries to navigate to www.%s.com, www.%s.org etc. If all of
  1203. // these fail then we navigate to pvarTargetFrame.
  1204. //
  1205. STDMETHODIMP CShellUIHelper::AutoScan
  1206. (
  1207. BSTR strSearch, // String to autoscan
  1208. BSTR strFailureUrl, // url to display is search fails
  1209. VARIANT* pvarTargetFrame // [optional] target frame
  1210. )
  1211. {
  1212. HRESULT hr = E_FAIL;
  1213. IWebBrowser2* pwb2;
  1214. // Don't bother autoscanning if there are extended characters in the search string
  1215. if (!HasExtendedChar(strSearch))
  1216. {
  1217. //first, check to see if the url is trying to spoof /1 security
  1218. hr = IsSpecialUrl(strFailureUrl) ? E_FAIL : S_OK;
  1219. if (SUCCEEDED(hr))
  1220. {
  1221. LPWSTR pszTarget = (pvarTargetFrame && pvarTargetFrame->vt == VT_BSTR && pvarTargetFrame->bstrVal) ?
  1222. pvarTargetFrame->bstrVal : L"_main";
  1223. hr = GetTargetFrame(_punkSite, pszTarget, &pwb2); // GetTargetFrame can return NULL pwb2 on S_OK (when bstrVal is "_blank")
  1224. if (!pwb2)
  1225. hr = E_FAIL;
  1226. if (SUCCEEDED(hr))
  1227. {
  1228. BSTR bstrFrameSrc = NULL;
  1229. hr = pwb2->get_LocationURL(&bstrFrameSrc);
  1230. if (SUCCEEDED(hr))
  1231. {
  1232. IHTMLDocument2 *pHtmlDoc;
  1233. if (SUCCEEDED(GetHTMLDoc2(_punkSite, &pHtmlDoc)))
  1234. {
  1235. BSTR bstrDocUrl;
  1236. if (SUCCEEDED(pHtmlDoc->get_URL(&bstrDocUrl)))
  1237. {
  1238. hr = AccessAllowed(_punkSite, bstrDocUrl, bstrFrameSrc) ? S_OK : E_ACCESSDENIED;
  1239. SysFreeString(bstrDocUrl);
  1240. }
  1241. pHtmlDoc->Release();
  1242. }
  1243. SysFreeString(bstrFrameSrc);
  1244. }
  1245. // Don't allow access to MyComputer zone from non-MyComputer zone.
  1246. if (SUCCEEDED(hr) && !CanNavigateToUrlWithLocalMachineCheck(_punkSite, strFailureUrl))
  1247. hr = E_ACCESSDENIED;
  1248. if (SUCCEEDED(hr))
  1249. {
  1250. // We don't want to navigate to strSearch. Start searching using the
  1251. // first autoscan substitution.
  1252. WCHAR szFormat[MAX_PATH];
  1253. WCHAR szUrl[MAX_URL_STRING];
  1254. if (GetSearchFormatString(1, szFormat, sizeof(szFormat)) != ERROR_SUCCESS)
  1255. {
  1256. hr = E_FAIL;
  1257. }
  1258. else
  1259. {
  1260. wnsprintf(szUrl, ARRAYSIZE(szUrl), szFormat, strSearch);
  1261. BSTRBLOB bstrBlob;
  1262. bstrBlob.cbSize = lstrlenW(szUrl) * sizeof(WCHAR);
  1263. bstrBlob.pData = (BYTE*)szUrl;
  1264. BSTR bstrUrl = (BSTR)bstrBlob.pData;
  1265. // Save the original search string for autoscanning. Normally
  1266. // this come from the addressbar, but in our case we store it as
  1267. // a property
  1268. VARIANT v;
  1269. VariantInit (&v);
  1270. v.vt = VT_BSTR;
  1271. v.bstrVal = strSearch;
  1272. pwb2->PutProperty((BSTR)s_sstrSearch.wsz, v);
  1273. // Save the error page in case the scan fails
  1274. v.vt = VT_BSTR;
  1275. v.bstrVal = strFailureUrl;
  1276. pwb2->PutProperty((BSTR)s_sstrFailureUrl.wsz, v);
  1277. // Navigate with autosearch enabled
  1278. VARIANT vFlags;
  1279. vFlags.vt = VT_I4;
  1280. vFlags.lVal = navAllowAutosearch;
  1281. pwb2->Navigate(bstrUrl, &vFlags, pvarTargetFrame, PVAREMPTY, PVAREMPTY);
  1282. }
  1283. }
  1284. pwb2->Release();
  1285. }
  1286. }
  1287. }
  1288. //script runtime error protection
  1289. return SUCCEEDED(hr) ? S_OK : S_FALSE;
  1290. }
  1291. typedef HRESULT (*PFNSHOWBROWSERUI)(IUnknown *punkSite, HWND hwnd, VARIANT *pvarIn, VARIANT *pvarOut);
  1292. typedef void (*PFNOPENLANGUAGEDIALOG)(HWND hwnd, HINSTANCE hinst, LPSTR lpszCmdLine, int nCmdShow);
  1293. HRESULT ShowLanguageDialog(IUnknown *punkSite, HWND hwnd, VARIANT *pvarIn, VARIANT *pvarOut)
  1294. {
  1295. HRESULT hr = E_FAIL;
  1296. HINSTANCE hInstInetcpl = LoadLibrary(TEXT("inetcpl.cpl"));
  1297. if (hInstInetcpl)
  1298. {
  1299. PFNOPENLANGUAGEDIALOG pfnOpenLanguageDialog =
  1300. (PFNOPENLANGUAGEDIALOG)GetProcAddress( hInstInetcpl, "OpenLanguageDialog" );
  1301. if (pfnOpenLanguageDialog)
  1302. {
  1303. pfnOpenLanguageDialog(hwnd, NULL, NULL, SW_SHOW);
  1304. hr = S_OK;
  1305. }
  1306. FreeLibrary(hInstInetcpl);
  1307. }
  1308. return hr;
  1309. }
  1310. HRESULT ShowOrganizeFavorites(IUnknown *punkSite, HWND hwnd, VARIANT *pvarIn, VARIANT *pvarOut)
  1311. {
  1312. return DoOrganizeFavDlgW(hwnd, NULL) ? S_OK : E_FAIL;
  1313. }
  1314. HRESULT ShowPrivacySettings(IUnknown *punkSite, HWND hwnd, VARIANT *pvarIn, VARIANT *pvarOut)
  1315. {
  1316. LaunchPrivacySettings(hwnd);
  1317. return S_OK;
  1318. }
  1319. HRESULT ShowProgramAccessAndDefaults(IUnknown *punkSite, HWND hwnd, VARIANT *pvarIn, VARIANT *pvarOut)
  1320. {
  1321. HRESULT hr;
  1322. const WCHAR c_szControlExe[] = L"control.exe";
  1323. WCHAR szControlPath[MAX_PATH];
  1324. UINT nLen = GetSystemDirectory(szControlPath, ARRAYSIZE(szControlPath));
  1325. // This accounts for needing a backslash after the sysdir
  1326. if ((nLen + ARRAYSIZE(c_szControlExe)) < ARRAYSIZE(szControlPath))
  1327. {
  1328. PathAppend(szControlPath, c_szControlExe);
  1329. HINSTANCE hInst = ShellExecute(NULL, NULL, szControlPath, L"appwiz.cpl,,3", NULL, SW_SHOWNORMAL);
  1330. if (hInst > (HINSTANCE)HINSTANCE_ERROR)
  1331. {
  1332. hr = S_OK;
  1333. }
  1334. else
  1335. {
  1336. hr = HRESULT_FROM_WIN32(PtrToInt(hInst));
  1337. }
  1338. }
  1339. else
  1340. {
  1341. hr = E_OUTOFMEMORY;
  1342. }
  1343. return hr;
  1344. }
  1345. struct BROWSERUI_MAP
  1346. {
  1347. LPWSTR pwszName;
  1348. PFNSHOWBROWSERUI pfnShowBrowserUI;
  1349. };
  1350. const BROWSERUI_MAP s_browserUIMap[] =
  1351. {
  1352. { L"LanguageDialog", ShowLanguageDialog },
  1353. { L"OrganizeFavorites", ShowOrganizeFavorites },
  1354. { L"PrivacySettings", ShowPrivacySettings },
  1355. { L"ProgramAccessAndDefaults", ShowProgramAccessAndDefaults }
  1356. };
  1357. STDMETHODIMP CShellUIHelper::ShowBrowserUI(BSTR bstrName, VARIANT *pvarIn, VARIANT *pvarOut)
  1358. {
  1359. HRESULT hr = E_FAIL;
  1360. for (int i = 0; i < ARRAYSIZE(s_browserUIMap); i++)
  1361. {
  1362. if (pvarOut)
  1363. {
  1364. VariantInit(pvarOut);
  1365. }
  1366. if (0 == StrCmpIW(s_browserUIMap[i].pwszName, bstrName))
  1367. {
  1368. hr = s_browserUIMap[i].pfnShowBrowserUI(_punkSite, _GetOwnerWindow(), pvarIn, pvarOut);
  1369. }
  1370. }
  1371. return S_OK == hr ? S_OK : S_FALSE;
  1372. }
  1373. // the find dialog does the following:
  1374. //
  1375. // rng = document.body.createTextRange();
  1376. // if (rng.findText("Find this text"))
  1377. // rng.select();
  1378. STDMETHODIMP CShellUIHelper::_DoFindOnPage(IDispatch* pdisp)
  1379. {
  1380. HRESULT hr;
  1381. IWebBrowser2* pwb2;
  1382. IDispatch* pdispDocument;
  1383. IHTMLDocument2* pDocument;
  1384. IHTMLElement* pBody;
  1385. IHTMLBodyElement* pBodyElement;
  1386. IHTMLTxtRange* pRange;
  1387. ASSERT(pdisp);
  1388. if (!pdisp)
  1389. return E_FAIL;
  1390. hr = pdisp->QueryInterface(IID_PPV_ARG(IWebBrowser2, &pwb2));
  1391. if (SUCCEEDED(hr))
  1392. {
  1393. hr = pwb2->get_Document(&pdispDocument);
  1394. if (SUCCEEDED(hr) && (NULL != pdispDocument))
  1395. {
  1396. hr = pdispDocument->QueryInterface(IID_PPV_ARG(IHTMLDocument2, &pDocument));
  1397. if (SUCCEEDED(hr))
  1398. {
  1399. hr = pDocument->get_body(&pBody);
  1400. if (SUCCEEDED(hr) && (NULL != pBody))
  1401. {
  1402. hr = pBody->QueryInterface(IID_PPV_ARG(IHTMLBodyElement, &pBodyElement));
  1403. if (SUCCEEDED(hr))
  1404. {
  1405. hr = pBodyElement->createTextRange(&pRange);
  1406. if (SUCCEEDED(hr) && (NULL != pRange))
  1407. {
  1408. VARIANT_BOOL vbfFoundText;
  1409. hr = pRange->findText(_bstrQuery, 1000000, 0, &vbfFoundText);
  1410. if (SUCCEEDED(hr) && (vbfFoundText == VARIANT_TRUE))
  1411. {
  1412. hr = pRange->select();
  1413. }
  1414. pRange->Release();
  1415. }
  1416. pBodyElement->Release();
  1417. }
  1418. pBody->Release();
  1419. }
  1420. pDocument->Release();
  1421. }
  1422. pdispDocument->Release();
  1423. }
  1424. pwb2->Release();
  1425. }
  1426. return hr;
  1427. }
  1428. //
  1429. // Launch the favorites import/export wizard
  1430. //
  1431. STDMETHODIMP CShellUIHelper::ImportExportFavorites(VARIANT_BOOL fImport, BSTR strImpExpPath)
  1432. {
  1433. //don't allow to import/export to folders other than Favorites from OM
  1434. DoImportOrExport(fImport==VARIANT_TRUE, NULL, (LPCWSTR)strImpExpPath, TRUE);
  1435. return S_OK;
  1436. }
  1437. //
  1438. // Save the form data via intelliforms
  1439. //
  1440. STDMETHODIMP CShellUIHelper::AutoCompleteSaveForm(VARIANT *Form)
  1441. {
  1442. HRESULT hrRet = S_FALSE;
  1443. IHTMLDocument2 *pDoc2=NULL;
  1444. GetHTMLDoc2(_punkSite, &pDoc2);
  1445. if (pDoc2)
  1446. {
  1447. hrRet = IntelliFormsSaveForm(pDoc2, Form);
  1448. pDoc2->Release();
  1449. }
  1450. return hrRet;
  1451. }
  1452. //
  1453. // Attach intelliforms to this document
  1454. //
  1455. STDMETHODIMP CShellUIHelper::AutoCompleteAttach(VARIANT *Reserved)
  1456. {
  1457. HRESULT hr=E_FAIL;
  1458. if (_pvIntelliForms == NULL)
  1459. {
  1460. IHTMLDocument2 *pDoc2=NULL;
  1461. GetHTMLDoc2(_punkSite, &pDoc2);
  1462. if (pDoc2)
  1463. {
  1464. hr = S_OK;
  1465. AttachIntelliForms(NULL, _GetOwnerWindow(), pDoc2, &_pvIntelliForms);
  1466. pDoc2->Release();
  1467. }
  1468. }
  1469. return SUCCEEDED(hr) ? S_OK : S_FALSE;
  1470. }