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.

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