Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

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