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.

10114 lines
283 KiB

  1. #include "priv.h"
  2. #include "sccls.h"
  3. #include "hlframe.h"
  4. #include <iethread.h>
  5. #include <shobjidlp.h>
  6. #include "stdenum.h"
  7. #include "winlist.h"
  8. #include "iedde.h"
  9. #include "bindcb.h" // for CStubBindStatusCallback
  10. #include "mshtmdid.h"
  11. #include "resource.h"
  12. #include "security.h"
  13. #include "htregmng.h"
  14. #include "mlang.h" // for GetRfc1766FromLcid
  15. #include "winver.h"
  16. #include "dhuihand.h" // for GetFindDialogUp()
  17. #include <varutil.h>
  18. #include <mluisupp.h>
  19. #define DM_FRAMEPROPERTY 0
  20. #define TO_VARIANT_BOOL(b) (b?VARIANT_TRUE:VARIANT_FALSE)
  21. // If URL contains \1 in the string then the URL is really an empty url with the
  22. // security information following the 0x01.
  23. #define EMPTY_URL 0x01
  24. EXTERN_C const IID IID_IProvideMultipleClassInfo;
  25. #ifndef HLNF_EXTERNALNAVIGATE
  26. #define HLNF_EXTERNALNAVIGATE 0x10000000
  27. #endif
  28. #define NAVFAIL_URL TEXT("about:NavigationFailure")
  29. #define NAVFAIL_URL_DESKTOPITEM TEXT("about:DesktopItemNavigationFailure")
  30. #define CPMSG(psz) TraceMsg(TF_SHDAUTO, "ief ConnectionPoint::%s", psz)
  31. #define CPMSG2(psz,d) TraceMsg(TF_SHDAUTO, "ief ConnectionPoint::%s %x", psz, d)
  32. #define DM_CPC 0
  33. // Are there other definitions for these? Particularly MSIE
  34. // We need some reasonable defaults in case we can't get the user agent string from the registry.
  35. //
  36. #define MSIE L"Microsoft Internet Explorer"
  37. #define APPCODENAME L"Mozilla"
  38. #define APPVERSION L"4.0 (compatible; MSIE 6.0)"
  39. #define USERAGENT L"Mozilla/4.0 (compatible; MSIE 6.0)"
  40. #define NO_NAME_NAME L"_No__Name:"
  41. #define EXTENDER_DISPID_BASE ((ULONG)(0x80010000))
  42. #define IS_EXTENDER_DISPID(x) (((ULONG)(x) & 0xFFFF0000) == EXTENDER_DISPID_BASE)
  43. BOOL GetNextOption(BSTR& bstrOptionString, BSTR* optionName, int* piValue);
  44. BSTR GetNextToken(BSTR bstr, BSTR delimiters, BSTR whitespace, BSTR *nextPos);
  45. DWORD OpenAndNavigateToURL(CIEFrameAuto*, BSTR *, const WCHAR*, ITargetNotify*, BOOL bNoHistory, BOOL bSilent);
  46. HRESULT __cdecl DoInvokeParamHelper(IUnknown* punk, IConnectionPoint* pccp, LPBOOL pf, void **ppv, DISPID dispid, UINT cArgs, ...);
  47. BSTR SafeSysAllocStringLen(const WCHAR *pStr, const unsigned int len);
  48. //====================================================================================
  49. // Define a new internal class that is used to manage a set of simple properties that
  50. // we manage as part of the object. This is mainly used such that pages (or objects
  51. // that manage a page can save state across pages.
  52. class CIEFrameAutoProp
  53. {
  54. public:
  55. HRESULT Initialize(BSTR szProperty)
  56. {
  57. UINT cch = lstrlenW(szProperty);
  58. if (cch < ARRAYSIZE(_sstr.wsz)) {
  59. StrCpyNW(_sstr.wsz, szProperty, ARRAYSIZE(_sstr.wsz));
  60. _sstr.cb = cch * sizeof(WCHAR);
  61. _szProperty = _sstr.wsz;
  62. return S_OK;
  63. }
  64. _szProperty = SysAllocString(szProperty);
  65. return _szProperty ? S_OK : E_OUTOFMEMORY;
  66. }
  67. HRESULT SetValue(VARIANT *pvtValue, IWebBrowser2* pauto);
  68. HRESULT CopyValue(VARIANT *pvtValue);
  69. BOOL IsExpired(DWORD dwCur);
  70. BOOL IsOurProp(BSTR szProperty) { return StrCmpW(szProperty, _szProperty) == 0;}
  71. CIEFrameAutoProp * Next() {return _next;}
  72. CIEFrameAutoProp () { VariantInit(&_vtValue); }
  73. ~CIEFrameAutoProp()
  74. {
  75. if (_szProperty && _szProperty != _sstr.wsz)
  76. SysFreeString(_szProperty);
  77. _VariantClear();
  78. }
  79. void _VariantClear();
  80. CIEFrameAutoProp *_next;
  81. protected:
  82. BSTR _szProperty;
  83. VARIANT _vtValue;
  84. SA_BSTRGUID _sstr;
  85. BOOL _fDiscardable : 1;
  86. BOOL _fOwned : 1; // call SetSite(NULL) when discard
  87. DWORD _dwLastAccessed;
  88. } ;
  89. #ifdef DEBUG
  90. #define MSEC_PROPSWEEP (1*1000)
  91. #define MSEC_PROPEXPIRE (5*1000)
  92. #else
  93. #define MSEC_PROPSWEEP (5*1000*60) // sweep every 5 min
  94. #define MSEC_PROPEXPIRE (10*1000*60) // expire in 10 min
  95. #endif
  96. void CIEFrameAutoProp::_VariantClear()
  97. {
  98. if (_vtValue.vt == VT_UNKNOWN && _fOwned)
  99. {
  100. _fOwned = FALSE;
  101. HRESULT hr = IUnknown_SetSite(_vtValue.punkVal, NULL);
  102. ASSERT(SUCCEEDED(hr));
  103. }
  104. VariantClearLazy(&_vtValue);
  105. }
  106. HRESULT CIEFrameAutoProp::SetValue(VARIANT *pvtValue, IWebBrowser2* pauto)
  107. {
  108. TraceMsg(DM_FRAMEPROPERTY, "CIEFAP::SetValue called");
  109. _dwLastAccessed = GetCurrentTime();
  110. // In case we have _fOwned==TRUE.
  111. _VariantClear();
  112. if (pvtValue->vt == VT_UNKNOWN && pvtValue->punkVal)
  113. {
  114. // Check if this is discardable or not.
  115. IUnknown* punk;
  116. if (SUCCEEDED(pvtValue->punkVal->QueryInterface(IID_IDiscardableBrowserProperty, (void **)&punk)))
  117. {
  118. TraceMsg(DM_FRAMEPROPERTY, "CIEFAP::SetValue adding a discardable");
  119. _fDiscardable = TRUE;
  120. punk->Release();
  121. }
  122. //
  123. // Check if we need to call SetSite(NULL) when we discard.
  124. //
  125. IObjectWithSite* pows;
  126. HRESULT hresT = pvtValue->punkVal->QueryInterface(IID_PPV_ARG(IObjectWithSite, &pows));
  127. if (SUCCEEDED(hresT))
  128. {
  129. IUnknown* psite;
  130. hresT = pows->GetSite(IID_PPV_ARG(IUnknown, &psite));
  131. if (SUCCEEDED(hresT) && psite)
  132. {
  133. _fOwned = IsSameObject(psite, pauto);
  134. psite->Release();
  135. }
  136. pows->Release();
  137. }
  138. }
  139. if (pvtValue->vt & VT_BYREF)
  140. return VariantCopyInd(&_vtValue, pvtValue);
  141. else
  142. return VariantCopyLazy(&_vtValue, pvtValue);
  143. }
  144. HRESULT CIEFrameAutoProp::CopyValue(VARIANT *pvtValue)
  145. {
  146. _dwLastAccessed = GetCurrentTime();
  147. return VariantCopyLazy(pvtValue, &_vtValue);
  148. }
  149. BOOL CIEFrameAutoProp::IsExpired(DWORD dwCur)
  150. {
  151. BOOL fExpired = FALSE;
  152. if (_fDiscardable) {
  153. fExpired = ((dwCur - _dwLastAccessed) > MSEC_PROPEXPIRE);
  154. }
  155. return fExpired;
  156. }
  157. //IDispatch functions, now part of IWebBrowserApp
  158. STDAPI SafeGetItemObject(LPSHELLVIEW psv, UINT uItem, REFIID riid, void **ppv);
  159. HRESULT CIEFrameAuto::v_InternalQueryInterface(REFIID riid, void ** ppvObj)
  160. {
  161. static const QITAB qit[] = {
  162. // perf: last tuned 980728
  163. QITABENT(CIEFrameAuto, IConnectionPointContainer), // IID_ConnectionPointContainer
  164. QITABENT(CIEFrameAuto, IWebBrowser2), // IID_IWebBrowser2
  165. QITABENT(CIEFrameAuto, IServiceProvider), // IID_IServiceProvider
  166. QITABENTMULTI(CIEFrameAuto, IWebBrowserApp, IWebBrowser2), // IID_IWebBrowserApp
  167. QITABENT(CIEFrameAuto, IShellService), // IID_IShellService
  168. QITABENT(CIEFrameAuto, IEFrameAuto), // IID_IEFrameAuto
  169. QITABENT(CIEFrameAuto, IExpDispSupport), // IID_IExpDispSupport
  170. QITABENT(CIEFrameAuto, IWebBrowserPriv), // IID_IWebBrowserPriv
  171. QITABENT(CIEFrameAuto, ITargetFrame2), // IID_ITargetFrame2
  172. QITABENT(CIEFrameAuto, IHlinkFrame), // IID_IHlinkFrame
  173. QITABENT(CIEFrameAuto, IOleCommandTarget), // IID_IOleCommandTarget
  174. QITABENT(CIEFrameAuto, IUrlHistoryNotify), // IID_IUrlHistoryNotify
  175. QITABENTMULTI(CIEFrameAuto, IDispatch, IWebBrowser2), // rare IID_IDispatch
  176. QITABENTMULTI(CIEFrameAuto, IWebBrowser, IWebBrowser2),// rare IID_IWebBrowser
  177. QITABENT(CIEFrameAuto, IExternalConnection), // rare IID_IExternalConnection
  178. QITABENT(CIEFrameAuto, ITargetNotify), // rare IID_ITargetNotify
  179. QITABENT(CIEFrameAuto, ITargetFramePriv), // rare IID_ITargetFramePriv
  180. { 0 },
  181. };
  182. HRESULT hres = QISearch(this, qit, riid, ppvObj);
  183. if (FAILED(hres))
  184. {
  185. if (IsEqualIID(riid, IID_ITargetFrame))
  186. {
  187. *ppvObj = SAFECAST(&_TargetFrame, ITargetFrame*);
  188. AddRef();
  189. return S_OK;
  190. }
  191. }
  192. return hres;
  193. }
  194. LONG CIEFrameAuto::s_cIEFrameAuto = 0;
  195. CIEFrameAuto::CIEFrameAuto(IUnknown* punkAgg) :
  196. m_dwFrameMarginWidth(0xFFFFFFFF)
  197. ,m_dwFrameMarginHeight(0xFFFFFFFF)
  198. ,CImpIDispatch(LIBID_SHDocVw, 1, 1, IID_IWebBrowser2)
  199. ,CAggregatedUnknown(punkAgg)
  200. {
  201. TraceMsg(TF_SHDLIFE, "ctor CIEFrameAuto %x", this);
  202. //
  203. // REVIEW: We don't need to DllAddRef as long as all instances
  204. // of CIEFrameAuto are scoped by either CShellBrowser/CExplorerBrowser
  205. // or CWebBrowserOC. We can remove the DllAddRef/Release, but it's not
  206. // a perf hit so why bother??
  207. //
  208. DllAddRef();
  209. InterlockedIncrement(&s_cIEFrameAuto);
  210. ASSERT(_cLocks==0);
  211. ASSERT(_pITI==NULL);
  212. ASSERT(_pbs==NULL);
  213. ASSERT(_hwnd==NULL);
  214. ASSERT(_pProps==NULL);
  215. ASSERT(_phlbc == NULL);
  216. ASSERT(_dwRegHLBC == 0);
  217. ASSERT(m_bOffline==FALSE);
  218. ASSERT(m_bSilent==FALSE);
  219. ASSERT(_hinstMSHTML==0);
  220. ASSERT(_pfnMEGetIDsOfNames==0);
  221. ASSERT(0==_pwszShortcutPath);
  222. TraceMsg(TF_SHDLIFE, "ctor CIEFrameAuto(%x) being constructed", this);
  223. m_cpWebBrowserEvents.SetOwner(_GetInner(), &DIID_DWebBrowserEvents);
  224. m_cpWebBrowserEvents2.SetOwner(_GetInner(), &DIID_DWebBrowserEvents2);
  225. m_cpPropNotify.SetOwner(_GetInner(), &IID_IPropertyNotifySink);
  226. HRESULT hr = _omwin.Init();
  227. ASSERT(SUCCEEDED(hr));
  228. hr = _omloc.Init();
  229. ASSERT(SUCCEEDED(hr));
  230. hr = _omnav.Init(&_mimeTypes, &_plugins, &_profile);
  231. ASSERT(SUCCEEDED(hr));
  232. hr = _omhist.Init();
  233. ASSERT(SUCCEEDED(hr));
  234. hr = _mimeTypes.Init();
  235. ASSERT(SUCCEEDED(hr));
  236. hr = _plugins.Init();
  237. ASSERT(SUCCEEDED(hr));
  238. hr = _profile.Init();
  239. ASSERT(SUCCEEDED(hr));
  240. }
  241. HRESULT CIEFrameAuto_CreateInstance(IUnknown* pUnkOuter, IUnknown** ppunk)
  242. {
  243. CIEFrameAuto * pauto = new CIEFrameAuto(pUnkOuter);
  244. if (pauto) {
  245. *ppunk = pauto->_GetInner();
  246. return S_OK;
  247. }
  248. *ppunk = NULL;
  249. return E_OUTOFMEMORY;
  250. }
  251. STDAPI_(void) DestroyHdpaHooks(); // implemented in url.cpp
  252. CIEFrameAuto::~CIEFrameAuto()
  253. {
  254. ASSERT(!_psp);
  255. // We're done with MSHTML's MatchExactGetIDsOfNames
  256. if (_hinstMSHTML)
  257. {
  258. FreeLibrary(_hinstMSHTML);
  259. }
  260. // Clear any pending or active navigation contexts
  261. _SetPendingNavigateContext(NULL, NULL);
  262. _ActivatePendingNavigateContext();
  263. // Close the browse context and release it.
  264. if (_phlbc)
  265. {
  266. IHlinkBrowseContext * phlbc = _phlbc;
  267. phlbc->AddRef();
  268. SetBrowseContext(NULL);
  269. phlbc->Close(0);
  270. phlbc->Release();
  271. }
  272. SetOwner(NULL);
  273. if (m_pszFrameName)
  274. {
  275. LocalFree(m_pszFrameName);
  276. m_pszFrameName = NULL;
  277. }
  278. if (m_pszFrameSrc)
  279. {
  280. LocalFree(m_pszFrameSrc);
  281. m_pszFrameSrc = NULL;
  282. }
  283. if (_pITI)
  284. _pITI->Release();
  285. if (_pbs)
  286. _pbs->Release();
  287. if (_pwszShortcutPath)
  288. {
  289. LocalFree(_pwszShortcutPath);
  290. _pwszShortcutPath = NULL;
  291. }
  292. if (_pwszShortcutPathPending)
  293. {
  294. LocalFree(_pwszShortcutPathPending);
  295. _pwszShortcutPathPending = NULL;
  296. }
  297. // Paranoia
  298. _ClearPropertyList();
  299. ASSERT( 0 != s_cIEFrameAuto );
  300. LONG cRef = InterlockedDecrement(&s_cIEFrameAuto);
  301. ASSERT(cRef >= 0 );
  302. if (0 == cRef )
  303. {
  304. //
  305. // we were releasing these guys
  306. // in DllRelease, but to avoid mem
  307. // leaks we need to be more aggressive
  308. // about deleting them.
  309. //
  310. DestroyHdpaHooks();
  311. }
  312. DllRelease();
  313. TraceMsg(TF_SHDLIFE, "dtor CIEFrameAuto %x", this);
  314. }
  315. /* IWebBrowserApp methods */
  316. // Display name of the application
  317. HRESULT CIEFrameAuto::get_Name(BSTR * pbstrName)
  318. {
  319. *pbstrName = LoadBSTR(IDS_NAME);
  320. return *pbstrName ? S_OK : E_OUTOFMEMORY;
  321. }
  322. HRESULT CIEFrameAuto::get_HWND(LONG_PTR *pHWND)
  323. {
  324. *pHWND = HandleToLong(_GetHWND());
  325. return *pHWND ? S_OK : E_FAIL;
  326. }
  327. // Fule filespec of executable, but sample I've seen doesn't give extension
  328. HRESULT CIEFrameAuto::get_FullName(BSTR * pbstrFullName)
  329. {
  330. // HACK: This is also the way to tell it to update the pidl in the window list.
  331. if (_pbs) //Make sure we have a IBrowserService.
  332. _pbs->UpdateWindowList();
  333. TCHAR szPath[MAX_PATH];
  334. if (GetModuleFileName(NULL, szPath, ARRAYSIZE(szPath)) > 0)
  335. {
  336. *pbstrFullName = SysAllocStringT(szPath);
  337. return *pbstrFullName ? S_OK : E_OUTOFMEMORY;
  338. }
  339. *pbstrFullName = NULL;
  340. return E_FAIL;
  341. }
  342. // Path to the executable
  343. STDMETHODIMP CIEFrameAuto::get_Path(BSTR * pbstrPath)
  344. {
  345. TCHAR szPath[MAX_PATH];
  346. if (GetModuleFileName(NULL, szPath, ARRAYSIZE(szPath)) > 0)
  347. {
  348. *PathFindFileName(szPath) = TEXT('\0');
  349. *pbstrPath = SysAllocStringT(szPath);
  350. return *pbstrPath ? S_OK : E_OUTOFMEMORY;
  351. }
  352. *pbstrPath = NULL;
  353. return E_FAIL;
  354. }
  355. HRESULT CIEFrameAuto::get_Application(IDispatch **ppDisp)
  356. {
  357. return QueryInterface(IID_PPV_ARG(IDispatch, ppDisp));
  358. }
  359. HRESULT CIEFrameAuto::get_Parent(IDispatch **ppDisp)
  360. {
  361. return QueryInterface(IID_PPV_ARG(IDispatch, ppDisp));
  362. }
  363. HRESULT CIEFrameAuto::get_Left(long * pl)
  364. {
  365. ASSERT(pl);
  366. HRESULT hr;
  367. HWND hwnd = _GetHWND();
  368. if (hwnd)
  369. {
  370. RECT rc;
  371. GetWindowRect(hwnd, &rc);
  372. *pl = rc.left;
  373. hr = S_OK;
  374. }
  375. else
  376. {
  377. *pl = 0;
  378. hr = S_FALSE;
  379. }
  380. return hr;
  381. }
  382. HRESULT CIEFrameAuto::put_Left(long Left)
  383. {
  384. RECT rc;
  385. if (_pbs)
  386. _pbs->SetFlags(BSF_UISETBYAUTOMATION, BSF_UISETBYAUTOMATION);
  387. HWND hwnd = _GetHWND();
  388. if (hwnd)
  389. {
  390. GetWindowRect(hwnd, &rc);
  391. SetWindowPos(hwnd, NULL, Left, rc.top, 0, 0, SWP_NOACTIVATE|SWP_NOZORDER|SWP_NOSIZE);
  392. }
  393. return S_OK;
  394. }
  395. HRESULT CIEFrameAuto::get_Top(long * pl)
  396. {
  397. ASSERT(pl);
  398. HRESULT hr;
  399. HWND hwnd = _GetHWND();
  400. if (hwnd)
  401. {
  402. RECT rc;
  403. GetWindowRect(hwnd, &rc);
  404. *pl = rc.top;
  405. hr = S_OK;
  406. }
  407. else
  408. {
  409. *pl = 0;
  410. hr = S_FALSE;
  411. }
  412. return hr;
  413. }
  414. HRESULT CIEFrameAuto::put_Top(long Top)
  415. {
  416. RECT rc;
  417. if (_pbs)
  418. _pbs->SetFlags(BSF_UISETBYAUTOMATION, BSF_UISETBYAUTOMATION);
  419. HWND hwnd = _GetHWND();
  420. if (hwnd)
  421. {
  422. GetWindowRect(hwnd, &rc);
  423. SetWindowPos(hwnd, NULL, rc.left, Top, 0, 0, SWP_NOACTIVATE|SWP_NOZORDER|SWP_NOSIZE);
  424. }
  425. return S_OK;
  426. }
  427. HRESULT CIEFrameAuto::get_Width(long * pl)
  428. {
  429. ASSERT(pl);
  430. HRESULT hr;
  431. HWND hwnd = _GetHWND();
  432. if (hwnd)
  433. {
  434. RECT rc;
  435. GetWindowRect(hwnd, &rc);
  436. *pl = rc.right - rc.left;
  437. hr = S_OK;
  438. }
  439. else
  440. {
  441. *pl = 0;
  442. hr = S_FALSE;
  443. }
  444. return hr;
  445. }
  446. HRESULT CIEFrameAuto::put_Width(long Width)
  447. {
  448. if (_pbs)
  449. _pbs->SetFlags(BSF_UISETBYAUTOMATION, BSF_UISETBYAUTOMATION);
  450. HWND hwnd = _GetHWND();
  451. if (hwnd)
  452. {
  453. RECT rc;
  454. GetWindowRect(hwnd, &rc);
  455. SetWindowPos(hwnd, NULL, 0, 0, Width, rc.bottom-rc.top, SWP_NOACTIVATE|SWP_NOZORDER|SWP_NOMOVE);
  456. }
  457. return S_OK;
  458. }
  459. HRESULT CIEFrameAuto::get_Height(long * pl)
  460. {
  461. ASSERT(pl);
  462. HRESULT hr;
  463. HWND hwnd = _GetHWND();
  464. if (hwnd)
  465. {
  466. RECT rc;
  467. GetWindowRect(hwnd, &rc);
  468. *pl = rc.bottom - rc.top;
  469. hr = S_OK;
  470. }
  471. else
  472. {
  473. *pl = 0;
  474. hr = S_FALSE;
  475. }
  476. return hr;
  477. }
  478. HRESULT CIEFrameAuto::put_Height(long Height)
  479. {
  480. if (_pbs)
  481. _pbs->SetFlags(BSF_UISETBYAUTOMATION, BSF_UISETBYAUTOMATION);
  482. HWND hwnd = _GetHWND();
  483. if (hwnd)
  484. {
  485. RECT rc;
  486. GetWindowRect(hwnd, &rc);
  487. SetWindowPos(hwnd, NULL, 0, 0, rc.right-rc.left, Height, SWP_NOACTIVATE|SWP_NOZORDER|SWP_NOMOVE);
  488. }
  489. return S_OK;
  490. }
  491. HRESULT CIEFrameAuto::put_Titlebar(BOOL fValue)
  492. {
  493. HWND hwnd;
  494. HRESULT hres = get_HWND((LONG_PTR*)&hwnd);
  495. if (SUCCEEDED(hres))
  496. {
  497. DWORD dwVal = GetWindowLong(hwnd, GWL_STYLE);
  498. if (fValue)
  499. dwVal |= WS_CAPTION;
  500. else
  501. dwVal &= ~WS_CAPTION;
  502. if (SetWindowLong(hwnd, GWL_STYLE, dwVal))
  503. {
  504. // We need to do a SetWindowPos in order for the style changes to take effect
  505. SetWindowPos(hwnd, NULL, 0, 0, 0, 0, SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_FRAMECHANGED);
  506. }
  507. else
  508. hres = E_FAIL;
  509. }
  510. return hres;
  511. }
  512. HRESULT CIEFrameAuto::get_Visible(VARIANT_BOOL * pBool)
  513. {
  514. HWND hwnd = _GetHWND();
  515. *pBool = hwnd ? TO_VARIANT_BOOL(IsWindowVisible(hwnd)) : VARIANT_FALSE;
  516. return S_OK;
  517. }
  518. HRESULT CIEFrameAuto::put_Visible(VARIANT_BOOL Value)
  519. {
  520. HWND hwnd = _GetHWND();
  521. if (hwnd)
  522. {
  523. ::ShowWindow(hwnd, Value? SW_SHOW : SW_HIDE);
  524. if (Value)
  525. ::SetForegroundWindow(::GetLastActivePopup(hwnd));
  526. FireEvent_OnAdornment(_GetOuter(), DISPID_ONVISIBLE, Value);
  527. }
  528. return S_OK;
  529. }
  530. HRESULT CIEFrameAuto::get_Document(IDispatch **ppDisp)
  531. {
  532. HRESULT hres = E_FAIL;
  533. IShellView * psv = NULL;
  534. *ppDisp = NULL;
  535. if (_psb)
  536. {
  537. hres = _psb->QueryActiveShellView(&psv);
  538. if (FAILED(hres))
  539. {
  540. CComVariant cvarUnk;
  541. hres = _pmsc->Exec(&CGID_ShellDocView, SHDVID_GETPENDINGOBJECT, 0, NULL, &cvarUnk);
  542. if (SUCCEEDED(hres))
  543. {
  544. if ((VT_UNKNOWN == V_VT(&cvarUnk)) && V_UNKNOWN(&cvarUnk))
  545. {
  546. hres = cvarUnk.punkVal->QueryInterface(IID_IShellView, (void**)&psv);
  547. }
  548. else
  549. {
  550. hres = E_FAIL;
  551. }
  552. }
  553. }
  554. if (psv)
  555. {
  556. IDispatch * pDisp;
  557. hres = SafeGetItemObject(psv, SVGIO_BACKGROUND, IID_PPV_ARG(IDispatch, &pDisp));
  558. if (SUCCEEDED(hres))
  559. {
  560. // (scotrobe 01/14/2000): We need to QI for IHTMLDocument2 to support
  561. // bad apps (e.g., HotMetal Pro) that cast the IDispatch to IHTMLDocument2.
  562. // Casting like this used to work because the object returned from
  563. // SafeGetItemObject() used to implement IHTMLDocument2. Now, it delegates
  564. // that implementation to another object. If the QI for IHTMLDocument2 fails, '
  565. // then the object is not MSHTML. In that case, we just return the
  566. // IDispatch that was returned from SafeGetItemObject().
  567. //
  568. IHTMLDocument2 * pDocument;
  569. HRESULT hr = pDisp->QueryInterface(IID_PPV_ARG(IHTMLDocument2, &pDocument));
  570. if (SUCCEEDED(hr))
  571. {
  572. *ppDisp = pDocument;
  573. pDisp->Release();
  574. }
  575. else // Non-html document
  576. {
  577. *ppDisp = pDisp; // Don't release pDisp
  578. }
  579. }
  580. psv->Release();
  581. }
  582. }
  583. return hres;
  584. }
  585. HRESULT CIEFrameAuto::get_Busy(VARIANT_BOOL *pBool)
  586. {
  587. if (_pbs == NULL)
  588. {
  589. TraceMsg(DM_WARNING, "CIEA::get_Busy called _pbs==NULL");
  590. return E_FAIL;
  591. }
  592. BNSTATE bnstate;
  593. HRESULT hres = _pbs->GetNavigateState(&bnstate);
  594. if (SUCCEEDED(hres))
  595. {
  596. *pBool = TO_VARIANT_BOOL(bnstate != BNS_NORMAL);
  597. hres = S_OK;
  598. }
  599. return hres;
  600. }
  601. // MSDN97 keeps asking for a location until it gets success, so it
  602. // hangs if we fail. Make sure no code paths return early from here...
  603. //
  604. HRESULT CIEFrameAuto::_get_Location(BSTR * pbstr, UINT uFlags)
  605. {
  606. if (_pbs)
  607. {
  608. LPITEMIDLIST pidl;
  609. HRESULT hres = _pbs->GetPidl(&pidl);
  610. if (SUCCEEDED(hres))
  611. {
  612. WCHAR wszTitle[MAX_URL_STRING];
  613. hres = _pbs->IEGetDisplayName(pidl, wszTitle, uFlags);
  614. ILFree(pidl);
  615. if (SUCCEEDED(hres))
  616. {
  617. //
  618. // if url is a pluggable protocol, get the real url by
  619. // chopping of the base url
  620. //
  621. WCHAR *pchUrl = StrChrW(wszTitle, L'\1');
  622. if (pchUrl)
  623. *pchUrl = 0;
  624. //
  625. // if there is already an URL then we just use it
  626. //
  627. if ((uFlags & SHGDN_FORPARSING) && !PathIsURLW(wszTitle))
  628. {
  629. int nScheme;
  630. //
  631. // otherwise we need to treat it as if it were new
  632. // and make sure it is a parseable URL.
  633. //
  634. DWORD cchTitle = ARRAYSIZE(wszTitle);
  635. ParseURLFromOutsideSourceW(wszTitle, wszTitle, &cchTitle, NULL);
  636. // BUG FIX #12221:
  637. // ParseURLFromOutsideSource() was called to turn a file path into
  638. // a fully qualified FILE URL. If the URL was of any other type
  639. // (non-URL sections of the name space), then we want to NULL out the
  640. // string to indicate that it's invalid. We don't return E_FAIL because
  641. // HotDog Pro appears to have problems with that as indicated by the comment
  642. // below.
  643. nScheme = GetUrlSchemeW(wszTitle);
  644. if (URL_SCHEME_FILE != nScheme)
  645. wszTitle[0] = TEXT('\0');
  646. }
  647. *pbstr = SysAllocString(wszTitle);
  648. return *pbstr ? S_OK : E_OUTOFMEMORY;
  649. }
  650. }
  651. }
  652. // If we're here, the TLGetPidl call failed. This can happen if get_LocationName
  653. // or get_LocationURL is called before the first navigate is complete. HotDog Pro does
  654. // this, and was failing with E_FAIL. Now we'll just return an empty string with S_FALSE.
  655. //
  656. // Also MSDN97 hangs (NT5 bug 232126) if we return failure. Guess there hosed on low
  657. // memory situations...
  658. //
  659. *pbstr = SysAllocString(L"");
  660. return *pbstr ? S_FALSE : E_OUTOFMEMORY;
  661. }
  662. HRESULT CIEFrameAuto::get_LocationName(BSTR * pbstrLocationName)
  663. {
  664. return _get_Location(pbstrLocationName, SHGDN_NORMAL);
  665. }
  666. HRESULT CIEFrameAuto::get_LocationURL(BSTR * pbstrLocationURL)
  667. {
  668. return _get_Location(pbstrLocationURL, SHGDN_FORPARSING);
  669. }
  670. HRESULT CIEFrameAuto::Quit()
  671. {
  672. // try to close it down...
  673. _fQuitInProgress = 1;
  674. HWND hwnd = _GetHWND();
  675. if (hwnd)
  676. PostMessage(hwnd, WM_CLOSE, 0, 0);
  677. return S_OK;
  678. }
  679. HRESULT CIEFrameAuto::ClientToWindow(int *pcx, int *pcy)
  680. {
  681. if (_pbs==NULL)
  682. {
  683. TraceMsg(DM_WARNING, "CIEA::ClientToWindow called _pbs==NULL");
  684. return E_FAIL;
  685. }
  686. HWND hwnd;
  687. RECT rc;
  688. BOOL b;
  689. rc.left = 0;
  690. rc.right = *pcx;
  691. rc.top = 0;
  692. rc.bottom = *pcy;
  693. _pbs->IsControlWindowShown(FCW_MENUBAR, &b);
  694. HWND hwnd2 = _GetHWND();
  695. if (hwnd2)
  696. AdjustWindowRect(&rc, GetWindowLong(hwnd2, GWL_STYLE), b);
  697. *pcx = rc.right-rc.left;
  698. *pcy = rc.bottom-rc.top;
  699. _pbs->IsControlWindowShown(FCW_STATUS, &b);
  700. if (b)
  701. {
  702. _psb->GetControlWindow(FCW_STATUS, &hwnd);
  703. if (hwnd)
  704. {
  705. GetWindowRect(hwnd, &rc);
  706. *pcy += rc.bottom-rc.top;
  707. }
  708. }
  709. _pbs->IsControlWindowShown(FCW_INTERNETBAR, &b);
  710. if (b)
  711. {
  712. _psb->GetControlWindow(FCW_INTERNETBAR, &hwnd);
  713. if (hwnd)
  714. {
  715. GetWindowRect(hwnd, &rc);
  716. *pcy += rc.bottom-rc.top;
  717. }
  718. }
  719. // add in 4 pixels for 3d borders, but don't include scrollbars
  720. // 'cause Netscape doesn't
  721. *pcy += 2*GetSystemMetrics(SM_CYEDGE);
  722. *pcx += 2*GetSystemMetrics(SM_CXEDGE);
  723. return S_OK;
  724. }
  725. void CIEFrameAuto::_ClearPropertyList()
  726. {
  727. CIEFrameAutoProp *pprop = _pProps;
  728. _pProps = NULL; // cleared out early...
  729. CIEFrameAutoProp *ppropNext;
  730. while (pprop)
  731. {
  732. ppropNext = pprop->Next();
  733. delete pprop;
  734. pprop = ppropNext;
  735. }
  736. }
  737. HRESULT CIEFrameAuto::PutProperty(BSTR bstrProperty, VARIANT vtValue)
  738. {
  739. if (!bstrProperty)
  740. {
  741. TraceMsg(TF_ERROR, "CIEFrameAuto::PutProperty() - bstrProperty is NULL!");
  742. return E_INVALIDARG;
  743. }
  744. #ifdef DEBUG
  745. // Check if this BSTR is a valid BSTR
  746. SA_BSTR* psstr = (SA_BSTR*)((LPBYTE)bstrProperty - sizeof(ULONG));
  747. ASSERT(psstr->cb == lstrlenW(psstr->wsz)*sizeof(WCHAR));
  748. #endif
  749. HRESULT hres;
  750. CIEFrameAutoProp *pprop = _pProps;
  751. while (pprop && !pprop->IsOurProp(bstrProperty))
  752. pprop=pprop->Next();
  753. if (!pprop)
  754. {
  755. pprop = new CIEFrameAutoProp;
  756. if (!pprop)
  757. return E_OUTOFMEMORY;
  758. if (FAILED(hres=pprop->Initialize(bstrProperty)))
  759. {
  760. delete pprop;
  761. return hres;
  762. }
  763. pprop->_next = _pProps;
  764. _pProps = pprop;
  765. }
  766. hres = pprop->SetValue(&vtValue, this);
  767. // We should now tell anyone who is listening about the change...
  768. FireEvent_DoInvokeBstr(_GetOuter(), DISPID_PROPERTYCHANGE, bstrProperty);
  769. return hres;
  770. }
  771. HRESULT CIEFrameAuto::GetProperty(BSTR bstrProperty, VARIANT * pvtValue)
  772. {
  773. if (!bstrProperty || !pvtValue)
  774. return E_INVALIDARG;
  775. VariantInit(pvtValue);
  776. CIEFrameAutoProp *pprop = _pProps;
  777. while (pprop && !pprop->IsOurProp(bstrProperty))
  778. pprop = pprop->Next();
  779. if (pprop)
  780. {
  781. return pprop->CopyValue(pvtValue);
  782. }
  783. // Did not find property return empty...
  784. // Not there. Probably not worth an error...
  785. return S_OK;
  786. }
  787. extern HRESULT TargetQueryService(IUnknown *punk, REFIID riid, void **ppvObj);
  788. //+-------------------------------------------------------------------------
  789. //
  790. // Method : CIEFrameAuto::Navigate
  791. //
  792. // Interface : IWebBrowser
  793. //
  794. //--------------------------------------------------------------------------
  795. HRESULT CIEFrameAuto::Navigate(BSTR URL,
  796. VARIANT * Flags,
  797. VARIANT * TargetFrameName,
  798. VARIANT * PostData,
  799. VARIANT * Headers)
  800. {
  801. return _NavigateHelper(URL, Flags, TargetFrameName, PostData, Headers);
  802. }
  803. //+-------------------------------------------------------------------------
  804. //
  805. // Method : CIEFrameAuto::NavigateWithBindCtx
  806. //
  807. // Interface : IWebBrowserPriv
  808. //
  809. //--------------------------------------------------------------------------
  810. HRESULT CIEFrameAuto::NavigateWithBindCtx(VARIANT FAR * pvarUrl,
  811. VARIANT FAR * pvarFlags,
  812. VARIANT FAR * pvarTargetFrameName,
  813. VARIANT FAR * pvarPostData,
  814. VARIANT FAR * pvarHeaders,
  815. IBindCtx * pBindCtx,
  816. BSTR bstrLocation)
  817. {
  818. return _NavigateHelper(V_BSTR(pvarUrl),
  819. pvarFlags,
  820. pvarTargetFrameName,
  821. pvarPostData,
  822. pvarHeaders,
  823. pBindCtx,
  824. bstrLocation);
  825. }
  826. //+-------------------------------------------------------------------------
  827. //
  828. // Method : CIEFrameAuto::NavigateWithBC
  829. //
  830. // Interface : IWebBrowserPriv
  831. //
  832. //--------------------------------------------------------------------------
  833. HRESULT
  834. CIEFrameAuto::OnClose()
  835. {
  836. // Clear any pending or active navigation contexts
  837. //
  838. _SetPendingNavigateContext(NULL, NULL);
  839. _ActivatePendingNavigateContext();
  840. return S_OK;
  841. }
  842. //+-------------------------------------------------------------------------
  843. //
  844. // Method : CIEFrameAuto::_NavigateHelper
  845. //
  846. //--------------------------------------------------------------------------
  847. HRESULT
  848. CIEFrameAuto::_NavigateHelper(BSTR URL,
  849. VARIANT * Flags,
  850. VARIANT * TargetFrameName,
  851. VARIANT * PostData,
  852. VARIANT * Headers,
  853. IBindCtx * pNavBindCtx, /* = NULL */
  854. BSTR bstrLocation /* = NULL */)
  855. {
  856. if (NULL == _pbs)
  857. {
  858. TraceMsg(DM_WARNING, "CIEA::Navigate called _pbs==NULL");
  859. return E_FAIL;
  860. }
  861. if (NULL == URL)
  862. {
  863. TraceMsg(TF_SHDAUTO, "Shell automation: CIEFrameAuto::Navigate <NULL> called");
  864. return(_BrowseObject(PIDL_NOTHING, 0));
  865. }
  866. // Special hack for AOL: They send us the following "url" as a null navigate.
  867. // Then they immediately follow it with the url for the new window. That second
  868. // navigate is failing with RPC_E_CALL_REJECTED because of our message filter.
  869. // We fix the new window case by special casing this URL and returning S_FALSE.
  870. // This url will not likely ever be seen in the real world, and if it is typed in,
  871. // will get normalized and canonicalized long before getting here.
  872. //
  873. if (!StrCmpIW(URL, L"x-$home$://null"))
  874. {
  875. return S_FALSE;
  876. }
  877. #ifdef BROWSENEWPROCESS_STRICT // "Nav in new process" has become "Launch in new process", so this is no longer needed
  878. // if we want ALL navigates to be in a separate process, then we need to
  879. // pick off URL navigates for CShellBrowser IShellBrowser implementations
  880. // when we are in the explorer process. We can wait until IShellBrowser::BrowseObject,
  881. // but then we may lose TargetFrameName etc...
  882. //
  883. if (IsBrowseNewProcessAndExplorer() && !IsShellUrl(URL, TRUE))
  884. {
  885. }
  886. #endif
  887. HRESULT hres;
  888. LPITEMIDLIST pidl = NULL;
  889. LPBINDCTX pBindCtx = NULL;
  890. DWORD cbPostData = 0;
  891. LPCWSTR pwzHeaders = NULL;
  892. DWORD dwInFlags = 0;
  893. DWORD dwFlags = 0;
  894. LPCBYTE pPostData = NULL;
  895. DWORD grBindFlags = 0;
  896. SAFEARRAY * pPostDataArray = NULL;
  897. BOOL fOpenWithFrameName = FALSE;
  898. CStubBindStatusCallback * pStubCallback = NULL;
  899. // get target frame name out of variant
  900. LPCWSTR pwzTargetFrameName = NULL;
  901. LPCWSTR pwzUnprefixedTargetFrameName = NULL;
  902. hres = E_FAIL;
  903. TraceMsg(TF_SHDAUTO, "Shell automation: CIEFrameAuto::Navigate %s called", URL);
  904. if (TargetFrameName)
  905. {
  906. if ((VT_BSTR | VT_BYREF) == TargetFrameName->vt)
  907. pwzTargetFrameName = *TargetFrameName->pbstrVal;
  908. else if (VT_BSTR == TargetFrameName->vt)
  909. pwzTargetFrameName = TargetFrameName->bstrVal;
  910. }
  911. // if a target name was specified, send the navigation to the appropriate target
  912. // NOTE: for compatibility we can't change the meaning of target here
  913. // thus we don't attempt to find alias
  914. if ((pwzTargetFrameName && pwzTargetFrameName[0]))
  915. {
  916. LPTARGETFRAME2 pOurTargetFrame = NULL;
  917. IUnknown *punkTargetFrame;
  918. IWebBrowserApp * pIWebBrowserApp;
  919. BOOL fHandled = FALSE;
  920. // see if there is an existing frame with the specified target name
  921. // NOTE: we used docked parameter of _self to force navigation of this
  922. // frame, regardless of whether it is WebBar.
  923. hres = TargetQueryService((IShellBrowser *)this, IID_PPV_ARG(ITargetFrame2, &pOurTargetFrame));
  924. ASSERT(SUCCEEDED(hres));
  925. if (SUCCEEDED(hres))
  926. {
  927. // Workaround for the way Compuserve handles the NewWindow event (window.open)
  928. // They tell the new instance of the web browser to navigate, but they pass the target frame
  929. // name they received on the NewWindow event. This confuses us because that frame name
  930. // has the "_[number]" prefix.
  931. //
  932. // If the first two characters are "_[", then look for the "]" and reallocate a string
  933. // with everthing after that bracket.
  934. //
  935. if (StrCmpNW(pwzTargetFrameName, L"_[", 2) == 0)
  936. {
  937. pwzUnprefixedTargetFrameName = StrChrW(pwzTargetFrameName, L']');
  938. if (pwzUnprefixedTargetFrameName)
  939. {
  940. pwzUnprefixedTargetFrameName++;
  941. pwzTargetFrameName = SysAllocString(pwzUnprefixedTargetFrameName);
  942. if (!pwzTargetFrameName)
  943. {
  944. hres = E_OUTOFMEMORY;
  945. goto exit;
  946. }
  947. }
  948. }
  949. hres = pOurTargetFrame->FindFrame(pwzTargetFrameName,
  950. FINDFRAME_JUSTTESTEXISTENCE,
  951. &punkTargetFrame);
  952. if (SUCCEEDED(hres) && punkTargetFrame)
  953. {
  954. // yes, we found a frame with that name. QI for the automation
  955. // interface on that frame and call navigate on it.
  956. hres = punkTargetFrame->QueryInterface(IID_PPV_ARG(IWebBrowserApp, &pIWebBrowserApp));
  957. punkTargetFrame->Release();
  958. ASSERT(SUCCEEDED(hres));
  959. if (SUCCEEDED(hres))
  960. {
  961. VARIANT var;
  962. LBSTR::CString strFrame;
  963. VariantInit(&var);
  964. var.vt = VT_BSTR;
  965. var.bstrVal = strFrame;
  966. hres = pIWebBrowserApp->Navigate(URL, Flags, &var, PostData, Headers);
  967. var.bstrVal = NULL;
  968. VariantClearLazy(&var);
  969. pIWebBrowserApp->Release();
  970. fHandled = TRUE;
  971. }
  972. }
  973. else if (SUCCEEDED(hres))
  974. {
  975. //no target found means we need to open a new window
  976. //hres = E_FAIL forces parsing of URL into pidl
  977. //if we have no target frame name, then
  978. // BETA1 hack chrisfra 3/3/97. in BETA 2 TargetFrame2
  979. // interface must support aliasing of targets (even if NULL
  980. // to support links in desktop components as per PM requirements
  981. if (!pwzTargetFrameName || !pwzTargetFrameName[0])
  982. {
  983. ASSERT(_fDesktopComponent());
  984. pwzTargetFrameName = L"_desktop";
  985. }
  986. dwFlags |= HLNF_OPENINNEWWINDOW;
  987. fOpenWithFrameName = TRUE;
  988. hres = E_FAIL;
  989. }
  990. pOurTargetFrame->Release();
  991. if (fHandled)
  992. goto exit;
  993. }
  994. }
  995. if (FAILED(hres))
  996. {
  997. hres = _PidlFromUrlEtc(CP_ACP, (LPCWSTR)URL, bstrLocation, &pidl);
  998. if (FAILED(hres))
  999. goto exit;
  1000. }
  1001. // to perform the navigation, we either call an internal method
  1002. // (_pbs->NavigateToPidl) or an external interface (IHlinkFrame::Navigate),
  1003. // depending on what data we need to pass. NavigateToPidl is faster
  1004. // and cheaper, but does not allow us to pass headers or post data, just
  1005. // the URL! So what we do is call the fast and cheap way if only the URL
  1006. // was specified (the 90% case), and if either headers or post data were
  1007. // specified then we call the external interface. We have to do a bunch
  1008. // of wrapping of parameters in IMonikers and IHlinks and whatnot only to
  1009. // unwrap them at the other end, so we won't call this unless we need to.
  1010. if (Headers)
  1011. {
  1012. if ((VT_BSTR | VT_BYREF) == Headers->vt)
  1013. {
  1014. pwzHeaders = *Headers->pbstrVal;
  1015. }
  1016. else if (VT_BSTR == Headers->vt)
  1017. {
  1018. pwzHeaders = Headers->bstrVal;
  1019. }
  1020. }
  1021. //
  1022. // HACK: We used to do VT_ARRAY==PostData->vt, which is bogus.
  1023. // It is supposed to be VT_ARRAY|VT_UI1==PostData->vt. We can't
  1024. // however do it for backward compatibility with AOL and CompuServe.
  1025. // Therefore, we do (VT_ARRAY & PostData->vt)
  1026. //
  1027. if (PostData && (VT_ARRAY & PostData->vt))
  1028. {
  1029. if (VT_BYREF & PostData->vt)
  1030. {
  1031. pPostDataArray = *PostData->pparray;
  1032. }
  1033. else
  1034. {
  1035. pPostDataArray = PostData->parray;
  1036. }
  1037. ASSERT(pPostDataArray);
  1038. if (pPostDataArray)
  1039. {
  1040. // lock the array for reading, get pointer to data
  1041. hres = SafeArrayAccessData(pPostDataArray, (void**)&pPostData);
  1042. if (SUCCEEDED(hres))
  1043. {
  1044. long nElements = 0;
  1045. DWORD dwElemSize;
  1046. // get number of elements in array
  1047. SafeArrayGetUBound(pPostDataArray,1,(long *) &nElements);
  1048. // SafeArrayGetUBound returns zero-based max index, add one to get element count
  1049. nElements++;
  1050. // get bytes per element
  1051. dwElemSize = SafeArrayGetElemsize(pPostDataArray);
  1052. // bytes per element should be one if we created this array
  1053. ASSERT(dwElemSize == 1);
  1054. // calculate total byte count anyway so that we can handle
  1055. // safe arrays other people might create with different element sizes
  1056. cbPostData = dwElemSize * nElements;
  1057. if (0 == cbPostData)
  1058. pPostData = NULL;
  1059. }
  1060. }
  1061. }
  1062. // convert from automation interface flags (nav*) to
  1063. // hyperlinking flags (HLNF_*)
  1064. if (Flags)
  1065. {
  1066. if (Flags->vt == VT_I4)
  1067. {
  1068. dwInFlags = Flags->lVal;
  1069. }
  1070. else if (Flags->vt == VT_I2)
  1071. {
  1072. dwInFlags = Flags->iVal;
  1073. }
  1074. if ((dwInFlags & navOpenInNewWindow))
  1075. {
  1076. dwFlags |= HLNF_OPENINNEWWINDOW;
  1077. }
  1078. if (dwInFlags & navNoHistory)
  1079. {
  1080. dwFlags |= HLNF_CREATENOHISTORY;
  1081. }
  1082. if (dwInFlags & navNoReadFromCache)
  1083. {
  1084. grBindFlags |= BINDF_RESYNCHRONIZE | BINDF_PRAGMA_NO_CACHE;
  1085. }
  1086. if (dwInFlags & navNoWriteToCache)
  1087. {
  1088. grBindFlags |= BINDF_NOWRITECACHE;
  1089. }
  1090. if (dwInFlags & navHyperlink)
  1091. {
  1092. grBindFlags |= BINDF_HYPERLINK;
  1093. }
  1094. if (dwInFlags & navEnforceRestricted)
  1095. {
  1096. grBindFlags |= BINDF_ENFORCERESTRICTED;
  1097. }
  1098. // Should call IsBrowserFrameOptionsPidlSet() instead. Some URL delegate
  1099. // NSEs may or may not want this feature.
  1100. if (IsURLChild(pidl, TRUE) && (dwInFlags & navAllowAutosearch))
  1101. {
  1102. dwFlags |= HLNF_ALLOW_AUTONAVIGATE;
  1103. }
  1104. }
  1105. // if we have either headers or post data or need to open the page in a
  1106. // new window or pass HLNF_CREATENOHISTORY, we have to do the navigation
  1107. // the hard way (through IHlinkFrame::Navigate) -- here we have to do
  1108. // a bunch of wrapping of parameters into COM objects that IHlinkFrame::
  1109. // Navigate wants.
  1110. if (pwzHeaders || pPostData || dwFlags || grBindFlags)
  1111. {
  1112. // Check to see if this frame is offline.
  1113. // This is the same as doing a get_Offline
  1114. VARIANT_BOOL vtbFrameIsOffline = m_bOffline ? VARIANT_TRUE : VARIANT_FALSE;
  1115. VARIANT_BOOL vtbFrameIsSilent = m_bSilent ? VARIANT_TRUE : VARIANT_FALSE;
  1116. // make a "stub" bind status callback to hold that data and pass it
  1117. // to the URL moniker when requested
  1118. hres = CStubBindStatusCallback_Create(pwzHeaders,pPostData,cbPostData,
  1119. vtbFrameIsOffline, vtbFrameIsSilent,
  1120. TRUE, grBindFlags, &pStubCallback);
  1121. if (FAILED(hres))
  1122. goto exit;
  1123. // get the canonicalized name back out of the pidl. Note this is
  1124. // different than the URL passed in... it has been auto-protocol-ized,
  1125. // canonicalized and generally munged in the process of creating the pidl,
  1126. // which is what we want to use.
  1127. // need +3. +2 for iegetdisplayname call inside failed statment below, and +1 for movememory further below
  1128. WCHAR wszPath[MAX_URL_STRING+3]; // note stomping below if changed to dynalloc
  1129. hres = _pbs->IEGetDisplayName(pidl, wszPath, SHGDN_FORPARSING);
  1130. if (FAILED(hres))
  1131. {
  1132. // On Win9x, IEGetDisplayName(SHGDN_FORPARSING) will return NOT_IMPLEMENTED
  1133. // for \\servername (but not \\servername\share)
  1134. // We need to work around this.
  1135. DWORD ccPath = ARRAYSIZE(wszPath);
  1136. if (SUCCEEDED(PathCreateFromUrl(URL, wszPath, &ccPath, 0))
  1137. && *wszPath==L'\\'
  1138. && *(wszPath+1)==L'\\')
  1139. {
  1140. hres = _pbs->IEGetDisplayName(pidl, wszPath + 2, SHGDN_FORADDRESSBAR); // assumes MAX_URL_STRING size for the string
  1141. }
  1142. }
  1143. if (FAILED(hres))
  1144. {
  1145. TraceMsg(DM_ERROR, "CIEFrameAuto::Navigate _pbs->IEGetDisplayName failed %x", hres);
  1146. goto exit;
  1147. }
  1148. WCHAR *pwzLocation = (WCHAR *)UrlGetLocationW(wszPath);
  1149. if (pwzLocation)
  1150. {
  1151. // NOTE: we allocated an extra char, just so we could do the following
  1152. MoveMemory(pwzLocation+1, pwzLocation, (lstrlenW(pwzLocation)+1)*sizeof(WCHAR));
  1153. *pwzLocation++ = TEXT('\0'); // we own wszPath, so we can do this.
  1154. }
  1155. if (!pNavBindCtx) // A bind ctx was not passed in.
  1156. {
  1157. // Create a bind context to pass to IHlinkFrame::Navigate
  1158. //
  1159. hres = CreateBindCtx(0, &pBindCtx);
  1160. if (FAILED(hres))
  1161. goto exit;
  1162. }
  1163. else
  1164. {
  1165. pBindCtx = pNavBindCtx;
  1166. pBindCtx->AddRef();
  1167. }
  1168. // We have either post data or headers (or we need to open
  1169. // in a new window) to pass in addition to URL.
  1170. // Call IHlinkFrame::Navigate to do the navigation
  1171. //
  1172. hres = NavigateHack(dwFlags,
  1173. pBindCtx,
  1174. pStubCallback,
  1175. fOpenWithFrameName ? pwzTargetFrameName:NULL,
  1176. wszPath,
  1177. pwzLocation);
  1178. }
  1179. else
  1180. {
  1181. ASSERT(dwFlags == 0);
  1182. if (pNavBindCtx)
  1183. {
  1184. _SetPendingNavigateContext(pNavBindCtx, NULL);
  1185. }
  1186. //
  1187. // NOTES: We used to call _pbs->NavigatePidl (in IE3.0), now we call
  1188. // _psb->BrowseObject, so that we ALWAYS hit that code path.
  1189. //
  1190. hres = _BrowseObject(pidl, SBSP_SAMEBROWSER|SBSP_ABSOLUTE);
  1191. }
  1192. exit:
  1193. // clean up
  1194. if (pPostDataArray)
  1195. {
  1196. // done reading from array, unlock it
  1197. SafeArrayUnaccessData(pPostDataArray);
  1198. }
  1199. // If pwzUnprefixedTargetFrameName is non-null, then we allocated and set our own
  1200. // pwzTargetFrameName.
  1201. //
  1202. if (pwzUnprefixedTargetFrameName && pwzTargetFrameName)
  1203. {
  1204. SysFreeString((BSTR) pwzTargetFrameName);
  1205. }
  1206. ATOMICRELEASE(pStubCallback);
  1207. ATOMICRELEASE(pBindCtx);
  1208. Pidl_Set(&pidl, NULL);
  1209. return hres;
  1210. }
  1211. //
  1212. // Parameters:
  1213. // pvaClsid Specifies the bar to be shown/hide
  1214. // pvaShow Specifies whether or not we should show or hide (default is show)
  1215. // pvaSize Specifies the size (optional)
  1216. // HACK: really hoaky nCmdExecOpt overloading...
  1217. //
  1218. HRESULT CIEFrameAuto::ShowBrowserBar(VARIANT * pvaClsid, VARIANT *pvaShow, VARIANT *pvaSize)
  1219. {
  1220. // Use this convenient, marshalable method to show or hide the Address (URL) band, the tool band,
  1221. // or the link band.
  1222. //
  1223. if (pvaShow && pvaShow->vt == VT_EMPTY)
  1224. pvaShow = NULL;
  1225. if (pvaShow && pvaShow->vt != VT_BOOL)
  1226. return DISP_E_TYPEMISMATCH;
  1227. if (pvaClsid->vt == VT_I2
  1228. && (pvaClsid->iVal == FCW_ADDRESSBAR
  1229. || pvaClsid->iVal == FCW_TOOLBAND
  1230. || pvaClsid->iVal == FCW_LINKSBAR))
  1231. {
  1232. return IUnknown_Exec(_pbs, &CGID_Explorer, SBCMDID_SHOWCONTROL,
  1233. MAKELONG(pvaClsid->iVal, pvaShow ? pvaShow->boolVal : 1), NULL, NULL);
  1234. }
  1235. else {
  1236. return IUnknown_Exec(_pbs, &CGID_ShellDocView, SHDVID_SHOWBROWSERBAR,
  1237. pvaShow ? pvaShow->boolVal : 1, pvaClsid, NULL);
  1238. }
  1239. }
  1240. HRESULT CIEFrameAuto::Navigate2(VARIANT * pvURL, VARIANT * pFlags, VARIANT * pTargetFrameName, VARIANT * pPostData, VARIANT * pHeaders)
  1241. {
  1242. HRESULT hr = E_INVALIDARG;
  1243. if (pFlags && ((WORD)(VT_I4) == pFlags->vt) && (pFlags->lVal == navBrowserBar))
  1244. {
  1245. hr = IUnknown_Exec(_pbs, &CGID_ShellDocView, SHDVID_NAVIGATEBB, 0, pvURL, NULL);
  1246. }
  1247. else if (!pvURL)
  1248. {
  1249. hr = Navigate(NULL, NULL, NULL, NULL, NULL);
  1250. }
  1251. else
  1252. {
  1253. LPCWSTR pszURL = VariantToStrCast(pvURL);
  1254. if (pszURL)
  1255. {
  1256. hr = Navigate((BSTR)pszURL, pFlags, pTargetFrameName, pPostData, pHeaders);
  1257. }
  1258. else
  1259. {
  1260. LPITEMIDLIST pidl = VariantToIDList(pvURL);
  1261. if (pidl)
  1262. {
  1263. hr = _BrowseObject(pidl, SBSP_SAMEBROWSER | SBSP_ABSOLUTE);
  1264. ILFree(pidl);
  1265. }
  1266. }
  1267. }
  1268. return hr;
  1269. }
  1270. HRESULT CIEFrameAuto::GoBack()
  1271. {
  1272. HRESULT hr;
  1273. IWebBrowser *pwb;
  1274. if (!IsSameObject(_psb, _psbFrameTop) && _psbFrameTop)
  1275. {
  1276. hr = IUnknown_QueryService(_psbFrameTop, IID_ITargetFrame2, IID_PPV_ARG(IWebBrowser, &pwb));
  1277. if (pwb)
  1278. {
  1279. hr = pwb->GoBack();
  1280. pwb->Release();
  1281. }
  1282. else
  1283. hr = E_FAIL;
  1284. }
  1285. else
  1286. hr = _BrowseObject(NULL, SBSP_SAMEBROWSER|SBSP_NAVIGATEBACK);
  1287. return hr;
  1288. }
  1289. HRESULT CIEFrameAuto::GoForward()
  1290. {
  1291. HRESULT hr;
  1292. IWebBrowser *pwb;
  1293. if (!IsSameObject(_psb, _psbFrameTop) && _psbFrameTop)
  1294. {
  1295. hr = IUnknown_QueryService(_psbFrameTop, IID_ITargetFrame2, IID_PPV_ARG(IWebBrowser, &pwb));
  1296. if (pwb)
  1297. {
  1298. hr = pwb->GoForward();
  1299. pwb->Release();
  1300. }
  1301. else
  1302. hr = E_FAIL;
  1303. }
  1304. else
  1305. hr = _BrowseObject(NULL, SBSP_SAMEBROWSER|SBSP_NAVIGATEFORWARD);
  1306. return hr;
  1307. }
  1308. HRESULT CIEFrameAuto::_GoStdLocation(DWORD dwWhich)
  1309. {
  1310. TraceMsg(TF_SHDAUTO, "Shell automation: CIEFrameAuto:GoHome called");
  1311. HRESULT hres;
  1312. LPITEMIDLIST pidl = NULL;
  1313. HWND hwnd = _GetHWND();
  1314. if (hwnd)
  1315. {
  1316. hres = SHDGetPageLocation(hwnd, dwWhich, NULL, 0, &pidl);
  1317. if (SUCCEEDED(hres)) {
  1318. //
  1319. // NOTES: We used to call _pbs->NavigatePidl (in IE3.0), now we call
  1320. // _psb->BrowseObject, so that we ALWAYS hit that code path.
  1321. //
  1322. hres = _BrowseObject(pidl, SBSP_SAMEBROWSER|SBSP_ABSOLUTE);
  1323. ILFree(pidl);
  1324. }
  1325. }
  1326. else
  1327. {
  1328. hres = S_FALSE;
  1329. }
  1330. return hres;
  1331. }
  1332. HRESULT CIEFrameAuto::GoHome()
  1333. {
  1334. return _GoStdLocation(IDP_START);
  1335. }
  1336. HRESULT CIEFrameAuto::GoSearch()
  1337. {
  1338. return _GoStdLocation(IDP_SEARCH);
  1339. }
  1340. HRESULT CIEFrameAuto::Stop()
  1341. {
  1342. //
  1343. // Calling _CancelPendingNavigation() is not enough here because
  1344. // it does not stop the on-going navigation in the current page.
  1345. // Exec(NULL, OLECMDID_STOP) will cancel pending navigation AND
  1346. // stop the on-going navigation.
  1347. //
  1348. if (_pmsc) {
  1349. return _pmsc->Exec(NULL, OLECMDID_STOP, 0, NULL, NULL);
  1350. }
  1351. return(E_UNEXPECTED);
  1352. }
  1353. HRESULT CIEFrameAuto::Refresh()
  1354. {
  1355. VARIANT v = {0};
  1356. v.vt = VT_I4;
  1357. v.lVal = OLECMDIDF_REFRESH_NO_CACHE;
  1358. return Refresh2(&v);
  1359. }
  1360. HRESULT CIEFrameAuto::Refresh2(VARIANT * Level)
  1361. {
  1362. HRESULT hres = E_FAIL;
  1363. IShellView *psv;
  1364. if (_psb && SUCCEEDED(hres = _psb->QueryActiveShellView(&psv)) && psv)
  1365. {
  1366. hres = IUnknown_Exec(psv, NULL, OLECMDID_REFRESH, OLECMDEXECOPT_PROMPTUSER, Level, NULL);
  1367. psv->Release();
  1368. }
  1369. return hres;
  1370. }
  1371. STDMETHODIMP CIEFrameAuto::get_Container(IDispatch **ppDisp)
  1372. {
  1373. *ppDisp = NULL;
  1374. return NOERROR;
  1375. }
  1376. STDMETHODIMP CIEFrameAuto::get_FullScreen(VARIANT_BOOL * pBool)
  1377. {
  1378. HRESULT hres;
  1379. BOOL bValue;
  1380. if (_pbs==NULL) {
  1381. TraceMsg(DM_WARNING, "CIEA::get_FullScreen called _pbs==NULL");
  1382. return E_FAIL;
  1383. }
  1384. // Put the processing of this in the main Frame class
  1385. bValue = (BOOL)*pBool;
  1386. hres = _pbs->IsControlWindowShown((UINT)-1, &bValue);
  1387. *pBool = TO_VARIANT_BOOL(bValue);
  1388. return hres;
  1389. }
  1390. STDMETHODIMP CIEFrameAuto::put_FullScreen(VARIANT_BOOL Bool)
  1391. {
  1392. HRESULT hres;
  1393. if (_pbs==NULL) {
  1394. TraceMsg(DM_WARNING, "CIEA::put_FullScreen called _pbs==NULL");
  1395. return E_FAIL;
  1396. }
  1397. _pbs->SetFlags(BSF_UISETBYAUTOMATION, BSF_UISETBYAUTOMATION);
  1398. // Put the processing of this in the main Frame class
  1399. hres = _pbs->ShowControlWindow((UINT)-1, (BOOL)Bool);
  1400. FireEvent_OnAdornment(_GetOuter(), DISPID_ONFULLSCREEN, Bool);
  1401. return(hres);
  1402. }
  1403. STDMETHODIMP CIEFrameAuto::get_StatusBar(VARIANT_BOOL * pBool)
  1404. {
  1405. HRESULT hres;
  1406. BOOL bValue;
  1407. if (!pBool)
  1408. return E_INVALIDARG;
  1409. if (_pbs==NULL) {
  1410. TraceMsg(DM_WARNING, "CIEA::get_StatusBar called _pbs==NULL");
  1411. return E_FAIL;
  1412. }
  1413. // Put the processing of this in the main Frame class
  1414. bValue = (BOOL)*pBool;
  1415. hres = _pbs->IsControlWindowShown(FCW_STATUS, &bValue);
  1416. *pBool = TO_VARIANT_BOOL(bValue);
  1417. return hres;
  1418. }
  1419. STDMETHODIMP CIEFrameAuto::put_StatusBar(VARIANT_BOOL Bool)
  1420. {
  1421. HRESULT hres;
  1422. if (_pbs==NULL) {
  1423. TraceMsg(DM_WARNING, "CIEA::put_StatusBar called _pbs==NULL");
  1424. return E_FAIL;
  1425. }
  1426. _pbs->SetFlags(BSF_UISETBYAUTOMATION, BSF_UISETBYAUTOMATION);
  1427. hres = _pbs->ShowControlWindow(FCW_STATUS, (BOOL)Bool);
  1428. FireEvent_OnAdornment(_GetOuter(), DISPID_ONSTATUSBAR, Bool);
  1429. return(hres);
  1430. }
  1431. STDMETHODIMP CIEFrameAuto::get_StatusText(BSTR * pbstr)
  1432. {
  1433. HRESULT hr = E_FAIL;
  1434. *pbstr = NULL; // clear out in case of error...
  1435. if (_pbs)
  1436. {
  1437. IShellBrowser *psb;
  1438. hr = _pbs->QueryInterface(IID_PPV_ARG(IShellBrowser, &psb));
  1439. if (SUCCEEDED(hr))
  1440. {
  1441. LRESULT ret;
  1442. hr = psb->SendControlMsg(FCW_STATUS, SB_GETTEXTLENGTH, 0, 0, &ret);
  1443. if (SUCCEEDED(hr))
  1444. {
  1445. ret++; // #246956: We need to make 2 extra spaces for the end
  1446. *pbstr = SysAllocStringLen(NULL, LOWORD(ret)+1); // ret doesn't include NULL in count
  1447. if (*pbstr)
  1448. {
  1449. hr = psb->SendControlMsg(FCW_STATUS, SB_GETTEXTW, 0, (LPARAM)(*pbstr), &ret);
  1450. if (FAILED(hr))
  1451. {
  1452. SysFreeString(*pbstr);
  1453. *pbstr = NULL;
  1454. }
  1455. }
  1456. else
  1457. {
  1458. hr = E_OUTOFMEMORY;
  1459. }
  1460. }
  1461. psb->Release();
  1462. }
  1463. }
  1464. return hr;
  1465. }
  1466. STDMETHODIMP CIEFrameAuto::put_StatusText(BSTR bstr)
  1467. {
  1468. if (_pbs==NULL)
  1469. {
  1470. TraceMsg(DM_WARNING, "CIEA::put_StatusText called _pbs==NULL");
  1471. return E_FAIL;
  1472. }
  1473. IShellBrowser *psb;
  1474. HRESULT hres = _pbs->QueryInterface(IID_PPV_ARG(IShellBrowser, &psb));
  1475. if (SUCCEEDED(hres))
  1476. {
  1477. hres = psb->SendControlMsg(FCW_STATUS, SB_SETTEXTW, 0, (LPARAM)bstr, NULL);
  1478. psb->Release();
  1479. }
  1480. return hres;
  1481. }
  1482. STDMETHODIMP CIEFrameAuto::get_ToolBar(int * pBool)
  1483. {
  1484. if (_pbs==NULL) {
  1485. TraceMsg(DM_WARNING, "CIEA::get_ToolBar called _pbs==NULL");
  1486. return E_FAIL;
  1487. }
  1488. // Put the processing of this in the main Frame class
  1489. BOOL fShown;
  1490. HRESULT hres;
  1491. *pBool = 0;
  1492. if (SUCCEEDED(hres = _pbs->IsControlWindowShown(FCW_INTERNETBAR, &fShown)) && fShown)
  1493. *pBool = 1;
  1494. // Don't user hres of next call as this will fail on IE3 which does not
  1495. // have a FCW_TOOLBAR control
  1496. else if (SUCCEEDED(_pbs->IsControlWindowShown(FCW_TOOLBAR, &fShown)) && fShown)
  1497. *pBool = 2;
  1498. return hres;
  1499. }
  1500. STDMETHODIMP CIEFrameAuto::put_ToolBar(int Bool)
  1501. {
  1502. HRESULT hres;
  1503. if (_pbs==NULL) {
  1504. TraceMsg(DM_WARNING, "CIEA::put_Toolbar called _pbs==NULL");
  1505. return E_FAIL;
  1506. }
  1507. _pbs->SetFlags(BSF_UISETBYAUTOMATION, BSF_UISETBYAUTOMATION);
  1508. // Put the processing of this in the main Frame class
  1509. _pbs->ShowControlWindow(FCW_TOOLBAR, (Bool == 2));
  1510. hres = _pbs->ShowControlWindow(FCW_INTERNETBAR, ((Bool==1)||(Bool == VARIANT_TRUE)));
  1511. FireEvent_OnAdornment(_GetOuter(), DISPID_ONTOOLBAR, Bool);
  1512. return(hres);
  1513. }
  1514. STDMETHODIMP CIEFrameAuto::get_MenuBar(THIS_ VARIANT_BOOL * pbool)
  1515. {
  1516. BOOL bValue;
  1517. HRESULT hres;
  1518. if (_pbs==NULL) {
  1519. TraceMsg(DM_WARNING, "CIEA::get_MenuBar called _pbs==NULL");
  1520. return E_FAIL;
  1521. }
  1522. if (pbool==NULL)
  1523. return E_INVALIDARG;
  1524. // Put the processing of this in the main Frame class
  1525. bValue = (BOOL)*pbool;
  1526. hres = _pbs->IsControlWindowShown(FCW_MENUBAR, &bValue);
  1527. *pbool = TO_VARIANT_BOOL(bValue);
  1528. return hres;
  1529. }
  1530. STDMETHODIMP CIEFrameAuto::put_MenuBar(THIS_ VARIANT_BOOL mybool)
  1531. {
  1532. HRESULT hres;
  1533. if (_pbs==NULL) {
  1534. TraceMsg(DM_WARNING, "CIEA::put_MenuBar called _pbs==NULL");
  1535. return E_FAIL;
  1536. }
  1537. _pbs->SetFlags(BSF_UISETBYAUTOMATION, BSF_UISETBYAUTOMATION);
  1538. hres = _pbs->ShowControlWindow(FCW_MENUBAR, (BOOL)mybool);
  1539. FireEvent_OnAdornment(_GetOuter(), DISPID_ONMENUBAR, mybool);
  1540. return(hres);
  1541. }
  1542. //
  1543. // IWebBrowser2
  1544. //
  1545. HRESULT CIEFrameAuto::QueryStatusWB(OLECMDID cmdID, OLECMDF * pcmdf)
  1546. {
  1547. if (_pmsc)
  1548. {
  1549. OLECMD rgcmd;
  1550. HRESULT hr;
  1551. rgcmd.cmdID = cmdID;
  1552. rgcmd.cmdf = *pcmdf;
  1553. hr = _pmsc->QueryStatus(NULL, 1, &rgcmd, NULL);
  1554. *pcmdf = (OLECMDF) rgcmd.cmdf;
  1555. return hr;
  1556. }
  1557. return (E_UNEXPECTED);
  1558. }
  1559. HRESULT CIEFrameAuto::ExecWB(OLECMDID cmdID, OLECMDEXECOPT cmdexecopt, VARIANT * pvaIn, VARIANT * pvaOut)
  1560. {
  1561. if (_pmsc)
  1562. {
  1563. return _pmsc->Exec(NULL, cmdID, cmdexecopt, pvaIn, pvaOut);
  1564. }
  1565. return (E_UNEXPECTED);
  1566. }
  1567. STDMETHODIMP CIEFrameAuto::get_Offline(THIS_ VARIANT_BOOL * pbOffline)
  1568. {
  1569. if (!pbOffline)
  1570. return E_INVALIDARG;
  1571. *pbOffline = TO_VARIANT_BOOL(m_bOffline);
  1572. return S_OK;
  1573. }
  1574. void SendAmbientPropChange(IOleCommandTarget* pct, int prop)
  1575. {
  1576. if (pct)
  1577. {
  1578. VARIANTARG VarArgIn;
  1579. VarArgIn.vt = VT_I4;
  1580. VarArgIn.lVal = prop;
  1581. pct->Exec(&CGID_ShellDocView, SHDVID_AMBIENTPROPCHANGE, 0, &VarArgIn, NULL);
  1582. }
  1583. }
  1584. STDMETHODIMP CIEFrameAuto::put_Offline(THIS_ VARIANT_BOOL bOffline)
  1585. {
  1586. TraceMsg(TF_SHDAUTO, "Shell automation: CIEFrameAuto:put_Offline called");
  1587. if ((m_bOffline && bOffline) || (!(m_bOffline || bOffline))) // The mode is not changing
  1588. return S_OK;
  1589. m_bOffline = bOffline ? TRUE : FALSE;
  1590. // Let children know an ambient property may have changed
  1591. //
  1592. SendAmbientPropChange(_pmsc, DISPID_AMBIENT_OFFLINEIFNOTCONNECTED);
  1593. return S_OK;
  1594. }
  1595. STDMETHODIMP CIEFrameAuto::get_Silent(THIS_ VARIANT_BOOL * pbSilent)
  1596. {
  1597. if (!pbSilent)
  1598. return E_INVALIDARG;
  1599. *pbSilent = TO_VARIANT_BOOL(m_bSilent);
  1600. return S_OK;
  1601. }
  1602. STDMETHODIMP CIEFrameAuto::put_Silent(THIS_ VARIANT_BOOL bSilent)
  1603. {
  1604. TraceMsg(TF_SHDAUTO, "Shell automation: CIEFrameAuto:put_Silent called");
  1605. if ((m_bSilent && bSilent) || (!(m_bSilent || bSilent))) // The mode is not changing
  1606. return S_OK;
  1607. m_bSilent = bSilent ? TRUE : FALSE;
  1608. // Let children know an ambient property may have changed
  1609. //
  1610. SendAmbientPropChange(_pmsc, DISPID_AMBIENT_SILENT);
  1611. return S_OK;
  1612. }
  1613. //
  1614. // NOTE: RegisterAsBrowser is a kind of a misnomer here - zekel 8-SEP-97
  1615. // this is used for 3rd party apps to register the browser as being theirs,
  1616. // and not being one of our default shell browsers to use and abuse at
  1617. // our pleasure. this keeps it out of the reusable winlist. this fixes
  1618. // the bug where our welcome.exe page gets reused on a shellexec.
  1619. //
  1620. HRESULT CIEFrameAuto::get_RegisterAsBrowser(VARIANT_BOOL * pbRegister)
  1621. {
  1622. if (pbRegister)
  1623. {
  1624. *pbRegister = _fRegisterAsBrowser ? VARIANT_TRUE : VARIANT_FALSE;
  1625. return S_OK;
  1626. }
  1627. return E_INVALIDARG;
  1628. }
  1629. HRESULT CIEFrameAuto::put_RegisterAsBrowser(VARIANT_BOOL bRegister)
  1630. {
  1631. if (bRegister)
  1632. {
  1633. if (_pbs == NULL) //Make sure we have a IBrowserService.
  1634. return S_FALSE;
  1635. _fRegisterAsBrowser = TRUE;
  1636. _pbs->RegisterWindow(TRUE, SWC_3RDPARTY);
  1637. return S_OK;
  1638. }
  1639. //
  1640. // we dont support a way to turn it off
  1641. return E_FAIL;
  1642. }
  1643. HRESULT CIEFrameAuto::get_TheaterMode(VARIANT_BOOL * pbRegister)
  1644. {
  1645. if (!pbRegister)
  1646. return E_INVALIDARG;
  1647. if (_pbs) {
  1648. DWORD dw;
  1649. _pbs->GetFlags(&dw);
  1650. *pbRegister = TO_VARIANT_BOOL(dw & BSF_THEATERMODE);
  1651. return S_OK;
  1652. }
  1653. // rgardner poor choice of return error code - need better error
  1654. // This error puts of "undefined error" dialog
  1655. return E_FAIL;
  1656. }
  1657. HRESULT CIEFrameAuto::put_TheaterMode(VARIANT_BOOL bRegister)
  1658. {
  1659. if (_pbs) {
  1660. _pbs->SetFlags(bRegister ? BSF_THEATERMODE : 0, BSF_THEATERMODE);
  1661. return S_OK;
  1662. }
  1663. return S_FALSE;
  1664. }
  1665. HRESULT CIEFrameAuto::get_RegisterAsDropTarget(VARIANT_BOOL * pbRegister)
  1666. {
  1667. if (!pbRegister)
  1668. return E_INVALIDARG;
  1669. if (_pbs==NULL) {
  1670. TraceMsg(DM_WARNING, "CIEA::get_RegisterAsDropTarget called _pbs==NULL");
  1671. return E_FAIL;
  1672. }
  1673. DWORD dw;
  1674. _pbs->GetFlags(&dw);
  1675. *pbRegister = TO_VARIANT_BOOL(dw & BSF_REGISTERASDROPTARGET);
  1676. return S_OK;
  1677. }
  1678. HRESULT CIEFrameAuto::put_RegisterAsDropTarget(VARIANT_BOOL bRegister)
  1679. {
  1680. if (_pbs==NULL) {
  1681. TraceMsg(DM_WARNING, "CIEA::put_RegisterAsDropTarget called _pbs==NULL");
  1682. return E_FAIL;
  1683. }
  1684. _pbs->SetFlags(bRegister ? BSF_REGISTERASDROPTARGET : 0, BSF_REGISTERASDROPTARGET);
  1685. return S_OK;
  1686. }
  1687. HRESULT CIEFrameAuto::get_AddressBar(VARIANT_BOOL * pValue)
  1688. {
  1689. BOOL bValue;
  1690. HRESULT hres;
  1691. if (!pValue)
  1692. return E_INVALIDARG;
  1693. if (_pbs==NULL) {
  1694. TraceMsg(DM_WARNING, "CIEA::get_AddressBar called _pbs==NULL");
  1695. return E_FAIL;
  1696. }
  1697. // Put the processing of this in the main Frame class
  1698. bValue = (BOOL)*pValue;
  1699. hres = _pbs->IsControlWindowShown(FCW_ADDRESSBAR, &bValue);
  1700. *pValue = TO_VARIANT_BOOL(bValue);
  1701. return hres;
  1702. }
  1703. HRESULT CIEFrameAuto::put_AddressBar(VARIANT_BOOL Value)
  1704. {
  1705. HRESULT hres;
  1706. if (_pbs==NULL) {
  1707. TraceMsg(DM_WARNING, "CIEA::put_AddressBar called _pbs==NULL");
  1708. return E_FAIL;
  1709. }
  1710. _pbs->SetFlags(BSF_UISETBYAUTOMATION, BSF_UISETBYAUTOMATION);
  1711. hres = _pbs->ShowControlWindow(FCW_ADDRESSBAR, (BOOL)Value);
  1712. FireEvent_OnAdornment(_GetOuter(), DISPID_ONADDRESSBAR, Value);
  1713. return(hres);
  1714. }
  1715. HRESULT CIEFrameAuto::get_Resizable(VARIANT_BOOL * pValue)
  1716. {
  1717. HRESULT hres;
  1718. DWORD dw;
  1719. if (!pValue)
  1720. return E_INVALIDARG;
  1721. if (_pbs==NULL)
  1722. {
  1723. TraceMsg(DM_WARNING, "CIEA::get_Resizable called _pbs==NULL");
  1724. return E_FAIL;
  1725. }
  1726. hres = _pbs->GetFlags(&dw);
  1727. *pValue = TO_VARIANT_BOOL (dw & BSF_RESIZABLE);
  1728. return hres;
  1729. }
  1730. HRESULT CIEFrameAuto::put_Resizable(VARIANT_BOOL Value)
  1731. {
  1732. HRESULT hres;
  1733. if (_pbs==NULL)
  1734. {
  1735. TraceMsg(DM_WARNING, "CIEA::put_Resizable called _pbs==NULL");
  1736. return E_FAIL;
  1737. }
  1738. hres = _pbs->SetFlags(
  1739. Value ? (BSF_RESIZABLE | BSF_CANMAXIMIZE) : 0,
  1740. (BSF_RESIZABLE | BSF_CANMAXIMIZE));
  1741. return hres ;
  1742. }
  1743. void UpdateBrowserReadyState(IUnknown * punk, DWORD dwReadyState)
  1744. {
  1745. if (punk)
  1746. {
  1747. IDocNavigate *pdn;
  1748. if (SUCCEEDED(punk->QueryInterface(IID_PPV_ARG(IDocNavigate, &pdn))))
  1749. {
  1750. pdn->OnReadyStateChange(NULL, dwReadyState);
  1751. pdn->Release();
  1752. }
  1753. }
  1754. }
  1755. HRESULT CIEFrameAuto::put_DefaultReadyState(DWORD dwDefaultReadyState, BOOL fUpdateBrowserReadyState)
  1756. {
  1757. _dwDefaultReadyState = dwDefaultReadyState;
  1758. TraceMsg(TF_SHDNAVIGATE, "CIEA(%x)::psb(%x) new default ReadyState %d", this, _psb, dwDefaultReadyState);
  1759. if (fUpdateBrowserReadyState)
  1760. {
  1761. UpdateBrowserReadyState(_psb, _dwDefaultReadyState);
  1762. }
  1763. return S_OK;
  1764. }
  1765. HRESULT CIEFrameAuto::OnDocumentComplete(void)
  1766. {
  1767. TraceMsg(DM_FRAMEPROPERTY, "CIEFA::OnDocumentComplete called");
  1768. DWORD dwCur = GetCurrentTime();
  1769. VARIANT varEmpty = { 0 };
  1770. if (dwCur - _dwTickPropertySweep > MSEC_PROPSWEEP) {
  1771. TraceMsg(DM_FRAMEPROPERTY, "CIEFA::OnDocumentComplete start sweeping");
  1772. for (CIEFrameAutoProp *pprop = _pProps; pprop;) {
  1773. CIEFrameAutoProp* ppropNext = pprop->Next();
  1774. if (pprop->IsExpired(dwCur)) {
  1775. TraceMsg(DM_FRAMEPROPERTY, "CIEFA::OnDocumentComplete deleting an expired property");
  1776. pprop->SetValue(&varEmpty, this);
  1777. }
  1778. pprop=ppropNext;
  1779. }
  1780. _dwTickPropertySweep = dwCur;
  1781. }
  1782. return S_OK;
  1783. }
  1784. HRESULT CIEFrameAuto::OnWindowsListMarshalled(void)
  1785. {
  1786. _fWindowsListMarshalled = TRUE;
  1787. return S_OK;
  1788. }
  1789. HRESULT CIEFrameAuto::SetDocHostFlags(DWORD dwDocHostFlags)
  1790. {
  1791. _dwDocHostInfoFlags = dwDocHostFlags;
  1792. return S_OK;
  1793. }
  1794. HRESULT CIEFrameAuto::get_ReadyState(READYSTATE * plReadyState)
  1795. {
  1796. READYSTATE lReadyState = (READYSTATE)_dwDefaultReadyState;
  1797. if (_psb)
  1798. {
  1799. IDocNavigate* pdn;
  1800. if (SUCCEEDED(_psb->QueryInterface(IID_PPV_ARG(IDocNavigate, &pdn))))
  1801. {
  1802. pdn->get_ReadyState((LPDWORD)&lReadyState);
  1803. pdn->Release();
  1804. }
  1805. }
  1806. TraceMsg(TF_SHDNAVIGATE, "CIEA(%x)::psb(%x)->get_ReadyState returning %d", this, _psb, lReadyState);
  1807. *plReadyState = lReadyState;
  1808. return S_OK;
  1809. }
  1810. STDMETHODIMP CIEFrameAuto::get_TopLevelContainer(VARIANT_BOOL * pBool)
  1811. {
  1812. *pBool = TRUE;
  1813. return NOERROR;
  1814. }
  1815. STDMETHODIMP CIEFrameAuto::get_Type(BSTR * pbstrType)
  1816. {
  1817. HRESULT hres = E_FAIL;
  1818. *pbstrType = NULL;
  1819. IShellView *psv;
  1820. if (_psb && SUCCEEDED(hres = _psb->QueryActiveShellView(&psv)) && psv)
  1821. {
  1822. IOleObject *pobj;
  1823. hres = SafeGetItemObject(psv, SVGIO_BACKGROUND, IID_PPV_ARG(IOleObject, &pobj));
  1824. if (SUCCEEDED(hres))
  1825. {
  1826. LPOLESTR pwszUserType;
  1827. hres = pobj->GetUserType(USERCLASSTYPE_FULL, &pwszUserType);
  1828. if (hres == OLE_S_USEREG)
  1829. {
  1830. CLSID clsid;
  1831. hres = pobj->GetUserClassID(&clsid);
  1832. if (SUCCEEDED(hres))
  1833. {
  1834. hres = OleRegGetUserType(clsid, USERCLASSTYPE_FULL, &pwszUserType);
  1835. }
  1836. }
  1837. if (SUCCEEDED(hres) && pwszUserType)
  1838. {
  1839. *pbstrType = SysAllocString(pwszUserType);
  1840. if (*pbstrType == NULL)
  1841. {
  1842. hres = E_OUTOFMEMORY;
  1843. }
  1844. OleFree(pwszUserType);
  1845. }
  1846. pobj->Release();
  1847. }
  1848. psv->Release();
  1849. }
  1850. return hres;
  1851. }
  1852. HRESULT CIEFrameAuto::SetOwner(IUnknown* punkOwner)
  1853. {
  1854. ATOMICRELEASE(_pbs);
  1855. ATOMICRELEASE(_psp);
  1856. ATOMICRELEASE(_psb);
  1857. ATOMICRELEASE(_psbProxy);
  1858. ATOMICRELEASE(_poctFrameTop);
  1859. ATOMICRELEASE(_psbFrameTop);
  1860. ATOMICRELEASE(_psbTop);
  1861. ATOMICRELEASE(_pmsc);
  1862. if (punkOwner)
  1863. {
  1864. // Check if we're the desktop - if so, we do not act as
  1865. // parent frame to our children (desktop components)
  1866. _fDesktopFrame = FALSE;
  1867. IUnknown *punkDesktop;
  1868. if (SUCCEEDED(punkOwner->QueryInterface(SID_SShellDesktop, (void **)&punkDesktop)))
  1869. {
  1870. _fDesktopFrame = TRUE;
  1871. punkDesktop->Release();
  1872. }
  1873. punkOwner->QueryInterface(IID_PPV_ARG(IBrowserService, &_pbs));
  1874. punkOwner->QueryInterface(IID_PPV_ARG(IShellBrowser, &_psb));
  1875. UpdateBrowserReadyState(_psb, _dwDefaultReadyState);
  1876. HRESULT hresT = punkOwner->QueryInterface(IID_PPV_ARG(IServiceProvider, &_psp));
  1877. if (SUCCEEDED(hresT))
  1878. {
  1879. _psp->QueryService(SID_SShellBrowser, IID_PPV_ARG(IOleCommandTarget, &_pmsc));
  1880. _psp->QueryService(SID_STopLevelBrowser, IID_PPV_ARG(IShellBrowser, &_psbTop));
  1881. _psp->QueryService(SID_STopFrameBrowser, IID_PPV_ARG(IShellBrowser, &_psbFrameTop));
  1882. // this is the browser we should tell to navigate if we're asked to navigate
  1883. _psp->QueryService(SID_SProxyBrowser, IID_PPV_ARG(IShellBrowser, &_psbProxy));
  1884. if (!_psbProxy)
  1885. {
  1886. _psbProxy = _psb;
  1887. _psbProxy->AddRef();
  1888. }
  1889. // we use _poctFrameTop::Exec to set history selection pidl
  1890. if (_psbFrameTop && _psbProxy == _psb)
  1891. {
  1892. _psbFrameTop->QueryInterface(IID_PPV_ARG(IOleCommandTarget, &_poctFrameTop));
  1893. }
  1894. // We should always have one of these -- used to notify of frame closing
  1895. // and new window navigation.
  1896. ASSERT(_psbTop);
  1897. ASSERT(_psbFrameTop);
  1898. // Since the desktop does not support IOleCommandTarget (intentionally)
  1899. // _pmsc could be NULL. No need to RIP here.
  1900. //
  1901. // ASSERT(_pmsc);
  1902. }
  1903. ASSERT(_pbs);
  1904. ASSERT(_psp);
  1905. ASSERT(_psb);
  1906. }
  1907. else
  1908. {
  1909. _omwin.DeInit();
  1910. //
  1911. // We need to clear the property list here (than in the destructor)
  1912. // to break the circular ref-count.
  1913. //
  1914. _ClearPropertyList();
  1915. }
  1916. return S_OK;
  1917. }
  1918. HRESULT CIEFrameAuto::SetOwnerHwnd(HWND hwndOwner)
  1919. {
  1920. _hwnd = hwndOwner;
  1921. return S_OK;
  1922. }
  1923. HWND CIEFrameAuto::_GetHWND()
  1924. {
  1925. if (!_hwnd && _pbs)
  1926. {
  1927. IOleWindow * pow;
  1928. if (SUCCEEDED(_pbs->QueryInterface(IID_PPV_ARG(IOleWindow, &pow))))
  1929. {
  1930. pow->GetWindow(&_hwnd);
  1931. pow->Release();
  1932. }
  1933. }
  1934. // people that call this assume that we always succeed
  1935. //
  1936. // ... people who call this better quit making incorrect
  1937. // assumptions. If we can't guarantee an hwnd the caller
  1938. // can't assume they'll be getting one. (edwardp)
  1939. if (_hwnd == NULL)
  1940. {
  1941. TraceMsg(DM_WARNING, "CIEA::_GetHWND returning NULL");
  1942. }
  1943. return _hwnd;
  1944. }
  1945. // *** IConnectionPointContainer ***
  1946. CConnectionPoint* CIEFrameAuto::_FindCConnectionPointNoRef(BOOL fdisp, REFIID iid)
  1947. {
  1948. CConnectionPoint* pccp;
  1949. // VB team claims its safe to fire new dispids to old event sinks.
  1950. // This will cause a fault on an old event sink if they assumed
  1951. // only the dispids in the old typelib would ever be fired and they
  1952. // did no bounds checking and jumped into space. Let's trust the VB
  1953. // team and see if we discover any poor event sinks.
  1954. //
  1955. // They also say we sould just extend our primary dispinterface instead
  1956. // of replace it with an equivalent but different one. That approach
  1957. // unfortunately leaves the offending bad event mechanism sit in
  1958. // the VB programmer's face.
  1959. //
  1960. // I want to do three things:
  1961. // 1. Change the primary dispinterface to see what headaches that causes.
  1962. // This has nice positives and its easy to change back later. (fdisp==TRUE case)
  1963. // 2. Don't fire old events to consumers of the new dispinterface.
  1964. // This will flush out any compatability issues of containers
  1965. // connecting to the default dispinterface when they really
  1966. // wanted the old DIID.
  1967. // 3. Do fire new events to old sinks. This will flush out any
  1968. // compatability issues with VBs theory.
  1969. //
  1970. // We can't do all three, so let's choose 1 and 2. We can
  1971. // force 3 by randomly firing out-of-range dispids if this
  1972. // is important...
  1973. //
  1974. if (IsEqualIID(iid, DIID_DWebBrowserEvents2) ||
  1975. (fdisp && IsEqualIID(iid, IID_IDispatch)))
  1976. {
  1977. pccp = &m_cpWebBrowserEvents2;
  1978. }
  1979. else if (IsEqualIID(iid, DIID_DWebBrowserEvents))
  1980. {
  1981. pccp = &m_cpWebBrowserEvents;
  1982. }
  1983. else if (IsEqualIID(iid, IID_IPropertyNotifySink))
  1984. {
  1985. pccp = &m_cpPropNotify;
  1986. }
  1987. else
  1988. {
  1989. pccp = NULL;
  1990. }
  1991. return pccp;
  1992. }
  1993. STDMETHODIMP CIEFrameAuto::EnumConnectionPoints(LPENUMCONNECTIONPOINTS * ppEnum)
  1994. {
  1995. return CreateInstance_IEnumConnectionPoints(ppEnum, 3,
  1996. m_cpWebBrowserEvents2.CastToIConnectionPoint(),
  1997. m_cpWebBrowserEvents.CastToIConnectionPoint(),
  1998. m_cpPropNotify.CastToIConnectionPoint());
  1999. }
  2000. //=============================================================================
  2001. // Our class factory
  2002. class CIEFrameClassFactory : public IClassFactory
  2003. {
  2004. public:
  2005. CIEFrameClassFactory(IUnknown* punkAuto, REFCLSID clsid, UINT uFlags);
  2006. // IUnKnown
  2007. STDMETHODIMP QueryInterface(REFIID, void **);
  2008. STDMETHODIMP_(ULONG) AddRef(void);
  2009. STDMETHODIMP_(ULONG) Release(void);
  2010. // IClassFactory
  2011. STDMETHODIMP CreateInstance(
  2012. IUnknown *pUnkOuter, REFIID riid, void **ppvObject);
  2013. STDMETHODIMP LockServer(BOOL fLock);
  2014. // Helper functions...
  2015. HRESULT CleanUpAutomationObject();
  2016. void Revoke(void);
  2017. protected:
  2018. ~CIEFrameClassFactory();
  2019. LONG _cRef;
  2020. IUnknown *_punkAuto; // Only for the first one for the process
  2021. DWORD _dwRegister; // The value returned from CoRegisterClassObject;
  2022. UINT _uFlags; // extra COF_ bits to pass to our create browser window code
  2023. };
  2024. #define AssertParking() ASSERT(g_tidParking==0 || g_tidParking == GetCurrentThreadId())
  2025. #ifdef NO_MARSHALLING
  2026. EXTERN_C void IEFrameNewWindowSameThread(IETHREADPARAM* piei);
  2027. #endif
  2028. CIEFrameClassFactory::CIEFrameClassFactory(IUnknown* punkAuto, REFCLSID clsid, UINT uFlags)
  2029. : _cRef(1), _dwRegister((DWORD)-1), _uFlags(uFlags)
  2030. {
  2031. AssertParking();
  2032. if (punkAuto)
  2033. {
  2034. _punkAuto = punkAuto;
  2035. punkAuto->AddRef();
  2036. }
  2037. HRESULT hres = CoRegisterClassObject(clsid, this, CLSCTX_LOCAL_SERVER | CLSCTX_INPROC_SERVER,
  2038. REGCLS_MULTIPLEUSE, &_dwRegister);
  2039. if (FAILED(hres))
  2040. {
  2041. _dwRegister = (DWORD)-1;
  2042. }
  2043. TraceMsg(TF_SHDLIFE, "ctor CIEFrameClassFactory %x", this);
  2044. }
  2045. CIEFrameClassFactory::~CIEFrameClassFactory()
  2046. {
  2047. AssertParking();
  2048. ASSERT(_dwRegister == (DWORD)-1);
  2049. if (_punkAuto)
  2050. _punkAuto->Release();
  2051. TraceMsg(TF_SHDLIFE, "dtor CIEFrameClassFactory %x", this);
  2052. }
  2053. void CIEFrameClassFactory::Revoke(void)
  2054. {
  2055. if (_dwRegister != (DWORD)-1)
  2056. {
  2057. CoRevokeClassObject(_dwRegister);
  2058. _dwRegister = (DWORD)-1;
  2059. }
  2060. }
  2061. HRESULT CIEFrameClassFactory::QueryInterface(REFIID riid, void **ppvObj)
  2062. {
  2063. static const QITAB qit[] = {
  2064. QITABENT(CIEFrameClassFactory, IClassFactory), // IID_IClassFactory
  2065. { 0 },
  2066. };
  2067. return QISearch(this, qit, riid, ppvObj);
  2068. }
  2069. ULONG CIEFrameClassFactory::AddRef(void)
  2070. {
  2071. return InterlockedIncrement(&_cRef);
  2072. }
  2073. ULONG CIEFrameClassFactory::Release(void)
  2074. {
  2075. ASSERT( 0 != _cRef );
  2076. ULONG cRef = InterlockedDecrement(&_cRef);
  2077. if ( 0 == cRef )
  2078. {
  2079. delete this;
  2080. }
  2081. return cRef;
  2082. }
  2083. //
  2084. // We call this function to clean up the automation object if something
  2085. // goes wrong and OLE did not pick it up. Under a normal circumstance,
  2086. // _punkAuto is supposed to be NULL.
  2087. //
  2088. HRESULT CIEFrameClassFactory::CleanUpAutomationObject()
  2089. {
  2090. AssertParking();
  2091. ASSERT(_punkAuto==NULL);
  2092. ATOMICRELEASE(_punkAuto);
  2093. return S_OK;
  2094. }
  2095. class IETHREADHANDSHAKE : public IEFreeThreadedHandShake
  2096. {
  2097. public:
  2098. // *** IUnknown methods ***
  2099. STDMETHODIMP QueryInterface(THIS_ REFIID riid, void ** ppvObj) { *ppvObj = NULL; return E_NOTIMPL; } // HACK: we're not a real com object
  2100. STDMETHODIMP_(ULONG) AddRef(THIS);
  2101. STDMETHODIMP_(ULONG) Release(THIS);
  2102. // *** IIEFreeThreadedHandShake methods ***
  2103. STDMETHODIMP_(void) PutHevent(THIS_ HANDLE hevent) { _hevent = hevent; }
  2104. STDMETHODIMP_(HANDLE) GetHevent(THIS) { return _hevent; }
  2105. STDMETHODIMP_(void) PutHresult(THIS_ HRESULT hres) { _hres = hres; }
  2106. STDMETHODIMP_(HRESULT) GetHresult(THIS) { return _hres; }
  2107. STDMETHODIMP_(IStream*) GetStream(THIS) { return _pstm; }
  2108. protected:
  2109. LONG _cRef; // ref-count (must be thread safe)
  2110. HANDLE _hevent;
  2111. IStream* _pstm;
  2112. HRESULT _hres; // result from CoMarshalInterface
  2113. friend IEFreeThreadedHandShake* CreateIETHREADHANDSHAKE();
  2114. IETHREADHANDSHAKE(HANDLE heventIn, IStream* pstmIn);
  2115. ~IETHREADHANDSHAKE();
  2116. };
  2117. IETHREADHANDSHAKE::IETHREADHANDSHAKE(HANDLE heventIn, IStream* pstmIn)
  2118. : _cRef(1), _hevent(heventIn), _pstm(pstmIn), _hres(E_FAIL)
  2119. {
  2120. TraceMsg(TF_SHDLIFE, "ctor IETHREADHANDSHAKE %x", this);
  2121. ASSERT(_hevent);
  2122. ASSERT(_pstm);
  2123. _pstm->AddRef();
  2124. }
  2125. IETHREADHANDSHAKE::~IETHREADHANDSHAKE()
  2126. {
  2127. TraceMsg(TF_SHDLIFE, "dtor IETHREADHANDSHAKE %x", this);
  2128. CloseHandle(_hevent);
  2129. _pstm->Release();
  2130. }
  2131. ULONG IETHREADHANDSHAKE::AddRef()
  2132. {
  2133. return InterlockedIncrement(&_cRef);
  2134. }
  2135. ULONG IETHREADHANDSHAKE::Release()
  2136. {
  2137. ASSERT( 0 != _cRef );
  2138. ULONG cRef = InterlockedDecrement(&_cRef);
  2139. if ( 0 == cRef )
  2140. {
  2141. delete this;
  2142. }
  2143. return cRef;
  2144. }
  2145. IEFreeThreadedHandShake* CreateIETHREADHANDSHAKE()
  2146. {
  2147. IEFreeThreadedHandShake* piehs = NULL;
  2148. HANDLE hevent = CreateEvent(NULL, TRUE, FALSE, NULL);
  2149. if (hevent)
  2150. {
  2151. IStream* pstm;
  2152. HRESULT hres = CreateStreamOnHGlobal(NULL, TRUE, &pstm);
  2153. if (SUCCEEDED(hres))
  2154. {
  2155. IETHREADHANDSHAKE* p = new IETHREADHANDSHAKE(hevent, pstm);
  2156. if (p)
  2157. {
  2158. // this is free threaded, so we can't know which thread will free it.
  2159. // technically our caller should do this, but we return an
  2160. // interface and not the class itself...
  2161. piehs = SAFECAST(p, IEFreeThreadedHandShake*);
  2162. }
  2163. pstm->Release();
  2164. }
  2165. if (!piehs)
  2166. CloseHandle(hevent);
  2167. }
  2168. return piehs;
  2169. }
  2170. HRESULT CIEFrameClassFactory::CreateInstance(IUnknown *pUnkOuter, REFIID riid, void **ppvObject)
  2171. {
  2172. HRESULT hres = E_FAIL;
  2173. //
  2174. // Check if this is the very first automation request.
  2175. //
  2176. if (_punkAuto && g_tidParking == GetCurrentThreadId())
  2177. {
  2178. //
  2179. // Yes, return the first browser object.
  2180. //
  2181. hres = _punkAuto->QueryInterface(riid, ppvObject);
  2182. // We don't want to return it twice.
  2183. ATOMICRELEASE(_punkAuto);
  2184. }
  2185. else
  2186. {
  2187. #ifndef NO_MARSHALLING
  2188. //
  2189. // No, create a new browser window in a new thread and
  2190. // return a marshalled pointer.
  2191. //
  2192. hres = E_OUTOFMEMORY;
  2193. IEFreeThreadedHandShake* piehs = CreateIETHREADHANDSHAKE();
  2194. if (piehs)
  2195. {
  2196. IETHREADPARAM *piei = SHCreateIETHREADPARAM(NULL, SW_SHOWNORMAL, NULL, piehs);
  2197. if (piei)
  2198. {
  2199. piei->uFlags |= (_uFlags | COF_CREATENEWWINDOW | COF_NOFINDWINDOW | COF_INPROC);
  2200. DWORD idThread;
  2201. HANDLE hthread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)SHOpenFolderWindow, piei, 0, &idThread);
  2202. if (hthread)
  2203. {
  2204. // Wait until either
  2205. // (1) the thread is terminated
  2206. // (2) the event is signaled (by the new thread)
  2207. // (3) time-out
  2208. //
  2209. // Note that we call MsgWaitForMultipleObjects
  2210. // to avoid dead lock in case the other thread
  2211. // sends a broadcast message to us (unlikely, but
  2212. // theoreticallly possible).
  2213. //
  2214. HANDLE ah[] = { piehs->GetHevent(), hthread };
  2215. DWORD dwStart = GetTickCount();
  2216. #define MSEC_MAXWAIT (30 * 1000)
  2217. DWORD dwWait = MSEC_MAXWAIT;
  2218. DWORD dwWaitResult;
  2219. do {
  2220. dwWaitResult = MsgWaitForMultipleObjects(ARRAYSIZE(ah), ah, FALSE,
  2221. dwWait, QS_SENDMESSAGE);
  2222. if (dwWaitResult == WAIT_OBJECT_0 + ARRAYSIZE(ah)) // msg input
  2223. {
  2224. // allow pending SendMessage() to go through
  2225. MSG msg;
  2226. PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE);
  2227. }
  2228. else
  2229. break; // signaled or timed out, exit the loop
  2230. // Update the dwWait. It will become larger
  2231. // than MSEC_MAXWAIT if we wait more than that.
  2232. dwWait = dwStart + MSEC_MAXWAIT - GetTickCount();
  2233. } while (dwWait <= MSEC_MAXWAIT);
  2234. switch (dwWaitResult)
  2235. {
  2236. default:
  2237. ASSERT(0);
  2238. case WAIT_OBJECT_0 + 1:
  2239. TraceMsg(DM_ERROR, "CIECF::CI thread terminated before signaling us"); // probably leak the IETHREADPARAM and IETHREADHANDSHAKE in this case
  2240. hres = E_FAIL;
  2241. break;
  2242. case WAIT_OBJECT_0 + ARRAYSIZE(ah): // msg input
  2243. case WAIT_TIMEOUT:
  2244. TraceMsg(DM_ERROR, "CIECF::CI time out");
  2245. hres = E_FAIL;
  2246. break;
  2247. case WAIT_OBJECT_0: // hevent signaled
  2248. hres = piehs->GetHresult();
  2249. if (SUCCEEDED(hres))
  2250. {
  2251. IStream* pstm = piehs->GetStream();
  2252. pstm->Seek(c_li0, STREAM_SEEK_SET, NULL);
  2253. hres = CoUnmarshalInterface(pstm, riid, ppvObject);
  2254. }
  2255. else
  2256. TraceMsg(DM_ERROR, "CIECF::CI piehs->hres has an error %x", hres);
  2257. break;
  2258. }
  2259. CloseHandle(hthread);
  2260. }
  2261. else
  2262. {
  2263. SHDestroyIETHREADPARAM(piei);
  2264. hres = E_OUTOFMEMORY;
  2265. }
  2266. }
  2267. else
  2268. {
  2269. hres = E_OUTOFMEMORY;
  2270. TraceMsg(DM_ERROR, "CIECF::CI new IETHREADPARAM failed");
  2271. }
  2272. piehs->Release();
  2273. }
  2274. #else // !NO_MARSHALLING
  2275. //
  2276. // Create a new window on the same thread
  2277. //
  2278. IEFreeThreadedHandShake* piehs = CreateIETHREADHANDSHAKE();
  2279. if (piehs)
  2280. {
  2281. IETHREADPARAM* piei = SHCreateIETHREADPARAM(NULL, SW_SHOWNORMAL, NULL, piehs);
  2282. if (piei)
  2283. IEFrameNewWindowSameThread(piei);
  2284. if (SUCCEEDED(piehs->GetHresult()))
  2285. {
  2286. IUnknown* punk;
  2287. IStream * pstm = piehs->GetStream();
  2288. if (pstm)
  2289. {
  2290. ULONG pcbRead = 0;
  2291. pstm->Seek(c_li0, STREAM_SEEK_SET, NULL);
  2292. hres = pstm->Read(&punk, sizeof(punk), &pcbRead);
  2293. if (SUCCEEDED(hres))
  2294. {
  2295. hres = punk->QueryInterface(riid, ppvObject);
  2296. punk->Release();
  2297. }
  2298. }
  2299. }
  2300. else
  2301. {
  2302. hres = piehs->GetHresult();
  2303. TraceMsg(DM_ERROR, "CIECF::CI piehs->hres has an error %x", piehs->GetHresult());
  2304. }
  2305. piehs->Release();
  2306. }
  2307. #endif // NO_MARSHALLING
  2308. }
  2309. return hres;
  2310. }
  2311. HRESULT CIEFrameClassFactory::LockServer(BOOL fLock)
  2312. {
  2313. return S_OK;
  2314. }
  2315. BOOL Is98orEarlier()
  2316. {
  2317. BOOL bRet = FALSE;
  2318. OSVERSIONINFOA s_osvi;
  2319. s_osvi.dwOSVersionInfoSize = sizeof(s_osvi);
  2320. GetVersionExA(&s_osvi);
  2321. bRet = s_osvi.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS &&
  2322. s_osvi.dwMajorVersion == 4;
  2323. return bRet;
  2324. }
  2325. void GetEventURL(LPCITEMIDLIST pidl, LBSTR::CString & p_rstrPath)
  2326. {
  2327. HRESULT hres = E_FAIL;
  2328. if (pidl)
  2329. {
  2330. LPTSTR pstrPath = p_rstrPath.GetBuffer(MAX_URL_STRING);
  2331. if (p_rstrPath.GetAllocLength() < MAX_URL_STRING)
  2332. {
  2333. TraceMsg(TF_WARNING, "GetEventURL() - p_rstrPath Allocation Failed!");
  2334. hres = E_OUTOFMEMORY;
  2335. }
  2336. else
  2337. {
  2338. hres = IEGetDisplayName(pidl, pstrPath, SHGDN_FORPARSING);
  2339. // Let CString class own the buffer again.
  2340. p_rstrPath.ReleaseBuffer();
  2341. }
  2342. if (FAILED(hres) && Is98orEarlier())
  2343. {
  2344. LBSTR::CString strTempUrl;
  2345. LPTSTR pstrTempUrl = strTempUrl.GetBuffer(INTERNET_MAX_URL_LENGTH);
  2346. if (strTempUrl.GetAllocLength() < INTERNET_MAX_URL_LENGTH)
  2347. {
  2348. TraceMsg(TF_WARNING, "GetEventURL() - strTempUrl Allocation Failed!");
  2349. hres = E_OUTOFMEMORY;
  2350. }
  2351. else
  2352. {
  2353. hres = IEGetDisplayName(pidl, pstrTempUrl, SHGDN_NORMAL);
  2354. // Let CString class own the buffer again.
  2355. strTempUrl.ReleaseBuffer();
  2356. }
  2357. if (SUCCEEDED(hres))
  2358. {
  2359. LPTSTR pFoundStr = NULL;
  2360. BOOL bNotMachineName = FALSE;
  2361. pFoundStr = StrChr(strTempUrl, _T(':'));
  2362. if (pFoundStr)
  2363. {
  2364. bNotMachineName = TRUE;
  2365. }
  2366. else if ((strTempUrl[0] == _T('\\')) ||
  2367. (strTempUrl[0] == _T('/')))
  2368. {
  2369. bNotMachineName = TRUE;
  2370. }
  2371. if (bNotMachineName)
  2372. {
  2373. p_rstrPath = strTempUrl;
  2374. }
  2375. else
  2376. {
  2377. p_rstrPath = _T("\\\\") + strTempUrl;
  2378. }
  2379. }
  2380. }
  2381. }
  2382. if (FAILED(hres))
  2383. {
  2384. p_rstrPath.Empty();
  2385. }
  2386. }
  2387. HRESULT GetWBConnectionPoints(IUnknown* punk, IConnectionPoint **ppccp1, IConnectionPoint **ppccp2);
  2388. HRESULT GetTopWBConnectionPoints(IUnknown* punk, IConnectionPoint **ppccpTop1, IConnectionPoint **ppccpTop2)
  2389. {
  2390. HRESULT hres = E_FAIL;
  2391. if (ppccpTop1)
  2392. *ppccpTop1 = NULL;
  2393. if (ppccpTop2)
  2394. *ppccpTop2 = NULL;
  2395. IServiceProvider *pspSB;
  2396. if (punk && SUCCEEDED(IUnknown_QueryService(punk, SID_STopFrameBrowser, IID_PPV_ARG(IServiceProvider, &pspSB))))
  2397. {
  2398. IWebBrowser2 *pwb;
  2399. if (SUCCEEDED(pspSB->QueryService(SID_SInternetExplorer, IID_PPV_ARG(IWebBrowser2, &pwb))))
  2400. {
  2401. // We only want the toplevel interfaces if we're a frameset
  2402. //
  2403. if (!IsSameObject(punk, pwb))
  2404. {
  2405. hres = GetWBConnectionPoints(pwb, ppccpTop1, ppccpTop2);
  2406. }
  2407. pwb->Release();
  2408. }
  2409. pspSB->Release();
  2410. }
  2411. return hres;
  2412. }
  2413. // Fires a NavigateComplete (DISPID_NAVIGATECOMPLETE)
  2414. // event to container if there are any advise sinks
  2415. void FireEvent_NavigateComplete(IUnknown* punk, IWebBrowser2* pwb2, LPCITEMIDLIST pidl, HWND hwnd)
  2416. {
  2417. IConnectionPoint* pcp1 = NULL;
  2418. IConnectionPoint* pcpTopWBEvt2 = NULL;
  2419. IConnectionPoint* pcpWBEvt2 = NULL;
  2420. // if we don't have any sinks, then there's nothing to do. we intentionally
  2421. // ignore errors here.
  2422. //
  2423. LBSTR::CString strPath;
  2424. GetEventURL(pidl, strPath);
  2425. //
  2426. // Notify IEDDE of navigate complete.
  2427. //
  2428. IEDDE_AfterNavigate(strPath, hwnd);
  2429. // Fire NavigateComplete2 off the parent and top-level frames.
  2430. // We only fire [Frame]NavigateComplete off the top-level
  2431. // frame for backward compatibility.
  2432. //
  2433. GetTopWBConnectionPoints(punk, &pcp1, &pcpTopWBEvt2);
  2434. DISPID dispid = pcp1 ? DISPID_FRAMENAVIGATECOMPLETE : DISPID_NAVIGATECOMPLETE;
  2435. GetWBConnectionPoints(punk, pcp1 ? NULL : &pcp1, &pcpWBEvt2);
  2436. if (pcpTopWBEvt2 || pcpWBEvt2)
  2437. {
  2438. VARIANT vURL = {0};
  2439. BOOL bSysAllocated = FALSE;
  2440. // If IEGetDisplayName above failed, pack the PIDL in the variant
  2441. //
  2442. // Try to keep OLEAUT32 unloaded if possible.
  2443. //
  2444. V_VT(&vURL) = VT_BSTR;
  2445. // If OLEAUT32 is already loaded
  2446. if (GetModuleHandle(TEXT("OLEAUT32.DLL")))
  2447. {
  2448. // then do the SysAllocString
  2449. V_BSTR(&vURL) = SysAllocString(strPath);
  2450. // What happens if this comes back NULL?
  2451. bSysAllocated = TRUE;
  2452. }
  2453. else
  2454. {
  2455. // else use the stack version
  2456. V_BSTR(&vURL) = strPath;
  2457. }
  2458. TraceMsg(TF_SHDCONTROL, "Event: NavigateComplete2[%ls]", strPath);
  2459. // Fire the event to the parent first and then the top-level object.
  2460. // For symmetry we fire NavigateComplete2 packed as a Variant.
  2461. //
  2462. if (pcpWBEvt2)
  2463. {
  2464. DoInvokeParamHelper(punk, pcpWBEvt2, NULL, NULL, DISPID_NAVIGATECOMPLETE2, 2,
  2465. VT_DISPATCH, pwb2,
  2466. VT_VARIANT|VT_BYREF, &vURL);
  2467. ATOMICRELEASE(pcpWBEvt2);
  2468. }
  2469. if (pcpTopWBEvt2)
  2470. {
  2471. DoInvokeParamHelper(punk, pcpTopWBEvt2, NULL, NULL, DISPID_NAVIGATECOMPLETE2, 2,
  2472. VT_DISPATCH, pwb2,
  2473. VT_VARIANT|VT_BYREF, &vURL);
  2474. ATOMICRELEASE(pcpTopWBEvt2);
  2475. }
  2476. // Since we pass the BSTR in a VT_VARIANT|VT_BYREF, OLEAUT32 might have freed and reallocated it.
  2477. //
  2478. ASSERT(V_VT(&vURL) == VT_BSTR);
  2479. if (bSysAllocated)
  2480. {
  2481. SysFreeString(V_BSTR(&vURL));
  2482. }
  2483. }
  2484. if (pcp1)
  2485. {
  2486. //
  2487. // Compuserve History manager compatability: Don't fire NavigateComplete if it's a javascript:
  2488. // or vbscript: URL.
  2489. //
  2490. if (GetUrlSchemeW(strPath) != URL_SCHEME_JAVASCRIPT &&
  2491. GetUrlSchemeW(strPath) != URL_SCHEME_VBSCRIPT)
  2492. {
  2493. // IE3 did not fire on NULL pidl
  2494. if (pidl)
  2495. {
  2496. TraceMsg(TF_SHDCONTROL, "Event: NavigateComplete[%ls]", strPath);
  2497. // call DoInvokeParam to package up parameters and call
  2498. // IDispatch::Invoke on the container.
  2499. //
  2500. // This pseudo-BSTR is passed as a straight BSTR so doesn't need to be SysAllocString'ed.
  2501. //
  2502. DoInvokeParamHelper(punk, pcp1, NULL, NULL, dispid, 1, VT_BSTR, strPath);
  2503. }
  2504. }
  2505. ATOMICRELEASE(pcp1);
  2506. }
  2507. }
  2508. void FireEvent_DocumentComplete(IUnknown* punk, IWebBrowser2* pwb2, LPCITEMIDLIST pidl)
  2509. {
  2510. IConnectionPoint* pcpTopWBEvt2 = NULL;
  2511. IConnectionPoint* pcpWBEvt2 = NULL;
  2512. // TODO: (mwatt) Investigate why we are occasionally getting bogus DocumentComplete events
  2513. // with null disp pointers.
  2514. if (!punk)
  2515. {
  2516. return;
  2517. }
  2518. LBSTR::CString strPath;
  2519. GetEventURL(pidl, strPath);
  2520. // Fire DocumentComplete off the parent and top-level frames.
  2521. //
  2522. GetTopWBConnectionPoints(punk, NULL, &pcpTopWBEvt2);
  2523. GetWBConnectionPoints(punk, NULL, &pcpWBEvt2);
  2524. if (pcpTopWBEvt2 || pcpWBEvt2)
  2525. {
  2526. VARIANT vURL = {0};
  2527. BOOL bSysAllocated = FALSE;
  2528. // If IEGetDisplayName above failed, pack the PIDL in the variant
  2529. //
  2530. // Try to keep OLEAUT32 unloaded if possible.
  2531. //
  2532. V_VT(&vURL) = VT_BSTR;
  2533. // If OLEAUT32 is already loaded
  2534. if (GetModuleHandle(TEXT("OLEAUT32.DLL")))
  2535. {
  2536. // then do the SysAllocString
  2537. V_BSTR(&vURL) = SysAllocString(strPath);
  2538. bSysAllocated = TRUE;
  2539. }
  2540. else
  2541. {
  2542. // else use the stack version
  2543. V_BSTR(&vURL) = strPath;
  2544. }
  2545. // Fire the event to the parent first and then the top-level object.
  2546. //
  2547. if (pcpWBEvt2)
  2548. {
  2549. DoInvokeParamHelper(punk, pcpWBEvt2, NULL, NULL, DISPID_DOCUMENTCOMPLETE, 2,
  2550. VT_DISPATCH, pwb2,
  2551. VT_VARIANT|VT_BYREF, &vURL);
  2552. ATOMICRELEASE(pcpWBEvt2);
  2553. }
  2554. if (pcpTopWBEvt2)
  2555. {
  2556. DoInvokeParamHelper(punk, pcpTopWBEvt2, NULL, NULL, DISPID_DOCUMENTCOMPLETE, 2,
  2557. VT_DISPATCH, pwb2,
  2558. VT_VARIANT|VT_BYREF, &vURL);
  2559. ATOMICRELEASE(pcpTopWBEvt2);
  2560. }
  2561. // Since we pass the BSTR in a VT_VARIANT|VT_BYREF, OLEAUT32 might have freed and reallocated it.
  2562. //
  2563. ASSERT(V_VT(&vURL) == VT_BSTR);
  2564. if (bSysAllocated)
  2565. {
  2566. SysFreeString(V_BSTR(&vURL));
  2567. }
  2568. }
  2569. IEFrameAuto* pief;
  2570. if (SUCCEEDED(pwb2->QueryInterface(IID_PPV_ARG(IEFrameAuto, &pief))))
  2571. {
  2572. pief->OnDocumentComplete();
  2573. pief->Release();
  2574. }
  2575. }
  2576. void AllocEventStuff(LPCTSTR pszFrameName, BSTR * pbstrFrameName,
  2577. LPCTSTR pszHeaders, BSTR * pbstrHeaders,
  2578. LPBYTE pPostData, DWORD cbPostData, VARIANTARG * pvaPostData)
  2579. {
  2580. SAFEARRAY * psaPostData = NULL;
  2581. // allocate BSTRs for frame name, headers
  2582. *pbstrFrameName = NULL;
  2583. if (pszFrameName && pszFrameName[0])
  2584. {
  2585. *pbstrFrameName = SysAllocStringT(pszFrameName);
  2586. }
  2587. *pbstrHeaders = NULL;
  2588. if (pszHeaders && pszHeaders[0])
  2589. {
  2590. *pbstrHeaders = SysAllocStringT(pszHeaders);
  2591. }
  2592. if (pPostData && cbPostData) {
  2593. // make a SAFEARRAY for post data
  2594. psaPostData = MakeSafeArrayFromData(pPostData,cbPostData);
  2595. }
  2596. // put the post data SAFEARRAY into a variant so we can pass through automation
  2597. VariantInit(pvaPostData);
  2598. if (psaPostData) {
  2599. pvaPostData->vt = VT_ARRAY | VT_UI1;
  2600. pvaPostData->parray = psaPostData;
  2601. }
  2602. }
  2603. void FreeEventStuff(BSTR bstrFrameName, BSTR bstrHeaders, VARIANTARG * pvaPostData)
  2604. {
  2605. // free the things we allocated
  2606. if (bstrFrameName)
  2607. SysFreeString(bstrFrameName);
  2608. if (bstrHeaders)
  2609. SysFreeString(bstrHeaders);
  2610. if (pvaPostData->parray)
  2611. {
  2612. ASSERT(pvaPostData->vt == (VT_ARRAY | VT_UI1));
  2613. VariantClearLazy(pvaPostData);
  2614. }
  2615. }
  2616. /*******************************************************************
  2617. NAME: FireEvent_BeforeNavigate
  2618. SYNOPSIS: Fires a BeforeNavigate (DISPID_BEFORENAVIGATE) event to container
  2619. if there are any advise sinks
  2620. NOTES: If the container wants to cancel this navigation,
  2621. it fills in pfCancel with TRUE and we should cancel.
  2622. ********************************************************************/
  2623. void FireEvent_BeforeNavigate(IUnknown* punk, HWND hwnd, IWebBrowser2* pwb2,
  2624. LPCITEMIDLIST pidl,LPCWSTR pwzLocation,
  2625. DWORD dwFlags,LPCTSTR pszFrameName,LPBYTE pPostData,
  2626. DWORD cbPostData,LPCTSTR pszHeaders,BOOL * pfProcessedInOut)
  2627. {
  2628. HRESULT hres = E_FAIL;
  2629. IConnectionPoint* pcpTopWBEvt1 = NULL;
  2630. IConnectionPoint* pcpTopWBEvt2 = NULL;
  2631. IConnectionPoint* pcpWBEvt2 = NULL;
  2632. BSTR bstrFrameName = NULL;
  2633. BSTR bstrHeaders = NULL;
  2634. VARIANTARG vaPostData;
  2635. ASSERT(pfProcessedInOut);
  2636. //
  2637. // HACKHACK (5.5 bug#98986) for fault caused by FrontPage indexing
  2638. // past the end of this bool (instead of V_BOOLREF, they
  2639. // use V_VARIANTREF->boolVal (CIEControl::XEventSink::Invoke))
  2640. // and trashing our stack.
  2641. // This has been entered as a bug for Office10, the contact
  2642. // is TCrowley our PM is KamV. (marcmill 1/04/2000)
  2643. //
  2644. union tagFrontPageHack {
  2645. BOOL fCancel;
  2646. VARIANT varBogus;
  2647. } CancelHack = { 0 };
  2648. BOOL *pfProcessed = &CancelHack.fCancel;
  2649. // We start with "unprocessed"
  2650. //
  2651. ASSERT(*pfProcessed == FALSE);
  2652. // Build the URL name
  2653. //
  2654. LBSTR::CString strPath;
  2655. GetEventURL(pidl, strPath);
  2656. // Fire BeforeNavigate2 off the parent and top-level frames.
  2657. // We only fire [Frame]BeforeNavigate off the top-level
  2658. // frame for backward compatibility.
  2659. //
  2660. GetTopWBConnectionPoints(punk, &pcpTopWBEvt1, &pcpTopWBEvt2);
  2661. DISPID dispid = pcpTopWBEvt1 ? DISPID_FRAMEBEFORENAVIGATE : DISPID_BEFORENAVIGATE;
  2662. GetWBConnectionPoints(punk, pcpTopWBEvt1 ? NULL : &pcpTopWBEvt1, &pcpWBEvt2);
  2663. // Our caller couldn't pass in the proper IExpDispSupport since
  2664. // it may have been aggregated. We do the QI here. Only call
  2665. // AllocEventStuff if we really are going to fire an event.
  2666. //
  2667. if (pcpTopWBEvt1 || pcpTopWBEvt2 || pcpWBEvt2)
  2668. {
  2669. AllocEventStuff(pszFrameName, &bstrFrameName, pszHeaders, &bstrHeaders, pPostData, cbPostData, &vaPostData);
  2670. }
  2671. // We fire BeforeNavigate2 before DDE because whoever created us may
  2672. // redirect this navigate by cancelling and trying again. DDE will get
  2673. // notified on the redirected Navigate. IE3 didn't do it this way,
  2674. // so fire the BeforeNavigate event last...
  2675. //
  2676. if (pcpTopWBEvt2 || pcpWBEvt2)
  2677. {
  2678. // For symmetry we pack everything in variants
  2679. //
  2680. // If FAILED(hresGDN) then pack URL as PIDL, not BSTR
  2681. //
  2682. BOOL bSysAllocated = FALSE;
  2683. VARIANT vURL = {0};
  2684. V_VT(&vURL) = VT_BSTR;
  2685. if (GetModuleHandle(TEXT("OLEAUT32.DLL")))
  2686. {
  2687. // then do the SysAllocString
  2688. V_BSTR(&vURL) = SysAllocString(strPath);
  2689. bSysAllocated = TRUE;
  2690. }
  2691. else
  2692. {
  2693. // else use the stack version
  2694. V_BSTR(&vURL) = strPath;
  2695. }
  2696. VARIANT vFlags = {0};
  2697. V_VT(&vFlags) = VT_I4;
  2698. V_I4(&vFlags) = dwFlags;
  2699. VARIANT vFrameName = {0};
  2700. V_VT(&vFrameName) = VT_BSTR;
  2701. V_BSTR(&vFrameName) = bstrFrameName;
  2702. VARIANT vPostData = {0};
  2703. V_VT(&vPostData) = VT_VARIANT | VT_BYREF;
  2704. V_VARIANTREF(&vPostData) = &vaPostData;
  2705. VARIANT vHeaders = {0};
  2706. V_VT(&vHeaders) = VT_BSTR;
  2707. V_BSTR(&vHeaders) = bstrHeaders;
  2708. TraceMsg(TF_SHDCONTROL, "Event: BeforeNavigate2[%ls]", strPath);
  2709. // Fire the event ot the parent first and then the top-level object.
  2710. //
  2711. if (pcpWBEvt2)
  2712. {
  2713. DoInvokeParamHelper(punk, pcpWBEvt2, pfProcessed, NULL, DISPID_BEFORENAVIGATE2, 7,
  2714. VT_DISPATCH, pwb2,
  2715. VT_VARIANT | VT_BYREF, &vURL,
  2716. VT_VARIANT | VT_BYREF, &vFlags,
  2717. VT_VARIANT | VT_BYREF, &vFrameName,
  2718. VT_VARIANT | VT_BYREF, &vPostData,
  2719. VT_VARIANT | VT_BYREF, &vHeaders,
  2720. VT_BOOL | VT_BYREF, pfProcessed);
  2721. }
  2722. // Only continue if the parent object didn't cancel.
  2723. //
  2724. if (pcpTopWBEvt2 && !*pfProcessed)
  2725. {
  2726. DoInvokeParamHelper(punk, pcpTopWBEvt2, pfProcessed, NULL, DISPID_BEFORENAVIGATE2, 7,
  2727. VT_DISPATCH, pwb2,
  2728. VT_VARIANT | VT_BYREF, &vURL,
  2729. VT_VARIANT | VT_BYREF, &vFlags,
  2730. VT_VARIANT | VT_BYREF, &vFrameName,
  2731. VT_VARIANT | VT_BYREF, &vPostData,
  2732. VT_VARIANT | VT_BYREF, &vHeaders,
  2733. VT_BOOL | VT_BYREF, pfProcessed);
  2734. }
  2735. if (bSysAllocated)
  2736. {
  2737. SysFreeString(V_BSTR(&vURL));
  2738. }
  2739. bstrFrameName = V_BSTR(&vFrameName);
  2740. bstrHeaders = V_BSTR(&vHeaders);
  2741. }
  2742. if (*pfProcessed)
  2743. goto Exit;
  2744. //
  2745. // NOTE: IE3 called the IEDDE hook before BeforeNavigate.
  2746. //
  2747. IEDDE_BeforeNavigate(strPath, pfProcessed);
  2748. if (*pfProcessed)
  2749. goto Exit;
  2750. //
  2751. // Compuserve History manager compatability: Don't fire BeforeNavigate if it's a javascript:
  2752. // or vbscript: URL.
  2753. //
  2754. if (pcpTopWBEvt1
  2755. && GetUrlSchemeW(strPath) != URL_SCHEME_JAVASCRIPT
  2756. && GetUrlSchemeW(strPath) != URL_SCHEME_VBSCRIPT)
  2757. {
  2758. TraceMsg(TF_SHDCONTROL, "Event: BeforeNavigate[%ls]", strPath);
  2759. // call DoInvokeParam to package up these parameters and call
  2760. // IDispatch::Invoke on the container.
  2761. DoInvokeParamHelper(punk, pcpTopWBEvt1, pfProcessed,NULL, dispid, 6,
  2762. VT_BSTR, strPath, // URL
  2763. VT_I4, dwFlags, // flags
  2764. VT_BSTR, bstrFrameName, // target frame name
  2765. VT_VARIANT | VT_BYREF, &vaPostData, // post data
  2766. VT_BSTR, bstrHeaders, // headers
  2767. VT_BOOL | VT_BYREF, pfProcessed); // BOOL * for indicating "processed"
  2768. }
  2769. Exit:
  2770. *pfProcessedInOut = *pfProcessed; // HACK for FrontPage -- see above for details
  2771. if (pcpTopWBEvt1 || pcpTopWBEvt2 || pcpWBEvt2)
  2772. {
  2773. FreeEventStuff(bstrFrameName, bstrHeaders, &vaPostData);
  2774. ATOMICRELEASE(pcpTopWBEvt1);
  2775. ATOMICRELEASE(pcpTopWBEvt2);
  2776. ATOMICRELEASE(pcpWBEvt2);
  2777. }
  2778. }
  2779. /*******************************************************************
  2780. NAME: FireEvent_NavigateError
  2781. SYNOPSIS: Fires a NavigateError (DISPID_NAVIGATEERROR) event
  2782. to the container if there are any advise sinks
  2783. NOTES: If the container wants to cancel
  2784. autosearch and friendly error pages,
  2785. it fills in pfCancel with TRUE and we should cancel.
  2786. ********************************************************************/
  2787. void FireEvent_NavigateError(IUnknown * punk,
  2788. IWebBrowser2 * pwb2,
  2789. LPCITEMIDLIST pidl,
  2790. BSTR bstrTargetFrameName,
  2791. DWORD dwStatusCode,
  2792. BOOL * pfCancel)
  2793. {
  2794. // If we find that the dwStatusCode can legally be 0,
  2795. // we should just return from this method and not
  2796. // fire the event. dwStatusCode == 0 implies no error.
  2797. //
  2798. ASSERT(dwStatusCode != 0);
  2799. BSTR bstrFrameName = NULL;
  2800. if (bstrTargetFrameName && bstrTargetFrameName[0])
  2801. {
  2802. bstrFrameName = SysAllocStringT(bstrTargetFrameName);
  2803. }
  2804. // if we don't have any sinks, then there's nothing to do. we intentionally
  2805. // ignore errors here.
  2806. IConnectionPoint * pcpTopWBEvt2 = NULL;
  2807. IConnectionPoint * pcpWBEvt2 = NULL;
  2808. *pfCancel = FALSE;
  2809. // Fire event off the parent and top-level frames.
  2810. //
  2811. GetTopWBConnectionPoints(punk, NULL, &pcpTopWBEvt2);
  2812. GetWBConnectionPoints(punk, NULL, &pcpWBEvt2);
  2813. // Need to convert the URL to version that matches BN2
  2814. LBSTR::CString strPath;
  2815. BOOL bSysAllocated = FALSE;
  2816. GetEventURL(pidl, strPath);
  2817. VARIANT vTargetURL = {0};
  2818. V_VT(&vTargetURL) = VT_BSTR;
  2819. if (GetModuleHandle(TEXT("OLEAUT32.DLL")))
  2820. {
  2821. // then do the SysAllocString
  2822. V_BSTR(&vTargetURL) = SysAllocString(strPath);
  2823. bSysAllocated = TRUE;
  2824. }
  2825. else
  2826. {
  2827. // else use the stack version
  2828. V_BSTR(&vTargetURL) = strPath;
  2829. }
  2830. VARIANT vStatusCode = {0};
  2831. V_VT(&vStatusCode) = VT_I4;
  2832. V_I4(&vStatusCode) = dwStatusCode;
  2833. VARIANT vTargetFrame = {0};
  2834. V_VT(&vTargetFrame) = VT_BSTR;
  2835. V_BSTR(&vTargetFrame) = bstrFrameName;
  2836. // Fire the event to the parent first and then the top-level object.
  2837. //
  2838. if (pcpWBEvt2)
  2839. {
  2840. DoInvokeParamHelper(punk, pcpWBEvt2, NULL, NULL, DISPID_NAVIGATEERROR, 5,
  2841. VT_DISPATCH, pwb2,
  2842. VT_VARIANT | VT_BYREF, &vTargetURL,
  2843. VT_VARIANT | VT_BYREF, &vTargetFrame,
  2844. VT_VARIANT | VT_BYREF, &vStatusCode,
  2845. VT_BOOL | VT_BYREF, pfCancel);
  2846. ATOMICRELEASE(pcpWBEvt2);
  2847. }
  2848. if (pcpTopWBEvt2)
  2849. {
  2850. DoInvokeParamHelper(punk, pcpTopWBEvt2, NULL, NULL, DISPID_NAVIGATEERROR, 5,
  2851. VT_DISPATCH, pwb2,
  2852. VT_VARIANT | VT_BYREF, &vTargetURL,
  2853. VT_VARIANT | VT_BYREF, &vTargetFrame,
  2854. VT_VARIANT | VT_BYREF, &vStatusCode,
  2855. VT_BOOL | VT_BYREF, pfCancel);
  2856. ATOMICRELEASE(pcpTopWBEvt2);
  2857. }
  2858. if (bSysAllocated)
  2859. {
  2860. SysFreeString(V_BSTR(&vTargetURL));
  2861. }
  2862. bstrFrameName = V_BSTR(&vTargetFrame);
  2863. if (bstrFrameName)
  2864. {
  2865. SysFreeString(bstrFrameName);
  2866. }
  2867. }
  2868. /*******************************************************************
  2869. NAME: FireEvent_PrintTemplateEvent
  2870. SYNOPSIS: Fires a PrintTemplateInstantiation (DISPID_PRINTTEMPLATEINSTANTIATION) or
  2871. a PrintTemplateTeardown (DISPID_PRINTTEMPLATETEARDOWN) event to container
  2872. if there are any advise sinks
  2873. ********************************************************************/
  2874. void FireEvent_PrintTemplateEvent(IUnknown* punk, IWebBrowser2* pwb2, DISPID dispidPrintEvent)
  2875. {
  2876. // if we don't have any sinks, then there's nothing to do. we intentionally
  2877. // ignore errors here.
  2878. IConnectionPoint* pcpTopWBEvt2 = NULL;
  2879. IConnectionPoint* pcpWBEvt2 = NULL;
  2880. // Fire the event off the parent and top-level frames.
  2881. //
  2882. GetTopWBConnectionPoints(punk, NULL, &pcpTopWBEvt2);
  2883. GetWBConnectionPoints(punk, NULL, &pcpWBEvt2);
  2884. // Fire the event to the parent first and then the top-level object.
  2885. //
  2886. if (pcpWBEvt2)
  2887. {
  2888. DoInvokeParamHelper(punk, pcpWBEvt2, NULL, NULL, dispidPrintEvent, 1,
  2889. VT_DISPATCH, pwb2);
  2890. ATOMICRELEASE(pcpWBEvt2);
  2891. }
  2892. if (pcpTopWBEvt2)
  2893. {
  2894. DoInvokeParamHelper(punk, pcpTopWBEvt2, NULL, NULL, dispidPrintEvent, 1,
  2895. VT_DISPATCH, pwb2);
  2896. ATOMICRELEASE(pcpTopWBEvt2);
  2897. }
  2898. }
  2899. /*******************************************************************
  2900. NAME: FireEvent_UpdatePageStatus
  2901. SYNOPSIS: Fires a UpdatePageStatus (DISPID_UPDATEPAGESTATUS)
  2902. event to container
  2903. if there are any advise sinks
  2904. ********************************************************************/
  2905. void FireEvent_UpdatePageStatus(IUnknown* punk, IWebBrowser2* pwb2, DWORD nPage, BOOL fDone)
  2906. {
  2907. // if we don't have any sinks, then there's nothing to do. we intentionally
  2908. // ignore errors here.
  2909. IConnectionPoint* pcpTopWBEvt2 = NULL;
  2910. IConnectionPoint* pcpWBEvt2 = NULL;
  2911. // Fire the event off the parent and top-level frames.
  2912. //
  2913. GetTopWBConnectionPoints(punk, NULL, &pcpTopWBEvt2);
  2914. GetWBConnectionPoints(punk, NULL, &pcpWBEvt2);
  2915. VARIANT vnPage = {0};
  2916. V_VT(&vnPage) = VT_I4;
  2917. V_I4(&vnPage) = nPage;
  2918. VARIANT vfDone = {0};
  2919. V_VT(&vfDone) = VT_BOOL;
  2920. V_BOOL(&vfDone) = fDone;
  2921. // Fire the event to the parent first and then the top-level object.
  2922. //
  2923. if (pcpWBEvt2)
  2924. {
  2925. DoInvokeParamHelper(punk, pcpWBEvt2, NULL, NULL, DISPID_UPDATEPAGESTATUS, 3,
  2926. VT_DISPATCH, pwb2,
  2927. VT_VARIANT|VT_BYREF, &vnPage,
  2928. VT_VARIANT|VT_BYREF, &vfDone);
  2929. ATOMICRELEASE(pcpWBEvt2);
  2930. }
  2931. if (pcpTopWBEvt2)
  2932. {
  2933. DoInvokeParamHelper(punk, pcpTopWBEvt2, NULL, NULL, DISPID_UPDATEPAGESTATUS, 3,
  2934. VT_DISPATCH, pwb2,
  2935. VT_VARIANT|VT_BYREF, &vnPage,
  2936. VT_VARIANT|VT_BYREF, &vfDone);
  2937. ATOMICRELEASE(pcpTopWBEvt2);
  2938. }
  2939. }
  2940. /*******************************************************************
  2941. NAME: FireEvent_PrivacyImpactedStateChange
  2942. SYNOPSIS: Fires the privacy PrivacyImpactedStateChange event
  2943. to container if there are any advise sinks
  2944. ********************************************************************/
  2945. void FireEvent_PrivacyImpactedStateChange(IUnknown* punk, BOOL bPrivacyImpacted)
  2946. {
  2947. // if we don't have any sinks, then there's nothing to do. we intentionally
  2948. // ignore errors here.
  2949. IConnectionPoint* pcpTopWBEvt2 = NULL;
  2950. //
  2951. // Typically most events fire at the frame or both at frame and top level
  2952. // Since we want to fire at the top level only we just call
  2953. // GetWBConnectionPoints instead of GetTopWBConnectionPoints here
  2954. // since we always get passed in the punk for the top level
  2955. // GetTopWBConnectionPoints returns the event interfaces ONLY
  2956. // in a frameset scenario anyway.
  2957. //
  2958. GetWBConnectionPoints(punk, NULL, &pcpTopWBEvt2);
  2959. if (pcpTopWBEvt2)
  2960. {
  2961. DoInvokeParamHelper(punk, pcpTopWBEvt2, NULL, NULL, DISPID_PRIVACYIMPACTEDSTATECHANGE, 1,
  2962. VT_BOOL, bPrivacyImpacted);
  2963. ATOMICRELEASE(pcpTopWBEvt2);
  2964. }
  2965. }
  2966. /*******************************************************************
  2967. NAME: FireEvent_NewWindow
  2968. SYNOPSIS: Fires an NewWindow (DISPID_NEWWINDOW) event to container
  2969. if there are any advise sinks
  2970. NOTES: If the container wants to handle new window creation itself,
  2971. pfProcessed is filled in with TRUE on exit and we should not
  2972. create a new window ourselves.
  2973. ********************************************************************/
  2974. void FireEvent_NewWindow(IUnknown* punk, HWND hwnd,
  2975. LPCITEMIDLIST pidl,LPWSTR pwzLocation,
  2976. DWORD dwFlags,LPTSTR pszFrameName,LPBYTE pPostData,
  2977. DWORD cbPostData,LPTSTR pszHeaders,BOOL * pfProcessed)
  2978. {
  2979. LBSTR::CString strPath;
  2980. GetEventURL(pidl, strPath);
  2981. *pfProcessed = FALSE;
  2982. IEDDE_BeforeNavigate(strPath, pfProcessed);
  2983. if (*pfProcessed)
  2984. return;
  2985. // We fire [Frame]NewWindow off the top frame only
  2986. //
  2987. // NOTE: This will break anyone watching navigations within a frameset...
  2988. // Do we care?
  2989. //
  2990. IConnectionPoint *pccp;
  2991. DISPID dispid = 0; // init to suppress bogus C4701 warning
  2992. if (S_OK == GetTopWBConnectionPoints(punk, &pccp, NULL))
  2993. dispid = DISPID_FRAMENEWWINDOW;
  2994. else if (S_OK == GetWBConnectionPoints(punk, &pccp, NULL))
  2995. dispid = DISPID_NEWWINDOW;
  2996. if (pccp)
  2997. {
  2998. BSTR bstrFrameName, bstrHeaders;
  2999. VARIANTARG vaPostData;
  3000. AllocEventStuff(pszFrameName, &bstrFrameName, pszHeaders, &bstrHeaders, pPostData, cbPostData, &vaPostData);
  3001. if (pidl != NULL)
  3002. {
  3003. // call DoInvokeParam to package up these parameters and call
  3004. // IDispatch::Invoke on the container.
  3005. DoInvokeParamHelper(punk, pccp, pfProcessed, NULL, dispid, 6,
  3006. VT_BSTR, strPath, // URL
  3007. VT_I4, dwFlags, // flags
  3008. VT_BSTR, bstrFrameName, // target frame name
  3009. VT_VARIANT | VT_BYREF, &vaPostData, // post data
  3010. VT_BSTR, bstrHeaders, // headers
  3011. VT_BOOL | VT_BYREF, pfProcessed); // BOOL * for indicating "processed"
  3012. }
  3013. FreeEventStuff(bstrFrameName, bstrHeaders, &vaPostData);
  3014. pccp->Release();
  3015. }
  3016. return;
  3017. }
  3018. void FireEvent_NewWindow2(IUnknown* punk, IUnknown** ppunkNewWindow, BOOL *pfCancel)
  3019. {
  3020. IConnectionPoint* pcpTopWBEvt2 = NULL;
  3021. IConnectionPoint* pcpWBEvt2 = NULL;
  3022. *pfCancel = FALSE;
  3023. *ppunkNewWindow = NULL;
  3024. // Fire NewWindow2 off the parent and top-level frames.
  3025. // We only fire [Frame]NewWindow off the top-level
  3026. // frame for backward compatibility.
  3027. //
  3028. GetTopWBConnectionPoints(punk, NULL, &pcpTopWBEvt2);
  3029. GetWBConnectionPoints(punk, NULL, &pcpWBEvt2);
  3030. if (pcpTopWBEvt2 || pcpWBEvt2)
  3031. {
  3032. //
  3033. // The AOL browser wants to override the behavior of "Open in New Window"
  3034. // so it opens a new AOL window instead of a new IE window. They do this by
  3035. // responding to this message by creating the AOL window and putting its
  3036. // IUnknown into *ppunkNewWindow.
  3037. // Fire the event to the parent and then the top-level window. The
  3038. // pfCancel and ppunkNewWindow returned by the parent override the ones
  3039. // returned by the top-level window.
  3040. //
  3041. if (pcpWBEvt2)
  3042. {
  3043. DoInvokeParamHelper(punk, pcpWBEvt2, pfCancel, (void **)ppunkNewWindow, DISPID_NEWWINDOW2, 2,
  3044. VT_DISPATCH|VT_BYREF, ppunkNewWindow,
  3045. VT_BOOL |VT_BYREF, pfCancel);
  3046. }
  3047. // If the parent object cancels or specifies a new window,
  3048. // don't fire the event to the top-level object.
  3049. //
  3050. if (pcpTopWBEvt2 && !*pfCancel && !*ppunkNewWindow)
  3051. {
  3052. DoInvokeParamHelper(punk, pcpTopWBEvt2, pfCancel, (void **)ppunkNewWindow, DISPID_NEWWINDOW2, 2,
  3053. VT_DISPATCH|VT_BYREF, ppunkNewWindow,
  3054. VT_BOOL |VT_BYREF, pfCancel);
  3055. }
  3056. ATOMICRELEASE(pcpWBEvt2);
  3057. ATOMICRELEASE(pcpTopWBEvt2);
  3058. }
  3059. }
  3060. void FireEvent_FileDownload(IUnknown * punk, BOOL * pfCancel, VARIANT_BOOL bDocObject)
  3061. {
  3062. IConnectionPoint * pcpWBEvt2 = NULL;
  3063. IConnectionPoint * pcpTopWBEvt2 = NULL;
  3064. *pfCancel = FALSE;
  3065. GetWBConnectionPoints(punk, NULL, &pcpWBEvt2);
  3066. GetTopWBConnectionPoints(punk, NULL, &pcpTopWBEvt2);
  3067. if (pcpWBEvt2)
  3068. {
  3069. // disp params are reverse ordered, so the additional parameter is passed first
  3070. DoInvokeParamHelper(punk, pcpWBEvt2, pfCancel, NULL, DISPID_FILEDOWNLOAD, 2,
  3071. VT_BOOL, bDocObject,
  3072. VT_BOOL | VT_BYREF, pfCancel);
  3073. }
  3074. if (pcpTopWBEvt2 && !*pfCancel)
  3075. {
  3076. // disp params are reverse ordered, so the additional parameter is passed first
  3077. DoInvokeParamHelper(punk, pcpWBEvt2, pfCancel, NULL, DISPID_FILEDOWNLOAD, 2,
  3078. VT_BOOL, bDocObject,
  3079. VT_BOOL | VT_BYREF, pfCancel);
  3080. }
  3081. ATOMICRELEASE(pcpWBEvt2);
  3082. ATOMICRELEASE(pcpTopWBEvt2);
  3083. }
  3084. void FireEvent_DoInvokeString(IExpDispSupport* peds, DISPID dispid, LPSTR psz)
  3085. {
  3086. IConnectionPoint* pccp1, * pccp2;
  3087. if (S_OK == GetWBConnectionPoints(peds, &pccp1, &pccp2))
  3088. {
  3089. // send as generic parameter to DoInvokeParam to package up
  3090. LBSTR::CString strText;
  3091. LPTSTR pstrText = strText.GetBuffer(MAX_URL_STRING);
  3092. if (strText.GetAllocLength() < MAX_URL_STRING)
  3093. {
  3094. TraceMsg(TF_WARNING, "FireEvent_DoInvokeString() - strText Allocation Failed!");
  3095. strText.Empty();
  3096. }
  3097. else
  3098. {
  3099. SHAnsiToUnicode(psz, pstrText, MAX_URL_STRING);
  3100. // Let CString class own the buffer again.
  3101. strText.ReleaseBuffer();
  3102. }
  3103. if (! strText.IsEmpty())
  3104. {
  3105. if (pccp2)
  3106. {
  3107. DoInvokeParamHelper(SAFECAST(peds, IUnknown*), pccp2, NULL, NULL, dispid, 1, VT_BSTR, strText);
  3108. }
  3109. if (pccp1)
  3110. {
  3111. DoInvokeParamHelper(SAFECAST(peds, IUnknown*), pccp1, NULL, NULL, dispid, 1, VT_BSTR, strText);
  3112. }
  3113. }
  3114. if (pccp2)
  3115. {
  3116. pccp2->Release();
  3117. }
  3118. if (pccp1)
  3119. {
  3120. pccp1->Release();
  3121. }
  3122. }
  3123. }
  3124. void FireEvent_DoInvokeStringW(IExpDispSupport* peds, DISPID dispid, LPWSTR psz)
  3125. {
  3126. IConnectionPoint* pccp1, * pccp2;
  3127. if (S_OK == GetWBConnectionPoints(peds, &pccp1, &pccp2))
  3128. {
  3129. // send as generic parameter to DoInvokeParam to package up
  3130. LBSTR::CString strText;
  3131. if (psz)
  3132. {
  3133. strText = psz;
  3134. }
  3135. else
  3136. {
  3137. strText.Empty();
  3138. }
  3139. if (pccp2)
  3140. {
  3141. DoInvokeParamHelper(SAFECAST(peds, IUnknown*), pccp2, NULL, NULL, dispid, 1, VT_BSTR, strText);
  3142. }
  3143. if (pccp1)
  3144. {
  3145. DoInvokeParamHelper(SAFECAST(peds, IUnknown*), pccp1, NULL, NULL, dispid, 1, VT_BSTR, strText);
  3146. }
  3147. if (pccp2)
  3148. {
  3149. pccp2->Release();
  3150. }
  3151. if (pccp1)
  3152. {
  3153. pccp1->Release();
  3154. }
  3155. }
  3156. }
  3157. void FireEvent_DoInvokeBstr(IUnknown* punk, DISPID dispid, BSTR bstr)
  3158. {
  3159. IConnectionPoint* pccp1, * pccp2;
  3160. if (S_OK == GetWBConnectionPoints(punk, &pccp1, &pccp2))
  3161. {
  3162. if (pccp2)
  3163. {
  3164. DoInvokeParamHelper(punk, pccp2, NULL, NULL, dispid, 1, VT_BSTR, bstr);
  3165. pccp2->Release();
  3166. }
  3167. if (pccp1)
  3168. {
  3169. DoInvokeParamHelper(punk, pccp1, NULL, NULL, dispid, 1, VT_BSTR, bstr);
  3170. pccp1->Release();
  3171. }
  3172. }
  3173. }
  3174. void FireEvent_DoInvokeDispid(IUnknown* punk, DISPID dispid)
  3175. {
  3176. IConnectionPoint *pccp1, *pccp2;
  3177. if (S_OK == GetWBConnectionPoints(punk, &pccp1, &pccp2))
  3178. {
  3179. if (pccp2)
  3180. {
  3181. DoInvokeParamHelper(punk, pccp2, NULL, NULL, dispid, 0);
  3182. pccp2->Release();
  3183. }
  3184. if (pccp1)
  3185. {
  3186. DoInvokeParamHelper(punk, pccp1, NULL, NULL, dispid, 0);
  3187. pccp1->Release();
  3188. }
  3189. }
  3190. }
  3191. void FireEvent_DoInvokeDwords(IExpDispSupport* peds, DISPID dispid, DWORD dw1,DWORD dw2)
  3192. {
  3193. IConnectionPoint *pccp1, *pccp2;
  3194. if (S_OK == GetWBConnectionPoints(peds, &pccp1, &pccp2))
  3195. {
  3196. if (pccp2)
  3197. {
  3198. DoInvokeParamHelper(SAFECAST(peds, IUnknown*), pccp2, NULL, NULL, dispid, 2, VT_I4, dw1, VT_I4, dw2);
  3199. pccp2->Release();
  3200. }
  3201. if (pccp1)
  3202. {
  3203. DoInvokeParamHelper(SAFECAST(peds, IUnknown*), pccp1, NULL, NULL, dispid, 2, VT_I4, dw1, VT_I4, dw2);
  3204. pccp1->Release();
  3205. }
  3206. }
  3207. }
  3208. void FireEvent_Quit(IExpDispSupport* peds)
  3209. {
  3210. IConnectionPoint *pccp1, *pccp2;
  3211. if (S_OK == GetWBConnectionPoints(peds, &pccp1, &pccp2))
  3212. {
  3213. if (pccp2)
  3214. {
  3215. DoInvokeParamHelper(SAFECAST(peds, IUnknown*), pccp2, NULL, NULL, DISPID_ONQUIT, 0);
  3216. pccp2->Release();
  3217. }
  3218. if (pccp1)
  3219. {
  3220. // IE3 fired the quit event incorrectly. It was supposed to
  3221. // be VT_BOOL|VT_BYREF and we were supposed to honor the return
  3222. // result and not allow the quit. It never worked that way...
  3223. DoInvokeParamHelper(SAFECAST(peds, IUnknown*), pccp1, NULL, NULL, DISPID_QUIT, 1, VT_BOOL, VARIANT_FALSE);
  3224. pccp1->Release();
  3225. }
  3226. }
  3227. }
  3228. void FireEvent_OnAdornment(IUnknown* punk, DISPID dispid, VARIANT_BOOL f)
  3229. {
  3230. VARIANTARG args[1];
  3231. IUnknown_CPContainerInvokeParam(punk, DIID_DWebBrowserEvents2,
  3232. dispid, args, 1, VT_BOOL, f);
  3233. #ifdef DEBUG
  3234. // Verify that every IExpDispSupport also supports IConnectionPointContainer
  3235. IConnectionPointContainer *pcpc;
  3236. IExpDispSupport* peds;
  3237. if (SUCCEEDED(punk->QueryInterface(IID_PPV_ARG(IConnectionPointContainer, &pcpc))))
  3238. {
  3239. pcpc->Release();
  3240. }
  3241. else if (SUCCEEDED(punk->QueryInterface(IID_PPV_ARG(IExpDispSupport, &peds))))
  3242. {
  3243. peds->Release();
  3244. AssertMsg(0, TEXT("IExpDispSupport without IConnectionPointContainer for %08x"), punk);
  3245. }
  3246. #endif
  3247. }
  3248. HRESULT CIEFrameAuto::OnInvoke(DISPID dispidMember, REFIID iid, LCID lcid, WORD wFlags, DISPPARAMS *pdispparams,
  3249. VARIANT *pVarResult, EXCEPINFO *pexcepinfo, UINT *puArgErr)
  3250. {
  3251. VARIANT_BOOL vtb = FALSE;
  3252. HRESULT hres = S_OK;
  3253. //riid is supposed to be IID_NULL always
  3254. if (IID_NULL != iid)
  3255. return DISP_E_UNKNOWNINTERFACE;
  3256. if (!(wFlags & DISPATCH_PROPERTYGET))
  3257. return E_FAIL; // Currently we only handle Gets for Ambient Properties
  3258. switch (dispidMember)
  3259. {
  3260. case DISPID_AMBIENT_OFFLINEIFNOTCONNECTED:
  3261. get_Offline(&vtb);
  3262. pVarResult->vt = VT_BOOL;
  3263. pVarResult->boolVal = vtb ? TRUE : FALSE;
  3264. break;
  3265. case DISPID_AMBIENT_SILENT:
  3266. get_Silent(&vtb);
  3267. pVarResult->vt = VT_BOOL;
  3268. pVarResult->boolVal = vtb ? TRUE : FALSE;
  3269. break;
  3270. case DISPID_AMBIENT_PALETTE:
  3271. if (_pbs)
  3272. {
  3273. HPALETTE hpal;
  3274. hres = _pbs->GetPalette(&hpal);
  3275. if (SUCCEEDED(hres))
  3276. {
  3277. pVarResult->vt = VT_HANDLE;
  3278. pVarResult->intVal = PtrToLong(hpal);
  3279. }
  3280. }
  3281. else
  3282. hres = E_FAIL;
  3283. break;
  3284. default:
  3285. hres = E_FAIL;
  3286. }
  3287. return hres;
  3288. }
  3289. // *** IExternalConnection ***
  3290. DWORD CIEFrameAuto::AddConnection(DWORD extconn, DWORD reserved)
  3291. {
  3292. TraceMsg(TF_SHDLIFE, "shd - TR CIEFrameAuto::AddConnection(%d) called _cLock(before)=%d", extconn, _cLocks);
  3293. if (extconn & EXTCONN_STRONG)
  3294. return ++_cLocks;
  3295. return 0;
  3296. }
  3297. DWORD CIEFrameAuto::ReleaseConnection(DWORD extconn, DWORD reserved, BOOL fLastReleaseCloses)
  3298. {
  3299. TraceMsg(TF_SHDLIFE, "shd - TR CIEFrameAuto::ReleaseConnection(%d,,%d) called _cLock(before)=%d", extconn, fLastReleaseCloses, _cLocks);
  3300. if (!(extconn & EXTCONN_STRONG))
  3301. return 0;
  3302. _cLocks--;
  3303. if (((_cLocks == 0) || (_cLocks == 1 && _fWindowsListMarshalled)) && fLastReleaseCloses)
  3304. {
  3305. // We could/should have the visiblity update the count of locks.
  3306. // but this is implier for now.
  3307. VARIANT_BOOL fVisible;
  3308. get_Visible(&fVisible);
  3309. if (!fVisible)
  3310. {
  3311. HWND hwnd = _GetHWND();
  3312. //
  3313. // Notice that we close it only if that's the top level browser
  3314. // to avoid closing a hidden WebBrowserOC by mistake.
  3315. //
  3316. if (hwnd && _psbTop == _psb && !IsNamedWindow(hwnd, c_szShellEmbedding))
  3317. {
  3318. // The above test is necessary but not sufficient to determine if the item we're looking
  3319. // at is the browser frame or the WebBrowserOC.
  3320. TraceMsg(TF_SHDAUTO, "CIEFrameAuto::ReleaseConnection posting WM_CLOSE to %x", hwnd);
  3321. PostMessage(hwnd, WM_CLOSE, 0, 0);
  3322. }
  3323. }
  3324. }
  3325. return _cLocks;
  3326. }
  3327. HRESULT CIEFrameAuto::_BrowseObject(LPCITEMIDLIST pidl, UINT wFlags)
  3328. {
  3329. if (_psb)
  3330. return _psb->BrowseObject(pidl, wFlags);
  3331. return E_FAIL;
  3332. }
  3333. // return interface for riid via pct->Exec(&CGID_ShellDocView, SHDVID_GETPENDINGOBJECT...)
  3334. HRESULT ExecPending(IOleCommandTarget *pct, REFIID riid, void **ppvoid, VARIANT *pvarargIn)
  3335. {
  3336. HRESULT hres = E_FAIL;
  3337. VARIANT varOut;
  3338. VariantInit(&varOut);
  3339. hres = pct->Exec(&CGID_ShellDocView, SHDVID_GETPENDINGOBJECT, 0, pvarargIn, &varOut);
  3340. if (SUCCEEDED(hres))
  3341. {
  3342. if (varOut.vt == VT_UNKNOWN && varOut.punkVal)
  3343. {
  3344. hres = varOut.punkVal->QueryInterface(riid, ppvoid);
  3345. // Avoid oleaut for this common and known case
  3346. varOut.punkVal->Release();
  3347. return hres;
  3348. }
  3349. else hres = E_FAIL;
  3350. }
  3351. VariantClearLazy(&varOut);
  3352. return hres;
  3353. }
  3354. // returns URL for pending shell view iff there is one and there is NOT an
  3355. // active view. result returned in VT_BSTR variant
  3356. HRESULT CIEFrameAuto::_QueryPendingUrl(VARIANT *pvarResult)
  3357. {
  3358. HRESULT hres = E_FAIL;
  3359. if (_psb)
  3360. {
  3361. IShellView *psv;
  3362. if (SUCCEEDED(_psb->QueryActiveShellView(&psv)))
  3363. {
  3364. SAFERELEASE(psv);
  3365. }
  3366. else
  3367. {
  3368. IOleCommandTarget *pct;
  3369. // Use ExecPending to get IOleCommandTarget on pending shell view
  3370. hres = ExecPending(_pmsc, IID_PPV_ARG(IOleCommandTarget, &pct), NULL);
  3371. if (SUCCEEDED(hres))
  3372. {
  3373. // Use Exec to get URL corresponding to pending shell view
  3374. hres = pct->Exec(&CGID_ShellDocView, SHDVID_GETPENDINGURL, 0, NULL, pvarResult);
  3375. pct->Release();
  3376. }
  3377. }
  3378. }
  3379. return hres;
  3380. }
  3381. HRESULT CIEFrameAuto::_QueryPendingDelegate(IDispatch **ppDisp, VARIANT *pvarargIn)
  3382. {
  3383. HRESULT hres = E_FAIL;
  3384. *ppDisp = NULL;
  3385. if (_psb)
  3386. {
  3387. if (_pmsc)
  3388. {
  3389. IOleCommandTarget *pct;
  3390. // Use ExecPending to get IOleCommandTarget of pending shell view
  3391. hres = ExecPending(_pmsc, IID_PPV_ARG(IOleCommandTarget, &pct), pvarargIn);
  3392. if (SUCCEEDED(hres))
  3393. {
  3394. // Use ExecPending to get IDispatch of DocObject in pending shell view
  3395. hres = ExecPending(pct, IID_PPV_ARG(IDispatch, ppDisp), NULL);
  3396. pct->Release();
  3397. }
  3398. }
  3399. }
  3400. return hres;
  3401. }
  3402. // Gets IDispath of either the DocObject of the active shell view or, if there
  3403. // isn't an active shell view, but there is a pending shell view, ask for it's
  3404. // DocObject. If necessary, one will be created on the fly
  3405. HRESULT CIEFrameAuto::_QueryDelegate(IDispatch **ppDisp)
  3406. {
  3407. HRESULT hres = E_FAIL;
  3408. IShellView *psv;
  3409. *ppDisp = NULL;
  3410. if (_psb)
  3411. {
  3412. if (SUCCEEDED(_psb->QueryActiveShellView(&psv)) && psv)
  3413. {
  3414. ITargetContainer *ptgcActive;
  3415. HRESULT hrLocal;
  3416. LPOLESTR pwzFrameSrc;
  3417. hres = SafeGetItemObject(psv, SVGIO_BACKGROUND, IID_PPV_ARG(IDispatch, ppDisp));
  3418. // Hack to support x = window.open("","FRAME");x = window.open("URL","FRAME")
  3419. if (SUCCEEDED(hres) &&
  3420. *ppDisp &&
  3421. SUCCEEDED((*ppDisp)->QueryInterface(IID_PPV_ARG(ITargetContainer, &ptgcActive))))
  3422. {
  3423. hrLocal = ptgcActive->GetFrameUrl(&pwzFrameSrc);
  3424. if (SUCCEEDED(hrLocal) && pwzFrameSrc)
  3425. {
  3426. if (URL_SCHEME_ABOUT == GetUrlSchemeW(pwzFrameSrc))
  3427. {
  3428. IDispatch *pidPending;
  3429. VARIANT varIn;
  3430. // Pass in bool to override safety check for no active shell view
  3431. VariantInit(&varIn);
  3432. varIn.vt = VT_BOOL;
  3433. varIn.boolVal = TRUE;
  3434. hrLocal = _QueryPendingDelegate(&pidPending, &varIn);
  3435. if (SUCCEEDED(hrLocal) && pidPending)
  3436. {
  3437. (*ppDisp)->Release();
  3438. *ppDisp = pidPending;
  3439. }
  3440. VariantClearLazy(&varIn);
  3441. }
  3442. OleFree(pwzFrameSrc);
  3443. }
  3444. ptgcActive->Release();
  3445. }
  3446. psv->Release();
  3447. }
  3448. else
  3449. {
  3450. hres = _QueryPendingDelegate(ppDisp, NULL);
  3451. }
  3452. }
  3453. return hres;
  3454. }
  3455. extern HRESULT ShowHlinkFrameWindow(IUnknown *pUnkTargetHlinkFrame);
  3456. //=========================================================================
  3457. // Helper API
  3458. //=========================================================================
  3459. //
  3460. // API: HlinkFrameNavigate{NHL}
  3461. //
  3462. // This is a helper function to be called by DocObject implementations
  3463. // which are not be able to open itself as a stand-alone app (like MSHTML).
  3464. // If their IHlinkTarget::Navigate is called when the client is not set,
  3465. // they will call this API to open a separate browser window in a separate
  3466. // process (I assume that those DocObjects are all InProc DLLs).
  3467. //
  3468. // HLINK.DLL's IHlink implementation will hit this code path when
  3469. // a hyperlink object is activated in non-browser window (such as Office
  3470. // apps).
  3471. //
  3472. STDAPI HlinkFrameNavigate(DWORD grfHLNF, LPBC pbc,
  3473. IBindStatusCallback *pibsc,
  3474. IHlink* pihlNavigate,
  3475. IHlinkBrowseContext *pihlbc)
  3476. {
  3477. HRESULT hres S_OK;
  3478. IUnknown* punk = NULL;
  3479. TraceMsg(TF_COCREATE, "HlinkFrameNavigate called");
  3480. #ifdef DEBUG
  3481. DWORD dwTick = GetCurrentTime();
  3482. #endif
  3483. grfHLNF &= ~HLNF_OPENINNEWWINDOW; // Implied by CreateTargetFrame
  3484. hres = CreateTargetFrame(NULL, &punk);
  3485. #ifdef DEBUG
  3486. TraceMsg(TF_COCREATE, "HlinkFrameNavigate called CoCreate %x (took %d msec)",
  3487. hres, GetCurrentTime()-dwTick);
  3488. #endif
  3489. if (SUCCEEDED(hres))
  3490. {
  3491. IHlinkFrame* phfrm;
  3492. hres = punk->QueryInterface(IID_PPV_ARG(IHlinkFrame, &phfrm));
  3493. if (SUCCEEDED(hres))
  3494. {
  3495. if (pihlbc)
  3496. {
  3497. phfrm->SetBrowseContext(pihlbc);
  3498. grfHLNF |= HLNF_EXTERNALNAVIGATE;
  3499. }
  3500. hres = phfrm->Navigate(grfHLNF, pbc, pibsc, pihlNavigate);
  3501. if (SUCCEEDED(hres))
  3502. {
  3503. hres = ShowHlinkFrameWindow(punk);
  3504. } else {
  3505. TraceMsg(DM_ERROR, "HlinkFrameNavigate QI(InternetExplorer) failed (%x)", hres);
  3506. }
  3507. TraceMsg(TF_SHDNAVIGATE, "HlinkFrameNavigate phfrm->Navigate returned (%x)", hres);
  3508. phfrm->Release();
  3509. } else {
  3510. TraceMsg(DM_ERROR, "HlinkFrameNavigate QI(IHlinkFrame) failed (%x)", hres);
  3511. }
  3512. punk->Release();
  3513. } else {
  3514. TraceMsg(DM_ERROR, "HlinkFrameNavigate CoCreateInstance failed (%x)", hres);
  3515. }
  3516. return hres;
  3517. }
  3518. STDAPI HlinkFrameNavigateNHL(DWORD grfHLNF, LPBC pbc,
  3519. IBindStatusCallback *pibsc,
  3520. LPCWSTR pszTargetFrame,
  3521. LPCWSTR pszUrl,
  3522. LPCWSTR pszLocation)
  3523. {
  3524. HRESULT hres S_OK;
  3525. IUnknown* punk = NULL;
  3526. #define MAX_CONTENTTYPE MAX_PATH // This is a good size.
  3527. TraceMsg(TF_COCREATE, "HlinkFrameNavigateNHL called");
  3528. #ifdef DEBUG
  3529. DWORD dwTick = GetCurrentTime();
  3530. #endif
  3531. // This should be more general, but we're punting the FILE: case for IE 4
  3532. // unless the extension is .htm or .html (all that Netscape 3.0 registers for)
  3533. // we'll go with ShellExecute if IE is not the default browser. NOTE:
  3534. // this means POST will not be supported and pszTargetFrame will be ignored
  3535. // we don't shellexecute FILE: url's because URL.DLL doesn't give a security
  3536. // warning for .exe's etc.
  3537. if ((!IsIEDefaultBrowser()))
  3538. {
  3539. WCHAR wszUrl[INTERNET_MAX_URL_LENGTH];
  3540. CHAR aszUrl[INTERNET_MAX_URL_LENGTH];
  3541. int chUrl;
  3542. HINSTANCE hinstRet;
  3543. LPWSTR pwszExt;
  3544. BOOL bSafeToExec = TRUE;
  3545. DWORD dwCodePage = 0;
  3546. if (pibsc)
  3547. {
  3548. DWORD dw = 0;
  3549. BINDINFO bindinfo = { sizeof(BINDINFO) };
  3550. HRESULT hrLocal = pibsc->GetBindInfo(&dw, &bindinfo);
  3551. if (SUCCEEDED(hrLocal))
  3552. {
  3553. dwCodePage = bindinfo.dwCodePage;
  3554. ReleaseBindInfo(&bindinfo);
  3555. }
  3556. }
  3557. if (!dwCodePage)
  3558. {
  3559. dwCodePage = CP_ACP;
  3560. }
  3561. chUrl = lstrlenW(pszUrl);
  3562. pwszExt = PathFindExtensionW(pszUrl);
  3563. if (URL_SCHEME_FILE == GetUrlSchemeW(pszUrl))
  3564. {
  3565. WCHAR wszContentType[MAX_CONTENTTYPE];
  3566. DWORD dwSize = ARRAYSIZE(wszContentType);
  3567. bSafeToExec = FALSE;
  3568. // Get Content type.
  3569. if (SUCCEEDED(AssocQueryString(0, ASSOCSTR_CONTENTTYPE, pwszExt, NULL, wszContentType, &dwSize)))
  3570. {
  3571. bSafeToExec = 0 == StrCmpIW(wszContentType, L"text/html");
  3572. }
  3573. }
  3574. if (bSafeToExec)
  3575. {
  3576. StrCpyNW(wszUrl, pszUrl, ARRAYSIZE(wszUrl));
  3577. // don't attempt unless we have at least enough for '#' {any} '\0'
  3578. // NOTE: # is included in pszLocation
  3579. if (pszLocation && *pszLocation && ARRAYSIZE(wszUrl) - chUrl >= 3)
  3580. {
  3581. StrCpyNW(&wszUrl[chUrl], pszLocation, ARRAYSIZE(wszUrl) - chUrl - 1);
  3582. }
  3583. //
  3584. // UNICODE - should this get changed to wchar?
  3585. //
  3586. // finally we will get the string in the native codepage
  3587. SHUnicodeToAnsiCP(dwCodePage, wszUrl, aszUrl, ARRAYSIZE(aszUrl));
  3588. hinstRet = ShellExecuteA(NULL, NULL, aszUrl, NULL, NULL, SW_SHOWNORMAL);
  3589. return ((UINT_PTR)hinstRet) <= 32 ? E_FAIL:S_OK;
  3590. }
  3591. }
  3592. grfHLNF &= ~HLNF_OPENINNEWWINDOW; // Implied by CreateTargetFrame
  3593. hres = CreateTargetFrame(pszTargetFrame, &punk);
  3594. #ifdef DEBUG
  3595. TraceMsg(TF_COCREATE, "HlinkFrameNavigateNHL called CoCreate %x (took %d msec)", hres, GetCurrentTime()-dwTick);
  3596. #endif
  3597. if (SUCCEEDED(hres))
  3598. {
  3599. ITargetFramePriv *ptgfp;
  3600. hres = punk->QueryInterface(IID_PPV_ARG(ITargetFramePriv, &ptgfp));
  3601. if (SUCCEEDED(hres))
  3602. {
  3603. hres = ptgfp->NavigateHack(grfHLNF, pbc, pibsc, NULL, pszUrl, pszLocation);
  3604. if (SUCCEEDED(hres))
  3605. {
  3606. hres = ShowHlinkFrameWindow(punk);
  3607. }
  3608. else
  3609. {
  3610. TraceMsg(DM_ERROR, "HlinkFrameNavigate QI(InternetExplorer) failed (%x)", hres);
  3611. }
  3612. TraceMsg(TF_SHDNAVIGATE, "HlinkFrameNavigate phfrm->Navigate returned (%x)", hres);
  3613. ptgfp->Release();
  3614. }
  3615. else
  3616. {
  3617. TraceMsg(DM_ERROR, "HlinkFrameNavigate QI(IHlinkFrame) failed (%x)", hres);
  3618. }
  3619. punk->Release();
  3620. }
  3621. else
  3622. {
  3623. TraceMsg(DM_ERROR, "HlinkFrameNavigate CoCreateInstance failed (%x)", hres);
  3624. }
  3625. return hres;
  3626. }
  3627. CIEFrameClassFactory* g_pcfactory = NULL;
  3628. CIEFrameClassFactory* g_pcfactoryShell = NULL;
  3629. //
  3630. // This function is called when the first browser window is being created.
  3631. // punkAuto is non-NULL if and only if the browser is started as the result
  3632. // of CoCreateInstance.
  3633. //
  3634. void IEInitializeClassFactoryObject(IUnknown* punkAuto)
  3635. {
  3636. ASSERT(g_pcfactory==NULL);
  3637. ASSERT(g_pcfactoryShell==NULL);
  3638. AssertParking();
  3639. // We don't want to register this local server stuff for the shell process
  3640. // if we are in browse in new process and this is the Explorer process.
  3641. if (!IsBrowseNewProcessAndExplorer())
  3642. {
  3643. g_pcfactory = new CIEFrameClassFactory(punkAuto, CLSID_InternetExplorer, COF_IEXPLORE);
  3644. }
  3645. g_pcfactoryShell = new CIEFrameClassFactory(NULL, CLSID_ShellBrowserWindow, COF_SHELLFOLDERWINDOW);
  3646. }
  3647. //
  3648. // This function is called when the primaty thread is going away.
  3649. // It revokes the class factory object and release it.
  3650. //
  3651. void IERevokeClassFactoryObject(void)
  3652. {
  3653. AssertParking();
  3654. if (g_pcfactory)
  3655. {
  3656. g_pcfactory->Revoke();
  3657. ATOMICRELEASE(g_pcfactory);
  3658. }
  3659. if (g_pcfactoryShell)
  3660. {
  3661. g_pcfactoryShell->Revoke();
  3662. ATOMICRELEASE(g_pcfactoryShell);
  3663. }
  3664. }
  3665. //
  3666. // This function is called when the first browser window is being destroyed.
  3667. // It will remove the registered automation object (via IEInitializeClass...)
  3668. // to accidentally return an automation object to closed window.
  3669. //
  3670. void IECleanUpAutomationObject()
  3671. {
  3672. if (g_pcfactory)
  3673. g_pcfactory->CleanUpAutomationObject();
  3674. if (g_pcfactoryShell)
  3675. g_pcfactoryShell->CleanUpAutomationObject();
  3676. }
  3677. void IEOnFirstBrowserCreation(IUnknown* punk)
  3678. {
  3679. // For the desktop case, we DON'T have a g_tidParking set
  3680. // and we don't need one, so this assert is bogus in that
  3681. // case. But it's probably checking something valid, so
  3682. // I made the assert not fire in the desktop case. Unfortunately
  3683. // this also makes it not fire in most other cases that it
  3684. // checks, but at least it will check a few things (if automated)
  3685. //
  3686. ASSERT(g_tidParking == GetCurrentThreadId() || !punk);
  3687. // If automation, now is good time to register ourself...
  3688. if (g_fBrowserOnlyProcess)
  3689. IEInitializeClassFactoryObject(punk);
  3690. //
  3691. // Tell IEDDE that automation services are now available.
  3692. //
  3693. IEDDE_AutomationStarted();
  3694. }
  3695. HRESULT CoCreateNewIEWindow(DWORD dwClsContext, REFIID riid, void **ppvunk)
  3696. {
  3697. // QFE 2844 -- We don't want to create a new window as a local
  3698. // server off of the registered class object. Simply create
  3699. // the window in a new thread by a direct createinstance.
  3700. if (dwClsContext & CLSCTX_INPROC_SERVER)
  3701. {
  3702. HRESULT hr = REGDB_E_CLASSNOTREG;
  3703. IClassFactory *pcf = NULL;
  3704. *ppvunk = NULL;
  3705. if (g_pcfactory &&
  3706. SUCCEEDED(hr = g_pcfactory->QueryInterface(IID_PPV_ARG(IClassFactory, &pcf))))
  3707. {
  3708. hr = pcf->CreateInstance(NULL, riid, ppvunk);
  3709. pcf->Release();
  3710. }
  3711. if (SUCCEEDED(hr))
  3712. {
  3713. return hr;
  3714. }
  3715. else
  3716. {
  3717. // Try other contexts via CoCreateInstance since inproc failed.
  3718. dwClsContext &= ~CLSCTX_INPROC_SERVER;
  3719. if (!dwClsContext) {
  3720. return hr;
  3721. }
  3722. }
  3723. }
  3724. return CoCreateInstance(CLSID_InternetExplorer, NULL, dwClsContext, riid, ppvunk);
  3725. }
  3726. SAFEARRAY * MakeSafeArrayFromData(LPCBYTE pData,DWORD cbData)
  3727. {
  3728. if (!pData || 0 == cbData)
  3729. return NULL; // nothing to do
  3730. // create a one-dimensional safe array
  3731. SAFEARRAY *psa = SafeArrayCreateVector(VT_UI1,0,cbData);
  3732. if (psa)
  3733. {
  3734. // copy data into the area in safe array reserved for data
  3735. // Note we party directly on the pointer instead of using locking/
  3736. // unlocking functions. Since we just created this and no one
  3737. // else could possibly know about it or be using it, this is OK.
  3738. ASSERT(psa->pvData);
  3739. memcpy(psa->pvData,pData,cbData);
  3740. }
  3741. return psa;
  3742. }
  3743. /******************************************************************************
  3744. Helper Functions
  3745. ******************************************************************************/
  3746. /******************************************************************************
  3747. Safe version of the Win32 SysAllocStringLen() function. Allows you to
  3748. pass in a string (pStr) that is smaller than the desired BSTR (len).
  3749. ******************************************************************************/
  3750. BSTR SafeSysAllocStringLen(const WCHAR *pStr, const unsigned int len)
  3751. {
  3752. // SysAllocStringLen allocates len + 1
  3753. BSTR pNewStr = SysAllocStringLen(NULL, len);
  3754. if (pStr && pNewStr)
  3755. {
  3756. // StrCpyNW always null terminates so we need to copy len+1
  3757. StrCpyNW(pNewStr, pStr, len + 1);
  3758. }
  3759. return pNewStr;
  3760. }
  3761. BSTR SysAllocStringFromANSI(const char *pStr, int size = -1)
  3762. {
  3763. if (!pStr)
  3764. return 0;
  3765. if (size < 0)
  3766. size = lstrlenA(pStr);
  3767. // Allocates size + 1
  3768. BSTR bstr = SysAllocStringLen(NULL, size);
  3769. if (bstr)
  3770. {
  3771. if (!MultiByteToWideChar(CP_ACP, 0, pStr, -1, bstr, size + 1))
  3772. {
  3773. SysFreeString(bstr);
  3774. bstr = 0;
  3775. }
  3776. }
  3777. return bstr;
  3778. }
  3779. HRESULT GetDelegateOnIDispatch(IDispatch* pdisp, const DISPID delegateID, IDispatch ** const ppDelegate)
  3780. {
  3781. HRESULT hres;
  3782. if (!pdisp || ! ppDelegate)
  3783. return E_POINTER;
  3784. DISPPARAMS dispparams = {0};
  3785. VARIANT VarResult;
  3786. VariantInit(&VarResult);
  3787. hres = pdisp->Invoke( delegateID,
  3788. IID_NULL,
  3789. 0,
  3790. DISPATCH_PROPERTYGET,
  3791. &dispparams,
  3792. &VarResult,
  3793. NULL,
  3794. NULL);
  3795. if (SUCCEEDED(hres))
  3796. {
  3797. if (VarResult.vt == VT_DISPATCH && VarResult.pdispVal)
  3798. {
  3799. *ppDelegate = VarResult.pdispVal;
  3800. (*ppDelegate)->AddRef();
  3801. }
  3802. else
  3803. {
  3804. // Temporary hack (I think) until Trident always returns IDispatch
  3805. if (VarResult.pdispVal && VarResult.vt == VT_UNKNOWN)
  3806. hres = VarResult.pdispVal->QueryInterface(IID_PPV_ARG(IDispatch, ppDelegate));
  3807. else
  3808. hres = E_FAIL;
  3809. }
  3810. VariantClearLazy(&VarResult);
  3811. }
  3812. return hres;
  3813. }
  3814. HRESULT GetRootDelegate(CIEFrameAuto* pauto, IDispatch ** const ppRootDelegate)
  3815. {
  3816. IDispatch *pdiDocObject;
  3817. HRESULT hres;
  3818. if (!pauto || !ppRootDelegate)
  3819. return E_POINTER;
  3820. // Get the IHTMLWindow2 of docobject in our frame. Note: if this is cached
  3821. // you must put glue into docobjhost to release the cache when deactivating
  3822. // view.
  3823. hres = pauto->_QueryDelegate(&pdiDocObject);
  3824. if (SUCCEEDED(hres))
  3825. {
  3826. hres = GetDelegateOnIDispatch(pdiDocObject, DISPID_WINDOWOBJECT, ppRootDelegate);
  3827. pdiDocObject->Release();
  3828. }
  3829. return hres;
  3830. }
  3831. HRESULT GetWindowFromUnknown(IUnknown *pUnk, IHTMLWindow2 **pWinOut)
  3832. {
  3833. return IUnknown_QueryService(pUnk, SID_SOmWindow, IID_PPV_ARG(IHTMLWindow2, pWinOut));
  3834. }
  3835. /******************************************************************************
  3836. Automation Stub Object
  3837. ******************************************************************************/
  3838. CIEFrameAuto::CAutomationStub::CAutomationStub(DISPID minDispid, DISPID maxDispid, BOOL fOwnDefaultDispid) :
  3839. _MinDispid(minDispid), _MaxDispid(maxDispid), _fOwnDefaultDispid(fOwnDefaultDispid)
  3840. {
  3841. ASSERT(!_pInterfaceTypeInfo2);
  3842. ASSERT(!_pCoClassTypeInfo2);
  3843. ASSERT(!_pAuto);
  3844. ASSERT(!_pInstance);
  3845. ASSERT(!_fLoaded);
  3846. }
  3847. CIEFrameAuto::CAutomationStub::~CAutomationStub()
  3848. {
  3849. SAFERELEASE(_pInterfaceTypeInfo2);
  3850. SAFERELEASE(_pCoClassTypeInfo2);
  3851. }
  3852. HRESULT CIEFrameAuto::CAutomationStub::Init(void *instance, REFIID iid, REFIID clsid, CIEFrameAuto *pauto)
  3853. {
  3854. if (!pauto || !instance)
  3855. return E_POINTER;
  3856. _iid = iid;
  3857. _clsid = clsid;
  3858. // Don't need to AddRef this since our lifetime is controled by CIEFrameAuto
  3859. _pAuto = pauto;
  3860. _pInstance = instance;
  3861. return S_OK;
  3862. }
  3863. STDMETHODIMP CIEFrameAuto::CAutomationStub::QueryInterface(REFIID riid, void **ppv)
  3864. {
  3865. *ppv = NULL;
  3866. if (IsEqualIID(riid, IID_IUnknown) ||
  3867. IsEqualIID(riid, IID_IDispatch) ||
  3868. IsEqualIID(riid, IID_IDispatchEx))
  3869. {
  3870. *ppv = SAFECAST(this, IDispatchEx*);
  3871. }
  3872. else if (IsEqualIID(riid, IID_IProvideClassInfo))
  3873. {
  3874. *ppv = SAFECAST(this, IProvideClassInfo*);
  3875. }
  3876. else
  3877. {
  3878. return _InternalQueryInterface(riid, ppv);
  3879. }
  3880. AddRef();
  3881. return S_OK;
  3882. }
  3883. ULONG CIEFrameAuto::CAutomationStub::AddRef(void)
  3884. {
  3885. ASSERT(_pAuto);
  3886. return _pAuto->AddRef();
  3887. }
  3888. ULONG CIEFrameAuto::CAutomationStub::Release(void)
  3889. {
  3890. ASSERT(_pAuto);
  3891. return _pAuto->Release();
  3892. }
  3893. /******************************************************************************
  3894. // bradsch 11/8/96
  3895. // I don't think typeinfo for the object implemented in the browser should
  3896. // live in MSHTML. It should be moved to shdocvw. For now so we don't have
  3897. // to worry about hard coded LIBIDs and changing versions this methods gets
  3898. // typeinfo from the delegate that lives in Trident. In cases where we have
  3899. // not delegate this method tries to load typeinfo directly from MSHTML.
  3900. ******************************************************************************/
  3901. HRESULT CIEFrameAuto::CAutomationStub::ResolveTypeInfo2()
  3902. {
  3903. ASSERT(!_pInterfaceTypeInfo2);
  3904. ASSERT(!_pCoClassTypeInfo2);
  3905. ASSERT(_pAuto);
  3906. // Only try once.
  3907. _fLoaded = TRUE;
  3908. // Have we computed MatchExactGetIDsOfNames yet?
  3909. if (!IEFrameAuto()->_hinstMSHTML)
  3910. {
  3911. // No, so look for helper function in mshtml.dll
  3912. IEFrameAuto()->_hinstMSHTML = LoadLibrary(TEXT("mshtml.dll"));
  3913. if (IEFrameAuto()->_hinstMSHTML && !IEFrameAuto()->_pfnMEGetIDsOfNames)
  3914. {
  3915. IEFrameAuto()->_pfnMEGetIDsOfNames =
  3916. (PFN_MatchExactGetIDsOfNames)GetProcAddress(IEFrameAuto()->_hinstMSHTML, "MatchExactGetIDsOfNames");
  3917. }
  3918. }
  3919. ITypeLib *pTypeLib = 0;
  3920. IDispatch *pDisp = 0;
  3921. HRESULT hr = GetRootDelegate(_pAuto, &pDisp);
  3922. if (SUCCEEDED(hr))
  3923. {
  3924. UINT supported;
  3925. hr = pDisp->GetTypeInfoCount(&supported);
  3926. if (SUCCEEDED(hr) && supported)
  3927. {
  3928. ITypeInfo *pTypeInfo = 0;
  3929. hr = pDisp->GetTypeInfo(0, 0, &pTypeInfo);
  3930. if (SUCCEEDED(hr))
  3931. {
  3932. UINT index;
  3933. hr = pTypeInfo->GetContainingTypeLib(&pTypeLib, &index);
  3934. SAFERELEASE(pTypeInfo);
  3935. }
  3936. }
  3937. SAFERELEASE(pDisp);
  3938. }
  3939. if (FAILED(hr))
  3940. {
  3941. // If, for some reason, we failed to load the type library this way,
  3942. // load the type library directly out of MSHTML's resources.
  3943. // We shouldn't hard code this...
  3944. hr = LoadTypeLib(L"mshtml.tlb", &pTypeLib);
  3945. }
  3946. if (FAILED(hr))
  3947. return hr;
  3948. ITypeInfo *pTopTypeInfo = 0;
  3949. ITypeInfo *pTmpTypeInfo = 0;
  3950. ITypeInfo *pCoClassTypeInfo = 0;
  3951. // Get the coclass TypeInfo
  3952. hr = pTypeLib->GetTypeInfoOfGuid(_clsid, &pCoClassTypeInfo);
  3953. if (SUCCEEDED(hr))
  3954. hr = pCoClassTypeInfo->QueryInterface(IID_ITypeInfo2, (void**)&_pCoClassTypeInfo2);
  3955. if (FAILED(hr))
  3956. goto Exit;
  3957. // get the TKIND_INTERFACE
  3958. hr = pTypeLib->GetTypeInfoOfGuid(_iid, &pTopTypeInfo);
  3959. if (SUCCEEDED(hr))
  3960. {
  3961. HREFTYPE hrt;
  3962. // get the TKIND_INTERFACE from a TKIND_DISPATCH
  3963. hr = pTopTypeInfo->GetRefTypeOfImplType(0xffffffff, &hrt);
  3964. if (SUCCEEDED(hr))
  3965. {
  3966. // get the typeInfo associated with the href
  3967. hr = pTopTypeInfo->GetRefTypeInfo(hrt, &pTmpTypeInfo);
  3968. if (SUCCEEDED(hr))
  3969. hr = pTmpTypeInfo->QueryInterface(IID_ITypeInfo2, (void**)&_pInterfaceTypeInfo2);
  3970. }
  3971. }
  3972. Exit:
  3973. SAFERELEASE(pCoClassTypeInfo);
  3974. SAFERELEASE(pTmpTypeInfo);
  3975. SAFERELEASE(pTopTypeInfo);
  3976. SAFERELEASE(pTypeLib);
  3977. return hr;
  3978. }
  3979. // *** IDispatch members ***
  3980. HRESULT CIEFrameAuto::CAutomationStub::GetTypeInfoCount(UINT *typeinfo)
  3981. {
  3982. if (!typeinfo)
  3983. return E_POINTER;
  3984. if (!_fLoaded)
  3985. ResolveTypeInfo2();
  3986. *typeinfo = _pInterfaceTypeInfo2 ? 1 : 0;
  3987. return S_OK;
  3988. }
  3989. HRESULT CIEFrameAuto::CAutomationStub::GetTypeInfo(UINT itinfo, LCID, ITypeInfo **typeinfo)
  3990. {
  3991. if (!typeinfo)
  3992. return E_POINTER;
  3993. *typeinfo = NULL;
  3994. if (0 != itinfo)
  3995. return TYPE_E_ELEMENTNOTFOUND;
  3996. if (!_fLoaded)
  3997. {
  3998. HRESULT hr = ResolveTypeInfo2();
  3999. if (FAILED(hr))
  4000. return hr;
  4001. }
  4002. if (_pInterfaceTypeInfo2)
  4003. {
  4004. *typeinfo = _pInterfaceTypeInfo2;
  4005. _pInterfaceTypeInfo2->AddRef();
  4006. }
  4007. return *typeinfo ? S_OK : E_FAIL;
  4008. }
  4009. HRESULT CIEFrameAuto::CAutomationStub::GetIDsOfNames(
  4010. REFIID riid,
  4011. OLECHAR **rgszNames,
  4012. UINT cNames,
  4013. LCID lcid,
  4014. DISPID *rgdispid)
  4015. {
  4016. // Since the majority of script operates on built in (non-expando) properties
  4017. // This implementation should be faster than simply passing all lookups to
  4018. // the delegate.
  4019. // Handle it if we can. It is OK to return a DISPID for a method/property
  4020. // that is implemented by Trident. We will simply pass it through in Invoke
  4021. if (!_fLoaded)
  4022. ResolveTypeInfo2();
  4023. if (!_pInterfaceTypeInfo2)
  4024. return TYPE_E_CANTLOADLIBRARY;
  4025. HRESULT hr = _pInterfaceTypeInfo2->GetIDsOfNames(rgszNames, cNames, rgdispid);
  4026. if (FAILED(hr))
  4027. {
  4028. IDispatchEx *delegate = 0;
  4029. hr = _GetIDispatchExDelegate(&delegate);
  4030. if (SUCCEEDED(hr))
  4031. {
  4032. hr = delegate->GetIDsOfNames(riid, rgszNames, cNames, lcid, rgdispid);
  4033. delegate->Release();
  4034. }
  4035. }
  4036. return hr;
  4037. }
  4038. HRESULT CIEFrameAuto::CAutomationStub::InvokeEx (DISPID dispidMember,
  4039. LCID lcid,
  4040. WORD wFlags,
  4041. DISPPARAMS * pdispparams,
  4042. VARIANT * pvarResult,
  4043. EXCEPINFO * pexcepinfo,
  4044. IServiceProvider *pSrvProvider)
  4045. {
  4046. HRESULT hr;
  4047. if (dispidMember == DISPID_SECURITYCTX)
  4048. {
  4049. //
  4050. // Return the url of the document as a bstr.
  4051. //
  4052. if (pvarResult)
  4053. {
  4054. hr = _pAuto->_QueryPendingUrl(pvarResult);
  4055. if (SUCCEEDED(hr))
  4056. return S_OK;
  4057. }
  4058. }
  4059. if ((dispidMember != DISPID_SECURITYCTX) &&
  4060. ((dispidMember >= _MinDispid && dispidMember <= _MaxDispid) ||
  4061. (_fOwnDefaultDispid && DISPID_VALUE == dispidMember)))
  4062. {
  4063. BOOL fNamedDispThis = FALSE;
  4064. VARIANTARG *rgOldVarg = NULL; // init to suppress bogus C4701 warning
  4065. DISPID *rgdispidOldNamedArgs = NULL; // init to suppress bogus C4701 warning
  4066. if (!_fLoaded)
  4067. ResolveTypeInfo2();
  4068. if (!_pInterfaceTypeInfo2)
  4069. return TYPE_E_CANTLOADLIBRARY;
  4070. // Any invoke call from a script engine might have the named argument
  4071. // DISPID_THIS. If so then we'll not include this argument in the
  4072. // list of parameters because oleaut doesn't know how to deal with this
  4073. // argument.
  4074. if (pdispparams->cNamedArgs && (pdispparams->rgdispidNamedArgs[0] == DISPID_THIS))
  4075. {
  4076. fNamedDispThis = TRUE;
  4077. pdispparams->cNamedArgs--;
  4078. pdispparams->cArgs--;
  4079. rgOldVarg = pdispparams->rgvarg;
  4080. rgdispidOldNamedArgs = pdispparams->rgdispidNamedArgs;
  4081. pdispparams->rgvarg++;
  4082. pdispparams->rgdispidNamedArgs++;
  4083. if (pdispparams->cNamedArgs == 0)
  4084. pdispparams->rgdispidNamedArgs = NULL;
  4085. if (pdispparams->cArgs == 0)
  4086. pdispparams->rgvarg = NULL;
  4087. }
  4088. // It belongs to us. Use the typelib to call our method.
  4089. hr = _pInterfaceTypeInfo2->Invoke(_pInstance,
  4090. dispidMember,
  4091. wFlags,
  4092. pdispparams,
  4093. pvarResult,
  4094. pexcepinfo,
  4095. NULL);
  4096. // Replace the named DISPID_THIS argument.
  4097. if (fNamedDispThis)
  4098. {
  4099. pdispparams->cNamedArgs++;
  4100. pdispparams->cArgs++;
  4101. pdispparams->rgvarg = rgOldVarg;
  4102. pdispparams->rgdispidNamedArgs = rgdispidOldNamedArgs;
  4103. }
  4104. }
  4105. else
  4106. {
  4107. // Pass it along
  4108. IDispatchEx *delegate = 0;
  4109. hr = _GetIDispatchExDelegate(&delegate);
  4110. if (SUCCEEDED(hr))
  4111. {
  4112. hr = delegate->InvokeEx(dispidMember,
  4113. lcid,
  4114. wFlags,
  4115. pdispparams,
  4116. pvarResult,
  4117. pexcepinfo,
  4118. pSrvProvider);
  4119. delegate->Release();
  4120. }
  4121. else
  4122. {
  4123. // If we're hosting a non-Trident DocObject, we can get here trying to answer an
  4124. // Invoke on the Security Context. This can cause cross-frame access to fail,
  4125. // even when we want it to succeed. If we pass back the URL of the active view,
  4126. // then Trident can do the proper cross-frame access checking.
  4127. //
  4128. if (dispidMember == DISPID_SECURITYCTX)
  4129. {
  4130. if (_pAuto && _pAuto->_psb) // Check them both for paranoia.
  4131. {
  4132. IShellView *psv;
  4133. if (SUCCEEDED(_pAuto->_psb->QueryActiveShellView(&psv)))
  4134. {
  4135. IOleCommandTarget *pct;
  4136. if (SUCCEEDED(psv->QueryInterface(IID_PPV_ARG(IOleCommandTarget, &pct))))
  4137. {
  4138. // The name of the ID is misleading -- it really returns the URL of the view. It was
  4139. // invented for Pending views, but works just as well for active views.
  4140. //
  4141. hr = pct->Exec(&CGID_ShellDocView, SHDVID_GETPENDINGURL, 0, NULL, pvarResult);
  4142. SAFERELEASE(pct);
  4143. }
  4144. SAFERELEASE(psv);
  4145. }
  4146. }
  4147. }
  4148. }
  4149. }
  4150. return hr;
  4151. }
  4152. HRESULT CIEFrameAuto::CAutomationStub::Invoke(
  4153. DISPID dispidMember,
  4154. REFIID,
  4155. LCID lcid,
  4156. WORD wFlags,
  4157. DISPPARAMS *pdispparams,
  4158. VARIANT *pvarResult,
  4159. EXCEPINFO *pexcepinfo,
  4160. UINT *)
  4161. {
  4162. return InvokeEx (dispidMember, lcid, wFlags, pdispparams, pvarResult, pexcepinfo, NULL);
  4163. }
  4164. // *** IDispatchEx members ***
  4165. STDMETHODIMP CIEFrameAuto::CAutomationStub::GetDispID(
  4166. BSTR bstrName,
  4167. DWORD grfdex,
  4168. DISPID *pid)
  4169. {
  4170. HRESULT hr;
  4171. if (!_fLoaded)
  4172. ResolveTypeInfo2();
  4173. if (!_pInterfaceTypeInfo2)
  4174. return TYPE_E_CANTLOADLIBRARY;
  4175. // Do a case sensitive compare?
  4176. if (IEFrameAuto()->_pfnMEGetIDsOfNames)
  4177. {
  4178. // Case sensitve GetIDsOfNames.
  4179. hr = (IEFrameAuto()->_pfnMEGetIDsOfNames)(_pInterfaceTypeInfo2,
  4180. IID_NULL,
  4181. &bstrName,
  4182. 1, 0, pid,
  4183. grfdex & fdexNameCaseSensitive);
  4184. }
  4185. else
  4186. {
  4187. hr = _pInterfaceTypeInfo2->GetIDsOfNames(&bstrName, 1, pid);
  4188. }
  4189. // If fails then try typelibrary.
  4190. if (FAILED(hr))
  4191. {
  4192. IDispatchEx *delegate = 0;
  4193. // Always delegate which is faster, avoids loading the typelibrary.
  4194. hr = _GetIDispatchExDelegate(&delegate);
  4195. if (SUCCEEDED(hr))
  4196. {
  4197. hr = delegate->GetDispID(bstrName, grfdex, pid);
  4198. delegate->Release();
  4199. }
  4200. }
  4201. return hr;
  4202. }
  4203. STDMETHODIMP CIEFrameAuto::CAutomationStub::DeleteMemberByName(BSTR bstr, DWORD grfdex)
  4204. {
  4205. HRESULT hr;
  4206. IDispatchEx *delegate = 0;
  4207. // Always delegate which is faster, avoids loading the typelibrary.
  4208. hr = _GetIDispatchExDelegate(&delegate);
  4209. if (SUCCEEDED(hr))
  4210. {
  4211. hr = delegate->DeleteMemberByName(bstr,grfdex);
  4212. delegate->Release();
  4213. }
  4214. return hr;
  4215. }
  4216. STDMETHODIMP CIEFrameAuto::CAutomationStub::DeleteMemberByDispID(DISPID id)
  4217. {
  4218. HRESULT hr;
  4219. IDispatchEx *delegate = 0;
  4220. // Always delegate which is faster, avoids loading the typelibrary.
  4221. hr = _GetIDispatchExDelegate(&delegate);
  4222. if (SUCCEEDED(hr))
  4223. {
  4224. hr = delegate->DeleteMemberByDispID(id);
  4225. delegate->Release();
  4226. }
  4227. return hr;
  4228. }
  4229. STDMETHODIMP CIEFrameAuto::CAutomationStub::GetMemberProperties(DISPID id, DWORD grfdexFetch, DWORD *pgrfdex)
  4230. {
  4231. HRESULT hr;
  4232. IDispatchEx *delegate = 0;
  4233. // Always delegate which is faster, avoids loading the typelibrary.
  4234. hr = _GetIDispatchExDelegate(&delegate);
  4235. if (SUCCEEDED(hr))
  4236. {
  4237. hr = delegate->GetMemberProperties( id, grfdexFetch, pgrfdex);
  4238. delegate->Release();
  4239. }
  4240. return hr;
  4241. }
  4242. STDMETHODIMP CIEFrameAuto::CAutomationStub::GetMemberName(DISPID id, BSTR *pbstrName)
  4243. {
  4244. HRESULT hr;
  4245. IDispatchEx *delegate = 0;
  4246. // Always delegate which is faster, avoids loading the typelibrary.
  4247. hr = _GetIDispatchExDelegate(&delegate);
  4248. if (SUCCEEDED(hr))
  4249. {
  4250. hr = delegate->GetMemberName( id, pbstrName);
  4251. delegate->Release();
  4252. }
  4253. return hr;
  4254. }
  4255. STDMETHODIMP CIEFrameAuto::CAutomationStub::GetNextDispID(
  4256. DWORD grfdex,
  4257. DISPID id,
  4258. DISPID *pid)
  4259. {
  4260. IDispatchEx *delegate = 0;
  4261. HRESULT hr = _GetIDispatchExDelegate(&delegate);
  4262. if (SUCCEEDED(hr))
  4263. {
  4264. hr = delegate->GetNextDispID(grfdex, id, pid);
  4265. delegate->Release();
  4266. }
  4267. return hr;
  4268. }
  4269. STDMETHODIMP CIEFrameAuto::CAutomationStub::GetNameSpaceParent(IUnknown **ppunk)
  4270. {
  4271. HRESULT hr;
  4272. if (!ppunk)
  4273. {
  4274. hr = E_INVALIDARG;
  4275. goto Cleanup;
  4276. }
  4277. *ppunk = NULL;
  4278. hr = S_OK;
  4279. Cleanup:
  4280. return hr;
  4281. }
  4282. // *** IProvideClassInfo members ***
  4283. STDMETHODIMP CIEFrameAuto::CAutomationStub::GetClassInfo(ITypeInfo **typeinfo)
  4284. {
  4285. if (!typeinfo)
  4286. return E_POINTER;
  4287. if (!_fLoaded)
  4288. {
  4289. HRESULT hr = ResolveTypeInfo2();
  4290. if (FAILED(hr))
  4291. {
  4292. *typeinfo = NULL;
  4293. return hr;
  4294. }
  4295. }
  4296. *typeinfo = _pCoClassTypeInfo2;
  4297. if (*typeinfo)
  4298. {
  4299. (*typeinfo)->AddRef();
  4300. return S_OK;
  4301. }
  4302. return E_FAIL;
  4303. }
  4304. /******************************************************************************
  4305. Window Object
  4306. ******************************************************************************/
  4307. // Define static variables
  4308. unsigned long CIEFrameAuto::COmWindow::s_uniqueIndex = 0;
  4309. CIEFrameAuto::COmWindow::COmWindow() :
  4310. CAutomationStub(MIN_BROWSER_DISPID, MAX_BROWSER_DISPID, FALSE)
  4311. {
  4312. ASSERT(FALSE == _fCallbackOK);
  4313. ASSERT(!_pOpenedWindow);
  4314. ASSERT(_varOpener.vt == VT_EMPTY);
  4315. ASSERT(!_dwCPCookie);
  4316. ASSERT(!_pCP);
  4317. ASSERT(!_fOnloadFired);
  4318. ASSERT(!_fIsChild);
  4319. ASSERT(!_pIntelliForms);
  4320. _fDelegateWindowOM = TRUE; // Always delegate, unless told otherwise.
  4321. }
  4322. HRESULT CIEFrameAuto::COmWindow::Init()
  4323. {
  4324. _cpWindowEvents.SetOwner(SAFECAST(SAFECAST(this, CAutomationStub*), IDispatchEx*), &DIID_HTMLWindowEvents);
  4325. CIEFrameAuto* pauto = IToClass(CIEFrameAuto, _omwin, this);
  4326. return CAutomationStub::Init(SAFECAST(this, IHTMLWindow2*), IID_IHTMLWindow2, CLSID_HTMLWindow2, pauto);
  4327. }
  4328. #ifdef NO_MARSHALLING
  4329. EXTERN_C const GUID IID_IWindowStatus;
  4330. #endif
  4331. HRESULT CIEFrameAuto::COmWindow::_InternalQueryInterface(REFIID riid, void ** const ppv)
  4332. {
  4333. ASSERT(!IsEqualIID(riid, IID_IUnknown));
  4334. if (IsEqualIID(riid, IID_IHTMLWindow2) || IsEqualIID(riid, IID_IHTMLFramesCollection2))
  4335. *ppv = SAFECAST(this, IHTMLWindow2*);
  4336. else if (IsEqualIID(riid, IID_IHTMLWindow3))
  4337. *ppv = SAFECAST(this, IHTMLWindow3*);
  4338. else if (IsEqualIID(riid, IID_ITargetNotify))
  4339. *ppv = SAFECAST(this, ITargetNotify*);
  4340. else if (IsEqualIID(riid, IID_IShellHTMLWindowSupport))
  4341. *ppv = SAFECAST(this, IShellHTMLWindowSupport*);
  4342. else if (IsEqualIID(riid, IID_IShellHTMLWindowSupport2))
  4343. *ppv = SAFECAST(this, IShellHTMLWindowSupport2*);
  4344. else if (IsEqualIID(riid, IID_IProvideMultipleClassInfo) ||
  4345. IsEqualIID(riid, IID_IProvideClassInfo2))
  4346. *ppv = SAFECAST(this, IProvideMultipleClassInfo*);
  4347. else if (IsEqualIID(riid, IID_IConnectionPointCB))
  4348. *ppv = SAFECAST(this, IConnectionPointCB*);
  4349. else if (IsEqualIID(riid, IID_IConnectionPointContainer))
  4350. *ppv = SAFECAST(this, IConnectionPointContainer*);
  4351. else if (IsEqualIID(riid, IID_IServiceProvider))
  4352. *ppv = SAFECAST(this, IServiceProvider *);
  4353. #ifdef NO_MARSHALLING
  4354. else if (IsEqualIID(riid, IID_IWindowStatus))
  4355. *ppv = SAFECAST(this, IWindowStatus *);
  4356. #endif
  4357. else
  4358. return E_NOINTERFACE;
  4359. AddRef();
  4360. return S_OK;
  4361. }
  4362. // ** IProvideMultipleClassInfo
  4363. STDMETHODIMP CIEFrameAuto::COmWindow::GetGUID(DWORD dwGuidKind, GUID* pGUID)
  4364. {
  4365. if (!pGUID)
  4366. return E_POINTER;
  4367. if (GUIDKIND_DEFAULT_SOURCE_DISP_IID == dwGuidKind)
  4368. {
  4369. *pGUID = DIID_HTMLWindowEvents;
  4370. return S_OK;
  4371. }
  4372. else
  4373. return E_INVALIDARG;
  4374. }
  4375. /******************************************************************************
  4376. Both IProvideMultipleClassInfo specific methods are passed along to Trident.
  4377. ******************************************************************************/
  4378. STDMETHODIMP CIEFrameAuto::COmWindow::GetMultiTypeInfoCount(ULONG *pcti)
  4379. {
  4380. IHTMLWindow2 *pWindow = 0;
  4381. HRESULT hr = _GetWindowDelegate(&pWindow);
  4382. if (SUCCEEDED(hr))
  4383. {
  4384. IProvideMultipleClassInfo *pMCI = 0;
  4385. hr = pWindow->QueryInterface(IID_PPV_ARG(IProvideMultipleClassInfo, &pMCI));
  4386. pWindow->Release();
  4387. if (SUCCEEDED(hr))
  4388. {
  4389. hr = pMCI->GetMultiTypeInfoCount(pcti);
  4390. pMCI->Release();
  4391. }
  4392. }
  4393. return hr;
  4394. }
  4395. STDMETHODIMP CIEFrameAuto::COmWindow::GetInfoOfIndex(ULONG iti, DWORD dwFlags, ITypeInfo **pptiCoClass, DWORD *pdwTIFlags, ULONG *pcdispidReserved,IID *piidPrimary,IID *piidSource)
  4396. {
  4397. IHTMLWindow2 *pWindow;
  4398. HRESULT hr = _GetWindowDelegate(&pWindow);
  4399. if (SUCCEEDED(hr))
  4400. {
  4401. IProvideMultipleClassInfo *pMCI = 0;
  4402. hr = pWindow->QueryInterface(IID_PPV_ARG(IProvideMultipleClassInfo, &pMCI));
  4403. pWindow->Release();
  4404. if (SUCCEEDED(hr))
  4405. {
  4406. hr = pMCI->GetInfoOfIndex(iti, dwFlags, pptiCoClass, pdwTIFlags, pcdispidReserved, piidPrimary, piidSource);
  4407. pMCI->Release();
  4408. }
  4409. }
  4410. return hr;
  4411. }
  4412. STDMETHODIMP CIEFrameAuto::COmWindow::GetDispID(BSTR bstrName, DWORD grfdex, DISPID *pid)
  4413. {
  4414. IDispatchEx *delegate;
  4415. HRESULT hr = _GetIDispatchExDelegate(&delegate);
  4416. if (SUCCEEDED(hr))
  4417. {
  4418. hr = delegate->GetDispID(bstrName, grfdex, pid);
  4419. delegate->Release();
  4420. }
  4421. else
  4422. {
  4423. return CAutomationStub::GetDispID(bstrName, grfdex, pid);
  4424. }
  4425. return hr;
  4426. }
  4427. /*****************************************************************************
  4428. IServiceProvider - this is used by mshtml as well as intelliforms in iforms.cpp
  4429. ******************************************************************************/
  4430. STDMETHODIMP CIEFrameAuto::COmWindow::QueryService(REFGUID guidService, REFIID riid, void ** ppv)
  4431. {
  4432. HRESULT hr = E_NOINTERFACE;
  4433. if (!ppv)
  4434. return E_POINTER;
  4435. *ppv = NULL;
  4436. if (IsEqualGUID(guidService,IID_IHTMLWindow2))
  4437. {
  4438. return QueryInterface(riid, ppv);
  4439. }
  4440. else if (IsEqualGUID(guidService, IID_IEnumPrivacyRecords))
  4441. {
  4442. IHTMLWindow2 *pWindow = 0;
  4443. IServiceProvider * pISP = NULL;
  4444. hr = _GetWindowDelegate(&pWindow);
  4445. if (SUCCEEDED(hr))
  4446. {
  4447. hr = pWindow->QueryInterface(IID_PPV_ARG(IServiceProvider, &pISP));
  4448. if (SUCCEEDED(hr))
  4449. {
  4450. hr = pISP->QueryService(IID_IEnumPrivacyRecords, riid, ppv);
  4451. pISP->Release();
  4452. }
  4453. pWindow->Release();
  4454. }
  4455. return hr;
  4456. }
  4457. return hr;
  4458. }
  4459. STDMETHODIMP CIEFrameAuto::COmWindow::ViewReleaseIntelliForms()
  4460. {
  4461. ReleaseIntelliForms();
  4462. return S_OK;
  4463. }
  4464. /******************************************************************************
  4465. This method is called when the document contained by the browser is being
  4466. deactivated (like when navigating to a new location). Currently we only use
  4467. this knowledge to handle event sourcing.
  4468. This method could also be used to optimize our connections to expando
  4469. implentations in the document (trident). Currently we obtain and release
  4470. the expando implementations for the Navigator, History, and Location objects
  4471. each time they are needed. ViewRelease (along with ViewActivated) would allow
  4472. us to grab and hold expando implementations until the next navigation.
  4473. ******************************************************************************/
  4474. STDMETHODIMP CIEFrameAuto::COmWindow::ViewReleased()
  4475. {
  4476. UnsinkDelegate();
  4477. ReleaseIntelliForms();
  4478. BSTR bstrName = SysAllocString(STR_FIND_DIALOG_NAME);
  4479. if (bstrName)
  4480. {
  4481. VARIANT varProp;
  4482. if (SUCCEEDED(_pAuto->GetProperty(bstrName, &varProp)))
  4483. {
  4484. if ((varProp.vt == VT_DISPATCH) && (varProp.pdispVal != NULL))
  4485. {
  4486. IUnknown* pWindow = varProp.pdispVal;
  4487. VARIANT vtTmp = {0};
  4488. _pAuto->PutProperty(bstrName, vtTmp);
  4489. //(davemi) see IE5 bug 57060 for why the below line doesn't work and IDispatch must be used instead
  4490. //pWindow->close();
  4491. IDispatch * pdisp;
  4492. if (SUCCEEDED(pWindow->QueryInterface(IID_PPV_ARG(IDispatch, &pdisp))))
  4493. {
  4494. DISPID dispid;
  4495. DISPPARAMS dispparamsNoArgs = {NULL, NULL, 0, 0};
  4496. BSTR bstrClose = SysAllocString(L"close");
  4497. if (bstrClose)
  4498. {
  4499. HRESULT hr;
  4500. hr = pdisp->GetIDsOfNames(IID_NULL, &bstrClose, 1, LOCALE_SYSTEM_DEFAULT, &dispid);
  4501. if (hr == S_OK)
  4502. {
  4503. VARIANT varTmp = {0};
  4504. pdisp->Invoke(dispid, IID_NULL, LOCALE_SYSTEM_DEFAULT, DISPATCH_METHOD, &dispparamsNoArgs, &varTmp, NULL, NULL);
  4505. }
  4506. SysFreeString(bstrClose);
  4507. }
  4508. pdisp->Release();
  4509. }
  4510. }
  4511. VariantClear(&varProp);
  4512. }
  4513. SysFreeString(bstrName);
  4514. }
  4515. return FireOnUnload();
  4516. }
  4517. /******************************************************************************
  4518. This method is called when the document contained by the browser is being
  4519. activated. Currently we only use this knowledge to handle event sourcing.
  4520. See comments for ViewReleased()
  4521. ******************************************************************************/
  4522. STDMETHODIMP CIEFrameAuto::COmWindow::ViewActivated()
  4523. {
  4524. HRESULT hr;
  4525. // These will fail for non-trident documents which is OK.
  4526. SinkDelegate();
  4527. AttachIntelliForms();
  4528. // This call will return TRUE if either:
  4529. // - The document has reached READYSTATE_COMPLETE or
  4530. // - The document does not support the ReadyState property
  4531. // If the delegate is not complete then we will be notified of READYSTATE
  4532. // changes later. These notifications will tell use when the document is
  4533. // complete and the Onload even should be fired.
  4534. if (IsDelegateComplete())
  4535. hr = FireOnLoad();
  4536. else
  4537. hr = S_OK;
  4538. return hr;
  4539. }
  4540. STDMETHODIMP CIEFrameAuto::COmWindow::ReadyStateChangedTo(long ready_state, IShellView *psv)
  4541. {
  4542. HRESULT hr = S_OK;
  4543. // We only want to fire Onload if the ready state has changed to
  4544. // READYSTATE_COMPLETE and the view that has changed states is the
  4545. // currently active view. If the pending view has completed states
  4546. // we can ignore the notification because Onload will be fired when
  4547. // the pending view is activated. Ignoring READYSTATE changes from
  4548. // the pending view garauntees we will never fire onload early for
  4549. // the currently active view.
  4550. if ((READYSTATE_COMPLETE == ready_state) && psv)
  4551. {
  4552. IShellView * const pCurrSV = _pAuto->_GetShellView();
  4553. if (pCurrSV)
  4554. {
  4555. if (IsSameObject(pCurrSV, psv))
  4556. {
  4557. hr = FireOnLoad();
  4558. }
  4559. pCurrSV->Release();
  4560. }
  4561. }
  4562. return hr;
  4563. }
  4564. // Attach intelliforms to FORM elements on page
  4565. HRESULT CIEFrameAuto::COmWindow::AttachIntelliForms()
  4566. {
  4567. HRESULT hr = E_FAIL;
  4568. if (_pIntelliForms)
  4569. {
  4570. ReleaseIntelliForms();
  4571. _pIntelliForms = NULL;
  4572. }
  4573. IHTMLDocument2 *pDoc2=NULL;
  4574. IDispatch *pdispDoc=NULL;
  4575. _pAuto->get_Document(&pdispDoc);
  4576. if (pdispDoc)
  4577. {
  4578. pdispDoc->QueryInterface(IID_PPV_ARG(IHTMLDocument2, &pDoc2));
  4579. pdispDoc->Release();
  4580. }
  4581. if (pDoc2)
  4582. {
  4583. ::AttachIntelliForms(this, NULL, pDoc2, &_pIntelliForms);
  4584. pDoc2->Release();
  4585. hr = S_OK;
  4586. }
  4587. if (_fIntelliFormsAskUser)
  4588. {
  4589. // Possibly ask user if they'd like to enable this feature
  4590. IntelliFormsDoAskUser(_pAuto->_GetHWND(), NULL); // NULL from _GetHWND() OK
  4591. _fIntelliFormsAskUser=FALSE;
  4592. }
  4593. return hr;
  4594. }
  4595. HRESULT CIEFrameAuto::COmWindow::ReleaseIntelliForms()
  4596. {
  4597. if (_pIntelliForms)
  4598. {
  4599. void *p = _pIntelliForms;
  4600. _pIntelliForms = NULL;
  4601. ::ReleaseIntelliForms(p);
  4602. }
  4603. return S_OK;
  4604. }
  4605. HRESULT CIEFrameAuto::COmWindow::DestroyIntelliForms()
  4606. {
  4607. ReleaseIntelliForms();
  4608. return S_OK;
  4609. }
  4610. // Request from Intelliforms that we prompt user on next load about
  4611. // enabling the Intelliforms feature
  4612. HRESULT CIEFrameAuto::COmWindow::IntelliFormsAskUser(LPCWSTR pwszValue)
  4613. {
  4614. _fIntelliFormsAskUser = TRUE;
  4615. return S_OK;
  4616. }
  4617. /******************************************************************************
  4618. This method is called when the browser is no longer busy and we should
  4619. retry any navigate that we had to defer while it was busy.
  4620. ******************************************************************************/
  4621. STDMETHODIMP CIEFrameAuto::COmWindow::CanNavigate()
  4622. {
  4623. CIEFrameAuto* pauto = IToClass(CIEFrameAuto, _omwin, this);
  4624. pauto->_omloc.RetryNavigate();
  4625. return S_OK;
  4626. }
  4627. STDMETHODIMP CIEFrameAuto::COmWindow::ActiveElementChanged(IHTMLElement * pHTMLElement)
  4628. {
  4629. return IntelliFormsActiveElementChanged(_pIntelliForms, pHTMLElement);
  4630. }
  4631. STDMETHODIMP CIEFrameAuto::COmWindow::IsGalleryMeta(BOOL bFlag)
  4632. {
  4633. // _bIsGalleryMeta = bFlag;
  4634. return S_OK;
  4635. }
  4636. HRESULT CIEFrameAuto::COmWindow::_GetIDispatchExDelegate(IDispatchEx ** const ppdelegate)
  4637. {
  4638. if (!ppdelegate)
  4639. return E_POINTER;
  4640. IDispatch *pRootDisp = 0;
  4641. HRESULT hr = GetRootDelegate(_pAuto, &pRootDisp);
  4642. if (SUCCEEDED(hr))
  4643. {
  4644. hr = pRootDisp->QueryInterface(IID_PPV_ARG(IDispatchEx, ppdelegate));
  4645. pRootDisp->Release();
  4646. }
  4647. return hr;
  4648. }
  4649. // *** IHTMLFramesCollection2 ***
  4650. HRESULT CIEFrameAuto::COmWindow::item(
  4651. /* [in] */ VARIANT *pvarIndex,
  4652. /* [retval][out] */ VARIANT *pvarResult)
  4653. {
  4654. IHTMLWindow2 *pWindow = 0;
  4655. HRESULT hr = _GetWindowDelegate(&pWindow);
  4656. if (SUCCEEDED(hr))
  4657. {
  4658. hr = pWindow->item(pvarIndex, pvarResult);
  4659. pWindow->Release();
  4660. }
  4661. return hr;
  4662. }
  4663. HRESULT CIEFrameAuto::COmWindow::get_length(long *pl)
  4664. {
  4665. IHTMLWindow2 *pWindow = 0;
  4666. HRESULT hr = _GetWindowDelegate(&pWindow);
  4667. if (SUCCEEDED(hr))
  4668. {
  4669. hr = pWindow->get_length(pl);
  4670. pWindow->Release();
  4671. }
  4672. return hr;
  4673. }
  4674. // *** IHTMLWindow2 ***
  4675. HRESULT CIEFrameAuto::COmWindow::get_name(BSTR *retval)
  4676. {
  4677. if (!retval)
  4678. return E_POINTER;
  4679. WCHAR *real_frame_name = 0;
  4680. WCHAR *use_frame_name = 0;
  4681. // Why doesn't GetFrameName use BSTR?
  4682. HRESULT hr = _pAuto->GetFrameName(&real_frame_name);
  4683. if (FAILED(hr))
  4684. return hr;
  4685. // If the frame's name is our special NO_NAME_NAME
  4686. // then our name is really be an empty string.
  4687. if (!real_frame_name || !StrCmpNW(real_frame_name, NO_NAME_NAME, ARRAYSIZE(NO_NAME_NAME) -1))
  4688. use_frame_name = L"";
  4689. else
  4690. use_frame_name = real_frame_name;
  4691. ASSERT(use_frame_name);
  4692. *retval = SysAllocString(use_frame_name);
  4693. if (real_frame_name)
  4694. OleFree(real_frame_name);
  4695. return *retval ? S_OK : E_OUTOFMEMORY;
  4696. }
  4697. HRESULT CIEFrameAuto::COmWindow::put_name(
  4698. /* [in] */ BSTR theName)
  4699. {
  4700. if (!theName)
  4701. return E_POINTER;
  4702. return _pAuto->SetFrameName(theName);
  4703. }
  4704. HRESULT CIEFrameAuto::COmWindow::get_parent(IHTMLWindow2 **retval)
  4705. {
  4706. if (!retval)
  4707. return E_POINTER;
  4708. HRESULT hr = E_FAIL;
  4709. IHTMLWindow2 *pWindow = NULL;
  4710. // Attempt to delegate this to the contained object.
  4711. if (_fDelegateWindowOM)
  4712. {
  4713. hr = _GetWindowDelegate(&pWindow);
  4714. if (SUCCEEDED(hr) && pWindow)
  4715. {
  4716. hr = pWindow->get_parent(retval);
  4717. }
  4718. }
  4719. // If delegation fails, use our implementation.
  4720. if (FAILED(hr))
  4721. {
  4722. *retval = 0;
  4723. IUnknown *pUnk = 0;
  4724. hr = _pAuto->GetParentFrame(&pUnk);
  4725. // If we are already the top, GetParentFrame set pUnk to NULL
  4726. if (SUCCEEDED(hr))
  4727. {
  4728. if (pUnk)
  4729. {
  4730. hr = GetWindowFromUnknown(pUnk, retval);
  4731. pUnk->Release();
  4732. }
  4733. else
  4734. {
  4735. *retval = this;
  4736. AddRef();
  4737. }
  4738. }
  4739. }
  4740. SAFERELEASE(pWindow);
  4741. return hr;
  4742. }
  4743. HRESULT CIEFrameAuto::COmWindow::get_self(IHTMLWindow2 **retval)
  4744. {
  4745. if (!retval)
  4746. return E_POINTER;
  4747. *retval = this;
  4748. AddRef();
  4749. return S_OK;
  4750. }
  4751. HRESULT CIEFrameAuto::COmWindow::get_top(IHTMLWindow2 **retval)
  4752. {
  4753. if (!retval)
  4754. return E_POINTER;
  4755. HRESULT hr = E_FAIL;
  4756. IHTMLWindow2 *pWindow = NULL;
  4757. // Attempt to delegate this to contained object.
  4758. if (_fDelegateWindowOM)
  4759. {
  4760. hr = _GetWindowDelegate(&pWindow);
  4761. if (SUCCEEDED(hr) && pWindow)
  4762. {
  4763. hr = pWindow->get_top(retval);
  4764. }
  4765. }
  4766. // If delegation fails, use our implementation.
  4767. if (FAILED(hr))
  4768. {
  4769. *retval = 0;
  4770. IUnknown *pUnk = 0;
  4771. // AddRef the interface to we can Release it in the while loop
  4772. ITargetFrame2 *pTfr = _pAuto;
  4773. pTfr->AddRef();
  4774. hr = pTfr->GetParentFrame(&pUnk);
  4775. // Keep calling GetParent until we fail or get a NULL (which is the top
  4776. while (SUCCEEDED(hr) && pUnk)
  4777. {
  4778. SAFERELEASE(pTfr);
  4779. hr = pUnk->QueryInterface(IID_PPV_ARG(ITargetFrame2, &pTfr));
  4780. pUnk->Release();
  4781. if (SUCCEEDED(hr))
  4782. hr = pTfr->GetParentFrame(&pUnk);
  4783. }
  4784. if (SUCCEEDED(hr))
  4785. hr = GetWindowFromUnknown(pTfr, retval);
  4786. SAFERELEASE(pTfr);
  4787. }
  4788. SAFERELEASE(pWindow);
  4789. return hr;
  4790. }
  4791. HRESULT CIEFrameAuto::COmWindow::get_window(IHTMLWindow2 **retval)
  4792. {
  4793. if (!retval)
  4794. return E_POINTER;
  4795. *retval = this;
  4796. AddRef();
  4797. return S_OK;
  4798. }
  4799. HRESULT CIEFrameAuto::COmWindow::get_frames(IHTMLFramesCollection2 **retval)
  4800. {
  4801. IHTMLWindow2 *pWindow = 0;
  4802. HRESULT hr = _GetWindowDelegate(&pWindow);
  4803. if (SUCCEEDED(hr))
  4804. {
  4805. hr = pWindow->get_frames(retval);
  4806. pWindow->Release();
  4807. }
  4808. return hr;
  4809. }
  4810. HRESULT CIEFrameAuto::COmWindow::get_location(IHTMLLocation **retval)
  4811. {
  4812. if (!retval)
  4813. return E_POINTER;
  4814. *retval = &_pAuto->_omloc;
  4815. (*retval)->AddRef();
  4816. return S_OK;
  4817. }
  4818. HRESULT CIEFrameAuto::COmWindow::get_navigator(IOmNavigator **retval)
  4819. {
  4820. if (!retval)
  4821. return E_POINTER;
  4822. *retval = &_pAuto->_omnav;
  4823. (*retval)->AddRef();
  4824. return S_OK;
  4825. }
  4826. HRESULT CIEFrameAuto::COmWindow::get_clientInformation(IOmNavigator **retval)
  4827. {
  4828. IHTMLWindow2 *pWindow = 0;
  4829. HRESULT hr = _GetWindowDelegate(&pWindow);
  4830. if (SUCCEEDED(hr))
  4831. {
  4832. hr = pWindow->get_clientInformation(retval);
  4833. pWindow->Release();
  4834. }
  4835. return hr;
  4836. }
  4837. HRESULT CIEFrameAuto::COmWindow::get_history(IOmHistory **retval)
  4838. {
  4839. if (!retval)
  4840. return E_POINTER;
  4841. *retval = &_pAuto->_omhist;
  4842. (*retval)->AddRef();
  4843. return S_OK;
  4844. }
  4845. HRESULT CIEFrameAuto::COmWindow::put_defaultStatus(BSTR statusmsg)
  4846. {
  4847. IHTMLWindow2 *pWindow = 0;
  4848. HRESULT hr = _GetWindowDelegate(&pWindow);
  4849. if (SUCCEEDED(hr))
  4850. {
  4851. hr = pWindow->put_defaultStatus(statusmsg);
  4852. pWindow->Release();
  4853. }
  4854. return hr;
  4855. }
  4856. HRESULT CIEFrameAuto::COmWindow::get_defaultStatus(BSTR *retval)
  4857. {
  4858. IHTMLWindow2 *pWindow = 0;
  4859. HRESULT hr = _GetWindowDelegate(&pWindow);
  4860. if (SUCCEEDED(hr))
  4861. {
  4862. hr = pWindow->get_defaultStatus(retval);
  4863. pWindow->Release();
  4864. }
  4865. return hr;
  4866. }
  4867. HRESULT CIEFrameAuto::COmWindow::put_status(BSTR statusmsg)
  4868. {
  4869. IHTMLWindow2 *pWindow = 0;
  4870. HRESULT hr = _GetWindowDelegate(&pWindow);
  4871. if (SUCCEEDED(hr))
  4872. {
  4873. hr = pWindow->put_status(statusmsg);
  4874. pWindow->Release();
  4875. }
  4876. return hr;
  4877. }
  4878. HRESULT CIEFrameAuto::COmWindow::get_status(BSTR *retval)
  4879. {
  4880. IHTMLWindow2 *pWindow = 0;
  4881. HRESULT hr = _GetWindowDelegate(&pWindow);
  4882. if (SUCCEEDED(hr))
  4883. {
  4884. hr = pWindow->get_status(retval);
  4885. pWindow->Release();
  4886. }
  4887. return hr;
  4888. }
  4889. HRESULT CIEFrameAuto::COmWindow::setTimeout(
  4890. /* [in] */ BSTR expression,
  4891. /* [in] */ long msec,
  4892. /* [optional] */ VARIANT *language,
  4893. /* [retval][out] */ long *timerID)
  4894. {
  4895. IHTMLWindow2 *pWindow = 0;
  4896. HRESULT hr = _GetWindowDelegate(&pWindow);
  4897. if (SUCCEEDED(hr))
  4898. {
  4899. hr = pWindow->setTimeout(expression, msec, language, timerID);
  4900. pWindow->Release();
  4901. }
  4902. return hr;
  4903. }
  4904. HRESULT CIEFrameAuto::COmWindow::clearTimeout(long timerID)
  4905. {
  4906. IHTMLWindow2 *pWindow = 0;
  4907. HRESULT hr = _GetWindowDelegate(&pWindow);
  4908. if (SUCCEEDED(hr))
  4909. {
  4910. hr = pWindow->clearTimeout(timerID);
  4911. pWindow->Release();
  4912. }
  4913. return hr;
  4914. }
  4915. HRESULT CIEFrameAuto::COmWindow::setInterval(
  4916. /* [in] */ BSTR expression,
  4917. /* [in] */ long msec,
  4918. /* [optional] */ VARIANT *language,
  4919. /* [retval][out] */ long *timerID)
  4920. {
  4921. IHTMLWindow2 *pWindow = 0;
  4922. HRESULT hr = _GetWindowDelegate(&pWindow);
  4923. if (SUCCEEDED(hr))
  4924. {
  4925. hr = pWindow->setInterval(expression, msec, language, timerID);
  4926. pWindow->Release();
  4927. }
  4928. return hr;
  4929. }
  4930. HRESULT CIEFrameAuto::COmWindow::clearInterval(long timerID)
  4931. {
  4932. IHTMLWindow2 *pWindow = 0;
  4933. HRESULT hr = _GetWindowDelegate(&pWindow);
  4934. if (SUCCEEDED(hr))
  4935. {
  4936. hr = pWindow->clearInterval(timerID);
  4937. pWindow->Release();
  4938. }
  4939. return hr;
  4940. }
  4941. HRESULT CIEFrameAuto::COmWindow::alert(BSTR message)
  4942. {
  4943. IHTMLWindow2 *pWindow = 0;
  4944. HRESULT hr = _GetWindowDelegate(&pWindow);
  4945. if (SUCCEEDED(hr))
  4946. {
  4947. hr = pWindow->alert(message);
  4948. pWindow->Release();
  4949. }
  4950. return hr;
  4951. }
  4952. HRESULT CIEFrameAuto::COmWindow::focus()
  4953. {
  4954. IHTMLWindow2 *pWindow = 0;
  4955. HRESULT hr = _GetWindowDelegate(&pWindow);
  4956. if (SUCCEEDED(hr))
  4957. {
  4958. hr = pWindow->focus();
  4959. pWindow->Release();
  4960. }
  4961. return hr;
  4962. }
  4963. HRESULT CIEFrameAuto::COmWindow::close()
  4964. {
  4965. IUnknown *pUnk = 0;
  4966. HRESULT hr;
  4967. if (_pAuto->_psb != _pAuto->_psbProxy) //if it's a band, just hide it
  4968. {
  4969. return IUnknown_ShowBrowserBar(_pAuto->_psbTop, CLSID_SearchBand, FALSE);
  4970. }
  4971. hr = _pAuto->GetParentFrame(&pUnk);
  4972. if (SUCCEEDED(hr))
  4973. {
  4974. if (!pUnk)
  4975. {
  4976. if (_fIsChild ||
  4977. IDYES == MLShellMessageBox(
  4978. _pAuto->_GetHWND(), // NULL from _GetHWND() OK
  4979. MAKEINTRESOURCE(IDS_CONFIRM_SCRIPT_CLOSE_TEXT),
  4980. MAKEINTRESOURCE(IDS_TITLE),
  4981. MB_YESNO | MB_ICONQUESTION))
  4982. {
  4983. _pAuto->Quit();
  4984. }
  4985. }
  4986. else
  4987. pUnk->Release();
  4988. }
  4989. return hr;
  4990. }
  4991. HRESULT CIEFrameAuto::COmWindow::blur()
  4992. {
  4993. IHTMLWindow2 *pWindow = 0;
  4994. HRESULT hr = _GetWindowDelegate(&pWindow);
  4995. if (SUCCEEDED(hr))
  4996. {
  4997. hr = pWindow->blur();
  4998. pWindow->Release();
  4999. }
  5000. return hr;
  5001. }
  5002. HRESULT CIEFrameAuto::COmWindow::scroll(long x, long y)
  5003. {
  5004. IHTMLWindow2 *pWindow = 0;
  5005. HRESULT hr = _GetWindowDelegate(&pWindow);
  5006. if (SUCCEEDED(hr))
  5007. {
  5008. hr = pWindow->scroll(x, y);
  5009. pWindow->Release();
  5010. }
  5011. return hr;
  5012. }
  5013. HRESULT CIEFrameAuto::COmWindow::confirm(
  5014. /* [optional] */ BSTR message,
  5015. /* [retval][out] */VARIANT_BOOL* confirmed)
  5016. {
  5017. IHTMLWindow2 *pWindow = 0;
  5018. HRESULT hr = _GetWindowDelegate(&pWindow);
  5019. if (SUCCEEDED(hr))
  5020. {
  5021. hr = pWindow->confirm(message, confirmed);
  5022. pWindow->Release();
  5023. }
  5024. return hr;
  5025. }
  5026. HRESULT CIEFrameAuto::COmWindow::prompt(
  5027. /* [optional] */ BSTR message,
  5028. /* [optional] */ BSTR defstr,
  5029. /* [retval][out] */ VARIANT* textdata)
  5030. {
  5031. IHTMLWindow2 *pWindow = 0;
  5032. HRESULT hr = _GetWindowDelegate(&pWindow);
  5033. if (SUCCEEDED(hr))
  5034. {
  5035. hr = pWindow->prompt(message, defstr, textdata);
  5036. pWindow->Release();
  5037. }
  5038. return hr;
  5039. }
  5040. HRESULT CIEFrameAuto::COmWindow::get_closed(VARIANT_BOOL *pl)
  5041. {
  5042. *pl = 0;
  5043. return S_OK;
  5044. }
  5045. #ifdef NO_MARSHALLING
  5046. HRESULT CIEFrameAuto::COmWindow::IsWindowActivated()
  5047. {
  5048. ASSERT(_pAuto);
  5049. BOOL fComplete = FALSE;
  5050. // Check for proper readystate support
  5051. IDispatch *pdispatch;
  5052. if (SUCCEEDED(_pAuto->get_Document(&pdispatch)))
  5053. {
  5054. VARIANTARG va;
  5055. EXCEPINFO excp;
  5056. if (SUCCEEDED(pdispatch->Invoke(DISPID_READYSTATE,
  5057. IID_NULL,
  5058. LOCALE_USER_DEFAULT,
  5059. DISPATCH_PROPERTYGET,
  5060. (DISPPARAMS *)&g_dispparamsNoArgs,
  5061. &va,
  5062. &excp,
  5063. NULL)))
  5064. {
  5065. if (VT_I4 == va.vt && READYSTATE_COMPLETE == va.lVal)
  5066. fComplete = TRUE;
  5067. }
  5068. pdispatch->Release();
  5069. }
  5070. return (fComplete?S_OK:S_FALSE);
  5071. }
  5072. #endif
  5073. // *** IHTMLWindow2 ***
  5074. HRESULT CIEFrameAuto::COmWindow::open(
  5075. /* [in] */ BSTR url,
  5076. /* [in] */ BSTR name,
  5077. /* [in] */ BSTR features,
  5078. /* [in] */ VARIANT_BOOL replace,
  5079. /* [out][retval] */ IHTMLWindow2 **ppomWindowResult)
  5080. {
  5081. // bradsch 11/11/96 this needs to be added back in at some point.
  5082. /*
  5083. // If the host does not support multiple windows in the same thread,
  5084. // then disable window.open
  5085. if (!g_fMultipleWindowsSupportedByHost)
  5086. {
  5087. // Hide the resulting error message from the user
  5088. if (m_pParser)
  5089. m_pParser->ShowErrors(FALSE);
  5090. return E_NOTIMPL;
  5091. }
  5092. */
  5093. ASSERT(ppomWindowResult);
  5094. if (!ppomWindowResult)
  5095. return E_POINTER;
  5096. HRESULT hr = S_OK;
  5097. BSTR bstrUrl = NULL;
  5098. BSTR bstrWindowName = NULL;
  5099. BSTR bstrUrlAbsolute = NULL;
  5100. _OpenOptions.ReInitialize();
  5101. // Process parameter: url
  5102. if (!url)
  5103. {
  5104. // if the URL is empty, use blank.htm instead
  5105. bstrUrl = SysAllocString(L"");
  5106. }
  5107. // Process parameter: name
  5108. if (name)
  5109. {
  5110. // Make sure we have a legal name
  5111. for(int i = 0; i < lstrlenW(name); i++)
  5112. {
  5113. if (!(IsCharAlphaNumericWrapW(name[i]) || TEXT('_') == name[i]))
  5114. {
  5115. hr = E_INVALIDARG;
  5116. goto Exit;
  5117. }
  5118. }
  5119. }
  5120. // Process parameter: features
  5121. if (features && lstrlenW(features) > 0)
  5122. {
  5123. hr = _ParseOptionString(features);
  5124. if (hr)
  5125. goto Exit;
  5126. }
  5127. //
  5128. // ***TLL*** shdocvw needs to handle the replace parameter.
  5129. //
  5130. // Compute the absolute version of the URL
  5131. if (!bstrUrl || *bstrUrl)
  5132. {
  5133. if (url)
  5134. {
  5135. if (*url == EMPTY_URL)
  5136. {
  5137. bstrUrlAbsolute = SysAllocString(url);
  5138. }
  5139. else
  5140. {
  5141. bstrUrlAbsolute = _pAuto->_omloc.ComputeAbsoluteUrl(bstrUrl ? bstrUrl : url);
  5142. }
  5143. }
  5144. }
  5145. else
  5146. {
  5147. bstrUrlAbsolute = bstrUrl;
  5148. bstrUrl = NULL;
  5149. }
  5150. if (!bstrUrlAbsolute)
  5151. goto Exit;
  5152. // If a window name is not provided we need to assign it a private name
  5153. // so we do not lose track of it. If the window name is "_blank" we need
  5154. // to create a new window each time with a private name. Other portions
  5155. // of this class must be smart enough to return and an empty string when
  5156. // this private name is used.
  5157. if (!name || !*name || (*name && !StrCmpW(name, L"_blank")))
  5158. {
  5159. bstrWindowName = _GenerateUniqueWindowName();
  5160. }
  5161. // Window open state tracking
  5162. _fCallbackOK = FALSE;
  5163. *ppomWindowResult = NULL;
  5164. // Try to navigate a frame in an existing window to the url or open a new one
  5165. hr = OpenAndNavigateToURL(_pAuto,
  5166. &bstrUrlAbsolute,
  5167. bstrWindowName ? bstrWindowName : name,
  5168. SAFECAST(this, ITargetNotify*),
  5169. replace,
  5170. BOOLIFY(_pAuto->m_bSilent));
  5171. if (SUCCEEDED(hr))
  5172. {
  5173. if (_fCallbackOK)
  5174. {
  5175. *ppomWindowResult = _pOpenedWindow;
  5176. _pOpenedWindow = NULL;
  5177. ASSERT(*ppomWindowResult);
  5178. #ifdef NO_MARSHALLING
  5179. MSG msg;
  5180. while (GetMessage(&msg, NULL, 0, 0))
  5181. {
  5182. TranslateMessage(&msg);
  5183. DispatchMessage(&msg);
  5184. IWindowStatus *pws;
  5185. if ((*ppomWindowResult) && SUCCEEDED((*ppomWindowResult)->QueryInterface(IID_PPV_ARG(IWindowStatus, &pws))))
  5186. {
  5187. if (pws->IsWindowActivated() == S_OK)
  5188. {
  5189. pws->Release();
  5190. break;
  5191. }
  5192. pws->Release();
  5193. }
  5194. else
  5195. break;
  5196. }
  5197. #endif
  5198. }
  5199. // This might turn an S_FALSE into an S_OK, but is needed to keep Trident happy.
  5200. // Change this back to if (hr != S_FALSE) hr = E_FAIL,
  5201. // change BASESB.CPP to return S_FALSE instead of S_OK on a busy navigate,
  5202. // and change Trident to handle S_FALSE from window.open (RRETURN1(hr, S_FALSE));
  5203. // hr = S_OK;
  5204. }
  5205. Exit:
  5206. SAFERELEASE(_pOpenedWindow);
  5207. // Clean up the unique name if we generated it ourself
  5208. if (bstrUrl)
  5209. SysFreeString(bstrUrl);
  5210. if (bstrUrlAbsolute)
  5211. SysFreeString(bstrUrlAbsolute);
  5212. if (bstrWindowName)
  5213. SysFreeString(bstrWindowName);
  5214. return hr;
  5215. }
  5216. BSTR CIEFrameAuto::COmWindow::_GenerateUniqueWindowName()
  5217. {
  5218. WCHAR buffer[ ARRAYSIZE(NO_NAME_NAME) + 12 ];
  5219. // Choose a name the user isn't likely to typed. Need to guard
  5220. // this becuase s_uniqueIndex is a shared static variable.
  5221. ENTERCRITICAL;
  5222. unsigned long val = ++s_uniqueIndex;
  5223. LEAVECRITICAL;
  5224. StringCchPrintf(buffer, ARRAYSIZE(buffer), L"%ls%lu", NO_NAME_NAME, val);
  5225. return SysAllocString(buffer);
  5226. }
  5227. //
  5228. // Zhenbinx - Trident only talks OM Unit, not device unit.
  5229. //
  5230. class CHiResUnitConvert
  5231. {
  5232. public:
  5233. CHiResUnitConvert(IHTMLWindow2 *pWindow2)
  5234. : _pWindow2(pWindow2)
  5235. {
  5236. if (_pWindow2)
  5237. {
  5238. _pWindow2->AddRef();
  5239. }
  5240. _llogicalXDPI = _llogicalYDPI = 1;
  5241. _ldeviceXDPI = _ldeviceYDPI = 1;
  5242. _fInited = FALSE;
  5243. }
  5244. ~CHiResUnitConvert()
  5245. {
  5246. if (_pWindow2)
  5247. {
  5248. _pWindow2->Release();
  5249. }
  5250. }
  5251. HRESULT Init();
  5252. LONG DeviceFromDocPixelsX(LONG cx)
  5253. {
  5254. if (!_fInited) Init();
  5255. return cx * _ldeviceXDPI / _llogicalXDPI;
  5256. }
  5257. LONG DeviceFromDocPixelsY(LONG cy)
  5258. {
  5259. if (!_fInited) Init();
  5260. return cy * _ldeviceYDPI / _llogicalYDPI;
  5261. }
  5262. private:
  5263. IHTMLWindow2 *_pWindow2;
  5264. BOOL _fInited;
  5265. LONG _llogicalXDPI;
  5266. LONG _llogicalYDPI;
  5267. LONG _ldeviceXDPI;
  5268. LONG _ldeviceYDPI;
  5269. };
  5270. HRESULT CHiResUnitConvert::Init()
  5271. {
  5272. HRESULT hr = S_OK;
  5273. IHTMLScreen *pScreen = NULL;
  5274. IHTMLScreen2 *pScreen2 = NULL;
  5275. if (!_pWindow2)
  5276. {
  5277. hr = E_FAIL;
  5278. goto Cleanup;
  5279. }
  5280. _fInited = TRUE;
  5281. hr = _pWindow2->get_screen(&pScreen);
  5282. if (!SUCCEEDED(hr))
  5283. goto Cleanup;
  5284. hr = pScreen->QueryInterface(IID_PPV_ARG(IHTMLScreen2, &pScreen2));
  5285. if (!SUCCEEDED(hr))
  5286. goto Cleanup;
  5287. hr = pScreen2->get_logicalXDPI(&_llogicalXDPI);
  5288. if (!SUCCEEDED(hr))
  5289. goto Cleanup;
  5290. hr = pScreen2->get_logicalYDPI(&_llogicalYDPI);
  5291. if (!SUCCEEDED(hr))
  5292. goto Cleanup;
  5293. hr = pScreen2->get_deviceXDPI(&_ldeviceXDPI);
  5294. if (!SUCCEEDED(hr))
  5295. goto Cleanup;
  5296. hr = pScreen2->get_deviceYDPI(&_ldeviceYDPI);
  5297. if (!SUCCEEDED(hr))
  5298. goto Cleanup;
  5299. #if DBG == 1
  5300. {
  5301. WCHAR wcBuffer[255];
  5302. StringCchPrintf(wcBuffer, ARRAYSIZE(wcBuffer), _T("logical: [%d]-[%d], device: [%d]-[%d]"), _llogicalXDPI, _llogicalYDPI, _ldeviceXDPI, _ldeviceYDPI);
  5303. OutputDebugString(wcBuffer);
  5304. }
  5305. #endif
  5306. Cleanup:
  5307. if (pScreen)
  5308. pScreen->Release();
  5309. if (pScreen2)
  5310. pScreen2->Release();
  5311. return hr;
  5312. }
  5313. HRESULT CIEFrameAuto::COmWindow::_ParseOptionString(BSTR bstrOptionString, ITargetNotify2 * ptgnNotify2 /* = NULL */)
  5314. {
  5315. BSTR optionName = NULL;
  5316. BSTR optionValue = NULL;
  5317. int fValue = TRUE;
  5318. BOOL fFirstSet = TRUE;
  5319. IHTMLWindow2 *pWindow = NULL;
  5320. BOOL fFullScreen = FALSE;
  5321. BOOL fChannelMode = FALSE;
  5322. if (!SUCCEEDED(_GetWindowDelegate(&pWindow)) && ptgnNotify2)
  5323. {
  5324. ptgnNotify2->QueryInterface(IID_PPV_ARG(IHTMLWindow2, &pWindow));
  5325. }
  5326. CHiResUnitConvert unitcvt(pWindow);
  5327. // CHiResUnitConvert's constructor AddRefs pWindow, we can release this here
  5328. if (pWindow)
  5329. pWindow->Release();
  5330. // Parse the options
  5331. while (GetNextOption(bstrOptionString, &optionName, &fValue))
  5332. {
  5333. if (fFirstSet)
  5334. {
  5335. // Netscape's interpretation is, if you set any open options
  5336. // then, unless explicitly set, turn off various UI options
  5337. _OpenOptions.fToolbar = FALSE;
  5338. _OpenOptions.fLocation = FALSE;
  5339. _OpenOptions.fDirectories = FALSE;
  5340. _OpenOptions.fStatus = FALSE;
  5341. _OpenOptions.fMenubar = FALSE;
  5342. _OpenOptions.fScrollbars = FALSE;
  5343. _OpenOptions.fResizable = FALSE;
  5344. fFirstSet = FALSE;
  5345. }
  5346. if (!StrCmpIW(L"toolbar", optionName))
  5347. _OpenOptions.fToolbar = fValue;
  5348. else if (!StrCmpIW(L"location", optionName))
  5349. _OpenOptions.fLocation = fValue;
  5350. else if (!StrCmpIW(L"directories", optionName))
  5351. _OpenOptions.fDirectories = fValue;
  5352. else if (!StrCmpIW(L"status", optionName))
  5353. _OpenOptions.fStatus = fValue;
  5354. else if (!StrCmpIW(L"menubar", optionName))
  5355. _OpenOptions.fMenubar = fValue;
  5356. else if (!StrCmpIW(L"scrollbars", optionName))
  5357. _OpenOptions.fScrollbars = fValue;
  5358. else if (!StrCmpIW(L"resizable", optionName))
  5359. _OpenOptions.fResizable = fValue;
  5360. else if (!StrCmpIW(L"width", optionName))
  5361. _OpenOptions.iWidth = unitcvt.DeviceFromDocPixelsX(fValue);
  5362. else if (!StrCmpIW(L"height", optionName))
  5363. _OpenOptions.iHeight = unitcvt.DeviceFromDocPixelsY(fValue);
  5364. else if (!StrCmpIW(L"fullscreen", optionName))
  5365. fFullScreen = fValue;
  5366. else if (!StrCmpIW(L"top", optionName))
  5367. _OpenOptions.iTop = unitcvt.DeviceFromDocPixelsY(fValue);
  5368. else if (!StrCmpIW(L"left", optionName))
  5369. _OpenOptions.iLeft = unitcvt.DeviceFromDocPixelsX(fValue);
  5370. else if (!StrCmpIW(L"channelmode", optionName))
  5371. fChannelMode = fValue;
  5372. else if (!StrCmpIW(L"titlebar", optionName))
  5373. _OpenOptions.fTitlebar = fValue;
  5374. SysFreeString(optionName);
  5375. }
  5376. // We no longer allow fullscreen mode. However,
  5377. // setting channel and fullscreen does something
  5378. // different that we want to keep
  5379. if (fFullScreen && fChannelMode)
  5380. {
  5381. _OpenOptions.fChannelMode = TRUE;
  5382. _OpenOptions.fFullScreen = TRUE;
  5383. }
  5384. else if (fFullScreen || fChannelMode)
  5385. {
  5386. _OpenOptions.fChannelMode = TRUE;
  5387. }
  5388. return S_OK;
  5389. }
  5390. // *** ITargetNotify members ***
  5391. /******************************************************************************
  5392. Called when navigate must create a new window. pUnkDestination is
  5393. IWebBrowserApp object for new frame (also HLinkFrame,ITargetFrame).
  5394. ******************************************************************************/
  5395. HRESULT CIEFrameAuto::COmWindow::OnCreate(IUnknown *pUnkDestination, ULONG cbCookie)
  5396. {
  5397. if (!pUnkDestination)
  5398. {
  5399. _fCallbackOK = FALSE;
  5400. return E_FAIL;
  5401. }
  5402. IWebBrowser2 *pNewIE = NULL;
  5403. HRESULT hr = pUnkDestination->QueryInterface(IID_PPV_ARG(IWebBrowser2, &pNewIE));
  5404. if (SUCCEEDED(hr))
  5405. {
  5406. _ApplyOpenOptions(pNewIE);
  5407. SAFERELEASE(_pOpenedWindow);
  5408. // We do not want to release this window. It will be handed out
  5409. // to caller of window.open. It is up to the caller to release it.
  5410. hr = GetWindowFromUnknown(pUnkDestination, &_pOpenedWindow);
  5411. if (SUCCEEDED(hr))
  5412. {
  5413. VARIANT var, varDummy;
  5414. VariantInit(&var);
  5415. VariantInit(&varDummy);
  5416. var.vt = VT_DISPATCH;
  5417. var.pdispVal = static_cast<CAutomationStub*>(this);
  5418. // call dummy put_opener in order to make use of its marshalling to set
  5419. // child flag in opened window
  5420. V_VT(&varDummy) = VT_BOOL;
  5421. V_BOOL(&varDummy) = 666;
  5422. hr = _pOpenedWindow->put_opener(varDummy);
  5423. // set actual opener
  5424. hr = _pOpenedWindow->put_opener(var);
  5425. }
  5426. //bradsch 10/27/96
  5427. //Need some code here that tells the IWebBrowserApp not to persist its state.
  5428. //This capability does not yet exist on IWebBrowserApp, mikesch is adding it.
  5429. pNewIE->Release();
  5430. }
  5431. if (SUCCEEDED(hr))
  5432. _fCallbackOK = TRUE;
  5433. return hr;
  5434. }
  5435. HRESULT CIEFrameAuto::COmWindow::OnReuse(IUnknown *pUnkDestination)
  5436. {
  5437. if (!pUnkDestination)
  5438. {
  5439. _fCallbackOK = FALSE;
  5440. return E_FAIL;
  5441. }
  5442. SAFERELEASE(_pOpenedWindow);
  5443. // We do not want to release this window. It will be handed out
  5444. // to caller of window.open. It is up to the caller to release it.
  5445. HRESULT hr = GetWindowFromUnknown(pUnkDestination, &_pOpenedWindow);
  5446. if (SUCCEEDED(hr))
  5447. _fCallbackOK = TRUE;
  5448. return hr;
  5449. }
  5450. HRESULT CIEFrameAuto::COmWindow::_ApplyOpenOptions(IWebBrowser2 *pie)
  5451. {
  5452. BOOL fMinusOne = FALSE;
  5453. ASSERT(pie);
  5454. // test TRUE explictly, as "2" is used as not inited
  5455. if (TRUE == _OpenOptions.fChannelMode)
  5456. {
  5457. pie->put_TheaterMode(-1);
  5458. if (!SHRestricted2W(REST_NoChannelUI, NULL, 0))
  5459. {
  5460. SA_BSTRGUID strGuid;
  5461. VARIANT vaGuid;
  5462. InitFakeBSTR(&strGuid, CLSID_FavBand);
  5463. vaGuid.vt = VT_BSTR;
  5464. vaGuid.bstrVal = strGuid.wsz;
  5465. pie->ShowBrowserBar(&vaGuid, NULL, NULL);
  5466. }
  5467. }
  5468. else if (_OpenOptions.fLocation
  5469. || _OpenOptions.fDirectories
  5470. || (_OpenOptions.fToolbar && _OpenOptions.fToolbar != CIEFrameAuto::COmWindow::BOOL_NOTSET)
  5471. || _OpenOptions.fMenubar)
  5472. {
  5473. // If either "location=yes" (Address bar) or "directories=yes" (Quick Links bar) or
  5474. // "toolbar=yes" are on, we need the internet toolbar to be on.
  5475. // Then we can turn off the bands we don't want.
  5476. //
  5477. pie->put_ToolBar(TRUE);
  5478. // We need to use the ShowBrowserBar method to handle bars/bands for which we don't have individual
  5479. // properties.
  5480. //
  5481. VARIANT varClsid, varShow, varOptional;
  5482. VariantInit(&varClsid);
  5483. VariantInit(&varShow);
  5484. VariantInit(&varOptional);
  5485. varClsid.vt = VT_I2;
  5486. varShow.vt = VT_BOOL;
  5487. varShow.boolVal = VARIANT_FALSE;
  5488. varOptional.vt = VT_ERROR;
  5489. varOptional.scode = DISP_E_PARAMNOTFOUND;
  5490. // "location=yes/no"
  5491. //
  5492. pie->put_AddressBar(BOOLIFY(_OpenOptions.fLocation));
  5493. fMinusOne = fMinusOne || !_OpenOptions.fLocation;
  5494. // "toolbar=yes/no"
  5495. //
  5496. varClsid.iVal = FCW_TOOLBAND;
  5497. varShow.boolVal = TO_VARIANT_BOOL(_OpenOptions.fToolbar);
  5498. pie->ShowBrowserBar(&varClsid, &varShow, &varOptional);
  5499. fMinusOne = fMinusOne || !_OpenOptions.fToolbar;
  5500. // "directories=yes/no"
  5501. //
  5502. varClsid.iVal = FCW_LINKSBAR;
  5503. varShow.boolVal = TO_VARIANT_BOOL(_OpenOptions.fDirectories);
  5504. pie->ShowBrowserBar(&varClsid, &varShow, &varOptional);
  5505. fMinusOne = fMinusOne || !_OpenOptions.fDirectories;
  5506. }
  5507. else
  5508. {
  5509. pie->put_ToolBar(FALSE);
  5510. }
  5511. // "statusbar=yes/no"
  5512. //
  5513. pie->put_StatusBar(BOOLIFY(_OpenOptions.fStatus));
  5514. fMinusOne = fMinusOne || !_OpenOptions.fStatus;
  5515. // "menubar=yes/no"
  5516. //
  5517. pie->put_MenuBar(BOOLIFY(_OpenOptions.fMenubar));
  5518. fMinusOne = fMinusOne || !_OpenOptions.fMenubar;
  5519. if (CIEFrameAuto::COmWindow::BOOL_NOTSET != _OpenOptions.fFullScreen)
  5520. pie->put_FullScreen(_OpenOptions.fFullScreen);
  5521. if (_OpenOptions.fScrollbars == FALSE)
  5522. {
  5523. DWORD dwFlags;
  5524. LPTARGETFRAME2 ptgf;
  5525. if (SUCCEEDED(pie->QueryInterface(IID_PPV_ARG(ITargetFrame2, &ptgf))))
  5526. {
  5527. if (SUCCEEDED(ptgf->GetFrameOptions(&dwFlags)))
  5528. {
  5529. if (_OpenOptions.fScrollbars == FALSE)
  5530. {
  5531. dwFlags &= ~(FRAMEOPTIONS_SCROLL_YES|FRAMEOPTIONS_SCROLL_NO|FRAMEOPTIONS_SCROLL_AUTO);
  5532. dwFlags |= FRAMEOPTIONS_SCROLL_NO;
  5533. }
  5534. ptgf->SetFrameOptions(dwFlags);
  5535. }
  5536. ptgf->Release();
  5537. }
  5538. }
  5539. pie->put_Resizable(BOOLIFY(_OpenOptions.fResizable));
  5540. // Only use the position and size information if the
  5541. // the script does not enable full-screen mode
  5542. if (TRUE != _OpenOptions.fFullScreen)
  5543. {
  5544. CIEFrameAuto * pFrameAuto = SAFECAST(pie, CIEFrameAuto *);
  5545. if (pFrameAuto)
  5546. pFrameAuto->put_Titlebar(_OpenOptions.fTitlebar);
  5547. // If the script specifies no size or positional information and
  5548. // the current window is in FullScreen mode then open the new
  5549. // window in FullScreen mode as well.
  5550. if (_OpenOptions.iWidth < 0 && _OpenOptions.iHeight < 0 && _OpenOptions.iTop < 0 && _OpenOptions.iLeft < 0)
  5551. {
  5552. VARIANT_BOOL fs = 0;
  5553. CIEFrameAuto* pauto = IToClass(CIEFrameAuto, _omwin, this);
  5554. HRESULT hr = pauto->get_FullScreen(&fs);
  5555. if (SUCCEEDED(hr) && fs)
  5556. pie->put_FullScreen(fs);
  5557. }
  5558. else
  5559. {
  5560. int iWidth = _OpenOptions.iWidth > 0 ? _OpenOptions.iWidth:300;
  5561. int iHeight = _OpenOptions.iHeight > 0 ? _OpenOptions.iHeight:300;
  5562. // Set a minimum size of 100x100
  5563. iWidth = iWidth > 100 ? iWidth : 100;
  5564. iHeight = iHeight > 100 ? iHeight : 100;
  5565. // Yes! Netscape doesn't treat the width and height as a content
  5566. // size when at least one adornment is turned off
  5567. if (fMinusOne) pie->ClientToWindow(&iWidth, &iHeight);
  5568. if (_OpenOptions.iWidth > 0)
  5569. pie->put_Width(iWidth);
  5570. if (_OpenOptions.iHeight > 0)
  5571. pie->put_Height(iHeight);
  5572. if (_OpenOptions.iTop >= 0)
  5573. pie->put_Top(_OpenOptions.iTop);
  5574. if (_OpenOptions.iLeft >= 0)
  5575. pie->put_Left(_OpenOptions.iLeft);
  5576. }
  5577. }
  5578. return S_OK;
  5579. }
  5580. HRESULT CIEFrameAuto::COmWindow::get_document(IHTMLDocument2 **ppomDocumentResult)
  5581. {
  5582. IHTMLWindow2 *pWindow = 0;
  5583. HRESULT hr = _GetWindowDelegate(&pWindow);
  5584. if (SUCCEEDED(hr))
  5585. {
  5586. hr = pWindow->get_document(ppomDocumentResult);
  5587. pWindow->Release();
  5588. }
  5589. return hr;
  5590. }
  5591. HRESULT CIEFrameAuto::COmWindow::navigate(BSTR url)
  5592. {
  5593. // This will do all the fun things that must be done
  5594. // to an URL before is can be used to navigate.
  5595. return _pAuto->_omloc.put_href(url);
  5596. }
  5597. /******************************************************************************
  5598. get_opener -
  5599. Returns the value of the opener property.
  5600. ******************************************************************************/
  5601. HRESULT CIEFrameAuto::COmWindow::get_opener(
  5602. /* [retval][out] */ VARIANT *pretval)
  5603. {
  5604. if (!pretval)
  5605. return E_POINTER;
  5606. return VariantCopy(pretval, &_varOpener);
  5607. }
  5608. /******************************************************************************
  5609. put_opener -
  5610. Sets the opener property opener of this window. This method may
  5611. be called either internally (from C++ code) or from a script. We must
  5612. Release our current opener if the new opener is valid (or VT_NULL).
  5613. COmWindow's DeInit method ensures this never causes a circular reference
  5614. when this object is in the same thread as "opener".
  5615. ******************************************************************************/
  5616. HRESULT CIEFrameAuto::COmWindow::put_opener(VARIANT opener)
  5617. {
  5618. // piggy back on put_opener's marshalling to set child flag. This will be called
  5619. // with VT_TYPE==VT_BOOL and a value of 666 only from oncreate(). Chances of this
  5620. // happening from script is very remote.
  5621. if (!_fIsChild && V_VT(&opener) == VT_BOOL && V_BOOL(&opener) == 666)
  5622. {
  5623. _fIsChild = TRUE;
  5624. return S_OK;
  5625. }
  5626. return VariantCopy(&_varOpener, &opener);
  5627. }
  5628. /******************************************************************************
  5629. executScript -
  5630. immediately executes the script passed in. needed for the multimedia
  5631. controls
  5632. ******************************************************************************/
  5633. HRESULT CIEFrameAuto::COmWindow::execScript(
  5634. /* [in] */ BSTR bstrCode,
  5635. /* [in] */ BSTR bstrLanguage,
  5636. /* [out] */ VARIANT *pvarRet)
  5637. {
  5638. IHTMLWindow2 *pWindow = 0;
  5639. HRESULT hr = _GetWindowDelegate(&pWindow);
  5640. if (SUCCEEDED(hr))
  5641. {
  5642. hr = pWindow->execScript(bstrCode, bstrLanguage, pvarRet);
  5643. pWindow->Release();
  5644. }
  5645. return hr;
  5646. }
  5647. HRESULT CIEFrameAuto::COmWindow::get_onblur(VARIANT *p)
  5648. {
  5649. IHTMLWindow2 *pWindow = 0;
  5650. HRESULT hr = _GetWindowDelegate(&pWindow);
  5651. if (SUCCEEDED(hr))
  5652. {
  5653. hr = pWindow->get_onblur(p);
  5654. pWindow->Release();
  5655. }
  5656. return hr;
  5657. }
  5658. HRESULT CIEFrameAuto::COmWindow::put_onblur(
  5659. /* [in] */ VARIANT v)
  5660. {
  5661. IHTMLWindow2 *pWindow = 0;
  5662. HRESULT hr = _GetWindowDelegate(&pWindow);
  5663. if (SUCCEEDED(hr))
  5664. {
  5665. hr = pWindow->put_onblur(v);
  5666. pWindow->Release();
  5667. }
  5668. return hr;
  5669. }
  5670. /******************************************************************************
  5671. get_onfocus -
  5672. Returns the value of the onfocus property.
  5673. ******************************************************************************/
  5674. HRESULT CIEFrameAuto::COmWindow::get_onfocus(VARIANT *p)
  5675. {
  5676. IHTMLWindow2 *pWindow = 0;
  5677. HRESULT hr = _GetWindowDelegate(&pWindow);
  5678. if (SUCCEEDED(hr))
  5679. {
  5680. hr = pWindow->get_onfocus(p);
  5681. pWindow->Release();
  5682. }
  5683. return hr;
  5684. }
  5685. HRESULT CIEFrameAuto::COmWindow::put_onfocus(
  5686. /* [in] */ VARIANT v)
  5687. {
  5688. IHTMLWindow2 *pWindow = 0;
  5689. HRESULT hr = _GetWindowDelegate(&pWindow);
  5690. if (SUCCEEDED(hr))
  5691. {
  5692. hr = pWindow->put_onfocus(v);
  5693. pWindow->Release();
  5694. }
  5695. return hr;
  5696. }
  5697. /******************************************************************************
  5698. get_onload -
  5699. Returns the value of the onload property.
  5700. ******************************************************************************/
  5701. HRESULT CIEFrameAuto::COmWindow::get_onload(
  5702. /* [p][out] */ VARIANT *p)
  5703. {
  5704. IHTMLWindow2 *pWindow = 0;
  5705. HRESULT hr = _GetWindowDelegate(&pWindow);
  5706. if (SUCCEEDED(hr))
  5707. {
  5708. hr = pWindow->get_onload(p);
  5709. pWindow->Release();
  5710. }
  5711. return hr;
  5712. }
  5713. HRESULT CIEFrameAuto::COmWindow::put_onload(VARIANT v)
  5714. {
  5715. IHTMLWindow2 *pWindow = 0;
  5716. HRESULT hr = _GetWindowDelegate(&pWindow);
  5717. if (SUCCEEDED(hr))
  5718. {
  5719. hr = pWindow->put_onload(v);
  5720. pWindow->Release();
  5721. }
  5722. return hr;
  5723. }
  5724. /******************************************************************************
  5725. get_onunload -
  5726. Returns the value of the onunload property.
  5727. ******************************************************************************/
  5728. HRESULT CIEFrameAuto::COmWindow::get_onunload(
  5729. /* [p][out] */ VARIANT *p)
  5730. {
  5731. IHTMLWindow2 *pWindow = 0;
  5732. HRESULT hr = _GetWindowDelegate(&pWindow);
  5733. if (SUCCEEDED(hr))
  5734. {
  5735. hr = pWindow->get_onunload(p);
  5736. pWindow->Release();
  5737. }
  5738. return hr;
  5739. }
  5740. HRESULT CIEFrameAuto::COmWindow::put_onunload(VARIANT v)
  5741. {
  5742. IHTMLWindow2 *pWindow = 0;
  5743. HRESULT hr = _GetWindowDelegate(&pWindow);
  5744. if (SUCCEEDED(hr))
  5745. {
  5746. hr = pWindow->put_onunload(v);
  5747. pWindow->Release();
  5748. }
  5749. return hr;
  5750. }
  5751. HRESULT CIEFrameAuto::COmWindow::put_onbeforeunload(VARIANT v)
  5752. {
  5753. IHTMLWindow2 *pWindow = 0;
  5754. HRESULT hr = _GetWindowDelegate(&pWindow);
  5755. if (SUCCEEDED(hr))
  5756. {
  5757. hr = pWindow->put_onbeforeunload(v);
  5758. pWindow->Release();
  5759. }
  5760. return hr;
  5761. }
  5762. HRESULT CIEFrameAuto::COmWindow::get_onbeforeunload(VARIANT *p)
  5763. {
  5764. IHTMLWindow2 *pWindow = 0;
  5765. HRESULT hr = _GetWindowDelegate(&pWindow);
  5766. if (SUCCEEDED(hr))
  5767. {
  5768. hr = pWindow->get_onbeforeunload(p);
  5769. pWindow->Release();
  5770. }
  5771. return hr;
  5772. }
  5773. /******************************************************************************
  5774. get_onhelp -
  5775. Returns the value of the onhelp property.
  5776. ******************************************************************************/
  5777. HRESULT CIEFrameAuto::COmWindow::get_onhelp(
  5778. /* [p][out] */ VARIANT *p)
  5779. {
  5780. IHTMLWindow2 *pWindow = 0;
  5781. HRESULT hr = _GetWindowDelegate(&pWindow);
  5782. if (SUCCEEDED(hr))
  5783. {
  5784. hr = pWindow->get_onhelp(p);
  5785. pWindow->Release();
  5786. }
  5787. return hr;
  5788. }
  5789. HRESULT CIEFrameAuto::COmWindow::put_onhelp(VARIANT v)
  5790. {
  5791. IHTMLWindow2 *pWindow = 0;
  5792. HRESULT hr = _GetWindowDelegate(&pWindow);
  5793. if (SUCCEEDED(hr))
  5794. {
  5795. hr = pWindow->put_onhelp(v);
  5796. pWindow->Release();
  5797. }
  5798. return hr;
  5799. }
  5800. /******************************************************************************
  5801. get_onresize -
  5802. Returns the value of the resize property.
  5803. ******************************************************************************/
  5804. HRESULT CIEFrameAuto::COmWindow::get_onresize(
  5805. /* [p][out] */ VARIANT *p)
  5806. {
  5807. IHTMLWindow2 *pWindow = 0;
  5808. HRESULT hr = _GetWindowDelegate(&pWindow);
  5809. if (SUCCEEDED(hr))
  5810. {
  5811. hr = pWindow->get_onresize(p);
  5812. pWindow->Release();
  5813. }
  5814. return hr;
  5815. }
  5816. HRESULT CIEFrameAuto::COmWindow::put_onresize(VARIANT v)
  5817. {
  5818. IHTMLWindow2 *pWindow = 0;
  5819. HRESULT hr = _GetWindowDelegate(&pWindow);
  5820. if (SUCCEEDED(hr))
  5821. {
  5822. hr = pWindow->put_onresize(v);
  5823. pWindow->Release();
  5824. }
  5825. return hr;
  5826. }
  5827. /******************************************************************************
  5828. get_onscroll -
  5829. Returns the value of the onscroll property.
  5830. ******************************************************************************/
  5831. HRESULT CIEFrameAuto::COmWindow::get_onscroll(
  5832. /* [p][out] */ VARIANT *p)
  5833. {
  5834. IHTMLWindow2 *pWindow = 0;
  5835. HRESULT hr = _GetWindowDelegate(&pWindow);
  5836. if (SUCCEEDED(hr))
  5837. {
  5838. hr = pWindow->get_onscroll(p);
  5839. pWindow->Release();
  5840. }
  5841. return hr;
  5842. }
  5843. HRESULT CIEFrameAuto::COmWindow::put_onscroll(VARIANT v)
  5844. {
  5845. IHTMLWindow2 *pWindow = 0;
  5846. HRESULT hr = _GetWindowDelegate(&pWindow);
  5847. if (SUCCEEDED(hr))
  5848. {
  5849. hr = pWindow->put_onscroll(v);
  5850. pWindow->Release();
  5851. }
  5852. return hr;
  5853. }
  5854. HRESULT CIEFrameAuto::COmWindow::get_Image(IHTMLImageElementFactory **retval)
  5855. {
  5856. IHTMLWindow2 *pWindow = 0;
  5857. HRESULT hr = _GetWindowDelegate(&pWindow);
  5858. if (SUCCEEDED(hr))
  5859. {
  5860. hr = pWindow->get_Image(retval);
  5861. pWindow->Release();
  5862. }
  5863. return hr;
  5864. }
  5865. /******************************************************************************
  5866. get_onerror -
  5867. Returns the value of the onerror property.
  5868. ******************************************************************************/
  5869. HRESULT CIEFrameAuto::COmWindow::get_onerror(
  5870. /* [p][out] */ VARIANT *p)
  5871. {
  5872. IHTMLWindow2 *pWindow = 0;
  5873. HRESULT hr = _GetWindowDelegate(&pWindow);
  5874. if (SUCCEEDED(hr))
  5875. {
  5876. hr = pWindow->get_onerror(p);
  5877. pWindow->Release();
  5878. }
  5879. return hr;
  5880. }
  5881. HRESULT CIEFrameAuto::COmWindow::put_onerror(VARIANT v)
  5882. {
  5883. IHTMLWindow2 *pWindow = 0;
  5884. HRESULT hr = _GetWindowDelegate(&pWindow);
  5885. if (SUCCEEDED(hr))
  5886. {
  5887. hr = pWindow->put_onerror(v);
  5888. pWindow->Release();
  5889. }
  5890. return hr;
  5891. }
  5892. HRESULT CIEFrameAuto::COmWindow::get_event(IHTMLEventObj **p)
  5893. {
  5894. IHTMLWindow2 *pWindow = 0;
  5895. HRESULT hr = _GetWindowDelegate(&pWindow);
  5896. if (SUCCEEDED(hr))
  5897. {
  5898. hr = pWindow->get_event(p);
  5899. pWindow->Release();
  5900. }
  5901. return hr;
  5902. }
  5903. HRESULT CIEFrameAuto::COmWindow::get__newEnum(IUnknown **p)
  5904. {
  5905. IHTMLWindow2 *pWindow = 0;
  5906. HRESULT hr = _GetWindowDelegate(&pWindow);
  5907. if (SUCCEEDED(hr))
  5908. {
  5909. hr = pWindow->get__newEnum(p);
  5910. pWindow->Release();
  5911. }
  5912. return hr;
  5913. }
  5914. HRESULT CIEFrameAuto::COmWindow::showModalDialog(BSTR dialog,
  5915. VARIANT* varArgIn,
  5916. VARIANT* varOptions,
  5917. VARIANT* varArgOut)
  5918. {
  5919. IHTMLWindow2 *pWindow = 0;
  5920. HRESULT hr = _GetWindowDelegate(&pWindow);
  5921. if (SUCCEEDED(hr))
  5922. {
  5923. hr = pWindow->showModalDialog(dialog, varArgIn, varOptions, varArgOut);
  5924. pWindow->Release();
  5925. }
  5926. return hr;
  5927. }
  5928. HRESULT CIEFrameAuto::COmWindow::showHelp(BSTR helpURL, VARIANT helpArg, BSTR features)
  5929. {
  5930. IHTMLWindow2 *pWindow = 0;
  5931. HRESULT hr = _GetWindowDelegate(&pWindow);
  5932. if (SUCCEEDED(hr))
  5933. {
  5934. hr = pWindow->showHelp(helpURL, helpArg, features);
  5935. pWindow->Release();
  5936. }
  5937. return hr;
  5938. }
  5939. HRESULT CIEFrameAuto::COmWindow::get_screen(IHTMLScreen **p)
  5940. {
  5941. IHTMLWindow2 *pWindow = 0;
  5942. HRESULT hr = _GetWindowDelegate(&pWindow);
  5943. if (SUCCEEDED(hr))
  5944. {
  5945. hr = pWindow->get_screen(p);
  5946. pWindow->Release();
  5947. }
  5948. return hr;
  5949. }
  5950. HRESULT CIEFrameAuto::COmWindow::get_Option(IHTMLOptionElementFactory **retval)
  5951. {
  5952. IHTMLWindow2 *pWindow = 0;
  5953. HRESULT hr = _GetWindowDelegate(&pWindow);
  5954. if (SUCCEEDED(hr))
  5955. {
  5956. hr = pWindow->get_Option(retval);
  5957. pWindow->Release();
  5958. }
  5959. return hr;
  5960. }
  5961. HRESULT CIEFrameAuto::COmWindow::toString(BSTR *Str)
  5962. {
  5963. IHTMLWindow2 *pWindow = 0;
  5964. HRESULT hr = _GetWindowDelegate(&pWindow);
  5965. if (SUCCEEDED(hr))
  5966. {
  5967. hr = pWindow->toString(Str);
  5968. pWindow->Release();
  5969. }
  5970. return hr;
  5971. }
  5972. HRESULT CIEFrameAuto::COmWindow::scrollBy(long x, long y)
  5973. {
  5974. IHTMLWindow2 *pWindow = 0;
  5975. HRESULT hr = _GetWindowDelegate(&pWindow);
  5976. if (SUCCEEDED(hr))
  5977. {
  5978. hr = pWindow->scrollBy(x, y);
  5979. pWindow->Release();
  5980. }
  5981. return hr;
  5982. }
  5983. HRESULT CIEFrameAuto::COmWindow::scrollTo(long x, long y)
  5984. {
  5985. IHTMLWindow2 *pWindow = 0;
  5986. HRESULT hr = _GetWindowDelegate(&pWindow);
  5987. if (SUCCEEDED(hr))
  5988. {
  5989. hr = pWindow->scrollTo(x, y);
  5990. pWindow->Release();
  5991. }
  5992. return hr;
  5993. }
  5994. HRESULT CIEFrameAuto::COmWindow::get_external(IDispatch **ppDisp)
  5995. {
  5996. IHTMLWindow2 *pWindow = 0;
  5997. HRESULT hr = _GetWindowDelegate(&pWindow);
  5998. if (SUCCEEDED(hr))
  5999. {
  6000. hr = pWindow->get_external(ppDisp);
  6001. pWindow->Release();
  6002. }
  6003. return hr;
  6004. }
  6005. // **** IHTMLWindow3 ****
  6006. HRESULT CIEFrameAuto::COmWindow::print()
  6007. {
  6008. IHTMLWindow3 *pWindow = NULL;
  6009. HRESULT hr = _GetWindowDelegate(&pWindow);
  6010. if (SUCCEEDED(hr))
  6011. {
  6012. hr = pWindow->print();
  6013. pWindow->Release();
  6014. }
  6015. return hr;
  6016. }
  6017. HRESULT CIEFrameAuto::COmWindow::showModelessDialog(BSTR strUrl,
  6018. VARIANT * pvarArgIn,
  6019. VARIANT * pvarOptions,
  6020. IHTMLWindow2 ** ppDialog)
  6021. {
  6022. IHTMLWindow3 *pWindow = 0;
  6023. HRESULT hr = _GetWindowDelegate(&pWindow);
  6024. if (SUCCEEDED(hr))
  6025. {
  6026. hr = pWindow->showModelessDialog(strUrl,
  6027. pvarArgIn,
  6028. pvarOptions,
  6029. ppDialog);
  6030. pWindow->Release();
  6031. }
  6032. return hr;
  6033. }
  6034. HRESULT CIEFrameAuto::COmWindow::put_onbeforeprint(VARIANT v)
  6035. {
  6036. IHTMLWindow3 *pWindow = 0;
  6037. HRESULT hr = _GetWindowDelegate(&pWindow);
  6038. if (SUCCEEDED(hr))
  6039. {
  6040. hr = pWindow->put_onbeforeprint(v);
  6041. pWindow->Release();
  6042. }
  6043. return hr;
  6044. }
  6045. HRESULT CIEFrameAuto::COmWindow::get_onbeforeprint(VARIANT *p)
  6046. {
  6047. IHTMLWindow3 *pWindow = 0;
  6048. HRESULT hr = _GetWindowDelegate(&pWindow);
  6049. if (SUCCEEDED(hr))
  6050. {
  6051. hr = pWindow->get_onbeforeprint(p);
  6052. pWindow->Release();
  6053. }
  6054. return hr;
  6055. }
  6056. HRESULT CIEFrameAuto::COmWindow::put_onafterprint(VARIANT v)
  6057. {
  6058. IHTMLWindow3 *pWindow = 0;
  6059. HRESULT hr = _GetWindowDelegate(&pWindow);
  6060. if (SUCCEEDED(hr))
  6061. {
  6062. hr = pWindow->put_onafterprint(v);
  6063. pWindow->Release();
  6064. }
  6065. return hr;
  6066. }
  6067. HRESULT CIEFrameAuto::COmWindow::get_onafterprint(VARIANT *p)
  6068. {
  6069. IHTMLWindow3 *pWindow = 0;
  6070. HRESULT hr = _GetWindowDelegate(&pWindow);
  6071. if (SUCCEEDED(hr))
  6072. {
  6073. hr = pWindow->get_onafterprint(p);
  6074. pWindow->Release();
  6075. }
  6076. return hr;
  6077. }
  6078. HRESULT CIEFrameAuto::COmWindow::get_screenTop(long *plVal)
  6079. {
  6080. IHTMLWindow3 *pWindow = 0;
  6081. HRESULT hr = _GetWindowDelegate(&pWindow);
  6082. if (SUCCEEDED(hr))
  6083. {
  6084. hr = pWindow->get_screenTop(plVal);
  6085. pWindow->Release();
  6086. }
  6087. return hr;
  6088. }
  6089. HRESULT CIEFrameAuto::COmWindow::get_screenLeft(long *plVal)
  6090. {
  6091. IHTMLWindow3 *pWindow = 0;
  6092. HRESULT hr = _GetWindowDelegate(&pWindow);
  6093. if (SUCCEEDED(hr))
  6094. {
  6095. hr = pWindow->get_screenLeft(plVal);
  6096. pWindow->Release();
  6097. }
  6098. return hr;
  6099. }
  6100. HRESULT CIEFrameAuto::COmWindow::get_clipboardData(IHTMLDataTransfer **ppDataTransfer)
  6101. {
  6102. IHTMLWindow3 *pWindow = NULL;
  6103. HRESULT hr = _GetWindowDelegate(&pWindow);
  6104. if (SUCCEEDED(hr))
  6105. {
  6106. hr = pWindow->get_clipboardData(ppDataTransfer);
  6107. pWindow->Release();
  6108. }
  6109. return hr;
  6110. }
  6111. HRESULT CIEFrameAuto::COmWindow::attachEvent(BSTR event, IDispatch* pDisp, VARIANT_BOOL *pResult)
  6112. {
  6113. IHTMLWindow3 *pWindow = 0;
  6114. HRESULT hr = _GetWindowDelegate(&pWindow);
  6115. if (SUCCEEDED(hr))
  6116. {
  6117. hr = pWindow->attachEvent(event, pDisp, pResult);
  6118. pWindow->Release();
  6119. }
  6120. return hr;
  6121. }
  6122. HRESULT CIEFrameAuto::COmWindow::detachEvent(BSTR event, IDispatch* pDisp)
  6123. {
  6124. IHTMLWindow3 *pWindow = 0;
  6125. HRESULT hr = _GetWindowDelegate(&pWindow);
  6126. if (SUCCEEDED(hr))
  6127. {
  6128. hr = pWindow->detachEvent(event, pDisp);
  6129. pWindow->Release();
  6130. }
  6131. return hr;
  6132. }
  6133. HRESULT CIEFrameAuto::COmWindow::setTimeout(
  6134. /* [in] */ VARIANT *pExpression,
  6135. /* [in] */ long msec,
  6136. /* [optional] */ VARIANT *language,
  6137. /* [retval][out] */ long *timerID)
  6138. {
  6139. IHTMLWindow3 *pWindow = 0;
  6140. HRESULT hr = _GetWindowDelegate(&pWindow);
  6141. if (SUCCEEDED(hr))
  6142. {
  6143. hr = pWindow->setTimeout(pExpression, msec, language, timerID);
  6144. pWindow->Release();
  6145. }
  6146. return hr;
  6147. }
  6148. HRESULT CIEFrameAuto::COmWindow::setInterval(
  6149. /* [in] */ VARIANT *pExpression,
  6150. /* [in] */ long msec,
  6151. /* [optional] */ VARIANT *language,
  6152. /* [retval][out] */ long *timerID)
  6153. {
  6154. IHTMLWindow3 *pWindow = 0;
  6155. HRESULT hr = _GetWindowDelegate(&pWindow);
  6156. if (SUCCEEDED(hr))
  6157. {
  6158. hr = pWindow->setInterval(pExpression, msec, language, timerID);
  6159. pWindow->Release();
  6160. }
  6161. return hr;
  6162. }
  6163. HRESULT CIEFrameAuto::COmWindow::moveTo(long x, long y)
  6164. {
  6165. HWND hwnd = _pAuto->_GetHWND();
  6166. if (!hwnd)
  6167. return S_OK;
  6168. ::SetWindowPos(hwnd, NULL, x, y, 0, 0, SWP_NOACTIVATE|SWP_NOZORDER|SWP_NOSIZE);
  6169. return S_OK;
  6170. }
  6171. HRESULT CIEFrameAuto::COmWindow::moveBy(long x, long y)
  6172. {
  6173. HWND hwnd = _pAuto->_GetHWND();
  6174. RECT rcWindow;
  6175. if (!hwnd)
  6176. return S_OK;
  6177. ::GetWindowRect (hwnd, &rcWindow);
  6178. ::SetWindowPos(hwnd, NULL, rcWindow.left+x, rcWindow.top+y, 0, 0, SWP_NOACTIVATE|SWP_NOZORDER|SWP_NOSIZE);
  6179. return S_OK;
  6180. }
  6181. HRESULT CIEFrameAuto::COmWindow::resizeTo(long x, long y)
  6182. {
  6183. HWND hwnd = _pAuto->_GetHWND();
  6184. if (!hwnd)
  6185. return S_OK;
  6186. if (x < 100)
  6187. x = 100;
  6188. if (y < 100)
  6189. y = 100;
  6190. ::SetWindowPos(hwnd, NULL, 0, 0, x, y, SWP_NOACTIVATE|SWP_NOZORDER|SWP_NOMOVE);
  6191. return S_OK;
  6192. }
  6193. HRESULT CIEFrameAuto::COmWindow::resizeBy(long x, long y)
  6194. {
  6195. HWND hwnd = _pAuto->_GetHWND();
  6196. RECT rcWindow;
  6197. long w, h;
  6198. if (!hwnd)
  6199. return S_OK;
  6200. ::GetWindowRect (hwnd, &rcWindow);
  6201. w = rcWindow.right - rcWindow.left + x;
  6202. h = rcWindow.bottom - rcWindow.top + y;
  6203. if (w < 100)
  6204. w = 100;
  6205. if (h < 100)
  6206. h = 100;
  6207. ::SetWindowPos(hwnd, NULL, 0, 0, w, h, SWP_NOACTIVATE|SWP_NOZORDER|SWP_NOMOVE);
  6208. return S_OK;
  6209. }
  6210. HRESULT CIEFrameAuto::COmWindow::_GetWindowDelegate(IHTMLWindow2 **ppomwDelegate)
  6211. {
  6212. if (!ppomwDelegate)
  6213. return E_POINTER;
  6214. IDispatch *pRootDisp = 0;
  6215. HRESULT hr = GetRootDelegate(_pAuto, &pRootDisp);
  6216. if (SUCCEEDED(hr))
  6217. {
  6218. hr = pRootDisp->QueryInterface(IID_PPV_ARG(IHTMLWindow2, ppomwDelegate));
  6219. pRootDisp->Release();
  6220. }
  6221. return hr;
  6222. }
  6223. HRESULT CIEFrameAuto::COmWindow::_GetWindowDelegate(IHTMLWindow3 **ppomwDelegate)
  6224. {
  6225. if (!ppomwDelegate)
  6226. return E_POINTER;
  6227. IDispatch *pRootDisp = 0;
  6228. HRESULT hr = GetRootDelegate(_pAuto, &pRootDisp);
  6229. if (SUCCEEDED(hr))
  6230. {
  6231. hr = pRootDisp->QueryInterface(IID_PPV_ARG(IHTMLWindow3, ppomwDelegate));
  6232. pRootDisp->Release();
  6233. }
  6234. return hr;
  6235. }
  6236. HRESULT CIEFrameAuto::COmWindow::SinkDelegate()
  6237. {
  6238. // Force an Unadvise if we already have a connection
  6239. if (_pCP)
  6240. UnsinkDelegate();
  6241. // If we do not have anyone sinking us, then we don't need to sink our
  6242. // delegate. If someone sinks us later we will sink our delegate in
  6243. // the IConnectionPointCB::OnAdvise callback.
  6244. if (_cpWindowEvents.IsEmpty())
  6245. return S_OK;
  6246. IHTMLWindow2 *pWindow;
  6247. HRESULT hr = _GetWindowDelegate(&pWindow);
  6248. if (SUCCEEDED(hr))
  6249. {
  6250. // We have to connect to the event source to get Trident specific events.
  6251. hr = ConnectToConnectionPoint(&_wesDelegate, DIID_HTMLWindowEvents, TRUE, pWindow, &_dwCPCookie, &_pCP);
  6252. pWindow->Release();
  6253. }
  6254. return hr;
  6255. }
  6256. HRESULT CIEFrameAuto::COmWindow::UnsinkDelegate()
  6257. {
  6258. if (_pCP)
  6259. {
  6260. _pCP->Unadvise(_dwCPCookie);
  6261. _pCP->Release();
  6262. _pCP = 0;
  6263. _dwCPCookie = 0;
  6264. }
  6265. return S_OK;
  6266. }
  6267. /******************************************************************************
  6268. Someone has sinked our events. This means we need to sink the events of our
  6269. delegate docobject if we have not already done so.
  6270. ******************************************************************************/
  6271. HRESULT CIEFrameAuto::COmWindow::OnAdvise(REFIID iid, DWORD cSinks, ULONG_PTR dwCookie)
  6272. {
  6273. HRESULT hr;
  6274. if (!_pCP)
  6275. hr = SinkDelegate();
  6276. else
  6277. hr = S_OK;
  6278. return hr;
  6279. }
  6280. HRESULT CIEFrameAuto::COmWindow::FireOnUnload()
  6281. {
  6282. HRESULT hr;
  6283. if (_fOnloadFired)
  6284. {
  6285. hr = _cpWindowEvents.InvokeDispid(DISPID_ONUNLOAD);
  6286. _fOnloadFired = FALSE;
  6287. }
  6288. else
  6289. hr = S_OK;
  6290. return hr;
  6291. }
  6292. HRESULT CIEFrameAuto::COmWindow::FireOnLoad()
  6293. {
  6294. HRESULT hr;
  6295. if (!_fOnloadFired)
  6296. {
  6297. hr = _cpWindowEvents.InvokeDispid(DISPID_ONUNLOAD);
  6298. _fOnloadFired = TRUE;
  6299. }
  6300. else
  6301. hr = S_OK;
  6302. return hr;
  6303. }
  6304. /******************************************************************************
  6305. Check of the docobject document is complete. The document is considered
  6306. complete if either:
  6307. - The document has reached READYSTATE_COMPLETE or
  6308. - The document does not support the DISPID_READYSTATE property
  6309. If the document is not complete, the caller of this method knows the
  6310. delegate supports the READYSTATE property and will receive a future
  6311. READYSTATE_COMPLETE notification.
  6312. ******************************************************************************/
  6313. BOOL CIEFrameAuto::COmWindow::IsDelegateComplete()
  6314. {
  6315. ASSERT(_pAuto);
  6316. BOOL fSupportsReadystate = FALSE;
  6317. BOOL fComplete = FALSE;
  6318. // Check for proper readystate support
  6319. IDispatch *pdispatch;
  6320. if (SUCCEEDED(_pAuto->get_Document(&pdispatch)))
  6321. {
  6322. VARIANTARG va;
  6323. EXCEPINFO excp;
  6324. if (SUCCEEDED(pdispatch->Invoke(DISPID_READYSTATE,
  6325. IID_NULL,
  6326. LOCALE_USER_DEFAULT,
  6327. DISPATCH_PROPERTYGET,
  6328. (DISPPARAMS *)&g_dispparamsNoArgs,
  6329. &va,
  6330. &excp,
  6331. NULL)))
  6332. {
  6333. fSupportsReadystate = TRUE;
  6334. if (VT_I4 == va.vt && READYSTATE_COMPLETE == va.lVal)
  6335. fComplete = TRUE;
  6336. }
  6337. pdispatch->Release();
  6338. }
  6339. return !fSupportsReadystate || fComplete;
  6340. }
  6341. STDMETHODIMP CIEFrameAuto::COmWindow::CWindowEventSink::QueryInterface(REFIID riid, void **ppv)
  6342. {
  6343. if (IsEqualIID(riid, IID_IUnknown) ||
  6344. IsEqualIID(riid, IID_IDispatch) ||
  6345. IsEqualIID(riid, DIID_HTMLWindowEvents) )
  6346. {
  6347. *ppv = SAFECAST(this, IDispatch*);
  6348. }
  6349. else
  6350. {
  6351. *ppv = NULL;
  6352. return E_NOINTERFACE;
  6353. }
  6354. AddRef();
  6355. return S_OK;
  6356. }
  6357. /******************************************************************************
  6358. We want to bind the lifetime of our owning object to this object
  6359. ******************************************************************************/
  6360. ULONG CIEFrameAuto::COmWindow::CWindowEventSink::AddRef(void)
  6361. {
  6362. COmWindow* pwin = IToClass(COmWindow, _wesDelegate, this);
  6363. return pwin->AddRef();
  6364. }
  6365. /******************************************************************************
  6366. We want to bind the lifetime of our owning object to this object
  6367. ******************************************************************************/
  6368. ULONG CIEFrameAuto::COmWindow::CWindowEventSink::Release(void)
  6369. {
  6370. COmWindow* pwin = IToClass(COmWindow, _wesDelegate, this);
  6371. return pwin->Release();
  6372. }
  6373. // *** IDispatch ***
  6374. STDMETHODIMP CIEFrameAuto::COmWindow::CWindowEventSink::Invoke(
  6375. DISPID dispid,
  6376. REFIID riid,
  6377. LCID lcid,
  6378. WORD wFlags,
  6379. DISPPARAMS *pdispparams,
  6380. VARIANT *pvarResult,
  6381. EXCEPINFO *pexcepinfo,
  6382. UINT *puArgErr )
  6383. {
  6384. HRESULT hr;
  6385. // This object just acts as a pass through for our delegate's
  6386. // window object. Since we interally generated events for both
  6387. // DISPID_ONLOAD
  6388. // DISPID_ONUNLOAD
  6389. // we just ignore those that are sourced by our delegate.
  6390. if (DISPID_ONLOAD == dispid ||
  6391. DISPID_ONUNLOAD == dispid )
  6392. {
  6393. hr = S_OK;
  6394. }
  6395. else
  6396. {
  6397. COmWindow* pwin = IToClass(COmWindow, _wesDelegate, this);
  6398. hr = pwin->_cpWindowEvents.InvokeDispid(dispid);
  6399. }
  6400. return hr;
  6401. }
  6402. HRESULT CIEFrameAuto::COmWindow::put_offscreenBuffering(VARIANT var)
  6403. {
  6404. IHTMLWindow2 *pWindow = 0;
  6405. HRESULT hr = _GetWindowDelegate(&pWindow);
  6406. if (SUCCEEDED(hr))
  6407. {
  6408. hr = pWindow->put_offscreenBuffering(var);
  6409. pWindow->Release();
  6410. }
  6411. return hr;
  6412. }
  6413. HRESULT CIEFrameAuto::COmWindow::get_offscreenBuffering(VARIANT *retval)
  6414. {
  6415. IHTMLWindow2 *pWindow = 0;
  6416. HRESULT hr = _GetWindowDelegate(&pWindow);
  6417. if (SUCCEEDED(hr))
  6418. {
  6419. hr = pWindow->get_offscreenBuffering(retval);
  6420. pWindow->Release();
  6421. }
  6422. return hr;
  6423. }
  6424. // *** IConnectionPointContainer ***
  6425. STDMETHODIMP CIEFrameAuto::COmWindow::FindConnectionPoint(REFIID iid, LPCONNECTIONPOINT *ppCP)
  6426. {
  6427. ASSERT(ppCP);
  6428. if (!ppCP)
  6429. return E_POINTER;
  6430. if (IsEqualIID(iid, DIID_HTMLWindowEvents) || IsEqualIID(iid, IID_IDispatch))
  6431. {
  6432. *ppCP = _cpWindowEvents.CastToIConnectionPoint();
  6433. }
  6434. else
  6435. {
  6436. *ppCP = NULL;
  6437. return E_NOINTERFACE;
  6438. }
  6439. (*ppCP)->AddRef();
  6440. return S_OK;
  6441. }
  6442. STDMETHODIMP CIEFrameAuto::COmWindow::EnumConnectionPoints(LPENUMCONNECTIONPOINTS * ppEnum)
  6443. {
  6444. return CreateInstance_IEnumConnectionPoints(ppEnum, 1,
  6445. _cpWindowEvents.CastToIConnectionPoint());
  6446. }
  6447. /******************************************************************************
  6448. Location Object
  6449. // bradsch 11/12/96
  6450. // The entire COmLocation object was copied from MSHTML and is a slimy pig
  6451. // dog. It should be replaced with the new URL cracking stuff in SHLWAPI.
  6452. ******************************************************************************/
  6453. CIEFrameAuto::COmLocation::COmLocation() :
  6454. CAutomationStub(MIN_BROWSER_DISPID, MAX_BROWSER_DISPID, TRUE)
  6455. {
  6456. ASSERT(!m_bstrFullUrl);
  6457. ASSERT(!m_bstrPort);
  6458. ASSERT(!m_bstrProtocol);
  6459. ASSERT(!m_bstrHostName);
  6460. ASSERT(!m_bstrPath);
  6461. ASSERT(!m_bstrSearch);
  6462. ASSERT(!m_bstrHash);
  6463. ASSERT(FALSE == m_fdontputinhistory);
  6464. ASSERT(FALSE == m_fRetryingNavigate);
  6465. }
  6466. HRESULT CIEFrameAuto::COmLocation::Init()
  6467. {
  6468. CIEFrameAuto* pauto = IToClass(CIEFrameAuto, _omloc, this);
  6469. return CAutomationStub::Init(SAFECAST(this, IHTMLLocation*), IID_IHTMLLocation, CLSID_HTMLLocation, pauto);
  6470. }
  6471. HRESULT CIEFrameAuto::COmLocation::CheckUrl()
  6472. {
  6473. BSTR currentUrl = 0;
  6474. HRESULT hr;
  6475. VARIANT varUrl;
  6476. VariantInit(&varUrl);
  6477. hr = _pAuto->_QueryPendingUrl(&varUrl);
  6478. if (FAILED(hr) || varUrl.vt != VT_BSTR || varUrl.bstrVal == NULL)
  6479. {
  6480. VariantClearLazy(&varUrl);
  6481. hr = _pAuto->get_LocationURL(&currentUrl);
  6482. }
  6483. else
  6484. {
  6485. // No VariantClear, we're extracting the bstrVal
  6486. currentUrl = varUrl.bstrVal;
  6487. }
  6488. if (SUCCEEDED(hr))
  6489. {
  6490. // If our stashed URL does not match the real current URL we need to reparse everything
  6491. if (!m_bstrFullUrl || StrCmpW(m_bstrFullUrl, currentUrl))
  6492. {
  6493. // This code is all going to change, so I am not worried about efficiency
  6494. FreeStuff();
  6495. m_bstrFullUrl = currentUrl;
  6496. hr = ParseUrl();
  6497. }
  6498. else
  6499. SysFreeString(currentUrl);
  6500. }
  6501. return hr;
  6502. }
  6503. HRESULT CIEFrameAuto::COmLocation::_InternalQueryInterface(REFIID riid, void ** const ppv)
  6504. {
  6505. ASSERT(!IsEqualIID(riid, IID_IUnknown));
  6506. if (IsEqualIID(riid, IID_IHTMLLocation))
  6507. *ppv = SAFECAST(this, IHTMLLocation *);
  6508. else if (IsEqualIID(riid, IID_IServiceProvider))
  6509. *ppv = SAFECAST(this, IObjectIdentity *);
  6510. else if (IsEqualIID(riid, IID_IObjectIdentity))
  6511. *ppv = SAFECAST(this, IServiceProvider *);
  6512. else
  6513. return E_NOINTERFACE;
  6514. AddRef();
  6515. return S_OK;
  6516. }
  6517. HRESULT CIEFrameAuto::COmLocation::_GetIDispatchExDelegate(IDispatchEx ** const delegate)
  6518. {
  6519. if (!delegate)
  6520. return E_POINTER;
  6521. IDispatch *pRootDisp = 0;
  6522. HRESULT hr = GetRootDelegate(_pAuto, &pRootDisp);
  6523. if (SUCCEEDED(hr))
  6524. {
  6525. IDispatch *pDelegateDisp = 0;
  6526. hr = GetDelegateOnIDispatch(pRootDisp, DISPID_LOCATIONOBJECT, &pDelegateDisp);
  6527. pRootDisp->Release();
  6528. if (SUCCEEDED(hr))
  6529. {
  6530. hr = pDelegateDisp->QueryInterface(IID_IDispatchEx, (void**)delegate);
  6531. pDelegateDisp->Release();
  6532. }
  6533. }
  6534. return hr;
  6535. }
  6536. /****************************************************************************
  6537. IObjectIdentity member implemtnation. this is necessary since mshtml has a locatino
  6538. proxy that it returns, whichc is a different pUnk than the location object returned by
  6539. shdocvw. The script engines use this interface to resolve the difference and allow
  6540. equality test to be perfomed on these objects.
  6541. ******************************************************************************/
  6542. STDMETHODIMP CIEFrameAuto::COmLocation::IsEqualObject(IUnknown * pUnk)
  6543. {
  6544. HRESULT hr;
  6545. IServiceProvider * pISP = NULL;
  6546. IHTMLLocation * pLoc = NULL;
  6547. IUnknown * pUnkThis = NULL;
  6548. IUnknown * pUnkTarget = NULL;
  6549. if (!pUnk)
  6550. return E_POINTER;
  6551. hr = pUnk->QueryInterface(IID_IServiceProvider, (void**)&pISP);
  6552. if (!SUCCEEDED(hr))
  6553. goto Cleanup;
  6554. hr = pISP->QueryService(IID_IHTMLLocation, IID_IHTMLLocation, (void**)&pLoc);
  6555. if (!SUCCEEDED(hr))
  6556. goto Cleanup;
  6557. hr = pLoc->QueryInterface(IID_IUnknown, (void**)&pUnkTarget);
  6558. if (!SUCCEEDED(hr))
  6559. goto Cleanup;
  6560. hr = QueryInterface(IID_IUnknown, (void**)&pUnkThis);
  6561. if (!SUCCEEDED(hr))
  6562. goto Cleanup;
  6563. hr = (pUnkThis == pUnkTarget) ? S_OK : S_FALSE;
  6564. Cleanup:
  6565. if (pISP) ATOMICRELEASE(pISP);
  6566. if (pLoc) ATOMICRELEASE(pLoc);
  6567. if (pUnkTarget) ATOMICRELEASE(pUnkTarget);
  6568. if (pUnkThis) ATOMICRELEASE(pUnkThis);
  6569. return hr;
  6570. }
  6571. /*****************************************************************************
  6572. IServiceProvider - this is currently only used by the impl of ISEqual object
  6573. on mshtml side,. adn only needs to return *this* when Queryied for location
  6574. service
  6575. ******************************************************************************/
  6576. STDMETHODIMP CIEFrameAuto::COmLocation::QueryService(REFGUID guidService, REFIID iid, void ** ppv)
  6577. {
  6578. HRESULT hr = E_NOINTERFACE;
  6579. if (!ppv)
  6580. return E_POINTER;
  6581. *ppv = NULL;
  6582. if (IsEqualGUID(guidService, IID_IHTMLLocation))
  6583. {
  6584. *ppv = SAFECAST(this, IHTMLLocation *);
  6585. hr = S_OK;
  6586. }
  6587. return hr;
  6588. }
  6589. /******************************************************************************
  6590. Helper function for the property access functions
  6591. Makes sure that the URL has been parsed and returns a copy
  6592. of the requested field as a BSTR.
  6593. ******************************************************************************/
  6594. HRESULT CIEFrameAuto::COmLocation::GetField(BSTR* bstrField, BSTR* pbstr)
  6595. {
  6596. HRESULT hr;
  6597. if (!pbstr)
  6598. return E_INVALIDARG;
  6599. if (!bstrField)
  6600. return E_FAIL;
  6601. hr = CheckUrl();
  6602. if (FAILED(hr))
  6603. return hr;
  6604. *pbstr = *bstrField ? SysAllocString(*bstrField): SysAllocString(L"");
  6605. return (*pbstr) ? S_OK : E_OUTOFMEMORY;
  6606. }
  6607. STDMETHODIMP CIEFrameAuto::COmLocation::toString (BSTR* pbstr)
  6608. {
  6609. return GetField(&m_bstrFullUrl, pbstr);
  6610. }
  6611. STDMETHODIMP CIEFrameAuto::COmLocation::get_href(BSTR* pbstr)
  6612. {
  6613. return GetField(&m_bstrFullUrl, pbstr);
  6614. }
  6615. STDMETHODIMP CIEFrameAuto::COmLocation::get_protocol(BSTR* pbstr)
  6616. {
  6617. return GetField(&m_bstrProtocol, pbstr);
  6618. }
  6619. STDMETHODIMP CIEFrameAuto::COmLocation::get_hostname(BSTR* pbstr)
  6620. {
  6621. return GetField(&m_bstrHostName, pbstr);
  6622. }
  6623. STDMETHODIMP CIEFrameAuto::COmLocation::get_host(BSTR* pbstr)
  6624. {
  6625. HRESULT hr;
  6626. INT cch;
  6627. BOOL fHavePort;
  6628. hr = CheckUrl();
  6629. if (FAILED(hr))
  6630. return hr;
  6631. if (!m_bstrHostName)
  6632. return E_POINTER;
  6633. cch = lstrlenW(m_bstrHostName);
  6634. fHavePort = m_bstrPort && *m_bstrPort;
  6635. if (fHavePort)
  6636. cch += lstrlenW(m_bstrPort) + 1; // for the ":"
  6637. *pbstr = SafeSysAllocStringLen(0, cch); // allocates cch + 1
  6638. if (!*pbstr)
  6639. return E_OUTOFMEMORY;
  6640. // Get the hostname
  6641. StrCpyNW(*pbstr, m_bstrHostName, cch + 1);
  6642. // add additional character for colon
  6643. // concatenate ":" and the port number, if there is a port number
  6644. if (fHavePort)
  6645. {
  6646. StrCatBuffW(*pbstr, L":", cch + 1);
  6647. StrCatBuffW(*pbstr, m_bstrPort, cch + 1);
  6648. }
  6649. return S_OK;
  6650. }
  6651. STDMETHODIMP CIEFrameAuto::COmLocation::get_pathname(BSTR* pbstr)
  6652. {
  6653. // Hack for Netscape compatability -- not in Nav3 or nav4.maybe in nav2?
  6654. // Netscape returned nothing for a path of "/"
  6655. // we used to do this but it looks like we should follow nav3/4 now (for OMCOMPAT)
  6656. return GetField(&m_bstrPath, pbstr);
  6657. }
  6658. STDMETHODIMP CIEFrameAuto::COmLocation::get_search(BSTR* pbstr)
  6659. {
  6660. return GetField(&m_bstrSearch, pbstr);
  6661. }
  6662. STDMETHODIMP CIEFrameAuto::COmLocation::get_hash(BSTR* pbstr)
  6663. {
  6664. return GetField(&m_bstrHash, pbstr);
  6665. }
  6666. STDMETHODIMP CIEFrameAuto::COmLocation::get_port(BSTR* pbstr)
  6667. {
  6668. return GetField(&m_bstrPort, pbstr);
  6669. }
  6670. STDMETHODIMP CIEFrameAuto::COmLocation::reload(VARIANT_BOOL fFlag)
  6671. {
  6672. VARIANT v = {0};
  6673. v.vt = VT_I4;
  6674. v.lVal = fFlag ?
  6675. OLECMDIDF_REFRESH_COMPLETELY|OLECMDIDF_REFRESH_CLEARUSERINPUT :
  6676. OLECMDIDF_REFRESH_NO_CACHE|OLECMDIDF_REFRESH_CLEARUSERINPUT;
  6677. return _pAuto->Refresh2(&v);
  6678. }
  6679. STDMETHODIMP CIEFrameAuto::COmLocation::replace(BSTR url)
  6680. {
  6681. m_fdontputinhistory = TRUE;
  6682. return put_href(url);
  6683. }
  6684. STDMETHODIMP CIEFrameAuto::COmLocation::assign(BSTR url)
  6685. {
  6686. return put_href(url);
  6687. }
  6688. void CIEFrameAuto::COmLocation::RetryNavigate()
  6689. {
  6690. //
  6691. // If a page does a navigate on an unload event and the unload is happening
  6692. // because the user shutdown the browser we would recurse to death.
  6693. // m_fRetryingNavigate was added to fix this scenario.
  6694. //
  6695. if (m_fPendingNavigate && !m_fRetryingNavigate)
  6696. {
  6697. m_fRetryingNavigate = TRUE;
  6698. DoNavigate();
  6699. m_fRetryingNavigate = FALSE;
  6700. }
  6701. }
  6702. //
  6703. //
  6704. // PrvHTParse - wrapper for Internet{Canonicalize/Combine}Url
  6705. // which does a local allocation of our returned string so we can
  6706. // free it as needed.
  6707. //
  6708. //
  6709. // We start by calling InternetCanonicalizeUrl() to perform any required
  6710. // canonicalization. If the caller specificed PARSE_ALL, we're done at that
  6711. // point and return the URL. This is the most common case.
  6712. //
  6713. // If the caller wanted parts of the URL, we will then call
  6714. // InternetCrackUrl() to break the URL into it's components, and
  6715. // finally InternetCreateUrl() to give us a string with just those
  6716. // components.
  6717. //
  6718. // ICU() has a bug which forces it to always prepend a scheme, so we have
  6719. // some final code at the end which removes the scheme if the caller
  6720. // specifically did not want one.
  6721. //
  6722. #define STARTING_URL_SIZE 127 // 128 minus 1
  6723. #define PARSE_ACCESS 16
  6724. #define PARSE_HOST 8
  6725. #define PARSE_PATH 4
  6726. #define PARSE_ANCHOR 2
  6727. #define PARSE_PUNCTUATION 1
  6728. #define PARSE_ALL 31
  6729. BSTR PrvHTParse(BSTR bstraName, BSTR bstrBaseName, int wanted)
  6730. {
  6731. DWORD cchP = STARTING_URL_SIZE+1;
  6732. DWORD cchNeed = cchP;
  6733. BOOL rc;
  6734. HRESULT hr;
  6735. if ((!bstraName && !bstrBaseName))
  6736. return NULL;
  6737. WCHAR *p = new WCHAR[cchP];
  6738. if (!p)
  6739. return NULL;
  6740. // ICU() does not accept NULL pointers, but it does handle "" strings
  6741. if (!bstrBaseName)
  6742. bstrBaseName = L"";
  6743. if (!bstraName)
  6744. bstraName = L"";
  6745. URL_COMPONENTSW uc = {0};
  6746. uc.dwStructSize = sizeof(uc);
  6747. // We will retry once if the failure was due to an insufficiently large buffer
  6748. hr = UrlCombineW(bstrBaseName, bstraName, p, &cchNeed, 0);
  6749. if (hr == E_POINTER)
  6750. {
  6751. // From the code, cchNeed has the same value as if UrlCombine had succeeded,
  6752. // which is the length of the combined URL, excluding the null.
  6753. cchP = ++cchNeed;
  6754. delete [] p;
  6755. p = new WCHAR[cchP];
  6756. if (!p)
  6757. goto free_and_exit;
  6758. hr = UrlCombineW(bstrBaseName, bstraName, p, &cchNeed, 0);
  6759. }
  6760. if (SUCCEEDED(hr) && wanted != PARSE_ALL)
  6761. {
  6762. // Since CreateUrl() will ignore our request to not add a scheme,
  6763. // we always ask it to crack one, so we can know the size if we need
  6764. // to remove it ourselves
  6765. uc.dwSchemeLength = INTERNET_MAX_SCHEME_LENGTH;
  6766. uc.lpszScheme = new WCHAR[uc.dwSchemeLength];
  6767. if (wanted & PARSE_HOST) {
  6768. uc.dwHostNameLength = INTERNET_MAX_HOST_NAME_LENGTH;
  6769. uc.lpszHostName = new WCHAR[uc.dwHostNameLength];
  6770. }
  6771. if (wanted & PARSE_PATH) {
  6772. uc.dwUrlPathLength = INTERNET_MAX_URL_LENGTH;
  6773. uc.lpszUrlPath = new WCHAR[uc.dwUrlPathLength];
  6774. }
  6775. if (wanted & PARSE_ANCHOR) {
  6776. uc.dwExtraInfoLength = INTERNET_MAX_URL_LENGTH;
  6777. uc.lpszExtraInfo = new WCHAR[uc.dwExtraInfoLength];
  6778. }
  6779. // if any of our allocations fail, fail the whole operation.
  6780. if ((!uc.lpszScheme) ||
  6781. ((wanted & PARSE_HOST) && (!uc.lpszHostName)) ||
  6782. ((wanted & PARSE_PATH) && (!uc.lpszUrlPath)) ||
  6783. ((wanted & PARSE_ANCHOR) && (!uc.lpszExtraInfo)))
  6784. goto free_and_exit;
  6785. rc = InternetCrackUrlW(p, cchNeed, 0, &uc);
  6786. // If we are failing here, we need to figure out why and fix it
  6787. if (!rc)
  6788. {
  6789. //TraceMsg(TF_WARNING, TEXT("PrvHTParse: InternetCrackUrl failed for \"\""), Dbg_SafeStr(p));
  6790. goto free_and_exit; // Couldn't crack it, so give back what we can
  6791. }
  6792. // InternetCreateUrlW takes in a count of WCHARs but if it
  6793. // fails, the same variable is set to a count of bytes. So we'll
  6794. // call this variable the ambiguous dwLength. Yuck.
  6795. cchNeed = cchP;
  6796. DWORD dwLength = cchNeed;
  6797. rc = InternetCreateUrlW(&uc, 0, p, &dwLength);
  6798. if (!rc)
  6799. {
  6800. delete [] p;
  6801. p = NULL;
  6802. const DWORD err = GetLastError();
  6803. if ((ERROR_INSUFFICIENT_BUFFER == err) && (dwLength > 0))
  6804. {
  6805. // dwLength comes out in bytes. We'll turn it into a char count
  6806. // The previous ANSI version allocated one char too many
  6807. // but it's too risky to correct that now
  6808. dwLength /= sizeof(WCHAR);
  6809. cchP = ++dwLength;
  6810. p = new WCHAR[cchP];
  6811. if (!p)
  6812. goto free_and_exit;
  6813. rc = InternetCreateUrlW(&uc, 0, p, &dwLength);
  6814. }
  6815. } // if !rc
  6816. if (rc)
  6817. {
  6818. // The most recent InternetCreateUrl was successful, so dwLength contains
  6819. // the number of wide chars stored in p.
  6820. cchNeed = dwLength;
  6821. // Special case: remove protocol if not requested. ICU() adds
  6822. // a protocol even if you tell it not to.
  6823. if (!(wanted & PARSE_ACCESS))
  6824. {
  6825. WCHAR *q;
  6826. // Make sure our string is sufficiently large for
  6827. ASSERT(cchNeed > uc.dwSchemeLength);
  6828. // For non-pluggable protocols, Add 3 for the ://, which is not counted in the scheme length, else add 1
  6829. int cch = lstrlenW(p + uc.dwSchemeLength + ((uc.nScheme == INTERNET_SCHEME_UNKNOWN) ? 1 : 3)) + 1;
  6830. q = new WCHAR[cch];
  6831. if (q)
  6832. {
  6833. StrCpyNW(q, (p + uc.dwSchemeLength + ((uc.nScheme == INTERNET_SCHEME_UNKNOWN) ? 1 : 3)), cch);
  6834. delete [] p;
  6835. p = q;
  6836. }
  6837. }
  6838. else
  6839. {
  6840. if ((wanted & (~PARSE_PUNCTUATION)) == PARSE_ACCESS)
  6841. {
  6842. // Special case #2: When only PARSE_ACCESS is requested,
  6843. // don't return the // suffix
  6844. p[uc.dwSchemeLength + 1] = '\0';
  6845. }
  6846. }
  6847. }
  6848. } // if wanted
  6849. free_and_exit:
  6850. delete [] uc.lpszScheme;
  6851. delete [] uc.lpszHostName;
  6852. delete [] uc.lpszUrlPath;
  6853. delete [] uc.lpszExtraInfo;
  6854. BSTR bstrp = 0;
  6855. if (p)
  6856. {
  6857. bstrp = SysAllocString(p);
  6858. delete [] p;
  6859. }
  6860. return bstrp;
  6861. }
  6862. STDMETHODIMP CIEFrameAuto::COmLocation::put_href(BSTR url)
  6863. {
  6864. HRESULT hr;
  6865. if (!url)
  6866. return E_INVALIDARG;
  6867. // Call CheckUrl before PrvHTParse to ensure we have a valid URL
  6868. hr = CheckUrl();
  6869. if (FAILED(hr))
  6870. return hr;
  6871. BSTR bstrUrlAbsolute = PrvHTParse(url, m_bstrFullUrl, PARSE_ALL);
  6872. if (!bstrUrlAbsolute )
  6873. return E_OUTOFMEMORY;
  6874. // Actually set the URL field
  6875. hr = SetField(&m_bstrFullUrl, bstrUrlAbsolute, FALSE);
  6876. SysFreeString(bstrUrlAbsolute);
  6877. return hr;
  6878. }
  6879. STDMETHODIMP CIEFrameAuto::COmLocation::put_protocol(BSTR bstr)
  6880. {
  6881. return SetField(&m_bstrProtocol, bstr, TRUE);
  6882. }
  6883. STDMETHODIMP CIEFrameAuto::COmLocation::put_hostname(BSTR bstr)
  6884. {
  6885. return SetField(&m_bstrHostName, bstr, TRUE);
  6886. }
  6887. STDMETHODIMP CIEFrameAuto::COmLocation::put_host(BSTR bstr)
  6888. {
  6889. HRESULT hr = S_OK;
  6890. WCHAR* colonPos = 0;
  6891. WCHAR* portName = NULL;
  6892. WCHAR* hostName = NULL;
  6893. hr = CheckUrl();
  6894. if (FAILED(hr))
  6895. return hr;
  6896. // Parse out the hostname and port and store them in
  6897. // the appropriate fields
  6898. colonPos = StrChrW(bstr, L':');
  6899. // Copy the characters up to the colon in the
  6900. // hostname field
  6901. if (colonPos == 0)
  6902. {
  6903. hostName = SysAllocString(bstr);
  6904. portName = SysAllocString(L"");
  6905. }
  6906. else
  6907. {
  6908. hostName = SafeSysAllocStringLen(bstr, (unsigned int)(colonPos-bstr));
  6909. portName = SafeSysAllocStringLen(colonPos+1, SysStringLen(bstr) - (unsigned int)(colonPos-bstr+1));
  6910. }
  6911. if (hostName && portName)
  6912. {
  6913. if (m_bstrHostName)
  6914. SysFreeString(m_bstrHostName);
  6915. if (m_bstrPort)
  6916. SysFreeString(m_bstrPort);
  6917. m_bstrHostName = hostName;
  6918. m_bstrPort = portName;
  6919. hostName = portName = 0;
  6920. hr = ComposeUrl();
  6921. if (SUCCEEDED(hr))
  6922. {
  6923. hr = DoNavigate();
  6924. }
  6925. }
  6926. else
  6927. hr = E_OUTOFMEMORY;
  6928. if (hostName)
  6929. SysFreeString(hostName);
  6930. if (portName)
  6931. SysFreeString(portName);
  6932. return hr;
  6933. }
  6934. STDMETHODIMP CIEFrameAuto::COmLocation::put_pathname(BSTR bstr)
  6935. {
  6936. return SetField(&m_bstrPath, bstr, TRUE);
  6937. }
  6938. STDMETHODIMP CIEFrameAuto::COmLocation::put_search(BSTR bstr)
  6939. {
  6940. if (!bstr)
  6941. return E_POINTER;
  6942. // If the provided search string begins with a "?" already,
  6943. // just use it "as is"
  6944. if (bstr[0] == L'?')
  6945. {
  6946. return SetField(&m_bstrSearch, bstr, TRUE);
  6947. }
  6948. // Otherwise prepend a question mark
  6949. else
  6950. {
  6951. // Allocate enough space for the string plus one more character ('#')
  6952. UINT cchSearch = lstrlenW(bstr) + 1;
  6953. BSTR bstrSearch = SafeSysAllocStringLen(L"?", cchSearch); // allocates cch + 1
  6954. if (!bstrSearch)
  6955. return E_OUTOFMEMORY;
  6956. StrCatBuffW(bstrSearch, bstr, cchSearch + 1);
  6957. HRESULT hr = SetField(&m_bstrSearch, bstrSearch, TRUE);
  6958. SysFreeString(bstrSearch);
  6959. return hr;
  6960. }
  6961. }
  6962. STDMETHODIMP CIEFrameAuto::COmLocation::put_hash(BSTR bstr)
  6963. {
  6964. if (!bstr)
  6965. return E_POINTER;
  6966. // If the provided hash string begins with a "#" already,
  6967. // just use it "as is"
  6968. if (bstr[0] == L'#')
  6969. {
  6970. return SetField(&m_bstrHash, bstr, TRUE);
  6971. }
  6972. // Otherwise prepend a pound sign
  6973. else
  6974. {
  6975. // Allocate enough space for the string plus one more character ('#')
  6976. UINT cchHash = lstrlenW(bstr) + 1;
  6977. BSTR bstrHash = SafeSysAllocStringLen(L"#", cchHash); // allocates cchHash + 1
  6978. if (!bstrHash)
  6979. return E_OUTOFMEMORY;
  6980. StrCatBuffW(bstrHash, bstr, cchHash + 1);
  6981. HRESULT hr = SetField(&m_bstrHash, bstrHash, TRUE);
  6982. SysFreeString(bstrHash);
  6983. return hr;
  6984. }
  6985. }
  6986. STDMETHODIMP CIEFrameAuto::COmLocation::put_port(BSTR bstr)
  6987. {
  6988. return SetField(&m_bstrPort, bstr, TRUE);
  6989. }
  6990. /******************************************************************************
  6991. // Helper function for the property setting functions
  6992. // Makes sure that the URL has been parsed
  6993. // Sets the field to its new value
  6994. // recomposes the URL, IF fRecomposeUrl is true
  6995. // If part of a window, tells the window to go to the new URL
  6996. //
  6997. // @todo JavaScript has some funky behavior on field setting--
  6998. // for example, the protocol field can be set to an entire URL.
  6999. // We need to make sure this functionality is duplicated
  7000. ******************************************************************************/
  7001. STDMETHODIMP CIEFrameAuto::COmLocation::SetField(BSTR* field, BSTR newval, BOOL fRecomposeUrl)
  7002. {
  7003. HRESULT hr = S_OK;
  7004. hr = CheckUrl();
  7005. if (FAILED(hr))
  7006. return hr;
  7007. // Copy the current URL!
  7008. BSTR bstrCurrentURL = SysAllocString(m_bstrFullUrl);
  7009. // Make a copy of the new value
  7010. BSTR valCopy = SysAllocString(newval);
  7011. if (!valCopy)
  7012. return E_OUTOFMEMORY;
  7013. // free the old value of field and set it to point to the new string
  7014. if (*field)
  7015. SysFreeString(*field);
  7016. *field = valCopy;
  7017. // Put together a new URL based on its constituents, if requested
  7018. if (fRecomposeUrl)
  7019. hr = ComposeUrl();
  7020. if (SUCCEEDED(hr))
  7021. {
  7022. if (bstrCurrentURL)
  7023. {
  7024. // If the new url is the same as the previous url then we want to navigate but not have it
  7025. // add to the history!
  7026. if (StrCmpW(bstrCurrentURL,m_bstrFullUrl) == 0)
  7027. {
  7028. m_fdontputinhistory = TRUE;
  7029. }
  7030. //
  7031. //clean up the old stuff before navigation
  7032. //
  7033. valCopy = SysAllocString(m_bstrFullUrl);
  7034. FreeStuff();
  7035. // valCopy can be NULL. does everybody else handle
  7036. // the NULL m_bstrFullUrl case?
  7037. m_bstrFullUrl = valCopy;
  7038. ParseUrl();
  7039. SysFreeString(bstrCurrentURL);
  7040. }
  7041. // Go to the new URL
  7042. hr = DoNavigate();
  7043. }
  7044. return hr;
  7045. }
  7046. /******************************************************************************
  7047. // Derive a new m_bstrUrl and m_bstrFullUrl from its constituents
  7048. ******************************************************************************/
  7049. STDMETHODIMP CIEFrameAuto::COmLocation::ComposeUrl()
  7050. {
  7051. HRESULT hr = S_OK;
  7052. ULONG len =
  7053. SysStringLen(m_bstrProtocol) +
  7054. 2 + // //
  7055. SysStringLen(m_bstrHostName) +
  7056. 1 + // trailing /
  7057. SysStringLen(m_bstrPort) +
  7058. 1 + // :
  7059. SysStringLen(m_bstrPath) +
  7060. 1 + // Possible leading /
  7061. (m_bstrSearch ? 1 : 0) + // ?
  7062. SysStringLen(m_bstrSearch) +
  7063. (m_bstrHash ? 1 : 0) + // #
  7064. SysStringLen(m_bstrHash) +
  7065. 10; // Trailing Termination + some slop
  7066. BSTR bstrUrl = SafeSysAllocStringLen(L"", len); // allocates len + 1
  7067. if (!bstrUrl)
  7068. return E_OUTOFMEMORY;
  7069. StrCatBuffW(bstrUrl, m_bstrProtocol, len + 1);
  7070. StrCatBuffW(bstrUrl, L"//", len + 1);
  7071. StrCatBuffW(bstrUrl, m_bstrHostName, len + 1);
  7072. if (lstrlenW(m_bstrPort))
  7073. {
  7074. StrCatBuffW(bstrUrl, L":", len + 1);
  7075. StrCatBuffW(bstrUrl, m_bstrPort, len + 1);
  7076. }
  7077. if (lstrlenW(m_bstrPath))
  7078. {
  7079. // prepend the leading slash if needed
  7080. if (m_bstrPath[0] != '/')
  7081. StrCatBuffW(bstrUrl, L"/", len + 1);
  7082. StrCatBuffW(bstrUrl, m_bstrPath, len + 1);
  7083. }
  7084. if (lstrlenW(m_bstrSearch) > 0)
  7085. {
  7086. StrCatBuffW(bstrUrl, m_bstrSearch, len + 1);
  7087. }
  7088. if (lstrlenW(m_bstrHash) > 0)
  7089. {
  7090. StrCatBuffW(bstrUrl, m_bstrHash, len + 1);
  7091. }
  7092. // OK, everything has succeeded
  7093. // Assign to member variables
  7094. if (m_bstrFullUrl)
  7095. SysFreeString(m_bstrFullUrl);
  7096. m_bstrFullUrl = bstrUrl;
  7097. return hr;
  7098. }
  7099. BSTR CIEFrameAuto::COmLocation::ComputeAbsoluteUrl(BSTR bstrUrlRelative)
  7100. {
  7101. if (FAILED(CheckUrl()))
  7102. return 0;
  7103. return PrvHTParse(bstrUrlRelative, m_bstrFullUrl, PARSE_ALL);
  7104. }
  7105. /******************************************************************************
  7106. // Tell the window to go to the current URL
  7107. ******************************************************************************/
  7108. STDMETHODIMP CIEFrameAuto::COmLocation::DoNavigate()
  7109. {
  7110. VARIANT v1;
  7111. v1.vt = VT_ERROR;
  7112. v1.scode = DISP_E_PARAMNOTFOUND;
  7113. if (m_fdontputinhistory)
  7114. {
  7115. v1.vt = VT_I4;
  7116. v1.lVal = navNoHistory;
  7117. // Reset the flag.
  7118. m_fdontputinhistory = FALSE;
  7119. }
  7120. HRESULT hres = _pAuto->Navigate(m_bstrFullUrl, &v1, PVAREMPTY, PVAREMPTY, PVAREMPTY);
  7121. if (hres == HRESULT_FROM_WIN32(ERROR_BUSY))
  7122. {
  7123. hres = S_OK;
  7124. m_fPendingNavigate = TRUE;
  7125. }
  7126. else
  7127. m_fPendingNavigate = FALSE;
  7128. return hres;
  7129. }
  7130. /******************************************************************************
  7131. // Parse a URL into its constituents and store them in member variables
  7132. ******************************************************************************/
  7133. STDMETHODIMP CIEFrameAuto::COmLocation::ParseUrl()
  7134. {
  7135. HRESULT hr = S_OK;
  7136. BSTR szProtocol = 0,
  7137. szHost = 0,
  7138. szPath = 0,
  7139. szSearch = 0,
  7140. szHash = 0,
  7141. searchPos = 0,
  7142. portPos = 0,
  7143. hashPos = 0;
  7144. m_bstrSearch = NULL;
  7145. // Strip out the search string and the hash string from the URL--
  7146. // the parser is too dumb to recognize them
  7147. searchPos = StrChrW(m_bstrFullUrl, L'?');
  7148. if (searchPos)
  7149. {
  7150. m_bstrSearch = SysAllocString(searchPos);
  7151. *searchPos = 0; // take it away again so it doesn't cause confusion
  7152. }
  7153. else
  7154. {
  7155. m_bstrSearch = SysAllocString(L"");
  7156. }
  7157. if (NULL == m_bstrSearch)
  7158. {
  7159. hr = E_OUTOFMEMORY;
  7160. goto exit;
  7161. }
  7162. // Get the anchor string, including the '#' prefix
  7163. hashPos = StrChrW(m_bstrFullUrl, L'#');
  7164. if (hashPos)
  7165. {
  7166. m_bstrHash = SysAllocString(hashPos);
  7167. *hashPos = 0; // take it away again so it doesn't cause confusion
  7168. }
  7169. else
  7170. {
  7171. m_bstrHash = SysAllocString(L"");
  7172. }
  7173. if (NULL == m_bstrHash)
  7174. {
  7175. hr = E_OUTOFMEMORY;
  7176. goto exit;
  7177. }
  7178. // Both m_bstrSearch and m_bstrHash can be NULL at this point
  7179. // does all the affected code handle this case?
  7180. // note there are more cases like this below (m_bstrProtocol for example)
  7181. // Parse the protocol
  7182. szProtocol = PrvHTParse(m_bstrFullUrl, 0, PARSE_ACCESS | PARSE_PUNCTUATION);
  7183. if (!szProtocol)
  7184. {
  7185. hr = E_OUTOFMEMORY;
  7186. goto exit;
  7187. }
  7188. m_bstrProtocol = SysAllocString(szProtocol);
  7189. if (NULL == m_bstrProtocol)
  7190. {
  7191. hr = E_OUTOFMEMORY;
  7192. goto exit;
  7193. }
  7194. // Parse the host name and port number (if any)
  7195. // First look for a port
  7196. szHost = PrvHTParse(m_bstrFullUrl, 0, PARSE_HOST);
  7197. if (!szHost)
  7198. {
  7199. hr = E_OUTOFMEMORY;
  7200. goto exit;
  7201. }
  7202. portPos = StrChrW(szHost, L':');
  7203. if (portPos)
  7204. {
  7205. m_bstrHostName = SafeSysAllocStringLen(szHost, (unsigned int)(portPos-szHost));
  7206. m_bstrPort = SysAllocString(portPos + 1);
  7207. }
  7208. else
  7209. {
  7210. m_bstrHostName = SysAllocString(szHost);
  7211. m_bstrPort = SysAllocString(L"");
  7212. }
  7213. if (NULL == m_bstrHostName || NULL == m_bstrPort)
  7214. {
  7215. hr = E_OUTOFMEMORY;
  7216. goto exit;
  7217. }
  7218. // Parse the path and search string (if any)
  7219. szPath = PrvHTParse(m_bstrFullUrl, 0, PARSE_PATH);
  7220. if (!szPath)
  7221. {
  7222. hr = E_OUTOFMEMORY;
  7223. goto exit;
  7224. }
  7225. // If the path doesn't start with a '/' then prepend one - Netscape compatibility
  7226. if (StrCmpIW(szProtocol, L"javascript:") && StrCmpIW(szProtocol, L"vbscript:") && szPath[0] != L'/')
  7227. {
  7228. WCHAR *szPath2 = szPath;
  7229. int cchPath = lstrlenW(szPath2)+2;
  7230. szPath = SafeSysAllocStringLen(0, cchPath); // allocates +1 char for the terminator
  7231. if (szPath)
  7232. {
  7233. szPath[0] = L'/';
  7234. szPath[1] = L'\0';
  7235. StrCatBuffW(szPath,szPath2, cchPath+1); //+1 added by alloc above
  7236. szPath[cchPath] = 0;
  7237. SysFreeString(szPath2);
  7238. }
  7239. else
  7240. szPath = szPath2;
  7241. }
  7242. m_bstrPath = SysAllocString(szPath);
  7243. if (NULL == m_bstrPath)
  7244. {
  7245. hr = E_OUTOFMEMORY;
  7246. goto exit;
  7247. }
  7248. exit:
  7249. // Restore hash and search characters
  7250. if (searchPos)
  7251. *searchPos = L'?';
  7252. if (hashPos)
  7253. *hashPos = L'#';
  7254. // Have to free these using SysFreeString because they come from PrvHTParse
  7255. if (szProtocol)
  7256. SysFreeString(szProtocol);
  7257. if (szHost)
  7258. SysFreeString(szHost);
  7259. if (szPath)
  7260. SysFreeString(szPath);
  7261. if (szHash)
  7262. SysFreeString(szHash);
  7263. return hr;
  7264. }
  7265. CIEFrameAuto::COmLocation::~COmLocation()
  7266. {
  7267. FreeStuff();
  7268. }
  7269. HRESULT CIEFrameAuto::COmLocation::FreeStuff()
  7270. {
  7271. if (m_bstrFullUrl)
  7272. {
  7273. SysFreeString(m_bstrFullUrl);
  7274. m_bstrFullUrl = 0;
  7275. }
  7276. if (m_bstrProtocol)
  7277. {
  7278. SysFreeString(m_bstrProtocol);
  7279. m_bstrProtocol = 0;
  7280. }
  7281. if (m_bstrHostName)
  7282. {
  7283. SysFreeString(m_bstrHostName);
  7284. m_bstrHostName = 0;
  7285. }
  7286. if (m_bstrPort)
  7287. {
  7288. SysFreeString(m_bstrPort);
  7289. m_bstrPort = 0;
  7290. }
  7291. if (m_bstrPath)
  7292. {
  7293. SysFreeString(m_bstrPath);
  7294. m_bstrPath = 0;
  7295. }
  7296. if (m_bstrSearch)
  7297. {
  7298. SysFreeString(m_bstrSearch);
  7299. m_bstrSearch = 0;
  7300. }
  7301. if (m_bstrHash)
  7302. {
  7303. SysFreeString(m_bstrHash);
  7304. m_bstrHash = 0;
  7305. }
  7306. return S_OK;
  7307. }
  7308. /******************************************************************************
  7309. Navigator Object
  7310. ******************************************************************************/
  7311. CIEFrameAuto::COmNavigator::COmNavigator() :
  7312. CAutomationStub(MIN_BROWSER_DISPID, MAX_BROWSER_DISPID, TRUE)
  7313. {
  7314. ASSERT(!_UserAgent);
  7315. ASSERT(FALSE == _fLoaded);
  7316. }
  7317. HRESULT CIEFrameAuto::COmNavigator::Init(CMimeTypes *pMimeTypes, CPlugins *pPlugins, COpsProfile *pProfile)
  7318. {
  7319. ASSERT(pMimeTypes != NULL);
  7320. _pMimeTypes = pMimeTypes;
  7321. ASSERT(pPlugins != NULL);
  7322. _pPlugins = pPlugins;
  7323. ASSERT(pProfile != NULL);
  7324. _pProfile = pProfile;
  7325. CIEFrameAuto* pauto = IToClass(CIEFrameAuto, _omnav, this);
  7326. return CAutomationStub::Init(SAFECAST(this, IOmNavigator*), IID_IOmNavigator, CLSID_HTMLNavigator, pauto);
  7327. }
  7328. /******************************************************************************
  7329. // bradsc 11/5/97
  7330. // This method should not use hard coded values. Where can we get this info?
  7331. // This method has to use non-unicode junk because of Win95
  7332. ******************************************************************************/
  7333. HRESULT CIEFrameAuto::COmNavigator::LoadUserAgent()
  7334. {
  7335. _fLoaded = TRUE;
  7336. CHAR szUserAgent[MAX_PATH]; // URLMON says the max length of the UA string is MAX_PATH
  7337. DWORD dwSize = MAX_PATH;
  7338. szUserAgent[0] = '\0';
  7339. if (ObtainUserAgentString(0, szUserAgent, &dwSize) == S_OK)
  7340. {
  7341. // Just figure out the real length since 'size' is ANSI bytes required.
  7342. //
  7343. _UserAgent = SysAllocStringFromANSI(szUserAgent);
  7344. }
  7345. return _UserAgent ? S_OK : E_FAIL;
  7346. }
  7347. HRESULT CIEFrameAuto::COmNavigator::_InternalQueryInterface(REFIID riid, void ** const ppv)
  7348. {
  7349. ASSERT(!IsEqualIID(riid, IID_IUnknown));
  7350. if (IsEqualIID(riid, IID_IOmNavigator))
  7351. *ppv = SAFECAST(this, IOmNavigator *);
  7352. else
  7353. return E_NOINTERFACE;
  7354. AddRef();
  7355. return S_OK;
  7356. }
  7357. STDMETHODIMP CIEFrameAuto::COmNavigator::Invoke(DISPID dispid, REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS *dispparams, VARIANT *pvarResult, EXCEPINFO *pexcepinfo, UINT *puArgErr)
  7358. {
  7359. HRESULT hr = CAutomationStub::Invoke(dispid,riid,lcid,wFlags,dispparams,pvarResult,pexcepinfo,puArgErr);
  7360. if (hr == DISP_E_MEMBERNOTFOUND
  7361. && (wFlags & DISPATCH_PROPERTYGET)
  7362. && dispid == DISPID_VALUE
  7363. && pvarResult != NULL && dispparams->cArgs == 0)
  7364. {
  7365. pvarResult->vt = VT_BSTR;
  7366. pvarResult->bstrVal = SysAllocString(L"[object Navigator]");
  7367. hr = pvarResult->bstrVal ? S_OK : E_OUTOFMEMORY;
  7368. }
  7369. return hr;
  7370. }
  7371. HRESULT CIEFrameAuto::COmNavigator::_GetIDispatchExDelegate(IDispatchEx ** const delegate)
  7372. {
  7373. if (!delegate)
  7374. return E_POINTER;
  7375. IDispatch *pRootDisp = 0;
  7376. HRESULT hr = GetRootDelegate(_pAuto, &pRootDisp);
  7377. if (SUCCEEDED(hr))
  7378. {
  7379. IDispatch *pDelegateDisp = 0;
  7380. hr = GetDelegateOnIDispatch(pRootDisp, DISPID_NAVIGATOROBJECT, &pDelegateDisp);
  7381. pRootDisp->Release();
  7382. if (SUCCEEDED(hr))
  7383. {
  7384. hr = pDelegateDisp->QueryInterface(IID_PPV_ARG(IDispatchEx, delegate));
  7385. pDelegateDisp->Release();
  7386. }
  7387. }
  7388. return hr;
  7389. }
  7390. // All of these have hard-coded lengths and locations
  7391. STDMETHODIMP CIEFrameAuto::COmNavigator::get_appCodeName(BSTR* retval)
  7392. {
  7393. HRESULT hr;
  7394. if (retval)
  7395. {
  7396. if (!_fLoaded)
  7397. LoadUserAgent();
  7398. if (_UserAgent)
  7399. {
  7400. *retval = SafeSysAllocStringLen(_UserAgent, 7);
  7401. hr = S_OK;
  7402. }
  7403. else
  7404. {
  7405. *retval = SysAllocString(APPCODENAME);
  7406. hr = *retval ? S_OK : E_OUTOFMEMORY;
  7407. }
  7408. }
  7409. else
  7410. {
  7411. hr = S_FALSE;
  7412. }
  7413. return hr;
  7414. }
  7415. /******************************************************************************
  7416. // bradsch 11/8/96
  7417. // We should read this out of the registry instead of hard coding!!
  7418. ******************************************************************************/
  7419. STDMETHODIMP CIEFrameAuto::COmNavigator::get_appName(BSTR* retval)
  7420. {
  7421. *retval = SysAllocString(MSIE);
  7422. return *retval ? S_OK : E_OUTOFMEMORY;
  7423. }
  7424. /******************************************************************************
  7425. // Netscape defined appVersion to be everything after
  7426. // the first 8 characters in the userAgent string.
  7427. ******************************************************************************/
  7428. STDMETHODIMP CIEFrameAuto::COmNavigator::get_appVersion(BSTR* retval)
  7429. {
  7430. if (retval)
  7431. {
  7432. if (!_fLoaded)
  7433. LoadUserAgent();
  7434. if (_UserAgent)
  7435. {
  7436. // If _UserAgent is less than 8 characters the registry is messed up.
  7437. // If _UserAgent is exactly 8 characters we will just return a NULL string.
  7438. if (lstrlenW(_UserAgent) < 8)
  7439. *retval = SysAllocString(L"");
  7440. else
  7441. *retval = SysAllocString(_UserAgent + 8);
  7442. return *retval ? S_OK : E_OUTOFMEMORY;
  7443. }
  7444. *retval = SysAllocString(APPVERSION);
  7445. return *retval ? S_OK : E_OUTOFMEMORY;
  7446. }
  7447. else
  7448. {
  7449. return S_FALSE;
  7450. }
  7451. }
  7452. STDMETHODIMP CIEFrameAuto::COmNavigator::get_userAgent(BSTR* retval)
  7453. {
  7454. if (retval)
  7455. {
  7456. if (!_fLoaded)
  7457. LoadUserAgent();
  7458. if (_UserAgent)
  7459. {
  7460. *retval = SysAllocString(_UserAgent);
  7461. }
  7462. else
  7463. {
  7464. *retval = SysAllocString(USERAGENT);
  7465. }
  7466. return *retval ? S_OK : E_OUTOFMEMORY;
  7467. }
  7468. else
  7469. {
  7470. return S_FALSE;
  7471. }
  7472. }
  7473. STDMETHODIMP CIEFrameAuto::COmNavigator::get_cookieEnabled(VARIANT_BOOL* enabled)
  7474. {
  7475. HRESULT hr = E_POINTER;
  7476. if (enabled)
  7477. {
  7478. BSTR strUrl;
  7479. *enabled = VARIANT_FALSE;
  7480. hr = _pAuto->_omloc.get_href(&strUrl);
  7481. if (SUCCEEDED(hr))
  7482. {
  7483. DWORD dwPolicy;
  7484. if (SUCCEEDED(ZoneCheckUrlExW(strUrl, &dwPolicy, sizeof(dwPolicy), NULL, NULL,
  7485. URLACTION_COOKIES_ENABLED, PUAF_NOUI, NULL)) &&
  7486. (URLPOLICY_DISALLOW != dwPolicy))
  7487. {
  7488. *enabled = VARIANT_TRUE;
  7489. }
  7490. SysFreeString(strUrl);
  7491. }
  7492. else
  7493. ASSERT(!strUrl); // If this failed and strUrl isn't NULL, then we are leaking.
  7494. }
  7495. return hr;
  7496. }
  7497. STDMETHODIMP CIEFrameAuto::COmNavigator::javaEnabled(VARIANT_BOOL* enabled)
  7498. {
  7499. HRESULT hr = E_POINTER;
  7500. if (enabled)
  7501. {
  7502. BSTR strUrl;
  7503. *enabled = VARIANT_FALSE;
  7504. hr = _pAuto->_omloc.get_href(&strUrl);
  7505. if (SUCCEEDED(hr))
  7506. {
  7507. DWORD dwPolicy;
  7508. if (SUCCEEDED(ZoneCheckUrlExW(strUrl, &dwPolicy, sizeof(dwPolicy), NULL, NULL,
  7509. URLACTION_JAVA_PERMISSIONS, PUAF_NOUI, NULL)) &&
  7510. (URLPOLICY_JAVA_PROHIBIT != dwPolicy))
  7511. {
  7512. *enabled = VARIANT_TRUE;
  7513. }
  7514. SysFreeString(strUrl);
  7515. }
  7516. else
  7517. ASSERT(!strUrl); // If this failed and strUrl isn't NULL, then we are leaking.
  7518. }
  7519. return hr;
  7520. }
  7521. STDMETHODIMP CIEFrameAuto::COmNavigator::taintEnabled (VARIANT_BOOL *pfEnabled)
  7522. {
  7523. if (pfEnabled)
  7524. {
  7525. *pfEnabled = VARIANT_FALSE;
  7526. }
  7527. else
  7528. return E_POINTER;
  7529. return S_OK;
  7530. }
  7531. STDMETHODIMP CIEFrameAuto::COmNavigator::get_mimeTypes (IHTMLMimeTypesCollection**ppMimeTypes)
  7532. {
  7533. if (ppMimeTypes)
  7534. {
  7535. *ppMimeTypes = _pMimeTypes;
  7536. _pMimeTypes->AddRef();
  7537. return S_OK;
  7538. }
  7539. else
  7540. return E_POINTER;
  7541. }
  7542. /******************************************************************************
  7543. // member: toString method
  7544. // Synopsis : we need to invoke on dispid_value, and coerce the result into
  7545. // a bstr.
  7546. //
  7547. ******************************************************************************/
  7548. STDMETHODIMP CIEFrameAuto::COmNavigator::toString(BSTR * pbstr)
  7549. {
  7550. HRESULT hr = E_POINTER;
  7551. if (pbstr)
  7552. {
  7553. *pbstr= SysAllocString(L"[object Navigator]");
  7554. if (!*pbstr)
  7555. hr = E_OUTOFMEMORY;
  7556. else
  7557. hr = S_OK;
  7558. }
  7559. return hr;
  7560. }
  7561. CIEFrameAuto::CCommonCollection::CCommonCollection() :
  7562. CAutomationStub(MIN_BROWSER_DISPID, MAX_BROWSER_DISPID, TRUE)
  7563. {
  7564. }
  7565. HRESULT CIEFrameAuto::CMimeTypes::Init()
  7566. {
  7567. CIEFrameAuto* pauto = IToClass(CIEFrameAuto, _mimeTypes, this);
  7568. return CAutomationStub::Init(SAFECAST(this, IHTMLMimeTypesCollection*), IID_IHTMLMimeTypesCollection,
  7569. CLSID_CMimeTypes, pauto);
  7570. }
  7571. HRESULT CIEFrameAuto::CCommonCollection::_GetIDispatchExDelegate(IDispatchEx ** const delegate)
  7572. {
  7573. if (!delegate)
  7574. return E_POINTER;
  7575. // We do not handle expandos yet
  7576. *delegate = NULL;
  7577. return DISP_E_MEMBERNOTFOUND;
  7578. }
  7579. HRESULT CIEFrameAuto::CMimeTypes::_InternalQueryInterface(REFIID riid, void ** const ppv)
  7580. {
  7581. if (IsEqualIID(riid, IID_IHTMLMimeTypesCollection))
  7582. *ppv = SAFECAST(this, IHTMLMimeTypesCollection *);
  7583. else
  7584. return E_NOINTERFACE;
  7585. AddRef();
  7586. return S_OK;
  7587. }
  7588. HRESULT CIEFrameAuto::CCommonCollection::GetDispID(BSTR bstrName, DWORD grfdex, DISPID *pid)
  7589. {
  7590. HRESULT hr;
  7591. hr = CAutomationStub::GetDispID(bstrName, grfdex, pid);
  7592. if (hr == DISP_E_MEMBERNOTFOUND)
  7593. {
  7594. // We ignore the command we do not understand
  7595. *pid = DISPID_UNKNOWN;
  7596. hr = S_OK;
  7597. }
  7598. return hr;
  7599. }
  7600. HRESULT CIEFrameAuto::CCommonCollection::InvokeEx(DISPID id, LCID lcid, WORD wFlags, DISPPARAMS *pdp, VARIANT *pvarRes, EXCEPINFO *pei, IServiceProvider *pspCaller)
  7601. {
  7602. if (id == DISPID_UNKNOWN && pvarRes)
  7603. {
  7604. V_VT(pvarRes) = VT_EMPTY;
  7605. return S_OK;
  7606. }
  7607. return CAutomationStub::InvokeEx(id, lcid, wFlags, pdp, pvarRes, pei, pspCaller);
  7608. }
  7609. HRESULT CIEFrameAuto::CCommonCollection::get_length(LONG* pLength)
  7610. {
  7611. if (pLength == NULL)
  7612. return E_POINTER;
  7613. *pLength = 0;
  7614. return S_OK;
  7615. }
  7616. HRESULT CIEFrameAuto::COmNavigator::get_plugins (IHTMLPluginsCollection **ppPlugins)
  7617. {
  7618. if (ppPlugins)
  7619. {
  7620. *ppPlugins = _pPlugins;
  7621. _pPlugins->AddRef();
  7622. return S_OK;
  7623. }
  7624. else
  7625. return E_POINTER;
  7626. }
  7627. HRESULT CIEFrameAuto::COmNavigator::get_opsProfile (IHTMLOpsProfile **ppOpsProfile)
  7628. {
  7629. if (ppOpsProfile)
  7630. {
  7631. *ppOpsProfile = _pProfile;
  7632. (*ppOpsProfile)->AddRef();
  7633. return S_OK;
  7634. }
  7635. else
  7636. return E_POINTER;
  7637. }
  7638. HRESULT CIEFrameAuto::COmNavigator::get_cpuClass(BSTR * p)
  7639. {
  7640. if (p)
  7641. {
  7642. SYSTEM_INFO SysInfo;
  7643. ::GetSystemInfo(&SysInfo);
  7644. switch(SysInfo.wProcessorArchitecture)
  7645. {
  7646. case PROCESSOR_ARCHITECTURE_INTEL:
  7647. *p = SysAllocString(L"x86");
  7648. break;
  7649. case PROCESSOR_ARCHITECTURE_AMD64:
  7650. *p = SysAllocString(L"AMD64");
  7651. break;
  7652. case PROCESSOR_ARCHITECTURE_IA64:
  7653. *p = SysAllocString(L"IA64");
  7654. break;
  7655. default:
  7656. *p = SysAllocString(L"Other");
  7657. break;
  7658. }
  7659. if (*p == NULL)
  7660. return E_OUTOFMEMORY;
  7661. else
  7662. return S_OK;
  7663. }
  7664. else
  7665. return E_POINTER;
  7666. }
  7667. #define MAX_VERSION_STRING 30
  7668. HRESULT CIEFrameAuto::COmNavigator::get_systemLanguage(BSTR * p)
  7669. {
  7670. HRESULT hr = E_POINTER;
  7671. if (p)
  7672. {
  7673. LCID lcid;
  7674. WCHAR strVer[MAX_VERSION_STRING];
  7675. *p = NULL;
  7676. lcid = ::GetSystemDefaultLCID();
  7677. hr = LcidToRfc1766W(lcid, strVer, MAX_VERSION_STRING);
  7678. if (!hr)
  7679. {
  7680. *p = SysAllocString(strVer);
  7681. if (!*p)
  7682. hr = E_OUTOFMEMORY;
  7683. }
  7684. }
  7685. return hr;
  7686. }
  7687. HRESULT CIEFrameAuto::COmNavigator::get_browserLanguage(BSTR * p)
  7688. {
  7689. LCID lcid =0;
  7690. LANGID lidUI;
  7691. WCHAR strVer[MAX_VERSION_STRING];
  7692. HRESULT hr;
  7693. if (!p)
  7694. {
  7695. return E_POINTER;
  7696. }
  7697. *p = NULL;
  7698. lidUI = MLGetUILanguage();
  7699. lcid = MAKELCID(lidUI, SORT_DEFAULT);
  7700. hr = LcidToRfc1766W(lcid, strVer, MAX_VERSION_STRING);
  7701. if (!hr)
  7702. {
  7703. *p = SysAllocString(strVer);
  7704. if (!*p)
  7705. return E_OUTOFMEMORY;
  7706. else
  7707. {
  7708. return S_OK;
  7709. }
  7710. }
  7711. return E_INVALIDARG;
  7712. }
  7713. HRESULT CIEFrameAuto::COmNavigator::get_userLanguage(BSTR * p)
  7714. {
  7715. HRESULT hr = E_POINTER;
  7716. if (p)
  7717. {
  7718. LCID lcid;
  7719. WCHAR strVer[MAX_VERSION_STRING];
  7720. *p = NULL;
  7721. lcid = ::GetUserDefaultLCID();
  7722. hr = LcidToRfc1766W(lcid, strVer, MAX_VERSION_STRING);
  7723. if (!hr)
  7724. {
  7725. *p = SysAllocString(strVer);
  7726. if (!*p)
  7727. hr = E_OUTOFMEMORY;
  7728. }
  7729. }
  7730. return hr;
  7731. }
  7732. HRESULT CIEFrameAuto::COmNavigator::get_platform(BSTR * p)
  7733. {
  7734. // Nav compatability item, returns the following in Nav:-
  7735. // Win32,Win16,Unix,Motorola,Max68k,MacPPC
  7736. // shdocvw is Win32 only, so
  7737. if (p)
  7738. {
  7739. *p = SysAllocString (L"Win32");
  7740. return *p ? S_OK : E_OUTOFMEMORY;
  7741. }
  7742. else
  7743. return E_POINTER;
  7744. }
  7745. HRESULT CIEFrameAuto::COmNavigator::get_appMinorVersion(BSTR * p)
  7746. {
  7747. HKEY hkInetSettings;
  7748. long lResult;
  7749. HRESULT hr = S_FALSE;
  7750. if (!p)
  7751. {
  7752. return E_POINTER;
  7753. }
  7754. *p = NULL;
  7755. lResult = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
  7756. TEXT("Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings"),
  7757. 0, KEY_QUERY_VALUE, &hkInetSettings);
  7758. if (ERROR_SUCCESS == lResult)
  7759. {
  7760. DWORD dwType;
  7761. TCHAR buffer[MAX_URL_STRING];
  7762. DWORD size = sizeof(buffer);
  7763. // If this is bigger than MAX_URL_STRING the registry is probably hosed.
  7764. lResult = RegQueryValueEx(hkInetSettings, TEXT("MinorVersion"), 0, &dwType, (BYTE*)buffer, &size);
  7765. RegCloseKey(hkInetSettings);
  7766. if (ERROR_SUCCESS == lResult && dwType == REG_SZ)
  7767. {
  7768. // Just figure out the real length since 'size' is ANSI bytes required.
  7769. *p = SysAllocString(buffer);
  7770. hr = *p ? S_OK : E_OUTOFMEMORY;
  7771. }
  7772. }
  7773. if (S_OK != hr)
  7774. {
  7775. *p = SysAllocString (L"0");
  7776. hr = *p ? S_OK : E_OUTOFMEMORY;
  7777. }
  7778. return hr;
  7779. }
  7780. HRESULT CIEFrameAuto::COmNavigator::get_connectionSpeed(long * p)
  7781. {
  7782. if (p)
  7783. {
  7784. *p = NULL;
  7785. return E_NOTIMPL;
  7786. }
  7787. else
  7788. return E_POINTER;
  7789. }
  7790. HRESULT CIEFrameAuto::COmNavigator::get_onLine(VARIANT_BOOL * p)
  7791. {
  7792. if (p)
  7793. {
  7794. *p = TO_VARIANT_BOOL(!IsGlobalOffline());
  7795. return S_OK;
  7796. }
  7797. else
  7798. return E_POINTER;
  7799. }
  7800. HRESULT CIEFrameAuto::CPlugins::Init()
  7801. {
  7802. CIEFrameAuto* pauto = IToClass(CIEFrameAuto, _plugins, this);
  7803. return CAutomationStub::Init(SAFECAST(this, IHTMLPluginsCollection*), IID_IHTMLPluginsCollection,
  7804. CLSID_CPlugins, pauto);
  7805. }
  7806. HRESULT CIEFrameAuto::CPlugins::_InternalQueryInterface(REFIID riid, void ** const ppv)
  7807. {
  7808. if (IsEqualIID(riid, IID_IHTMLPluginsCollection))
  7809. *ppv = SAFECAST(this, IHTMLPluginsCollection *);
  7810. else
  7811. return E_NOINTERFACE;
  7812. AddRef();
  7813. return S_OK;
  7814. }
  7815. /******************************************************************************
  7816. Window Open Support
  7817. ******************************************************************************/
  7818. CIEFrameAuto::COmHistory::COmHistory() :
  7819. CAutomationStub(MIN_BROWSER_DISPID, MAX_BROWSER_DISPID, TRUE)
  7820. {
  7821. }
  7822. HRESULT CIEFrameAuto::COmHistory::Init()
  7823. {
  7824. CIEFrameAuto* pauto = IToClass(CIEFrameAuto, _omhist, this);
  7825. return CAutomationStub::Init(SAFECAST(this, IOmHistory*), IID_IOmHistory, CLSID_HTMLHistory, pauto);
  7826. }
  7827. HRESULT CIEFrameAuto::COmHistory::_InternalQueryInterface(REFIID riid, void ** const ppv)
  7828. {
  7829. ASSERT(!IsEqualIID(riid, IID_IUnknown));
  7830. if (IsEqualIID(riid, IID_IOmHistory))
  7831. *ppv = SAFECAST(this, IOmHistory *);
  7832. else
  7833. return E_NOINTERFACE;
  7834. AddRef();
  7835. return S_OK;
  7836. }
  7837. HRESULT CIEFrameAuto::COmHistory::_GetIDispatchExDelegate(IDispatchEx ** const delegate)
  7838. {
  7839. if (!delegate)
  7840. return E_POINTER;
  7841. IDispatch *pRootDisp = 0;
  7842. HRESULT hr = GetRootDelegate(_pAuto, &pRootDisp);
  7843. if (SUCCEEDED(hr))
  7844. {
  7845. IDispatch *pDelegateDisp = 0;
  7846. hr = GetDelegateOnIDispatch(pRootDisp, DISPID_HISTORYOBJECT, &pDelegateDisp);
  7847. pRootDisp->Release();
  7848. if (SUCCEEDED(hr))
  7849. {
  7850. hr = pDelegateDisp->QueryInterface(IID_IDispatchEx, (void**)delegate);
  7851. pDelegateDisp->Release();
  7852. }
  7853. }
  7854. return hr;
  7855. }
  7856. /******************************************************************************
  7857. // I just tested Nav3 and they simply ignore parameters to back() and forward. They
  7858. // do, however, honor the value passed to go(). Hey... Netscape actually followed
  7859. // their documented behavior for once!
  7860. ******************************************************************************/
  7861. STDMETHODIMP CIEFrameAuto::COmHistory::back(VARIANT*)
  7862. {
  7863. //
  7864. // Netscape ignores all errors from these navigation functions
  7865. //
  7866. _pAuto->GoBack();
  7867. return S_OK;
  7868. }
  7869. STDMETHODIMP CIEFrameAuto::COmHistory::forward(VARIANT*)
  7870. {
  7871. //
  7872. // Netscape ignores all errors from these navigation functions
  7873. //
  7874. _pAuto->GoForward();
  7875. return S_OK;
  7876. }
  7877. /******************************************************************************
  7878. Get History Length from TravelLog
  7879. ******************************************************************************/
  7880. STDMETHODIMP CIEFrameAuto::COmHistory::get_length(short* retval)
  7881. {
  7882. // Make sure we have an IBrowserService pointer
  7883. if (_pAuto->_pbs==NULL)
  7884. {
  7885. TraceMsg(DM_WARNING, "CIEA::history.go called _pbs==NULL");
  7886. return E_FAIL;
  7887. }
  7888. *retval = 0;
  7889. // The new ITravelLog
  7890. ITravelLog *ptl;
  7891. // Get the new TravelLog from the browser service object.
  7892. if (SUCCEEDED(_pAuto->_pbs->GetTravelLog(&ptl)))
  7893. {
  7894. if (ptl)
  7895. *retval = (short)ptl->CountEntries(_pAuto->_pbs);
  7896. ptl->Release();
  7897. }
  7898. return S_OK;
  7899. }
  7900. STDMETHODIMP CIEFrameAuto::COmHistory::go(VARIANT *pVargDist)
  7901. {
  7902. // Parameter is optional. If not present, just refresh.
  7903. if (pVargDist->vt == VT_ERROR
  7904. && pVargDist->scode == DISP_E_PARAMNOTFOUND)
  7905. return _pAuto->Refresh();
  7906. // Change type to short if possible.
  7907. //
  7908. HRESULT hr = VariantChangeType(pVargDist, pVargDist, NULL, VT_I2);
  7909. if (SUCCEEDED(hr))
  7910. {
  7911. //
  7912. // If 0, just call Refresh
  7913. //
  7914. if (pVargDist->iVal == 0)
  7915. {
  7916. return _pAuto->Refresh();
  7917. }
  7918. // Make sure we have an IBrowserService pointer
  7919. if (_pAuto->_pbs==NULL)
  7920. {
  7921. TraceMsg(DM_WARNING, "CIEA::history.go called _pbs==NULL");
  7922. return E_FAIL;
  7923. }
  7924. // The new ITravelLog
  7925. ITravelLog *ptl;
  7926. // Get the new TravelLog from the browser service object.
  7927. if (SUCCEEDED(_pAuto->_pbs->GetTravelLog(&ptl)))
  7928. {
  7929. // Tell it to travel. Pass in the IShellBrowser pointer.
  7930. ptl->Travel(_pAuto->_pbs, pVargDist->iVal);
  7931. ptl->Release();
  7932. }
  7933. return S_OK;
  7934. }
  7935. // Now see if it's a string.
  7936. //
  7937. if (pVargDist->vt == VT_BSTR)
  7938. {
  7939. LPITEMIDLIST pidl;
  7940. ITravelLog *ptl;
  7941. ITravelEntry *pte;
  7942. // Make sure we have an IBrowserService pointer
  7943. if (_pAuto->_pbs==NULL)
  7944. {
  7945. TraceMsg(DM_WARNING, "CIEA::history.go called _pbs==NULL");
  7946. return E_FAIL;
  7947. }
  7948. if (SUCCEEDED(_pAuto->_PidlFromUrlEtc(CP_ACP, pVargDist->bstrVal, NULL, &pidl)))
  7949. {
  7950. if (SUCCEEDED(_pAuto->_pbs->GetTravelLog(&ptl)))
  7951. {
  7952. if (SUCCEEDED(ptl->FindTravelEntry(_pAuto->_pbs, pidl, &pte)))
  7953. {
  7954. pte->Invoke(_pAuto->_pbs);
  7955. pte->Release();
  7956. }
  7957. ptl->Release();
  7958. }
  7959. ILFree(pidl);
  7960. }
  7961. }
  7962. //
  7963. // Netscape ignores all errors from these navigation functions
  7964. //
  7965. return S_OK;
  7966. }
  7967. /******************************************************************************
  7968. Window Open Support
  7969. ******************************************************************************/
  7970. DWORD OpenAndNavigateToURL(
  7971. CIEFrameAuto *pauto, // IEFrameAuto of caller. Used to get IWeBrowserApp, ITargetFrame2, and IHlinkFrame methods
  7972. BSTR *pbstrURL, // URL to navigate to. Should already be an escaped absolute URL
  7973. const WCHAR *pwzTarget, // Name of the frame to navigate
  7974. ITargetNotify *pNotify, // Received callback on open. May be NULL
  7975. BOOL bNoHistory, // Don't add to history
  7976. BOOL bSilent) // This frame is in silent Mode
  7977. {
  7978. ASSERT(*pbstrURL);
  7979. ASSERT(pwzTarget);
  7980. ASSERT(pauto);
  7981. IUnknown *punkTargetFrame = NULL;
  7982. LPTARGETFRAMEPRIV ptgfpTarget = NULL;
  7983. BOOL fOpenInNewWindow = FALSE;
  7984. LPBINDCTX pBindCtx = NULL;
  7985. LPMONIKER pMoniker = NULL;
  7986. LPHLINK pHlink = NULL;
  7987. DWORD dwHlinkFlags = 0;
  7988. DWORD zone_cross = 0;
  7989. const WCHAR *pwzFindLoc = 0;
  7990. // Used to open a new window if there is not an existing frame
  7991. LPTARGETFRAMEPRIV ptgfp = SAFECAST(pauto, ITargetFramePriv*);
  7992. // Lookup the frame cooresponding to the target - this will give us the
  7993. // IUnknown for an object that can give us the coresponding IHlinkFrame
  7994. // via IServiceProvider::QueryService.
  7995. HRESULT hr = pauto->FindFrame(pwzTarget, FINDFRAME_JUSTTESTEXISTENCE, &punkTargetFrame);
  7996. if (punkTargetFrame)
  7997. {
  7998. // Get the IHlinkFrame for the target'ed frame.
  7999. hr = punkTargetFrame->QueryInterface(IID_PPV_ARG(ITargetFramePriv, &ptgfpTarget));
  8000. if (FAILED(hr))
  8001. goto Exit;
  8002. ptgfp = ptgfpTarget;
  8003. // if URL is empty
  8004. if (!**pbstrURL || **pbstrURL == EMPTY_URL)
  8005. {
  8006. LPTARGETNOTIFY ptgnNotify = NULL;
  8007. if (pNotify)
  8008. {
  8009. if (FAILED(pNotify->QueryInterface(IID_PPV_ARG(ITargetNotify, &ptgnNotify))))
  8010. ptgnNotify = NULL;
  8011. }
  8012. if (ptgnNotify)
  8013. {
  8014. ptgnNotify->OnReuse(punkTargetFrame);
  8015. ptgnNotify->Release();
  8016. }
  8017. goto Exit; // Don't navigate.
  8018. }
  8019. }
  8020. else if (SUCCEEDED(hr))
  8021. {
  8022. // No luck, open in new window
  8023. fOpenInNewWindow = TRUE;
  8024. // Now, if the URL is empty, replace it with "about:blank"
  8025. if (!**pbstrURL || **pbstrURL == EMPTY_URL)
  8026. {
  8027. BSTR bstrOldURL = *pbstrURL;
  8028. *pbstrURL = NULL;
  8029. if (*bstrOldURL == EMPTY_URL)
  8030. // The URL is really empty string however when the 0x01 is the
  8031. // character of the URL this signals that the security information
  8032. // follows. Therefore, we'll need to append the about:blank +
  8033. // \1 + callerURL.
  8034. CreateBlankURL(pbstrURL, TEXT("about:blank"), bstrOldURL);
  8035. else
  8036. CreateBlankURL(pbstrURL, pauto->_fDesktopComponent() ? NAVFAIL_URL_DESKTOPITEM : NAVFAIL_URL, bstrOldURL);
  8037. SysFreeString(bstrOldURL);
  8038. }
  8039. }
  8040. else
  8041. goto Exit;
  8042. // bradsch 11/12/96
  8043. // Need to figure out Browser-Control stuff for webcheck
  8044. // 11/12/96
  8045. // Need to implment this with Trident... I think "JavaScript:" should be
  8046. // supported as a real protocol. This would provide greater Navigator
  8047. // compatibility and allows us to avoid the following hack.
  8048. /*
  8049. if (!StrCmpNI(pszURL, JAVASCRIPT_PROTOCOL, ARRAY_ELEMENTS(JAVASCRIPT_PROTOCOL)-1))
  8050. {
  8051. if (tw && tw->w3doc && DLCtlShouldRunScripts(tw->lDLCtlFlags))
  8052. ScriptOMExecuteThis(tw->w3doc->dwScriptHandle, JAVASCRIPT, &pszURL[ARRAY_ELEMENTS(JAVASCRIPT_PROTOCOL)-1],
  8053. pszJavascriptTarget);
  8054. return ERROR_SUCCESS;
  8055. }
  8056. */
  8057. LONG_PTR hwnd;
  8058. hr = pauto->get_HWND(&hwnd);
  8059. if (FAILED(hr))
  8060. goto Exit;
  8061. BSTR bstrCurrentURL;
  8062. hr = pauto->get_LocationURL(&bstrCurrentURL);
  8063. if (FAILED(hr))
  8064. goto Exit;
  8065. zone_cross = ERROR_SUCCESS;
  8066. if (!bSilent)
  8067. {
  8068. ASSERT(pauto->_psb);
  8069. if (pauto->_psb)
  8070. pauto->_psb->EnableModelessSB(FALSE);
  8071. zone_cross = InternetConfirmZoneCrossing((HWND) hwnd, bstrCurrentURL, *pbstrURL, FALSE);
  8072. if (pauto->_psb)
  8073. pauto->_psb->EnableModelessSB(TRUE);
  8074. }
  8075. SysFreeString(bstrCurrentURL);
  8076. if (ERROR_CANCELLED == zone_cross)
  8077. {
  8078. hr = HRESULT_FROM_WIN32(zone_cross);
  8079. goto Exit;
  8080. }
  8081. // create a moniker and bind context for this URL
  8082. // use CreateAsyncBindCtxEx so that destination still navigates
  8083. // even if we exit, as in the following code:
  8084. // window.close()
  8085. // window.open("http://haha/jokesonyou.html","_blank");
  8086. hr = CreateAsyncBindCtxEx(NULL, 0, NULL, NULL, &pBindCtx, 0);
  8087. if (FAILED(hr))
  8088. goto Exit;
  8089. if (pNotify)
  8090. {
  8091. hr = pBindCtx->RegisterObjectParam(TARGET_NOTIFY_OBJECT_NAME, pNotify);
  8092. ASSERT(SUCCEEDED(hr));
  8093. }
  8094. // Seperate the base URL from the location (hash)
  8095. if (pwzFindLoc = StrChrW(*pbstrURL, '#'))
  8096. {
  8097. const WCHAR *pwzTemp = StrChrW(pwzFindLoc, '/');
  8098. if (!pwzTemp)
  8099. pwzTemp = StrChrW(pwzFindLoc, '\\');
  8100. // no delimiters past this # marker... we've found a location.
  8101. // break out
  8102. if (pwzTemp)
  8103. pwzFindLoc = NULL;
  8104. }
  8105. WCHAR wszBaseURL[MAX_URL_STRING+1];
  8106. WCHAR wszLocation[MAX_URL_STRING+1];
  8107. if (pwzFindLoc)
  8108. {
  8109. // StrCpyNW alway null terminates to we need to copy len+1
  8110. int cchCopy = (int)(pwzFindLoc-*pbstrURL+1);
  8111. if (cchCopy > ARRAYSIZE(wszBaseURL))
  8112. cchCopy = ARRAYSIZE(wszBaseURL);
  8113. StrCpyNW(wszBaseURL, *pbstrURL, cchCopy);
  8114. StrCpyNW(wszLocation, pwzFindLoc, ARRAYSIZE(wszLocation));
  8115. }
  8116. else
  8117. {
  8118. StrCpyNW(wszBaseURL, *pbstrURL, ARRAYSIZE(wszBaseURL));
  8119. wszLocation[0] = 0;
  8120. }
  8121. ASSERT(pBindCtx);
  8122. if (fOpenInNewWindow)
  8123. {
  8124. dwHlinkFlags |= HLNF_OPENINNEWWINDOW;
  8125. }
  8126. if (bNoHistory)
  8127. {
  8128. dwHlinkFlags |= HLNF_CREATENOHISTORY;
  8129. }
  8130. hr = ptgfp->NavigateHack(dwHlinkFlags,
  8131. pBindCtx,
  8132. NULL,
  8133. fOpenInNewWindow ? pwzTarget : NULL,
  8134. wszBaseURL,
  8135. pwzFindLoc ? wszLocation : NULL);
  8136. Exit:
  8137. SAFERELEASE(ptgfpTarget);
  8138. SAFERELEASE(punkTargetFrame);
  8139. SAFERELEASE(pBindCtx);
  8140. return hr;
  8141. }
  8142. HRESULT CreateBlankURL(BSTR *url, LPCTSTR pszErrorUrl, BSTR oldUrl)
  8143. {
  8144. ASSERT(url);
  8145. unsigned int cbTotal = 0;
  8146. if (pszErrorUrl)
  8147. cbTotal = lstrlen(pszErrorUrl);
  8148. if (oldUrl) // Security portion of URL to append.
  8149. cbTotal += lstrlenW(oldUrl);
  8150. if (cbTotal)
  8151. {
  8152. *url = SysAllocStringByteLen(NULL, cbTotal * sizeof(WCHAR)); // adds +1 to cbTotal
  8153. if (*url)
  8154. {
  8155. StrCpyN(*url, pszErrorUrl, cbTotal + 1);
  8156. // Append the security URL to the actual URL.
  8157. if (oldUrl)
  8158. {
  8159. StrCatBuffW(*url, oldUrl, cbTotal + 1);
  8160. }
  8161. return S_OK;
  8162. }
  8163. }
  8164. return E_FAIL;
  8165. }
  8166. // bradsch 11/14/96
  8167. // This parsing code was copied from MSHTML and really bites. It should be replaced.
  8168. BOOL GetNextOption(BSTR& bstrOptionString, BSTR* optionName, int* piValue)
  8169. {
  8170. WCHAR* delimiter;
  8171. // Get the name of the option being set
  8172. *optionName = GetNextToken(bstrOptionString, L"=,", L" \t\n\r", &delimiter);
  8173. BSTR optionSetting = NULL;
  8174. if (!*optionName)
  8175. return FALSE;
  8176. // If there is an equal sign, get the value being set
  8177. if (*delimiter=='=')
  8178. optionSetting = GetNextToken(delimiter+1, L"=,", L" \t\n\r", &delimiter);
  8179. if (!optionSetting)
  8180. *piValue = TRUE;
  8181. else
  8182. {
  8183. if (StrCmpIW(optionSetting, L"yes")==0)
  8184. *piValue = 1; // TRUE
  8185. else if (StrCmpIW(optionSetting, L"no")==0)
  8186. *piValue = 0; // FALSE
  8187. else
  8188. {
  8189. *piValue = StrToIntW(optionSetting);
  8190. }
  8191. SysFreeString(optionSetting);
  8192. }
  8193. // Advance the option string to the delimiter
  8194. bstrOptionString=delimiter;
  8195. return TRUE;
  8196. }
  8197. /******************************************************************************
  8198. // Return the next token, or NULL if there are no more tokens
  8199. ******************************************************************************/
  8200. BSTR GetNextToken(BSTR bstr, BSTR delimiters, BSTR whitespace, BSTR *nextPos)
  8201. {
  8202. BSTR result = NULL;
  8203. WCHAR* curPos = bstr;
  8204. // skip delimiters and whitespace to get the start of the token
  8205. while (*curPos && (StrChrW(delimiters, *curPos) || StrChrW(whitespace, *curPos)))
  8206. curPos++;
  8207. WCHAR* start = curPos;
  8208. // keep scanning until we reach another delimiter or whitespace
  8209. while (*curPos && !StrChrW(delimiters, *curPos) && !StrChrW(whitespace, *curPos))
  8210. curPos++;
  8211. if (curPos > start)
  8212. {
  8213. // copy out the token as the result
  8214. result = SafeSysAllocStringLen(start, (int)(curPos-start)); // allocates +1 for the terminator
  8215. }
  8216. // scan to past the whitespace to the next delimiter
  8217. while (*curPos && StrChrW(whitespace, *curPos))
  8218. curPos++;
  8219. // return the delimiter
  8220. *nextPos = curPos;
  8221. return result;
  8222. }
  8223. #define MAX_ARGS 10
  8224. HRESULT __cdecl DoInvokeParamHelper(IUnknown* punk, IConnectionPoint* pccp,
  8225. BOOL *pf, void **ppv, DISPID dispid, UINT cArgs, ...
  8226. /* param pairs of: LPVOID Arg, VARENUM Type, ... */)
  8227. {
  8228. HRESULT hr;
  8229. IShellBrowser * psb = NULL;
  8230. if (punk && S_OK == punk->QueryInterface(IID_PPV_ARG(IShellBrowser, &psb)))
  8231. psb->EnableModelessSB(FALSE);
  8232. // Calling with no params is wasteful, they should call DoInvoke directly
  8233. //
  8234. if (cArgs == 0)
  8235. {
  8236. // Can't possible cancel if there are no parameters
  8237. ASSERT(pf == NULL && ppv == NULL);
  8238. IConnectionPoint_SimpleInvoke(pccp, dispid, NULL);
  8239. hr = S_OK;
  8240. }
  8241. else if (cArgs < MAX_ARGS)
  8242. {
  8243. // This function can potentially get called *very frequently*. It is
  8244. // used, among other things, to set status text and progress barometer
  8245. // values. We need to make an array of VARIANTARGs to hold a variable
  8246. // number of parameters. As an optimization since we want to minimize
  8247. // overhead in this function, we will use a static array on the stack
  8248. // rather than allocating memory. This puts a limit (of MAX_ARGS) on
  8249. // the number of arguments this function can process; but this is just
  8250. // an internal function so that's OK. Bump up MAX_ARGS if you run out of
  8251. // room.
  8252. VARIANTARG VarArgList[MAX_ARGS];
  8253. DISPPARAMS dispparams = {0};
  8254. va_list ArgList;
  8255. va_start(ArgList, cArgs);
  8256. hr = SHPackDispParamsV(&dispparams, VarArgList, cArgs, ArgList);
  8257. va_end(ArgList);
  8258. // Now Simply Call The DoInvoke to do the real work...
  8259. if (S_OK == hr)
  8260. IConnectionPoint_InvokeWithCancel(pccp, dispid, &dispparams, pf, ppv);
  8261. hr = S_OK;
  8262. }
  8263. else
  8264. {
  8265. hr = E_UNEXPECTED;
  8266. }
  8267. if (psb)
  8268. {
  8269. psb->EnableModelessSB(TRUE);
  8270. SAFERELEASE(psb);
  8271. }
  8272. return hr;
  8273. }