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.

1627 lines
53 KiB

  1. #include "priv.h"
  2. #include "resource.h"
  3. #include "hlframe.h"
  4. #include "bindcb.h"
  5. #include "winlist.h"
  6. #include "iface.h"
  7. #include "shdocfl.h"
  8. #include <optary.h>
  9. #include <mluisupp.h>
  10. #define DM_SHELLEXECOBJECT 0x80000000
  11. // flags for SHDVID_DOCFAMILYCHARSET communication
  12. #define DFC_URLCHARSET 1
  13. #ifdef FEATURE_PICS
  14. #include "dochost.h" /* for IID_IsPicsBrowser */
  15. #endif
  16. #ifdef DEBUG
  17. extern DWORD g_dwPerf;
  18. #endif
  19. #define DM_HLINKTRACE DM_TRACE
  20. #define DM_WEBCHECKDRT 0
  21. #define JMPMSG(psz, psz2) TraceMsg(0, "shlf TR-CDOV::%s %s", psz, psz2)
  22. #define JMPMSG2(psz, x) TraceMsg(0, "shlf TR-CDOV::%s %x", psz, x)
  23. #define DOFMSG(psz) TraceMsg(0, "shlf TR-DOF::%s", psz)
  24. #define DOFMSG2(psz, x) TraceMsg(0, "shlf TR-DOF::%s %x", psz, x)
  25. #define URLMSG(psz) TraceMsg(0, "shlf TR-DOF::%s", psz)
  26. #define URLMSG2(psz, x) TraceMsg(0, "shlf TR-DOF::%s %x", psz, x)
  27. #define URLMSG3(psz, x, y) TraceMsg(0, "shlf TR-DOF::%s %x %x", psz, x, y)
  28. #define BSCMSG(psz, i, j) TraceMsg(0, "shlf TR-BSC::%s %x %x", psz, i, j)
  29. #define BSCMSG3(psz, i, j, k) TraceMsg(0, "shlf TR-BSC::%s %x %x %x", psz, i, j, k)
  30. #define BSCMSGS(psz, sz) TraceMsg(0, "shlf TR-BSC::%s %s", psz, sz)
  31. #define OIPSMSG(psz) TraceMsg(0, "shlf TR-OIPS::%s", psz)
  32. #define OIPSMSG3(psz, sz, p) TraceMsg(0, "shlf TR-OIPS::%s %s,%x", psz, sz,p)
  33. #define REFMSG0(psz) TraceMsg(0, "shlf TR-CDOV::%s", psz)
  34. #define REFMSG(psz, cRef) TraceMsg(0, "shlf TR-CDOV::%s new _cRef==%d", psz, cRef)
  35. #define REFMSG2(psz, if, cRef) TraceMsg(0, "shlf TR-CDOV::%s(%s) new _cRef==%d", psz, if, cRef)
  36. #define VIEWMSG(psz) TraceMsg(0, "shlf TR CDOV::%s", psz)
  37. #define VIEWMSG2(psz,xx) TraceMsg(0, "shlf TR CDOV::%s %x", psz,xx)
  38. #define CACHEMSG(psz, d) TraceMsg(0, "shlf TR CDocObjectCtx::%s %d", psz, d)
  39. #define HFRMMSG(psz) TraceMsg(TF_SHDNAVIGATE, "shlf HFRM::%s", psz)
  40. #define HFRMMSG2(psz, x, y) TraceMsg(TF_SHDNAVIGATE, "shlf HFRM::%s %x %x", psz, x, y)
  41. #define MNKMSG(psz, psz2) TraceMsg(0, "shlf MNK::%s (%s)", psz, psz2)
  42. #define SERVMSG(psz, x, y) TraceMsg(0, "shlf SERV::%s %x %x", psz, x, y)
  43. #define KEY_BINDCONTEXTPARAM _T("BIND_CONTEXT_PARAM")
  44. #define SZ_DWNBINDINFO_OBJECTPARAM _T("__DWNBINDINFO")
  45. BOOL g_fHlinkDLLLoaded = FALSE; // must be per-process
  46. STDAPI HlinkFrameNavigate(DWORD grfHLNF, IBindCtx *pbc,
  47. IBindStatusCallback *pibsc,
  48. IHlink* pihlNavigate,
  49. IHlinkBrowseContext *pihlbc);
  50. STDAPI HlinkFrameNavigateNHL(DWORD grfHLNF, IBindCtx *pbc,
  51. IBindStatusCallback *pibsc,
  52. LPCWSTR pszTargetFrame,
  53. LPCWSTR pszUrl,
  54. LPCWSTR pszLocation);
  55. // IHlinkFrame members
  56. HRESULT CIEFrameAuto::SetBrowseContext(IHlinkBrowseContext *pihlbc)
  57. {
  58. if (pihlbc)
  59. pihlbc->AddRef();
  60. if (_phlbc)
  61. {
  62. if (_dwRegHLBC)
  63. {
  64. _phlbc->Revoke(_dwRegHLBC);
  65. _dwRegHLBC = 0;
  66. }
  67. _phlbc->Release();
  68. }
  69. _phlbc = pihlbc;
  70. return NOERROR;
  71. }
  72. HRESULT CIEFrameAuto::GetBrowseContext(IHlinkBrowseContext **ppihlbc)
  73. {
  74. TraceMsg(0, "shlf TR ::GetBrowseContext called");
  75. *ppihlbc = _phlbc;
  76. if (_phlbc)
  77. {
  78. _phlbc->AddRef();
  79. return S_OK;
  80. }
  81. return E_FAIL;
  82. }
  83. void CIEFrameAuto::_SetPendingNavigateContext(IBindCtx *pbc, IBindStatusCallback *pibsc)
  84. {
  85. if (_pbscPending)
  86. {
  87. _pbscPending->Release();
  88. _pbscPending = NULL;
  89. }
  90. if (_pbcPending)
  91. {
  92. _pbcPending->Release();
  93. _pbcPending = NULL;
  94. }
  95. if (pibsc)
  96. {
  97. _pbscPending = pibsc;
  98. _pbscPending->AddRef();
  99. }
  100. if (pbc)
  101. {
  102. // as long as we are cacheing the pending BindCtx, if it specifies
  103. // a shortcut URL we need to cache that too. (IE:98431)
  104. IUnknown * pUnk = NULL;
  105. IHtmlLoadOptions * pHtmlLoadOptions = NULL;
  106. _pbcPending = pbc;
  107. _pbcPending->AddRef();
  108. pbc->GetObjectParam(_T("__HTMLLOADOPTIONS"), &pUnk);
  109. if (pUnk)
  110. {
  111. pUnk->QueryInterface(IID_IHtmlLoadOptions, (void **) &pHtmlLoadOptions);
  112. if (pHtmlLoadOptions)
  113. {
  114. TCHAR achCacheFile[MAX_PATH+1];
  115. ULONG cchCacheFile = ARRAYSIZE(achCacheFile)-1;
  116. memset(&achCacheFile, 0, (cchCacheFile+1)*sizeof(TCHAR) );
  117. // now determine if this is a shortcut-initiated load
  118. pHtmlLoadOptions->QueryOption(HTMLLOADOPTION_INETSHORTCUTPATH,
  119. &achCacheFile,
  120. &cchCacheFile);
  121. if (_pwszShortcutPathPending)
  122. LocalFree(_pwszShortcutPathPending);
  123. _pwszShortcutPathPending = StrDup(achCacheFile);
  124. pHtmlLoadOptions->Release();
  125. }
  126. pUnk->Release();
  127. }
  128. }
  129. }
  130. //
  131. // NavigateContext is a set of parameters passed from one CIEFrameAuto
  132. // to another.
  133. //
  134. void CIEFrameAuto::_ActivatePendingNavigateContext()
  135. {
  136. if (_pbsc)
  137. {
  138. _pbsc->Release();
  139. _pbsc = NULL;
  140. }
  141. if (_pbc)
  142. {
  143. _pbc->Release();
  144. _pbc = NULL;
  145. }
  146. if (_pwszShortcutPath)
  147. {
  148. LocalFree(_pwszShortcutPath);
  149. _pwszShortcutPath = NULL;
  150. }
  151. if (_pbscPending)
  152. {
  153. _pbsc = _pbscPending;
  154. _pbscPending = NULL;
  155. }
  156. if (_pbcPending)
  157. {
  158. _pbc = _pbcPending;
  159. _pbcPending = NULL;
  160. }
  161. if (_pwszShortcutPathPending)
  162. {
  163. _pwszShortcutPath = _pwszShortcutPathPending;
  164. _pwszShortcutPathPending = NULL;
  165. }
  166. }
  167. // Called to guarantee a newly created HLinkFrame's window is
  168. // visible after the navigate.
  169. HRESULT ShowHlinkFrameWindow(IUnknown *pUnkTargetHlinkFrame)
  170. {
  171. IWebBrowserApp* pdie;
  172. HRESULT hres = pUnkTargetHlinkFrame->QueryInterface(IID_PPV_ARG(IWebBrowserApp, &pdie));
  173. if (SUCCEEDED(hres))
  174. {
  175. pdie->put_Visible(TRUE);
  176. pdie->Release();
  177. }
  178. return hres;
  179. }
  180. HRESULT CIEFrameAuto::_NavigateMagnum(DWORD grfHLNF, IBindCtx *pbc, IBindStatusCallback *pibsc, LPCWSTR pszTargetName, LPCWSTR pszUrl, LPCWSTR pszLocation, IHlink *pihlNavigate, IMoniker *pmkTarget)
  181. {
  182. HRESULT hres = NOERROR;
  183. HFRMMSG2("Navigate called", grfHLNF, pihlNavigate);
  184. BOOL fNavigateForReal = pszUrl || (pihlNavigate && (pihlNavigate != (IHlink*)-1));
  185. _fSuppressHistory = _psbProxy != _psb; // no history for search band, etc
  186. _fSuppressSelect = _psbProxy != _psb; // no need to record select pidl
  187. if (grfHLNF != (DWORD)-1)
  188. {
  189. if (SHHLNF_WRITENOHISTORY & grfHLNF)
  190. {
  191. _fSuppressHistory = TRUE;
  192. }
  193. if (SHHLNF_NOAUTOSELECT & grfHLNF)
  194. {
  195. _fSuppressSelect = TRUE;
  196. }
  197. }
  198. if (pbc == NULL && pibsc == NULL && pihlNavigate == NULL && pszUrl == NULL)
  199. {
  200. //
  201. // This is a private interface so that mshtml can do navigation
  202. // if it is hosted by the shell. When IHlinkBrowseContext is implemented
  203. // in the shell this special code can be removed and the associated
  204. // code in mshtml that calls Navigate with these special parameters
  205. // can be removed so that it just goes through the
  206. // IHlinkBrowseContext->SetCurrentHlink interface.
  207. //
  208. // We also use this private mechanism to release the navigation
  209. // context with grfHLNF==0.
  210. //
  211. switch (grfHLNF&~(SHHLNF_WRITENOHISTORY|SHHLNF_NOAUTOSELECT))
  212. {
  213. case HLNF_NAVIGATINGBACK:
  214. hres = _BrowseObject(PIDL_LOCALHISTORY, SBSP_SAMEBROWSER|SBSP_NAVIGATEBACK);
  215. break;
  216. case HLNF_NAVIGATINGFORWARD:
  217. hres = _BrowseObject(PIDL_LOCALHISTORY, SBSP_SAMEBROWSER|SBSP_NAVIGATEFORWARD);
  218. break;
  219. case 0:
  220. _ActivatePendingNavigateContext();
  221. break;
  222. default:
  223. hres = E_INVALIDARG;
  224. break;
  225. }
  226. return hres;
  227. }
  228. #ifdef FEATURE_PICS
  229. /* As part of checking ratings, the PICS code will silently download the
  230. * root document of a site to look for rating labels in it. If that's a
  231. * frameset page, Trident will create OCXs for the subframes and try to
  232. * navigate them, which will invoke ratings checks for them and cause
  233. * infinite recursion. So here we check to see if our top-level browser
  234. * is really this PICS download, and if it is, we don't do any navigation.
  235. */
  236. IUnknown *punkPics;
  237. if (SUCCEEDED(QueryService(SID_STopLevelBrowser, IID_IsPicsBrowser, (void **)&punkPics)))
  238. {
  239. punkPics->Release();
  240. return S_OK;
  241. }
  242. #endif
  243. //
  244. // If we've got this call while we are busy (EnableModeless is FALSE),
  245. // we should just bail here (instead of doing somthing and let _JumpTo
  246. // call fail.
  247. //
  248. // This can happen if someone has a window.location="foobar.htm" in their unload
  249. // event handler.
  250. if (fNavigateForReal && !(grfHLNF & HLNF_OPENINNEWWINDOW))
  251. {
  252. // If _pbs is NULL, it is bad news; we can't navigate.
  253. // An allowable reason for this condition is that someone has called CIEFrameAuto::Quit()
  254. // and we are in the process of shutting down.
  255. //
  256. if (_pbs == NULL)
  257. {
  258. if (_fQuitInProgress)
  259. {
  260. TraceMsg(TF_WARNING, "CIEFrameAuto::_NavigateMagnum quitting due to browser closing.");
  261. return S_OK;
  262. }
  263. TraceMsg(TF_WARNING, "CIEFrameAuto::_NavigateMagnum _pbs is NULL, but we are not shutting down.");
  264. return E_FAIL;
  265. }
  266. // If we have a _pbs but the browser says that it can't navigate now, then return S_FALSE.
  267. //
  268. else if (_pbs->CanNavigateNow() != S_OK)
  269. {
  270. TraceMsg(TF_WARNING, "CIEFrameAuto::Navigate CanNavigateNow returns non S_OK, bail out.");
  271. return S_FALSE;
  272. }
  273. }
  274. //
  275. // This Navigate method is not re-entrant (because of _SetPendingNavigateContext)
  276. //
  277. if (_fBusy)
  278. {
  279. TraceMsg(DM_WARNING, "CIEA::Navigate re-entered. Returning E_FAIL");
  280. return E_FAIL;
  281. }
  282. _fBusy = TRUE;
  283. //
  284. // HACK: To let Webcheck DRT go.
  285. //
  286. if (fNavigateForReal && !(grfHLNF & HLNF_OPENINNEWWINDOW))
  287. {
  288. TraceMsg(DM_WEBCHECKDRT, "CIFA::Navigate calling _CancelPendingNavigation");
  289. VARIANT var = { 0 };
  290. var.vt = VT_I4;
  291. var.lVal = TRUE; // synchronous
  292. _CancelPendingNavigation(&var);
  293. }
  294. if (pszUrl && SHRestricted2(REST_NOFILEURL, NULL, 0) && PathIsFilePath(pszUrl))
  295. {
  296. TCHAR szPath[MAX_URL_STRING];
  297. SHUnicodeToTChar(pszUrl, szPath, ARRAYSIZE(szPath));
  298. MLShellMessageBox(NULL, MAKEINTRESOURCE(IDS_SHURL_ERR_PARSE_NOTALLOWED),
  299. szPath, MB_OK | MB_ICONERROR, szPath);
  300. _fBusy = FALSE;
  301. return E_ACCESSDENIED;
  302. }
  303. _SetPendingNavigateContext(pbc, pibsc);
  304. #ifdef DEBUG
  305. g_dwPerf = GetCurrentTime();
  306. #endif
  307. if (pihlNavigate == (IHlink*)-1)
  308. {
  309. //
  310. // HACK: -1 means "release the navigation state".
  311. // CDocObjectHost::_CancelPendingNavigation is the only caller.
  312. // It Exec's SBCMDID_CANCELNAVIGATION which will asynchronously
  313. // cancel the pending navigation. Therefore, we no longer need
  314. // to call _CancelPendingNavigation here. (SatoNa)
  315. //
  316. // _CancelPendingNavigation();
  317. }
  318. else if (pihlNavigate || pszUrl)
  319. {
  320. hres = S_OK;
  321. if (SUCCEEDED(hres))
  322. {
  323. if ((grfHLNF & HLNF_EXTERNALNAVIGATE) && (grfHLNF & HLNF_NAVIGATINGBACK))
  324. GoBack();
  325. else if ((grfHLNF & HLNF_EXTERNALNAVIGATE) && (grfHLNF & HLNF_NAVIGATINGFORWARD))
  326. GoForward();
  327. else
  328. {
  329. hres = _JumpTo(pbc,(LPWSTR) pszLocation, grfHLNF, pibsc, pihlNavigate, pszTargetName, pszUrl);
  330. if (FAILED(hres))
  331. {
  332. TraceMsg(DM_ERROR, "IEAuto::Navigate _JumpTo failed %x", hres);
  333. }
  334. }
  335. if (pihlNavigate)
  336. {
  337. //
  338. // Hopefully, we'll come up with a clean solution to
  339. // solve this problem nicely. I made a proposal to NatBro/SriniK
  340. // that CreateHlink will CoCreateInstance IHlink so that OLE
  341. // LoadLibrary it and maintains it as an InProc server. (SatoNa)
  342. //
  343. // HACK: If we AddRef to IHlink, we need to make it sure that
  344. // HLINK.DLL is stay loaded even though the DocObject InProc
  345. // server (that implicitly links to HLINK.DLL) is unloaded.
  346. //
  347. if (!g_fHlinkDLLLoaded)
  348. {
  349. LoadLibrary(TEXT("hlink.dll"));
  350. g_fHlinkDLLLoaded = TRUE;
  351. }
  352. }
  353. }
  354. else
  355. {
  356. TraceMsg(DM_ERROR, "CIEFA::Nav phl->GetMonRef failed %x", hres);
  357. }
  358. }
  359. _fBusy = FALSE;
  360. HFRMMSG2("Navigate returning", hres, 0);
  361. if (SUCCEEDED(hres) && (pihlNavigate != (IHlink*)-1))
  362. {
  363. if (grfHLNF & HLNF_EXTERNALNAVIGATE)
  364. {
  365. HWND hwndFrame;
  366. _psb->GetWindow(&hwndFrame);
  367. if (_phlbc)
  368. {
  369. // if we have a browse context, then we're navigating from it and
  370. // we should size our window to match it.
  371. HLBWINFO hlbwi;
  372. hlbwi.cbSize = SIZEOF(hlbwi);
  373. if (SUCCEEDED(_phlbc->GetBrowseWindowInfo(&hlbwi)) &&
  374. (hlbwi.grfHLBWIF & HLBWIF_HASFRAMEWNDINFO))
  375. {
  376. WINDOWPLACEMENT wp;
  377. wp.length = sizeof(WINDOWPLACEMENT);
  378. GetWindowPlacement(hwndFrame, &wp);
  379. wp.rcNormalPosition = hlbwi.rcFramePos;
  380. wp.showCmd = (hlbwi.grfHLBWIF & HLBWIF_FRAMEWNDMAXIMIZED)
  381. ? SW_SHOWMAXIMIZED : SW_SHOWNORMAL;
  382. // This is not broken in AOL because this
  383. // is an external navigate (word has cocreateinstance()d
  384. // Internet.Explorer and navigated it.
  385. //
  386. SetWindowPlacement(hwndFrame, &wp);
  387. }
  388. // Register the hlinkframe interface with the browse context, if it has not already
  389. // been registered
  390. if (_dwRegHLBC == 0)
  391. _phlbc->Register(0, (IHlinkFrame *) this, pmkTarget, &_dwRegHLBC);
  392. // add the link to browse context and
  393. // REVIEW: need to pass the proper friendly name
  394. _phlbc->OnNavigateHlink(grfHLNF, pmkTarget, pszLocation, NULL, NULL);
  395. }
  396. put_Visible(TRUE);
  397. SetForegroundWindow(hwndFrame);
  398. }
  399. //
  400. // According to SriniK, we need to call IHlinkSite::OnNavigationComplete
  401. // before returning from IHlinkFrame::Navigate with S_OK. (SatoNa)
  402. //
  403. if (pihlNavigate)
  404. {
  405. BOOL fExternal = FALSE;
  406. if (_phlbc && _pbs)
  407. {
  408. ITravelLog* ptl;
  409. if (SUCCEEDED(_pbs->GetTravelLog(&ptl)))
  410. {
  411. if (FAILED(ptl->GetTravelEntry(_pbs, 0, NULL)))
  412. {
  413. TraceMsg(DM_HLINKTRACE, "CIEFA::_NavMag this is external nav. Don't call OnNavigationComplete");
  414. fExternal = TRUE;
  415. }
  416. else if (SUCCEEDED(ptl->GetTravelEntry(_pbs, TLOG_BACKEXTERNAL, NULL)))
  417. {
  418. TraceMsg(DM_HLINKTRACE, "CIEFA::_NavMag this is external for. Don't call OnNavigationComplete");
  419. fExternal = TRUE;
  420. }
  421. ptl->Release();
  422. }
  423. }
  424. //
  425. // Don't call OnNavigationComplete if this is an external navigation.
  426. //
  427. if (!fExternal)
  428. {
  429. IHlinkSite* pihlSite = NULL;
  430. DWORD dwSiteData;
  431. HRESULT hresT = pihlNavigate->GetHlinkSite(&pihlSite, &dwSiteData);
  432. if (SUCCEEDED(hresT) && pihlSite)
  433. {
  434. TraceMsg(DM_HLINKTRACE, "CIEFA::_NavMag calling OnNavigationComplete");
  435. hresT = pihlSite->OnNavigationComplete(dwSiteData, 0, S_OK, L"");
  436. if (FAILED(hresT))
  437. {
  438. TraceMsg(DM_ERROR, "CIEFA::Navigat OnNavComplete failed %x", hresT);
  439. }
  440. pihlSite->Release();
  441. }
  442. }
  443. }
  444. }
  445. return hres;
  446. }
  447. //
  448. // HACK - what we really want is a good private marshalled interface - zekel 8-AUG-97
  449. // to the Browser. but for now we will overload the NavigateHack method,
  450. // because it is simple and quick for ship.
  451. //
  452. #define HLNF_REFERRERHACK 0x40000000
  453. HRESULT CIEFrameAuto::_ReferrerHack(LPCWSTR pszUrl)
  454. {
  455. if (_pbs == NULL) //Make sure we have a IBrowserService.
  456. return S_FALSE;
  457. LPITEMIDLIST pidl;
  458. if (SUCCEEDED(_pbs->IEParseDisplayName(CP_ACP, pszUrl, &pidl)))
  459. {
  460. ASSERT(pidl);
  461. _pbs->SetReferrer(pidl);
  462. ILFree(pidl);
  463. }
  464. return S_OK;
  465. }
  466. HRESULT CIEFrameAuto::NavigateHack(DWORD grfHLNF, IBindCtx *pbc, IBindStatusCallback *pibsc, LPCWSTR pszTargetName, LPCWSTR pszUrl, LPCWSTR pszLocation)
  467. {
  468. HRESULT hres = E_FAIL;
  469. IBindCtx * pBindCtx = pbc;
  470. IUnknown * pNotify = NULL;
  471. IUnknown * pBindCtxParam = NULL;
  472. BOOL fAsyncCalled = FALSE;
  473. // Check if we are actually a native frame build...
  474. if (pbc)
  475. {
  476. hres = pbc->GetObjectParam(KEY_BINDCONTEXTPARAM, &pBindCtxParam);
  477. }
  478. if (SUCCEEDED(hres) && pBindCtxParam)
  479. {
  480. // NavigateHack can be called multiple times, and we only want to create the
  481. // new bind context the first time. Since the ITargetNotify pointer is removed
  482. // after the first use, we can check that to make sure.
  483. // get and transfer the target notify pointer.
  484. hres = pbc->GetObjectParam(TARGET_NOTIFY_OBJECT_NAME, &pNotify);
  485. if (SUCCEEDED(hres) && pNotify)
  486. {
  487. // The call is coming from a native frame build of MSHTML.
  488. // We can not use their bind context, create a new one and transfer
  489. // parameters.
  490. // The old bind context is going to be released by the creator, so do not
  491. // make a release call on it.
  492. hres = CreateAsyncBindCtxEx(NULL, 0, NULL, NULL, &pBindCtx, 0);
  493. if(FAILED(hres))
  494. goto Exit;
  495. fAsyncCalled = TRUE;
  496. // carry over the ITargetNotify2 pointer.
  497. hres = pBindCtx->RegisterObjectParam( TARGET_NOTIFY_OBJECT_NAME, pNotify );
  498. if (FAILED(hres))
  499. goto Exit;
  500. pNotify->Release();
  501. pNotify = NULL;
  502. // carry over the bind context parameter.
  503. hres = pBindCtx->RegisterObjectParam( KEY_BINDCONTEXTPARAM, pBindCtxParam );
  504. if (FAILED(hres))
  505. goto Exit;
  506. {
  507. IUnknown * pDwnBindInfo = NULL;
  508. if (SUCCEEDED(pbc->GetObjectParam(SZ_DWNBINDINFO_OBJECTPARAM, &pDwnBindInfo)) && pDwnBindInfo)
  509. {
  510. pBindCtx->RegisterObjectParam(SZ_DWNBINDINFO_OBJECTPARAM, pDwnBindInfo);
  511. pDwnBindInfo->Release();
  512. }
  513. }
  514. }
  515. pBindCtxParam->Release();
  516. pBindCtxParam = NULL;
  517. }
  518. if (IsFlagSet(grfHLNF, HLNF_REFERRERHACK))
  519. hres = _ReferrerHack(pszUrl);
  520. else
  521. hres = _NavigateMagnum(grfHLNF, pBindCtx, pibsc, pszTargetName, pszUrl, pszLocation, NULL, NULL);
  522. Exit:
  523. SAFERELEASE(pNotify);
  524. SAFERELEASE(pBindCtxParam);
  525. // If the call failed anywhere, we can not be sure the new document
  526. // will free the object parameter that is in the bind context
  527. // we have created in this function.
  528. if (FAILED(hres) && pBindCtx)
  529. {
  530. // we don't want to change the return code here.
  531. pBindCtx->RevokeObjectParam(KEY_BINDCONTEXTPARAM);
  532. pBindCtx->RevokeObjectParam(TARGET_NOTIFY_OBJECT_NAME);
  533. }
  534. if (fAsyncCalled)
  535. pBindCtx->Release();
  536. return hres;
  537. }
  538. // passing NULL pibsc and pbc will make be like "ReleaseNavigationState"
  539. // passing -1 for pihlNavigate will cancel pending navigation
  540. HRESULT CIEFrameAuto::Navigate(DWORD grfHLNF, IBindCtx *pbc,
  541. IBindStatusCallback *pibsc, IHlink *pihlNavigate)
  542. {
  543. IMoniker* pmkTarget = NULL;
  544. LPOLESTR pwszDisplayName = NULL;
  545. LPOLESTR pwszLocation = NULL;
  546. LPOLESTR pwszFrameName = NULL;
  547. HRESULT hres = S_OK;
  548. if (pihlNavigate && ((IHlink *)-1) != pihlNavigate)
  549. {
  550. pihlNavigate->GetTargetFrameName(&pwszFrameName);
  551. //
  552. // Note that we are discarding "relative" portion.
  553. //
  554. hres = pihlNavigate->GetMonikerReference(HLINKGETREF_ABSOLUTE, &pmkTarget, &pwszLocation);
  555. HFRMMSG2("Navigate pihl->GetMonRef returned", hres, pmkTarget);
  556. if (SUCCEEDED(hres))
  557. {
  558. IBindCtx* pbcLocal;
  559. if (pbc)
  560. {
  561. pbcLocal = pbc;
  562. pbcLocal->AddRef();
  563. }
  564. else
  565. {
  566. hres = CreateBindCtx(0, &pbcLocal);
  567. }
  568. if (SUCCEEDED(hres))
  569. {
  570. hres = pmkTarget->GetDisplayName(pbcLocal, NULL, &pwszDisplayName);
  571. pbcLocal->Release();
  572. }
  573. }
  574. }
  575. if (SUCCEEDED(hres))
  576. {
  577. hres = _NavigateMagnum(grfHLNF, pbc, pibsc, pwszFrameName, pwszDisplayName, pwszLocation, pihlNavigate, pmkTarget);
  578. }
  579. if (pwszFrameName)
  580. {
  581. OleFree(pwszFrameName);
  582. }
  583. if (pwszDisplayName)
  584. {
  585. OleFree(pwszDisplayName);
  586. }
  587. if (pwszLocation)
  588. {
  589. OleFree(pwszLocation);
  590. }
  591. if (pmkTarget)
  592. {
  593. pmkTarget->Release();
  594. }
  595. return hres;
  596. }
  597. HRESULT CIEFrameAuto::OnNavigate(DWORD grfHLNF,
  598. /* [unique][in] */ IMoniker *pimkTarget,
  599. /* [unique][in] */ LPCWSTR pwzLocation,
  600. /* [unique][in] */ LPCWSTR pwzFriendlyName,
  601. /* [in] */ DWORD dwreserved)
  602. {
  603. TraceMsg(0, "shlf TR ::OnNavigate called");
  604. return S_OK;
  605. }
  606. void CIEFrameAuto::_CancelPendingNavigation(VARIANTARG* pvar)
  607. {
  608. TraceMsg(0, "shd TR _CancelPendingNavigation called");
  609. if (_pmsc)
  610. {
  611. TraceMsg(0, "shd TR _CancelPendingNavigation calling _pmsc->Exec");
  612. _pmsc->Exec(&CGID_Explorer, SBCMDID_CANCELNAVIGATION, 0, pvar, NULL);
  613. }
  614. }
  615. // *** ITargetNotify ***
  616. void
  617. CIEFrameAuto::_HandleOpenOptions( IUnknown * pUnkDestination, ITargetNotify * ptgnNotify)
  618. {
  619. HRESULT hres = S_OK;
  620. ITargetNotify2 * ptgnNotify2 = NULL;
  621. if (!pUnkDestination || !ptgnNotify)
  622. return;
  623. if (SUCCEEDED(ptgnNotify->QueryInterface( IID_ITargetNotify2, (void **)&ptgnNotify2)))
  624. {
  625. BSTR bstrOptions = NULL;
  626. ASSERT(ptgnNotify2);
  627. // Apply the options only if the initator of the navigation
  628. // asks for it.
  629. if (S_OK == ptgnNotify2->GetOptionString(&bstrOptions))
  630. {
  631. _omwin._OpenOptions.ReInitialize();
  632. if (bstrOptions)
  633. {
  634. _omwin._ParseOptionString(bstrOptions, ptgnNotify2);
  635. // We are done with the options string, release it
  636. SysFreeString(bstrOptions);
  637. }
  638. // Apply the options now.
  639. //
  640. IWebBrowser2 * pNewIE;
  641. if (SUCCEEDED(pUnkDestination->QueryInterface(IID_PPV_ARG(IWebBrowser2, &pNewIE))))
  642. {
  643. _omwin._ApplyOpenOptions(pNewIE);
  644. pNewIE->Release();
  645. }
  646. }
  647. ptgnNotify2->Release();
  648. }
  649. }
  650. HRESULT CIEFrameAuto::OnCreate(IUnknown *pUnkDestination, ULONG cbCookie)
  651. {
  652. HRESULT hres = S_OK;
  653. if (cbCookie == (ULONG)_cbCookie && _ptgnNotify)
  654. {
  655. _HandleOpenOptions( pUnkDestination, _ptgnNotify);
  656. hres = _ptgnNotify->OnCreate(pUnkDestination, cbCookie);
  657. SAFERELEASE(_ptgnNotify);
  658. }
  659. return hres;
  660. }
  661. HRESULT CIEFrameAuto::OnReuse(IUnknown *pUnkDestination)
  662. {
  663. return S_OK;
  664. }
  665. #define NOTIFY_WAIT_TIMEOUT (60000)
  666. // chrisfra 10/10/96: do we need EnableModeless(FALSE)/(TRUE) around
  667. // our little loop, or is the busy flag (which is set) sufficient?
  668. HRESULT CIEFrameAuto::_WaitForNotify()
  669. {
  670. if (_ptgnNotify && IsInternetExplorerApp())
  671. {
  672. DWORD dwObject, msWait, msStart = GetTickCount();
  673. goto DOPEEK;
  674. while (_ptgnNotify)
  675. {
  676. // NB We need to let the run dialog become active so we have to half handle sent
  677. // messages but we don't want to handle any input events or we'll swallow the
  678. // type-ahead.
  679. msWait = GetTickCount();
  680. if (msWait - msStart > NOTIFY_WAIT_TIMEOUT)
  681. break;
  682. msWait = NOTIFY_WAIT_TIMEOUT - (msWait - msStart);
  683. dwObject = MsgWaitForMultipleObjects(0, NULL, FALSE, msWait, QS_ALLINPUT);
  684. // Are we done waiting?
  685. switch (dwObject)
  686. {
  687. case WAIT_FAILED:
  688. break;
  689. case WAIT_OBJECT_0:
  690. DOPEEK:
  691. // got a message, dispatch it and wait again
  692. MSG msg;
  693. while (PeekMessage(&msg, NULL,0, 0, PM_REMOVE))
  694. {
  695. DispatchMessage(&msg);
  696. if (_ptgnNotify == NULL ||
  697. ((GetTickCount() - msStart) > NOTIFY_WAIT_TIMEOUT))
  698. break;
  699. }
  700. break;
  701. }
  702. }
  703. }
  704. return S_OK;
  705. }
  706. HRESULT CIEFrameAuto::_RegisterCallback(TCHAR *szFrameName, ITargetNotify *ptgnNotify)
  707. {
  708. HRESULT hr = S_OK;
  709. SAFERELEASE(_ptgnNotify);
  710. _fRegistered = 0;
  711. if (ptgnNotify)
  712. {
  713. IDispatch *pid;
  714. hr = QueryInterface(IID_PPV_ARG(IDispatch, &pid));
  715. if (SUCCEEDED(hr))
  716. {
  717. hr = E_FAIL;
  718. IShellWindows *psw = WinList_GetShellWindows(TRUE);
  719. if (psw != NULL)
  720. {
  721. long cbCookie;
  722. hr = psw->Register(pid, NULL, SWC_CALLBACK, &cbCookie);
  723. if (SUCCEEDED(hr))
  724. {
  725. TCHAR szCookie[25]; // big enough for "_[cbCookie]"
  726. int slenCookie;
  727. int slenName;
  728. int slenMin;
  729. _cbCookie = cbCookie;
  730. _fRegistered = 1;
  731. _ptgnNotify = ptgnNotify;
  732. _ptgnNotify->AddRef();
  733. // prepend unique id to target -- tells created WebBrowserOC to
  734. // register the remainder (if any) as frame name and to perform
  735. // callbacks on all registered callbacks
  736. wnsprintf(szCookie, ARRAYSIZE(szCookie), TEXT("_[%ld]"), cbCookie);
  737. slenCookie = lstrlen(szCookie);
  738. slenName = lstrlen(szFrameName);
  739. slenMin = min((int)MAX_URL_STRING-slenCookie,slenName);
  740. MoveMemory(&szFrameName[slenCookie], szFrameName, CbFromCch(slenMin));
  741. szFrameName[slenCookie+slenMin] = 0;
  742. CopyMemory(szFrameName, szCookie, CbFromCch(slenCookie));
  743. }
  744. psw->Release();
  745. }
  746. pid->Release();
  747. }
  748. }
  749. return hr;
  750. }
  751. HRESULT CIEFrameAuto::_RevokeCallback()
  752. {
  753. HRESULT hr = S_OK;
  754. if (_fRegistered)
  755. {
  756. IShellWindows *psw = WinList_GetShellWindows(TRUE);
  757. if (psw != NULL)
  758. {
  759. hr = psw->Revoke(_cbCookie);
  760. psw->Release();
  761. }
  762. }
  763. SAFERELEASE(_ptgnNotify);
  764. _fRegistered = 0;
  765. return hr;
  766. }
  767. //
  768. // HACK - what we really want is a good private marshalled interface - zekel 8-AUG-97
  769. // to the Browser. but for now we will overload the NavigateHack method,
  770. // because it is simple and quick for ship.
  771. //
  772. void CIEFrameAuto::_SetReferrer(ITargetFramePriv *ptgfp)
  773. {
  774. LPITEMIDLIST pidl;
  775. WCHAR szUrl[MAX_URL_STRING];
  776. ASSERT(ptgfp);
  777. //Make sure we have a IBrowserService.
  778. if (_psb && SUCCEEDED(_pbs->GetPidl(&pidl)))
  779. {
  780. if (SUCCEEDED(_pbs->IEGetDisplayName(pidl, szUrl, SHGDN_FORPARSING)))
  781. ptgfp->NavigateHack(HLNF_REFERRERHACK, NULL, NULL, NULL, szUrl, NULL);
  782. ILFree(pidl);
  783. }
  784. }
  785. HRESULT CIEFrameAuto::_JumpTo(IBindCtx *pbc, LPWSTR pszLocation, DWORD grfHLNF, IBindStatusCallback *pibsc, IHlink *pihlNavigate, LPCWSTR pszFrameName, LPCWSTR pszUrl)
  786. {
  787. LPITEMIDLIST pidl = NULL;
  788. HRESULT hres;
  789. ITargetNotify *ptgnNotify = NULL;
  790. IUnknown *punkNotify = NULL;
  791. IUnknown *punkThis = NULL;
  792. UINT uiCP = CP_ACP;
  793. // Get the current document codepage from Trident and use it for url string conversion if necessary.
  794. if (!(grfHLNF & HLNF_ALLOW_AUTONAVIGATE) && _pmsc)
  795. {
  796. VARIANT varOut = { 0 };
  797. VARIANT varIn = { 0 };
  798. varIn.vt = VT_I4;
  799. varIn.lVal = DFC_URLCHARSET; // we want the doc's url charset
  800. if (SUCCEEDED(_pmsc->Exec(&CGID_ShellDocView, SHDVID_DOCFAMILYCHARSET, 0, &varIn, &varOut)))
  801. uiCP = (UINT)varOut.lVal;
  802. }
  803. // Note that we are simply passing the pidl to ISB::BrowseObject,
  804. // assuming that new shell32.dll allows us to bind to DocObject
  805. // documents.
  806. //
  807. DWORD flags = (grfHLNF & HLNF_OPENINNEWWINDOW) ?
  808. (SBSP_NEWBROWSER | SBSP_ABSOLUTE | SBSP_INITIATEDBYHLINKFRAME) :
  809. (SBSP_SAMEBROWSER | SBSP_ABSOLUTE | SBSP_INITIATEDBYHLINKFRAME);
  810. flags |= ((grfHLNF & HLNF_ALLOW_AUTONAVIGATE) ? (SBSP_ALLOW_AUTONAVIGATE) : 0);
  811. flags |= ((grfHLNF & SHHLNF_WRITENOHISTORY) ? (SBSP_WRITENOHISTORY) : 0);
  812. flags |= ((grfHLNF & SHHLNF_NOAUTOSELECT) ? (SBSP_NOAUTOSELECT) : 0);
  813. if (pbc && SUCCEEDED(pbc->GetObjectParam(TARGET_NOTIFY_OBJECT_NAME, &punkNotify)))
  814. {
  815. if (FAILED(punkNotify->QueryInterface(IID_PPV_ARG(ITargetNotify, &ptgnNotify))))
  816. ptgnNotify = NULL;
  817. punkNotify->Release();
  818. QueryInterface(IID_PPV_ARG(IUnknown, &punkThis));
  819. }
  820. if (grfHLNF & HLNF_CREATENOHISTORY)
  821. flags |= SBSP_REDIRECT;
  822. if (flags & SBSP_NEWBROWSER)
  823. {
  824. TCHAR *pszHeaders = NULL;
  825. BYTE *pPostData = NULL;
  826. DWORD cbPostData = 0;
  827. TCHAR szFrameName[MAX_URL_STRING+1];
  828. STGMEDIUM stgPostData = { TYMED_NULL, NULL, NULL };
  829. //Qfe:1478 If restricted to open in new window, return failure.
  830. if ((grfHLNF & HLNF_OPENINNEWWINDOW)
  831. && SHIsRestricted2W(_hwnd, REST_NoOpeninNewWnd, NULL, 0))
  832. {
  833. SAFERELEASE(punkThis);
  834. return E_ACCESSDENIED;
  835. }
  836. szFrameName[0] = 0;
  837. // Here is where if we are doing a new window we must
  838. // extract frame, post etc and append to pidl. These must
  839. // be done in the following order (to match extraction code):
  840. // URLID_FRAMENAME,URLID_POSTDATA,URLID_HEADERS
  841. if (pszFrameName)
  842. {
  843. SHUnicodeToTChar(pszFrameName, szFrameName, ARRAYSIZE(szFrameName));
  844. }
  845. if (pibsc)
  846. {
  847. GetHeadersAndPostData(pibsc,&pszHeaders,&stgPostData,&cbPostData, NULL);
  848. if (stgPostData.tymed == TYMED_HGLOBAL)
  849. {
  850. pPostData = (LPBYTE) stgPostData.hGlobal;
  851. }
  852. }
  853. hres = _PidlFromUrlEtc(uiCP, pszUrl, pszLocation, &pidl);
  854. HFRMMSG2("_JumpTo _PidlFromUrlEtc returned", hres, pidl);
  855. if (SUCCEEDED(hres))
  856. {
  857. IUnknown* punkNewWindow = NULL;
  858. BOOL fCancel = FALSE;
  859. // The NewWindow2 event may return the window for us.
  860. FireEvent_NewWindow2(_GetOuter(), &punkNewWindow, &fCancel);
  861. if (!fCancel)
  862. {
  863. BOOL fProcessed = FALSE;
  864. // We might need the old NewWindow event...
  865. if (!punkNewWindow)
  866. {
  867. _RegisterCallback(szFrameName, ptgnNotify);
  868. // fire an event to indicate a new window needs to be created
  869. // to allow a container to handle it itself if it wants
  870. // since we may be aggregated, QI our parent
  871. // Yet another Compuserve workaround (IE 60688):
  872. // If the target frame name is "_blank", Compuserve will pass that name
  873. // in to the Navigate call of the new window. We would then create a new window
  874. // (which would fire this event) causing a loop. Break the recursion by sending
  875. // an empty string for the frame name.
  876. HWND hwnd = _GetHWND();
  877. if (hwnd)
  878. {
  879. FireEvent_NewWindow(_GetOuter(), hwnd, pidl,pszLocation,0,
  880. StrCmpI(szFrameName, TEXT("_blank")) ? szFrameName : TEXT(""), // Target frame name
  881. pPostData,cbPostData,pszHeaders,&fProcessed);
  882. }
  883. }
  884. if (!fProcessed)
  885. {
  886. if (!punkNewWindow)
  887. {
  888. #ifdef INCLUDE_BUSTED_OC_QI
  889. IUnknown* pdvb = NULL;
  890. #endif
  891. _RevokeCallback();
  892. #ifdef INCLUDE_BUSTED_OC_QI
  893. // For some unidentifiable reason the old code did NOT
  894. // create a new window if we were hosted in the WebBrowserOC.
  895. // mikesh/cheechew/jeremys/chrisfra don't know why this happens.
  896. // Who knows what app will break if we change this...
  897. // (Note: IDefViewBrowser is a CWebBrowseSB only interface)
  898. //
  899. // NOTE: chrisfra 3/11/97, this code breaks open a
  900. // new window for a non-existent target, when in
  901. // desktop component or browser band
  902. fCancel = !(_psbTop && FAILED(_psbTop->QueryInterface(IID_PPV_ARG(IDefViewBrowser, &pdvb))));
  903. if (pdvb)
  904. pdvb->Release();
  905. #endif
  906. }
  907. // what we really want to do is just hand this off to
  908. // _psbTop->BrowseObject and let it (CWebBrowserSB or CShellBrowser)
  909. // decide whether to use HlinkFrameNavigate or not, but if we
  910. // do that, then we lose the grfHLNF and pihlNavigate.
  911. // So put that logic here...
  912. //
  913. if (!fCancel)
  914. {
  915. hres = CreateTargetFrame(pszFrameName, &punkNewWindow);
  916. if (SUCCEEDED(hres))
  917. {
  918. // Notify ptgnNotify, then release and remove from bindctx
  919. if (ptgnNotify)
  920. {
  921. _HandleOpenOptions( punkNewWindow, ptgnNotify);
  922. ptgnNotify->OnCreate(punkNewWindow, GetTickCount());
  923. ptgnNotify->Release();
  924. ptgnNotify = NULL;
  925. pbc->RevokeObjectParam(TARGET_NOTIFY_OBJECT_NAME);
  926. }
  927. LPHLINKFRAME phf;
  928. hres = punkNewWindow->QueryInterface(IID_PPV_ARG(IHlinkFrame, &phf));
  929. if (SUCCEEDED(hres))
  930. {
  931. ITargetFramePriv * ptgfp;
  932. if (NULL == pihlNavigate)
  933. {
  934. hres = punkNewWindow->QueryInterface(IID_PPV_ARG(ITargetFramePriv, &ptgfp));
  935. }
  936. if (SUCCEEDED(hres))
  937. {
  938. if (pihlNavigate)
  939. {
  940. hres = phf->Navigate(grfHLNF & ~HLNF_OPENINNEWWINDOW,
  941. pbc,
  942. pibsc,
  943. pihlNavigate);
  944. }
  945. else
  946. {
  947. // HACK - see this methods comments
  948. _SetReferrer(ptgfp);
  949. hres = ptgfp->NavigateHack(grfHLNF & ~HLNF_OPENINNEWWINDOW,
  950. pbc,
  951. pibsc,
  952. NULL,
  953. pszUrl,
  954. pszLocation);
  955. }
  956. if (FAILED(hres))
  957. {
  958. TraceMsg(DM_ERROR, "CIEFA::_JumpTo marshalled IHlinkFrame::Navigate failed %x", hres);
  959. }
  960. ShowHlinkFrameWindow(punkNewWindow);
  961. if (NULL == pihlNavigate)
  962. {
  963. ptgfp->Release();
  964. }
  965. if(SUCCEEDED(hres) && pibsc)
  966. {
  967. _SetPendingNavigateContext(NULL, NULL);
  968. }
  969. }
  970. phf->Release();
  971. }
  972. }
  973. }
  974. else
  975. {
  976. //
  977. // If NEWBROWSER is specified when there is no top level
  978. // browser, we should ask IE/Shell to do browsing.
  979. // We don't pass HLNF_OPENINNEWWINDOW in this case.
  980. //
  981. // Notify object doing navigation that we are the object implementing IWebBrowserApp
  982. if (ptgnNotify) ptgnNotify->OnReuse(punkThis);
  983. if (pihlNavigate)
  984. {
  985. hres = HlinkFrameNavigate(grfHLNF & ~HLNF_OPENINNEWWINDOW,
  986. NULL, NULL, pihlNavigate, NULL);
  987. }
  988. else
  989. {
  990. hres = HlinkFrameNavigateNHL(grfHLNF & ~HLNF_OPENINNEWWINDOW,
  991. NULL, NULL, NULL, pszUrl, pszLocation);
  992. }
  993. }
  994. }
  995. else
  996. {
  997. // Oldstyle AOL or other 3rd Party, wait for registration of
  998. // WebBrowserOC, which calls us back on _ptgnNotify
  999. _WaitForNotify();
  1000. // We timed out the window create, notify caller
  1001. if (_ptgnNotify)
  1002. _ptgnNotify->OnCreate(NULL, 0);
  1003. _RevokeCallback();
  1004. }
  1005. }
  1006. if (punkNewWindow)
  1007. punkNewWindow->Release();
  1008. }
  1009. else
  1010. {
  1011. TraceMsg(DM_ERROR, "IEAuto::_JumpTo _PidlFromUrlEtc (1) failed %x", hres);
  1012. }
  1013. if (pszHeaders)
  1014. {
  1015. LocalFree(pszHeaders);
  1016. pszHeaders = NULL;
  1017. }
  1018. if (stgPostData.tymed != TYMED_NULL)
  1019. {
  1020. ReleaseStgMedium(&stgPostData);
  1021. }
  1022. }
  1023. else
  1024. {
  1025. // Notify object doing navigation that we are the object implementing IWebBrowserApp
  1026. if (ptgnNotify) ptgnNotify->OnReuse(punkThis);
  1027. hres = _PidlFromUrlEtc(uiCP, pszUrl, pszLocation, &pidl);
  1028. if (SUCCEEDED(hres))
  1029. {
  1030. hres = _psb->BrowseObject(pidl, flags);
  1031. }
  1032. else
  1033. {
  1034. TraceMsg(DM_ERROR, "IEAuto::_JumpTo _PidlFromUrlEtc (2) failed %x", hres);
  1035. }
  1036. }
  1037. if (pidl)
  1038. {
  1039. HFRMMSG2("_JumpTo _psb->BrowseObject returned", hres, 0);
  1040. ILFree(pidl);
  1041. }
  1042. if (ptgnNotify)
  1043. {
  1044. ptgnNotify->Release();
  1045. pbc->RevokeObjectParam(TARGET_NOTIFY_OBJECT_NAME);
  1046. }
  1047. SAFERELEASE(punkThis);
  1048. return hres;
  1049. }
  1050. HRESULT CIEFrameAuto::QueryService(REFGUID guidService, REFIID riid, void ** ppvObj)
  1051. {
  1052. *ppvObj = NULL;
  1053. // WARNING: Note that we are not following the strict semantics of
  1054. // ISP::QueryService. It is, however, OK because this (the fact that
  1055. // IHlinkFrame support IServiceProvider) is not public.
  1056. if (IsEqualIID(guidService, SID_SOmWindow))
  1057. {
  1058. return _omwin.QueryInterface(riid, ppvObj);
  1059. }
  1060. else if (IsEqualIID(guidService, IID_IHlinkFrame))
  1061. {
  1062. SERVMSG("QueryService called", _pbc, _pbsc);
  1063. if (IsEqualIID(riid, IID_IBindCtx) && _pbc)
  1064. {
  1065. *ppvObj = _pbc;
  1066. _pbc->AddRef();
  1067. }
  1068. else if (IsEqualIID(riid, IID_IBindStatusCallback) && _pbsc)
  1069. {
  1070. *ppvObj = _pbsc;
  1071. _pbsc->AddRef();
  1072. }
  1073. else
  1074. {
  1075. return QueryInterface(riid, ppvObj);
  1076. }
  1077. }
  1078. else if (IsEqualIID(guidService, SID_PendingBindStatusCallback))
  1079. {
  1080. if (IsEqualIID(riid, IID_IBindStatusCallback) && _pbscPending)
  1081. {
  1082. *ppvObj = _pbscPending;
  1083. _pbscPending->AddRef();
  1084. }
  1085. }
  1086. else if (_psp)
  1087. {
  1088. return _psp->QueryService(guidService, riid, ppvObj);
  1089. }
  1090. return *ppvObj ? S_OK : E_FAIL;
  1091. }
  1092. HRESULT CIEFrameAuto::Exec(
  1093. /* [unique][in] */ const GUID *pguidCmdGroup,
  1094. /* [in] */ DWORD nCmdID,
  1095. /* [in] */ DWORD nCmdexecopt,
  1096. /* [unique][in] */ VARIANTARG *pvarargIn,
  1097. /* [unique][out][in] */ VARIANTARG *pvarargOut)
  1098. {
  1099. HRESULT hres = S_OK;
  1100. if (pguidCmdGroup)
  1101. {
  1102. if (IsEqualGUID(CGID_Explorer, *pguidCmdGroup))
  1103. {
  1104. switch(nCmdID)
  1105. {
  1106. case SBCMDID_CANCELNAVIGATION:
  1107. _CancelPendingNavigation(NULL);
  1108. break;
  1109. case SBCMDID_SELECTHISTPIDL:
  1110. case SBCMDID_HISTSFOLDER:
  1111. if (_poctFrameTop)
  1112. hres = _poctFrameTop->Exec(pguidCmdGroup, nCmdID, nCmdexecopt, pvarargIn, pvarargOut);
  1113. else
  1114. hres = S_OK;
  1115. break;
  1116. case SBCMDID_IESHORTCUT:
  1117. #ifdef BROWSENEWPROCESS_STRICT // "Nav in new process" has become "Launch in new process", so this is no longer needed
  1118. // If this is an IE shortcut and browse in a new process is turned on
  1119. // and we are explorer.exe - we should pass on the request to navigate to
  1120. // this shortcut. The caller is expected to create a new window/process to
  1121. // launch this shortcut
  1122. if (IsBrowseNewProcessAndExplorer())
  1123. hres = E_FAIL;
  1124. else
  1125. #endif
  1126. hres = _NavIEShortcut(pvarargIn,pvarargOut);
  1127. break;
  1128. case SBCMDID_GETSHORTCUTPATH:
  1129. if (_pwszShortcutPath && pvarargOut)
  1130. {
  1131. pvarargOut->bstrVal = SysAllocString(_pwszShortcutPath);
  1132. if (pvarargOut->bstrVal)
  1133. pvarargOut->vt = VT_BSTR; //no need to set hres=S_OK since it is inited already
  1134. else
  1135. hres = E_OUTOFMEMORY;
  1136. }
  1137. else
  1138. {
  1139. if (pvarargOut)
  1140. pvarargOut->vt = VT_EMPTY;
  1141. hres = E_FAIL;
  1142. }
  1143. break;
  1144. default:
  1145. hres = OLECMDERR_E_NOTSUPPORTED;
  1146. }
  1147. }
  1148. else if (IsEqualGUID(CGID_ShortCut, *pguidCmdGroup))
  1149. {
  1150. if (_poctFrameTop) // we must check!
  1151. hres = _poctFrameTop->Exec(&CGID_ShortCut, nCmdID, nCmdexecopt, pvarargIn, pvarargOut);
  1152. else
  1153. hres = OLECMDERR_E_NOTSUPPORTED;
  1154. }
  1155. else if (IsEqualGUID(CGID_ShellDocView, *pguidCmdGroup))
  1156. {
  1157. switch (nCmdID)
  1158. {
  1159. case SHDVID_DELEGATEWINDOWOM:
  1160. _omwin.SetDelegationPolicy(V_BOOL(pvarargIn));
  1161. break;
  1162. default:
  1163. hres = OLECMDERR_E_NOTSUPPORTED;
  1164. }
  1165. }
  1166. else if (IsEqualGUID(CGID_InternetExplorer, *pguidCmdGroup))
  1167. // CGID_InternetExplorer are public defined in msiehost.h
  1168. {
  1169. switch (nCmdID)
  1170. {
  1171. case IECMDID_CLEAR_AUTOCOMPLETE_FOR_FORMS:
  1172. {
  1173. if (pvarargIn->vt == VT_I4)
  1174. {
  1175. hres = ClearAutoSuggestForForms(V_I4(pvarargIn));
  1176. }
  1177. else
  1178. hres = E_INVALIDARG;
  1179. }
  1180. break;
  1181. case IECMDID_SETID_AUTOCOMPLETE_FOR_FORMS:
  1182. {
  1183. if ((pvarargIn->vt == VT_UI8) ||
  1184. (pvarargIn->vt == VT_I8))
  1185. {
  1186. hres = SetIdAutoSuggestForForms(((GUID *)(&pvarargIn->ullVal)), _omwin.IntelliForms());
  1187. }
  1188. else
  1189. hres = E_INVALIDARG;
  1190. }
  1191. break;
  1192. default:
  1193. hres = OLECMDERR_E_NOTSUPPORTED;
  1194. }
  1195. }
  1196. else
  1197. {
  1198. hres = OLECMDERR_E_UNKNOWNGROUP;
  1199. }
  1200. }
  1201. else
  1202. {
  1203. hres = OLECMDERR_E_UNKNOWNGROUP;
  1204. }
  1205. return hres;
  1206. }
  1207. BOOL CIEFrameAuto::_fNavigationPending()
  1208. {
  1209. // unfortunately, the hyperlink frame doesn't REALLY know when there's
  1210. // a navigation pending or not because people might not call OnReleaseNavigation.
  1211. // only the real browser knows.
  1212. if (_pmsc)
  1213. {
  1214. MSOCMD rgCmd;
  1215. rgCmd.cmdID = SBCMDID_CANCELNAVIGATION;
  1216. rgCmd.cmdf = 0;
  1217. _pmsc->QueryStatus(&CGID_Explorer, 1, &rgCmd, NULL);
  1218. return (rgCmd.cmdf & MSOCMDF_ENABLED);
  1219. }
  1220. return FALSE;
  1221. }
  1222. HRESULT CIEFrameAuto::QueryStatus(const GUID *pguidCmdGroup,
  1223. ULONG cCmds, OLECMD rgCmds[], OLECMDTEXT *pcmdtext)
  1224. {
  1225. if (pguidCmdGroup && IsEqualGUID(CGID_Explorer, *pguidCmdGroup))
  1226. {
  1227. for (ULONG i = 0; i < cCmds; i++)
  1228. {
  1229. switch (rgCmds[i].cmdID)
  1230. {
  1231. case SBCMDID_CANCELNAVIGATION:
  1232. rgCmds[i].cmdf = _fNavigationPending() ? MSOCMDF_ENABLED : 0;
  1233. break;
  1234. case SBCMDID_WRITEHIST:
  1235. rgCmds[i].cmdf = _fSuppressHistory ? 0:MSOCMDF_ENABLED;
  1236. break;
  1237. case SBCMDID_SELECTHISTPIDL:
  1238. rgCmds[i].cmdf = _fSuppressSelect || !_poctFrameTop ? 0:MSOCMDF_ENABLED;
  1239. break;
  1240. default:
  1241. rgCmds[i].cmdf = 0;
  1242. break;
  1243. }
  1244. }
  1245. }
  1246. else
  1247. {
  1248. return OLECMDERR_E_UNKNOWNGROUP;
  1249. }
  1250. if (pcmdtext)
  1251. {
  1252. pcmdtext->cmdtextf = MSOCMDTEXTF_NONE;
  1253. pcmdtext->cwActual = 0;
  1254. }
  1255. return NOERROR;
  1256. }
  1257. HRESULT CIEFrameAuto::_PidlFromUrlEtc(UINT uiCP, LPCWSTR pszUrl, LPWSTR pszLocation, LPITEMIDLIST* ppidl)
  1258. {
  1259. *ppidl = NULL; // assumes error
  1260. // ALGORITHM:
  1261. // - First, we call IEParseDisplayName to generate the pidl
  1262. // to the specified URL or file name.
  1263. // - if we have fragment (pszLocation) specified,
  1264. // we call IEILAppendFragment() to add the hidden fragment id
  1265. if (_pbs == NULL) //Make sure we have a IBrowserService.
  1266. return (S_FALSE);
  1267. HRESULT hr = _pbs->IEParseDisplayName(uiCP, pszUrl, ppidl);
  1268. // This is ugly, if it's a file path that failed to parse because
  1269. // it doesn't exist, we want to create a SimpleIDList so we display
  1270. // a res: navigation failed IFrame instead of the err dlg displayed
  1271. // in DisplayParseError() below.
  1272. if (FAILED(hr))
  1273. {
  1274. TCHAR szPath[MAX_PATH];
  1275. DWORD cchBuf = ARRAYSIZE(szPath);
  1276. // If it's a FILE URL, convert it to a path.
  1277. if (IsFileUrlW(pszUrl) && SUCCEEDED(PathCreateFromUrl(pszUrl, szPath, &cchBuf, 0)))
  1278. {
  1279. // That worked, we are done because our buffer is now full.
  1280. }
  1281. else
  1282. {
  1283. // We now need to copy to the buffer and we assume it's a path.
  1284. StrCpyN(szPath, pszUrl, ARRAYSIZE(szPath));
  1285. }
  1286. *ppidl = SHSimpleIDListFromPath(szPath);
  1287. if (*ppidl)
  1288. hr = S_OK;
  1289. }
  1290. if (SUCCEEDED(hr))
  1291. {
  1292. if (pszLocation && *pszLocation)
  1293. {
  1294. *ppidl = IEILAppendFragment(*ppidl, pszLocation);
  1295. hr = *ppidl ? S_OK : E_OUTOFMEMORY;
  1296. }
  1297. }
  1298. else
  1299. {
  1300. //
  1301. // NOTES: This behavior is new in IE4.0. We are adding
  1302. // this message box based on the request (bug-report)
  1303. // from Office guys. (SatoNa)
  1304. //
  1305. hr = _pbs->DisplayParseError(hr, pszUrl);
  1306. }
  1307. return hr;
  1308. }
  1309. HRESULT CIEFrameAuto::_NavIEShortcut(VARIANT *pvarIn, VARIANT *pvarargOut)
  1310. {
  1311. // need to validate verb and clsid
  1312. HRESULT hr = E_ACCESSDENIED;
  1313. READYSTATE ready;
  1314. BOOL fForceNavigate = pvarargOut ? ((VT_BOOL == pvarargOut->vt ) && (pvarargOut->boolVal)) : FALSE;
  1315. get_ReadyState(&ready);
  1316. ASSERT(pvarIn);
  1317. ASSERT(pvarIn->vt == VT_BSTR);
  1318. //
  1319. // we dont want to allow the exec to go through if this window
  1320. // is busy with something else. we should probably allow
  1321. // READYSTATE_COMPLETE and READYSTATE_UNINITIALIZED.
  1322. // if we use READYSTATE_UNINITIALIZED, we need to init the browser
  1323. // and make it visible and stuff like that. something to the
  1324. // check that IPersisteHistory->LoadHistory() does in shvocx.cpp.
  1325. // right now we will only allow COMPLETE.
  1326. //
  1327. TraceMsgW(DM_SHELLEXECOBJECT, "[%X] IEAuto_NavIEShortcut entered '%s' ready = %d", this, pvarIn->bstrVal, ready);
  1328. if (((ready == READYSTATE_COMPLETE || ready == READYSTATE_UNINITIALIZED) || (fForceNavigate))
  1329. && S_OK == IUnknown_Exec(_psbTop, &CGID_Explorer, SBCMDID_ISIEMODEBROWSER, 0, NULL, NULL))
  1330. {
  1331. IPersistFile *ppf;
  1332. if (SUCCEEDED(CoCreateInstance(CLSID_InternetShortcut, NULL, CLSCTX_ALL, IID_PPV_ARG(IPersistFile, &ppf))))
  1333. {
  1334. if (SUCCEEDED(ppf->Load(pvarIn->bstrVal, STGM_READ)))
  1335. {
  1336. LPWSTR pszUrl = NULL;
  1337. TraceMsg(DM_SHELLEXECOBJECT, "[%X] IEAuto_NavIEShortcut shortcut inited with file", this);
  1338. IUniformResourceLocatorW *purl;
  1339. if (SUCCEEDED(ppf->QueryInterface(IID_PPV_ARG(IUniformResourceLocatorW, &purl))))
  1340. {
  1341. purl->GetURL(&pszUrl);
  1342. purl->Release();
  1343. }
  1344. if (pszUrl)
  1345. {
  1346. TraceMsgW(DM_SHELLEXECOBJECT, "[%X] IEAuto_NavIEShortcut found %s", this, pszUrl);
  1347. LPITEMIDLIST pidl;
  1348. IEParseDisplayNameW(CP_ACP, pszUrl, &pidl);
  1349. if (pidl)
  1350. {
  1351. ASSERT(NULL == _pwszShortcutPathPending);
  1352. if (_pwszShortcutPathPending)
  1353. LocalFree(_pwszShortcutPathPending);
  1354. _pwszShortcutPathPending = StrDupW(pvarIn->bstrVal);
  1355. hr = _BrowseObject(pidl, SBSP_SAMEBROWSER);
  1356. if (SUCCEEDED(hr))
  1357. {
  1358. if (ready == READYSTATE_UNINITIALIZED)
  1359. put_Visible(VARIANT_TRUE);
  1360. HWND hwnd = _GetHWND();
  1361. if (hwnd)
  1362. {
  1363. if (IsIconic(hwnd))
  1364. ShowWindow(hwnd, SW_RESTORE);
  1365. else
  1366. SetForegroundWindow(hwnd);
  1367. }
  1368. }
  1369. ILFree(pidl);
  1370. }
  1371. SHFree(pszUrl);
  1372. }
  1373. }
  1374. ppf->Release();
  1375. }
  1376. }
  1377. TraceMsg(DM_SHELLEXECOBJECT, "IEAuto_NavIEShortcut returns 0x%X", hr);
  1378. return hr;
  1379. }