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

1665 lines
56 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. BOOL _ShouldInvokeDefaultBrowserOnNewWindow(IUnknown *punk)
  786. {
  787. BOOL fResult = FALSE;
  788. IOleCommandTarget *poct;
  789. if (SUCCEEDED(IUnknown_QueryService(punk, SID_STopLevelBrowser, IID_PPV_ARG(IOleCommandTarget, &poct))))
  790. {
  791. VARIANT var;
  792. var.vt = VT_EMPTY;
  793. if (SUCCEEDED(poct->Exec(&CGID_InternetExplorer,
  794. IECMDID_GET_INVOKE_DEFAULT_BROWSER_ON_NEW_WINDOW,
  795. 0,
  796. NULL,
  797. &var)))
  798. {
  799. fResult = var.boolVal ? TRUE : FALSE;
  800. }
  801. poct->Release();
  802. }
  803. return fResult;
  804. }
  805. HRESULT CIEFrameAuto::_JumpTo(IBindCtx *pbc, LPWSTR pszLocation, DWORD grfHLNF, IBindStatusCallback *pibsc, IHlink *pihlNavigate, LPCWSTR pszFrameName, LPCWSTR pszUrl)
  806. {
  807. LPITEMIDLIST pidl = NULL;
  808. HRESULT hres;
  809. ITargetNotify *ptgnNotify = NULL;
  810. IUnknown *punkNotify = NULL;
  811. IUnknown *punkThis = NULL;
  812. UINT uiCP = CP_ACP;
  813. // Get the current document codepage from Trident and use it for url string conversion if necessary.
  814. if (!(grfHLNF & HLNF_ALLOW_AUTONAVIGATE) && _pmsc)
  815. {
  816. VARIANT varOut = { 0 };
  817. VARIANT varIn = { 0 };
  818. varIn.vt = VT_I4;
  819. varIn.lVal = DFC_URLCHARSET; // we want the doc's url charset
  820. if (SUCCEEDED(_pmsc->Exec(&CGID_ShellDocView, SHDVID_DOCFAMILYCHARSET, 0, &varIn, &varOut)))
  821. uiCP = (UINT)varOut.lVal;
  822. }
  823. // Note that we are simply passing the pidl to ISB::BrowseObject,
  824. // assuming that new shell32.dll allows us to bind to DocObject
  825. // documents.
  826. //
  827. DWORD flags = (grfHLNF & HLNF_OPENINNEWWINDOW) ?
  828. (SBSP_NEWBROWSER | SBSP_ABSOLUTE | SBSP_INITIATEDBYHLINKFRAME) :
  829. (SBSP_SAMEBROWSER | SBSP_ABSOLUTE | SBSP_INITIATEDBYHLINKFRAME);
  830. flags |= ((grfHLNF & HLNF_ALLOW_AUTONAVIGATE) ? (SBSP_ALLOW_AUTONAVIGATE) : 0);
  831. flags |= ((grfHLNF & SHHLNF_WRITENOHISTORY) ? (SBSP_WRITENOHISTORY) : 0);
  832. flags |= ((grfHLNF & SHHLNF_NOAUTOSELECT) ? (SBSP_NOAUTOSELECT) : 0);
  833. if (pbc && SUCCEEDED(pbc->GetObjectParam(TARGET_NOTIFY_OBJECT_NAME, &punkNotify)))
  834. {
  835. if (FAILED(punkNotify->QueryInterface(IID_PPV_ARG(ITargetNotify, &ptgnNotify))))
  836. ptgnNotify = NULL;
  837. punkNotify->Release();
  838. QueryInterface(IID_PPV_ARG(IUnknown, &punkThis));
  839. }
  840. if (grfHLNF & HLNF_CREATENOHISTORY)
  841. flags |= SBSP_REDIRECT;
  842. if (flags & SBSP_NEWBROWSER)
  843. {
  844. TCHAR *pszHeaders = NULL;
  845. BYTE *pPostData = NULL;
  846. DWORD cbPostData = 0;
  847. TCHAR szFrameName[MAX_URL_STRING+1];
  848. STGMEDIUM stgPostData = { TYMED_NULL, NULL, NULL };
  849. //Qfe:1478 If restricted to open in new window, return failure.
  850. if ((grfHLNF & HLNF_OPENINNEWWINDOW)
  851. && SHIsRestricted2W(_hwnd, REST_NoOpeninNewWnd, NULL, 0))
  852. {
  853. SAFERELEASE(punkThis);
  854. return E_ACCESSDENIED;
  855. }
  856. if ((_ShouldInvokeDefaultBrowserOnNewWindow(_psb) || IsDesktopFrame(_psb)) && !ShouldNavigateInIE(pszUrl))
  857. {
  858. // IE is not the default browser so we'll ShellExecute the Url since someone
  859. // has told us that's the behaviour they prefer.
  860. HINSTANCE hinstRet = ShellExecuteW(NULL, NULL, pszUrl, NULL, NULL, SW_SHOWNORMAL);
  861. hres = ((UINT_PTR)hinstRet) <= 32 ? E_FAIL : S_OK;
  862. }
  863. else
  864. {
  865. szFrameName[0] = 0;
  866. // Here is where if we are doing a new window we must
  867. // extract frame, post etc and append to pidl. These must
  868. // be done in the following order (to match extraction code):
  869. // URLID_FRAMENAME,URLID_POSTDATA,URLID_HEADERS
  870. if (pszFrameName)
  871. {
  872. SHUnicodeToTChar(pszFrameName, szFrameName, ARRAYSIZE(szFrameName));
  873. }
  874. if (pibsc)
  875. {
  876. GetHeadersAndPostData(pibsc,&pszHeaders,&stgPostData,&cbPostData, NULL);
  877. if (stgPostData.tymed == TYMED_HGLOBAL)
  878. {
  879. pPostData = (LPBYTE) stgPostData.hGlobal;
  880. }
  881. }
  882. hres = _PidlFromUrlEtc(uiCP, pszUrl, pszLocation, &pidl);
  883. HFRMMSG2("_JumpTo _PidlFromUrlEtc returned", hres, pidl);
  884. if (SUCCEEDED(hres))
  885. {
  886. IUnknown* punkNewWindow = NULL;
  887. BOOL fCancel = FALSE;
  888. // The NewWindow2 event may return the window for us.
  889. FireEvent_NewWindow2(_GetOuter(), &punkNewWindow, &fCancel);
  890. if (!fCancel)
  891. {
  892. BOOL fProcessed = FALSE;
  893. // We might need the old NewWindow event...
  894. if (!punkNewWindow)
  895. {
  896. _RegisterCallback(szFrameName, ptgnNotify);
  897. // fire an event to indicate a new window needs to be created
  898. // to allow a container to handle it itself if it wants
  899. // since we may be aggregated, QI our parent
  900. // Yet another Compuserve workaround (IE 60688):
  901. // If the target frame name is "_blank", Compuserve will pass that name
  902. // in to the Navigate call of the new window. We would then create a new window
  903. // (which would fire this event) causing a loop. Break the recursion by sending
  904. // an empty string for the frame name.
  905. HWND hwnd = _GetHWND();
  906. if (hwnd)
  907. {
  908. FireEvent_NewWindow(_GetOuter(), hwnd, pidl,pszLocation,0,
  909. StrCmpI(szFrameName, TEXT("_blank")) ? szFrameName : TEXT(""), // Target frame name
  910. pPostData,cbPostData,pszHeaders,&fProcessed);
  911. }
  912. }
  913. if (!fProcessed)
  914. {
  915. if (!punkNewWindow)
  916. {
  917. #ifdef INCLUDE_BUSTED_OC_QI
  918. IUnknown* pdvb = NULL;
  919. #endif
  920. _RevokeCallback();
  921. #ifdef INCLUDE_BUSTED_OC_QI
  922. // For some unidentifiable reason the old code did NOT
  923. // create a new window if we were hosted in the WebBrowserOC.
  924. // mikesh/cheechew/jeremys/chrisfra don't know why this happens.
  925. // Who knows what app will break if we change this...
  926. // (Note: IDefViewBrowser is a CWebBrowseSB only interface)
  927. //
  928. // NOTE: chrisfra 3/11/97, this code breaks open a
  929. // new window for a non-existent target, when in
  930. // desktop component or browser band
  931. fCancel = !(_psbTop && FAILED(_psbTop->QueryInterface(IID_PPV_ARG(IDefViewBrowser, &pdvb))));
  932. if (pdvb)
  933. pdvb->Release();
  934. #endif
  935. }
  936. // what we really want to do is just hand this off to
  937. // _psbTop->BrowseObject and let it (CWebBrowserSB or CShellBrowser)
  938. // decide whether to use HlinkFrameNavigate or not, but if we
  939. // do that, then we lose the grfHLNF and pihlNavigate.
  940. // So put that logic here...
  941. //
  942. if (!fCancel)
  943. {
  944. hres = CreateTargetFrame(pszFrameName, &punkNewWindow);
  945. if (SUCCEEDED(hres))
  946. {
  947. // Notify ptgnNotify, then release and remove from bindctx
  948. if (ptgnNotify)
  949. {
  950. _HandleOpenOptions( punkNewWindow, ptgnNotify);
  951. ptgnNotify->OnCreate(punkNewWindow, GetTickCount());
  952. ptgnNotify->Release();
  953. ptgnNotify = NULL;
  954. pbc->RevokeObjectParam(TARGET_NOTIFY_OBJECT_NAME);
  955. }
  956. LPHLINKFRAME phf;
  957. hres = punkNewWindow->QueryInterface(IID_PPV_ARG(IHlinkFrame, &phf));
  958. if (SUCCEEDED(hres))
  959. {
  960. ITargetFramePriv * ptgfp;
  961. if (NULL == pihlNavigate)
  962. {
  963. hres = punkNewWindow->QueryInterface(IID_PPV_ARG(ITargetFramePriv, &ptgfp));
  964. }
  965. if (SUCCEEDED(hres))
  966. {
  967. if (pihlNavigate)
  968. {
  969. hres = phf->Navigate(grfHLNF & ~HLNF_OPENINNEWWINDOW,
  970. pbc,
  971. pibsc,
  972. pihlNavigate);
  973. }
  974. else
  975. {
  976. // HACK - see this methods comments
  977. _SetReferrer(ptgfp);
  978. hres = ptgfp->NavigateHack(grfHLNF & ~HLNF_OPENINNEWWINDOW,
  979. pbc,
  980. pibsc,
  981. NULL,
  982. pszUrl,
  983. pszLocation);
  984. }
  985. if (FAILED(hres))
  986. {
  987. TraceMsg(DM_ERROR, "CIEFA::_JumpTo marshalled IHlinkFrame::Navigate failed %x", hres);
  988. }
  989. ShowHlinkFrameWindow(punkNewWindow);
  990. if (NULL == pihlNavigate)
  991. {
  992. ptgfp->Release();
  993. }
  994. if(SUCCEEDED(hres) && pibsc)
  995. {
  996. _SetPendingNavigateContext(NULL, NULL);
  997. }
  998. }
  999. phf->Release();
  1000. }
  1001. }
  1002. }
  1003. else
  1004. {
  1005. //
  1006. // If NEWBROWSER is specified when there is no top level
  1007. // browser, we should ask IE/Shell to do browsing.
  1008. // We don't pass HLNF_OPENINNEWWINDOW in this case.
  1009. //
  1010. // Notify object doing navigation that we are the object implementing IWebBrowserApp
  1011. if (ptgnNotify) ptgnNotify->OnReuse(punkThis);
  1012. if (pihlNavigate)
  1013. {
  1014. hres = HlinkFrameNavigate(grfHLNF & ~HLNF_OPENINNEWWINDOW,
  1015. NULL, NULL, pihlNavigate, NULL);
  1016. }
  1017. else
  1018. {
  1019. hres = HlinkFrameNavigateNHL(grfHLNF & ~HLNF_OPENINNEWWINDOW,
  1020. NULL, NULL, NULL, pszUrl, pszLocation);
  1021. }
  1022. }
  1023. }
  1024. else
  1025. {
  1026. // Oldstyle AOL or other 3rd Party, wait for registration of
  1027. // WebBrowserOC, which calls us back on _ptgnNotify
  1028. _WaitForNotify();
  1029. // We timed out the window create, notify caller
  1030. if (_ptgnNotify)
  1031. _ptgnNotify->OnCreate(NULL, 0);
  1032. _RevokeCallback();
  1033. }
  1034. }
  1035. if (punkNewWindow)
  1036. punkNewWindow->Release();
  1037. }
  1038. else
  1039. {
  1040. TraceMsg(DM_ERROR, "IEAuto::_JumpTo _PidlFromUrlEtc (1) failed %x", hres);
  1041. }
  1042. }
  1043. if (pszHeaders)
  1044. {
  1045. LocalFree(pszHeaders);
  1046. pszHeaders = NULL;
  1047. }
  1048. if (stgPostData.tymed != TYMED_NULL)
  1049. {
  1050. ReleaseStgMedium(&stgPostData);
  1051. }
  1052. }
  1053. else
  1054. {
  1055. // Notify object doing navigation that we are the object implementing IWebBrowserApp
  1056. if (ptgnNotify) ptgnNotify->OnReuse(punkThis);
  1057. hres = _PidlFromUrlEtc(uiCP, pszUrl, pszLocation, &pidl);
  1058. if (SUCCEEDED(hres))
  1059. {
  1060. hres = _psb->BrowseObject(pidl, flags);
  1061. }
  1062. else
  1063. {
  1064. TraceMsg(DM_ERROR, "IEAuto::_JumpTo _PidlFromUrlEtc (2) failed %x", hres);
  1065. }
  1066. }
  1067. if (pidl)
  1068. {
  1069. HFRMMSG2("_JumpTo _psb->BrowseObject returned", hres, 0);
  1070. ILFree(pidl);
  1071. }
  1072. if (ptgnNotify)
  1073. {
  1074. ptgnNotify->Release();
  1075. pbc->RevokeObjectParam(TARGET_NOTIFY_OBJECT_NAME);
  1076. }
  1077. SAFERELEASE(punkThis);
  1078. return hres;
  1079. }
  1080. HRESULT CIEFrameAuto::QueryService(REFGUID guidService, REFIID riid, void ** ppvObj)
  1081. {
  1082. *ppvObj = NULL;
  1083. // WARNING: Note that we are not following the strict semantics of
  1084. // ISP::QueryService. It is, however, OK because this (the fact that
  1085. // IHlinkFrame support IServiceProvider) is not public.
  1086. if (IsEqualIID(guidService, SID_SOmWindow))
  1087. {
  1088. return _omwin.QueryInterface(riid, ppvObj);
  1089. }
  1090. else if (IsEqualIID(guidService, IID_IHlinkFrame))
  1091. {
  1092. SERVMSG("QueryService called", _pbc, _pbsc);
  1093. if (IsEqualIID(riid, IID_IBindCtx) && _pbc)
  1094. {
  1095. *ppvObj = _pbc;
  1096. _pbc->AddRef();
  1097. }
  1098. else if (IsEqualIID(riid, IID_IBindStatusCallback) && _pbsc)
  1099. {
  1100. *ppvObj = _pbsc;
  1101. _pbsc->AddRef();
  1102. }
  1103. else
  1104. {
  1105. return QueryInterface(riid, ppvObj);
  1106. }
  1107. }
  1108. else if (IsEqualIID(guidService, SID_PendingBindStatusCallback))
  1109. {
  1110. if (IsEqualIID(riid, IID_IBindStatusCallback) && _pbscPending)
  1111. {
  1112. *ppvObj = _pbscPending;
  1113. _pbscPending->AddRef();
  1114. }
  1115. }
  1116. else if (_psp)
  1117. {
  1118. return _psp->QueryService(guidService, riid, ppvObj);
  1119. }
  1120. return *ppvObj ? S_OK : E_FAIL;
  1121. }
  1122. HRESULT CIEFrameAuto::Exec(
  1123. /* [unique][in] */ const GUID *pguidCmdGroup,
  1124. /* [in] */ DWORD nCmdID,
  1125. /* [in] */ DWORD nCmdexecopt,
  1126. /* [unique][in] */ VARIANTARG *pvarargIn,
  1127. /* [unique][out][in] */ VARIANTARG *pvarargOut)
  1128. {
  1129. HRESULT hres = S_OK;
  1130. if (pguidCmdGroup)
  1131. {
  1132. if (IsEqualGUID(CGID_Explorer, *pguidCmdGroup))
  1133. {
  1134. switch(nCmdID)
  1135. {
  1136. case SBCMDID_CANCELNAVIGATION:
  1137. _CancelPendingNavigation(NULL);
  1138. break;
  1139. case SBCMDID_SELECTHISTPIDL:
  1140. case SBCMDID_HISTSFOLDER:
  1141. if (_poctFrameTop)
  1142. hres = _poctFrameTop->Exec(pguidCmdGroup, nCmdID, nCmdexecopt, pvarargIn, pvarargOut);
  1143. else
  1144. hres = S_OK;
  1145. break;
  1146. case SBCMDID_IESHORTCUT:
  1147. #ifdef BROWSENEWPROCESS_STRICT // "Nav in new process" has become "Launch in new process", so this is no longer needed
  1148. // If this is an IE shortcut and browse in a new process is turned on
  1149. // and we are explorer.exe - we should pass on the request to navigate to
  1150. // this shortcut. The caller is expected to create a new window/process to
  1151. // launch this shortcut
  1152. if (IsBrowseNewProcessAndExplorer())
  1153. hres = E_FAIL;
  1154. else
  1155. #endif
  1156. hres = _NavIEShortcut(pvarargIn,pvarargOut);
  1157. break;
  1158. case SBCMDID_GETSHORTCUTPATH:
  1159. if (_pwszShortcutPath && pvarargOut)
  1160. {
  1161. pvarargOut->bstrVal = SysAllocString(_pwszShortcutPath);
  1162. if (pvarargOut->bstrVal)
  1163. pvarargOut->vt = VT_BSTR; //no need to set hres=S_OK since it is inited already
  1164. else
  1165. hres = E_OUTOFMEMORY;
  1166. }
  1167. else
  1168. {
  1169. if (pvarargOut)
  1170. pvarargOut->vt = VT_EMPTY;
  1171. hres = E_FAIL;
  1172. }
  1173. break;
  1174. default:
  1175. hres = OLECMDERR_E_NOTSUPPORTED;
  1176. }
  1177. }
  1178. else if (IsEqualGUID(CGID_ShortCut, *pguidCmdGroup))
  1179. {
  1180. if (_poctFrameTop) // we must check!
  1181. hres = _poctFrameTop->Exec(&CGID_ShortCut, nCmdID, nCmdexecopt, pvarargIn, pvarargOut);
  1182. else
  1183. hres = OLECMDERR_E_NOTSUPPORTED;
  1184. }
  1185. else if (IsEqualGUID(CGID_ShellDocView, *pguidCmdGroup))
  1186. {
  1187. switch (nCmdID)
  1188. {
  1189. case SHDVID_DELEGATEWINDOWOM:
  1190. _omwin.SetDelegationPolicy(V_BOOL(pvarargIn));
  1191. break;
  1192. default:
  1193. hres = OLECMDERR_E_NOTSUPPORTED;
  1194. }
  1195. }
  1196. else if (IsEqualGUID(CGID_InternetExplorer, *pguidCmdGroup))
  1197. // CGID_InternetExplorer are public defined in msiehost.h
  1198. {
  1199. switch (nCmdID)
  1200. {
  1201. case IECMDID_CLEAR_AUTOCOMPLETE_FOR_FORMS:
  1202. {
  1203. if (pvarargIn->vt == VT_I4)
  1204. {
  1205. hres = ClearAutoSuggestForForms(V_I4(pvarargIn));
  1206. }
  1207. else
  1208. hres = E_INVALIDARG;
  1209. }
  1210. break;
  1211. case IECMDID_SETID_AUTOCOMPLETE_FOR_FORMS:
  1212. {
  1213. if ((pvarargIn->vt == VT_UI8) ||
  1214. (pvarargIn->vt == VT_I8))
  1215. {
  1216. hres = SetIdAutoSuggestForForms(((GUID *)(&pvarargIn->ullVal)), _omwin.IntelliForms());
  1217. }
  1218. else
  1219. hres = E_INVALIDARG;
  1220. }
  1221. break;
  1222. default:
  1223. hres = OLECMDERR_E_NOTSUPPORTED;
  1224. }
  1225. }
  1226. else
  1227. {
  1228. hres = OLECMDERR_E_UNKNOWNGROUP;
  1229. }
  1230. }
  1231. else
  1232. {
  1233. hres = OLECMDERR_E_UNKNOWNGROUP;
  1234. }
  1235. return hres;
  1236. }
  1237. BOOL CIEFrameAuto::_fNavigationPending()
  1238. {
  1239. // unfortunately, the hyperlink frame doesn't REALLY know when there's
  1240. // a navigation pending or not because people might not call OnReleaseNavigation.
  1241. // only the real browser knows.
  1242. if (_pmsc)
  1243. {
  1244. MSOCMD rgCmd;
  1245. rgCmd.cmdID = SBCMDID_CANCELNAVIGATION;
  1246. rgCmd.cmdf = 0;
  1247. _pmsc->QueryStatus(&CGID_Explorer, 1, &rgCmd, NULL);
  1248. return (rgCmd.cmdf & MSOCMDF_ENABLED);
  1249. }
  1250. return FALSE;
  1251. }
  1252. HRESULT CIEFrameAuto::QueryStatus(const GUID *pguidCmdGroup,
  1253. ULONG cCmds, OLECMD rgCmds[], OLECMDTEXT *pcmdtext)
  1254. {
  1255. if (pguidCmdGroup && IsEqualGUID(CGID_Explorer, *pguidCmdGroup))
  1256. {
  1257. for (ULONG i = 0; i < cCmds; i++)
  1258. {
  1259. switch (rgCmds[i].cmdID)
  1260. {
  1261. case SBCMDID_CANCELNAVIGATION:
  1262. rgCmds[i].cmdf = _fNavigationPending() ? MSOCMDF_ENABLED : 0;
  1263. break;
  1264. case SBCMDID_WRITEHIST:
  1265. rgCmds[i].cmdf = _fSuppressHistory ? 0:MSOCMDF_ENABLED;
  1266. break;
  1267. case SBCMDID_SELECTHISTPIDL:
  1268. rgCmds[i].cmdf = _fSuppressSelect || !_poctFrameTop ? 0:MSOCMDF_ENABLED;
  1269. break;
  1270. default:
  1271. rgCmds[i].cmdf = 0;
  1272. break;
  1273. }
  1274. }
  1275. }
  1276. else
  1277. {
  1278. return OLECMDERR_E_UNKNOWNGROUP;
  1279. }
  1280. if (pcmdtext)
  1281. {
  1282. pcmdtext->cmdtextf = MSOCMDTEXTF_NONE;
  1283. pcmdtext->cwActual = 0;
  1284. }
  1285. return NOERROR;
  1286. }
  1287. HRESULT CIEFrameAuto::_PidlFromUrlEtc(UINT uiCP, LPCWSTR pszUrl, LPWSTR pszLocation, LPITEMIDLIST* ppidl)
  1288. {
  1289. *ppidl = NULL; // assumes error
  1290. // ALGORITHM:
  1291. // - First, we call IEParseDisplayName to generate the pidl
  1292. // to the specified URL or file name.
  1293. // - if we have fragment (pszLocation) specified,
  1294. // we call IEILAppendFragment() to add the hidden fragment id
  1295. if (_pbs == NULL) //Make sure we have a IBrowserService.
  1296. return (S_FALSE);
  1297. HRESULT hr = _pbs->IEParseDisplayName(uiCP, pszUrl, ppidl);
  1298. // This is ugly, if it's a file path that failed to parse because
  1299. // it doesn't exist, we want to create a SimpleIDList so we display
  1300. // a res: navigation failed IFrame instead of the err dlg displayed
  1301. // in DisplayParseError() below.
  1302. if (FAILED(hr))
  1303. {
  1304. TCHAR szPath[MAX_PATH];
  1305. DWORD cchBuf = ARRAYSIZE(szPath);
  1306. // If it's a FILE URL, convert it to a path.
  1307. if (IsFileUrlW(pszUrl) && SUCCEEDED(PathCreateFromUrl(pszUrl, szPath, &cchBuf, 0)))
  1308. {
  1309. // That worked, we are done because our buffer is now full.
  1310. }
  1311. else
  1312. {
  1313. // We now need to copy to the buffer and we assume it's a path.
  1314. StrCpyN(szPath, pszUrl, ARRAYSIZE(szPath));
  1315. }
  1316. *ppidl = SHSimpleIDListFromPath(szPath);
  1317. if (*ppidl)
  1318. hr = S_OK;
  1319. }
  1320. if (SUCCEEDED(hr))
  1321. {
  1322. if (pszLocation && *pszLocation)
  1323. {
  1324. *ppidl = IEILAppendFragment(*ppidl, pszLocation);
  1325. hr = *ppidl ? S_OK : E_OUTOFMEMORY;
  1326. }
  1327. }
  1328. else
  1329. {
  1330. //
  1331. // NOTES: This behavior is new in IE4.0. We are adding
  1332. // this message box based on the request (bug-report)
  1333. // from Office guys. (SatoNa)
  1334. //
  1335. hr = _pbs->DisplayParseError(hr, pszUrl);
  1336. }
  1337. return hr;
  1338. }
  1339. HRESULT CIEFrameAuto::_NavIEShortcut(VARIANT *pvarIn, VARIANT *pvarargOut)
  1340. {
  1341. // need to validate verb and clsid
  1342. HRESULT hr = E_ACCESSDENIED;
  1343. READYSTATE ready;
  1344. BOOL fForceNavigate = pvarargOut ? ((VT_BOOL == pvarargOut->vt ) && (pvarargOut->boolVal)) : FALSE;
  1345. get_ReadyState(&ready);
  1346. ASSERT(pvarIn);
  1347. ASSERT(pvarIn->vt == VT_BSTR);
  1348. //
  1349. // we dont want to allow the exec to go through if this window
  1350. // is busy with something else. we should probably allow
  1351. // READYSTATE_COMPLETE and READYSTATE_UNINITIALIZED.
  1352. // if we use READYSTATE_UNINITIALIZED, we need to init the browser
  1353. // and make it visible and stuff like that. something to the
  1354. // check that IPersisteHistory->LoadHistory() does in shvocx.cpp.
  1355. // right now we will only allow COMPLETE.
  1356. //
  1357. TraceMsgW(DM_SHELLEXECOBJECT, "[%X] IEAuto_NavIEShortcut entered '%s' ready = %d", this, pvarIn->bstrVal, ready);
  1358. if (((ready == READYSTATE_COMPLETE || ready == READYSTATE_UNINITIALIZED) || (fForceNavigate))
  1359. && S_OK == IUnknown_Exec(_psbTop, &CGID_Explorer, SBCMDID_ISIEMODEBROWSER, 0, NULL, NULL))
  1360. {
  1361. IPersistFile *ppf;
  1362. if (SUCCEEDED(CoCreateInstance(CLSID_InternetShortcut, NULL, CLSCTX_ALL, IID_PPV_ARG(IPersistFile, &ppf))))
  1363. {
  1364. if (SUCCEEDED(ppf->Load(pvarIn->bstrVal, STGM_READ)))
  1365. {
  1366. LPWSTR pszUrl = NULL;
  1367. TraceMsg(DM_SHELLEXECOBJECT, "[%X] IEAuto_NavIEShortcut shortcut inited with file", this);
  1368. IUniformResourceLocatorW *purl;
  1369. if (SUCCEEDED(ppf->QueryInterface(IID_PPV_ARG(IUniformResourceLocatorW, &purl))))
  1370. {
  1371. purl->GetURL(&pszUrl);
  1372. purl->Release();
  1373. }
  1374. if (pszUrl)
  1375. {
  1376. TraceMsgW(DM_SHELLEXECOBJECT, "[%X] IEAuto_NavIEShortcut found %s", this, pszUrl);
  1377. LPITEMIDLIST pidl;
  1378. IEParseDisplayNameW(CP_ACP, pszUrl, &pidl);
  1379. if (pidl)
  1380. {
  1381. ASSERT(NULL == _pwszShortcutPathPending);
  1382. if (_pwszShortcutPathPending)
  1383. LocalFree(_pwszShortcutPathPending);
  1384. _pwszShortcutPathPending = StrDupW(pvarIn->bstrVal);
  1385. hr = _BrowseObject(pidl, SBSP_SAMEBROWSER);
  1386. if (SUCCEEDED(hr))
  1387. {
  1388. if (ready == READYSTATE_UNINITIALIZED)
  1389. put_Visible(VARIANT_TRUE);
  1390. HWND hwnd = _GetHWND();
  1391. if (hwnd)
  1392. {
  1393. if (IsIconic(hwnd))
  1394. ShowWindow(hwnd, SW_RESTORE);
  1395. else
  1396. SetForegroundWindow(hwnd);
  1397. }
  1398. }
  1399. ILFree(pidl);
  1400. }
  1401. SHFree(pszUrl);
  1402. }
  1403. }
  1404. ppf->Release();
  1405. }
  1406. }
  1407. TraceMsg(DM_SHELLEXECOBJECT, "IEAuto_NavIEShortcut returns 0x%X", hr);
  1408. return hr;
  1409. }