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.

1831 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_IServiceProvider, (void**)&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. STDAPI GetHTMLDoc2(IUnknown *punk, IHTMLDocument2 **ppHtmlDoc)
  537. {
  538. *ppHtmlDoc = NULL;
  539. if (!punk)
  540. return E_FAIL;
  541. *ppHtmlDoc = NULL;
  542. // The window.external, jscript "new ActiveXObject" and the <OBJECT> tag
  543. // don't take us down the same road.
  544. IOleClientSite *pClientSite;
  545. HRESULT hr = punk->QueryInterface(IID_PPV_ARG(IOleClientSite, &pClientSite));
  546. if (SUCCEEDED(hr))
  547. {
  548. // <OBJECT> tag path
  549. IOleContainer *pContainer;
  550. hr = pClientSite->GetContainer(&pContainer);
  551. if (SUCCEEDED(hr))
  552. {
  553. hr = pContainer->QueryInterface(IID_PPV_ARG(IHTMLDocument2, ppHtmlDoc));
  554. pContainer->Release();
  555. }
  556. if (FAILED(hr))
  557. {
  558. // window.external path
  559. IWebBrowser2 *pWebBrowser2;
  560. hr = IUnknown_QueryService(pClientSite, SID_SWebBrowserApp, IID_PPV_ARG(IWebBrowser2, &pWebBrowser2));
  561. if (SUCCEEDED(hr))
  562. {
  563. IDispatch *pDispatch;
  564. hr = pWebBrowser2->get_Document(&pDispatch);
  565. if (SUCCEEDED(hr))
  566. {
  567. hr = pDispatch->QueryInterface(IID_PPV_ARG(IHTMLDocument2, ppHtmlDoc));
  568. pDispatch->Release();
  569. }
  570. pWebBrowser2->Release();
  571. }
  572. }
  573. pClientSite->Release();
  574. }
  575. else
  576. {
  577. // jscript path
  578. hr = IUnknown_QueryService(punk, SID_SContainerDispatch, IID_PPV_ARG(IHTMLDocument2, ppHtmlDoc));
  579. }
  580. ASSERT(FAILED(hr) || (*ppHtmlDoc));
  581. return hr;
  582. }
  583. // A lot like GetHTMLDoc2, but only cares about window.external
  584. STDMETHODIMP GetTopLevelBrowser(IUnknown *punk, IWebBrowser2 **ppwb2)
  585. {
  586. return IUnknown_QueryService(punk, SID_SWebBrowserApp, IID_PPV_ARG(IWebBrowser2, ppwb2));
  587. }
  588. STDMETHODIMP ZoneCheck(IUnknown *punkSite, BSTR bstrReqUrl)
  589. {
  590. HRESULT hr = E_ACCESSDENIED;
  591. // Return S_FALSE if we don't have a host site since we have no way of doing a
  592. // security check. This is as far as VB 5.0 apps get.
  593. if (!punkSite)
  594. return S_FALSE;
  595. // 1) Get an IHTMLDocument2 pointer
  596. // 2) Get URL from doc
  597. // 3) Create security manager
  598. // 4) Check if doc URL zone is local, if so everything's S_OK
  599. // 5) Otherwise, get and compare doc URL SID to requested URL SID
  600. IHTMLDocument2 *pHtmlDoc;
  601. if (SUCCEEDED(GetHTMLDoc2(punkSite, &pHtmlDoc)))
  602. {
  603. ASSERT(pHtmlDoc);
  604. BSTR bstrDocUrl;
  605. if (SUCCEEDED(pHtmlDoc->get_URL(&bstrDocUrl)))
  606. {
  607. ASSERT(bstrDocUrl);
  608. IInternetSecurityManager *pSecMgr;
  609. if (SUCCEEDED(CoCreateInstance(CLSID_InternetSecurityManager,
  610. NULL,
  611. CLSCTX_INPROC_SERVER,
  612. IID_IInternetSecurityManager,
  613. (void **)&pSecMgr)))
  614. {
  615. ASSERT(pSecMgr);
  616. DWORD dwZoneID = URLZONE_UNTRUSTED;
  617. if (SUCCEEDED(pSecMgr->MapUrlToZone(bstrDocUrl, &dwZoneID, 0)))
  618. {
  619. if (dwZoneID == URLZONE_LOCAL_MACHINE)
  620. hr = S_OK;
  621. }
  622. if (hr != S_OK && bstrReqUrl)
  623. {
  624. BYTE reqSid[MAX_SIZE_SECURITY_ID], docSid[MAX_SIZE_SECURITY_ID];
  625. DWORD cbReqSid = ARRAYSIZE(reqSid);
  626. DWORD cbDocSid = ARRAYSIZE(docSid);
  627. if ( SUCCEEDED(pSecMgr->GetSecurityId(bstrReqUrl, reqSid, &cbReqSid, 0))
  628. && SUCCEEDED(pSecMgr->GetSecurityId(bstrDocUrl, docSid, &cbDocSid, 0))
  629. && (cbReqSid == cbDocSid)
  630. && (memcmp(reqSid, docSid, cbReqSid) == 0))
  631. {
  632. hr = S_OK;
  633. }
  634. }
  635. pSecMgr->Release();
  636. }
  637. SysFreeString(bstrDocUrl);
  638. }
  639. pHtmlDoc->Release();
  640. }
  641. else
  642. {
  643. // If we don't have an IHTMLDocument2 we aren't running in a browser that supports
  644. // our OM. We shouldn't block in this case since we could potentially
  645. // get here from other hosts (VB, WHS, etc.).
  646. hr = S_FALSE;
  647. }
  648. return hr;
  649. }
  650. // This function checks to see if a navigation is happening from either internet
  651. // or restricted url to LOCAL_MACHINE.
  652. BOOL CanNavigateToUrlWithLocalMachineCheck(IUnknown *punkSite, BSTR pchurltarget)
  653. {
  654. BOOL bCanNavigate = FALSE;
  655. // Get the DochostUI flags for the site.
  656. IDocHostUIHandler *pIDocHostUI;
  657. if (SUCCEEDED(punkSite->QueryInterface(IID_PPV_ARG(IDocHostUIHandler, &pIDocHostUI))))
  658. {
  659. DOCHOSTUIINFO dhInfo;
  660. if (SUCCEEDED(pIDocHostUI->GetHostInfo(&dhInfo)))
  661. {
  662. if (!(dhInfo.dwFlags & DOCHOSTUIFLAG_LOCAL_MACHINE_ACCESS_CHECK))
  663. bCanNavigate = TRUE;
  664. }
  665. pIDocHostUI->Release();
  666. }
  667. // If the DOCHOSTUIFLAG_LOCAL_MACHINE_ACCESS_CHECK is set or if we failed to
  668. // get the flags, do a check to see if the zone is elevated to local machine.
  669. if (!bCanNavigate)
  670. {
  671. // Get the site's url.
  672. IHTMLDocument2 *pHtmlDoc;
  673. if (SUCCEEDED(GetHTMLDoc2(punkSite, &pHtmlDoc)))
  674. {
  675. BSTR pchurlsource;
  676. if (SUCCEEDED(pHtmlDoc->get_URL(&pchurlsource)))
  677. {
  678. IInternetSecurityManager *pSecMgr;
  679. if (SUCCEEDED(IUnknown_QueryService(punkSite, SID_SInternetSecurityManager,
  680. IID_PPV_ARG(IInternetSecurityManager, &pSecMgr))) ||
  681. SUCCEEDED(CoCreateInstance(CLSID_InternetSecurityManager, NULL, CLSCTX_INPROC_SERVER,
  682. IID_PPV_ARG(IInternetSecurityManager, &pSecMgr))))
  683. {
  684. DWORD dwZoneIDSource = URLZONE_UNTRUSTED;
  685. DWORD dwZoneIDTarget = URLZONE_LOCAL_MACHINE;
  686. DWORD dwFlags = PUAF_DEFAULT;
  687. // Get zone of the source url.
  688. if (!pchurlsource || IsSpecialUrl(pchurlsource))
  689. {
  690. // Treat special Urls as restricted.
  691. dwZoneIDSource = URLZONE_UNTRUSTED;
  692. }
  693. else if (!SUCCEEDED(pSecMgr->MapUrlToZone(pchurlsource, &dwZoneIDSource, 0)))
  694. {
  695. // If MapUrlToZone fails, treat the url as restricted.
  696. dwZoneIDSource = URLZONE_UNTRUSTED;
  697. }
  698. // Get zone of the target url
  699. if (!SUCCEEDED(pSecMgr->MapUrlToZone(pchurltarget, &dwZoneIDTarget, 0)))
  700. {
  701. // If MapUrlToZone fails, treat the url as MyComputer. This is safe.
  702. dwZoneIDTarget = URLZONE_LOCAL_MACHINE;
  703. }
  704. // Check if there is a zone elevation.
  705. if ((dwZoneIDSource != URLZONE_INTERNET &&
  706. dwZoneIDSource != URLZONE_UNTRUSTED) ||
  707. dwZoneIDTarget != URLZONE_LOCAL_MACHINE)
  708. {
  709. // There is no zone elevation.
  710. bCanNavigate = TRUE;
  711. }
  712. pSecMgr->Release();
  713. }
  714. SysFreeString(pchurlsource);
  715. }
  716. pHtmlDoc->Release();
  717. }
  718. }
  719. return bCanNavigate;
  720. }
  721. STDMETHODIMP CShellUIHelper::IsSubscribed(BSTR bstrURL, VARIANT_BOOL* pBool)
  722. {
  723. HRESULT hr;
  724. if (!bstrURL || !pBool)
  725. {
  726. return E_INVALIDARG;
  727. }
  728. hr = ZoneCheck(_punkSite, bstrURL);
  729. if (SUCCEEDED(hr))
  730. {
  731. ISubscriptionMgr *pSubscriptionMgr;
  732. hr = CoCreateInstance(CLSID_SubscriptionMgr, NULL, CLSCTX_INPROC_SERVER,
  733. IID_ISubscriptionMgr, (void**)&pSubscriptionMgr);
  734. if (SUCCEEDED(hr))
  735. {
  736. ASSERT(pSubscriptionMgr);
  737. BOOL tmpBool;
  738. hr = pSubscriptionMgr->IsSubscribed(bstrURL, &tmpBool);
  739. *pBool = tmpBool ? VARIANT_TRUE : VARIANT_FALSE;
  740. pSubscriptionMgr->Release();
  741. }
  742. }
  743. return hr;
  744. }
  745. /****************************************************************************
  746. *
  747. * AddDesktopComponentA - Adds a component to the desktop
  748. *
  749. * ENTRY:
  750. * hwnd - the parent for all UI
  751. * pszUrlA - the URL of the component
  752. * iCompType - one of COMP_TYPE_*
  753. * iLeft, iTop, iWidth, iHeight - dimensions of the component
  754. * dwFlags - additional flags
  755. *
  756. * RETURNS:
  757. * TRUE on success
  758. *
  759. ****************************************************************************/
  760. BOOL AddDesktopComponentW(HWND hwnd, LPCWSTR pszUrl, int iCompType,
  761. int iLeft, int iTop, int iWidth, int iHeight,
  762. DWORD dwFlags)
  763. {
  764. COMPONENT Comp;
  765. BOOL fRet = FALSE;
  766. HRESULT hres;
  767. Comp.dwSize = sizeof(Comp);
  768. //
  769. // Build the pcomp structure.
  770. //
  771. Comp.dwID = -1;
  772. Comp.iComponentType = iCompType;
  773. Comp.fChecked = TRUE;
  774. Comp.fDirty = FALSE;
  775. Comp.fNoScroll = FALSE;
  776. Comp.dwSize = SIZEOF(Comp);
  777. Comp.cpPos.dwSize = SIZEOF(COMPPOS);
  778. Comp.cpPos.iLeft = iLeft;
  779. Comp.cpPos.iTop = iTop;
  780. Comp.cpPos.dwWidth = iWidth;
  781. Comp.cpPos.dwHeight = iHeight;
  782. Comp.cpPos.izIndex = COMPONENT_TOP;
  783. Comp.cpPos.fCanResize = TRUE;
  784. Comp.cpPos.fCanResizeX = TRUE;
  785. Comp.cpPos.fCanResizeY = TRUE;
  786. Comp.cpPos.iPreferredLeftPercent = 0;
  787. Comp.cpPos.iPreferredTopPercent = 0;
  788. StrCpyNW(Comp.wszSource, pszUrl, ARRAYSIZE(Comp.wszSource));
  789. StrCpyNW(Comp.wszSubscribedURL, pszUrl, ARRAYSIZE(Comp.wszSource));
  790. StrCpyNW(Comp.wszFriendlyName, pszUrl, ARRAYSIZE(Comp.wszFriendlyName));
  791. Comp.dwCurItemState = IS_NORMAL;
  792. IActiveDesktop * piad;
  793. //
  794. // Add it to the system.
  795. //
  796. hres = CoCreateInstance(CLSID_ActiveDesktop, NULL, CLSCTX_INPROC_SERVER, IID_IActiveDesktop, (LPVOID*)&piad);
  797. if (SUCCEEDED(hres))
  798. {
  799. dwFlags |= DTI_ADDUI_POSITIONITEM;
  800. piad->AddDesktopItemWithUI(hwnd, &Comp, dwFlags);
  801. piad->Release();
  802. fRet = TRUE;
  803. }
  804. return fRet;
  805. }
  806. //------------------------------------------------------------------------
  807. STDMETHODIMP CShellUIHelper::AddDesktopComponent(BSTR strURL, BSTR strType,
  808. /* [optional, in] */ VARIANT *Left,
  809. /* [optional, in] */ VARIANT *Top,
  810. /* [optional, in] */ VARIANT *Width,
  811. /* [optional, in] */ VARIANT *Height)
  812. {
  813. #ifndef DISABLE_ACTIVEDESKTOP_FOR_UNIX
  814. HRESULT hres;
  815. int iType;
  816. if (StrCmpIW(strType, L"image")==0)
  817. {
  818. iType = COMP_TYPE_PICTURE;
  819. }
  820. else if (StrCmpIW(strType, L"website")==0)
  821. {
  822. iType = COMP_TYPE_WEBSITE;
  823. }
  824. else
  825. {
  826. iType = 0;
  827. }
  828. if (iType)
  829. {
  830. AddDesktopComponentW(_GetOwnerWindow(), strURL, iType,
  831. OptionalVariantToInt(Left, -1),
  832. OptionalVariantToInt(Top, -1),
  833. OptionalVariantToInt(Width, -1),
  834. OptionalVariantToInt(Height, -1),
  835. DTI_ADDUI_DISPSUBWIZARD);
  836. hres = S_OK;
  837. }
  838. else
  839. {
  840. hres = E_INVALIDARG;
  841. }
  842. return hres;
  843. #else // #ifndef DISABLE_ACTIVEDESKTOP_FOR_UNIX
  844. return E_INVALIDARG;
  845. #endif // #ifndef DISABLE_ACTIVEDESKTOP_FOR_UNIX
  846. }
  847. void RemoveDefaultWallpaper();
  848. STDMETHODIMP CShellUIHelper::ResetFirstBootMode()
  849. {
  850. #ifndef DISABLE_ACTIVEDESKTOP_FOR_UNIX
  851. if (MLShellMessageBox(
  852. _GetOwnerWindow(),
  853. MAKEINTRESOURCE(IDS_CONFIRM_RESETFLAG),
  854. MAKEINTRESOURCE(IDS_TITLE),
  855. MB_YESNO | MB_ICONQUESTION) == IDYES)
  856. {
  857. RemoveDefaultWallpaper();
  858. return S_OK;
  859. }
  860. #endif // #ifndef DISABLE_ACTIVEDESKTOP_FOR_UNIX
  861. return S_FALSE;
  862. }
  863. // Little helper function used to change the safemode state
  864. void SetSafeMode(DWORD dwFlags)
  865. {
  866. IActiveDesktopP * piadp;
  867. HRESULT hres = CoCreateInstance(CLSID_ActiveDesktop, NULL, CLSCTX_INPROC_SERVER, IID_IActiveDesktopP, (LPVOID*)&piadp);
  868. if (SUCCEEDED(hres))
  869. {
  870. piadp->SetSafeMode(dwFlags);
  871. piadp->Release();
  872. }
  873. }
  874. STDMETHODIMP CShellUIHelper::ResetSafeMode()
  875. {
  876. #ifndef DISABLE_ACTIVEDESKTOP_FOR_UNIX
  877. if ((ZoneCheck(_punkSite, NULL) == S_OK) || (MLShellMessageBox(
  878. _GetOwnerWindow(),
  879. MAKEINTRESOURCE(IDS_CONFIRM_RESET_SAFEMODE),
  880. MAKEINTRESOURCE(IDS_TITLE),
  881. MB_YESNO | MB_ICONQUESTION) == IDYES))
  882. {
  883. SetSafeMode(SSM_CLEAR | SSM_REFRESH);
  884. return S_OK;
  885. }
  886. #endif // #ifndef DISABLE_ACTIVEDESKTOP_FOR_UNIX
  887. return S_FALSE;
  888. }
  889. STDMETHODIMP CShellUIHelper::RefreshOfflineDesktop()
  890. {
  891. #ifndef DISABLE_ACTIVEDESKTOP_FOR_UNIX
  892. IADesktopP2 * piad;
  893. HRESULT hres = CoCreateInstance(CLSID_ActiveDesktop, NULL, CLSCTX_INPROC_SERVER, IID_IADesktopP2, (LPVOID*)&piad);
  894. if (SUCCEEDED(hres))
  895. {
  896. piad->UpdateAllDesktopSubscriptions();
  897. piad->Release();
  898. }
  899. #endif // #ifndef DISABLE_ACTIVEDESKTOP_FOR_UNIX
  900. return S_OK;
  901. }
  902. STDMETHODIMP CShellUIHelper::GetTypeInfoCount(UINT * pctinfo)
  903. {
  904. return E_NOTIMPL;
  905. }
  906. STDMETHODIMP CShellUIHelper::GetTypeInfo(UINT itinfo, LCID lcid, ITypeInfo **pptinfo)
  907. {
  908. return E_NOTIMPL;
  909. }
  910. STDMETHODIMP CShellUIHelper::GetIDsOfNames(REFIID riid, OLECHAR **rgszNames,
  911. UINT cNames, LCID lcid, DISPID * rgdispid)
  912. {
  913. HRESULT hr = E_FAIL;
  914. // First let our host get a crack at this method
  915. IDispatch *pDisp = GetExternalDispatch();
  916. if (pDisp)
  917. {
  918. hr = pDisp->GetIDsOfNames(riid, rgszNames, cNames, lcid, rgdispid);
  919. if (SUCCEEDED(hr))
  920. {
  921. if (rgdispid[0] > 0)
  922. {
  923. // Offset there dispid
  924. rgdispid[0] += DISPID_SHELLUIHELPERLAST;
  925. }
  926. }
  927. }
  928. if (FAILED(hr))
  929. {
  930. // Our host didn't support it so we'll see if it's one of ours.
  931. hr = CImpIDispatch::GetIDsOfNames(riid, rgszNames, cNames, lcid, rgdispid);
  932. }
  933. return hr;
  934. }
  935. HRESULT CShellUIHelper::Invoke(DISPID dispidMember, REFIID riid, LCID lcid, WORD wFlags,
  936. DISPPARAMS *pdispparams, VARIANT * pvarResult, EXCEPINFO *pexcepinfo, UINT *puArgErr)
  937. {
  938. HRESULT hr = DISP_E_MEMBERNOTFOUND;
  939. if ((dispidMember > 0) && (dispidMember <= DISPID_SHELLUIHELPERLAST))
  940. {
  941. hr = CImpIDispatch::Invoke(dispidMember, riid, lcid, wFlags, pdispparams,
  942. pvarResult, pexcepinfo, puArgErr);
  943. }
  944. else if (_fWaitingToFindText && (dispidMember == DISPID_DOCUMENTCOMPLETE))
  945. {
  946. ASSERT(pdispparams->rgvarg[1].vt == VT_DISPATCH);
  947. _fWaitingToFindText = FALSE;
  948. hr = _DoFindOnPage(pdispparams->rgvarg[1].pdispVal);
  949. }
  950. else
  951. {
  952. IDispatch *pDisp = GetExternalDispatch();
  953. if (pDisp)
  954. {
  955. if (dispidMember > 0)
  956. {
  957. // Fixup the offset we added in GetIDsOfNames
  958. dispidMember -= DISPID_SHELLUIHELPERLAST;
  959. }
  960. hr = pDisp->Invoke(dispidMember, riid, lcid, wFlags, pdispparams,
  961. pvarResult, pexcepinfo, puArgErr);
  962. }
  963. }
  964. return hr;
  965. }
  966. STDMETHODIMP CShellUIHelper::GetDispID(BSTR bstrName, DWORD grfdex, DISPID *pid)
  967. {
  968. HRESULT hr = E_FAIL;
  969. LCID lcid = GetSystemDefaultLCID();
  970. // First let our host get a crack at this method via IDispatchEx or IDispatch
  971. if (_pExternalDispEx)
  972. {
  973. hr = _pExternalDispEx->GetDispID(bstrName, grfdex, pid);
  974. }
  975. else if (_pExternalDisp)
  976. {
  977. hr = _pExternalDisp->GetIDsOfNames(IID_NULL, &bstrName, 1, lcid, pid);
  978. }
  979. if (SUCCEEDED(hr))
  980. {
  981. if (*pid > 0)
  982. {
  983. *pid += DISPID_SHELLUIHELPERLAST;
  984. }
  985. }
  986. else
  987. {
  988. // Our host didn't support it so we'll see if it's one of ours.
  989. hr = CImpIDispatch::GetIDsOfNames(IID_NULL, &bstrName, 1, lcid, pid);
  990. }
  991. return hr;
  992. }
  993. STDMETHODIMP CShellUIHelper::InvokeEx(DISPID id, LCID lcid, WORD wFlags, DISPPARAMS *pdp,
  994. VARIANT *pvarRes, EXCEPINFO *pei,
  995. IServiceProvider *pspCaller)
  996. {
  997. HRESULT hr = DISP_E_MEMBERNOTFOUND;
  998. UINT ArgErr; // inetsdk says this isn't used here
  999. // First see if it's ours
  1000. if ((id > 0) && (id <= DISPID_SHELLUIHELPERLAST))
  1001. {
  1002. hr = CImpIDispatch::Invoke(id, IID_NULL, lcid, wFlags, pdp,
  1003. pvarRes, pei, &ArgErr);
  1004. }
  1005. else
  1006. {
  1007. if (id > 0)
  1008. {
  1009. id -= DISPID_SHELLUIHELPERLAST;
  1010. }
  1011. // otherwise try external IDispatchEx
  1012. if (_pExternalDispEx)
  1013. {
  1014. hr = _pExternalDispEx->InvokeEx(id, lcid, wFlags, pdp, pvarRes, pei, pspCaller);
  1015. }
  1016. // finally try the external IDispatch
  1017. else if (_pExternalDisp)
  1018. {
  1019. hr = _pExternalDisp->Invoke(id, IID_NULL, lcid, wFlags, pdp,
  1020. pvarRes, pei, &ArgErr);
  1021. }
  1022. }
  1023. return hr;
  1024. }
  1025. STDMETHODIMP CShellUIHelper::DeleteMemberByName(BSTR bstr, DWORD grfdex)
  1026. {
  1027. HRESULT hr = E_NOTIMPL;
  1028. if (_pExternalDispEx)
  1029. {
  1030. hr = _pExternalDispEx->DeleteMemberByName(bstr, grfdex);
  1031. }
  1032. return hr;
  1033. }
  1034. STDMETHODIMP CShellUIHelper::DeleteMemberByDispID(DISPID id)
  1035. {
  1036. HRESULT hr = E_NOTIMPL;
  1037. if (_pExternalDispEx)
  1038. {
  1039. hr = _pExternalDispEx->DeleteMemberByDispID(id);
  1040. }
  1041. return hr;
  1042. }
  1043. STDMETHODIMP CShellUIHelper::GetMemberProperties(DISPID id, DWORD grfdexFetch, DWORD *pgrfdex)
  1044. {
  1045. HRESULT hr = E_NOTIMPL;
  1046. if (_pExternalDispEx)
  1047. {
  1048. hr = _pExternalDispEx->GetMemberProperties(id, grfdexFetch, pgrfdex);
  1049. }
  1050. return hr;
  1051. }
  1052. STDMETHODIMP CShellUIHelper::GetMemberName(DISPID id, BSTR *pbstrName)
  1053. {
  1054. HRESULT hr = E_NOTIMPL;
  1055. if (_pExternalDispEx)
  1056. {
  1057. hr = _pExternalDispEx->GetMemberName(id, pbstrName);
  1058. }
  1059. return hr;
  1060. }
  1061. STDMETHODIMP CShellUIHelper::GetNextDispID(DWORD grfdex, DISPID id, DISPID *pid)
  1062. {
  1063. HRESULT hr = E_NOTIMPL;
  1064. if (_pExternalDispEx)
  1065. {
  1066. hr = _pExternalDispEx->GetNextDispID(grfdex, id, pid);
  1067. }
  1068. return hr;
  1069. }
  1070. STDMETHODIMP CShellUIHelper::GetNameSpaceParent(IUnknown **ppunk)
  1071. {
  1072. HRESULT hr = E_NOTIMPL;
  1073. if (_pExternalDispEx)
  1074. {
  1075. hr = _pExternalDispEx->GetNameSpaceParent(ppunk);
  1076. }
  1077. return hr;
  1078. }
  1079. int GetIntFromReg(HKEY hKey,
  1080. LPCTSTR lpszSubkey,
  1081. LPCTSTR lpszNameValue,
  1082. int iDefault)
  1083. {
  1084. TCHAR szValue[20];
  1085. DWORD dwSizeofValueBuff = SIZEOF(szValue);
  1086. int iRetValue = iDefault;
  1087. DWORD dwType;
  1088. if ((SHGetValue(hKey, lpszSubkey, lpszNameValue, &dwType,(LPBYTE)szValue,
  1089. &dwSizeofValueBuff) == ERROR_SUCCESS) && dwSizeofValueBuff)
  1090. {
  1091. if (dwType == REG_SZ)
  1092. {
  1093. iRetValue = (int)StrToInt(szValue);
  1094. }
  1095. }
  1096. return iRetValue;
  1097. }
  1098. void GetRegLocation(LPTSTR lpszResult, DWORD cchResult, LPCTSTR lpszKey, LPCTSTR lpszScheme)
  1099. {
  1100. TCHAR szSubkey[MAX_PATH];
  1101. DWORD dwDataLength = sizeof(szSubkey) - 2 * sizeof(TCHAR);
  1102. DWORD dwType;
  1103. StrCpyN(szSubkey, TEXT("\\"), ARRAYSIZE(szSubkey));
  1104. if (lpszScheme)
  1105. StrCatBuff(szSubkey, lpszScheme, ARRAYSIZE(szSubkey));
  1106. else
  1107. SHGetValue(HKEY_CURRENT_USER, REG_DESKCOMP_SCHEME, REG_VAL_SCHEME_DISPLAY, &dwType,
  1108. (LPBYTE)(szSubkey) + sizeof(TCHAR), &dwDataLength);
  1109. if (szSubkey[1])
  1110. StrCatBuff(szSubkey, TEXT("\\"), ARRAYSIZE(szSubkey));
  1111. wnsprintf(lpszResult, cchResult, lpszKey, szSubkey);
  1112. }
  1113. #define c_szWallpaper REG_VAL_GENERAL_WALLPAPER
  1114. void RemoveDefaultWallpaper()
  1115. {
  1116. // Read the Wallpaper from the Old location.
  1117. TCHAR szOldWallpaper[MAX_PATH];
  1118. DWORD dwType;
  1119. DWORD dwSize = SIZEOF(szOldWallpaper);
  1120. if (SHGetValue(HKEY_CURRENT_USER, REGSTR_PATH_DESKTOP, c_szWallpaper, &dwType, szOldWallpaper, &dwSize) != ERROR_SUCCESS)
  1121. szOldWallpaper[0] = TEXT('\0');
  1122. // Read the wallpaper style
  1123. DWORD dwWallpaperStyle = GetIntFromReg(HKEY_CURRENT_USER, REGSTR_PATH_DESKTOP, REG_VAL_GENERAL_TILEWALLPAPER, WPSTYLE_TILE);
  1124. TCHAR szDeskcomp[MAX_PATH];
  1125. GetRegLocation(szDeskcomp, ARRAYSIZE(szDeskcomp), REG_DESKCOMP_GENERAL, NULL);
  1126. // Set the old wallpaper into the new location.
  1127. SHSetValue(HKEY_CURRENT_USER, szDeskcomp,
  1128. c_szWallpaper, REG_SZ, (LPBYTE)szOldWallpaper, SIZEOF(szOldWallpaper));
  1129. // 98/08/14 vtan: This used to write out a REG_DWORD. It should've
  1130. // written out a REG_SZ.
  1131. TCHAR szWallpaperStyle[2];
  1132. (TCHAR*)StrCpyN(szWallpaperStyle, TEXT("0"), ARRAYSIZE(szWallpaperStyle));
  1133. szWallpaperStyle[0] += static_cast<TCHAR>(dwWallpaperStyle & WPSTYLE_MAX);
  1134. // Set the old wallpaper style into the new location.
  1135. SHSetValue(HKEY_CURRENT_USER, szDeskcomp,
  1136. REG_VAL_GENERAL_TILEWALLPAPER, REG_SZ, (LPBYTE)szWallpaperStyle, SIZEOF(szWallpaperStyle));
  1137. // 98/08/14 vtan #196226: Moved the create instance of IActiveDesktop
  1138. // to here from entry of the function. When the instance is created the
  1139. // registry information is cached in the member variable data. The
  1140. // registry information for the wallpaper is then changed behind the
  1141. // object instance and ApplyChanges() is called on STALE information.
  1142. // By deferring the object instantiation to after the registry changes
  1143. // the changes are applied correctly.
  1144. IActiveDesktop * piad;
  1145. HRESULT hres = CoCreateInstance(CLSID_ActiveDesktop, NULL, CLSCTX_INPROC_SERVER, IID_IActiveDesktop, (LPVOID*)&piad);
  1146. if (SUCCEEDED(hres))
  1147. {
  1148. piad->ApplyChanges(AD_APPLY_FORCE | AD_APPLY_HTMLGEN | AD_APPLY_REFRESH);
  1149. piad->Release();
  1150. }
  1151. }
  1152. HRESULT GetTargetFrame(IUnknown* _punkSite, BSTR bstrFrame, IWebBrowser2** ppunkTargetFrame)
  1153. {
  1154. IWebBrowser2 * pwb2;
  1155. HRESULT hr = GetTopLevelBrowser(_punkSite, &pwb2);
  1156. *ppunkTargetFrame = NULL;
  1157. if (SUCCEEDED(hr))
  1158. {
  1159. ITargetFrame2 * pOurTargetFrame;
  1160. IUnknown * punkTargetFrame = NULL;
  1161. // See if there is an existing frame with the specified target name
  1162. hr = TargetQueryService(pwb2, IID_PPV_ARG(ITargetFrame2, &pOurTargetFrame));
  1163. if (SUCCEEDED(hr))
  1164. {
  1165. hr = pOurTargetFrame->FindFrame(bstrFrame, FINDFRAME_JUSTTESTEXISTENCE, &punkTargetFrame);
  1166. if (SUCCEEDED(hr) && punkTargetFrame)
  1167. {
  1168. // yes, we found a frame with that name. QI for the automation
  1169. // interface on that frame.
  1170. hr = punkTargetFrame->QueryInterface(IID_PPV_ARG(IWebBrowser2, ppunkTargetFrame));
  1171. punkTargetFrame->Release();
  1172. }
  1173. pOurTargetFrame->Release();
  1174. }
  1175. pwb2->Release();
  1176. }
  1177. return hr;
  1178. }
  1179. // NavigateAndFind
  1180. // 1. navigate the specified target frame to the specified url
  1181. // 2. set _fWaitingToFindText so that on DocumentComplete,
  1182. // mimic the find dialog and select/highlight the specified text
  1183. STDMETHODIMP CShellUIHelper::NavigateAndFind(BSTR URL, BSTR strQuery, VARIANT* varTargetFrame)
  1184. {
  1185. HRESULT hr;
  1186. IWebBrowser2 * pwb2 = NULL;
  1187. BSTR bstrFrameSrc = NULL;
  1188. if (_bstrQuery)
  1189. SysFreeString(_bstrQuery);
  1190. _bstrQuery = SysAllocString(strQuery);
  1191. BSTR bstrTemp = NULL;
  1192. if (!IsSpecialUrl(URL))
  1193. {
  1194. hr = S_OK;
  1195. }
  1196. else
  1197. {
  1198. bstrTemp = SysAllocString(URL);
  1199. if (bstrTemp)
  1200. {
  1201. hr = WrapSpecialUrl(&bstrTemp);
  1202. if (SUCCEEDED(hr))
  1203. URL = bstrTemp;
  1204. }
  1205. else
  1206. hr = E_OUTOFMEMORY;
  1207. }
  1208. // Security: Don't allow javascript on one web page
  1209. // to automatically execute in the zone
  1210. // of the target frame URL.
  1211. if (SUCCEEDED(hr) && varTargetFrame)
  1212. {
  1213. hr = GetTargetFrame(_punkSite, varTargetFrame->bstrVal, &pwb2); // GetTargetFrame can return NULL pwb2 on S_OK (when bstrVal is "_blank")
  1214. if (SUCCEEDED(hr) && pwb2)
  1215. {
  1216. hr = pwb2->get_LocationURL(&bstrFrameSrc);
  1217. if (SUCCEEDED(hr))
  1218. {
  1219. IHTMLDocument2 *pHtmlDoc;
  1220. if (SUCCEEDED(GetHTMLDoc2(_punkSite, &pHtmlDoc)))
  1221. {
  1222. BSTR bstrDocUrl;
  1223. if (SUCCEEDED(pHtmlDoc->get_URL(&bstrDocUrl)))
  1224. {
  1225. hr = AccessAllowed(bstrDocUrl, bstrFrameSrc) ? S_OK : E_ACCESSDENIED;
  1226. if(!IsSpecialUrl(URL) && hr == E_ACCESSDENIED)
  1227. {
  1228. // For non-script navigates check policy
  1229. DWORD dwPolicy = 0;
  1230. DWORD dwContext = 0;
  1231. if( SUCCEEDED(ZoneCheckUrlEx(bstrDocUrl, &dwPolicy, sizeof(dwPolicy), &dwContext,
  1232. sizeof(dwContext), URLACTION_HTML_SUBFRAME_NAVIGATE, 0, NULL)) &&
  1233. GetUrlPolicyPermissions(dwPolicy) == URLPOLICY_ALLOW)
  1234. {
  1235. hr = S_OK;
  1236. }
  1237. }
  1238. SysFreeString(bstrDocUrl);
  1239. }
  1240. pHtmlDoc->Release();
  1241. }
  1242. SysFreeString(bstrFrameSrc);
  1243. }
  1244. pwb2->Release();
  1245. pwb2 = NULL;
  1246. }
  1247. }
  1248. // Don't allow access to MyComputer zone from non-MyComputer zone.
  1249. if (SUCCEEDED(hr) && !CanNavigateToUrlWithLocalMachineCheck(_punkSite, URL))
  1250. hr = E_ACCESSDENIED;
  1251. if (SUCCEEDED(hr))
  1252. hr = GetTopLevelBrowser(_punkSite, &pwb2);
  1253. if (SUCCEEDED(hr))
  1254. {
  1255. _fWaitingToFindText = TRUE;
  1256. pwb2->Navigate(URL, PVAREMPTY, varTargetFrame, PVAREMPTY, PVAREMPTY);
  1257. pwb2->Release();
  1258. }
  1259. if (bstrTemp)
  1260. SysFreeString(bstrTemp);
  1261. //script runtime error protection
  1262. return SUCCEEDED(hr) ? S_OK : S_FALSE;
  1263. }
  1264. // AutoScan
  1265. //
  1266. // Takes the search string and tries to navigate to www.%s.com, www.%s.org etc. If all of
  1267. // these fail then we navigate to pvarTargetFrame.
  1268. //
  1269. STDMETHODIMP CShellUIHelper::AutoScan
  1270. (
  1271. BSTR strSearch, // String to autoscan
  1272. BSTR strFailureUrl, // url to display is search fails
  1273. VARIANT* pvarTargetFrame // [optional] target frame
  1274. )
  1275. {
  1276. HRESULT hr = E_FAIL;
  1277. IWebBrowser2* pwb2;
  1278. // Don't bother autoscanning if there are extended characters in the search string
  1279. if (!HasExtendedChar(strSearch))
  1280. {
  1281. //first, check to see if the url is trying to spoof /1 security
  1282. BSTR bstrTemp = NULL;
  1283. if (IsSpecialUrl(strFailureUrl))
  1284. {
  1285. bstrTemp = SysAllocString(strFailureUrl);
  1286. if (bstrTemp)
  1287. {
  1288. hr = WrapSpecialUrl(&bstrTemp);
  1289. if (SUCCEEDED(hr))
  1290. strFailureUrl = bstrTemp;
  1291. }
  1292. else
  1293. hr = E_OUTOFMEMORY;
  1294. }
  1295. else
  1296. {
  1297. hr = S_OK;
  1298. }
  1299. if (SUCCEEDED(hr))
  1300. {
  1301. LPWSTR pszTarget = (pvarTargetFrame && pvarTargetFrame->vt == VT_BSTR && pvarTargetFrame->bstrVal) ?
  1302. pvarTargetFrame->bstrVal : L"_main";
  1303. hr = GetTargetFrame(_punkSite, pszTarget, &pwb2); // GetTargetFrame can return NULL pwb2 on S_OK (when bstrVal is "_blank")
  1304. if (!pwb2)
  1305. hr = E_FAIL;
  1306. if (SUCCEEDED(hr))
  1307. {
  1308. BSTR bstrFrameSrc = NULL;
  1309. hr = pwb2->get_LocationURL(&bstrFrameSrc);
  1310. if (SUCCEEDED(hr))
  1311. {
  1312. IHTMLDocument2 *pHtmlDoc;
  1313. if (SUCCEEDED(GetHTMLDoc2(_punkSite, &pHtmlDoc)))
  1314. {
  1315. BSTR bstrDocUrl;
  1316. if (SUCCEEDED(pHtmlDoc->get_URL(&bstrDocUrl)))
  1317. {
  1318. hr = AccessAllowed(bstrDocUrl, bstrFrameSrc) ? S_OK : E_ACCESSDENIED;
  1319. SysFreeString(bstrDocUrl);
  1320. }
  1321. pHtmlDoc->Release();
  1322. }
  1323. SysFreeString(bstrFrameSrc);
  1324. }
  1325. // Don't allow access to MyComputer zone from non-MyComputer zone.
  1326. if (SUCCEEDED(hr) && !CanNavigateToUrlWithLocalMachineCheck(_punkSite, strFailureUrl))
  1327. hr = E_ACCESSDENIED;
  1328. if (SUCCEEDED(hr))
  1329. {
  1330. // We don't want to navigate to strSearch. Start searching using the
  1331. // first autoscan substitution.
  1332. WCHAR szFormat[MAX_PATH];
  1333. WCHAR szUrl[MAX_URL_STRING];
  1334. if (GetSearchFormatString(1, szFormat, sizeof(szFormat)) != ERROR_SUCCESS)
  1335. {
  1336. hr = E_FAIL;
  1337. }
  1338. else
  1339. {
  1340. wnsprintf(szUrl, ARRAYSIZE(szUrl), szFormat, strSearch);
  1341. BSTRBLOB bstrBlob;
  1342. bstrBlob.cbSize = lstrlenW(szUrl) * sizeof(WCHAR);
  1343. bstrBlob.pData = (BYTE*)szUrl;
  1344. BSTR bstrUrl = (BSTR)bstrBlob.pData;
  1345. // Save the original search string for autoscanning. Normally
  1346. // this come from the addressbar, but in our case we store it as
  1347. // a property
  1348. VARIANT v;
  1349. VariantInit (&v);
  1350. v.vt = VT_BSTR;
  1351. v.bstrVal = strSearch;
  1352. pwb2->PutProperty((BSTR)s_sstrSearch.wsz, v);
  1353. // Save the error page in case the scan fails
  1354. v.vt = VT_BSTR;
  1355. v.bstrVal = strFailureUrl;
  1356. pwb2->PutProperty((BSTR)s_sstrFailureUrl.wsz, v);
  1357. // Navigate with autosearch enabled
  1358. VARIANT vFlags;
  1359. vFlags.vt = VT_I4;
  1360. vFlags.lVal = navAllowAutosearch;
  1361. pwb2->Navigate(bstrUrl, &vFlags, pvarTargetFrame, PVAREMPTY, PVAREMPTY);
  1362. }
  1363. }
  1364. pwb2->Release();
  1365. }
  1366. }
  1367. if (bstrTemp)
  1368. SysFreeString(bstrTemp);
  1369. }
  1370. //script runtime error protection
  1371. return SUCCEEDED(hr) ? S_OK : S_FALSE;
  1372. }
  1373. typedef HRESULT (*PFNSHOWBROWSERUI)(IUnknown *punkSite, HWND hwnd, VARIANT *pvarIn, VARIANT *pvarOut);
  1374. typedef void (*PFNOPENLANGUAGEDIALOG)(HWND hwnd, HINSTANCE hinst, LPSTR lpszCmdLine, int nCmdShow);
  1375. HRESULT ShowLanguageDialog(IUnknown *punkSite, HWND hwnd, VARIANT *pvarIn, VARIANT *pvarOut)
  1376. {
  1377. HRESULT hr = E_FAIL;
  1378. HINSTANCE hInstInetcpl = LoadLibrary(TEXT("inetcpl.cpl"));
  1379. if (hInstInetcpl)
  1380. {
  1381. PFNOPENLANGUAGEDIALOG pfnOpenLanguageDialog =
  1382. (PFNOPENLANGUAGEDIALOG)GetProcAddress( hInstInetcpl, "OpenLanguageDialog" );
  1383. if (pfnOpenLanguageDialog)
  1384. {
  1385. pfnOpenLanguageDialog(hwnd, NULL, NULL, SW_SHOW);
  1386. hr = S_OK;
  1387. }
  1388. FreeLibrary(hInstInetcpl);
  1389. }
  1390. return hr;
  1391. }
  1392. HRESULT ShowOrganizeFavorites(IUnknown *punkSite, HWND hwnd, VARIANT *pvarIn, VARIANT *pvarOut)
  1393. {
  1394. return DoOrganizeFavDlgW(hwnd, NULL) ? S_OK : E_FAIL;
  1395. }
  1396. HRESULT ShowPrivacySettings(IUnknown *punkSite, HWND hwnd, VARIANT *pvarIn, VARIANT *pvarOut)
  1397. {
  1398. LaunchPrivacySettings(hwnd);
  1399. return S_OK;
  1400. }
  1401. HRESULT ShowProgramAccessAndDefaults(IUnknown *punkSite, HWND hwnd, VARIANT *pvarIn, VARIANT *pvarOut)
  1402. {
  1403. HRESULT hr;
  1404. const WCHAR c_szControlExe[] = L"control.exe";
  1405. WCHAR szControlPath[MAX_PATH];
  1406. UINT nLen = GetSystemDirectory(szControlPath, ARRAYSIZE(szControlPath));
  1407. // This accounts for needing a backslash after the sysdir
  1408. if ((nLen + ARRAYSIZE(c_szControlExe)) < ARRAYSIZE(szControlPath))
  1409. {
  1410. PathAppend(szControlPath, c_szControlExe);
  1411. HINSTANCE hInst = ShellExecute(NULL, NULL, szControlPath, L"appwiz.cpl,,3", NULL, SW_SHOWNORMAL);
  1412. if (hInst > (HINSTANCE)HINSTANCE_ERROR)
  1413. {
  1414. hr = S_OK;
  1415. }
  1416. else
  1417. {
  1418. hr = HRESULT_FROM_WIN32(PtrToInt(hInst));
  1419. }
  1420. }
  1421. else
  1422. {
  1423. hr = E_OUTOFMEMORY;
  1424. }
  1425. return hr;
  1426. }
  1427. struct BROWSERUI_MAP
  1428. {
  1429. LPWSTR pwszName;
  1430. PFNSHOWBROWSERUI pfnShowBrowserUI;
  1431. };
  1432. const BROWSERUI_MAP s_browserUIMap[] =
  1433. {
  1434. { L"LanguageDialog", ShowLanguageDialog },
  1435. { L"OrganizeFavorites", ShowOrganizeFavorites },
  1436. { L"PrivacySettings", ShowPrivacySettings },
  1437. { L"ProgramAccessAndDefaults", ShowProgramAccessAndDefaults }
  1438. };
  1439. STDMETHODIMP CShellUIHelper::ShowBrowserUI(BSTR bstrName, VARIANT *pvarIn, VARIANT *pvarOut)
  1440. {
  1441. HRESULT hr = E_FAIL;
  1442. for (int i = 0; i < ARRAYSIZE(s_browserUIMap); i++)
  1443. {
  1444. if (pvarOut)
  1445. {
  1446. VariantInit(pvarOut);
  1447. }
  1448. if (0 == StrCmpIW(s_browserUIMap[i].pwszName, bstrName))
  1449. {
  1450. hr = s_browserUIMap[i].pfnShowBrowserUI(_punkSite, _GetOwnerWindow(), pvarIn, pvarOut);
  1451. }
  1452. }
  1453. return S_OK == hr ? S_OK : S_FALSE;
  1454. }
  1455. // the find dialog does the following:
  1456. //
  1457. // rng = document.body.createTextRange();
  1458. // if (rng.findText("Find this text"))
  1459. // rng.select();
  1460. STDMETHODIMP CShellUIHelper::_DoFindOnPage(IDispatch* pdisp)
  1461. {
  1462. HRESULT hr;
  1463. IWebBrowser2* pwb2;
  1464. IDispatch* pdispDocument;
  1465. IHTMLDocument2* pDocument;
  1466. IHTMLElement* pBody;
  1467. IHTMLBodyElement* pBodyElement;
  1468. IHTMLTxtRange* pRange;
  1469. ASSERT(pdisp);
  1470. if (!pdisp)
  1471. return E_FAIL;
  1472. hr = pdisp->QueryInterface(IID_IWebBrowser2, (void**)&pwb2);
  1473. if (SUCCEEDED(hr))
  1474. {
  1475. hr = pwb2->get_Document(&pdispDocument);
  1476. if (SUCCEEDED(hr) && (NULL != pdispDocument))
  1477. {
  1478. hr = pdispDocument->QueryInterface(IID_IHTMLDocument2, (void**)&pDocument);
  1479. if (SUCCEEDED(hr))
  1480. {
  1481. hr = pDocument->get_body(&pBody);
  1482. if (SUCCEEDED(hr) && (NULL != pBody))
  1483. {
  1484. hr = pBody->QueryInterface(IID_IHTMLBodyElement, (void**)&pBodyElement);
  1485. if (SUCCEEDED(hr))
  1486. {
  1487. hr = pBodyElement->createTextRange(&pRange);
  1488. if (SUCCEEDED(hr) && (NULL != pRange))
  1489. {
  1490. VARIANT_BOOL vbfFoundText;
  1491. hr = pRange->findText(_bstrQuery, 1000000, 0, &vbfFoundText);
  1492. if (SUCCEEDED(hr) && (vbfFoundText == VARIANT_TRUE))
  1493. {
  1494. hr = pRange->select();
  1495. }
  1496. pRange->Release();
  1497. }
  1498. pBodyElement->Release();
  1499. }
  1500. pBody->Release();
  1501. }
  1502. pDocument->Release();
  1503. }
  1504. pdispDocument->Release();
  1505. }
  1506. pwb2->Release();
  1507. }
  1508. return hr;
  1509. }
  1510. //
  1511. // Launch the favorites import/export wizard
  1512. //
  1513. STDMETHODIMP CShellUIHelper::ImportExportFavorites(VARIANT_BOOL fImport, BSTR strImpExpPath)
  1514. {
  1515. //don't allow to import/export to folders other than Favorites from OM
  1516. DoImportOrExport(fImport==VARIANT_TRUE, NULL, (LPCWSTR)strImpExpPath, TRUE);
  1517. return S_OK;
  1518. }
  1519. //
  1520. // Save the form data via intelliforms
  1521. //
  1522. STDMETHODIMP CShellUIHelper::AutoCompleteSaveForm(VARIANT *Form)
  1523. {
  1524. HRESULT hrRet = S_FALSE;
  1525. IHTMLDocument2 *pDoc2=NULL;
  1526. GetHTMLDoc2(_punkSite, &pDoc2);
  1527. if (pDoc2)
  1528. {
  1529. hrRet = IntelliFormsSaveForm(pDoc2, Form);
  1530. pDoc2->Release();
  1531. }
  1532. return hrRet;
  1533. }
  1534. //
  1535. // Attach intelliforms to this document
  1536. //
  1537. STDMETHODIMP CShellUIHelper::AutoCompleteAttach(VARIANT *Reserved)
  1538. {
  1539. HRESULT hr=E_FAIL;
  1540. if (_pvIntelliForms == NULL)
  1541. {
  1542. IHTMLDocument2 *pDoc2=NULL;
  1543. GetHTMLDoc2(_punkSite, &pDoc2);
  1544. if (pDoc2)
  1545. {
  1546. hr = S_OK;
  1547. AttachIntelliForms(NULL, _GetOwnerWindow(), pDoc2, &_pvIntelliForms);
  1548. pDoc2->Release();
  1549. }
  1550. }
  1551. return SUCCEEDED(hr) ? S_OK : S_FALSE;
  1552. }