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

1827 lines
62 KiB

  1. #include "priv.h"
  2. #include <varutil.h>
  3. #include "hlframe.h"
  4. #include "winlist.h"
  5. #include "resource.h" //CLSID_SearchBand
  6. #include "interned.h" // IHTMLPrivateWindow
  7. // Locally defined FINDFRAME flag used to guarantee ITargetFrame vs ITargetFrame2 compatibility
  8. #define FINDFRAME_OLDINTERFACE FINDFRAME_INTERNAL
  9. STDAPI SafeGetItemObject(LPSHELLVIEW psv, UINT uItem, REFIID riid, LPVOID *ppv);
  10. HRESULT TargetQueryService(LPUNKNOWN punk, REFIID riid, void **ppvObj);
  11. HRESULT CoCreateNewIEWindow( DWORD dwClsContext, REFIID riid, void **ppvunk );
  12. /******************************************************************
  13. NAME: SetOleStrMember
  14. SYNOPSIS: sets a new value for OleStr member
  15. ******************************************************************/
  16. HRESULT SetOleStrMember(WCHAR **ppszMember, LPCOLESTR pszNewValue)
  17. {
  18. HRESULT hr;
  19. if (*ppszMember)
  20. {
  21. LocalFree(*ppszMember);
  22. *ppszMember = NULL;
  23. }
  24. if (pszNewValue)
  25. {
  26. *ppszMember = StrDupW(pszNewValue);
  27. hr = *ppszMember ? S_OK : E_OUTOFMEMORY;
  28. }
  29. else
  30. {
  31. *ppszMember = NULL;
  32. hr = S_OK;
  33. }
  34. return hr;
  35. }
  36. /******************************************************************
  37. NAME: GetOleStrMember
  38. SYNOPSIS: gets a value for OleStr member as new CoTaskMemAlloc
  39. LPOLESTR
  40. ******************************************************************/
  41. HRESULT GetOleStrMember(LPCOLESTR pszMember, WCHAR **ppszReturnValue)
  42. {
  43. HRESULT hr;
  44. if (pszMember)
  45. hr = SHStrDupW(pszMember, ppszReturnValue);
  46. else
  47. {
  48. hr = S_OK;
  49. *ppszReturnValue = NULL;
  50. }
  51. return hr;
  52. }
  53. /*******************************************************************
  54. NAME: CIEFrameAuto::SetFrameName
  55. SYNOPSIS: Sets the Frame Name. Frees current one if exists.
  56. ********************************************************************/
  57. STDMETHODIMP CIEFrameAuto::SetFrameName(LPCOLESTR pszFrameName)
  58. {
  59. // AOL and other 3rd Party 3.0 compatibility. The ITargetNotify
  60. // object that sets off a window open operation via AOL container
  61. // registers itself in ShellCallbacks list and wnsprintf's the
  62. // coresponding cookie in the front of the frame name ("" if there
  63. // is no frame name as in _blank). we extract the cookie, notify
  64. // all registered callbacks, then set the name MINUS the _[NNNNN..]
  65. // that was prepending to the frame name.
  66. if (pszFrameName && lstrlen(pszFrameName) >= 2 && pszFrameName[0] == '_' && pszFrameName[1] == '[')
  67. {
  68. #define MAX_COOKIE 24
  69. WCHAR wszCookie[MAX_COOKIE + 1]; // big enough for "cbCookie"
  70. int i;
  71. long cbCookie;
  72. BOOL fNonDigit = FALSE;
  73. IShellWindows* psw = NULL;
  74. for (i = 2; i < MAX_COOKIE && pszFrameName[i] && pszFrameName[i] != ']'; i++)
  75. {
  76. wszCookie[i-2] = pszFrameName[i];
  77. if (i != 2 || pszFrameName[2] != '-')
  78. fNonDigit = fNonDigit || pszFrameName[i] < '0' || pszFrameName[i] > '9';
  79. }
  80. wszCookie[i-2] = 0;
  81. if (i >= 3 && pszFrameName[i] == ']' && !fNonDigit)
  82. {
  83. cbCookie = StrToIntW(wszCookie);
  84. psw = WinList_GetShellWindows(TRUE);
  85. if (psw)
  86. {
  87. IUnknown *punkThis;
  88. if (SUCCEEDED(QueryInterface(IID_PPV_ARG(IUnknown, &punkThis))))
  89. {
  90. psw->OnCreated(cbCookie, punkThis);
  91. punkThis->Release();
  92. }
  93. psw->Release();
  94. }
  95. pszFrameName = pszFrameName + i + 1;
  96. if (pszFrameName[0] == 0)
  97. pszFrameName = NULL;
  98. }
  99. }
  100. return SetOleStrMember(&m_pszFrameName, pszFrameName);
  101. }
  102. /*******************************************************************
  103. NAME: CIEFrameAuto::GetFrameName
  104. SYNOPSIS: Gets the Frame Name. Allocates a copy (this is an
  105. [OUT] parameter
  106. ********************************************************************/
  107. STDMETHODIMP CIEFrameAuto::GetFrameName(WCHAR **ppszFrameName)
  108. {
  109. return GetOleStrMember(m_pszFrameName, ppszFrameName);
  110. }
  111. /*******************************************************************
  112. NAME: CIEFrameAuto::_GetParentFramePrivate
  113. SYNOPSIS: Gets an the IUnknown pointer of the parent frame, or
  114. NULL if this is a top level frame. This pointer must be Released
  115. by Caller after use.
  116. IMPLEMENTATION:
  117. A Frame Container is required to implement ITargetFrame::GetParentFrame and
  118. implement GetParentFrame by returning the IUnknown pointer of the Browser that
  119. hosts it. A Browser implements GetParentFrame by returning NULL if it's
  120. top level or calling GetParentFrame on its Container if it is embedded.
  121. NOTE: THIS PRIVATE VERSION doesn't check for parent being desktopframe.
  122. ********************************************************************/
  123. HRESULT CIEFrameAuto::_GetParentFramePrivate(LPUNKNOWN *ppunkParentFrame)
  124. {
  125. LPOLEOBJECT pOleObject = NULL;
  126. LPOLECLIENTSITE pOleClientSite = NULL;
  127. HRESULT hr = S_OK;
  128. LPUNKNOWN punkParent = NULL;
  129. // Start off with OleObject for this OCX embedding, it will
  130. // be null if we're top level (a CIEFrameAuto, not a CVOCBrowser)
  131. _GetOleObject(&pOleObject);
  132. if (pOleObject != NULL)
  133. {
  134. // Assumes GetClientSite succeeds and returns NULL if we
  135. // are not embedded
  136. hr = pOleObject->GetClientSite(&pOleClientSite);
  137. if (FAILED(hr))
  138. goto errExit;
  139. pOleObject->Release();
  140. pOleObject = NULL;
  141. // If pOleClientSite is NULL, then we are at the top level
  142. if (pOleClientSite == NULL)
  143. {
  144. hr = S_OK;
  145. goto errExit;
  146. }
  147. else
  148. {
  149. hr = TargetQueryService(pOleClientSite, IID_PPV_ARG(IUnknown, &punkParent));
  150. if (FAILED(hr))
  151. {
  152. // if parent container does not support ITargetFrame, then
  153. // the parent container must be some other app, like VB. In this
  154. // case, we've already found the outermost frame (us). Return
  155. // S_OK and a NULL ptgfTargetFrame which indicates that we are the
  156. // outermost HTML frame.
  157. hr = S_OK;
  158. }
  159. SAFERELEASE(pOleClientSite);
  160. }
  161. }
  162. errExit:
  163. SAFERELEASE(pOleObject);
  164. SAFERELEASE(pOleClientSite);
  165. *ppunkParentFrame = punkParent;
  166. return hr;
  167. }
  168. /*******************************************************************
  169. NAME: CIEFrameAuto::GetParentFrame
  170. SYNOPSIS: Gets an the IUnknown pointer of the parent frame, or
  171. NULL if this is a top level frame. This pointer must be Released
  172. by Caller after use.
  173. IMPLEMENTATION:
  174. A Frame Container is required to implement ITargetFrame::GetParentFrame and
  175. implement GetParentFrame by returning the IUnknown pointer of the Browser that
  176. hosts it. A Browser implements GetParentFrame by returning NULL if it's
  177. top level or calling GetParentFrame on its Container if it is embedded.
  178. ********************************************************************/
  179. STDMETHODIMP CIEFrameAuto::GetParentFrame(LPUNKNOWN *ppunkParentFrame)
  180. {
  181. HRESULT hr = _GetParentFramePrivate(ppunkParentFrame);
  182. // Check if the parent is the desktop, if so, the frame chain stops
  183. // at us
  184. if (SUCCEEDED(hr) && *ppunkParentFrame)
  185. {
  186. LPTARGETFRAME2 ptgfParent;
  187. DWORD dwOptions;
  188. if (SUCCEEDED((*ppunkParentFrame)->QueryInterface(IID_PPV_ARG(ITargetFrame2, &ptgfParent))))
  189. {
  190. ptgfParent->GetFrameOptions(&dwOptions);
  191. if (dwOptions & FRAMEOPTIONS_DESKTOP)
  192. {
  193. (*ppunkParentFrame)->Release();
  194. *ppunkParentFrame = NULL;
  195. }
  196. ptgfParent->Release();
  197. }
  198. }
  199. return hr;
  200. }
  201. // PLEASE PROPOGATE ANY CHANGES TO THESE ENUMS TO \mshtml\iextag\httpwfh.h
  202. typedef enum _TARGET_TYPE {
  203. TARGET_FRAMENAME,
  204. TARGET_SELF,
  205. TARGET_PARENT,
  206. TARGET_BLANK,
  207. TARGET_TOP,
  208. TARGET_MAIN,
  209. TARGET_SEARCH,
  210. TARGET_MEDIA
  211. } TARGET_TYPE;
  212. typedef struct _TARGETENTRY {
  213. TARGET_TYPE targetType;
  214. const WCHAR *pTargetValue;
  215. } TARGETENTRY;
  216. static const TARGETENTRY targetTable[] =
  217. {
  218. {TARGET_SELF, L"_self"},
  219. {TARGET_PARENT, L"_parent"},
  220. {TARGET_BLANK, L"_blank"},
  221. {TARGET_TOP, L"_top"},
  222. {TARGET_MAIN, L"_main"},
  223. {TARGET_SEARCH, L"_search"},
  224. {TARGET_MEDIA, L"_media"},
  225. {TARGET_SELF, NULL}
  226. };
  227. /*******************************************************************
  228. NAME: ParseTargetType
  229. SYNOPSIS: Maps pszTarget into a target class.
  230. IMPLEMENTATION:
  231. Treats unknown MAGIC targets as _self
  232. ********************************************************************/
  233. // PLEASE PROPOGATE ANY CHANGES TO THIS FUNCTION TO \mshtml\iextag\httpwf.cxx
  234. TARGET_TYPE ParseTargetType(LPCOLESTR pszTarget)
  235. {
  236. const TARGETENTRY *pEntry = targetTable;
  237. if (pszTarget[0] != '_')
  238. return TARGET_FRAMENAME;
  239. while (pEntry->pTargetValue)
  240. {
  241. if (!StrCmpW(pszTarget, pEntry->pTargetValue))
  242. return pEntry->targetType;
  243. pEntry++;
  244. }
  245. // Treat unknown MAGIC targets as regular frame name! <<for NETSCAPE compatibility>>
  246. return TARGET_FRAMENAME;
  247. }
  248. /*******************************************************************
  249. NAME: TargetQueryService
  250. SYNOPSIS: Returns a pointer to containing Browser's ITargetFrame
  251. interface (or NULL if container does not support it)
  252. NOTES: If we don't yet have this interface pointer yet,
  253. this function will QueryInterface to get it.
  254. ********************************************************************/
  255. HRESULT TargetQueryService(LPUNKNOWN punk, REFIID riid, void **ppvObj)
  256. {
  257. // Get the ITargetFrame for the embedding.
  258. return IUnknown_QueryService(punk, IID_ITargetFrame2, riid, ppvObj);
  259. }
  260. /*******************************************************************
  261. NAME: _TargetTopLevelWindows
  262. SYNOPSIS: see FindFrame, does the named targets across windows
  263. ********************************************************************/
  264. HRESULT _TargetTopLevelWindows(LPTARGETFRAMEPRIV ptgfpThis, LPCOLESTR pszTargetName, DWORD dwFlags, LPUNKNOWN *ppunkTargetFrame)
  265. {
  266. IShellWindows* psw = NULL;
  267. HRESULT hr = E_FAIL;
  268. *ppunkTargetFrame = NULL;
  269. psw = WinList_GetShellWindows(TRUE);
  270. if (psw != NULL)
  271. {
  272. IUnknown *punkEnum;
  273. IEnumVARIANT *penumVariant;
  274. VARIANT VarResult;
  275. BOOL fDone = FALSE;
  276. LPTARGETFRAMEPRIV ptgfpWindowFrame;
  277. hr = psw->_NewEnum(&punkEnum);
  278. if (SUCCEEDED(hr))
  279. {
  280. hr = punkEnum->QueryInterface(IID_PPV_ARG(IEnumVARIANT, &penumVariant));
  281. if (SUCCEEDED(hr))
  282. {
  283. while (!fDone)
  284. {
  285. VariantInit(&VarResult);
  286. hr = penumVariant->Next(1, &VarResult, NULL);
  287. if (hr == NOERROR)
  288. {
  289. if (VarResult.vt == VT_DISPATCH && VarResult.pdispVal)
  290. {
  291. hr = VarResult.pdispVal->QueryInterface(IID_PPV_ARG(ITargetFramePriv, &ptgfpWindowFrame));
  292. if (SUCCEEDED(hr))
  293. {
  294. if (ptgfpWindowFrame != ptgfpThis)
  295. {
  296. hr = ptgfpWindowFrame->FindFrameDownwards(pszTargetName, dwFlags, ppunkTargetFrame);
  297. if (SUCCEEDED(hr) && *ppunkTargetFrame != NULL)
  298. {
  299. fDone = TRUE;
  300. }
  301. }
  302. ptgfpWindowFrame->Release();
  303. }
  304. }
  305. VariantClear(&VarResult);
  306. }
  307. else
  308. {
  309. fDone = TRUE;
  310. }
  311. }
  312. penumVariant->Release();
  313. }
  314. punkEnum->Release();
  315. }
  316. psw->Release();
  317. }
  318. return hr;
  319. }
  320. /*******************************************************************
  321. NAME: CreateTargetFrame
  322. SYNOPSIS: Creates a new window, if pszTargetName is not special
  323. target, names it pszTargetName. returns IUnknown for
  324. the object that implements ITargetFrame,IHlinkFrame and
  325. IWebBrowserApp.
  326. ********************************************************************/
  327. // PLEASE PROPOGATE ANY CHANGES TO THIS FUNCTION TO \mshtml\iextag\httpwf.cxx
  328. HRESULT CreateTargetFrame(LPCOLESTR pszTargetName, LPUNKNOWN /*IN,OUT*/ *ppunk)
  329. {
  330. LPTARGETFRAME2 ptgfWindowFrame;
  331. HRESULT hr = S_OK;
  332. // Launch a new window, set it's frame name to pszTargetName
  333. // return it's IUnknown. If the new window is passed to us,
  334. // just set the target name.
  335. if (NULL == *ppunk)
  336. {
  337. hr = CoCreateNewIEWindow(CLSCTX_INPROC_SERVER | CLSCTX_LOCAL_SERVER, IID_PPV_ARG(IUnknown, ppunk));
  338. }
  339. if (SUCCEEDED(hr))
  340. {
  341. // Don't set frame name if target is special or missing
  342. if (pszTargetName && ParseTargetType(pszTargetName) == TARGET_FRAMENAME)
  343. {
  344. HRESULT hrLocal;
  345. hrLocal = (*ppunk)->QueryInterface(IID_PPV_ARG(ITargetFrame2, &ptgfWindowFrame));
  346. if (SUCCEEDED(hrLocal))
  347. {
  348. ptgfWindowFrame->SetFrameName(pszTargetName);
  349. ptgfWindowFrame->Release();
  350. }
  351. }
  352. // Even if we don't set the frame name, we still want to return
  353. // success, otherwise we'd have a blank window hanging around.
  354. }
  355. return hr;
  356. }
  357. /*******************************************************************
  358. NAME: CIEFrameAuto::_DoNamedTarget
  359. SYNOPSIS: see FindFrame, does the named targets. checks itself
  360. then if that fails, all children except for punkContextFrame (if
  361. punkContextFrame != NULL). if all of the above fail, will recurse
  362. upwards if necessary, if punkContextFrame != NULL. if punkContextFrame
  363. is NULL, then this works out to checking ourself and all children
  364. then giving up.
  365. ********************************************************************/
  366. HRESULT CIEFrameAuto::_DoNamedTarget(LPCOLESTR pszTargetName, LPUNKNOWN punkContextFrame, DWORD dwFlags, LPUNKNOWN * ppunkTargetFrame)
  367. {
  368. // asserts
  369. HRESULT hr = S_OK;
  370. HRESULT hrLocal;
  371. LPUNKNOWN punkParent = NULL;
  372. LPUNKNOWN punkThisFrame = NULL;
  373. LPTARGETFRAMEPRIV ptgfpParent = NULL;
  374. LPUNKNOWN punkThis = NULL;
  375. LPUNKNOWN punkChildObj = NULL;
  376. LPUNKNOWN punkChildFrame = NULL;
  377. LPTARGETFRAMEPRIV ptgfpChild = NULL;
  378. LPOLECONTAINER pOleContainer = NULL;
  379. LPENUMUNKNOWN penumUnknown = NULL;
  380. LPUNKNOWN punkProxyContextFrame = NULL;
  381. LPTARGETFRAMEPRIV ptgfpTarget = NULL;
  382. ASSERT(ppunkTargetFrame);
  383. *ppunkTargetFrame = NULL;
  384. hr = QueryInterface(IID_PPV_ARG(IUnknown, &punkThis));
  385. ASSERT(punkThis != NULL);
  386. if (FAILED(hr))
  387. goto exitPoint;
  388. // First check for match on US!
  389. if (m_pszFrameName && !StrCmpW(pszTargetName, m_pszFrameName))
  390. {
  391. *ppunkTargetFrame = punkThis;
  392. // Set punkThis to NULL to prevent Release at exit
  393. punkThis = NULL;
  394. goto exitPoint;
  395. }
  396. // we ask our ShellView's embedded DocObject if it supports ITargetFrame. If it does,
  397. // we first let it look for the target.
  398. hrLocal = GetFramesContainer(&pOleContainer);
  399. if (SUCCEEDED(hrLocal) && pOleContainer != NULL)
  400. {
  401. hr = pOleContainer->EnumObjects(OLECONTF_EMBEDDINGS, &penumUnknown);
  402. if (hr != S_OK || penumUnknown == NULL)
  403. goto exitPoint;
  404. while (TRUE)
  405. {
  406. hr = penumUnknown->Next(1, &punkChildObj, NULL);
  407. if (punkChildObj == NULL)
  408. {
  409. hr = S_OK;
  410. break;
  411. }
  412. hrLocal = punkChildObj->QueryInterface(IID_PPV_ARG(ITargetFramePriv, &ptgfpChild));
  413. if (SUCCEEDED(hrLocal))
  414. {
  415. hr = ptgfpChild->QueryInterface(IID_PPV_ARG(IUnknown, &punkChildFrame));
  416. if (FAILED(hr))
  417. goto exitPoint;
  418. // IF this isn't the punkContextFrame, see if embedding supports ITargetFrame
  419. if (punkChildFrame != punkContextFrame)
  420. {
  421. hr = ptgfpChild->FindFrameDownwards(pszTargetName, dwFlags, ppunkTargetFrame);
  422. if (hr != S_OK || *ppunkTargetFrame != NULL)
  423. goto exitPoint;
  424. }
  425. }
  426. punkChildObj->Release();
  427. punkChildObj = NULL;
  428. SAFERELEASE(punkChildFrame);
  429. SAFERELEASE(ptgfpChild);
  430. }
  431. }
  432. if (!(*ppunkTargetFrame) && pOleContainer)
  433. {
  434. hr = _FindWindowByName(pOleContainer, pszTargetName, ppunkTargetFrame);
  435. if (S_OK == hr)
  436. goto exitPoint;
  437. }
  438. // We don't recurse to parent in punkContextFrame is NULL
  439. if (punkContextFrame == NULL)
  440. goto exitPoint;
  441. hr = GetParentFrame(&punkParent);
  442. if (hr != S_OK)
  443. goto exitPoint;
  444. if (punkParent != NULL)
  445. {
  446. // We have a parent, recurse upwards, with ourself as context frame
  447. hr = punkParent->QueryInterface(IID_PPV_ARG(ITargetFramePriv, &ptgfpParent));
  448. if (hr != S_OK)
  449. goto exitPoint;
  450. hr = ptgfpParent->FindFrameInContext(pszTargetName,
  451. punkThis,
  452. dwFlags,
  453. ppunkTargetFrame);
  454. goto exitPoint;
  455. }
  456. // At this point we've come to the top level frame.
  457. // Enumerate top level windows, unless we're a toolbar
  458. *ppunkTargetFrame = NULL;
  459. if (_psb != _psbProxy)
  460. {
  461. // Webbar : Find in context of top frame of proxy
  462. hr = TargetQueryService(_psbProxy, IID_PPV_ARG(ITargetFramePriv, &ptgfpTarget));
  463. if (SUCCEEDED(hr) && ptgfpTarget)
  464. {
  465. hr = ptgfpTarget->QueryInterface(IID_PPV_ARG(IUnknown, &punkProxyContextFrame));
  466. if (SUCCEEDED(hr))
  467. {
  468. hr = ptgfpTarget->FindFrameInContext(pszTargetName,
  469. punkProxyContextFrame,
  470. dwFlags,
  471. ppunkTargetFrame);
  472. if (*ppunkTargetFrame)
  473. goto exitPoint;
  474. }
  475. }
  476. }
  477. else if (!(FINDFRAME_OLDINTERFACE & dwFlags))
  478. {
  479. hr = _TargetTopLevelWindows((LPTARGETFRAMEPRIV)this, pszTargetName, dwFlags, ppunkTargetFrame);
  480. if (*ppunkTargetFrame)
  481. goto exitPoint;
  482. }
  483. // Now we have exhausted all frames. Unless FINDFRAME_JUSTTESTEXISTENCE
  484. // is set in dwFlags, create a new window, set it's frame name and return it
  485. if (dwFlags & FINDFRAME_JUSTTESTEXISTENCE)
  486. {
  487. hr = S_OK;
  488. }
  489. else
  490. {
  491. // CreateTargetFrame will not work with AOL 3.01 clients
  492. // so we must return E_FAIL
  493. hr = E_FAIL;
  494. }
  495. exitPoint:
  496. SAFERELEASE(punkProxyContextFrame);
  497. SAFERELEASE(ptgfpTarget);
  498. SAFERELEASE(punkThis);
  499. SAFERELEASE(punkThisFrame);
  500. SAFERELEASE(ptgfpParent);
  501. SAFERELEASE(punkParent);
  502. SAFERELEASE(punkChildFrame);
  503. SAFERELEASE(ptgfpChild);
  504. SAFERELEASE(penumUnknown);
  505. SAFERELEASE(pOleContainer);
  506. SAFERELEASE(punkChildObj);
  507. return hr;
  508. }
  509. //+-------------------------------------------------------------------------
  510. //
  511. // Method : CIEFrameAuto::_FindWindowByName
  512. //
  513. // Synopsis : Searches the give container for the given frame name.
  514. // This method is called when _DoNamedTarget fails to find
  515. // the target frame in one of the container's embeddings.
  516. //
  517. //+-------------------------------------------------------------------------
  518. HRESULT
  519. CIEFrameAuto::_FindWindowByName(IOleContainer * pOleContainer,
  520. LPCOLESTR pszTargetName,
  521. LPUNKNOWN * ppunkTargetFrame)
  522. {
  523. HRESULT hr;
  524. IHTMLDocument2 * pDocument;
  525. IHTMLPrivateWindow * pPrivWindow;
  526. IHTMLWindow2 * pHTMLWindow;
  527. IServiceProvider * pServiceProvider;
  528. IWebBrowserApp * pWebBrowserApp;
  529. ASSERT(pOleContainer);
  530. ASSERT(ppunkTargetFrame);
  531. hr = pOleContainer->QueryInterface(IID_PPV_ARG(IHTMLDocument2, &pDocument));
  532. if (SUCCEEDED(hr))
  533. {
  534. hr = pDocument->get_parentWindow(&pHTMLWindow);
  535. if (SUCCEEDED(hr))
  536. {
  537. hr = pHTMLWindow->QueryInterface(IID_PPV_ARG(IHTMLPrivateWindow, &pPrivWindow));
  538. pHTMLWindow->Release(); // being reused below
  539. if (SUCCEEDED(hr))
  540. {
  541. hr = pPrivWindow->FindWindowByName(pszTargetName, &pHTMLWindow);
  542. if (S_OK == hr)
  543. {
  544. hr = pHTMLWindow->QueryInterface(IID_PPV_ARG(IServiceProvider, &pServiceProvider));
  545. if (S_OK == hr)
  546. {
  547. hr = pServiceProvider->QueryService(SID_SWebBrowserApp, IID_PPV_ARG(IWebBrowserApp, &pWebBrowserApp));
  548. if (S_OK == hr)
  549. {
  550. *ppunkTargetFrame = SAFECAST(pWebBrowserApp, IUnknown*);
  551. (*ppunkTargetFrame)->AddRef();
  552. pWebBrowserApp->Release();
  553. }
  554. pServiceProvider->Release();
  555. }
  556. pHTMLWindow->Release();
  557. }
  558. pPrivWindow->Release();
  559. }
  560. }
  561. pDocument->Release();
  562. }
  563. return hr;
  564. }
  565. /*******************************************************************
  566. NAME: CIEFrameAuto::SetFrameSrc
  567. SYNOPSIS: Sets the Frame original SRC url. Frees current one if exists.
  568. ********************************************************************/
  569. HRESULT CIEFrameAuto::SetFrameSrc(LPCOLESTR pszFrameSrc)
  570. {
  571. return SetOleStrMember(&m_pszFrameSrc, pszFrameSrc);
  572. }
  573. IShellView* CIEFrameAuto::_GetShellView(void)
  574. {
  575. IShellView* psv = NULL;
  576. if (_psb)
  577. {
  578. _psb->QueryActiveShellView(&psv);
  579. }
  580. return psv;
  581. }
  582. /*******************************************************************
  583. NAME: CIEFrameAuto::GetFrameSrc
  584. SYNOPSIS: Gets the Frame original URL. Allocates a copy (this is an
  585. [OUT] parameter
  586. NOTES: If we are at top level, SRC is dynamic, so ask our
  587. contained DocObject to do it for us.
  588. ********************************************************************/
  589. HRESULT CIEFrameAuto::GetFrameSrc(WCHAR **ppszFrameSrc)
  590. {
  591. LPUNKNOWN punkParent = NULL;
  592. LPTARGETFRAME ptgfTargetFrame = NULL;
  593. LPTARGETCONTAINER ptgcTargetContainer = NULL;
  594. *ppszFrameSrc = NULL;
  595. HRESULT hr = GetParentFrame(&punkParent);
  596. if (hr != S_OK)
  597. goto exitPoint;
  598. // If we're an embedding we have original src. If we're top level and
  599. // src has been set, return that, else defer to document
  600. if (punkParent != NULL || m_pszFrameSrc)
  601. {
  602. hr = GetOleStrMember(m_pszFrameSrc, ppszFrameSrc);
  603. }
  604. else // We're top level without an explicit SRC
  605. {
  606. *ppszFrameSrc = NULL;
  607. hr = S_OK; // review: since we are w/o SRC, we should succeed even though we don't fill out ppszFrameSrc in failure case?
  608. IShellView* psv = _GetShellView();
  609. if (psv)
  610. {
  611. HRESULT hrLocal = SafeGetItemObject(psv, SVGIO_BACKGROUND, IID_PPV_ARG(ITargetContainer, &ptgcTargetContainer));
  612. if (SUCCEEDED(hrLocal))
  613. {
  614. hr = ptgcTargetContainer->GetFrameUrl(ppszFrameSrc);
  615. }
  616. else
  617. {
  618. // Backwards compatibility
  619. hrLocal = SafeGetItemObject(psv, SVGIO_BACKGROUND, IID_PPV_ARG(ITargetFrame, &ptgfTargetFrame));
  620. if (SUCCEEDED(hrLocal))
  621. {
  622. hr = ptgfTargetFrame->GetFrameSrc(ppszFrameSrc);
  623. }
  624. }
  625. psv->Release();
  626. }
  627. }
  628. exitPoint:
  629. SAFERELEASE(punkParent);
  630. SAFERELEASE(ptgfTargetFrame);
  631. SAFERELEASE(ptgcTargetContainer);
  632. return hr;
  633. }
  634. /*******************************************************************
  635. NAME: CIEFrameAuto::GetFramesContainer
  636. SYNOPSIS: Returns an addref'ed pointer to the LPOLECONTAINER
  637. for our nested frames. Can be NULL.
  638. ********************************************************************/
  639. HRESULT CIEFrameAuto::GetFramesContainer(LPOLECONTAINER *ppContainer)
  640. {
  641. LPTARGETFRAME ptgfTargetFrame = NULL;
  642. LPTARGETCONTAINER ptgcTargetContainer = NULL;
  643. HRESULT hr = E_FAIL;
  644. *ppContainer = NULL;
  645. IShellView* psv = _GetShellView();
  646. if (psv)
  647. {
  648. HRESULT hrLocal = SafeGetItemObject(psv, SVGIO_BACKGROUND, IID_PPV_ARG(ITargetContainer, &ptgcTargetContainer));
  649. if (SUCCEEDED(hrLocal))
  650. {
  651. hr = ptgcTargetContainer->GetFramesContainer(ppContainer);
  652. }
  653. else
  654. {
  655. // Backwards compatibility
  656. hrLocal = SafeGetItemObject(psv, SVGIO_BACKGROUND, IID_PPV_ARG(ITargetFrame, &ptgfTargetFrame));
  657. if (SUCCEEDED(hrLocal))
  658. {
  659. hr = ptgfTargetFrame->GetFramesContainer(ppContainer);
  660. }
  661. }
  662. psv->Release();
  663. }
  664. SAFERELEASE(ptgcTargetContainer);
  665. SAFERELEASE(ptgfTargetFrame);
  666. return hr;
  667. }
  668. /*******************************************************************
  669. NAME: CIEFrameAuto::SetFrameOptions
  670. SYNOPSIS: Sets the Frame Options.
  671. ********************************************************************/
  672. HRESULT CIEFrameAuto::SetFrameOptions(DWORD dwFlags)
  673. {
  674. m_dwFrameOptions = dwFlags;
  675. return S_OK;
  676. }
  677. /*******************************************************************
  678. NAME: CIEFrameAuto::GetFrameOptions
  679. SYNOPSIS: Returns the frame options
  680. ********************************************************************/
  681. HRESULT CIEFrameAuto::GetFrameOptions(LPDWORD pdwFlags)
  682. {
  683. *pdwFlags = m_dwFrameOptions;
  684. // If we are full screen turn on a few extras...
  685. VARIANT_BOOL fFullScreen;
  686. if ((SUCCEEDED(get_FullScreen(&fFullScreen)) && fFullScreen == VARIANT_TRUE) ||
  687. (SUCCEEDED(get_TheaterMode(&fFullScreen)) && fFullScreen == VARIANT_TRUE))
  688. {
  689. *pdwFlags |= FRAMEOPTIONS_SCROLL_AUTO | FRAMEOPTIONS_NO3DBORDER;
  690. }
  691. else if (_psbProxy != _psb)
  692. {
  693. // If we are in the WebBar, turn off the 3D border.
  694. *pdwFlags |= FRAMEOPTIONS_NO3DBORDER;
  695. }
  696. // if we are desktop, turn on FRAMEOPTIONS_DESKTOP
  697. if (_fDesktopFrame)
  698. {
  699. *pdwFlags |= FRAMEOPTIONS_DESKTOP;
  700. }
  701. return S_OK;
  702. }
  703. /*******************************************************************
  704. NAME: CIEFrameAuto::SetFrameMargins
  705. SYNOPSIS: Sets the Frame margins.
  706. ********************************************************************/
  707. HRESULT CIEFrameAuto::SetFrameMargins(DWORD dwWidth, DWORD dwHeight)
  708. {
  709. m_dwFrameMarginWidth = dwWidth;
  710. m_dwFrameMarginHeight = dwHeight;
  711. return S_OK;
  712. }
  713. /*******************************************************************
  714. NAME: CIEFrameAuto::GetFrameMargins
  715. SYNOPSIS: Returns the frame margins
  716. ********************************************************************/
  717. HRESULT CIEFrameAuto::GetFrameMargins(LPDWORD pdwWidth, LPDWORD pdwHeight)
  718. {
  719. *pdwWidth = m_dwFrameMarginWidth;
  720. *pdwHeight = m_dwFrameMarginHeight;
  721. return S_OK;
  722. }
  723. /*******************************************************************
  724. NAME: CIEFrameAuto::_fDesktopComponent
  725. SYNOPSIS: Returns TRUE if this frame is a desktop component
  726. top level frame or a the top frame of a browser band other than
  727. the search pane. These panes need special treatment of FindFrame
  728. and navigate.
  729. *******************************************************************/
  730. BOOL CIEFrameAuto::_fDesktopComponent()
  731. {
  732. BOOL fInDesktop = FALSE;
  733. LPUNKNOWN punkParent;
  734. // Special interpretation for desktop components and non-search browser bands
  735. // NULL pszTargetName at top level frames is defined as being targeted
  736. // to the window whose frame is "_desktop". this will create a new top level
  737. // browser as necessary and return it's frame.
  738. if (SUCCEEDED(_GetParentFramePrivate(&punkParent)) && punkParent)
  739. {
  740. DWORD dwOptions;
  741. LPTARGETFRAME2 ptgfTop;
  742. // not a top level frame unless our parent is desktop frame
  743. if (SUCCEEDED(punkParent->QueryInterface(IID_PPV_ARG(ITargetFrame2, &ptgfTop))))
  744. {
  745. if (SUCCEEDED(ptgfTop->GetFrameOptions(&dwOptions)))
  746. {
  747. fInDesktop = (dwOptions & FRAMEOPTIONS_DESKTOP) ? TRUE:FALSE;
  748. }
  749. ptgfTop->Release();
  750. }
  751. punkParent->Release();
  752. }
  753. else if (m_dwFrameOptions & FRAMEOPTIONS_BROWSERBAND)
  754. {
  755. // a browser band - check for search band (proxied hlinkframe)
  756. fInDesktop = _psb == _psbProxy;
  757. }
  758. return fInDesktop;
  759. }
  760. // ITargetFrame2 members
  761. /*******************************************************************
  762. NAME: CIEFrameAuto::GetTargetAlias
  763. SYNOPSIS: Gets the Frame Name. Allocates a copy (this is an
  764. [OUT] parameter
  765. ********************************************************************/
  766. STDMETHODIMP CIEFrameAuto::GetTargetAlias(LPCOLESTR pszTargetName, WCHAR **ppszTargetAlias)
  767. {
  768. // Special interpretation for desktop components and non-search browser bands
  769. // NULL pszTargetName and "_top" at top level frames are defined as being targeted
  770. // to the window whose frame is "_desktop". this will create a new top level
  771. // browser as necessary and return it's frame.
  772. if (pszTargetName == NULL && _fDesktopComponent())
  773. return GetOleStrMember(L"_desktop", ppszTargetAlias);
  774. *ppszTargetAlias = NULL;
  775. return E_FAIL;
  776. }
  777. /*******************************************************************
  778. NAME: CIEFrameAuto::FindFrame
  779. SYNOPSIS: Gets an the IUnknown pointer of the frame referenced
  780. by pszTarget. This pointer must be Released by Caller after use.
  781. punkContextFrame, if not NULL, is the IUnknown pointer for the immediate
  782. descendent frame in whose subtree the Target reference (eg anchor with a Target tag)
  783. resides. dwFlags are flags which modify FindFrame's behaviour and
  784. can be any combination of FINDFRAME_FLAGS. In particular, SETTING
  785. FINDFRAME_JUSTTESTEXISTENCE allows the caller to defeat the default
  786. FindFrame behavior of creating a new top level frame named pszTarget,
  787. if pszTarget does not exist.
  788. IMPLEMENTATION:
  789. NOTE: In HTML all anchors and other TARGET tags can occur ONLY in
  790. leaf FRAMES!!
  791. punkContextFrame is significant only if pszTarget is not
  792. a MAGIC target name (_self, _top, _blank, _parent).
  793. Non-MAGIC target names:
  794. first off, this frame should check if it matches pszTarget and return
  795. it's own IUnknown pointer forthwith.
  796. if punkContextFrame is not NULL, all child Frames
  797. except punkContextFrame should be searched (depth first) for
  798. pszTarget with punkContextFrame == NULL. on failure, the parent of this
  799. frame should be recursively called with this frame replacing punkContextFrame.
  800. if this is a top level Frame (so there is no parent), all top level frames
  801. should be called with punkContextFrame == NULL. if this fails, then a new top level
  802. frame should be created (unless FINDFRAME_JUSTTESTEXISTENCE is set in
  803. dwFlags), named pszTarget and its IUnknown returned.
  804. if punkContextFrame is NULL, all child Frames should be searched
  805. depth first for pszTarget. on failure, NULL should be returned.
  806. MAGIC target names:
  807. _self should return the IUnknown of this ITargetFrame
  808. _top should be recursively passed up to the top level ITargetFrame. if
  809. there is no FrameParent, this defaults to _self.
  810. _parent should return the IUnknown of the FrameParent ITargetFrame. if
  811. there is no FrameParent, this defaults to _self.
  812. _blank should be recursively passed up to the top level ITargetFrame,
  813. which should create a unnamed top level frame
  814. ********************************************************************/
  815. STDMETHODIMP CIEFrameAuto::FindFrame(LPCOLESTR pszTargetName,
  816. DWORD dwFlags,
  817. LPUNKNOWN *ppunkTargetFrame)
  818. {
  819. LPTARGETFRAMEPRIV ptgfpTarget = NULL;
  820. LPUNKNOWN punkContextFrame = NULL;
  821. HRESULT hr = E_FAIL;
  822. BOOL fInContext = TRUE;
  823. BOOL fWasMain = FALSE;
  824. TARGET_TYPE targetType;
  825. if (pszTargetName == NULL || *pszTargetName == 0)
  826. pszTargetName = L"_self";
  827. targetType = ParseTargetType(pszTargetName);
  828. if (targetType == TARGET_MAIN)
  829. {
  830. fWasMain = TRUE;
  831. pszTargetName = L"_self";
  832. }
  833. *ppunkTargetFrame = NULL;
  834. // Default behavior:
  835. // If this is a webbar and targeting _main, find frame in _psbProxy and return it
  836. // If this is in browser, find frame relative to ourselves
  837. if (_psb != _psbProxy && fWasMain)
  838. {
  839. // Webbar : Find in context of top frame of proxy
  840. hr = TargetQueryService(_psbProxy, IID_PPV_ARG(ITargetFramePriv, &ptgfpTarget));
  841. }
  842. else
  843. {
  844. // Browser : A normal find in context in ourself
  845. hr = QueryInterface(IID_PPV_ARG(ITargetFramePriv, &ptgfpTarget));
  846. }
  847. if (SUCCEEDED(hr) && ptgfpTarget)
  848. {
  849. if (fInContext)
  850. {
  851. hr = ptgfpTarget->QueryInterface(IID_PPV_ARG(IUnknown, &punkContextFrame));
  852. if (SUCCEEDED(hr))
  853. {
  854. hr = ptgfpTarget->FindFrameInContext(pszTargetName,
  855. punkContextFrame,
  856. dwFlags,
  857. ppunkTargetFrame);
  858. }
  859. }
  860. else
  861. {
  862. hr = ptgfpTarget->FindFrameDownwards(pszTargetName,
  863. dwFlags,
  864. ppunkTargetFrame);
  865. }
  866. }
  867. SAFERELEASE(punkContextFrame);
  868. SAFERELEASE(ptgfpTarget);
  869. if (SUCCEEDED(hr)
  870. && *ppunkTargetFrame == NULL
  871. && !(FINDFRAME_OLDINTERFACE&dwFlags)) hr = S_FALSE;
  872. return hr;
  873. }
  874. // ITargetFramePriv members
  875. /*******************************************************************
  876. NAME: CIEFrameAuto::FindFrameDownwards
  877. SYNOPSIS:
  878. IMPLEMENTATION:
  879. ********************************************************************/
  880. STDMETHODIMP CIEFrameAuto::FindFrameDownwards(LPCOLESTR pszTargetName,
  881. DWORD dwFlags,
  882. LPUNKNOWN *ppunkTargetFrame)
  883. {
  884. return FindFrameInContext(pszTargetName,
  885. NULL,
  886. dwFlags | FINDFRAME_JUSTTESTEXISTENCE,
  887. ppunkTargetFrame);
  888. }
  889. /*******************************************************************
  890. NAME: CIEFrameAuto::FindFrameInContext
  891. SYNOPSIS:
  892. IMPLEMENTATION:
  893. ********************************************************************/
  894. // can this function be any bigger?
  895. STDMETHODIMP CIEFrameAuto::FindFrameInContext(LPCOLESTR pszTargetName,
  896. LPUNKNOWN punkContextFrame,
  897. DWORD dwFlags,
  898. LPUNKNOWN *ppunkTargetFrame)
  899. {
  900. //asserts
  901. TARGET_TYPE targetType;
  902. HRESULT hr = S_OK;
  903. LPUNKNOWN punkParent = NULL;
  904. LPUNKNOWN punkThisFrame = NULL;
  905. LPTARGETFRAMEPRIV ptgfpTargetFrame = NULL;
  906. LPUNKNOWN punkThis = NULL;
  907. targetType = ParseTargetType(pszTargetName);
  908. if (targetType == TARGET_FRAMENAME)
  909. {
  910. hr = _DoNamedTarget(pszTargetName, punkContextFrame, dwFlags, ppunkTargetFrame);
  911. goto exitPoint;
  912. }
  913. // Must be a Magic Target
  914. //for search, first show the search bar and then reach across to get it's TargetFrame
  915. if (targetType == TARGET_SEARCH)
  916. {
  917. SA_BSTRGUID strGuid;
  918. VARIANT vaGuid;
  919. InitFakeBSTR(&strGuid, CLSID_SearchBand);
  920. vaGuid.vt = VT_BSTR;
  921. vaGuid.bstrVal = strGuid.wsz;
  922. //if we're in an explorer bar, use the proxy's pbs
  923. IBrowserService *pbs = _pbs;
  924. if (_psb != _psbProxy)
  925. {
  926. EVAL(SUCCEEDED(_psbProxy->QueryInterface(IID_PPV_ARG(IBrowserService, &pbs))));
  927. }
  928. IUnknown_Exec(pbs, &CGID_ShellDocView, SHDVID_SHOWBROWSERBAR, 1, &vaGuid, NULL);
  929. VARIANT vaPunkBand = {0};
  930. hr = IUnknown_Exec(pbs, &CGID_ShellDocView, SHDVID_GETBROWSERBAR, NULL, NULL, &vaPunkBand);
  931. if (_psb != _psbProxy)
  932. {
  933. ATOMICRELEASE(pbs);
  934. }
  935. if (hr == S_OK)
  936. {
  937. IDeskBand* pband = (IDeskBand*)vaPunkBand.punkVal;
  938. ASSERT(pband);
  939. if (pband)
  940. {
  941. IBrowserBand* pbb;
  942. hr = pband->QueryInterface(IID_PPV_ARG(IBrowserBand, &pbb));
  943. if (SUCCEEDED(hr))
  944. {
  945. // now, get the pidl search pane is navigated to.
  946. // if it's null we have to navigate it to something -- default search url (web search)
  947. // this used to be in CSearchBand::_NavigateOC but caused problems
  948. // if user had dial up networking set up and tried to get to the file search we would
  949. // first set pidl to web search url (_NavigateOC is called by _CreateOCHost) which would
  950. // cause AutoDial dialog to come up and then we would navigate the pane to the file search
  951. // (nt5 bug#186970) reljai -- 6/22/98
  952. VARIANT varPidl = {0};
  953. if (SUCCEEDED(IUnknown_Exec(pbb, &CGID_SearchBand, SBID_GETPIDL, 0, NULL, &varPidl)))
  954. {
  955. ISearchItems* psi;
  956. LPITEMIDLIST pidl = VariantToIDList(&varPidl);
  957. VariantClear(&varPidl);
  958. if (!pidl && SUCCEEDED(IUnknown_QueryService(pbb, SID_SExplorerToolbar, IID_PPV_ARG(ISearchItems, &psi))))
  959. {
  960. // get the default search url
  961. WCHAR wszSearchUrl[INTERNET_MAX_URL_LENGTH];
  962. if (SUCCEEDED(psi->GetDefaultSearchUrl(wszSearchUrl, ARRAYSIZE(wszSearchUrl))))
  963. {
  964. IBandNavigate* pbn;
  965. if (SUCCEEDED(pbb->QueryInterface(IID_PPV_ARG(IBandNavigate, &pbn))))
  966. {
  967. // reuse pidl
  968. IECreateFromPathW(wszSearchUrl, &pidl);
  969. pbn->Select(pidl);
  970. pbn->Release();
  971. }
  972. }
  973. psi->Release();
  974. }
  975. ILFree(pidl);
  976. }
  977. IWebBrowser2* pwb;
  978. hr = pbb->GetObjectBB(IID_PPV_ARG(IWebBrowser2, &pwb));
  979. //set the search pane's opener property
  980. if (SUCCEEDED(hr))
  981. {
  982. IDispatch* pdisp;
  983. if (SUCCEEDED(pwb->get_Document(&pdisp)) && pdisp)
  984. {
  985. IHTMLDocument2* pDoc;
  986. if (SUCCEEDED(pdisp->QueryInterface(IID_PPV_ARG(IHTMLDocument2, &pDoc))) && pDoc)
  987. {
  988. IHTMLWindow2* pWindow;
  989. if (SUCCEEDED(pDoc->get_parentWindow(&pWindow)) && pWindow)
  990. {
  991. VARIANT var;
  992. VariantInit(&var);
  993. var.vt = VT_DISPATCH;
  994. // unknown or dispatch QI?
  995. _omwin.QueryInterface(IID_IUnknown, (void **)&var.pdispVal);
  996. pWindow->put_opener(var);
  997. VariantClear(&var);
  998. pWindow->Release();
  999. }
  1000. pDoc->Release();
  1001. }
  1002. pdisp->Release();
  1003. }
  1004. }
  1005. if (SUCCEEDED(hr))
  1006. {
  1007. hr = pwb->QueryInterface(IID_ITargetFramePriv, (void **)ppunkTargetFrame);
  1008. pwb->Release();
  1009. }
  1010. pbb->Release();
  1011. }
  1012. pband->Release();
  1013. }
  1014. }
  1015. else
  1016. {
  1017. //maybe we're the search bar
  1018. //hack to let search pane know to remember the next navigation
  1019. IUnknown *punkThis;
  1020. if (SUCCEEDED(_psb->QueryInterface(IID_PPV_ARG(IUnknown, &punkThis))))
  1021. {
  1022. hr = QueryInterface(IID_PPV_ARG(ITargetFramePriv, &ptgfpTargetFrame));
  1023. if (SUCCEEDED(hr))
  1024. *ppunkTargetFrame = ptgfpTargetFrame;
  1025. ptgfpTargetFrame = NULL;
  1026. punkThis->Release();
  1027. }
  1028. }
  1029. goto exitPoint;
  1030. }
  1031. // content pane of MediaBar:
  1032. if (targetType == TARGET_MEDIA)
  1033. {
  1034. SA_BSTRGUID strGuid;
  1035. VARIANT vaGuid;
  1036. InitFakeBSTR(&strGuid, CLSID_MediaBand);
  1037. vaGuid.vt = VT_BSTR;
  1038. vaGuid.bstrVal = strGuid.wsz;
  1039. //if we're in an explorer bar, use the proxy's pbs
  1040. IBrowserService *pbs = _pbs;
  1041. if (_psb != _psbProxy)
  1042. {
  1043. EVAL(SUCCEEDED(_psbProxy->QueryInterface(IID_PPV_ARG(IBrowserService, &pbs))));
  1044. }
  1045. IUnknown_Exec(pbs, &CGID_ShellDocView, SHDVID_SHOWBROWSERBAR, 1, &vaGuid, NULL);
  1046. VARIANT vaPunkBand = {0};
  1047. hr = IUnknown_Exec(pbs, &CGID_ShellDocView, SHDVID_GETBROWSERBAR, NULL, NULL, &vaPunkBand);
  1048. if (_psb != _psbProxy)
  1049. {
  1050. ATOMICRELEASE(pbs);
  1051. }
  1052. if (hr == S_OK)
  1053. {
  1054. IDeskBand* pband = (IDeskBand*)vaPunkBand.punkVal;
  1055. ASSERT(pband);
  1056. if (pband)
  1057. {
  1058. IBrowserBand* pbb;
  1059. hr = pband->QueryInterface(IID_PPV_ARG(IBrowserBand, &pbb));
  1060. if (SUCCEEDED(hr))
  1061. {
  1062. IWebBrowser2* pwb;
  1063. hr = pbb->GetObjectBB(IID_PPV_ARG(IWebBrowser2, &pwb));
  1064. //set the media pane's opener property
  1065. if (SUCCEEDED(hr))
  1066. {
  1067. IDispatch* pdisp;
  1068. if (SUCCEEDED(pwb->get_Document(&pdisp)) && pdisp)
  1069. {
  1070. IHTMLDocument2* pDoc;
  1071. if (SUCCEEDED(pdisp->QueryInterface(IID_PPV_ARG(IHTMLDocument2, &pDoc))) && pDoc)
  1072. {
  1073. IHTMLWindow2* pWindow;
  1074. if (SUCCEEDED(pDoc->get_parentWindow(&pWindow)) && pWindow)
  1075. {
  1076. VARIANT var;
  1077. VariantInit(&var);
  1078. var.vt = VT_DISPATCH;
  1079. // are we supposed to QI for dispatch or unknown here?
  1080. _omwin.QueryInterface(IID_IUnknown, (void**)&var.pdispVal);
  1081. pWindow->put_opener(var);
  1082. VariantClear(&var);
  1083. pWindow->Release();
  1084. }
  1085. pDoc->Release();
  1086. }
  1087. pdisp->Release();
  1088. }
  1089. }
  1090. if (SUCCEEDED(hr))
  1091. {
  1092. hr = pwb->QueryInterface(IID_ITargetFramePriv, (void **)ppunkTargetFrame);
  1093. pwb->Release();
  1094. }
  1095. pbb->Release();
  1096. }
  1097. pband->Release();
  1098. }
  1099. }
  1100. else
  1101. {
  1102. ASSERT(0); // means we have no explorer bands at all........
  1103. // but the SHDVID_SHOWBROWSERBAR just before does launch the media bar
  1104. }
  1105. goto exitPoint;
  1106. }
  1107. hr = QueryInterface(IID_PPV_ARG(IUnknown, &punkThis));
  1108. ASSERT(punkThis != NULL);
  1109. if (targetType == TARGET_SELF)
  1110. {
  1111. *ppunkTargetFrame = punkThis;
  1112. // Set punkThis to NULL to prevent Release at exit
  1113. punkThis = NULL;
  1114. }
  1115. else // _blank, _parent, _top
  1116. {
  1117. hr = GetParentFrame(&punkParent);
  1118. if (hr != S_OK) goto exitPoint;
  1119. if (punkParent == NULL)
  1120. {
  1121. if (targetType == TARGET_PARENT || targetType == TARGET_TOP)
  1122. {
  1123. *ppunkTargetFrame = punkThis;
  1124. // Set punkThis to NULL to prevent Release at exit
  1125. punkThis = NULL;
  1126. }
  1127. else // TARGET_BLANK
  1128. {
  1129. if (dwFlags & FINDFRAME_JUSTTESTEXISTENCE)
  1130. {
  1131. // It is the client's responsibility to handle "_blank"
  1132. hr = S_OK;
  1133. }
  1134. else
  1135. {
  1136. // CreateTargetFrame will not work with AOL 3.01 clients
  1137. // so we must return E_FAIL
  1138. hr = E_FAIL;
  1139. }
  1140. *ppunkTargetFrame = NULL;
  1141. }
  1142. }
  1143. else // punkParent != NULL
  1144. {
  1145. // Handle parent ourself, defer _top and _blank to top level frame
  1146. if (targetType == TARGET_PARENT)
  1147. {
  1148. *ppunkTargetFrame = punkParent;
  1149. // Set punkThisFrame to NULL to prevent Release at exit
  1150. punkParent = NULL;
  1151. }
  1152. else
  1153. {
  1154. hr = punkParent->QueryInterface(IID_PPV_ARG(ITargetFramePriv, &ptgfpTargetFrame));
  1155. if (hr != S_OK)
  1156. goto exitPoint;
  1157. hr = ptgfpTargetFrame->FindFrameInContext(pszTargetName,
  1158. punkThis,
  1159. dwFlags,
  1160. ppunkTargetFrame);
  1161. }
  1162. }
  1163. }
  1164. exitPoint:
  1165. SAFERELEASE(punkThis);
  1166. SAFERELEASE(punkThisFrame);
  1167. SAFERELEASE(ptgfpTargetFrame);
  1168. SAFERELEASE(punkParent);
  1169. return hr;
  1170. }
  1171. HRESULT CIEFrameAuto::_GetOleObject(IOleObject** ppobj)
  1172. {
  1173. HRESULT hres = E_UNEXPECTED;
  1174. if (_pbs) {
  1175. hres = _pbs->GetOleObject(ppobj);
  1176. }
  1177. return hres;
  1178. }
  1179. // ITargetFrame implementation for backwards compatibility
  1180. HRESULT CIEFrameAuto::CTargetFrame::QueryInterface(REFIID riid, LPVOID * ppvObj)
  1181. {
  1182. CIEFrameAuto* pie = IToClass(CIEFrameAuto, _TargetFrame, this);
  1183. return pie->QueryInterface(riid, ppvObj);
  1184. }
  1185. ULONG CIEFrameAuto::CTargetFrame::AddRef(void)
  1186. {
  1187. CIEFrameAuto* pie = IToClass(CIEFrameAuto, _TargetFrame, this);
  1188. return pie->AddRef();
  1189. }
  1190. ULONG CIEFrameAuto::CTargetFrame::Release(void)
  1191. {
  1192. CIEFrameAuto* pie = IToClass(CIEFrameAuto, _TargetFrame, this);
  1193. return pie->Release();
  1194. }
  1195. /*******************************************************************
  1196. NAME: CIEFrameAuto::CTargetFrame::SetFrameName
  1197. SYNOPSIS: Sets the Frame Name. Frees current one if exists.
  1198. ********************************************************************/
  1199. STDMETHODIMP CIEFrameAuto::CTargetFrame::SetFrameName(LPCOLESTR pszFrameName)
  1200. {
  1201. CIEFrameAuto* pie = IToClass(CIEFrameAuto, _TargetFrame, this);
  1202. return pie->SetFrameName(pszFrameName);
  1203. }
  1204. /*******************************************************************
  1205. NAME: CIEFrameAuto::CTargetFrame::GetFrameName
  1206. SYNOPSIS: Gets the Frame Name. Allocates a copy (this is an
  1207. [OUT] parameter
  1208. ********************************************************************/
  1209. STDMETHODIMP CIEFrameAuto::CTargetFrame::GetFrameName(WCHAR **ppszFrameName)
  1210. {
  1211. CIEFrameAuto* pie = IToClass(CIEFrameAuto, _TargetFrame, this);
  1212. return pie->GetFrameName(ppszFrameName);
  1213. }
  1214. /*******************************************************************
  1215. NAME: CIEFrameAuto::CTargetFrame::GetParentFrame
  1216. SYNOPSIS: Gets an the IUnknown pointer of the parent frame, or
  1217. NULL if this is a top level frame. This pointer must be Released
  1218. by Caller after use.
  1219. IMPLEMENTATION:
  1220. A Frame Container is required to implement ITargetFrame::GetParentFrame and
  1221. implement GetParentFrame by returning the IUnknown pointer of the Browser that
  1222. hosts it. A Browser implements GetParentFrame by returning NULL if it's
  1223. top level or calling GetParentFrame on its Container if it is embedded.
  1224. ********************************************************************/
  1225. STDMETHODIMP CIEFrameAuto::CTargetFrame::GetParentFrame(LPUNKNOWN *ppunkParentFrame)
  1226. {
  1227. CIEFrameAuto* pie = IToClass(CIEFrameAuto, _TargetFrame, this);
  1228. return pie->GetParentFrame(ppunkParentFrame);
  1229. }
  1230. /*******************************************************************
  1231. NAME: CIEFrameAuto::CTargetFrame::FindFrame
  1232. SYNOPSIS: Gets an the IUnknown pointer of the frame referenced
  1233. by pszTarget. This pointer must be Released by Caller after use.
  1234. punkContextFrame, if not NULL, is the IUnknown pointer for the immediate
  1235. descendent frame in whose subtree the Target reference (eg anchor with a Target tag)
  1236. resides. dwFlags are flags which modify FindFrame's behaviour and
  1237. can be any combination of FINDFRAME_FLAGS. In particular, SETTING
  1238. FINDFRAME_JUSTTESTEXISTENCE allows the caller to defeat the default
  1239. FindFrame behavior of creating a new top level frame named pszTarget,
  1240. if pszTarget does not exist.
  1241. IMPLEMENTATION:
  1242. NOTE: In HTML all anchors and other TARGET tags can occur ONLY in
  1243. leaf FRAMES!!
  1244. punkContextFrame is significant only if pszTarget is not
  1245. a MAGIC target name (_self, _top, _blank, _parent).
  1246. Non-MAGIC target names:
  1247. first off, this frame should check if it matches pszTarget and return
  1248. it's own IUnknown pointer forthwith.
  1249. if punkContextFrame is not NULL, all child Frames
  1250. except punkContextFrame should be searched (depth first) for
  1251. pszTarget with punkContextFrame == NULL. on failure, the parent of this
  1252. frame should be recursively called with this frame replacing punkContextFrame.
  1253. if this is a top level Frame (so there is no parent), all top level frames
  1254. should be called with punkContextFrame == NULL. if this fails, then a new top level
  1255. frame should be created (unless FINDFRAME_JUSTTESTEXISTENCE is set in
  1256. dwFlags), named pszTarget and its IUnknown returned.
  1257. if punkContextFrame is NULL, all child Frames should be searched
  1258. depth first for pszTarget. on failure, NULL should be returned.
  1259. MAGIC target names:
  1260. _self should return the IUnknown of this ITargetFrame
  1261. _top should be recursively passed up to the top level ITargetFrame. if
  1262. there is no FrameParent, this defaults to _self.
  1263. _parent should return the IUnknown of the FrameParent ITargetFrame. if
  1264. there is no FrameParent, this defaults to _self.
  1265. _blank should be recursively passed up to the top level ITargetFrame,
  1266. which should create a unnamed top level frame
  1267. ********************************************************************/
  1268. STDMETHODIMP CIEFrameAuto::CTargetFrame::FindFrame(LPCOLESTR pszTargetName,
  1269. LPUNKNOWN punkContextFrame,
  1270. DWORD dwFlags,
  1271. LPUNKNOWN *ppunkTargetFrame)
  1272. {
  1273. CIEFrameAuto* pie = IToClass(CIEFrameAuto, _TargetFrame, this);
  1274. return pie->FindFrame(pszTargetName, dwFlags|FINDFRAME_OLDINTERFACE, ppunkTargetFrame);
  1275. }
  1276. /*******************************************************************
  1277. NAME: CIEFrameAuto::CTargetFrame::RemoteNavigate
  1278. SYNOPSIS: Used in response to WM_COPYDATA message with dwData
  1279. equal to TF_NAVIGATE. Does a FindFrame (named
  1280. target only) and if frame is not found returns
  1281. S_FALSE. If found, returns S_OK and fires off the
  1282. navigate. cLength is number of ULONGs in pulData
  1283. TODO: Relies on RemoteNavigate member of top level MSHTML
  1284. docobject host. Need to write the equivalent code
  1285. to work if top level frame contains some other DocObject.
  1286. Post,etc require help from bindstatuscallback.
  1287. ********************************************************************/
  1288. HRESULT CIEFrameAuto::CTargetFrame::RemoteNavigate(ULONG cLength,ULONG *pulData)
  1289. {
  1290. // FEATURE chrisfra 10/22/96 - this is now here purely for backwards compatibility and
  1291. // should be removed for ie4.0
  1292. return E_FAIL;
  1293. }
  1294. /*******************************************************************
  1295. NAME: CIEFrameAuto::CTargetFrame::SetFrameSrc
  1296. SYNOPSIS: Sets the Frame original SRC url. Frees current one if exists.
  1297. ********************************************************************/
  1298. HRESULT CIEFrameAuto::CTargetFrame::SetFrameSrc(LPCOLESTR pszFrameSrc)
  1299. {
  1300. CIEFrameAuto* pie = IToClass(CIEFrameAuto, _TargetFrame, this);
  1301. return pie->SetFrameSrc(pszFrameSrc);
  1302. }
  1303. /*******************************************************************
  1304. NAME: CIEFrameAuto::CTargetFrame::GetFrameSrc
  1305. SYNOPSIS: Gets the Frame original URL. Allocates a copy (this is an
  1306. [OUT] parameter
  1307. NOTES: If we are at top level, SRC is dynamic, so ask our
  1308. contained DocObject to do it for us.
  1309. ********************************************************************/
  1310. HRESULT CIEFrameAuto::CTargetFrame::GetFrameSrc(WCHAR **ppszFrameSrc)
  1311. {
  1312. CIEFrameAuto* pie = IToClass(CIEFrameAuto, _TargetFrame, this);
  1313. return pie->GetFrameSrc(ppszFrameSrc);
  1314. }
  1315. /*******************************************************************
  1316. NAME: CIEFrameAuto::CTargetFrame::GetFramesContainer
  1317. SYNOPSIS: Returns an addref'ed pointer to the LPOLECONTAINER
  1318. for our nested frames. Can be NULL.
  1319. ********************************************************************/
  1320. HRESULT CIEFrameAuto::CTargetFrame::GetFramesContainer(LPOLECONTAINER *ppContainer)
  1321. {
  1322. CIEFrameAuto* pie = IToClass(CIEFrameAuto, _TargetFrame, this);
  1323. return pie->GetFramesContainer(ppContainer);
  1324. }
  1325. /*******************************************************************
  1326. NAME: CIEFrameAuto::CTargetFrame::SetFrameOptions
  1327. SYNOPSIS: Sets the Frame Options.
  1328. ********************************************************************/
  1329. HRESULT CIEFrameAuto::CTargetFrame::SetFrameOptions(DWORD dwFlags)
  1330. {
  1331. CIEFrameAuto* pie = IToClass(CIEFrameAuto, _TargetFrame, this);
  1332. return pie->SetFrameOptions(dwFlags);
  1333. }
  1334. /*******************************************************************
  1335. NAME: CIEFrameAuto::CTargetFrame::GetFrameOptions
  1336. SYNOPSIS: Returns the frame options
  1337. ********************************************************************/
  1338. HRESULT CIEFrameAuto::CTargetFrame::GetFrameOptions(LPDWORD pdwFlags)
  1339. {
  1340. CIEFrameAuto* pie = IToClass(CIEFrameAuto, _TargetFrame, this);
  1341. return pie->GetFrameOptions(pdwFlags);
  1342. }
  1343. /*******************************************************************
  1344. NAME: CIEFrameAuto::CTargetFrame::SetFrameMargins
  1345. SYNOPSIS: Sets the Frame margins.
  1346. ********************************************************************/
  1347. HRESULT CIEFrameAuto::CTargetFrame::SetFrameMargins(DWORD dwWidth, DWORD dwHeight)
  1348. {
  1349. CIEFrameAuto* pie = IToClass(CIEFrameAuto, _TargetFrame, this);
  1350. return pie->SetFrameMargins(dwWidth, dwHeight);
  1351. }
  1352. /*******************************************************************
  1353. NAME: CIEFrameAuto::CTargetFrame::GetFrameMargins
  1354. SYNOPSIS: Returns the frame margins
  1355. ********************************************************************/
  1356. HRESULT CIEFrameAuto::CTargetFrame::GetFrameMargins(LPDWORD pdwWidth, LPDWORD pdwHeight)
  1357. {
  1358. CIEFrameAuto* pie = IToClass(CIEFrameAuto, _TargetFrame, this);
  1359. return pie->GetFrameMargins(pdwWidth, pdwHeight);
  1360. }
  1361. /*******************************************************************
  1362. NAME: CIEFrameAuto::FindBrowserByIndex
  1363. SYNOPSIS: Returns an IUnknown that points to a Browser that
  1364. has the requested index
  1365. ********************************************************************/
  1366. HRESULT CIEFrameAuto::FindBrowserByIndex(DWORD dwID,IUnknown **ppunkBrowser)
  1367. {
  1368. HRESULT hr = S_OK;
  1369. IOleContainer * poc = NULL;
  1370. IBrowserService *pbs;
  1371. ASSERT(ppunkBrowser);
  1372. *ppunkBrowser = NULL;
  1373. if (!_psb)
  1374. return E_FAIL;
  1375. // first check self
  1376. if(SUCCEEDED(_psb->QueryInterface(IID_PPV_ARG(IBrowserService, &pbs))))
  1377. {
  1378. ASSERT(pbs);
  1379. if(dwID == pbs->GetBrowserIndex())
  1380. {
  1381. // this is the one...
  1382. *ppunkBrowser = (IUnknown *)pbs;
  1383. goto exitPoint;
  1384. }
  1385. SAFERELEASE(pbs);
  1386. }
  1387. hr = GetFramesContainer(&poc);
  1388. if (SUCCEEDED(hr) && poc)
  1389. {
  1390. IEnumUnknown *penum = NULL;
  1391. hr = E_FAIL;
  1392. if (S_OK != poc->EnumObjects(OLECONTF_EMBEDDINGS, &penum) || penum == NULL)
  1393. goto exitPoint;
  1394. IUnknown *punk;
  1395. while (S_OK == penum->Next(1, &punk, NULL))
  1396. {
  1397. if (punk == NULL)
  1398. break;
  1399. ITargetFramePriv *ptf;
  1400. if (SUCCEEDED(punk->QueryInterface(IID_PPV_ARG(ITargetFramePriv, &ptf))))
  1401. {
  1402. ASSERT(ptf);
  1403. hr = ptf->FindBrowserByIndex(dwID, ppunkBrowser);
  1404. ptf->Release();
  1405. }
  1406. punk->Release();
  1407. if (SUCCEEDED(hr)) //foundit!
  1408. break;
  1409. }
  1410. // Native frames - no WebBrowser OC in frame. Note that
  1411. // if a WebOC is included on a web page with an <OBJECT>
  1412. // tag, navigations in the WebOC will be placed in the travel
  1413. // log. However, since the WebOC does not currently support
  1414. // ITravelLogClient, back and forward will not work correctly.
  1415. // The WebOC will need to be updated to support ITravelLogClient.
  1416. //
  1417. if (FAILED(hr))
  1418. {
  1419. IHTMLDocument2 *pDoc;
  1420. if (SUCCEEDED(poc->QueryInterface(IID_PPV_ARG(IHTMLDocument2, &pDoc))))
  1421. {
  1422. IHTMLWindow2 *pWnd;
  1423. if (SUCCEEDED(pDoc->get_parentWindow(&pWnd)))
  1424. {
  1425. IHTMLWindow2 *pTop;
  1426. if (SUCCEEDED(pWnd->get_top(&pTop)))
  1427. {
  1428. ITravelLogClient *ptlc;
  1429. if (SUCCEEDED(pTop->QueryInterface(IID_PPV_ARG(ITravelLogClient, &ptlc))))
  1430. {
  1431. hr = ptlc->FindWindowByIndex(dwID, ppunkBrowser);
  1432. ptlc->Release();
  1433. }
  1434. pTop->Release();
  1435. }
  1436. pWnd->Release();
  1437. }
  1438. pDoc->Release();
  1439. }
  1440. }
  1441. SAFERELEASE(penum);
  1442. poc->Release();
  1443. }
  1444. else
  1445. {
  1446. hr = E_FAIL;
  1447. }
  1448. exitPoint:
  1449. return hr;
  1450. }
  1451. // External helper function for TRIDENT when it stands alone w/o the steely thews of
  1452. // shdocvw CIEFrameAuto to shield it's pityfull body.
  1453. STDAPI HlinkFindFrame(LPCWSTR pszFrameName, LPUNKNOWN *ppunk)
  1454. {
  1455. HRESULT hres = E_FAIL;
  1456. *ppunk = NULL;
  1457. if (pszFrameName)
  1458. {
  1459. switch (ParseTargetType(pszFrameName))
  1460. {
  1461. case TARGET_FRAMENAME:
  1462. hres = _TargetTopLevelWindows(NULL, pszFrameName, FINDFRAME_JUSTTESTEXISTENCE, ppunk);
  1463. break;
  1464. case TARGET_BLANK:
  1465. hres = S_FALSE;
  1466. break;
  1467. }
  1468. }
  1469. return hres;
  1470. }