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.

13489 lines
426 KiB

  1. //
  2. // NOTES:
  3. //
  4. // This is the code which enables the explorer hosting (being a container)
  5. // a DocObject (a super set of OLE in-place object). In a nut shell, this
  6. // code creates an object (class CDocObjectHost) which can be plugged into
  7. // the explorer's right pane (by supporting IShellView) is also a DocObject
  8. // container (by supporting IOleClientSite, IOleInPlaceSite, ...).
  9. //
  10. // This CDocObjectHost directly supports following interfaces:
  11. //
  12. // Group 1 (to be plugged in):
  13. // IShellView, IDropTarget
  14. // Group 2 (to be a Doc site):
  15. // IOleClientSite, IOleDocumentSite
  16. // Group 3 (to be a View Site)
  17. // IOleInPlaceSite
  18. // It also supports following interfaces indirectly via contained object,
  19. // CDocObjectFrame.
  20. //
  21. // IOleInPlaceFrame, IOleCommandTarget
  22. //
  23. // The reason we export them separately is because we may need to return
  24. // a different hwnd for GetWindow method. The CDocObjectHost object always
  25. // returns hwnd of the view window, but the CDocObjectFrame returns hwnd
  26. // of the explorer in case the explorer support IOleInPlaceUIWindow.
  27. //
  28. // It also supports following interface indirectly via contained object,
  29. // CProxyActiveObject.
  30. //
  31. // IOleInPlaceActiveObject
  32. //
  33. //
  34. // --------------------------------------------------------
  35. // Explorer (browser)
  36. // --------------------------------------------------------
  37. // ^ | |
  38. // | | |
  39. // ISB (+IOIUI) ISV IOIAO
  40. // | | |
  41. // | V |
  42. // ----------------------------V---------------------------
  43. // CDocObjectHost CProxyActiveObject CDocObjectFrame
  44. // ----------------------------------------------^---------
  45. // ^ | |
  46. // | | |
  47. // IOCS/IOIPS/IMDS IO/IOIPO/IMV/IMCT IOIUI/IOIF/IMCT
  48. // | | |
  49. // | V |
  50. // ---------------------------------------------------------
  51. // DocObject (Doc + View)
  52. // ---------------------------------------------------------
  53. //
  54. #include "priv.h"
  55. #include "iehelpid.h"
  56. #include "bindcb.h"
  57. #include "winlist.h"
  58. #include "droptgt.h"
  59. #include <mshtml.h> // CLSID_HTMLDocument
  60. #include <mshtmcid.h>
  61. #include "resource.h"
  62. #include <htmlhelp.h>
  63. #include <prsht.h>
  64. #include <inetcpl.h>
  65. #include <optary.h>
  66. #include "impexp.h"
  67. #include "impexpwz.h"
  68. #include "thicket.h"
  69. #include "uemapp.h"
  70. #include "iextag.h" // web folders
  71. #include "browsext.h"
  72. #include "interned.h" // IHTMLPrivateWindow
  73. #include "dochost.h"
  74. #include <mluisupp.h>
  75. #include <varutil.h>
  76. #include "msiehost.h"
  77. #include "shdocfl.h"
  78. #include "mediautil.h"
  79. #include "mediahlpr.h"
  80. #include "privacyui.hpp"
  81. #include "brdispp.h"
  82. // temp, going away once itbar edit stuff moves here
  83. #define CITIDM_EDITPAGE 10
  84. // Command group for private communication with CITBar
  85. // 67077B95-4F9D-11D0-B884-00AA00B60104
  86. const GUID CGID_PrivCITCommands = { 0x67077B95L, 0x4F9D, 0x11D0, 0xB8, 0x84,
  87. 0x00, 0xAA, 0x00, 0xB6, 0x01, 0x04 };
  88. // end temp itbar stuff
  89. // Command group for accessing Bind Context Param set by Trident (Media Bar hook)
  90. // (copied from mshtml\src\other\include\othrguid.h)
  91. static const GUID CGID_DownloadObjectBindContext = { 0x3050f3df, 0x98b5, 0x11cf, 0xbb, 0x82,
  92. 0x00, 0xaa, 0x00, 0xbd, 0xce, 0x0b };
  93. static const GUID CLSID_JITWMP8 = { 0x6BF52A52, 0x394A, 0x11d3, 0xb1, 0x53, 0x00, 0xc0, 0x4f, 0x79, 0xfa, 0xa6 };
  94. #define DBG_ACCELENTRIES 2
  95. #define OPT_ACCELENTRIES 1
  96. #define EXPLORER_EXE TEXT("explorer.exe")
  97. #define IEXPLORE_EXE TEXT("iexplore.exe")
  98. #define DBG_ACCELENTRIES_WITH_FILEMENU 6
  99. #define OPT_ACCELENTRIES_WITH_FILEMENU 5
  100. EXTERN_C const GUID IID_IDocHostObject = {0x67431840L, 0xC511, 0x11CF, 0x89, 0xA9, 0x00, 0xA0, 0xC9, 0x05, 0x41, 0x29};
  101. EXTERN_C const GUID IID_IMimeInfo = {0xF77459A0L, 0xBF9A, 0x11cf, 0xBA, 0x4E, 0x00, 0xC0, 0x4F, 0xD7, 0x08, 0x16};
  102. EXTERN_C const GUID IID_IsPicsBrowser = {0xF114C2C0L, 0x90BE, 0x11D0, 0x83, 0xB1, 0x00, 0xC0, 0x4F, 0xD7, 0x05, 0xB2};
  103. #include <shlwapi.h>
  104. #include <ratingsp.h>
  105. #include <ratings.h>
  106. #define DM_ZONECROSSING 0
  107. #define DM_SAVEASHACK 0
  108. #define DM_MIMEMAPPING 0
  109. #define DM_SELFASC TF_SHDBINDING
  110. #define DM_ACCEPTHEADER 0
  111. #define DM_DEBUGTFRAME 0
  112. #define DM_DOCHOSTUIHANDLER 0
  113. #define DM_PREMERGEDMENU 0
  114. #define DM_FOCUS 0
  115. #define DM_DOCCP 0
  116. #define DM_PICS 0
  117. #define DM_SSL 0
  118. #define KEY_BINDCONTEXTPARAM _T("BIND_CONTEXT_PARAM")
  119. // media bar entries
  120. #define WZ_RADIO_PROTOCOL L"vnd.ms.radio:"
  121. enum PlayMimeOptions {PLAYMIME_YES, PLAYMIME_NO, PLAYMIME_YESSAVE, PLAYMIME_NOSAVE};
  122. // WARNING: Never define it in shipping product.
  123. #ifdef DEBUG
  124. // #define TEST_DELAYED_SHOWMSOVIEW
  125. #endif
  126. void CShdAdviseSink_Advise(IBrowserService * pwb, IOleObject* pole);
  127. UINT MayOpenSafeOpenDialog(HWND hwndOwner,
  128. LPCTSTR pszFileClass,
  129. LPCTSTR pszURL,
  130. LPCTSTR pszCacheName,
  131. LPCTSTR pszDisplay,
  132. UINT uiCP,
  133. IUnknown * punk,
  134. IOleCommandTarget * pCmdTarget = NULL,
  135. BOOL fDisableOK = FALSE);
  136. LONG _GetSearchFormatString(DWORD dwIndex, LPTSTR psz, DWORD cbpsz);
  137. DWORD _GetErrorThreshold(DWORD dwError);
  138. BOOL IsRegisteredClient(LPCTSTR pszClient);
  139. HRESULT _GetSearchString(IServiceProvider * psp, VARIANT * pvarSearch);
  140. int EUIndexFromError(DWORD dwError);
  141. BOOL IsErrorHandled(DWORD dwError);
  142. HRESULT _GetSearchInfo(IServiceProvider * psp,
  143. LPDWORD pdwIndex,
  144. LPBOOL pfAllowSearch,
  145. LPBOOL pfContinueSearch,
  146. LPBOOL pfSentToEngine,
  147. VARIANT * pvarUrl);
  148. STDAPI _URLMONMonikerFromPidl(LPCITEMIDLIST pidl, IMoniker ** ppmk, BOOL * pfFileProtocol);
  149. LRESULT CALLBACK PolicyDlgProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam);
  150. extern BOOL IsImportExportDisabled(void);
  151. // macros
  152. #define DO_SEARCH_ON_STATUSCODE(x) ((x == 0) || (x == HTTP_STATUS_BAD_GATEWAY) || (x == HTTP_STATUS_GATEWAY_TIMEOUT))
  153. // Suite Apps Registry keys
  154. #define NEW_MAIL_DEF_KEY TEXT("Mail")
  155. #define NEW_NEWS_DEF_KEY TEXT("News")
  156. #define NEW_CONTACTS_DEF_KEY TEXT("Contacts")
  157. #define NEW_CALL_DEF_KEY TEXT("Internet Call")
  158. #define NEW_APPOINTMENT_DEF_KEY TEXT("Appointment")
  159. #define NEW_MEETING_DEF_KEY TEXT("Meeting")
  160. #define NEW_TASK_DEF_KEY TEXT("Task")
  161. #define NEW_TASKREQUEST_DEF_KEY TEXT("Task Request")
  162. #define NEW_JOURNAL_DEF_KEY TEXT("Journal")
  163. #define NEW_NOTE_DEF_KEY TEXT("Note")
  164. #ifdef DEBUG
  165. DWORD g_dwPerf = 0;
  166. #endif
  167. // #include "..\shell32\fstreex.h" // for IDFOLDER
  168. // HACK:
  169. struct IDFOLDERA
  170. {
  171. WORD cb;
  172. BYTE bFlags;
  173. };
  174. typedef IDFOLDERA* LPIDFOLDERA;
  175. const ITEMIDLIST s_idNull = { {0} };
  176. //
  177. // Icons are globally shared among multiple threads.
  178. //
  179. HICON g_hiconSSL = NULL;
  180. HICON g_hiconFortezza = NULL;
  181. HICON g_hiconOffline = NULL;
  182. HICON g_hiconPrinter = NULL;
  183. HICON g_hiconScriptErr = NULL;
  184. HICON g_hiconPrivacyImpact = NULL;
  185. HICON g_ahiconState[IDI_STATE_LAST-IDI_STATE_FIRST+1] = { NULL };
  186. #define MAX_MIXED_STR_LEN 32
  187. // OpenUIURL is just a wrapper for OpenUI, calling CreateURLMoniker() if the
  188. // caller only has an URL.
  189. extern BOOL __cdecl _FormatMessage(LPCSTR szTemplate, LPSTR szBuf, UINT cchBuf, ...);
  190. #include "asyncrat.h"
  191. #define MAX_STATUS_SIZE 128
  192. //
  193. // Set this flag if we are going to use IHlinkBrowseContext in HLINK.DLL
  194. // #define HLINK_EXTRA
  195. //
  196. // Array of http error codes and file names.
  197. //
  198. extern ErrorUrls c_aErrorUrls[];
  199. #define DM_RECYCLE DM_TRACE
  200. #define DM_BINDAPPHACK TF_SHDAPPHACK
  201. #define DM_ADVISE TF_SHDLIFE
  202. #define DM_APPHACK DM_WARNING
  203. #define NAVMSG3(psz, x, y) TraceMsg(0, "shdv NAV::%s %x %x", psz, x, y)
  204. #define PAINTMSG(psz,x) TraceMsg(0, "shd TR-PAINT::%s %x", psz, x)
  205. #define JMPMSG(psz, psz2) TraceMsg(0, "shd TR-CDOV::%s %s", psz, psz2)
  206. #define JMPMSG2(psz, x) TraceMsg(0, "shd TR-CDOV::%s %x", psz, x)
  207. #define DOFMSG(psz) TraceMsg(0, "shd TR-DOF::%s", psz)
  208. #define DOFMSG2(psz, x) TraceMsg(0, "shd TR-DOF::%s %x", psz, x)
  209. #define URLMSG(psz) TraceMsg(TF_SHDBINDING, "shd TR-DOF::%s", psz)
  210. #define URLMSG2(psz, x) TraceMsg(TF_SHDBINDING, "shd TR-DOF::%s %x", psz, x)
  211. #define URLMSG3(psz, x, y) TraceMsg(TF_SHDBINDING, "shd TR-DOF::%s %x %x", psz, x, y)
  212. #define OIPSMSG(psz) TraceMsg(0, "shd TR-OIPS::%s", psz)
  213. #define OIPSMSG3(psz, sz, p) TraceMsg(0, "shd TR-OIPS::%s %s,%x", psz, sz,p)
  214. #define VIEWMSG(psz) TraceMsg(0, "sdv TR CDOV::%s", psz)
  215. #define VIEWMSG2(psz,xx) TraceMsg(0, "sdv TR CDOV::%s %x", psz,xx)
  216. #define OPENMSG(psz) TraceMsg(TF_SHDBINDING, "shd OPENING %s", psz)
  217. #define OPENMSG2(psz, x) TraceMsg(TF_SHDBINDING, "shd OPENING %s %x", psz, x)
  218. #define HFRMMSG(psz) TraceMsg(0, "shd HFRM::%s", psz)
  219. #define HFRMMSG2(psz, x, y) TraceMsg(0, "shd HFRM::%s %x %x", psz, x, y)
  220. #define MNKMSG(psz, psz2) TraceMsg(0, "shd MNK::%s (%s)", psz, psz2)
  221. #define CHAINMSG(psz, x) TraceMsg(0, "shd CHAIN::%s %x", psz, x)
  222. #define SHVMSG(psz, x, y) TraceMsg(0, "shd SHV::%s %x %x", psz, x, y)
  223. #define HOMEMSG(psz, psz2, x) TraceMsg(TF_SHDNAVIGATE, "shd HOME::%s %s %x", psz, psz2, x)
  224. #define SAVEMSG(psz, x) TraceMsg(0, "shd SAVE::%s %x", psz, x)
  225. #define PERFMSG(psz, x) TraceMsg(TF_SHDPERF, "PERF::%s %d msec", psz, x)
  226. static const TCHAR szRegKey_SMIEM[] = TEXT("Software\\Microsoft\\Internet Explorer\\Main");
  227. static const TCHAR szRegVal_ErrDlgPerErr[] = TEXT("Error Dlg Displayed On Every Error");
  228. static const TCHAR szRegVal_ErrDlgDetailsOpen[] = TEXT("Error Dlg Details Pane Open");
  229. ////////////////////////////////////////////////////////////
  230. // ShabbirS (980917) - BugFix# 34259
  231. // Repair menuitem in the Help Menu.
  232. typedef HRESULT (* FIXIEPROC) (BOOL, DWORD);
  233. void RepairIE()
  234. {
  235. HINSTANCE hIESetup;
  236. FIXIEPROC fpFixIE;
  237. hIESetup = LoadLibrary(L"IESetup.dll");
  238. if (hIESetup)
  239. {
  240. fpFixIE = (FIXIEPROC) GetProcAddress(hIESetup,"FixIE");
  241. if (fpFixIE)
  242. {
  243. fpFixIE(TRUE,0);
  244. }
  245. FreeLibrary(hIESetup);
  246. }
  247. }
  248. BOOL _IsDesktopItem(CDocObjectHost * pdoh)
  249. {
  250. BOOL fIsDesktopItem = FALSE;
  251. IServiceProvider * psb;
  252. ASSERT(pdoh);
  253. //Check if we are a desktop component.
  254. if (SUCCEEDED(pdoh->QueryService(SID_STopLevelBrowser, IID_IServiceProvider, (void **)&psb)))
  255. {
  256. LPTARGETFRAME2 ptgf;
  257. if (SUCCEEDED(psb->QueryService(IID_ITargetFrame2, IID_ITargetFrame2, (void **)&ptgf)))
  258. {
  259. DWORD dwOptions;
  260. if (SUCCEEDED(ptgf->GetFrameOptions(&dwOptions)))
  261. {
  262. //Is this a desktop component?
  263. if (IsFlagSet(dwOptions, FRAMEOPTIONS_DESKTOP))
  264. fIsDesktopItem = TRUE;
  265. }
  266. ptgf->Release();
  267. }
  268. psb->Release();
  269. }
  270. return fIsDesktopItem;
  271. }
  272. BOOL _IsImmediateParentDesktop(CDocObjectHost *pdoh, IServiceProvider *psp)
  273. {
  274. BOOL fImmediateParentIsDesktop = FALSE;
  275. LPTARGETFRAME2 ptgf;
  276. //First check if this is hosted on desktop.
  277. if (!_IsDesktopItem(pdoh))
  278. return FALSE; //This is not a desktop item. So, the immediate parent can't be desktop!
  279. //We know that this is a desktop item. Check if the immediate parent is desktop
  280. // or it is hosted too deep on desktop!
  281. if (psp && SUCCEEDED(psp->QueryService(IID_ITargetFrame2, IID_ITargetFrame2, (void **)&ptgf)))
  282. {
  283. IUnknown *pUnkParent;
  284. //Get it's immediate parent.
  285. if(SUCCEEDED(ptgf->GetParentFrame(&pUnkParent)))
  286. {
  287. if(pUnkParent)
  288. {
  289. //Has a parent. So, the immediate parent can't be desktop!
  290. pUnkParent->Release();
  291. fImmediateParentIsDesktop = FALSE;
  292. }
  293. else
  294. fImmediateParentIsDesktop = TRUE; //No parent. Must be a desktop comp.
  295. }
  296. ptgf->Release();
  297. }
  298. return(fImmediateParentIsDesktop);
  299. }
  300. // Gets the current display name in wide char
  301. //
  302. // If fURL is TRUE, it returns file-URL with file: prefix.
  303. //
  304. HRESULT CDocObjectHost::_GetCurrentPageW(LPOLESTR * ppszDisplayName, BOOL fURL)
  305. {
  306. HRESULT hres = E_FAIL;
  307. ASSERT(_pmkCur);
  308. *ppszDisplayName = NULL;
  309. if (_pmkCur) {
  310. IBindCtx* pbc;
  311. hres = CreateBindCtx(0, &pbc);
  312. if (SUCCEEDED(hres))
  313. {
  314. hres = _pmkCur->GetDisplayName(pbc, NULL, ppszDisplayName);
  315. //
  316. // special handling just for file: urls.
  317. //
  318. if (SUCCEEDED(hres) && _fFileProtocol)
  319. {
  320. ASSERT(*ppszDisplayName);
  321. WCHAR szText[MAX_URL_STRING];
  322. DWORD cchText = SIZECHARS(szText);
  323. if (!fURL)
  324. {
  325. hres = PathCreateFromUrlW(*ppszDisplayName, szText, &cchText, 0);
  326. }
  327. else
  328. {
  329. // we need this to be in the normalized form of the URL
  330. // for internal usage. urlmon keeps them in the funny PATHURL style
  331. hres = UrlCanonicalizeW(*ppszDisplayName, szText, &cchText, 0);
  332. }
  333. if (SUCCEEDED(hres))
  334. {
  335. UINT cchDisplayName = lstrlenW(*ppszDisplayName);
  336. if (cchText > cchDisplayName)
  337. {
  338. // need to resize
  339. CoTaskMemFree(*ppszDisplayName);
  340. *ppszDisplayName = (WCHAR *)CoTaskMemAlloc((cchText + 1) * SIZEOF(WCHAR));
  341. if (*ppszDisplayName)
  342. {
  343. // go ahead and copy it in
  344. StrCpyNW(*ppszDisplayName, szText, cchText + 1);
  345. }
  346. else
  347. hres = E_OUTOFMEMORY;
  348. }
  349. else
  350. {
  351. StrCpyNW(*ppszDisplayName, szText, cchDisplayName + 1);
  352. }
  353. }
  354. }
  355. pbc->Release();
  356. }
  357. }
  358. if (FAILED(hres) && *ppszDisplayName)
  359. {
  360. OleFree(*ppszDisplayName);
  361. *ppszDisplayName = NULL;
  362. }
  363. return hres;
  364. }
  365. //
  366. // We fire NavigateError in one location in DocObjectHost
  367. // However it is fired from (n) locations in DocHostBsc
  368. // so I have extracted the common code
  369. //
  370. void
  371. CDocObjectHost::_FireNavigateErrorHelper(IHTMLWindow2 * pHTMLWindow2,
  372. DWORD dwStatusCode,
  373. BOOL * pfCancelAutoSearch,
  374. BSTR bstrURL /* = NULL */)
  375. {
  376. ASSERT(!pHTMLWindow2 || !IsBadReadPtr(pHTMLWindow2, sizeof(IHTMLWindow2*)));
  377. ASSERT(dwStatusCode != 0);
  378. ASSERT(!IsBadWritePtr(pfCancelAutoSearch, sizeof(BOOL)));
  379. ASSERT(!bstrURL || !IsBadReadPtr(bstrURL, sizeof(BSTR)));
  380. if ( ! _pwb )
  381. {
  382. TraceMsg( TF_ERROR, "CDocObjectHost::_FireNavigateErrorHelper() - _pwb is NULL!" );
  383. return;
  384. }
  385. ITridentService2 * pTridentSvc2;
  386. HRESULT hres = _pwb->QueryInterface(IID_ITridentService2, (void**)&pTridentSvc2);
  387. if (SUCCEEDED(hres))
  388. {
  389. LPOLESTR pwzURL = NULL;
  390. BSTR bstrMkURL = NULL;
  391. BSTR bstrPidlURL = NULL;
  392. BSTR bstrFrameName = NULL;
  393. if (!bstrURL)
  394. {
  395. ASSERT(!_pmkCur || !IsBadReadPtr(_pmkCur, sizeof(_pmkCur)));
  396. ASSERT(!_pbcCur || !IsBadReadPtr(_pbcCur, sizeof(_pbcCur)));
  397. if (_pmkCur && _pbcCur)
  398. {
  399. EVAL(S_OK == _pmkCur->GetDisplayName(_pbcCur, NULL, &pwzURL));
  400. bstrMkURL = SysAllocString(pwzURL);
  401. }
  402. else if (_pidl)
  403. {
  404. TCHAR szUrl[MAX_URL_STRING];
  405. HRESULT hresGDN = IEGetDisplayName(_pidl, szUrl, SHGDN_FORPARSING);
  406. if (SUCCEEDED(hresGDN))
  407. {
  408. bstrPidlURL = SysAllocString(szUrl);
  409. }
  410. else
  411. {
  412. bstrPidlURL = SysAllocString(_T(""));
  413. }
  414. }
  415. }
  416. if (pHTMLWindow2)
  417. pHTMLWindow2->get_name(&bstrFrameName);
  418. pTridentSvc2->FireNavigateError(pHTMLWindow2,
  419. bstrURL ? bstrURL : bstrMkURL ? bstrMkURL : bstrPidlURL,
  420. bstrFrameName,
  421. dwStatusCode,
  422. pfCancelAutoSearch);
  423. pTridentSvc2->Release();
  424. OleFree(pwzURL);
  425. SysFreeString(bstrPidlURL);
  426. SysFreeString(bstrMkURL);
  427. SysFreeString(bstrFrameName);
  428. }
  429. }
  430. HRESULT CDocObjectHost::_GetCurrentPage(LPTSTR szBuf, UINT cchMax, BOOL fURL)
  431. {
  432. szBuf[0] = 0; // zero out buffer
  433. WCHAR * pszDisplayName;
  434. HRESULT hres = _GetCurrentPageW(&pszDisplayName, fURL);
  435. if (SUCCEEDED(hres))
  436. {
  437. StrCpyN(szBuf, pszDisplayName, cchMax);
  438. OleFree(pszDisplayName);
  439. }
  440. return hres;
  441. }
  442. //========================================================================
  443. // CDocObjectHost members
  444. //========================================================================
  445. CDocObjectHost::CDocObjectHost(BOOL fWindowOpen /* = FALSE */) : _cRef(1), _uState(SVUIA_DEACTIVATE)
  446. {
  447. DllAddRef();
  448. TraceMsg(TF_SHDLIFE, "ctor CDocObjectHost %x", this);
  449. TraceMsg(DM_DEBUGTFRAME, "ctor CDocObjectHost %x, %x", this, &_bsc);
  450. // Initialize proxy objects (which are contained)
  451. _dof.Initialize(this);
  452. _xao.Initialize(this);
  453. #ifdef HLINK_EXTRA
  454. HRESULT hres = HlinkCreateBrowseContext(NULL, IID_IHlinkBrowseContext, (void **)&_pihlbc);
  455. TraceMsg(0, "sdv TR CDOV::constructor HlinkCreateBrowseContext returned %x", hres);
  456. #endif // HLINK_EXTRA
  457. ::_RefPicsQueries(); /* we'll free PICS async query list when last dochost is destroyed */
  458. _dwPicsKeyBase = 1;
  459. _pScriptErrList = NULL;
  460. _fScriptErrDlgOpen = FALSE;
  461. _strPriorityStatusText = NULL;
  462. _iString = -1;
  463. _uiCP = CP_ACP;
  464. _PicsProcBase._pdoh = this;
  465. VariantInit(&_varUserEnteredUrl);
  466. _fWindowOpen = fWindowOpen;
  467. ASSERT(!_fDocCanNavigate);
  468. ASSERT(!_fPrevDocHost);
  469. }
  470. CDocObjectHost::~CDocObjectHost()
  471. {
  472. ASSERT(_pole==NULL); // to catch extra release.
  473. ASSERT(_psp==NULL); // to cache extra release.
  474. ASSERT(_hwnd==NULL);
  475. ASSERT(_pmsoc==NULL);
  476. ASSERT(_pmsot==NULL);
  477. ASSERT(_pmsov==NULL);
  478. ASSERT(_pcmdMergedMenu==NULL);
  479. ASSERT(NULL == _pHTMLWindow);
  480. ASSERT(VT_EMPTY == V_VT(&_varUserEnteredUrl));
  481. if (_pScriptErrList != NULL)
  482. {
  483. _pScriptErrList->Release();
  484. }
  485. if (_strPriorityStatusText != NULL)
  486. {
  487. SysFreeString(_strPriorityStatusText);
  488. }
  489. #ifdef HLINK_EXTRA
  490. ASSERT(_phls == NULL);
  491. ATOMICRELEASE(_pihlbc);
  492. #endif // HLINK_EXTRA
  493. ::_ReleasePicsQueries();
  494. if ( _PicsProcBase._pRootDownload
  495. || _PicsProcBase._pPicsProcNext) {
  496. ASSERT(0); /* need to destroy this earlier to prevent Trident problems */
  497. _RemoveAllPicsProcessors();
  498. }
  499. if (_padvise) {
  500. _padvise->OnClose();
  501. ATOMICRELEASE(_padvise);
  502. }
  503. if (_pwszRefreshUrl)
  504. OleFree(_pwszRefreshUrl);
  505. if (_hmenuBrowser) {
  506. AssertMsg(0, TEXT("_hmenuBrowser should be NULL!"));
  507. DestroyMenu(_hmenuBrowser);
  508. }
  509. if (_hmenuFrame) {
  510. DestroyMenu(_hmenuFrame);
  511. }
  512. if (_hacc)
  513. {
  514. DestroyAcceleratorTable(_hacc);
  515. _hacc = NULL;
  516. }
  517. if (_hinstInetCpl)
  518. FreeLibrary(_hinstInetCpl);
  519. if (_ptbStd)
  520. delete [] _ptbStd;
  521. if (_pBrowsExt)
  522. {
  523. _pBrowsExt->Release();
  524. }
  525. ILFree(_pidl);
  526. _pidl = NULL;
  527. // Make it sure that View Window is released (and _psb)
  528. DestroyHostWindow(); // which will call _CloseMsoView and _UnBind
  529. _ResetOwners();
  530. TraceMsg(TF_SHDLIFE, "dtor CDocObjectHost %x", this);
  531. DllRelease();
  532. }
  533. #ifdef DEBUG
  534. /*----------------------------------------------------------
  535. Purpose: Dump the menu handles for this docobj. Optionally
  536. breaks after dumping handles.
  537. Returns:
  538. Cond: --
  539. */
  540. void
  541. CDocObjectHost::_DumpMenus(
  542. IN LPCTSTR pszMsg,
  543. IN BOOL bBreak)
  544. {
  545. if (IsFlagSet(g_dwDumpFlags, DF_DEBUGMENU))
  546. {
  547. ASSERT(pszMsg);
  548. TraceMsg(TF_ALWAYS, "DocHost: Dumping menus for %#08x %s", (LPVOID)this, pszMsg);
  549. TraceMsg(TF_ALWAYS, " _hmenuBrowser = %x, _hmenuSet = %x, _hmenuFrame = %x",
  550. _hmenuBrowser, _hmenuSet, _hmenuFrame);
  551. TraceMsg(TF_ALWAYS, " _hmenuCur = %x, _hmenuMergedHelp = %x, _hmenuObjHelp = %x",
  552. _hmenuCur, _hmenuMergedHelp, _hmenuObjHelp);
  553. _menulist.Dump(pszMsg);
  554. if (bBreak && IsFlagSet(g_dwBreakFlags, BF_ONDUMPMENU))
  555. DebugBreak();
  556. }
  557. }
  558. #endif
  559. HRESULT CDocObjectHost::QueryInterface(REFIID riid, void ** ppvObj)
  560. {
  561. static const QITAB qit[] = {
  562. QITABENTMULTI(CDocObjectHost, IOleInPlaceSite, IOleInPlaceSiteEx),
  563. QITABENTMULTI(CDocObjectHost, IOleWindow, IOleInPlaceSiteEx),
  564. QITABENT(CDocObjectHost, IOleClientSite),
  565. QITABENT(CDocObjectHost, IOleDocumentSite),
  566. QITABENT(CDocObjectHost, IOleCommandTarget),
  567. QITABENT(CDocObjectHost, IServiceProvider),
  568. QITABENT(CDocObjectHost, IViewObject),
  569. QITABENT(CDocObjectHost, IAdviseSink),
  570. QITABENT(CDocObjectHost, IDocHostObject),
  571. QITABENT(CDocObjectHost, IDocHostUIHandler),
  572. QITABENT(CDocObjectHost, IDocHostUIHandler2),
  573. QITABENT(CDocObjectHost, IDocHostShowUI),
  574. QITABENT(CDocObjectHost, IDispatch),
  575. QITABENT(CDocObjectHost, IPropertyNotifySink),
  576. QITABENT(CDocObjectHost, IOleControlSite),
  577. { 0 },
  578. };
  579. static const QITAB qit1[] = {
  580. QITABENT(CDocObjectHost, IOleInPlaceSiteEx),
  581. { 0 },
  582. };
  583. HRESULT hr = QISearch(this, qit, riid, ppvObj);
  584. if (hr == S_OK)
  585. return S_OK;
  586. if (_pWebOCInPlaceSiteEx)
  587. return QISearch(this, qit1, riid, ppvObj);
  588. return hr;
  589. }
  590. void CDocObjectHost::_ResetOwners()
  591. {
  592. _pszLocation = NULL;
  593. _uiCP = CP_ACP;
  594. _ReleasePendingObject();
  595. ATOMICRELEASE(_psv);
  596. ATOMICRELEASE(_pmsoctView);
  597. ATOMICRELEASE(_pdvs);
  598. ATOMICRELEASE(_psb);
  599. ATOMICRELEASE(_pwb);
  600. ATOMICRELEASE(_phf);
  601. ATOMICRELEASE(_pocthf);
  602. ATOMICRELEASE(_punkSFHistory);
  603. ATOMICRELEASE(_pmsoctBrowser);
  604. ATOMICRELEASE(_psp);
  605. ATOMICRELEASE(_peds);
  606. ATOMICRELEASE(_pedsHelper);
  607. ATOMICRELEASE(_pWebOCUIHandler);
  608. ATOMICRELEASE(_pWebOCUIHandler2);
  609. ATOMICRELEASE(_pWebOCShowUI);
  610. ATOMICRELEASE(_pWebOCInPlaceSiteEx);
  611. // Release cached OleInPlaceUIWindow of the browser
  612. ATOMICRELEASE(_pipu);
  613. // Tell embedded CDocHostUIHandler object to release its references on us.
  614. _dhUIHandler.SetSite(NULL);
  615. }
  616. ULONG CDocObjectHost::AddRef()
  617. {
  618. _cRef++;
  619. TraceMsg(TF_SHDREF, "CDocObjectHost(%x)::AddRef called, new _cRef=%d", this, _cRef);
  620. return _cRef;
  621. }
  622. ULONG CDocObjectHost::Release()
  623. {
  624. _cRef--;
  625. TraceMsg(TF_SHDREF, "CDocObjectHost(%x)::Release called, new _cRef=%d", this, _cRef);
  626. if (_cRef > 0)
  627. return _cRef;
  628. delete this;
  629. return 0;
  630. }
  631. // cut & paste from browseui\itbar.cpp
  632. int RemoveHiddenButtons(TBBUTTON* ptbn, int iCount)
  633. {
  634. int i;
  635. int iTotal = 0;
  636. TBBUTTON* ptbn1 = ptbn;
  637. for (i = 0; i < iCount; i++, ptbn1++) {
  638. if (!(ptbn1->fsState & TBSTATE_HIDDEN)) {
  639. if (ptbn1 != ptbn) {
  640. *ptbn = *ptbn1;
  641. }
  642. ptbn++;
  643. iTotal++;
  644. }
  645. }
  646. return iTotal;
  647. }
  648. // We use two different image lists in the TBBUTTON array. The bitmaps for browser-specific buttons
  649. // cut/copy/paste have been moved to shdocvw, and are therefore obtained from a second image list.
  650. // MAKELONG(0,1) accesses the first image from this second list. Without a call to MAKELONG there is
  651. // a 0 in the upper integer, thereby referencing the first list by default.
  652. static const TBBUTTON c_tbStd[] = {
  653. {10, DVIDM_SHOWTOOLS, TBSTATE_ENABLED, BTNS_BUTTON, {0,0}, 0, 10},
  654. {13, DVIDM_MAILNEWS, TBSTATE_ENABLED, BTNS_WHOLEDROPDOWN, {0,0}, 0, 13 },
  655. { 8, DVIDM_FONTS, TBSTATE_ENABLED, BTNS_WHOLEDROPDOWN, {0,0}, 0, 8 },
  656. { 7, DVIDM_PRINT, TBSTATE_ENABLED, BTNS_BUTTON, {0,0}, 0, 7 },
  657. { 9, DVIDM_EDITPAGE, TBSTATE_ENABLED, BTNS_BUTTON, {0,0}, 0, 9 },
  658. {15, DVIDM_DISCUSSIONS, TBSTATE_ENABLED, BTNS_BUTTON, {0,0}, 0, 15 },
  659. {MAKELONG(0,1), DVIDM_CUT, TBSTATE_ENABLED, BTNS_BUTTON, {0,0}, 0, 0 },
  660. {MAKELONG(1,1), DVIDM_COPY, TBSTATE_ENABLED, BTNS_BUTTON, {0,0}, 0, 0 },
  661. {MAKELONG(2,1), DVIDM_PASTE, TBSTATE_ENABLED, BTNS_BUTTON, {0,0}, 0, 0 },
  662. {MAKELONG(3,1), DVIDM_ENCODING, TBSTATE_ENABLED, BTNS_WHOLEDROPDOWN, {0,0}, 0, 0 },
  663. {MAKELONG(5,1), DVIDM_PRINTPREVIEW, TBSTATE_ENABLED, BTNS_BUTTON, {0,0}, 0, 0 },
  664. };
  665. // c_tbStd and c_rest need to match exactly
  666. static const BROWSER_RESTRICTIONS c_rest[] = {
  667. REST_BTN_TOOLS,
  668. REST_BTN_MAIL,
  669. REST_BTN_FONTS,
  670. REST_BTN_PRINT,
  671. REST_BTN_EDIT,
  672. REST_BTN_DISCUSSIONS,
  673. REST_BTN_CUT,
  674. REST_BTN_COPY,
  675. REST_BTN_PASTE,
  676. REST_BTN_ENCODING,
  677. REST_BTN_PRINTPREVIEW,
  678. };
  679. #ifdef DEBUG
  680. void _AssertRestrictionOrderIsCorrect()
  681. {
  682. COMPILETIME_ASSERT(ARRAYSIZE(c_tbStd) == ARRAYSIZE(c_rest));
  683. for (UINT i = 0; i < ARRAYSIZE(c_tbStd); i++)
  684. {
  685. // If any of these rip, it means that c_rest and c_tbStd have
  686. // gotten out of sync. Need to fix up c_rest to match c_tbStd.
  687. switch (c_tbStd[i].idCommand)
  688. {
  689. case DVIDM_SHOWTOOLS: ASSERT(c_rest[i] == REST_BTN_TOOLS); break;
  690. case DVIDM_MAILNEWS: ASSERT(c_rest[i] == REST_BTN_MAIL); break;
  691. case DVIDM_FONTS: ASSERT(c_rest[i] == REST_BTN_FONTS); break;
  692. case DVIDM_PRINT: ASSERT(c_rest[i] == REST_BTN_PRINT); break;
  693. case DVIDM_EDITPAGE: ASSERT(c_rest[i] == REST_BTN_EDIT); break;
  694. case DVIDM_DISCUSSIONS: ASSERT(c_rest[i] == REST_BTN_DISCUSSIONS); break;
  695. case DVIDM_CUT: ASSERT(c_rest[i] == REST_BTN_CUT); break;
  696. case DVIDM_COPY: ASSERT(c_rest[i] == REST_BTN_COPY); break;
  697. case DVIDM_PASTE: ASSERT(c_rest[i] == REST_BTN_PASTE); break;
  698. case DVIDM_ENCODING: ASSERT(c_rest[i] == REST_BTN_ENCODING); break;
  699. case DVIDM_PRINTPREVIEW: ASSERT(c_rest[i] == REST_BTN_PRINTPREVIEW); break;
  700. default: ASSERT(0); break;
  701. }
  702. }
  703. }
  704. #endif
  705. BYTE _BtnStateFromRestIfAvailable(BOOL fAvailable, DWORD dwRest)
  706. {
  707. if (fAvailable)
  708. return SHBtnStateFromRestriction(dwRest, TBSTATE_ENABLED);
  709. return TBSTATE_HIDDEN;
  710. }
  711. BOOL CDocObjectHost::_ToolsButtonAvailable()
  712. {
  713. OLECMD rgcmd = { OLECMDID_HIDETOOLBARS, 0 };
  714. if (_pmsoctBrowser)
  715. _pmsoctBrowser->QueryStatus(NULL, 1, &rgcmd, NULL);
  716. return (rgcmd.cmdf & OLECMDF_SUPPORTED);
  717. }
  718. __inline BYTE CDocObjectHost::_DefToolsButtonState(DWORD dwRest)
  719. {
  720. BOOL fAvailable = _ToolsButtonAvailable();
  721. return _BtnStateFromRestIfAvailable(fAvailable, dwRest);
  722. }
  723. static const TCHAR c_szRegKeyCoolbar[] = TEXT("Software\\Microsoft\\Internet Explorer\\Toolbar");
  724. BYTE CDocObjectHost::_DefFontsButtonState(DWORD dwRest)
  725. {
  726. BYTE fsState = TBSTATE_ENABLED;
  727. // default to whatever the IE4 reg key specifies,
  728. // or FALSE if reg key not present (clean install)
  729. if (!SHRegGetBoolUSValue(c_szRegKeyCoolbar, TEXT("ShowFonts"), FALSE, FALSE))
  730. fsState |= TBSTATE_HIDDEN;
  731. return SHBtnStateFromRestriction(dwRest, fsState);
  732. }
  733. DWORD CDocObjectHost::_DiscussionsButtonCmdf()
  734. {
  735. if (SHRegGetBoolUSValue(c_szRegKeyCoolbar,
  736. TEXT("ShowDiscussionButton"), FALSE, TRUE) &&
  737. _pmsoctBrowser) {
  738. OLECMD rgcmds[] = {
  739. { SBCMDID_DISCUSSIONBAND, 0 },
  740. };
  741. static const int buttonsInternal[] = {
  742. DVIDM_DISCUSSIONS,
  743. };
  744. _pmsoctBrowser->QueryStatus(&CGID_Explorer, ARRAYSIZE(rgcmds), rgcmds, NULL);
  745. return rgcmds[0].cmdf;
  746. }
  747. return 0;
  748. }
  749. __inline BOOL CDocObjectHost::_DiscussionsButtonAvailable()
  750. {
  751. return (_DiscussionsButtonCmdf() & OLECMDF_SUPPORTED);
  752. }
  753. __inline BYTE CDocObjectHost::_DefDiscussionsButtonState(DWORD dwRest)
  754. {
  755. BOOL fAvailable = _DiscussionsButtonAvailable();
  756. return _BtnStateFromRestIfAvailable(fAvailable, dwRest);
  757. }
  758. BOOL CDocObjectHost::_MailButtonAvailable()
  759. {
  760. OLECMD rgcmdMailFavs[] = { { SBCMDID_DOMAILMENU, 0} };
  761. if (_pmsoctBrowser)
  762. _pmsoctBrowser->QueryStatus(&CGID_Explorer, ARRAYSIZE(rgcmdMailFavs), rgcmdMailFavs, NULL);
  763. if (rgcmdMailFavs[0].cmdf & OLECMDF_ENABLED)
  764. return TRUE;
  765. return FALSE;
  766. }
  767. __inline BYTE CDocObjectHost::_DefMailButtonState(DWORD dwRest)
  768. {
  769. BOOL fAvailable = _MailButtonAvailable();
  770. return _BtnStateFromRestIfAvailable(fAvailable, dwRest);
  771. }
  772. // We default the edit button to visible if there is an html editer registered
  773. BOOL CDocObjectHost::_EditButtonAvailable()
  774. {
  775. DWORD cchVerb;
  776. return (SUCCEEDED(AssocQueryString(0, ASSOCSTR_COMMAND, TEXT(".htm"), TEXT("edit"), NULL, &cchVerb)) ||
  777. SUCCEEDED(AssocQueryString(0, ASSOCSTR_COMMAND, TEXT("htmlfile"), TEXT("edit"), NULL, &cchVerb)));
  778. }
  779. __inline BYTE CDocObjectHost::_DefEditButtonState(DWORD dwRest)
  780. {
  781. BYTE fsState;
  782. if (_EditButtonAvailable())
  783. fsState = TBSTATE_ENABLED;
  784. else
  785. fsState = TBSTATE_HIDDEN;
  786. return SHBtnStateFromRestriction(dwRest, fsState);
  787. }
  788. void CDocObjectHost::_MarkDefaultButtons(PTBBUTTON tbStd)
  789. {
  790. // We're assuming tbStd is the same size as c_tbStd
  791. #ifdef DEBUG
  792. _AssertRestrictionOrderIsCorrect();
  793. #endif
  794. DWORD dwRest[ARRAYSIZE(c_tbStd)];
  795. BOOL fCheckRestriction = SHRestricted2(REST_SPECIFYDEFAULTBUTTONS, NULL, 0);
  796. for (UINT i = 0; i < ARRAYSIZE(c_rest); i++) {
  797. if (fCheckRestriction)
  798. dwRest[i] = SHRestricted2(c_rest[i], NULL, 0);
  799. else
  800. dwRest[i] = RESTOPT_BTN_STATE_DEFAULT;
  801. }
  802. // We want the Cut, Copy, Paste buttons to default off of the toolbar
  803. // (but available in the view-toolbars-customize dialog)
  804. // We set the state of the buttons to TBSTATE_HIDDEN here, but leave them alone
  805. // in ETCMDID_GETBUTTONS so that they appear in the customize dialog.
  806. ASSERT(tbStd[6].idCommand == DVIDM_CUT);
  807. ASSERT(tbStd[7].idCommand == DVIDM_COPY);
  808. ASSERT(tbStd[8].idCommand == DVIDM_PASTE);
  809. ASSERT(tbStd[9].idCommand == DVIDM_ENCODING);
  810. ASSERT(tbStd[10].idCommand == DVIDM_PRINTPREVIEW);
  811. for (i = 6; i <= 10; i++)
  812. tbStd[i].fsState = SHBtnStateFromRestriction(dwRest[i], tbStd[i].fsState | TBSTATE_HIDDEN);
  813. ASSERT(tbStd[0].idCommand == DVIDM_SHOWTOOLS);
  814. tbStd[0].fsState = _DefToolsButtonState(dwRest[0]);
  815. ASSERT(tbStd[1].idCommand == DVIDM_MAILNEWS);
  816. tbStd[1].fsState = _DefMailButtonState(dwRest[1]);
  817. ASSERT(tbStd[2].idCommand == DVIDM_FONTS);
  818. tbStd[2].fsState = _DefFontsButtonState(dwRest[2]);
  819. ASSERT(tbStd[3].idCommand == DVIDM_PRINT);
  820. tbStd[3].fsState = SHBtnStateFromRestriction(dwRest[3], TBSTATE_ENABLED);
  821. ASSERT(tbStd[4].idCommand == DVIDM_EDITPAGE);
  822. tbStd[4].fsState = _DefEditButtonState(dwRest[4]);
  823. ASSERT(tbStd[5].idCommand == DVIDM_DISCUSSIONS);
  824. tbStd[5].fsState = _DefDiscussionsButtonState(dwRest[5]);
  825. }
  826. const GUID* CDocObjectHost::_GetButtonCommandGroup()
  827. {
  828. if (_ToolsButtonAvailable())
  829. return &CLSID_MSOButtons;
  830. else
  831. return &CLSID_InternetButtons;
  832. }
  833. void CDocObjectHost::_AddButtons(BOOL fForceReload)
  834. {
  835. if (!_pBrowsExt)
  836. return;
  837. IExplorerToolbar* pxtb;
  838. if (_psp && SUCCEEDED(_psp->QueryService(SID_SExplorerToolbar, IID_IExplorerToolbar, (void **)&pxtb)))
  839. {
  840. const GUID* pguid = _GetButtonCommandGroup();
  841. HRESULT hr = pxtb->SetCommandTarget((IOleCommandTarget*)this, pguid, 0);
  842. if (!fForceReload && hr == S_FALSE) {
  843. // Another dochost already merged the buttons into the toolbar under the
  844. // same command group, so don't bother re-merging. We just need to initialize
  845. // _iString, since we're skipping the call to _pBrowsExt->InitButtons below.
  846. VARIANT var = { VT_I4 };
  847. IUnknown_Exec(_pBrowsExt, &CLSID_PrivBrowsExtCommands, PBEC_GETSTRINGINDEX, 0, &var, NULL); // should always succeed
  848. _iString = var.lVal;
  849. } else {
  850. UINT nNumExtButtons = 0;
  851. _pBrowsExt->GetNumButtons(&nNumExtButtons);
  852. int nNumButtons = nNumExtButtons + ARRAYSIZE(c_tbStd);
  853. // GetTBArray insures that tbStd != NULL, so we don't need that check here
  854. TBBUTTON *tbStd = new TBBUTTON[nNumButtons];
  855. if (tbStd != NULL)
  856. {
  857. memcpy(tbStd, c_tbStd, SIZEOF(TBBUTTON) * ARRAYSIZE(c_tbStd));
  858. UINT iStringIndex = (UINT)-1; // result of adding the string buffer to the toolbar string list
  859. HRESULT hr = _pBrowsExt->InitButtons(pxtb, &iStringIndex, pguid);
  860. ASSERT(tbStd[6].idCommand == DVIDM_CUT);
  861. ASSERT(tbStd[7].idCommand == DVIDM_COPY);
  862. ASSERT(tbStd[8].idCommand == DVIDM_PASTE);
  863. ASSERT(tbStd[9].idCommand == DVIDM_ENCODING);
  864. ASSERT(tbStd[10].idCommand == DVIDM_PRINTPREVIEW);
  865. if (SUCCEEDED(hr) && iStringIndex != -1)
  866. {
  867. tbStd[6].iString = iStringIndex;
  868. tbStd[7].iString = iStringIndex + 1;
  869. tbStd[8].iString = iStringIndex + 2;
  870. tbStd[9].iString = iStringIndex + 3;
  871. tbStd[10].iString = iStringIndex+ 4;
  872. _iString = (int)iStringIndex;
  873. }
  874. else
  875. {
  876. tbStd[6].iString = tbStd[7].iString = tbStd[8].iString = tbStd[9].iString = tbStd[10].iString = -1;
  877. _iString = -1;
  878. }
  879. // Add custom buttons to the toolbar array. We pass in the nNumButtons
  880. // as a *sanity check*...
  881. _pBrowsExt->GetButtons(&tbStd[ARRAYSIZE(c_tbStd)], nNumExtButtons, TRUE);
  882. _MarkDefaultButtons(tbStd);
  883. nNumButtons = RemoveHiddenButtons(tbStd, nNumButtons);
  884. pxtb->AddButtons(pguid, nNumButtons, tbStd);
  885. delete [] tbStd;
  886. }
  887. }
  888. pxtb->Release();
  889. }
  890. }
  891. HRESULT CDocObjectHost::UIActivate(UINT uState, BOOL fPrevViewIsDocView)
  892. {
  893. TraceMsg(TF_SHDUIACTIVATE, "DOH::UIActivate called %d->%d (this=%x)",
  894. _uState, uState, this);
  895. HRESULT hres = S_OK;
  896. UINT uStatePrev = _uState;
  897. // We are supposed to update the menu
  898. if (uState != _uState)
  899. {
  900. // There was a state transition.
  901. //
  902. _uState = uState;
  903. // If the new state is SVUIA_DEACTIVATE
  904. //
  905. if (_uState == SVUIA_DEACTIVATE)
  906. {
  907. //
  908. // When we are deactivating (we are navigating away)
  909. // we UIDeactivate the current MsoView.
  910. //
  911. _UIDeactivateMsoView();
  912. _IPDeactivateMsoView(_pmsov);
  913. _DestroyBrowserMenu();
  914. }
  915. else if (_uState == SVUIA_INPLACEACTIVATE && uStatePrev == SVUIA_ACTIVATE_FOCUS)
  916. {
  917. // Transition from SVUIA_ACTIVATE_FOCUS->SVUIA_INPLACEACTIVATE
  918. //
  919. // If we set this DONT_UIDEACTIVATE, then we stop calling
  920. // UIActivate(FALSE) when a DocObject in a frameset looses a focus.
  921. // It will solve some problems with Office apps (Excel, PPT), which
  922. // InPlaceDeactivate when we call UIActivate(FALSE). We want to treat
  923. // it as a bug, but unfortunately DocObject spec says that's OK.
  924. //
  925. // Putting this work around, however, slightly confuses MSHTML
  926. // (both classic and Trident). Once it's UIActivated, it keep
  927. // thinking that it's UIActivated and never calls onUIActivate.
  928. // Until we figure out what's the right implementation,
  929. // we can't turn this on. (SatoNa -- 11/04/96).
  930. //
  931. _GetAppHack(); // get if we don't have it yet.
  932. if (_dwAppHack & BROWSERFLAG_DONTUIDEACTIVATE) {
  933. //
  934. // HACK: We are supposed to just call UIActivate(FALSE) when
  935. // another DocObject (in the case of a frame set) became
  936. // UIActivated. Excel/PPT, however, InplaceDeactivate instead.
  937. // To work around, SriniK suggested us to call
  938. // OnDocWindowActivate(FALSE). (SatoNa)
  939. //
  940. IOleInPlaceActiveObject* piact = _xao.GetObject(); // no AddRef
  941. TraceMsg(TF_SHDAPPHACK, "DOH::UIActivate APPHACK calling %x->OnDocWindowActivate (this=%x)",
  942. piact, this);
  943. if (piact)
  944. {
  945. piact->OnDocWindowActivate(FALSE);
  946. }
  947. }
  948. else if (!(_dwAppHack & BROWSERFLAG_DONTDEACTIVATEMSOVIEW))
  949. {
  950. // HACK: In Excel, if we deactiveate the view, it never gets focus again
  951. // fix for the bug: #20906
  952. // Also, we don't want to deactivate the view
  953. // if the document is currently navigating.
  954. //
  955. _UIDeactivateMsoView();
  956. }
  957. else
  958. {
  959. // We're transitioning from SVUIA_ACTIVATE_FOCUS->SVUIA_INPLACEACTIVATE
  960. // and BROWSERFLAG_DONTDEACTIVATEMSOVIEW is set.
  961. // call the object's IOleInPlactActiveObject::OnFrameWindowActivate(FALSE);
  962. IOleInPlaceActiveObject* piact = _xao.GetObject(); // no AddRef
  963. if (piact)
  964. {
  965. piact->OnFrameWindowActivate(FALSE);
  966. }
  967. }
  968. }
  969. else if (uStatePrev == SVUIA_DEACTIVATE)
  970. {
  971. //
  972. // If UIActivate is called either
  973. // (1) when the binding is pending; _bsc._pbc!=NULL
  974. // (2) when the async binding is done; _bsc._pole!=NULL
  975. //
  976. SHVMSG("UIActivate about to call _Bind", _bsc._pbc, NULL);
  977. if (_pole == NULL && _bsc._pbc)
  978. {
  979. ASSERT(_pmkCur);
  980. IBindCtx* pbc = _bsc._pbc;
  981. pbc->AddRef();
  982. HRESULT hresT = _BindSync(_pmkCur, _bsc._pbc, _bsc._psvPrev);
  983. pbc->Release();
  984. ASSERT(_bsc._pbc==NULL);
  985. ASSERT(_bsc._psvPrev==NULL);
  986. ASSERT(_bsc._pbscChained==NULL);
  987. }
  988. hres = _EnsureActivateMsoView();
  989. // We are being asked to UI activate and we are currently deactivated. Show
  990. // the view now.
  991. if (SUCCEEDED(hres) && DocCanHandleNavigation())
  992. {
  993. _ShowMsoView();
  994. }
  995. _AddButtons(FALSE);
  996. }
  997. else
  998. {
  999. // opening a new document for 1st time (to UIActive or IPActive)
  1000. goto GoSetFocus;
  1001. }
  1002. }
  1003. else
  1004. {
  1005. TraceMsg(TF_SHDUIACTIVATE, "DOH:::UIActivate -- same uState (%x)", _uState);
  1006. GoSetFocus:
  1007. if ((_uState == SVUIA_ACTIVATE_FOCUS)) {
  1008. // see if object is already UIActive.
  1009. if (_ActiveHwnd()) {
  1010. // if it is, we have an hwnd and all we need to do
  1011. // is SetFocus (for compatibility w/ weird guys...)
  1012. if ( IsChildOrSelf( _ActiveHwnd(), GetFocus() ) != S_OK )
  1013. {
  1014. TraceMsg(TF_SHDUIACTIVATE, "DOH:::UIActivate -- calling SetFocus(%x)", _ActiveHwnd());
  1015. SetFocus(_ActiveHwnd());
  1016. }
  1017. }
  1018. else {
  1019. // we're in the OC, and it's IPActive not UIActive.
  1020. // (either that or it's the very 1st time for the main view).
  1021. // NOTE: Due to CBaseBrowser code that defers SVUIA_ACTIVATE_FOCUS until
  1022. // application is active, we can have a top level docobject go
  1023. // SVUIA_INPLACEACTIVE and then on activation of the window,
  1024. // we transition to SVUIA_ACTIVATE_FOCUS, thus never UIActivating
  1025. // the docobject (cf: BUG 62138)
  1026. hres = _DoVerbHelper(FALSE);
  1027. }
  1028. }
  1029. }
  1030. if ((_uState == SVUIA_INPLACEACTIVATE) || (_uState == SVUIA_ACTIVATE_FOCUS))
  1031. _PlaceProgressBar();
  1032. return hres;
  1033. }
  1034. //*** _DoVerbHelper -- DoVerb w/ various hacks
  1035. // NOTES
  1036. // do comments in _OnSetFocus apply here?
  1037. HRESULT CDocObjectHost::_DoVerbHelper(BOOL fOC)
  1038. {
  1039. HRESULT hres = E_FAIL;
  1040. LONG iVerb = OLEIVERB_SHOW;
  1041. MSG msg;
  1042. LPMSG pmsg = NULL;
  1043. if (_pole)
  1044. {
  1045. if (_uState == SVUIA_INPLACEACTIVATE)
  1046. {
  1047. iVerb = OLEIVERB_INPLACEACTIVATE;
  1048. }
  1049. else if ((_uState == SVUIA_ACTIVATE_FOCUS))
  1050. {
  1051. iVerb = OLEIVERB_UIACTIVATE;
  1052. }
  1053. else
  1054. {
  1055. TraceMsg(TF_ERROR, "DOC::_DoVerbHelper untested (and probably the wrong iVerb mapping)");
  1056. }
  1057. if (_pedsHelper)
  1058. {
  1059. if (SUCCEEDED(_pedsHelper->GetDoVerbMSG(&msg)))
  1060. {
  1061. pmsg = &msg;
  1062. }
  1063. }
  1064. hres = _pole->DoVerb(iVerb, pmsg, this, (UINT)-1, _hwnd, &_rcView);
  1065. if (hres == OLEOBJ_E_INVALIDVERB && iVerb == OLEIVERB_INPLACEACTIVATE)
  1066. {
  1067. hres = _pole->DoVerb(OLEIVERB_SHOW, pmsg, this, (UINT)-1, _hwnd, &_rcView);
  1068. }
  1069. if (FAILED(hres))
  1070. {
  1071. TraceMsg(DM_ERROR, "DOC::_DoVerbHelper _pole->DoVerb ##FAILED## %x", hres);
  1072. }
  1073. }
  1074. return hres;
  1075. }
  1076. void CDocObjectHost::_IPDeactivateMsoView(IOleDocumentView* pmsov)
  1077. {
  1078. IInitViewLinkedWebOC* pInitViewLinkedWebOC;
  1079. BOOL fIsViewLinked = FALSE;
  1080. TraceMsg(TF_SHDUIACTIVATE, "DOH::_IPDeactivateMsoView called (this==%x)", this);
  1081. if (pmsov)
  1082. {
  1083. // Because of NativeFrames, in the viewlinked WebOC case, the ReleaseShellView does not
  1084. // Deactivate the DocumentView. The sequence of these events is critical to Application
  1085. // Compatibility. So we force the show before the InPlaceDeactivate if we have a viewlinked WebOC.
  1086. ASSERT(_pwb);
  1087. HRESULT hres = E_FAIL;
  1088. if ( _pwb )
  1089. {
  1090. hres = _pwb->QueryInterface(IID_IInitViewLinkedWebOC, (void**)&pInitViewLinkedWebOC);
  1091. }
  1092. if (SUCCEEDED(hres))
  1093. {
  1094. hres = pInitViewLinkedWebOC->IsViewLinkedWebOC(&fIsViewLinked);
  1095. if (SUCCEEDED(hres) && fIsViewLinked)
  1096. {
  1097. pmsov->Show(FALSE);
  1098. }
  1099. pInitViewLinkedWebOC->Release();
  1100. }
  1101. IOleInPlaceObject* pipo = NULL;
  1102. HRESULT hresT = _pole->QueryInterface(IID_IOleInPlaceObject, (void **)&pipo);
  1103. if (SUCCEEDED(hresT))
  1104. {
  1105. pipo->InPlaceDeactivate();
  1106. pipo->Release();
  1107. }
  1108. if (!fIsViewLinked)
  1109. pmsov->Show(FALSE);
  1110. }
  1111. }
  1112. void CDocObjectHost::_UIDeactivateMsoView(void)
  1113. {
  1114. TraceMsg(TF_SHDUIACTIVATE, "DOH::_UIDeactivateMsoView called (this==%x)", this);
  1115. if (_pmsov)
  1116. {
  1117. _pmsov->UIActivate(FALSE);
  1118. }
  1119. }
  1120. //
  1121. // Hide the office toolbar
  1122. //
  1123. void CDocObjectHost::_HideOfficeToolbars(void)
  1124. {
  1125. if (_pmsot) {
  1126. OLECMD rgcmd = { OLECMDID_HIDETOOLBARS, 0 };
  1127. _pmsot->QueryStatus(NULL, 1, &rgcmd, NULL);
  1128. // LATCHED means hidden
  1129. rgcmd.cmdf &= (OLECMDF_SUPPORTED | OLECMDF_LATCHED);
  1130. // If it's supported and visible (not LATCHED), toggle it.
  1131. if (rgcmd.cmdf == OLECMDF_SUPPORTED) {
  1132. _pmsot->Exec(NULL, OLECMDID_HIDETOOLBARS, OLECMDEXECOPT_DONTPROMPTUSER, NULL, NULL);
  1133. }
  1134. }
  1135. }
  1136. void CDocObjectHost::_ShowMsoView(void)
  1137. {
  1138. HRESULT hres;
  1139. //
  1140. // HACK: Word97 UIDeactivate when we call SetInPlaceSite even with the
  1141. // same in-place site.
  1142. //
  1143. IOleInPlaceSite* psite;
  1144. hres = _pmsov->GetInPlaceSite(&psite);
  1145. if (SUCCEEDED(hres) && psite) {
  1146. if (psite!=this) {
  1147. _pmsov->SetInPlaceSite(this);
  1148. } else {
  1149. TraceMsg(TF_SHDAPPHACK, "DOH::_ShowMsoView not calling SetInPlaceSite because it's already set");
  1150. }
  1151. psite->Release();
  1152. } else {
  1153. _pmsov->SetInPlaceSite(this);
  1154. }
  1155. GetClientRect(_hwnd, &_rcView);
  1156. if ((_uState != SVUIA_INPLACEACTIVATE)
  1157. || !(_dwAppHack & BROWSERFLAG_MSHTML) // or if it's not Trident (office apps expect this call)
  1158. )
  1159. {
  1160. // Trident is sending progress changed messages here -- and causing Compuserve a problem.
  1161. // Flag the fact that we're UIActivating them, and suppress forwarding ProgressChanged
  1162. // messages to our container when this flag is true. (IE v4.1 bug 54787)
  1163. //
  1164. _fUIActivatingView = TRUE;
  1165. _pmsov->UIActivate(TRUE);
  1166. _fUIActivatingView = FALSE;
  1167. }
  1168. //
  1169. // HACK:
  1170. //
  1171. // We call _HideOfficeToolbars when our OnUIActivate is called.
  1172. // SriniK suggested us to do it in order to avoid flashing.
  1173. // It works well with Excel (3404), but does not work with Word.
  1174. // Word does not hide its toolbars correctly. To work around that
  1175. // bug, we call _HideofficeToolbars here again.
  1176. //
  1177. _HideOfficeToolbars();
  1178. hres = _pmsov->SetRect(&_rcView);
  1179. if (FAILED(hres)) {
  1180. TraceMsg(DM_ERROR, "DOC::_ShowMsoView _pmsov->SetRect ##FAILED## %x", hres);
  1181. }
  1182. if (FAILED(hres) && _uState == SVUIA_INPLACEACTIVATE) {
  1183. TraceMsg(TF_SHDAPPHACK, "APPHACK# DOH::_ShowMsoView calling UIActivate");
  1184. // HACKHACK: for word. they refuse to show if they aren't UIActivated.
  1185. // if the setrect fails, and we didn't do a UIActivate, do it now.
  1186. _fDontInplaceActivate = TRUE;
  1187. TraceMsg(TF_SHDAPPHACK, "HACK: CDOH::_ShowMsoView calling UIActive(TRUE) to work around Word bug");
  1188. _pmsov->UIActivate(TRUE);
  1189. _pmsov->SetRect(&_rcView);
  1190. }
  1191. // This is the other case where Trident sends Progress changed messages.
  1192. //
  1193. _fUIActivatingView = TRUE;
  1194. hres = _pmsov->Show(TRUE);
  1195. _fUIActivatingView = FALSE;
  1196. if (FAILED(hres)) {
  1197. TraceMsg(DM_ERROR, "DOH::_ShowMsoView _pmsov->Show ##FAILED## %x", hres);
  1198. }
  1199. _fDrawBackground = FALSE; /* now that we've shown the object, no need to paint our own background */
  1200. }
  1201. HRESULT CDocObjectHost::_ActivateMsoView()
  1202. {
  1203. _EnableModeless(FALSE);
  1204. #ifdef DEBUG
  1205. PERFMSG(TEXT("_ActivateMsoView"), GetCurrentTime() - g_dwPerf);
  1206. g_dwPerf = GetCurrentTime();
  1207. #endif
  1208. HRESULT hres = NOERROR;
  1209. if (!DocCanHandleNavigation() || _fWindowOpen)
  1210. {
  1211. if (!_phls)
  1212. {
  1213. _pole->QueryInterface(IID_IHlinkSource, (void **)&_phls);
  1214. }
  1215. if (_phls && !_fIsHistoricalObject)
  1216. {
  1217. //
  1218. // Special test case for IHlinkFrame marshaling.
  1219. //
  1220. hres = _phls->Navigate(0, _pszLocation);
  1221. //
  1222. // If this is one of our internal error pages, we can ignore the
  1223. // failure on the bogus location. In this case pwszLocation will
  1224. // be the original url that failed preceeded with a '#'.
  1225. //
  1226. LPOLESTR pwszUrl;
  1227. if (FAILED(hres) && SUCCEEDED(_GetCurrentPageW(&pwszUrl, TRUE)))
  1228. {
  1229. // if it begins with res: it may be our erro page
  1230. if (pwszUrl[0] == L'r' && pwszUrl[1] == L'e' && IsErrorUrl(pwszUrl))
  1231. {
  1232. // It's our internal error page, so ignore the error
  1233. hres = S_OK;
  1234. }
  1235. OleFree(pwszUrl);
  1236. }
  1237. #ifdef DEBUG
  1238. if (!_fWindowOpen && FAILED(hres))
  1239. {
  1240. TraceMsg(DM_ERROR, "DOC::_ActivateMsoView _phls->Navigate(%s) ##FAILED## %x",
  1241. _pszLocation ? _pszLocation : TEXT(""), hres);
  1242. }
  1243. #endif
  1244. }
  1245. else
  1246. {
  1247. // todo: use _DoVerbHelper? (but careful! ACT_FOCUS different)
  1248. LONG iVerb = OLEIVERB_SHOW;
  1249. MSG msg;
  1250. LPMSG pmsg = NULL;
  1251. if (_uState == SVUIA_INPLACEACTIVATE) {
  1252. iVerb = OLEIVERB_INPLACEACTIVATE;
  1253. }
  1254. if (_pedsHelper)
  1255. {
  1256. if (SUCCEEDED(_pedsHelper->GetDoVerbMSG(&msg)))
  1257. {
  1258. pmsg = &msg;
  1259. }
  1260. }
  1261. hres = _pole->DoVerb(iVerb, pmsg, this, (UINT)-1, _hwnd, &_rcView);
  1262. if (hres == OLEOBJ_E_INVALIDVERB && iVerb == OLEIVERB_INPLACEACTIVATE)
  1263. hres = _pole->DoVerb(OLEIVERB_SHOW, pmsg, this, (UINT)-1, _hwnd, &_rcView);
  1264. if (FAILED(hres)) {
  1265. TraceMsg(DM_ERROR, "DOC::_ActivateMsoView _pole->DoVerb ##FAILED## %x", hres);
  1266. }
  1267. }
  1268. }
  1269. _fPrevDocHost = TRUE;
  1270. // the doc is activated
  1271. if (SUCCEEDED(hres))
  1272. {
  1273. _ReleasePendingObject();
  1274. if (_fHaveParentSite)
  1275. {
  1276. _HideOfficeToolbars();
  1277. }
  1278. }
  1279. _EnableModeless(TRUE);
  1280. return hres;
  1281. }
  1282. void CDocObjectHost::OnInitialUpdate()
  1283. {
  1284. _fWindowOpen = FALSE;
  1285. ResetRefreshUrl();
  1286. }
  1287. void CDocObjectHost::ResetRefreshUrl()
  1288. {
  1289. if (_pwszRefreshUrl)
  1290. {
  1291. OleFree(_pwszRefreshUrl);
  1292. _pwszRefreshUrl = NULL;
  1293. }
  1294. }
  1295. //+---------------------------------------------------------------------------
  1296. //
  1297. // Member : CDocObjectHost::_NavigateDocument
  1298. //
  1299. // Synopsis : Navigates the document to the given URL
  1300. //
  1301. //+---------------------------------------------------------------------------
  1302. HRESULT
  1303. CDocObjectHost::_NavigateDocument(BSTR bstrUrl, BSTR bstrLocation)
  1304. {
  1305. HRESULT hres = E_FAIL;
  1306. DWORD dwFlags = 0;
  1307. IHTMLPrivateWindow * pPrivWindow = NULL;
  1308. ASSERT(_fDocCanNavigate && (_fPrevDocHost || _uState == SVUIA_DEACTIVATE));
  1309. ASSERT(_pHTMLWindow);
  1310. // Waiting for the real navigate call so we don't get duplicate events
  1311. if (_pwb)
  1312. {
  1313. _pwb->SetNavigateState(BNS_NORMAL);
  1314. }
  1315. if (_pHTMLWindow) // Stress fix
  1316. {
  1317. hres = _pHTMLWindow->QueryInterface(IID_IHTMLPrivateWindow, (void**)&pPrivWindow);
  1318. if (S_OK == hres)
  1319. {
  1320. CComBSTR cbstrShortCut;
  1321. IBindStatusCallback * pBindStatusCallback;
  1322. LPTSTR pszHeaders = NULL;
  1323. LPBYTE pPostData = NULL;
  1324. DWORD cbPostData = 0;
  1325. STGMEDIUM stgPostData;
  1326. BOOL fHavePostStg = FALSE;
  1327. BSTR bstrHeaders = NULL;
  1328. VARIANT vaHeaders = {0};
  1329. SAFEARRAY * psaPostData = NULL;
  1330. VARIANT vaPostData = {0};
  1331. if (SUCCEEDED(IUnknown_QueryService(_phf, SID_SHlinkFrame, IID_PPV_ARG(IBindStatusCallback, &pBindStatusCallback))))
  1332. {
  1333. GetHeadersAndPostData(pBindStatusCallback, &pszHeaders, &stgPostData, &cbPostData, NULL);
  1334. pBindStatusCallback->Release();
  1335. fHavePostStg = TRUE;
  1336. if (stgPostData.tymed == TYMED_HGLOBAL)
  1337. {
  1338. pPostData = (LPBYTE) stgPostData.hGlobal;
  1339. if (pPostData && cbPostData)
  1340. {
  1341. // make a SAFEARRAY for post data
  1342. psaPostData = MakeSafeArrayFromData(pPostData, cbPostData);
  1343. // put the post data SAFEARRAY into a variant so we can pass through automation
  1344. if (psaPostData)
  1345. {
  1346. V_VT(&vaPostData) = VT_ARRAY | VT_UI1;
  1347. V_ARRAY(&vaPostData) = psaPostData;
  1348. }
  1349. }
  1350. }
  1351. if (pszHeaders && pszHeaders[0])
  1352. {
  1353. bstrHeaders = SysAllocStringT(pszHeaders);
  1354. V_VT(&vaHeaders) = VT_BSTR;
  1355. V_BSTR(&vaHeaders) = bstrHeaders;
  1356. }
  1357. }
  1358. _GetShortCutPath(&cbstrShortCut);
  1359. _GetDocNavFlags(&dwFlags);
  1360. // Do the navigate
  1361. //
  1362. hres = pPrivWindow->SuperNavigate(bstrUrl,
  1363. bstrLocation,
  1364. cbstrShortCut,
  1365. NULL,
  1366. &vaPostData,
  1367. &vaHeaders,
  1368. dwFlags);
  1369. pPrivWindow->Release();
  1370. if (fHavePostStg)
  1371. {
  1372. ReleaseStgMedium(&stgPostData);
  1373. }
  1374. if (bstrHeaders)
  1375. {
  1376. SysFreeString(bstrHeaders);
  1377. }
  1378. if (V_ARRAY(&vaPostData))
  1379. {
  1380. ASSERT(V_VT(&vaPostData) == (VT_ARRAY | VT_UI1));
  1381. VariantClearLazy(&vaPostData);
  1382. }
  1383. _fRefresh = FALSE; // clear the refresh flag.
  1384. }
  1385. }
  1386. return hres;
  1387. }
  1388. //+---------------------------------------------------------------------------
  1389. //
  1390. // Member : CDocObjectHost::_GetShortCutPath
  1391. //
  1392. // Synopsis : Returns the shortcut path.
  1393. //
  1394. //+---------------------------------------------------------------------------
  1395. void
  1396. CDocObjectHost::_GetShortCutPath(BSTR * pbstrShortCutPath)
  1397. {
  1398. HRESULT hres;
  1399. VARIANT varShortCutPath = {0};
  1400. IOleCommandTarget * pcmdt;
  1401. ASSERT(pbstrShortCutPath);
  1402. *pbstrShortCutPath = NULL;
  1403. hres = QueryService(SID_SHlinkFrame, IID_IOleCommandTarget, (void **)&pcmdt);
  1404. if (S_OK == hres)
  1405. {
  1406. hres = pcmdt->Exec(&CGID_Explorer, SBCMDID_GETSHORTCUTPATH, 0, NULL, &varShortCutPath);
  1407. if (S_OK == hres && VT_BSTR == V_VT(&varShortCutPath) && V_BSTR(&varShortCutPath))
  1408. {
  1409. *pbstrShortCutPath = SysAllocString(V_BSTR(&varShortCutPath));
  1410. }
  1411. else if (_pocthf)
  1412. {
  1413. VariantClear(&varShortCutPath);
  1414. // if we couldn't find it on that service, try the cached HLink interface
  1415. // this is necessary for ND & Mars which provide a different implementation for the HLink interface
  1416. hres = _pocthf->Exec(&CGID_Explorer, SBCMDID_GETSHORTCUTPATH, 0, NULL, &varShortCutPath);
  1417. if (S_OK == hres && VT_BSTR == V_VT(&varShortCutPath) && V_BSTR(&varShortCutPath))
  1418. {
  1419. *pbstrShortCutPath = SysAllocString(V_BSTR(&varShortCutPath));
  1420. }
  1421. }
  1422. pcmdt->Release();
  1423. }
  1424. VariantClear(&varShortCutPath);
  1425. }
  1426. //+---------------------------------------------------------------------------
  1427. //
  1428. // Member : CDocObjectHost::_GetDocNavFlags
  1429. //
  1430. // Synopsis : Returns the flags for navigation.
  1431. //
  1432. //+---------------------------------------------------------------------------
  1433. void
  1434. CDocObjectHost::_GetDocNavFlags(DWORD * pdwDocNavFlags)
  1435. {
  1436. // Find out if we are in the middle of an autosearch.
  1437. // If we are, set the necessary document flags.
  1438. //
  1439. HRESULT hr;
  1440. DWORD dwSuffixIdx = -1;
  1441. BOOL fAllowSearch = FALSE;
  1442. BOOL fContinueSearch = FALSE;
  1443. DWORD dwNavFlags = 0;
  1444. ASSERT(pdwDocNavFlags);
  1445. hr = _GetSearchInfo(_psp, &dwSuffixIdx, &fAllowSearch,
  1446. &fContinueSearch, NULL, NULL);
  1447. if (SUCCEEDED(hr) && dwSuffixIdx > 1 && fContinueSearch)
  1448. {
  1449. // We aren't really in an autosearch, but are in
  1450. // a redirection from an autosearch (i.e., there is
  1451. // a long standing bug where the MSN autosearch page
  1452. // is placed in the travel log. When you press back,
  1453. // the search is restarted. However, if the search
  1454. // info is not reset here, the suffix index is incorrect.
  1455. //
  1456. if (!fAllowSearch)
  1457. {
  1458. _bsc._SetSearchInfo(this, 0, fAllowSearch, fContinueSearch, FALSE);
  1459. }
  1460. }
  1461. // Check to see if the navigation should be suppressed from the history
  1462. //
  1463. if ( _pwb && (S_OK == _pwb->GetFlags(&dwNavFlags))
  1464. && (dwNavFlags & BSF_NAVNOHISTORY))
  1465. {
  1466. *pdwDocNavFlags |= DOCNAVFLAG_DONTUPDATETLOG;
  1467. }
  1468. if ( _fRefresh )
  1469. {
  1470. *pdwDocNavFlags |= DOCNAVFLAG_REFRESH;
  1471. }
  1472. }
  1473. HRESULT CDocObjectHost::_EnsureActivateMsoView()
  1474. {
  1475. HRESULT hres = E_FAIL;
  1476. // if we've got an ole object and
  1477. // either we don't have a view, or we don't have an active view..
  1478. // do the activation
  1479. if (_pole)
  1480. {
  1481. if (!_pmsov || !_ActiveObject()) {
  1482. hres = _ActivateMsoView();
  1483. // Note that we should not UIActivate it here. We should wait
  1484. // until the DocObject calls our ActivateMe
  1485. // _ShowMsoView();
  1486. }
  1487. }
  1488. return hres;
  1489. }
  1490. //
  1491. // This member closes the MsoView window and releases interface
  1492. // pointers. This is essentially the reverse of _CreateMsoView.
  1493. //
  1494. void CDocObjectHost::_CloseMsoView(void)
  1495. {
  1496. ATOMICRELEASE(_pmsot);
  1497. if (_pmsov)
  1498. {
  1499. VIEWMSG(TEXT("_CloseMsoView calling pmsov->UIActivate(FALSE)"));
  1500. IOleDocumentView* pmsov = _pmsov;
  1501. _pmsov = NULL;
  1502. _fDontInplaceActivate = FALSE;
  1503. #ifdef DONT_UIDEACTIVATE
  1504. if (_uState != SVUIA_DEACTIVATE)
  1505. pmsov->UIActivate(FALSE);
  1506. #else // DONT_UIDEACTIVATE
  1507. if (_uState == SVUIA_ACTIVATE_FOCUS)
  1508. pmsov->UIActivate(FALSE);
  1509. #endif // DONT_UIDEACTIVATE
  1510. _IPDeactivateMsoView(pmsov);
  1511. pmsov->CloseView(0);
  1512. pmsov->SetInPlaceSite(NULL);
  1513. pmsov->Release();
  1514. VIEWMSG(TEXT("_CloseMsoView called pmsov->Release()"));
  1515. }
  1516. ATOMICRELEASE(_pmsoc);
  1517. }
  1518. void CDocObjectHost::_OnPaint(HDC hdc)
  1519. {
  1520. if (_pmsov && !_ActiveObject())
  1521. {
  1522. HRESULT hres;
  1523. RECT rcClient;
  1524. GetClientRect(_hwnd, &rcClient);
  1525. hres = OleDraw(_pmsov, DVASPECT_CONTENT, hdc, &rcClient);
  1526. TraceMsg(0, "shd TR ::_OnPaint OleDraw returns %x", hres);
  1527. }
  1528. }
  1529. HRESULT _GetDefaultLocation(LPWSTR pszPath, DWORD cchPathSizeIn, UINT id)
  1530. {
  1531. WCHAR szPath[MAX_URL_STRING];
  1532. DWORD cbSize = SIZEOF(szPath);
  1533. DWORD cchPathSize = cchPathSizeIn;
  1534. HRESULT hres = E_FAIL;
  1535. HKEY hkey;
  1536. // Share this code!!!
  1537. // This is Internet Explorer Specific
  1538. HKEY hkeyroot = id == IDP_CHANNELGUIDE ? HKEY_CURRENT_USER : HKEY_LOCAL_MACHINE;
  1539. if (RegOpenKeyW(hkeyroot,
  1540. L"Software\\Microsoft\\Internet Explorer\\Main",
  1541. &hkey)==ERROR_SUCCESS)
  1542. {
  1543. DWORD dwType;
  1544. LPCWSTR pszName;
  1545. switch(id) {
  1546. default:
  1547. ASSERT(0);
  1548. case DVIDM_GOHOME:
  1549. pszName = L"Default_Page_URL";
  1550. break;
  1551. case DVIDM_GOSEARCH:
  1552. pszName = L"Default_Search_URL";
  1553. break;
  1554. case IDP_UPDATE:
  1555. pszName = L"Default_Update_URL";
  1556. break;
  1557. case IDP_CHANNELGUIDE:
  1558. pszName = L"ChannelsURL";
  1559. break;
  1560. }
  1561. if (RegQueryValueExW(hkey, pszName,
  1562. 0, &dwType, (LPBYTE)szPath, &cbSize)==ERROR_SUCCESS)
  1563. {
  1564. // When reading a URL from registry, treat it like it was typed
  1565. // in on the address bar.
  1566. hres = S_OK;
  1567. if(!ParseURLFromOutsideSourceW(szPath, pszPath, &cchPathSize, NULL))
  1568. StrCpyNW(pszPath, szPath, cchPathSizeIn);
  1569. if(IsFileUrlW(pszPath))
  1570. {
  1571. cchPathSize = cchPathSizeIn;
  1572. hres = PathCreateFromUrlW(pszPath, pszPath, &cchPathSize, 0);
  1573. }
  1574. }
  1575. RegCloseKey(hkey);
  1576. }
  1577. HOMEMSG("_GetStdLocation returning",
  1578. (SUCCEEDED(hres) ? pszPath : TEXT("Error")), hres);
  1579. return hres;
  1580. }
  1581. HRESULT _GetStdLocation(LPTSTR pszPath, DWORD cchPathSize, UINT id)
  1582. {
  1583. TCHAR szPathTemp[MAX_URL_STRING];
  1584. DWORD cchTempSize = ARRAYSIZE(szPathTemp);
  1585. HRESULT hres = E_FAIL;
  1586. LPCWSTR pszName = NULL;
  1587. ASSERT(cchPathSize >= cchTempSize); // If we hit this, we will truncate the URL in some cases.
  1588. ASSERT(pszPath && (cchPathSize > 0)); // Not Optional
  1589. pszPath[0] = TEXT('\0');
  1590. // Share this code!!!
  1591. // This is Internet Explorer Specific
  1592. switch(id) {
  1593. default:
  1594. ASSERT(0);
  1595. case DVIDM_GOHOME:
  1596. pszName = L"Start Page";
  1597. break;
  1598. case DVIDM_GOFIRSTHOME:
  1599. case DVIDM_GOFIRSTHOMERO:
  1600. pszName = L"First Home Page";
  1601. break;
  1602. case DVIDM_GOSEARCH:
  1603. pszName = L"Search Page";
  1604. break;
  1605. case DVIDM_SEARCHBAR:
  1606. pszName = L"Search Bar";
  1607. break;
  1608. case DVIDM_GOLOCALPAGE:
  1609. pszName = L"Local Page";
  1610. break;
  1611. }
  1612. hres = URLSubRegQuery(szRegKey_SMIEM, pszName, TRUE,
  1613. szPathTemp, cchTempSize, URLSUB_ALL);
  1614. if (FAILED(hres) &&
  1615. ((DVIDM_GOFIRSTHOME == id) || (DVIDM_GOFIRSTHOMERO == id)))
  1616. {
  1617. // The First Home key doesn't exist so use the home key.
  1618. pszName = TEXT("Start Page");
  1619. hres = URLSubRegQuery(szRegKey_SMIEM, pszName, TRUE,
  1620. szPathTemp, cchTempSize, URLSUB_ALL);
  1621. id = DVIDM_GOHOME;
  1622. }
  1623. if (SUCCEEDED(hres))
  1624. {
  1625. // When reading a URL from registry, treat it like it was typed
  1626. // in on the address bar.
  1627. // Recursion block. If requesting the home page, and the home page is "about:home", substitute
  1628. // "about:blank" (otherwise we'll recurse to death)
  1629. if (DVIDM_GOHOME == id && !StrCmpI(szPathTemp, TEXT("about:home")) )
  1630. {
  1631. StrCpyN(szPathTemp, TEXT("about:blank"), MAX_URL_STRING);
  1632. }
  1633. if(ParseURLFromOutsideSourceW(szPathTemp, pszPath, &cchPathSize, NULL))
  1634. {
  1635. if(IsFileUrlW(pszPath))
  1636. hres = PathCreateFromUrlW(pszPath, pszPath, &cchPathSize, 0);
  1637. }
  1638. }
  1639. if (DVIDM_GOFIRSTHOME == id) // Delete that FIRSTHOME key
  1640. {
  1641. HUSKEY hUSKey;
  1642. if (ERROR_SUCCESS == SHRegOpenUSKey(szRegKey_SMIEM, KEY_WRITE, NULL, &hUSKey, FALSE))
  1643. {
  1644. SHRegDeleteUSValue(hUSKey, TEXT("First Home Page"), SHREGDEL_DEFAULT);
  1645. SHRegCloseUSKey(hUSKey);
  1646. }
  1647. hres = S_OK;
  1648. }
  1649. HOMEMSG("_GetStdLocation returning",
  1650. (SUCCEEDED(hres) ? pszPath : TEXT("Error")), hres);
  1651. return hres;
  1652. }
  1653. HRESULT WINAPI _GetDefaultLocation(UINT idp, LPWSTR pszPath, UINT cchMax)
  1654. {
  1655. switch (idp)
  1656. {
  1657. case IDP_UPDATE:
  1658. case IDP_CHANNELGUIDE:
  1659. URLSubLoadString(NULL, IDS_DEF_UPDATE+(idp-IDP_UPDATE), pszPath, cchMax, URLSUB_ALL);
  1660. break;
  1661. default:
  1662. _GetDefaultLocation(pszPath, cchMax, (idp == IDP_SEARCH) ? DVIDM_GOSEARCH : DVIDM_GOHOME);
  1663. break;
  1664. }
  1665. return S_OK;
  1666. }
  1667. HRESULT WINAPI SHDGetPageLocation(HWND hwndOwner, UINT idp, LPWSTR pszPath, UINT cchMax, LPITEMIDLIST *ppidlOut)
  1668. {
  1669. TCHAR szBuf[MAX_URL_STRING];
  1670. if (pszPath==NULL) {
  1671. pszPath = szBuf;
  1672. cchMax = ARRAYSIZE(szBuf);
  1673. }
  1674. *pszPath = L'\0';
  1675. *ppidlOut = NULL;
  1676. HRESULT hres = S_OK;
  1677. switch (idp) {
  1678. case IDP_UPDATE:
  1679. case IDP_CHANNELGUIDE:
  1680. ASSERT(IDP_CHANNELGUIDE-IDP_UPDATE == IDS_DEF_CHANNELGUIDE-IDS_DEF_UPDATE);
  1681. if (FAILED(hres = _GetDefaultLocation(pszPath, cchMax, idp)))
  1682. {
  1683. hres = _GetDefaultLocation(idp, pszPath, cchMax);
  1684. }
  1685. break;
  1686. default:
  1687. ASSERT(idp==IDP_START || idp==IDP_SEARCH);
  1688. hres = _GetStdLocation(pszPath, cchMax,
  1689. (idp == IDP_SEARCH) ? DVIDM_GOSEARCH : DVIDM_GOHOME);
  1690. if (FAILED(hres))
  1691. {
  1692. hres = _GetDefaultLocation(idp, pszPath, cchMax);
  1693. }
  1694. break;
  1695. }
  1696. if (SUCCEEDED(hres))
  1697. {
  1698. hres = IECreateFromPath(pszPath, ppidlOut);
  1699. if (FAILED(hres))
  1700. {
  1701. // IECreateFromPath() above could have failed if the default location
  1702. // was invalid. (Like file://server_no_exist/
  1703. _GetDefaultLocation(idp, pszPath, cchMax);
  1704. hres = IECreateFromPath(pszPath, ppidlOut);
  1705. }
  1706. HOMEMSG("SHDGetPageLocation SHILCreateFromPage returned", pszPath, hres);
  1707. }
  1708. return hres;
  1709. }
  1710. void CDocObjectHost::_ChainBSC()
  1711. {
  1712. if (!_bsc._pbscChained && _phf)
  1713. {
  1714. // Get "chaigned" bind status, if any
  1715. IServiceProvider * psp = NULL;
  1716. HRESULT hres = _phf->QueryInterface(IID_IServiceProvider, (void **)&psp);
  1717. CHAINMSG("_StartAsyncBinding hlf->QI returns", hres);
  1718. if (SUCCEEDED(hres))
  1719. {
  1720. ASSERT(NULL == _bsc._pbscChained);
  1721. hres = psp->QueryService(SID_SHlinkFrame, IID_IBindStatusCallback, (void **)&_bsc._pbscChained);
  1722. CHAINMSG("_StartAsyncBinding psp(hlf)->QS returns", hres);
  1723. psp->Release();
  1724. if (SUCCEEDED(hres))
  1725. {
  1726. ASSERT(NULL==_bsc._pnegotiateChained);
  1727. _bsc._pbscChained->QueryInterface(IID_IHttpNegotiate, (void **)&_bsc._pnegotiateChained);
  1728. }
  1729. }
  1730. }
  1731. }
  1732. //
  1733. // WARNING: Following two global variables are shared among multiple-threads
  1734. // in a thread. Therefore, all right-access must be serialized and all read
  1735. // access should be blocked when right is going on.
  1736. //
  1737. // Right now, we just initialize them once (based on the registry setting)
  1738. // and never update. It allows us to simplify the code quite a bit. If we
  1739. // need to update, then _RegisterMediaTypeClass should be changed significantlly
  1740. // so that we can safely handle multiple access to those hdsa's. (SatoNa)
  1741. //
  1742. HDSA g_hdsaCls = NULL;
  1743. HDSA g_hdsaStr = NULL;
  1744. BOOL CDocObjectHost::_BuildClassMapping(void)
  1745. {
  1746. if (g_hdsaCls)
  1747. {
  1748. return DSA_GetItemCount(g_hdsaCls) == DSA_GetItemCount(g_hdsaStr);
  1749. }
  1750. ENTERCRITICAL;
  1751. if (!g_hdsaCls) {
  1752. g_hdsaStr = DSA_Create(SIZEOF(LPCSTR), 32);
  1753. if (g_hdsaStr)
  1754. {
  1755. HDSA hdsaCls = DSA_Create(SIZEOF(CLSID), 32);
  1756. if (hdsaCls)
  1757. {
  1758. HKEY hkey;
  1759. if (RegOpenKey(HKEY_LOCAL_MACHINE,
  1760. TEXT("Software\\Microsoft\\Internet Explorer\\MediaTypeClass"),
  1761. &hkey) == ERROR_SUCCESS)
  1762. {
  1763. TCHAR szCLSID[64]; // enough for "{CLSID}"
  1764. for (int iKey=0;
  1765. RegEnumKey(hkey, iKey, szCLSID, SIZEOF(szCLSID)/sizeof(szCLSID[0]))==ERROR_SUCCESS;
  1766. iKey++)
  1767. {
  1768. CLSID clsid;
  1769. if (FAILED(CLSIDFromString(szCLSID, &clsid))) {
  1770. TraceMsg(DM_WARNING, "CDOH::_RMTC CLSIDFromString(%x) failed", szCLSID);
  1771. continue;
  1772. }
  1773. TraceMsg(DM_MIMEMAPPING, "CDOH::_RMTC RegEnumKey found %s", szCLSID);
  1774. HKEY hkeyCLSID;
  1775. if (RegOpenKey(hkey, szCLSID, &hkeyCLSID) == ERROR_SUCCESS)
  1776. {
  1777. for (int iValue=0; ; iValue++)
  1778. {
  1779. CHAR szFormatName[128];
  1780. DWORD dwType;
  1781. DWORD cchValueName = ARRAYSIZE(szFormatName);
  1782. //
  1783. // Keep the name ansi because it needs to get
  1784. // passed to urlmon's RegisterMediaTypeClass as
  1785. // ansi.
  1786. //
  1787. if (RegEnumValueA(hkeyCLSID, iValue, szFormatName, &cchValueName, NULL,
  1788. &dwType, NULL, NULL)==ERROR_SUCCESS)
  1789. {
  1790. TraceMsg(DM_MIMEMAPPING, "CDOH::_RMTC RegEnumValue found %s", szFormatName);
  1791. LPSTR psz = StrDupA(szFormatName);
  1792. if (psz) {
  1793. DSA_InsertItem(hdsaCls, 0xffff, &clsid);
  1794. if (DSA_InsertItem(g_hdsaStr, 0xffff, &psz)<0) {
  1795. LocalFree(psz);
  1796. psz = NULL;
  1797. break;
  1798. }
  1799. }
  1800. } else {
  1801. break;
  1802. }
  1803. }
  1804. RegCloseKey(hkeyCLSID);
  1805. } else {
  1806. TraceMsg(DM_WARNING, "CDOH::_RMTC RegOpenKey(%s) failed", szCLSID);
  1807. }
  1808. }
  1809. RegCloseKey(hkey);
  1810. } else {
  1811. TraceMsg(0, "CDOH::_RMTC RegOpenKey(MediaTypeClass) failed");
  1812. }
  1813. //
  1814. // Update g_hdsaCls at the end so that other thread won't
  1815. // access while we are adding items.
  1816. //
  1817. g_hdsaCls = hdsaCls;
  1818. ASSERT(DSA_GetItemCount(g_hdsaCls)==DSA_GetItemCount(g_hdsaStr));
  1819. }
  1820. }
  1821. }
  1822. LEAVECRITICAL;
  1823. return (g_hdsaCls && DSA_GetItemCount(g_hdsaCls)==DSA_GetItemCount(g_hdsaStr));
  1824. }
  1825. HRESULT CDocObjectHost::_RegisterMediaTypeClass(IBindCtx* pbc)
  1826. {
  1827. HRESULT hres = S_FALSE; // Assume no mapping
  1828. if (_BuildClassMapping() && DSA_GetItemCount(g_hdsaCls)) {
  1829. //
  1830. // WARNING: This code assumes that g_hdsaCls/g_hdsaStr never
  1831. // changes once they are initializes. Read notes above
  1832. // those global variables for detail.
  1833. //
  1834. hres = RegisterMediaTypeClass(pbc,
  1835. DSA_GetItemCount(g_hdsaCls),
  1836. (LPCSTR*)DSA_GetItemPtr(g_hdsaStr, 0),
  1837. (CLSID*)DSA_GetItemPtr(g_hdsaCls, 0), 0);
  1838. TraceMsg(DM_MIMEMAPPING, "CDOH::_StartAsyncBinding RegisterMTC returns %x", hres);
  1839. }
  1840. // Now see if the container has anything that needs to be registered
  1841. //
  1842. if (_psp)
  1843. {
  1844. IMimeInfo * pIMimeInfo;
  1845. hres = _psp->QueryService(SID_IMimeInfo, IID_IMimeInfo, (void **)&pIMimeInfo);
  1846. if (SUCCEEDED(hres))
  1847. {
  1848. UINT cTypes = 0;
  1849. LPCSTR *ppszTypes = NULL;
  1850. CLSID *pclsIDs= NULL;
  1851. ASSERT(pIMimeInfo);
  1852. hres = pIMimeInfo->GetMimeCLSIDMapping(&cTypes, &ppszTypes, &pclsIDs);
  1853. if (SUCCEEDED(hres)) {
  1854. if (cTypes && ppszTypes && pclsIDs) {
  1855. // Last one to register wins, so if the container wants to override what is
  1856. // already registered this should do it.
  1857. // URLMon will handle the duplicates corectly.
  1858. //
  1859. hres = RegisterMediaTypeClass(pbc, cTypes, ppszTypes, pclsIDs, 0);
  1860. TraceMsg(DM_MIMEMAPPING, "CDOH::_StartAsyncBinding RegisterMTC for Container returns %x", hres);
  1861. }
  1862. // RegisterMediaTypeClass should have made copies
  1863. // so free the containers allocations as it expects us to do
  1864. //
  1865. // CoTaskMemFree(NULL) is OK
  1866. //
  1867. CoTaskMemFree(ppszTypes);
  1868. CoTaskMemFree(pclsIDs);
  1869. }
  1870. pIMimeInfo->Release();
  1871. } else {
  1872. hres = S_FALSE;
  1873. }
  1874. }
  1875. return hres;
  1876. }
  1877. HRESULT _RegisterAcceptHeaders(IBindCtx* pbc, IShellBrowser* psb)
  1878. {
  1879. return RegisterDefaultAcceptHeaders(pbc, psb);
  1880. }
  1881. HRESULT GetAmbientBoolProp(IExpDispSupport* peds, DISPID dispid, BOOL *pb)
  1882. {
  1883. VARIANT var = {0};
  1884. // Assume failure
  1885. *pb = FALSE;
  1886. HRESULT hres = peds->OnInvoke(dispid, IID_NULL, NULL, DISPATCH_PROPERTYGET, (DISPPARAMS *)&g_dispparamsNoArgs, &var, NULL, NULL);
  1887. if (SUCCEEDED(hres))
  1888. {
  1889. // VB returns success with VT_EMPTY, so we can't assert here
  1890. if (var.vt == VT_BOOL)
  1891. {
  1892. *pb = (var.boolVal) ? TRUE : FALSE;
  1893. }
  1894. else
  1895. {
  1896. // Even though VB says VT_EMPTY, we don't know what other containers
  1897. // might shove in here. Make sure we clean up.
  1898. //
  1899. VariantClear(&var);
  1900. }
  1901. }
  1902. else
  1903. {
  1904. hres = E_FAIL;
  1905. }
  1906. return hres;
  1907. }
  1908. HRESULT CDocObjectHost::_GetOfflineSilent(BOOL *pbIsOffline, BOOL *pbIsSilent)
  1909. {
  1910. if (_peds)
  1911. {
  1912. if (pbIsOffline)
  1913. GetAmbientBoolProp(_peds, DISPID_AMBIENT_OFFLINEIFNOTCONNECTED, pbIsOffline);
  1914. if (pbIsSilent)
  1915. GetAmbientBoolProp(_peds, DISPID_AMBIENT_SILENT, pbIsSilent);
  1916. }
  1917. else
  1918. {
  1919. if (pbIsOffline)
  1920. *pbIsOffline = FALSE;
  1921. if (pbIsSilent)
  1922. *pbIsSilent = FALSE;
  1923. }
  1924. return S_OK;
  1925. }
  1926. /*
  1927. Callback function for RatingObtainQuery
  1928. */
  1929. void RatingObtainQueryCallback(DWORD dwUserData, HRESULT hr, LPCSTR pszRating, LPVOID lpvInpageRating)
  1930. {
  1931. TraceMsg(DM_PICS, "RatingObtainQueryCallback given result %x", hr);
  1932. /* WARNING: This function is called by MSRATING.DLL on a separate thread,
  1933. * not the main message loop thread. Touch nothing in important data
  1934. * structures not protected by critical sections!
  1935. *
  1936. * Merely format up a windows message with the info we have; we'll handle
  1937. * this in the main thread, if we ever get there.
  1938. *
  1939. * Note that pszRating is ignored, we count on the ratings engine to have
  1940. * called RatingCheckUserAccess for us and provide the HRESULT.
  1941. */
  1942. if (!::_PostPicsMessage(dwUserData, hr, lpvInpageRating))
  1943. {
  1944. if ( lpvInpageRating )
  1945. {
  1946. ::RatingFreeDetails(lpvInpageRating);
  1947. lpvInpageRating = NULL;
  1948. }
  1949. }
  1950. }
  1951. HRESULT CDocObjectHost::_StartAsyncBinding(IMoniker * pmk, IBindCtx * pbc, IShellView * psvPrev)
  1952. {
  1953. URLMSG(TEXT("_StartAsyncBinding called"));
  1954. HRESULT hres;
  1955. ASSERT(_bsc._pbc == NULL && _pole == NULL);
  1956. _bsc._RegisterObjectParam(pbc);
  1957. //
  1958. // Associate the client site as an object parameter to this
  1959. // bind context so that Trident can pick it up while processing
  1960. // IPersistMoniker::Load().
  1961. //
  1962. pbc->RegisterObjectParam(WSZGUID_OPID_DocObjClientSite, SAFECAST(this, IOleClientSite*));
  1963. _ChainBSC();
  1964. IUnknown * punk = NULL;
  1965. _bsc._pbc = pbc;
  1966. pbc->AddRef();
  1967. // Decide right here whether or not this frame is offline
  1968. BOOL bFrameIsOffline = FALSE;
  1969. BOOL bFrameIsSilent = FALSE;
  1970. this->_GetOfflineSilent(&bFrameIsOffline, &bFrameIsSilent);
  1971. _bsc._bFrameIsOffline = bFrameIsOffline ? TRUE : FALSE;
  1972. _bsc._bFrameIsSilent = bFrameIsSilent ? TRUE : FALSE;
  1973. BOOL bSuppressUI = (_bsc._bFrameIsSilent || _IsDesktopItem(SAFECAST(this, CDocObjectHost*))) ? TRUE : FALSE;
  1974. #ifdef DEBUG
  1975. PERFMSG(TEXT("_StartAsyncBinding Calling pmk->BindToObject"), GetCurrentTime()-g_dwPerf);
  1976. g_dwPerf = GetCurrentTime();
  1977. #endif
  1978. #ifdef DEBUG
  1979. if (g_dwPrototype & 0x00000800) {
  1980. TraceMsg(DM_TRACE, "CDOH::_StartAsyncBinding skipping CLSID mapping");
  1981. }
  1982. else
  1983. #endif
  1984. {
  1985. // Register overriding mime->CLSID mapping
  1986. _RegisterMediaTypeClass(pbc);
  1987. }
  1988. // Register accept headers
  1989. _RegisterAcceptHeaders(pbc, _psb);
  1990. if (_pwb)
  1991. {
  1992. _pwb->SetNavigateState(BNS_BEGIN_NAVIGATE);
  1993. }
  1994. _StartBasePicsProcessor();
  1995. //
  1996. // Crazy sync/async behavior of URLMON. - zekel - 6-AUG-97
  1997. // any of the following may occur:
  1998. //
  1999. // 1. SUCCESS or FAILURE: we receive sync E_PENDING from BindToObject,
  2000. // and then get an Async HRESULT on OnStopBinding().
  2001. // this is the most common case and the basic design.
  2002. //
  2003. // 2. SUCCESS: we receive sync S_OK from BindToObject and
  2004. // need to complete the async behavior on our BSCB ourself
  2005. // since urlmon started but did not finish.
  2006. //
  2007. // 3. SUCCESS: while inside BindToObject(), we receive sync S_OK
  2008. // from OnStopBinding(), and then BindToObject returns with S_OK.
  2009. //
  2010. // 4. FAILURE: simplest case is an error being returned from BindToObject()
  2011. // but without an any OnStopBinding() so we need to complete
  2012. // the async behavior on our BSCB ourself since urlmon started but did not finish.
  2013. // this usually occurs when accessing local files.
  2014. //
  2015. // 5. FAILURE: while inside BindToObject(), we receive sync S_OK from OnStopBinding(),
  2016. // and then BindToObject returns with some other error that needs to be handled.
  2017. // this occurs with some malformed urls.
  2018. //
  2019. // 6. FAILURE: while inside BindToObject(), we receive a sync error from OnStopBinding(),
  2020. // and then BindToObject returns with some other error (usually E_FAIL).
  2021. // we need to trust the first one. this occurs when wininet
  2022. // returns syncronous errors, and its error is the one returned in OnStopBinding()
  2023. //
  2024. // 7. FAILURE: while inside BindToObject(), we receive a sync error from OnStopBinding(),
  2025. // and then BindToObject returns with E_PENDING. which we think means everything
  2026. // is going great, and urlmon thinks it is done. this happens with a file: to
  2027. // a resource that is not hostable. we need to show the download UI.
  2028. //
  2029. // in order to support all the errors in the most consistent and safe manner,
  2030. // we defer any errors in OnStopBinding() if they are delivered synchronously
  2031. // on BindToObject(). the OnStopBinding() error always overrides the BindToObject()
  2032. // error, but any error will always override any success.
  2033. //
  2034. ASSERT(S_OK == _hrOnStopBinding);
  2035. _fSyncBindToObject = TRUE;
  2036. URLMSG(TEXT("_StartAsyncBinding calling pmk->BindToObject"));
  2037. hres = pmk->BindToObject(pbc, NULL, IID_IUnknown, (void**)&punk);
  2038. URLMSG3(TEXT("_StartAsyncBinding pmk->BindToObject returned"), hres, punk);
  2039. _fSyncBindToObject = FALSE;
  2040. if (SUCCEEDED(_hrOnStopBinding) && (SUCCEEDED(hres) || hres==E_PENDING))
  2041. {
  2042. hres = S_OK;
  2043. if (_bsc._pbc) {
  2044. //
  2045. // In case OnStopBinding hasn't been called.
  2046. //
  2047. if (!_pole)
  2048. {
  2049. if (psvPrev)
  2050. {
  2051. _bsc._psvPrev = psvPrev;
  2052. psvPrev->AddRef();
  2053. }
  2054. }
  2055. else
  2056. {
  2057. URLMSG3(TEXT("_StartAsyncBinding we've already got _pole"), hres, _pole);
  2058. }
  2059. //
  2060. // If moniker happen to return the object synchronously, emulate
  2061. // OnDataAvailable callback and OnStopBinding.
  2062. //
  2063. if (punk)
  2064. {
  2065. _bsc.OnObjectAvailable(IID_IUnknown, punk);
  2066. _bsc.OnStopBinding(hres, NULL);
  2067. punk->Release();
  2068. ASSERT(_bsc._pbc==NULL);
  2069. }
  2070. }
  2071. else
  2072. {
  2073. //
  2074. // OnStopBinding has been already called.
  2075. //
  2076. if (punk)
  2077. {
  2078. AssertMsg(0, TEXT("CDOH::_StartAsyncBinding pmk->BindToObject returned punk after calling OnStopBinding")); // Probably URLMON bug.
  2079. punk->Release();
  2080. }
  2081. }
  2082. }
  2083. else
  2084. {
  2085. // Binding failed.
  2086. TraceMsg(DM_WARNING, "CDOH::_StartAsyncBinding failed (%x)", hres);
  2087. //
  2088. // Urlmon is inconsistent in it's error handling - zekel - 4-AUG-97
  2089. // urlmon can return errors in three different ways from BindToObject()
  2090. // 1. it can return back a simple syncronous error. without calling OnStopBinding()
  2091. //
  2092. // 2. it can return a sync error,
  2093. // but call OnStopBinding() with S_OK first on the same thread;
  2094. //
  2095. // 3. it can return a sync error,
  2096. // but also call OnStopBinding() with the real Error first on the same thread.
  2097. //
  2098. // 4. it can return E_PENDING,
  2099. // but already have called OnStopBinding() with the real error.
  2100. //
  2101. // SOLUTIONS:
  2102. // in all cases of error in OnStopBinding(), we will now postpone the OnStopBinding processing util after
  2103. // we have returned from the BindToObject(). we try to use the best error.
  2104. // we allow successful OnStopBinding() to pass through unmolested, and trap
  2105. // the error here if necessary.
  2106. //
  2107. if (FAILED(_hrOnStopBinding))
  2108. hres = _hrOnStopBinding;
  2109. if (_bsc._pbc)
  2110. _bsc.OnStopBinding(hres, NULL);
  2111. else if (!bSuppressUI)
  2112. {
  2113. //
  2114. // OnStopBinding was already called, but with a success
  2115. // so we need to handle the error here. this happens
  2116. // with some invalid URLs like http:/server
  2117. //
  2118. BOOL fCancelErrorPage = FALSE;
  2119. _FireNavigateErrorHelper(NULL, ERRORPAGE_SYNTAX, &fCancelErrorPage);
  2120. if (fCancelErrorPage)
  2121. {
  2122. _CancelPendingNavigation(TRUE, FALSE);
  2123. }
  2124. else
  2125. {
  2126. // Fix for W98 webtv app. If we're in a frame don't
  2127. // blow away the frame set to dispaly the error.
  2128. //
  2129. if (!_fHaveParentSite)
  2130. {
  2131. _bsc._NavigateToErrorPage(ERRORPAGE_SYNTAX, this, FALSE);
  2132. }
  2133. }
  2134. }
  2135. ASSERT(_bsc._pbc==NULL);
  2136. }
  2137. return hres;
  2138. }
  2139. void CDocObjectHost::_ReleasePendingObject(BOOL fIfInited)
  2140. {
  2141. HRESULT hres;
  2142. IOleObject *polePending;
  2143. #ifdef TRIDENT_NEEDS_LOCKRUNNING
  2144. IRunnableObject *pro;
  2145. #endif
  2146. if (fIfInited == FALSE && _fPendingWasInited == FALSE)
  2147. return;
  2148. if (_punkPending)
  2149. {
  2150. if (_fCreatingPending)
  2151. {
  2152. _fAbortCreatePending = 1;
  2153. return;
  2154. }
  2155. if (!_fPendingNeedsInit && !IsSameObject(_punkPending, _pole))
  2156. {
  2157. hres = _punkPending->QueryInterface(IID_IOleObject, (void **) &polePending);
  2158. if (SUCCEEDED(hres)) {
  2159. LPOLECLIENTSITE pcs;
  2160. if (SUCCEEDED(polePending->GetClientSite(&pcs)) && pcs)
  2161. {
  2162. if (pcs == SAFECAST(this, LPOLECLIENTSITE))
  2163. {
  2164. polePending->SetClientSite(NULL);
  2165. }
  2166. pcs->Release();
  2167. }
  2168. polePending->Release();
  2169. }
  2170. }
  2171. #ifdef TRIDENT_NEEDS_LOCKRUNNING
  2172. // TRIDENT NO LONGER SUPPORTS IRunnableObject
  2173. hres = _punkPending->QueryInterface(IID_IRunnableObject, (void **) &pro);
  2174. if (SUCCEEDED(hres))
  2175. {
  2176. hres = pro->LockRunning(FALSE, TRUE);
  2177. pro->Release();
  2178. }
  2179. #endif
  2180. SAFERELEASE(_punkPending);
  2181. _fPendingWasInited = FALSE;
  2182. }
  2183. }
  2184. void CDocObjectHost::_ReleaseOleObject(BOOL fIfInited)
  2185. {
  2186. TraceMsg(DM_DEBUGTFRAME, "CDocObjectHost::_ReleaseOleObject called %x (%x)", _pole, this);
  2187. // Minimize impact by cleaning up in affected cases only.
  2188. if (fIfInited == FALSE && _fPendingWasInited == FALSE)
  2189. return;
  2190. // release _pole object and all the associated QI'ed pointers
  2191. if (_phls) {
  2192. _phls->SetBrowseContext(NULL); // probably no need
  2193. ATOMICRELEASE(_phls);
  2194. }
  2195. if (_pvo) {
  2196. IAdviseSink *pSink;
  2197. // paranoia: only blow away the advise sink if it is still us
  2198. if (SUCCEEDED(_pvo->GetAdvise(NULL, NULL, &pSink)) && pSink) {
  2199. if (pSink == (IAdviseSink *)this) {
  2200. _pvo->SetAdvise(0, 0, NULL);
  2201. } else {
  2202. ASSERT(0); // do we really hit this case?
  2203. }
  2204. pSink->Release();
  2205. }
  2206. ATOMICRELEASE(_pvo);
  2207. }
  2208. if (_pole)
  2209. {
  2210. LPOLECLIENTSITE pcs;
  2211. if (SUCCEEDED(_pole->GetClientSite(&pcs)) && pcs)
  2212. {
  2213. if (IsSameObject(pcs, SAFECAST(this, LPOLECLIENTSITE)))
  2214. {
  2215. _pole->SetClientSite(NULL);
  2216. }
  2217. pcs->Release();
  2218. }
  2219. // Notes: Make it sure that we don't hold a bogus _pole even
  2220. // for a moment (while we call Release).
  2221. ATOMICRELEASE(_pole);
  2222. }
  2223. }
  2224. //
  2225. // This member releases all the interfaces to the DocObject, which is
  2226. // essentially the reverse of _Bind.
  2227. //
  2228. void CDocObjectHost::_UnBind(void)
  2229. {
  2230. ATOMICRELEASE(_pHTMLWindow);
  2231. ATOMICRELEASE(_pmsot);
  2232. VariantClear(&_varUserEnteredUrl);
  2233. ASSERT(!_pmsov); // paranoia
  2234. ATOMICRELEASE(_pmsov);
  2235. ASSERT(!_pmsoc); // paranoia
  2236. ATOMICRELEASE(_pmsoc);
  2237. _xao.SetActiveObject(NULL);
  2238. if (_pole)
  2239. {
  2240. // Just in case we're destroyed while we were waiting
  2241. // for the docobj to display itself.
  2242. //
  2243. _RemoveTransitionCapability();
  2244. //
  2245. // If this is NOT MSHTML, cache the OLE server so that we don't
  2246. // need to restart or load the OLE server again.
  2247. //
  2248. if (!(_dwAppHack & (BROWSERFLAG_MSHTML | BROWSERFLAG_DONTCACHESERVER)))
  2249. {
  2250. IBrowserService *pbs;
  2251. if (SUCCEEDED(QueryService(SID_STopLevelBrowser, IID_IBrowserService, (void **)&pbs)))
  2252. {
  2253. pbs->CacheOLEServer(_pole);
  2254. pbs->Release();
  2255. }
  2256. }
  2257. TraceMsg(DM_ADVISE, "CDocObjectHost::_UnBind about to call Close of %x", _pole);
  2258. _pole->Close(OLECLOSE_NOSAVE);
  2259. _ReleaseOleObject();
  2260. }
  2261. _ReleasePendingObject();
  2262. ATOMICRELEASE(_pstg);
  2263. ATOMICRELEASE(_pbcCur);
  2264. ATOMICRELEASE(_pmkCur);
  2265. }
  2266. //
  2267. // HACK: If we open Excel95 objects directly, Excel goes crazy and eventually
  2268. // hit GPF. Here is the background info, I've got Office guys (SatoNa).
  2269. //
  2270. // From: Rajeev Misra (Xenix)
  2271. //
  2272. // 1) Excel does not handle the foll. case very well. Taking a normal file
  2273. // loading it through IPersistFile:Load and then bringing it up as an
  2274. // embedded object. The code was always tested so that the embedded
  2275. // objects always got loaded through ScPrsLoad. I am seeing a bunch of
  2276. // asserts in Excel that say that this assumption is being destroyed.
  2277. // ASSERT(_pole);
  2278. //
  2279. // From: Srini Koppolu
  2280. //
  2281. // For you, there is only one case, i.e. you always deal with the files. Then your code should look like this
  2282. //
  2283. // CreateFileMoniker from the file
  2284. // pUIActiveObject->OnFrameWindowActivate(FALSE);
  2285. // pmk->BindToObject(IID_IDataObject, &pdobj)
  2286. // pUIActiveObject->OnFrameWindowActivate(TRUE);
  2287. // OleCreateFromData()
  2288. //
  2289. // OnFrameWindowActivate is done to take care of another excel problem.
  2290. // If you currently have and Excel object UIActive in you and you try to
  2291. // do IPersistFile::Load on Excel, then it will cause problems.
  2292. //
  2293. void CDocObjectHost::_AppHackForExcel95(void)
  2294. {
  2295. ASSERT(_pole);
  2296. HRESULT hres;
  2297. IDataObject* pdt = NULL;
  2298. hres = _pole->QueryInterface(IID_IDataObject, (void **)&pdt);
  2299. TraceMsg(DM_BINDAPPHACK, "_PostBindAppHack -- QI(IOleDataObject) returned %x", hres);
  2300. if (SUCCEEDED(hres))
  2301. {
  2302. ASSERT(_pstg==NULL);
  2303. hres = StgCreateDocfile(NULL,
  2304. STGM_DIRECT | STGM_CREATE | STGM_READWRITE
  2305. | STGM_SHARE_EXCLUSIVE | STGM_DELETEONRELEASE,
  2306. 0, &_pstg);
  2307. TraceMsg(DM_BINDAPPHACK, "_PostBindAppHack StgCreateDocFile(NULL) returned %x", hres);
  2308. if (SUCCEEDED(hres))
  2309. {
  2310. IOleObject* poleCopy = NULL;
  2311. hres = OleCreateFromData(pdt, IID_IOleObject, OLERENDER_NONE,
  2312. NULL, this, _pstg, (void **)&poleCopy);
  2313. TraceMsg(DM_BINDAPPHACK, "_PostBindAppHack OleCreateFromData(IOleObject) returned %x", hres);
  2314. if (SUCCEEDED(hres)) {
  2315. _fCantSaveBack = TRUE;
  2316. ATOMICRELEASE(_pole);
  2317. _pole = poleCopy;
  2318. }
  2319. }
  2320. pdt->Release();
  2321. }
  2322. }
  2323. //
  2324. // This function get the UserClassID from the object and opens the regkey
  2325. // for that CLSID and returns. If pdwAppHack is non-NULL AND CLSID is
  2326. // CLSID_HTMLDocument, we skip all and returns the default apphack flag.
  2327. // This is a perf optimization, but prevents us from setting browser
  2328. // flags for Trident, which is fine. (SatoNa)
  2329. //
  2330. HKEY _GetUserCLSIDKey(IOleObject* pole, const CLSID* pclsid, DWORD* pdwAppHack)
  2331. {
  2332. HKEY hkey = NULL; // assume error
  2333. HRESULT hres;
  2334. CLSID clsid = CLSID_NULL;
  2335. if (pole)
  2336. {
  2337. hres = pole->GetUserClassID(&clsid);
  2338. // GetUserClassID is optional, can return E_FAIL, then is defined to be
  2339. // the same as that returned by IPersist::GetClassID. cf, msdev documentation
  2340. // for GetUserClassID
  2341. if (FAILED(hres))
  2342. {
  2343. hres = IUnknown_GetClassID(pole, &clsid);
  2344. }
  2345. }
  2346. else if (pclsid)
  2347. {
  2348. clsid = *pclsid;
  2349. hres = S_OK;
  2350. }
  2351. else
  2352. {
  2353. return NULL;
  2354. }
  2355. //
  2356. // Notice that we check for two CLSIDs to see if this is MSHTML.
  2357. //
  2358. if (pdwAppHack)
  2359. {
  2360. static const IID IID_IVBOleObj =
  2361. {0xb88c9640, 0x14e0, 0x11d0, { 0xb3, 0x49, 0x0, 0xa0, 0xc9, 0xa, 0xea, 0x82 } };
  2362. IUnknown * pVBOleObj;
  2363. if ( IsEqualGUID(clsid, CLSID_HTMLDocument)
  2364. || IsEqualGUID(clsid, CLSID_MHTMLDocument)
  2365. || IsEqualGUID(clsid, CLSID_HTMLPluginDocument) )
  2366. {
  2367. TraceMsg(TF_SHDAPPHACK, "_GetUserCLSID this is Trident. Skip opening reg key");
  2368. *pdwAppHack = BROWSERFLAG_NEVERERASEBKGND | BROWSERFLAG_SUPPORTTOP
  2369. | BROWSERFLAG_MSHTML;
  2370. return NULL;
  2371. }
  2372. else if (pole && SUCCEEDED(pole->QueryInterface(IID_IVBOleObj, (void**)&pVBOleObj) ))
  2373. {
  2374. // If the object answers to IID_IVBOleObj, it's a VB doc object and shouldn't be cached.
  2375. //
  2376. pVBOleObj->Release();
  2377. *pdwAppHack = BROWSERFLAG_DONTCACHESERVER;
  2378. }
  2379. }
  2380. //
  2381. // HACK: MSHTML.DLL does not implement GetUserClassID, but
  2382. // returns S_OK. That's why we need to check for CLSID_NULL.
  2383. //
  2384. if (SUCCEEDED(hres) && !IsEqualGUID(clsid, CLSID_NULL)) {
  2385. TCHAR szBuf[50]; // 50 is enough for GUID
  2386. SHStringFromGUID(clsid, szBuf, ARRAYSIZE(szBuf));
  2387. TraceMsg(DM_BINDAPPHACK, "_PostBindAppHack GetUserClassID = %s", szBuf);
  2388. TCHAR szKey[60]; // 60 is enough for CLSID\\{CLSID_XX}
  2389. wnsprintf(szKey, ARRAYSIZE(szKey), TEXT("CLSID\\%s"), szBuf);
  2390. if (RegOpenKey(HKEY_CLASSES_ROOT, szKey, &hkey)!=ERROR_SUCCESS)
  2391. {
  2392. TraceMsg(DM_WARNING, "_GetUserCLSIDKey RegOpenKey(%s) failed", szKey);
  2393. // I don't trust RegOpenKey.
  2394. hkey = NULL;
  2395. }
  2396. }
  2397. return hkey;
  2398. }
  2399. BOOL _GetAppHackKey(LPCTSTR pszProgID, DWORD* pdwData)
  2400. {
  2401. BOOL fSuccess = FALSE;
  2402. HKEY hkey;
  2403. if (RegOpenKey(HKEY_CLASSES_ROOT, pszProgID, &hkey)==ERROR_SUCCESS)
  2404. {
  2405. DWORD dwType;
  2406. DWORD cbSize = SIZEOF(*pdwData);
  2407. if (RegQueryValueEx(hkey, TEXT("BrowserFlags"), NULL,
  2408. &dwType, (LPBYTE)pdwData, &cbSize)==ERROR_SUCCESS
  2409. && (dwType==REG_DWORD || (dwType==REG_BINARY && cbSize==SIZEOF(*pdwData))))
  2410. {
  2411. fSuccess = TRUE;
  2412. }
  2413. else
  2414. {
  2415. //
  2416. // Unlike IE3, we make it absolutely sure that the type of object
  2417. // has either "DocObject" key or "BrowseInPlace" key under the
  2418. // ProgID. We can't rely on QI(IID_IOleDocument) because MFC 4.2
  2419. // has a bug and returns S_OK to it. As far as I know, MS-Paint
  2420. // and OmniPage pro are affected by this. We could individually
  2421. // address each of them, but it's probably impossible to catch
  2422. // all. This change has a small risk of breaking existing DocObject
  2423. // server which does not have neither key. If we find such a
  2424. // server, we'll address those individually (which is much easier
  2425. // than covering all MFC apps). (SatoNa)
  2426. //
  2427. TCHAR ach[MAX_PATH];
  2428. BOOL fBrowsable = FALSE;
  2429. LONG cb = SIZEOF(ach);
  2430. if (RegQueryValue(hkey, TEXT("DocObject"), ach, &cb) == ERROR_SUCCESS)
  2431. {
  2432. fBrowsable = TRUE;
  2433. }
  2434. else
  2435. {
  2436. cb=SIZEOF(ach);
  2437. if (RegQueryValue(hkey, TEXT("BrowseInPlace"), ach, &cb) == ERROR_SUCCESS)
  2438. {
  2439. fBrowsable = TRUE;
  2440. }
  2441. }
  2442. if (!fBrowsable) {
  2443. TraceMsg(DM_WARNING, "_GetAppHackKey this is neither DocObject or BrowseInPlace");
  2444. *pdwData = BROWSERFLAG_DONTINPLACE;
  2445. }
  2446. }
  2447. RegCloseKey(hkey);
  2448. }
  2449. return fSuccess;
  2450. }
  2451. void GetAppHackFlags(IOleObject* pole, const CLSID* pclsid, DWORD* pdwAppHack)
  2452. {
  2453. HKEY hkey = _GetUserCLSIDKey(pole, pclsid, pdwAppHack);
  2454. if (hkey)
  2455. {
  2456. TCHAR szValue[MAX_PATH];
  2457. LONG cb = SIZEOF(szValue);
  2458. if (RegQueryValue(hkey, TEXT("ProgID"), szValue, &cb) == ERROR_SUCCESS)
  2459. {
  2460. //
  2461. // First, check if we have an BrowserFlags flag in the registry.
  2462. // If there is, use it. Otherwise, try hard-coded progIDs as
  2463. // we did in IE 3.0
  2464. //
  2465. _GetAppHackKey(szValue, pdwAppHack);
  2466. if (!(*pdwAppHack & BROWSERFLAG_REPLACE)) {
  2467. typedef struct _APPHACK {
  2468. LPCTSTR pszProgID;
  2469. DWORD dwAppHack;
  2470. } APPHACK;
  2471. //
  2472. // We no longer need to disable in-place activation of
  2473. // MS-PAINT because we look for "BrowseInPlace" or
  2474. // "DocObject" key
  2475. //
  2476. // { "Paint.Picture", BROWSERFLAG_DONTINPLACE },
  2477. //
  2478. const static APPHACK s_aah[] = {
  2479. { TEXT("Excel.Sheet.5"), BROWSERFLAG_OPENCOPY },
  2480. { TEXT("Excel.Chart.5"), BROWSERFLAG_OPENCOPY },
  2481. { TEXT("SoundRec"), BROWSERFLAG_OPENVERB },
  2482. { TEXT("Word.Document.6"), BROWSERFLAG_SETHOSTNAME },
  2483. { TEXT("Word.Document.8"), BROWSERFLAG_DONTUIDEACTIVATE | BROWSERFLAG_SETHOSTNAME },
  2484. { TEXT("PowerPoint.Show.8"), BROWSERFLAG_DONTUIDEACTIVATE | BROWSERFLAG_PRINTPROMPTUI },
  2485. { TEXT("Excel.Sheet.8"), BROWSERFLAG_DONTDEACTIVATEMSOVIEW | BROWSERFLAG_INITNEWTOKEEP },
  2486. { TEXT("Excel.Chart.8"), BROWSERFLAG_DONTDEACTIVATEMSOVIEW | BROWSERFLAG_INITNEWTOKEEP },
  2487. { TEXT("ABCFlowCharter6.Document"), BROWSERFLAG_DONTINPLACE },
  2488. { TEXT("ABCFlowCharter7.Document"), BROWSERFLAG_DONTINPLACE },
  2489. { TEXT("FlowCharter7.Document"), BROWSERFLAG_DONTINPLACE },
  2490. { TEXT("ChannelFile"), BROWSERFLAG_DONTAUTOCLOSE },
  2491. { TEXT("Visio.Drawing.5"), BROWSERFLAG_ENABLETOOLSBTN | BROWSERFLAG_SAVEASWHENCLOSING },
  2492. { TEXT("Visio.Drawing.4"), BROWSERFLAG_ENABLETOOLSBTN | BROWSERFLAG_SAVEASWHENCLOSING }
  2493. };
  2494. const static TCHAR s_ActiveMoveCtx[] = TEXT("AMOVIE.ActiveMovieControl");
  2495. if (!StrCmpN(szValue, s_ActiveMoveCtx, ARRAYSIZE(s_ActiveMoveCtx)-1))
  2496. {
  2497. *pdwAppHack = BROWSERFLAG_DONTAUTOCLOSE;
  2498. }
  2499. else
  2500. {
  2501. for (int i=0; i<ARRAYSIZE(s_aah); i++) {
  2502. if (StrCmp(szValue, s_aah[i].pszProgID)==0)
  2503. {
  2504. *pdwAppHack |= s_aah[i].dwAppHack;
  2505. break;
  2506. }
  2507. }
  2508. }
  2509. }
  2510. TraceMsg(DM_BINDAPPHACK, "_GetAppHack ProgID=%s, *pdwAppHack=%x",
  2511. szValue, *pdwAppHack);
  2512. } else {
  2513. TraceMsg(DM_BINDAPPHACK, "_GetAppHack RegQueryValue(ProgID) failed");
  2514. }
  2515. RegCloseKey(hkey);
  2516. }
  2517. }
  2518. DWORD CDocObjectHost::_GetAppHack(void)
  2519. {
  2520. ASSERT(_pole);
  2521. if (!_fHaveAppHack && _pole)
  2522. {
  2523. _dwAppHack = 0; // Assume no hack
  2524. _fHaveAppHack = TRUE;
  2525. ::GetAppHackFlags(_pole, NULL, &_dwAppHack);
  2526. }
  2527. return _pole ? _dwAppHack : 0;
  2528. }
  2529. void CDocObjectHost::_PostBindAppHack(void)
  2530. {
  2531. _GetAppHack();
  2532. if (_fAppHackForExcel()) {
  2533. _AppHackForExcel95();
  2534. }
  2535. }
  2536. //
  2537. // This member binds to the object specified by a moniker.
  2538. //
  2539. HRESULT CDocObjectHost::_BindSync(IMoniker* pmk, IBindCtx* pbc, IShellView* psvPrev)
  2540. {
  2541. ASSERT(pbc || !_pole);
  2542. HRESULT hres = S_OK;
  2543. ASSERT(_pole==NULL);
  2544. // Check if we are in the middle of asynchronous binding
  2545. if (_bsc._fBinding)
  2546. {
  2547. // Yes, wait until it's done or canceled/stopped
  2548. URLMSG(TEXT("_Bind called in the middle of async-binding. Wait in a message loop"));
  2549. while(_bsc._fBinding)
  2550. {
  2551. MSG msg;
  2552. if (GetMessage(&msg, NULL, 0, 0))
  2553. {
  2554. TranslateMessage(&msg);
  2555. DispatchMessage(&msg);
  2556. }
  2557. }
  2558. if (!_pole)
  2559. {
  2560. hres = E_FAIL; // Get the error code from OnStopBinding
  2561. }
  2562. }
  2563. else
  2564. {
  2565. // No, bind synchronously
  2566. URLMSG(TEXT("_Bind. Performing syncronous binding"));
  2567. hres = pmk->BindToObject(pbc, NULL, IID_IOleObject, (void **)&_pole);
  2568. }
  2569. TraceMsg(0, "sdv TR : _Bind -- pmk->BindToObject(IOleObject) returned %x", hres);
  2570. _OnBound(hres);
  2571. return hres;
  2572. }
  2573. void CDocObjectHost::_OnBound(HRESULT hres)
  2574. {
  2575. if (SUCCEEDED(hres)) {
  2576. _PostBindAppHack();
  2577. _InitOleObject();
  2578. }
  2579. }
  2580. //
  2581. // This function returns TRUE if the specified file's open command is
  2582. // associated with "explorer.exe" or "iexplore.exe".
  2583. //
  2584. // NOTES: It does not check if the "open" command is actually the default
  2585. // or not, but that's sufficient in 99.99 cases.
  2586. //
  2587. BOOL IsAssociatedWithIE(LPCWSTR szPath)
  2588. {
  2589. LPCTSTR pszExtension = PathFindExtension(szPath);
  2590. BOOL bRet = FALSE;
  2591. TCHAR szBuf[MAX_PATH];
  2592. TCHAR szExt[_MAX_EXT];
  2593. DWORD cchBuf = ARRAYSIZE(szBuf);
  2594. if (SUCCEEDED(AssocQueryString(0, ASSOCSTR_COMMAND, szExt, TEXT("open"), szBuf, &cchBuf)))
  2595. {
  2596. TraceMsg(TF_SHDBINDING, "IsAssociatedWithIE(%s) found %s as open command", szPath, szBuf);
  2597. LPCTSTR pszFound;
  2598. if ( (pszFound=StrStrI(szBuf, IEXPLORE_EXE))
  2599. || (pszFound=StrStrI(szBuf, EXPLORER_EXE)) )
  2600. {
  2601. if (pszFound==szBuf || *(pszFound - 1)==TEXT('\\'))
  2602. {
  2603. bRet = TRUE;
  2604. }
  2605. }
  2606. }
  2607. TraceMsg(DM_SELFASC, "IsAssociatedWithIE(%s) returning %d", szPath, bRet);
  2608. return bRet;
  2609. }
  2610. HRESULT CDocObjectHost::_MayHaveVirus(REFCLSID rclsid)
  2611. {
  2612. //
  2613. // We'll call this function twice if the file is associated
  2614. // with a bogus CLSID (such as ImageComposer).
  2615. //
  2616. if (_fConfirmed)
  2617. {
  2618. TraceMsg(TF_SHDAPPHACK, "CDOH::_MayHaveVirus called twice. Return S_OK");
  2619. return S_OK;
  2620. }
  2621. TraceMsg(TF_SHDPROGRESS, "DOH::_MayHaveVirus called");
  2622. LPWSTR pwzProgID = NULL;
  2623. HRESULT hresT = E_FAIL;
  2624. if (SUCCEEDED(ProgIDFromCLSID(rclsid, &pwzProgID)))
  2625. {
  2626. if ( StrCmpI(pwzProgID, TEXT("htmlfile")) != 0
  2627. && StrCmpI(pwzProgID, TEXT("htmlfile_FullWindowEmbed")) != 0
  2628. && StrCmpI(pwzProgID, TEXT("mhtmlfile")) != 0
  2629. && StrCmpI(pwzProgID, TEXT("xmlfile")) != 0
  2630. && StrCmpI(pwzProgID, TEXT("xslfile")) != 0)
  2631. {
  2632. TCHAR szURL[MAX_URL_STRING];
  2633. TCHAR * pszURL = szURL;
  2634. hresT = _GetCurrentPage(szURL, ARRAYSIZE(szURL), TRUE);
  2635. if (SUCCEEDED(hresT))
  2636. {
  2637. UINT uRet = IDOK;
  2638. if (_PicsProcBase._fbPicsWaitFlags || !_PicsProcBase._fPicsAccessAllowed)
  2639. {
  2640. _PicsProcBase._fbPicsWaitFlags &= ~(PICS_WAIT_FOR_INDOC | PICS_WAIT_FOR_END); /* indoc ratings only on htmlfile */
  2641. TraceMsg(DM_PICS, "CDOH::_MayHaveVirus found non-HTML, waitflags now %x", (DWORD)_PicsProcBase._fbPicsWaitFlags);
  2642. uRet = _PicsProcBase._PicsBlockingDialog();
  2643. }
  2644. if (uRet == IDOK)
  2645. {
  2646. TraceMsg(TF_SHDPROGRESS, "DOH::_MayHaveVirus calling MayOpenSafeDialogOpenDialog(%s)", pwzProgID);
  2647. if (_bsc._pszRedirectedURL && *_bsc._pszRedirectedURL)
  2648. pszURL = _bsc._pszRedirectedURL;
  2649. IUnknown * punk;
  2650. BOOL fDisableOpen = TRUE;
  2651. LPCTSTR pszExt = NULL;
  2652. if (_bsc._pszCacheFileName)
  2653. pszExt = PathFindExtension(_bsc._pszCacheFileName);
  2654. else if (pszURL)
  2655. pszExt = PathFindExtension(pszURL);
  2656. if (pszExt)
  2657. {
  2658. TCHAR szClassName[MAX_PATH];
  2659. DWORD cbSize = SIZEOF(szClassName);
  2660. // if the ProgIDs don't match then disable the open button
  2661. if (ERROR_SUCCESS == SHGetValue(HKEY_CLASSES_ROOT, pszExt, NULL, NULL, szClassName, &cbSize))
  2662. fDisableOpen = StrCmpI(pwzProgID, szClassName);
  2663. }
  2664. QueryInterface(IID_IUnknown, (void**)&punk);
  2665. uRet = MayOpenSafeOpenDialog(_hwnd, pwzProgID, pszURL, _bsc._pszCacheFileName, NULL, _uiCP, punk, _pmsoctBrowser, fDisableOpen);
  2666. ATOMICRELEASE(punk);
  2667. _fCalledMayOpenSafeDlg = TRUE;
  2668. }
  2669. switch(uRet)
  2670. {
  2671. case IDIGNORE:
  2672. //
  2673. // allow the safeopen dlg to pop up later if necessary
  2674. //
  2675. _fCalledMayOpenSafeDlg = FALSE;
  2676. _fConfirmed = FALSE;
  2677. break; // continue download
  2678. case IDOK:
  2679. //
  2680. // Set this flag to avoid poppping this dialog box twice.
  2681. //
  2682. _fConfirmed = TRUE;
  2683. break; // continue download
  2684. case IDD_SAVEAS:
  2685. IUnknown *punk;
  2686. hresT = QueryInterface(IID_IUnknown, (void**)&punk);
  2687. if(SUCCEEDED(hresT))
  2688. {
  2689. CDownLoad_OpenUI(_pmkCur, _bsc._pbc, FALSE, TRUE, NULL, NULL, NULL, NULL, NULL, _bsc._pszRedirectedURL, _uiCP, punk);
  2690. punk->Release();
  2691. }
  2692. // fall through to abort binding.
  2693. case IDCANCEL:
  2694. hresT = HRESULT_FROM_WIN32(ERROR_CANCELLED);
  2695. break;
  2696. }
  2697. }
  2698. else
  2699. {
  2700. TraceMsg(DM_ERROR, "DOH::_MayHaveVirus _GetCurrentPage failed %x", hresT);
  2701. }
  2702. }
  2703. else
  2704. {
  2705. TraceMsg(TF_SHDPROGRESS, "DOH::_MayHaveVirus this is htmlfile -- don't call MayOpenSafeDialogOpenDialog");
  2706. _fPicsBlockLate = TRUE;
  2707. }
  2708. OleFree(pwzProgID);
  2709. }
  2710. return hresT;
  2711. }
  2712. STDMETHODIMP CDocObjectHost::SaveObject(void)
  2713. {
  2714. TraceMsg(0, "sdv TR: CDOV::SaveObject called");
  2715. // Implemente it later.
  2716. return S_OK;
  2717. }
  2718. STDMETHODIMP CDocObjectHost::GetMoniker(DWORD dwAssign,
  2719. DWORD dwWhichMoniker,
  2720. IMoniker **ppmk)
  2721. {
  2722. HRESULT hres = E_INVALIDARG;
  2723. *ppmk = NULL;
  2724. TraceMsg(TF_SHDBINDING, "CDOH::GetMoniker called dwWhichMoniker=%x", dwWhichMoniker);
  2725. switch(dwWhichMoniker)
  2726. {
  2727. case OLEWHICHMK_OBJREL:
  2728. case OLEWHICHMK_OBJFULL:
  2729. if (_pmkCur)
  2730. {
  2731. *ppmk = _pmkCur;
  2732. _pmkCur->AddRef();
  2733. hres = S_OK;
  2734. }
  2735. else
  2736. {
  2737. hres = E_UNEXPECTED;
  2738. }
  2739. break;
  2740. }
  2741. return hres;
  2742. }
  2743. STDMETHODIMP CDocObjectHost::GetContainer(
  2744. IOleContainer **ppContainer)
  2745. {
  2746. // According to CKindel, we should implement this method
  2747. // as the way for a DocObject to access IDispatch interface of
  2748. // the container (i.e., frame). I'm currently thinking leaving
  2749. // all it's non-IUnknown memeber unimplemented. If there is no
  2750. // need to enumerates objects, we can simply QI from IShellBrowser
  2751. // to IOleContainer and return it. (SatoNa)
  2752. //
  2753. // NOTE: If trident calls this after DestroyHostWindow, we have nothing
  2754. // to give out. Hopefully this is not bad. (MikeSh)
  2755. TraceMsg(0, "sdv TR: CDOV::GetContainer called");
  2756. if (_psb)
  2757. return _psb->QueryInterface(IID_IOleContainer, (void **)ppContainer);
  2758. return E_FAIL;
  2759. }
  2760. STDMETHODIMP CDocObjectHost::ShowObject(void)
  2761. {
  2762. TraceMsg(0, "sdv TR: CDOV::ShowObject called");
  2763. return E_NOTIMPL; // As specified in Kraig's document
  2764. }
  2765. STDMETHODIMP CDocObjectHost::OnShowWindow(BOOL fShow)
  2766. {
  2767. TraceMsg(TF_SHDUIACTIVATE, "DOH::OnShowWindow(%d) called (this=%x)", fShow, this);
  2768. return E_NOTIMPL; // As specified in Kraig's document
  2769. }
  2770. STDMETHODIMP CDocObjectHost::RequestNewObjectLayout(void)
  2771. {
  2772. TraceMsg(0, "sdv TR: CDOV::RequestNewObjectLayout called");
  2773. return E_NOTIMPL; // As specified in Kraig's document
  2774. }
  2775. //
  2776. // This is the standard way for non-active embedding to access
  2777. // the IHlinkFrame interface. We happened to use our QI to implement
  2778. // this, but the semantics of QueryService is different from QI.
  2779. // It does not necessary return the same object.
  2780. //
  2781. HRESULT CDocObjectHost::QueryService(REFGUID guidService, REFIID riid, void **ppvObj)
  2782. {
  2783. if( IsEqualGUID(guidService, IID_IElementNamespaceTable) )
  2784. {
  2785. return IUnknown_QueryService(_pole, IID_IElementNamespaceTable, riid, ppvObj);
  2786. }
  2787. // In order for the context menu to work correctly inside IFrames, we
  2788. // need to fail a certain query ONLY for IFrames on desktop.
  2789. else if (!IsEqualGUID(guidService, CLSID_HTMLDocument) || !_IsImmediateParentDesktop(this, _psp))
  2790. {
  2791. //
  2792. // Delegate ISP to the _psb.
  2793. //
  2794. if (_psb && _psp)
  2795. return _psp->QueryService(guidService, riid, ppvObj);
  2796. }
  2797. *ppvObj = NULL;
  2798. return E_NOINTERFACE;
  2799. }
  2800. /*----------------------------------------------------------
  2801. Purpose: Remove the submenu(s) that are in _hmenuFrame
  2802. from _hmenuBrowser.
  2803. */
  2804. void CDocObjectHost::_RemoveFrameSubMenus(void)
  2805. {
  2806. HMENU hmenu;
  2807. ASSERT(IS_VALID_HANDLE(_hmenuBrowser, MENU));
  2808. ASSERT(IS_VALID_HANDLE(_hmenuFrame, MENU));
  2809. // The file menu in _hmenuBrowser consists of the file menu from
  2810. // _hmenuFrame and IShellBrowser. The part added by _hmenuFrame
  2811. // includes a submenu (Send To), which must be removed before
  2812. // _hmenuBrowser is destroyed.
  2813. // We could just explicitly remove the Send To submenu. But to
  2814. // prevent the expensive bug hunt that it took to find this in the
  2815. // first place, we're going to iterate thru the menu and, for
  2816. // any submenus that belong to our template, we'll remove them.
  2817. int citemFile = 0;
  2818. UINT nID = 0;
  2819. // Get the count of menu items in our template's File menu and
  2820. // the ID of the first menu item.
  2821. hmenu = GetMenuFromID(_hmenuFrame, FCIDM_MENU_FILE);
  2822. if (hmenu)
  2823. {
  2824. citemFile = GetMenuItemCount(hmenu);
  2825. nID = GetMenuItemID(hmenu, 0);
  2826. }
  2827. // Now look at the browser menu's File menu and, starting at
  2828. // nID, remove any submenus.
  2829. hmenu = GetMenuFromID(_hmenuBrowser, FCIDM_MENU_FILE);
  2830. if (hmenu)
  2831. {
  2832. int citem = GetMenuItemCount(hmenu);
  2833. int iTop;
  2834. int i;
  2835. // Where does our template file menu start?
  2836. for (iTop = 0; iTop < citem; iTop++)
  2837. {
  2838. if (GetMenuItemID(hmenu, iTop) == nID)
  2839. {
  2840. // Start at where our template file menu ends and work up
  2841. for (i = iTop + citemFile - 1; 0 < citemFile ; i--, citemFile--)
  2842. {
  2843. HMENU hmenuSub = GetSubMenu(hmenu, i);
  2844. if (hmenuSub)
  2845. RemoveMenu(hmenu, i, MF_BYPOSITION);
  2846. }
  2847. break;
  2848. }
  2849. }
  2850. }
  2851. }
  2852. /*----------------------------------------------------------
  2853. Purpose: Destroy the browser menu.
  2854. */
  2855. HRESULT CDocObjectHost::_DestroyBrowserMenu(void)
  2856. {
  2857. TraceMsg(TF_SHDUIACTIVATE, "DOH::_DestroyBrowserMenu called");
  2858. if (_hmenuBrowser) {
  2859. // First remove any submenus that are held by other menus,
  2860. // so we don't blow them away.
  2861. _RemoveFrameSubMenus();
  2862. if (EVAL(_psb)) {
  2863. _psb->RemoveMenusSB(_hmenuBrowser);
  2864. }
  2865. DestroyMenu(_hmenuBrowser);
  2866. _hmenuBrowser = NULL;
  2867. }
  2868. return S_OK;
  2869. }
  2870. HRESULT CDocObjectHost::_CreateBrowserMenu(LPOLEMENUGROUPWIDTHS pmw)
  2871. {
  2872. TraceMsg(TF_SHDUIACTIVATE, "DOH::_CreateBrowserMenu called");
  2873. if (_hmenuBrowser) {
  2874. return S_OK;
  2875. }
  2876. _hmenuBrowser = CreateMenu();
  2877. if (!_hmenuBrowser) {
  2878. return E_OUTOFMEMORY;
  2879. }
  2880. HRESULT hres = E_FAIL;
  2881. // Allow IShellBrowser a chance to add its menus
  2882. if (EVAL(_psb))
  2883. hres = _psb->InsertMenusSB(_hmenuBrowser, pmw);
  2884. // HACK: Win95 explorer returns E_NOTIMPL
  2885. if (hres==E_NOTIMPL) {
  2886. hres = S_OK;
  2887. }
  2888. if (SUCCEEDED(hres)) {
  2889. // Load our menu if not loaded yet
  2890. if (!_hmenuFrame)
  2891. {
  2892. _hmenuFrame = LoadMenu(MLGetHinst(), MAKEINTRESOURCE(MID_FOCUS));
  2893. }
  2894. // Get the "File" sub-menu from the shell browser.
  2895. MENUITEMINFO mii;
  2896. mii.cbSize = sizeof(mii);
  2897. mii.fMask = MIIM_SUBMENU;
  2898. if (GetMenuItemInfo(_hmenuBrowser, FCIDM_MENU_FILE, FALSE, &mii))
  2899. {
  2900. HMENU hmenuFileBrowse = mii.hSubMenu;
  2901. // Merge our menuitems into this submenu.
  2902. if (_hmenuFrame)
  2903. {
  2904. MENUITEMINFO miiItem;
  2905. miiItem.cbSize = SIZEOF(MENUITEMINFO);
  2906. miiItem.fMask = MIIM_SUBMENU;
  2907. if (GetMenuItemInfo(_hmenuFrame, FCIDM_MENU_FILE, FALSE, &miiItem))
  2908. {
  2909. TCHAR szItem[128];
  2910. HMENU hmenuFileT = miiItem.hSubMenu;
  2911. UINT citem = GetMenuItemCount(hmenuFileT);
  2912. for (int i=citem-1; i>=0 ; i--)
  2913. {
  2914. // We need to reset for each item.
  2915. miiItem.fMask = MIIM_STATE | MIIM_ID | MIIM_SUBMENU | MIIM_CHECKMARKS | MIIM_TYPE | MIIM_DATA;
  2916. miiItem.fType = MFT_STRING;
  2917. miiItem.cch = ARRAYSIZE(szItem);
  2918. miiItem.dwTypeData = szItem;
  2919. miiItem.dwItemData = 0;
  2920. if (GetMenuItemInfo(hmenuFileT, i, TRUE, &miiItem)) {
  2921. InsertMenuItem(hmenuFileBrowse, 0, TRUE, &miiItem);
  2922. }
  2923. }
  2924. }
  2925. }
  2926. if (!IEHardened() && -1 != GetMenuState(hmenuFileBrowse, DVIDM_ADDSITE, MF_BYCOMMAND))
  2927. {
  2928. DeleteMenu(hmenuFileBrowse, DVIDM_ADDSITE, MF_BYCOMMAND);
  2929. }
  2930. }
  2931. else
  2932. {
  2933. TraceMsg(TF_SHDUIACTIVATE, "DOH::_CreateBrowseMenu parent has no File menu (it's probably a browser OC)");
  2934. ASSERT(0); // DocObject in OC is not supposed to call InsertMenus.
  2935. }
  2936. }
  2937. DEBUG_CODE( _DumpMenus(TEXT("after _CreateBrowserMenu"), TRUE); )
  2938. return hres;
  2939. }
  2940. //
  2941. // IOleInPlaceFrame::InsertMenus equivalent
  2942. //
  2943. HRESULT CDocObjectHost::_InsertMenus(
  2944. /* [in] */ HMENU hmenuShared,
  2945. /* [out][in] */ LPOLEMENUGROUPWIDTHS lpMenuWidths)
  2946. {
  2947. HRESULT hres = S_OK;
  2948. int nMenuOffset = 0;
  2949. TraceMsg(TF_SHDUIACTIVATE, "DOH::InsertMenus called (this=%x)", this);
  2950. // Assume error (no menu merge)
  2951. lpMenuWidths->width[0] = 0;
  2952. lpMenuWidths->width[2] = 0;
  2953. lpMenuWidths->width[4] = 0;
  2954. lpMenuWidths->width[5] = 0;
  2955. // be extra safe and don't attempt menu merging if we're not top level
  2956. if (_fHaveParentSite)
  2957. return S_OK;
  2958. OLEMENUGROUPWIDTHS mw = { {0} };
  2959. hres = _CreateBrowserMenu(&mw);
  2960. if (FAILED(hres)) {
  2961. TraceMsg(DM_ERROR, "DOH::InsertMenus _CreateBrpwserMenu failed");
  2962. return hres;
  2963. }
  2964. // Get the "File" sub-menu from the shell browser.
  2965. MENUITEMINFO mii;
  2966. TCHAR szSubMenu[128];
  2967. mii.cbSize = SIZEOF(mii);
  2968. mii.fMask = MIIM_SUBMENU|MIIM_TYPE|MIIM_ID;
  2969. mii.cch = ARRAYSIZE(szSubMenu);
  2970. mii.dwTypeData = szSubMenu;
  2971. if (EVAL(GetMenuItemInfo(_hmenuBrowser, FCIDM_MENU_FILE, FALSE, &mii)))
  2972. {
  2973. ASSERT(szSubMenu == mii.dwTypeData);
  2974. InsertMenuItem(hmenuShared, nMenuOffset++, TRUE, &mii);
  2975. lpMenuWidths->width[0] = 1;
  2976. }
  2977. // Note that we need to re-initialize mii
  2978. mii.cch = ARRAYSIZE(szSubMenu);
  2979. if (EVAL(GetMenuItemInfo(_hmenuBrowser, FCIDM_MENU_EXPLORE, FALSE, &mii)))
  2980. {
  2981. // GetMenuItemInfo is recursive (why?). The item it retrieves
  2982. // for FCIDM_MENU_EXPLORE can either be the top level Go menu, or if that
  2983. // does not exist (NT5 case), it returns the Go To submenu of View.
  2984. //
  2985. // Code has been added in in the SetMenu implementations of Shell Browser
  2986. // and Dochost to detect the second case, because the menu dispatch list
  2987. // does not recognize this kind of menu merging (80734).
  2988. DeleteMenu(mii.hSubMenu, FCIDM_PREVIOUSFOLDER, MF_BYCOMMAND);
  2989. InsertMenuItem(hmenuShared, nMenuOffset++, TRUE, &mii);
  2990. lpMenuWidths->width[4]++;
  2991. }
  2992. mii.cch = ARRAYSIZE(szSubMenu);
  2993. if (EVAL(GetMenuItemInfo(_hmenuBrowser, FCIDM_MENU_FAVORITES, FALSE, &mii)))
  2994. {
  2995. InsertMenuItem(hmenuShared, nMenuOffset++, TRUE, &mii);
  2996. lpMenuWidths->width[4]++;
  2997. }
  2998. if (_hmenuFrame)
  2999. {
  3000. // Micro-merge the help menu.
  3001. mii.cch = ARRAYSIZE(szSubMenu);
  3002. if (EVAL(GetMenuItemInfo(_hmenuFrame, FCIDM_MENU_HELP, FALSE, &mii)))
  3003. {
  3004. InsertMenuItem(hmenuShared, nMenuOffset++, TRUE, &mii);
  3005. lpMenuWidths->width[5]++;
  3006. }
  3007. }
  3008. DEBUG_CODE( _DumpMenus(TEXT("after InsertMenus"), TRUE); )
  3009. return hres;
  3010. }
  3011. /*----------------------------------------------------------
  3012. Purpose: Different objects may add their own Help menu (like
  3013. Word and Excel). This function detects if the object
  3014. added its own help menu, or if it added items to our
  3015. help menu, or if it is just using our help menu.
  3016. If they added their own help menu, we remove ours.
  3017. */
  3018. void CDocObjectHost::_CompleteHelpMenuMerge(HMENU hmenu)
  3019. {
  3020. HMENU hmenuHelp;
  3021. MENUITEMINFO mii;
  3022. TCHAR szSubMenu[80];
  3023. mii.cbSize = SIZEOF(mii);
  3024. mii.fMask = MIIM_SUBMENU;
  3025. // see if they added anything to our menu
  3026. if (GetMenuItemInfo(_hmenuFrame, FCIDM_MENU_HELP, FALSE, &mii))
  3027. {
  3028. hmenuHelp = mii.hSubMenu;
  3029. int iMenuCount = GetMenuItemCount(mii.hSubMenu);
  3030. // Did the number of items in the help menu change?
  3031. if (iMenuCount != HELP_ITEM_COUNT) {
  3032. // Yes; that means they added something. This has been micro-merged.
  3033. _hmenuMergedHelp = mii.hSubMenu;
  3034. _hmenuObjHelp = GetSubMenu(mii.hSubMenu, iMenuCount -1);
  3035. goto Bail;
  3036. }
  3037. // Our menu didn't change. Now find out if they added their own
  3038. // help menu or if we ARE the help. If they added their own, we need
  3039. // to remove our help menu.
  3040. _hmenuMergedHelp = NULL;
  3041. _hmenuObjHelp = NULL;
  3042. int iCount = GetMenuItemCount(hmenu) - 1;
  3043. int i;
  3044. for (i = iCount ; i >= 0 ; i--) {
  3045. mii.fMask = MIIM_SUBMENU|MIIM_TYPE;
  3046. mii.cch = ARRAYSIZE(szSubMenu);
  3047. mii.dwTypeData = szSubMenu;
  3048. if (GetMenuItemInfo(hmenu, i, TRUE, &mii)) {
  3049. if (mii.hSubMenu == hmenuHelp) {
  3050. BOOL bRemove = FALSE;
  3051. if (iCount != i) {
  3052. // if we're not the last one, then we're not it
  3053. bRemove = TRUE;
  3054. } else {
  3055. // if we are the last one see if the help menu was added
  3056. // right before us
  3057. TCHAR szMenuTitle[80];
  3058. mii.cch = ARRAYSIZE(szMenuTitle);
  3059. mii.dwTypeData = szMenuTitle;
  3060. if (GetMenuItemInfo(hmenu, i-1, TRUE, &mii)) {
  3061. if (!StrCmpI(szMenuTitle, szSubMenu)) {
  3062. // same menu string yank ours
  3063. bRemove = TRUE;
  3064. }
  3065. }
  3066. }
  3067. if (bRemove) {
  3068. RemoveMenu(hmenu, i, MF_BYPOSITION);
  3069. }
  3070. }
  3071. }
  3072. }
  3073. }
  3074. Bail:;
  3075. DEBUG_CODE( _DumpMenus(TEXT("after _CompleteHelpMenuMerge"), TRUE); )
  3076. }
  3077. //
  3078. // IOleInPlaceFrame::SetMenu equivalent
  3079. //
  3080. HRESULT CDocObjectHost::_SetMenu(
  3081. /* [in] */ HMENU hmenuShared, OPTIONAL
  3082. /* [in] */ HOLEMENU holemenu, OPTIONAL
  3083. /* [in] */ HWND hwndActiveObject)
  3084. {
  3085. TraceMsg(TF_SHDUIACTIVATE, "DOH::SetMenus(%x) called (this=%x)",
  3086. hmenuShared, this);
  3087. // be extra safe and don't attempt menu merging if we're not top level
  3088. if (_fHaveParentSite)
  3089. return S_OK;
  3090. // A NULL hmenuShared means to reinstate the container's original menu.
  3091. if (hmenuShared)
  3092. {
  3093. // Clean up duplicate help menus
  3094. _CompleteHelpMenuMerge(hmenuShared);
  3095. }
  3096. // Simply forwarding it to IShellBrowser
  3097. _hmenuSet = hmenuShared;
  3098. HRESULT hres = E_FAIL;
  3099. if (EVAL(_psb))
  3100. hres = _psb->SetMenuSB(hmenuShared, holemenu, hwndActiveObject);
  3101. if (SUCCEEDED(hres))
  3102. {
  3103. // need to tell the shell browser that we want doc obj style menu merging
  3104. if (_pmsoctBrowser)
  3105. _pmsoctBrowser->Exec(&CGID_Explorer, SBCMDID_ACTIVEOBJECTMENUS, 0, NULL, NULL);
  3106. // Compose our list of object/frame menus, so our menuband
  3107. // can dispatch the messages correctly. Essentially this is
  3108. // the same as the contents of holemenu, but since we don't
  3109. // have access to the internal struct, we must derive this
  3110. // info ourselves.
  3111. _menulist.Set(hmenuShared, _hmenuBrowser);
  3112. if (_hmenuMergedHelp)
  3113. _menulist.RemoveMenu(_hmenuMergedHelp);
  3114. if (_hmenuObjHelp)
  3115. _menulist.AddMenu(_hmenuObjHelp);
  3116. _hmenuCur = hmenuShared;
  3117. HWND hwndFrame;
  3118. _psb->GetWindow(&hwndFrame);
  3119. // 80734: Was the Go To menu taken from the View menu and grafted onto the
  3120. // main menu by DocHost? The menulist won't detect this graft, so we have
  3121. // to check ourselves and make sure it's not marked as belonging to the
  3122. // docobject.
  3123. //
  3124. // This test is duplicated in CShellBrowser2::SetMenuSB
  3125. MENUITEMINFO mii;
  3126. mii.cbSize = SIZEOF(mii);
  3127. mii.fMask = MIIM_SUBMENU;
  3128. if (hmenuShared && _hmenuBrowser &&
  3129. GetMenuItemInfo(hmenuShared, FCIDM_MENU_EXPLORE, FALSE, &mii))
  3130. {
  3131. HMENU hmenuGo = mii.hSubMenu;
  3132. if (GetMenuItemInfo(_hmenuBrowser, FCIDM_MENU_EXPLORE, FALSE, &mii) &&
  3133. mii.hSubMenu == hmenuGo && _menulist.IsObjectMenu(hmenuGo))
  3134. {
  3135. _menulist.RemoveMenu(hmenuGo);
  3136. }
  3137. }
  3138. // (scotth): why are we calling this, since this isn't compatible
  3139. // with menubands? That's the whole reason we have _menulist.
  3140. hres = OleSetMenuDescriptor(holemenu, hwndFrame, hwndActiveObject, &_dof, _ActiveObject());
  3141. }
  3142. DEBUG_CODE( _DumpMenus(TEXT("after SetMenu"), TRUE); )
  3143. return hres;
  3144. }
  3145. /*----------------------------------------------------------
  3146. Purpose: Returns TRUE if the given menu belongs to the browser
  3147. (as opposed to the object)
  3148. */
  3149. BOOL CDocObjectHost::_IsMenuShared(HMENU hmenu)
  3150. {
  3151. ASSERT(hmenu);
  3152. // (scotth): can we use _menulist here? (it would be faster)
  3153. if (_hmenuBrowser) {
  3154. for (int i = GetMenuItemCount(_hmenuBrowser) - 1 ; i >= 0; i--) {
  3155. if (GetSubMenu(_hmenuBrowser, i) == hmenu)
  3156. return TRUE;
  3157. }
  3158. }
  3159. // We have to special case the help menu. It's possible that the
  3160. // help menu in the shared menu actually came from _hmenuFrame
  3161. // (not _hmenuBrowser). We need to detect this case, otherwise
  3162. // the help menu gets destroyed but it is still referenced in
  3163. // _hmenuFrame.
  3164. MENUITEMINFO mii;
  3165. mii.cbSize = SIZEOF(mii);
  3166. mii.fMask = MIIM_SUBMENU;
  3167. ASSERT(IS_VALID_HANDLE(_hmenuFrame, MENU));
  3168. // Is this our help menu from _hmenuFrame?
  3169. if (GetMenuItemInfo(_hmenuFrame, FCIDM_MENU_HELP, FALSE, &mii) &&
  3170. mii.hSubMenu == hmenu)
  3171. {
  3172. // Yes
  3173. return TRUE;
  3174. }
  3175. return FALSE;
  3176. }
  3177. //
  3178. // IOleInPlaceFrame::RemoveMenus equivalent
  3179. //
  3180. HRESULT CDocObjectHost::_RemoveMenus(/* [in] */ HMENU hmenuShared)
  3181. {
  3182. TraceMsg(TF_SHDUIACTIVATE, "DOH::RemoveMenus called (this=%x)", this);
  3183. // be extra safe and don't attempt menu merging if we're not top level
  3184. if (_fHaveParentSite)
  3185. return S_OK;
  3186. ASSERT(GetMenuItemCount(hmenuShared) != (UINT)-1);
  3187. //
  3188. // It is ok to simply remove sub-menus here.
  3189. // because ours are shared with the _hmenuBrowser
  3190. // and destroying that below will take care of cleanup.
  3191. // However, we need to only remove menus that are ours.
  3192. //
  3193. for (int i = (int)GetMenuItemCount(hmenuShared) - 1 ; i >= 0; i--)
  3194. {
  3195. // TraceMsg(0, "sdv TR - ::RemoveMenus calling RemoveMenu(0)");
  3196. HMENU hmenu = GetSubMenu(hmenuShared, i);
  3197. if (hmenu && _IsMenuShared(hmenu)) {
  3198. RemoveMenu(hmenuShared, i, MF_BYPOSITION);
  3199. }
  3200. }
  3201. // TraceMsg(0, "sdv TR - ::RemoveMenus exiting");
  3202. return S_OK;
  3203. }
  3204. //
  3205. // IOleInPlaceFrame::SetStatusText equivalent
  3206. //
  3207. HRESULT CDocObjectHost::_SetStatusText(/* [in] */ LPCOLESTR pszStatusText)
  3208. {
  3209. LPCOLESTR pszForward;
  3210. if (_psb != NULL)
  3211. {
  3212. // if it's NULL or just "" then give precedence to
  3213. // _strPriorityStatusText, otherwise we display
  3214. // whatever we're given
  3215. if (pszStatusText != NULL && pszStatusText[0] != TEXT('\0') ||
  3216. _strPriorityStatusText == NULL)
  3217. {
  3218. pszForward = pszStatusText;
  3219. }
  3220. else
  3221. {
  3222. pszForward = _strPriorityStatusText;
  3223. }
  3224. _psb->SetStatusTextSB(pszForward);
  3225. }
  3226. // Always return S_OK or scripting will put up an error dialog.
  3227. return S_OK;
  3228. }
  3229. void CDocObjectHost::_SetPriorityStatusText(LPCOLESTR pszPriorityStatusText)
  3230. {
  3231. // if they gave us a new string, replace the old one,
  3232. // otherwise just NULL out the old one
  3233. if (_strPriorityStatusText != NULL)
  3234. {
  3235. SysFreeString(_strPriorityStatusText);
  3236. }
  3237. if (pszPriorityStatusText != NULL)
  3238. {
  3239. _strPriorityStatusText = SysAllocString(pszPriorityStatusText);
  3240. }
  3241. else
  3242. {
  3243. _strPriorityStatusText = NULL;
  3244. }
  3245. _SetStatusText(_strPriorityStatusText);
  3246. }
  3247. HRESULT CDocObjectHost::_EnableModeless(/* [in] */ BOOL fEnable)
  3248. {
  3249. TraceMsg(0, "sdv TR - ::EnableModeless called");
  3250. // Note that we used call _CancelPendingNavigation here.
  3251. // We do it in CBaseBrowser:::EnableModelesSB intead. (Satona)
  3252. // Simply forwarding it (which is not implemented)
  3253. if (EVAL(_psb))
  3254. return _psb->EnableModelessSB(fEnable);
  3255. return E_FAIL;
  3256. }
  3257. HRESULT CDocObjectHost::TranslateHostAccelerators(LPMSG lpmsg)
  3258. {
  3259. if (_hacc && ::TranslateAccelerator(_hwnd, _hacc, lpmsg)) {
  3260. return S_OK;
  3261. }
  3262. return S_FALSE;
  3263. }
  3264. // IOleInPlaceFrame equivalent ::TranslateAccelerator
  3265. // Forwarding it from DocObject -> Browser
  3266. HRESULT CDocObjectHost::_TranslateAccelerator(
  3267. /* [in] */ LPMSG lpmsg,
  3268. /* [in] */ WORD wID)
  3269. {
  3270. // TranslateAccelerator goes to the guy with the focus first
  3271. if (EVAL(_psb))
  3272. if (S_OK == _psb->TranslateAcceleratorSB(lpmsg, wID))
  3273. return S_OK;
  3274. #ifdef DEBUG
  3275. if (lpmsg->message == WM_KEYDOWN) {
  3276. TraceMsg(0, "CDocObjectHost::TrAcc(UP) called");
  3277. }
  3278. #endif
  3279. return TranslateHostAccelerators(lpmsg);
  3280. }
  3281. // IViewObject
  3282. HRESULT CDocObjectHost::Draw(DWORD dwDrawAspect, LONG lindex, void *pvAspect,
  3283. DVTARGETDEVICE *ptd, HDC hicTargetDev, HDC hdcDraw,
  3284. const RECTL *lprcBounds, const RECTL *lprcWBounds,
  3285. BOOL (*pfnContinue)(ULONG_PTR), ULONG_PTR dwContinue)
  3286. {
  3287. if (_pvo && lprcBounds)
  3288. {
  3289. if (_uState == SVUIA_DEACTIVATE && _hwnd)
  3290. {
  3291. HRESULT hresT = S_OK;
  3292. RECT rcClient;
  3293. GetClientRect(_hwnd, &rcClient);
  3294. //
  3295. // We should not call SetExtent with an empty rectangle.
  3296. // It happens when we print a page with a floating frame.
  3297. //
  3298. if (rcClient.right > 0 && rcClient.bottom > 0)
  3299. {
  3300. SIZEL sizel;
  3301. sizel.cx = MulDiv( rcClient.right, 2540, GetDeviceCaps( hdcDraw, LOGPIXELSX ) );
  3302. sizel.cy = MulDiv( rcClient.bottom, 2540, GetDeviceCaps( hdcDraw, LOGPIXELSY ) );
  3303. hresT = _pole->SetExtent(DVASPECT_CONTENT, &sizel);
  3304. }
  3305. #ifdef DEBUG
  3306. MoveToEx(hdcDraw, lprcBounds->left, lprcBounds->top, NULL);
  3307. LineTo(hdcDraw, lprcBounds->right, lprcBounds->bottom);
  3308. LineTo(hdcDraw, lprcBounds->left, lprcBounds->bottom);
  3309. LineTo(hdcDraw, lprcBounds->right, lprcBounds->top);
  3310. #endif
  3311. if (hresT!=S_OK) {
  3312. TraceMsg(DM_ERROR, "CDOH::Draw SetExtent returns non S_OK %x", hresT);
  3313. }
  3314. }
  3315. return _pvo->Draw(dwDrawAspect, lindex, pvAspect, ptd, hicTargetDev,
  3316. hdcDraw, lprcBounds, lprcWBounds, pfnContinue, dwContinue);
  3317. }
  3318. return OLE_E_BLANK;
  3319. }
  3320. HRESULT CDocObjectHost::GetColorSet(DWORD dwAspect, LONG lindex,
  3321. void *pvAspect, DVTARGETDEVICE *ptd, HDC hicTargetDev,
  3322. LOGPALETTE **ppColorSet)
  3323. {
  3324. if (_pvo)
  3325. {
  3326. return _pvo->GetColorSet(dwAspect, lindex, pvAspect, ptd, hicTargetDev,
  3327. ppColorSet);
  3328. }
  3329. if (ppColorSet)
  3330. *ppColorSet = NULL;
  3331. return S_FALSE;
  3332. }
  3333. HRESULT CDocObjectHost::Freeze(DWORD, LONG, void *, DWORD *pdwFreeze)
  3334. {
  3335. if (pdwFreeze)
  3336. *pdwFreeze = 0;
  3337. return E_NOTIMPL;
  3338. }
  3339. HRESULT CDocObjectHost::Unfreeze(DWORD)
  3340. {
  3341. return E_NOTIMPL;
  3342. }
  3343. HRESULT CDocObjectHost::SetAdvise(DWORD dwAspect, DWORD advf,
  3344. IAdviseSink *pSink)
  3345. {
  3346. if (dwAspect != DVASPECT_CONTENT)
  3347. return DV_E_DVASPECT;
  3348. if (advf & ~(ADVF_PRIMEFIRST | ADVF_ONLYONCE))
  3349. return E_INVALIDARG;
  3350. if (pSink != _padvise)
  3351. {
  3352. ATOMICRELEASE(_padvise);
  3353. _padvise = pSink;
  3354. if (_padvise)
  3355. _padvise->AddRef();
  3356. }
  3357. if (_padvise)
  3358. {
  3359. _advise_aspect = dwAspect;
  3360. _advise_advf = advf;
  3361. if (advf & ADVF_PRIMEFIRST)
  3362. OnViewChange(_advise_aspect, -1);
  3363. }
  3364. else
  3365. _advise_aspect = _advise_advf = 0;
  3366. return S_OK;
  3367. }
  3368. HRESULT CDocObjectHost::GetAdvise(DWORD *pdwAspect, DWORD *padvf,
  3369. IAdviseSink **ppSink)
  3370. {
  3371. if (pdwAspect)
  3372. *pdwAspect = _advise_aspect;
  3373. if (padvf)
  3374. *padvf = _advise_advf;
  3375. if (ppSink)
  3376. {
  3377. if (_padvise)
  3378. _padvise->AddRef();
  3379. *ppSink = _padvise;
  3380. }
  3381. return S_OK;
  3382. }
  3383. // IAdviseSink
  3384. void CDocObjectHost::OnDataChange(FORMATETC *, STGMEDIUM *)
  3385. {
  3386. }
  3387. void CDocObjectHost::OnViewChange(DWORD dwAspect, LONG lindex)
  3388. {
  3389. dwAspect &= _advise_aspect;
  3390. if (dwAspect && _padvise)
  3391. {
  3392. IAdviseSink *pSink = _padvise;
  3393. IUnknown *punkRelease;
  3394. if (_advise_advf & ADVF_ONLYONCE)
  3395. {
  3396. punkRelease = pSink;
  3397. _padvise = NULL;
  3398. _advise_aspect = _advise_advf = 0;
  3399. }
  3400. else
  3401. punkRelease = NULL;
  3402. pSink->OnViewChange(dwAspect, lindex);
  3403. if (punkRelease)
  3404. punkRelease->Release();
  3405. }
  3406. }
  3407. void CDocObjectHost::OnRename(IMoniker *)
  3408. {
  3409. }
  3410. void CDocObjectHost::OnSave()
  3411. {
  3412. }
  3413. void CDocObjectHost::OnClose()
  3414. {
  3415. //
  3416. // the doc object below went away so tell our advisee something changed
  3417. //
  3418. if (_padvise)
  3419. OnViewChange(_advise_aspect, -1);
  3420. }
  3421. // IOleWindow
  3422. HRESULT CDocObjectHost::GetWindow(HWND * lphwnd)
  3423. {
  3424. *lphwnd = _hwnd;
  3425. return S_OK;
  3426. }
  3427. HRESULT CDocObjectHost::ContextSensitiveHelp(BOOL fEnterMode)
  3428. {
  3429. // NOTES: This is optional
  3430. return E_NOTIMPL; // As specified in Kraig's document (optional)
  3431. }
  3432. // IOleInPlaceSite
  3433. HRESULT CDocObjectHost::CanInPlaceActivate(void)
  3434. {
  3435. OIPSMSG(TEXT("CanInPlaceActivate called"));
  3436. return S_OK;
  3437. }
  3438. HRESULT CDocObjectHost::OnInPlaceActivate(void)
  3439. {
  3440. OIPSMSG(TEXT("OnInPlaceActivate called"));
  3441. return S_OK;
  3442. }
  3443. HRESULT CDocObjectHost::OnUIActivate( void)
  3444. {
  3445. TraceMsg(TF_SHDUIACTIVATE, "-----------------------------------");
  3446. TraceMsg(TF_SHDUIACTIVATE, "OH::OnUIActivate called (this=%x)", this);
  3447. //
  3448. // Hide Office toolbars early enough so that it won't flash.
  3449. //
  3450. _HideOfficeToolbars();
  3451. // REVIEW:
  3452. // Should we remove 'our' menu here instead?
  3453. //
  3454. // [Copied from OLE 2.01 Spec]
  3455. // The container should remove any UI associated with its own
  3456. // activation. This is significant if the container is itself
  3457. // an embedded object.
  3458. //
  3459. OIPSMSG(TEXT("OnUIActivate called"));
  3460. if (EVAL(_psb))
  3461. {
  3462. // If we had the DocObject in SVUIA_INPLACEACTIVATE send it to SVUIA_ACTIVATE_FOCUS
  3463. //
  3464. // NOTES: Unlike IE3.0, we don't call _psv->UIActivate which has a side
  3465. // effect. We just update the _uState.
  3466. //
  3467. // _psv->UIActivate(SVUIA_ACTIVATE_FOCUS);
  3468. //
  3469. _uState = SVUIA_ACTIVATE_FOCUS;
  3470. return _psb->OnViewWindowActive(_psv);
  3471. }
  3472. return E_FAIL;
  3473. }
  3474. void CDocObjectHost::_GetClipRect(RECT* prc)
  3475. {
  3476. GetClientRect(_hwnd, prc);
  3477. prc->right -= _bwTools.right;
  3478. prc->bottom -= _bwTools.bottom;
  3479. }
  3480. IOleInPlaceSite* CDocObjectHost::_GetParentSite()
  3481. {
  3482. IOleInPlaceSite* pparentsite = NULL; // the parent's inplace site
  3483. if (_pwb)
  3484. {
  3485. _pwb->GetParentSite(&pparentsite);
  3486. }
  3487. return pparentsite;
  3488. }
  3489. HRESULT CDocObjectHost::GetWindowContext(
  3490. /* [out] */ IOleInPlaceFrame **ppFrame,
  3491. /* [out] */ IOleInPlaceUIWindow **ppDoc,
  3492. /* [out] */ LPRECT lprcPosRect,
  3493. /* [out] */ LPRECT lprcClipRect,
  3494. /* [out][in] */ LPOLEINPLACEFRAMEINFO lpFrameInfo)
  3495. {
  3496. OIPSMSG(TEXT("GetWindowContext called"));
  3497. // Todo: verify that lpFrameInfo->cb is the correct size!
  3498. // TraceMsg(0, "sdv TR - ::GetWindowContext called with lpFI->cb=%d (%d)",
  3499. // lpFrameInfo->cb, sizeof(*lpFrameInfo));
  3500. *ppFrame = &_dof; AddRef();
  3501. *ppDoc = NULL; // indicating that doc window == frame window
  3502. _GetClipRect(lprcClipRect);
  3503. lpFrameInfo->fMDIApp = FALSE;
  3504. //
  3505. // If the frame has IOleInPlaceUIWindow (both IE and Shell have),
  3506. // return that hwnd as hwndFrame so that OLE's menu dispatching
  3507. // code works correctly.
  3508. //
  3509. _dof.GetWindow(&lpFrameInfo->hwndFrame);
  3510. //
  3511. // We need to find out (from SriniK or KraigB), what is the
  3512. // implecation of this accelerator. Dealing with Word, it seems that
  3513. // Word does not call our TranslateAccelerator at all, unless the key
  3514. // stroke is the accelerator. If that's the spec. (of DocObject),
  3515. // there is no way to process the accelerator of the browser.
  3516. //
  3517. lpFrameInfo->haccel = _hacc;
  3518. if (!SHRestricted(REST_NOFILEMENU))
  3519. {
  3520. #ifdef DEBUG
  3521. lpFrameInfo->cAccelEntries = DBG_ACCELENTRIES_WITH_FILEMENU; // WARNING: see shdocvw.rc, ACCELL_DOCVIEW
  3522. #else
  3523. lpFrameInfo->cAccelEntries = OPT_ACCELENTRIES_WITH_FILEMENU; // WARNING: see shdocvw.rc, ACCELL_DOCVIEW
  3524. #endif
  3525. }
  3526. else
  3527. {
  3528. #ifdef DEBUG
  3529. lpFrameInfo->cAccelEntries = DBG_ACCELENTRIES; // WARNING: see shdocvw.rc, ACCELL_DOCVIEW
  3530. #else
  3531. lpFrameInfo->cAccelEntries = OPT_ACCELENTRIES; // WARNING: see shdocvw.rc, ACCELL_DOCVIEW
  3532. #endif
  3533. }
  3534. *lprcPosRect = _rcView;
  3535. return S_OK;
  3536. }
  3537. HRESULT CDocObjectHost::Scroll(
  3538. /* [in] */ SIZE scrollExtant)
  3539. {
  3540. TraceMsg(0, "sdv TR - ::Scroll called");
  3541. return E_NOTIMPL; // As specified in Kraig's document
  3542. }
  3543. HRESULT CDocObjectHost::OnUIDeactivate(
  3544. /* [in] */ BOOL fUndoable)
  3545. {
  3546. TraceMsg(TF_SHDUIACTIVATE, "DOH::OnUIDeactivate called (this=%x)", this);
  3547. DEBUG_CODE( _DumpMenus(TEXT("on OnUIDeactivate"), TRUE); )
  3548. if (_hmenuSet) {
  3549. OIPSMSG(TEXT("OnUIDeactivate We need to SetMenu(NULL, NULL, NULL)"));
  3550. _SetMenu(NULL, NULL, NULL);
  3551. }
  3552. return S_OK;
  3553. }
  3554. HRESULT CDocObjectHost::OnInPlaceDeactivate( void)
  3555. {
  3556. OIPSMSG(TEXT("OnInPlaceDeactivate called"));
  3557. return S_OK;
  3558. }
  3559. HRESULT CDocObjectHost::DiscardUndoState( void)
  3560. {
  3561. TraceMsg(0, "sdv TR - ::DiscardUndoState called");
  3562. return S_OK;
  3563. }
  3564. HRESULT CDocObjectHost::DeactivateAndUndo( void)
  3565. {
  3566. TraceMsg(0, "sdv TR - ::DeactivateAndUndo called");
  3567. return S_OK;
  3568. }
  3569. HRESULT CDocObjectHost::OnPosRectChange(
  3570. /* [in] */ LPCRECT lprcPosRect)
  3571. {
  3572. return E_NOTIMPL; // As specified in Kraig's document
  3573. }
  3574. HRESULT CDocObjectHost::OnInPlaceActivateEx(
  3575. /* [out] */ BOOL __RPC_FAR *pfNoRedraw,
  3576. /* [in] */ DWORD dwFlags)
  3577. {
  3578. OIPSMSG(TEXT("OnInPlaceActivateEx called"));
  3579. return S_OK;
  3580. }
  3581. HRESULT CDocObjectHost::OnInPlaceDeactivateEx(
  3582. /* [in] */ BOOL fNoRedraw)
  3583. {
  3584. OIPSMSG(TEXT("OnInPlaceDeactivateEx called"));
  3585. return S_OK;
  3586. }
  3587. HRESULT CDocObjectHost::RequestUIActivate( void)
  3588. {
  3589. if (_pWebOCInPlaceSiteEx)
  3590. return _pWebOCInPlaceSiteEx->RequestUIActivate();
  3591. else
  3592. return TRUE;
  3593. }
  3594. void CDocObjectHost::_OnNotify(LPNMHDR lpnm)
  3595. {
  3596. switch(lpnm->code) {
  3597. case TBN_BEGINDRAG:
  3598. #define ptbn ((LPTBNOTIFY)lpnm)
  3599. _OnMenuSelect(ptbn->iItem, 0, NULL);
  3600. break;
  3601. }
  3602. }
  3603. void MapAtToNull(LPTSTR psz)
  3604. {
  3605. while (*psz)
  3606. {
  3607. if (*psz == TEXT('@'))
  3608. {
  3609. LPTSTR pszNext = CharNext(psz);
  3610. *psz = 0;
  3611. psz = pszNext;
  3612. }
  3613. else
  3614. {
  3615. psz = CharNext(psz);
  3616. }
  3617. }
  3618. }
  3619. void BrowsePushed(HWND hDlg)
  3620. {
  3621. TCHAR szText[MAX_PATH];
  3622. DWORD cchText = ARRAYSIZE(szText);
  3623. TCHAR szFilter[MAX_PATH];
  3624. TCHAR szTitle[MAX_PATH];
  3625. LPITEMIDLIST pidl;
  3626. LPCITEMIDLIST pidlChild;
  3627. IShellFolder * pSF;
  3628. // load the filter and then replace all the @ characters with NULL. The end of the string will be doubly
  3629. // null-terminated
  3630. MLLoadShellLangString(IDS_BROWSEFILTER, szFilter, ARRAYSIZE(szFilter));
  3631. MapAtToNull(szFilter);
  3632. GetDlgItemText(hDlg, IDD_COMMAND, szText, ARRAYSIZE(szText));
  3633. PathUnquoteSpaces(szText);
  3634. // eliminate the "file://" stuff if necessary
  3635. if (IsFileUrlW(szText))
  3636. PathCreateFromUrl(szText, szText, &cchText, 0);
  3637. MLLoadShellLangString(IDS_TITLE, szTitle, ARRAYSIZE(szTitle));
  3638. if (GetFileNameFromBrowse(hDlg, szText, ARRAYSIZE(szText), NULL,
  3639. TEXT(".htm"), szFilter, szTitle))
  3640. {
  3641. if (SUCCEEDED(IECreateFromPath(szText, &pidl)))
  3642. {
  3643. if (SUCCEEDED(IEBindToParentFolder(pidl, &pSF, &pidlChild)))
  3644. {
  3645. HWND hWndCombo = GetDlgItem(hDlg, IDD_COMMAND);
  3646. COMBOBOXEXITEM cbexItem = {0};
  3647. cbexItem.mask = CBEIF_TEXT | CBEIF_IMAGE | CBEIF_SELECTEDIMAGE;
  3648. cbexItem.pszText = szText;
  3649. cbexItem.cchTextMax = ARRAYSIZE(szText);
  3650. cbexItem.iItem = -1;
  3651. cbexItem.iImage = IEMapPIDLToSystemImageListIndex(pSF, pidlChild, &cbexItem.iSelectedImage);
  3652. INT_PTR iPosition = SendMessage(hWndCombo, CBEM_INSERTITEM, (WPARAM)0, (LPARAM)(LPVOID)&cbexItem);
  3653. SendMessage(hWndCombo, CB_SETCURSEL, (WPARAM)iPosition, (LPARAM)0);
  3654. pSF->Release();
  3655. }
  3656. ILFree(pidl);
  3657. }
  3658. else
  3659. {
  3660. PathUnquoteSpaces(szText);
  3661. SetDlgItemText(hDlg, IDD_COMMAND, szText);
  3662. }
  3663. EnableOKButtonFromID(hDlg, IDD_COMMAND);
  3664. // place the focus on OK
  3665. SendMessage(hDlg, WM_NEXTDLGCTL, (WPARAM)GetDlgItem(hDlg, IDOK), TRUE);
  3666. }
  3667. }
  3668. struct SOpenDlg {
  3669. TCHAR szURL[MAX_URL_STRING];
  3670. IAddressEditBox *paebox; // Object that controls ComboBoxEx
  3671. IBandSite *pbs; // Used in AEBox Init call (used as a Connection Site)
  3672. IWinEventHandler *pweh; // Used to funnel IDD_COMMAND messages to the AEBox
  3673. };
  3674. const DWORD c_mapCtrlToContextIds[] = { 0, 0 };
  3675. const DWORD c_aRunHelpIds[] = {
  3676. IDD_ICON, NO_HELP,
  3677. IDD_PROMPT, NO_HELP,
  3678. IDD_RUNDLGOPENPROMPT, IDH_IE_RUN_COMMAND,
  3679. IDD_COMMAND, IDH_IE_RUN_COMMAND,
  3680. IDD_BROWSE, IDH_RUNBROWSE,
  3681. IDC_ASWEBFOLDER, IDH_WEB_FOLDERS_CKBOX,
  3682. 0, 0
  3683. };
  3684. HRESULT OpenDlgOnWebFolderOK(HWND hDlg, SOpenDlg * podlg)
  3685. {
  3686. ASSERT(podlg);
  3687. HRESULT hr = S_OK;
  3688. HWND hWndOpenBox = GetDlgItem(hDlg, IDD_COMMAND);
  3689. ComboBox_GetText(hWndOpenBox, podlg->szURL, ARRAYSIZE(podlg->szURL));
  3690. PathRemoveBlanks(podlg->szURL);
  3691. // int iScheme = GetUrlScheme(podlg->szURL);
  3692. // if ((URL_SCHEME_HTTP != iScheme) &&
  3693. // (URL_SCHEME_HTTPS != iScheme))
  3694. // {
  3695. // no, we don't support that protocol!!
  3696. // WCHAR wszMessage[MAX_PATH];
  3697. // WCHAR wszTitle[MAX_PATH];
  3698. // WCHAR wszErrorMessage[MAX_PATH + MAX_URL_STRING + 1];
  3699. // MLLoadShellLangString(IDS_ERRORBADURL, wszMessage, ARRAYSIZE(wszMessage));
  3700. // MLLoadShellLangString(IDS_ERRORBADURLTITLE, wszTitle, ARRAYSIZE(wszTitle));
  3701. // wnsprintf(wszErrorMessage, ARRAYSIZE(wszErrorMessage), wszMessage, podlg->szURL);
  3702. // MessageBox(hDlg, wszErrorMessage, wszTitle, MB_OK | MB_ICONERROR);
  3703. // hr = E_FAIL;
  3704. // }
  3705. return hr;
  3706. }
  3707. HRESULT OpenDlgOnOK(HWND hDlg, SOpenDlg * podlg)
  3708. {
  3709. ASSERT(podlg);
  3710. HRESULT hr = S_OK;
  3711. /*
  3712. Try to use newer parsing code if we have an AddressEditBox object
  3713. */
  3714. if (podlg->paebox)
  3715. hr = podlg->paebox->ParseNow(SHURL_FLAGS_NONE);
  3716. else
  3717. {
  3718. HWND hWndOpenBox = GetDlgItem(hDlg, IDD_COMMAND);
  3719. ComboBox_GetText(hWndOpenBox, podlg->szURL, ARRAYSIZE(podlg->szURL));
  3720. PathRemoveBlanks(podlg->szURL);
  3721. }
  3722. return hr;
  3723. }
  3724. void CleanUpAutoComplete(SOpenDlg *podlg)
  3725. {
  3726. ATOMICRELEASE(podlg->paebox);
  3727. ATOMICRELEASE(podlg->pweh);
  3728. ATOMICRELEASE(podlg->pbs);
  3729. ZeroMemory((PVOID)podlg, SIZEOF(SOpenDlg));
  3730. }
  3731. BOOL_PTR CALLBACK CDocObjectHost::s_RunDlgProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
  3732. {
  3733. SOpenDlg* podlg = (SOpenDlg*)GetWindowLongPtr(hDlg, DWLP_USER);
  3734. switch (uMsg)
  3735. {
  3736. case WM_DESTROY:
  3737. SHRemoveDefaultDialogFont(hDlg);
  3738. return FALSE;
  3739. case WM_INITDIALOG:
  3740. {
  3741. ASSERT(lParam);
  3742. HWND hWndOpenBox = GetDlgItem(hDlg, IDD_COMMAND);
  3743. HWND hWndEditBox = (HWND)SendMessage(hWndOpenBox, CBEM_GETEDITCONTROL, 0,0);
  3744. SetWindowLongPtr(hDlg, DWLP_USER, lParam);
  3745. podlg = (SOpenDlg *)lParam;
  3746. // cross-lang platform support
  3747. SHSetDefaultDialogFont(hDlg, IDD_COMMAND);
  3748. if (podlg->paebox)
  3749. {
  3750. if ( FAILED(podlg->paebox->Init(hWndOpenBox, hWndEditBox, AEB_INIT_DEFAULT | AEB_INIT_NOASYNC, podlg->pbs)) ||
  3751. FAILED(IUnknown_SetOwner(podlg->paebox, podlg->pbs)))
  3752. CleanUpAutoComplete(podlg);
  3753. }
  3754. // this limit.
  3755. SendMessage(hWndOpenBox, CB_LIMITTEXT, CBEMAXSTRLEN-1, 0L);
  3756. EnableWindow(GetDlgItem(hDlg, IDOK), FALSE);
  3757. if (SHRestricted(REST_NORUN))
  3758. EnableWindow(GetDlgItem(hDlg, IDC_ASWEBFOLDER), FALSE); // disable open as web folder
  3759. break;
  3760. }
  3761. case WM_HELP:
  3762. SHWinHelpOnDemandWrap((HWND) ((LPHELPINFO) lParam)->hItemHandle, c_szHelpFile,
  3763. HELP_WM_HELP, (DWORD_PTR)(LPTSTR) c_aRunHelpIds);
  3764. break;
  3765. case WM_CONTEXTMENU: // right mouse click
  3766. SHWinHelpOnDemandWrap((HWND) wParam, c_szHelpFile, HELP_CONTEXTMENU,
  3767. (DWORD_PTR)(LPTSTR) c_aRunHelpIds);
  3768. break;
  3769. case WM_COMMAND:
  3770. switch (GET_WM_COMMAND_ID(wParam, lParam))
  3771. {
  3772. case IDHELP:
  3773. break;
  3774. case IDD_BROWSE:
  3775. BrowsePushed(hDlg);
  3776. break;
  3777. case IDD_COMMAND:
  3778. switch (GET_WM_COMMAND_CMD(wParam, lParam))
  3779. {
  3780. case CBN_SELCHANGE:
  3781. break;
  3782. case CBN_EDITCHANGE:
  3783. case CBN_SELENDOK:
  3784. if (podlg->pweh)
  3785. podlg->pweh->OnWinEvent(hDlg, uMsg, wParam, lParam, NULL);
  3786. EnableOKButtonFromID(hDlg, IDD_COMMAND);
  3787. break;
  3788. default:
  3789. if (podlg->pweh)
  3790. podlg->pweh->OnWinEvent(hDlg, uMsg, wParam, lParam, NULL);
  3791. break;
  3792. }
  3793. break;
  3794. case IDOK:
  3795. {
  3796. HWND hwndCheckBox = GetDlgItem(hDlg, IDC_ASWEBFOLDER);
  3797. if (hwndCheckBox)
  3798. {
  3799. LRESULT lrState = SendMessage(hwndCheckBox, BM_GETCHECK, 0, 0);
  3800. if (lrState == BST_CHECKED)
  3801. {
  3802. if (SUCCEEDED(OpenDlgOnWebFolderOK(hDlg, podlg)))
  3803. EndDialog(hDlg, IDC_ASWEBFOLDER);
  3804. break;
  3805. }
  3806. else if (FAILED(OpenDlgOnOK(hDlg, podlg)))
  3807. break;
  3808. }
  3809. }
  3810. // Fall through to IDCANCEL to close dlg
  3811. case IDCANCEL:
  3812. EndDialog(hDlg, GET_WM_COMMAND_ID(wParam, lParam));
  3813. break;
  3814. default:
  3815. return FALSE;
  3816. }
  3817. break;
  3818. default:
  3819. return FALSE;
  3820. }
  3821. return TRUE;
  3822. }
  3823. void CDocObjectHost::_Navigate(LPCWSTR pwszURL)
  3824. {
  3825. IWebBrowser2* pwb2;
  3826. if (SUCCEEDED(IUnknown_QueryService(_psb, SID_SContainerDispatch, IID_IWebBrowser2, (void **)&pwb2)))
  3827. {
  3828. //
  3829. // HACK: We are not passing BSTR, but LPWSTR, which
  3830. // will work as far as IWebBrowser2 can handle
  3831. // NULL-terminated string correctly.
  3832. //
  3833. pwb2->Navigate((BSTR)pwszURL, NULL, NULL, NULL, NULL);
  3834. pwb2->Release();
  3835. }
  3836. }
  3837. HRESULT CDocObjectHost::_PrepFileOpenAddrBand(IAddressEditBox ** ppaeb, IWinEventHandler ** ppweh, IBandSite ** ppbs)
  3838. {
  3839. HRESULT hr;
  3840. *ppaeb = NULL;
  3841. *ppweh = NULL;
  3842. *ppbs = NULL;
  3843. // If our CoCreateInstance fails, s_rundlgproc will know because paebox
  3844. // will be NULL
  3845. hr = CoCreateInstance(CLSID_AddressEditBox, NULL, CLSCTX_INPROC_SERVER, IID_IAddressEditBox, (void **)ppaeb);
  3846. if (EVAL(SUCCEEDED(hr)))
  3847. {
  3848. IServiceProvider *pspT;
  3849. hr = (*ppaeb)->QueryInterface(IID_IWinEventHandler, (void **)ppweh);
  3850. // Travel up the object hierarchy, and obtain the same pointer that
  3851. // the address bar was ::Init'ed with
  3852. // WARNING: This is not optional. The addressband will fault if this fails.
  3853. if (EVAL(SUCCEEDED(hr) && _psp))
  3854. {
  3855. hr = _psp->QueryService(SID_SExplorerToolbar, IID_IServiceProvider, (void **)&pspT);
  3856. // In framed cases, CBaseBrowser2::QueryService() will filter out SID_SExplorerToolbar
  3857. // because it's afraid of Toolbars appearing in the frame. We won't have that problem,
  3858. // so we may need to go the TopLevelBrowser first and then ask around there.
  3859. if (FAILED(hr))
  3860. {
  3861. IServiceProvider *pspT2;
  3862. hr = _psp->QueryService(SID_STopLevelBrowser, IID_IServiceProvider, (void **)&pspT2);
  3863. if (EVAL(SUCCEEDED(hr)))
  3864. {
  3865. hr = pspT2->QueryService(SID_SExplorerToolbar, IID_IServiceProvider, (void **)&pspT);
  3866. pspT2->Release();
  3867. }
  3868. }
  3869. if (EVAL(SUCCEEDED(hr)))
  3870. {
  3871. if (EVAL(SUCCEEDED(hr = pspT->QueryService(IID_IBandSite, IID_IBandSite, (void **)ppbs))))
  3872. {
  3873. IDeskBand *pdbT;
  3874. // Had to include "ITBAR.H" to access CBIDX_ADDDRESS
  3875. // HACKHACK
  3876. #define CBIDX_ADDRESS 4
  3877. // If any of the following fails, I don't care because the MRU can be out of
  3878. // synch.
  3879. if (SUCCEEDED((*ppbs)->QueryBand(CBIDX_ADDRESS, &pdbT, NULL, NULL, 0)))
  3880. {
  3881. IUnknown_Exec(pdbT, &CGID_AddressEditBox, AECMDID_SAVE, 0, NULL, NULL);
  3882. pdbT->Release();
  3883. }
  3884. }
  3885. pspT->Release();
  3886. }
  3887. }
  3888. }
  3889. if (FAILED(hr))
  3890. {
  3891. ATOMICRELEASE(*ppaeb);
  3892. ATOMICRELEASE(*ppweh);
  3893. ATOMICRELEASE(*ppbs);
  3894. }
  3895. return hr;
  3896. }
  3897. void CDocObjectHost::_OnOpen(void)
  3898. {
  3899. HWND hwndFrame;
  3900. SOpenDlg odlg ={0};
  3901. _psb->GetWindow(&hwndFrame);
  3902. if (SHIsRestricted2W(_hwnd, REST_NoFileOpen, NULL, 0))
  3903. return;
  3904. if (EVAL(SUCCEEDED(_PrepFileOpenAddrBand(&(odlg.paebox), &odlg.pweh, &odlg.pbs))))
  3905. {
  3906. // TODO: Make it a helper member, which notifies up and down.
  3907. _psb->EnableModelessSB(FALSE);
  3908. INT_PTR iRet = DialogBoxParam(MLGetHinst(), MAKEINTRESOURCE(DLG_RUN), hwndFrame, s_RunDlgProc, (LPARAM)&odlg);
  3909. _psb->EnableModelessSB(TRUE);
  3910. if (iRet==IDOK)
  3911. {
  3912. if (g_dwStopWatchMode) // Perf mode to mark start time
  3913. StopWatch_MarkSameFrameStart(hwndFrame);
  3914. if (odlg.paebox)
  3915. odlg.paebox->Execute(SHURL_EXECFLAGS_NONE);
  3916. else
  3917. _Navigate(odlg.szURL);
  3918. }
  3919. if (iRet == IDC_ASWEBFOLDER)
  3920. {
  3921. BSTR bstrUrl = SysAllocString(odlg.szURL);
  3922. if (bstrUrl != NULL)
  3923. {
  3924. _NavigateFolder(bstrUrl);
  3925. SysFreeString(bstrUrl);
  3926. }
  3927. }
  3928. IUnknown_SetOwner(odlg.paebox, NULL);
  3929. }
  3930. // Cleanup ref counts
  3931. CleanUpAutoComplete(&odlg);
  3932. }
  3933. void CDocObjectHost::_OnClose() const
  3934. {
  3935. ASSERT(_pwb);
  3936. if (!_HideBrowserBar())
  3937. {
  3938. HRESULT hr = E_FAIL;
  3939. HWND hwnd = NULL;
  3940. IOleWindow * pOleWindow;
  3941. if ( _pwb )
  3942. {
  3943. hr = _pwb->QueryInterface(IID_PPV_ARG(IOleWindow, &pOleWindow));
  3944. }
  3945. if (SUCCEEDED(hr))
  3946. {
  3947. pOleWindow->GetWindow(&hwnd);
  3948. pOleWindow->Release();
  3949. if ( hwnd )
  3950. {
  3951. PostMessage(hwnd, WM_CLOSE, 0, 0);
  3952. }
  3953. }
  3954. }
  3955. }
  3956. BOOL CDocObjectHost::_HideBrowserBar() const
  3957. {
  3958. ASSERT(_pwb);
  3959. // Get the proxy browser. We only have
  3960. // a proxy browser if we are in a band.
  3961. //
  3962. IShellBrowser * pPrxyBrowser;
  3963. HRESULT hr = IUnknown_QueryService(_pwb,
  3964. SID_SProxyBrowser,
  3965. IID_IShellBrowser,
  3966. (void**)&pPrxyBrowser);
  3967. if (SUCCEEDED(hr))
  3968. {
  3969. hr = IUnknown_ShowBrowserBar(_psb, CLSID_SearchBand, FALSE);
  3970. }
  3971. return (SUCCEEDED(hr) ? TRUE : FALSE);
  3972. }
  3973. void CDocObjectHost::_OnImportExport(HWND hwnd)
  3974. {
  3975. // Decide if import/export is allowed here
  3976. if (IsImportExportDisabled())
  3977. {
  3978. MLShellMessageBox(
  3979. hwnd,
  3980. MAKEINTRESOURCE(IDS_EXPORT_DISABLED),
  3981. MAKEINTRESOURCE(IDS_CONFIRM_EXPTTL_FAV),
  3982. MB_OK);
  3983. return;
  3984. }
  3985. RunImportExportFavoritesWizard(hwnd);
  3986. }
  3987. void CDocObjectHost::_OnAddToSitesList(HWND hwnd, DWORD dwZone)
  3988. {
  3989. HMODULE hmod = LoadLibrary(TEXT("inetcpl.cpl"));
  3990. if(hmod)
  3991. {
  3992. BOOL (*pfnAddSitesDlg)(HWND, DWORD, LPCWSTR) = (BOOL (*)(HWND, DWORD, LPCWSTR))GetProcAddress(hmod, "LaunchAddSitesDialog");
  3993. if(pfnAddSitesDlg)
  3994. {
  3995. LPOLESTR pszUrl;
  3996. if (SUCCEEDED(_GetCurrentPageW(&pszUrl, TRUE)))
  3997. {
  3998. pfnAddSitesDlg(hwnd, dwZone, pszUrl);
  3999. OleFree(pszUrl);
  4000. }
  4001. }
  4002. FreeLibrary(hmod);
  4003. }
  4004. }
  4005. UINT_PTR CALLBACK DocHostSaveAsOFNHook(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam)
  4006. {
  4007. switch (msg)
  4008. {
  4009. case WM_INITDIALOG:
  4010. {
  4011. /* Hide the "Save as Type" text box */
  4012. CommDlg_OpenSave_HideControl(GetParent(hDlg), stc2);
  4013. /* Hide the listbox with save type extensions */
  4014. CommDlg_OpenSave_HideControl(GetParent(hDlg), cmb1);
  4015. /* Hide the Open as read-only control */
  4016. CommDlg_OpenSave_HideControl(GetParent(hDlg), chx1);
  4017. break;
  4018. }
  4019. default:
  4020. break;
  4021. }
  4022. return FALSE;
  4023. }
  4024. #define IDS_HELPURL_SUPPORT IDS_HELPMSWEB+4
  4025. #define SZ_REGKEY_HELPURL_OVERRIDE TEXT("Software\\Microsoft\\Internet Explorer\\Help_Menu_URLs")
  4026. #define SZ_REGVAL_HELPURL_SUPPORT TEXT("Online_Support")
  4027. #define SZ_REGVAL_HELPURL_TEMPLATE TEXT("%d")
  4028. void CDocObjectHost::_OnHelpGoto(UINT idRes)
  4029. {
  4030. HRESULT hr = E_FAIL;
  4031. WCHAR szURL[MAX_PATH]; // this is enough for our own
  4032. // First try to get a copy from the registry because this is where Admins (with the IEAK) over ride
  4033. // our default values.
  4034. // We special case the Online_Support URL because it was supported in IE3.
  4035. if (IDS_HELPURL_SUPPORT == idRes)
  4036. {
  4037. hr = URLSubRegQuery(SZ_REGKEY_HELPURL_OVERRIDE, SZ_REGVAL_HELPURL_SUPPORT, TRUE, szURL, ARRAYSIZE(szURL), URLSUB_ALL);
  4038. }
  4039. else
  4040. {
  4041. WCHAR szValue[MAX_PATH];
  4042. wnsprintfW(szValue, ARRAYSIZE(szValue), SZ_REGVAL_HELPURL_TEMPLATE, (idRes - IDS_HELPMSWEB + 1));
  4043. hr = URLSubRegQuery(SZ_REGKEY_HELPURL_OVERRIDE, szValue, TRUE, szURL, ARRAYSIZE(szURL), URLSUB_ALL);
  4044. }
  4045. if (FAILED(hr))
  4046. hr = URLSubLoadString(NULL, idRes, szURL, ARRAYSIZE(szURL), URLSUB_ALL);
  4047. if (SUCCEEDED(hr))
  4048. {
  4049. _Navigate(szURL);
  4050. }
  4051. }
  4052. STDAPI_(void) IEAboutBox( HWND hWnd );
  4053. // WM_COMMAND from _WndProc - execs are going down
  4054. void CDocObjectHost::_OnCommand(UINT wNotify, UINT id, HWND hwndControl)
  4055. {
  4056. if (_ShouldForwardMenu(WM_COMMAND, MAKEWPARAM(id, wNotify), (LPARAM)hwndControl))
  4057. {
  4058. _ForwardObjectMsg(WM_COMMAND, MAKEWPARAM(id, wNotify), (LPARAM)hwndControl);
  4059. return;
  4060. }
  4061. switch(id)
  4062. {
  4063. case DVIDM_HELPTUTORIAL:
  4064. _OnHelpGoto(IDS_HELPTUTORIAL);
  4065. break;
  4066. // ShabbirS (980917): BugFix# 34259 - Repair IE option.
  4067. case DVIDM_HELPREPAIR:
  4068. RepairIE();
  4069. break;
  4070. case DVIDM_HELPABOUT:
  4071. IEAboutBox( _hwnd );
  4072. break;
  4073. case DVIDM_HELPSEARCH:
  4074. {
  4075. uCLSSPEC ucs;
  4076. QUERYCONTEXT qc = { 0 };
  4077. ucs.tyspec = TYSPEC_CLSID;
  4078. ucs.tagged_union.clsid = CLSID_IEHelp;
  4079. HRESULT hres = FaultInIEFeature(_hwnd, &ucs, &qc, FIEF_FLAG_FORCE_JITUI);
  4080. if ( SUCCEEDED( hres ) )
  4081. {
  4082. // MLHtmlHelp runs on a separate thread and should therefore be
  4083. // safe against the kinds of message loops problems indicated above
  4084. ULONG_PTR uCookie = 0;
  4085. SHActivateContext(&uCookie);
  4086. MLHtmlHelp(_hwnd, TEXT("iexplore.chm > iedefault"), HH_DISPLAY_TOPIC, 0, ML_CROSSCODEPAGE);
  4087. if (uCookie)
  4088. {
  4089. SHDeactivateContext(uCookie);
  4090. }
  4091. }
  4092. else
  4093. {
  4094. TraceMsg( TF_WARNING, "CDocObjectHost::_OnCommand() - FaultInIEFeature() Failed with hr=0x%x!", hres );
  4095. }
  4096. break;
  4097. }
  4098. case DVIDM_DHFAVORITES:
  4099. _pmsoctBrowser->Exec(&CGID_Explorer, SBCMDID_ADDTOFAVORITES, OLECMDEXECOPT_PROMPTUSER, NULL, NULL);
  4100. break;
  4101. case DVIDM_GOHOME:
  4102. case DVIDM_GOSEARCH:
  4103. {
  4104. TCHAR szPath[MAX_URL_STRING];
  4105. LPITEMIDLIST pidl;
  4106. HRESULT hres = SHDGetPageLocation(_hwnd,
  4107. (id==DVIDM_GOSEARCH) ? IDP_SEARCH : IDP_START,
  4108. szPath, ARRAYSIZE(szPath), &pidl);
  4109. if (SUCCEEDED(hres))
  4110. {
  4111. _psb->BrowseObject(pidl, SBSP_ABSOLUTE | SBSP_SAMEBROWSER);
  4112. ILFree(pidl);
  4113. }
  4114. else
  4115. {
  4116. TCHAR szMessage[256];
  4117. BOOL fSuccess = FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
  4118. NULL, hres, 0, szMessage, ARRAYSIZE(szMessage), NULL);
  4119. if (!fSuccess)
  4120. szMessage[0] = 0;
  4121. MLShellMessageBox(_hwnd,
  4122. MAKEINTRESOURCE(IDS_CANTACCESSDOCUMENT),
  4123. szPath, MB_OK | MB_SETFOREGROUND | MB_ICONSTOP, szMessage);
  4124. }
  4125. }
  4126. break;
  4127. case DVIDM_STOPDOWNLOAD:
  4128. // We need to tell the container to cancel a pending navigation
  4129. // if any. Notice that the Cancel button serves for two purposes:
  4130. // (1) canceling a pending navigation
  4131. // (2) cancel any downloading
  4132. if (_psb)
  4133. _CancelPendingNavigation(FALSE);
  4134. goto TryDocument;
  4135. case DVIDM_NEWWINDOW:
  4136. // make sure the top level browser gets cloned, not an explorer bar
  4137. IShellBrowser* psbTop;
  4138. if (!SHIsRestricted2W(_hwnd, REST_NoOpeninNewWnd, NULL, 0) &&
  4139. !SHIsRestricted2W(_hwnd, REST_NoFileNew, NULL, 0) &&
  4140. EVAL(SUCCEEDED(_psp->QueryService(SID_STopLevelBrowser, IID_IShellBrowser, (void **)&psbTop))) && psbTop)
  4141. {
  4142. BOOL fHandled = FALSE;
  4143. if (_pWebOCUIHandler)
  4144. {
  4145. // Give the WebOC host a chance to handle this command, since it may
  4146. // not want an IE window to be created
  4147. if (S_OK == IUnknown_Exec(_pWebOCUIHandler, &CGID_DocHostCommandHandler,
  4148. IDM_NEW_TOPLEVELWINDOW, 0, NULL, NULL))
  4149. {
  4150. fHandled = TRUE;
  4151. }
  4152. }
  4153. if (!fHandled)
  4154. {
  4155. // tell the top level browser to save its window size to the registry so
  4156. // that our new window can pick it up and cascade properly
  4157. IUnknown_Exec(psbTop, &CGID_Explorer, SBCMDID_SUGGESTSAVEWINPOS, 0, NULL, NULL);
  4158. psbTop->BrowseObject(&s_idNull, SBSP_RELATIVE|SBSP_NEWBROWSER);
  4159. psbTop->Release();
  4160. }
  4161. }
  4162. break;
  4163. case DVIDM_OPEN:
  4164. _OnOpen();
  4165. break;
  4166. case DVIDM_SAVE:
  4167. if (!SHIsRestricted2W(_hwnd, REST_NoBrowserSaveAs, NULL, 0))
  4168. {
  4169. // There's a scenario where the XML MimeViewer, when aggregating Trident, answers "disabled" to
  4170. // OLECMDID_SAVE. However, since we don't call QueryStatus on the ACCELERATOR key sequence,
  4171. // we end up calling into Trident's IPersistFile::Save(), overwriting the XML file with the converted
  4172. // HTML.
  4173. //
  4174. // The right thing to do is to QS and beep if disabled.
  4175. //
  4176. if (_dwAppHack & BROWSERFLAG_MSHTML)
  4177. {
  4178. if (_pmsot)
  4179. {
  4180. OLECMD rgcmds[] = { { OLECMDID_SAVE, 0 }, };
  4181. _pmsot->QueryStatus(NULL, ARRAYSIZE(rgcmds), rgcmds, NULL);
  4182. if (!(rgcmds[0].cmdf & OLECMDF_ENABLED))
  4183. {
  4184. // If SAVE is disabled, provide user feedback.
  4185. MessageBeep(0);
  4186. break;
  4187. }
  4188. }
  4189. }
  4190. _OnSave();
  4191. }
  4192. break;
  4193. case DVIDM_DESKTOPSHORTCUT:
  4194. IUnknown_Exec(_psb, &CGID_Explorer, SBCMDID_CREATESHORTCUT, 0, NULL, NULL);
  4195. break;
  4196. case DVIDM_SENDPAGE:
  4197. IUnknown_Exec(_psb, &CGID_Explorer, SBCMDID_SENDPAGE, 0, NULL, NULL);
  4198. break;
  4199. case DVIDM_SENDSHORTCUT:
  4200. IUnknown_Exec(_psb, &CGID_Explorer, SBCMDID_SENDSHORTCUT, 0, NULL, NULL);
  4201. break;
  4202. case DVIDM_NEWMESSAGE:
  4203. if (FAILED(DropOnMailRecipient(NULL, 0)))
  4204. {
  4205. SHRunIndirectRegClientCommand(_hwnd, NEW_MAIL_DEF_KEY);
  4206. }
  4207. break;
  4208. case DVIDM_NEWPOST:
  4209. SHRunIndirectRegClientCommand(_hwnd, NEW_NEWS_DEF_KEY);
  4210. break;
  4211. case DVIDM_NEWCONTACT:
  4212. SHRunIndirectRegClientCommand(_hwnd, NEW_CONTACTS_DEF_KEY);
  4213. break;
  4214. case DVIDM_NEWAPPOINTMENT:
  4215. SHRunIndirectRegClientCommand(_hwnd, NEW_APPOINTMENT_DEF_KEY);
  4216. break;
  4217. case DVIDM_NEWMEETING:
  4218. SHRunIndirectRegClientCommand(_hwnd, NEW_MEETING_DEF_KEY);
  4219. break;
  4220. case DVIDM_NEWTASK:
  4221. SHRunIndirectRegClientCommand(_hwnd, NEW_TASK_DEF_KEY);
  4222. break;
  4223. case DVIDM_NEWTASKREQUEST:
  4224. SHRunIndirectRegClientCommand(_hwnd, NEW_TASKREQUEST_DEF_KEY);
  4225. break;
  4226. case DVIDM_NEWJOURNAL:
  4227. SHRunIndirectRegClientCommand(_hwnd, NEW_JOURNAL_DEF_KEY);
  4228. break;
  4229. case DVIDM_NEWNOTE:
  4230. SHRunIndirectRegClientCommand(_hwnd, NEW_NOTE_DEF_KEY);
  4231. break;
  4232. case DVIDM_CALL:
  4233. SHRunIndirectRegClientCommand(_hwnd, NEW_CALL_DEF_KEY);
  4234. break;
  4235. case DVIDM_SAVEASFILE:
  4236. //
  4237. // Handle the case where DocObject does not support "SaveAs"
  4238. // and we have enabled the menuitem anyway.
  4239. //
  4240. if (SHIsRestricted2W(_hwnd, REST_NoBrowserSaveAs, NULL, 0))
  4241. break;
  4242. if (_pmsot)
  4243. {
  4244. OLECMD rgcmds[] = { { OLECMDID_SAVEAS, 0 }, };
  4245. _pmsot->QueryStatus(NULL, ARRAYSIZE(rgcmds), rgcmds, NULL);
  4246. ASSERT(rgcmds[0].cmdf & OLECMDF_ENABLED);
  4247. if (!(rgcmds[0].cmdf & OLECMDF_ENABLED))
  4248. _OnSaveAs();
  4249. else
  4250. goto TryDocument;
  4251. }
  4252. break;
  4253. case DVIDM_IMPORTEXPORT:
  4254. _OnImportExport(_hwnd);
  4255. break;
  4256. case DVIDM_HELPIESEC:
  4257. _OnHelpGoto(IDS_HELPIESEC);
  4258. break;
  4259. case DVIDM_INTRANETSITES:
  4260. _OnAddToSitesList(_hwnd, URLZONE_INTRANET);
  4261. break;
  4262. case DVIDM_TRUSTEDSITES:
  4263. _OnAddToSitesList(_hwnd, URLZONE_TRUSTED);
  4264. break;
  4265. default:
  4266. if (IsInRange(id, DVIDM_HELPMSWEB, DVIDM_HELPMSWEBLAST))
  4267. {
  4268. if (id == FCIDM_HELPNETSCAPEUSERS)
  4269. SHHtmlHelpOnDemandWrap(_hwnd, TEXT("iexplore.chm > iedefault"), HH_DISPLAY_TOPIC, (DWORD_PTR) TEXT("lvg_nscp.htm"), ML_CROSSCODEPAGE);
  4270. else
  4271. _OnHelpGoto(IDS_HELPMSWEB + (id - DVIDM_HELPMSWEB));
  4272. }
  4273. else if (IsInRange(id, DVIDM_MSHTML_FIRST, DVIDM_MSHTML_LAST))
  4274. {
  4275. TraceMsg(DM_PREMERGEDMENU, "Processing merged menuitem %d", id - DVIDM_MSHTML_FIRST);
  4276. ASSERT(_pcmdMergedMenu);
  4277. if (_pcmdMergedMenu) {
  4278. HRESULT hresT=_pcmdMergedMenu->Exec(&CGID_MSHTML, id - DVIDM_MSHTML_FIRST, 0, NULL, NULL);
  4279. if (FAILED(hresT)) {
  4280. TraceMsg(DM_ERROR, "CDOH::_OnCommand _pcmdMergedMenu->Exec(%d) failed %x",
  4281. id - DVIDM_MSHTML_FIRST, hresT);
  4282. }
  4283. }
  4284. }
  4285. else if (IsInRange (id, DVIDM_MENUEXT_FIRST, DVIDM_MENUEXT_LAST))
  4286. {
  4287. // Menu Extensions
  4288. IUnknown_Exec(_pBrowsExt, &CLSID_ToolbarExtButtons, id, 0, NULL, NULL);
  4289. }
  4290. else
  4291. {
  4292. TryDocument:
  4293. if (_pmsot)
  4294. {
  4295. // Check if we need to call object's Exec.
  4296. UINT idMso = _MapToMso(id);
  4297. if (idMso != (UINT)-1)
  4298. {
  4299. // Yes. Call it.
  4300. _pmsot->Exec(NULL, idMso, OLECMDEXECOPT_PROMPTUSER, NULL, NULL);
  4301. }
  4302. else if (id == DVIDM_PRINTFRAME)
  4303. {
  4304. _pmsot->Exec(&CGID_ShellDocView, SHDVID_PRINTFRAME, OLECMDEXECOPT_PROMPTUSER, NULL, NULL);
  4305. }
  4306. }
  4307. }
  4308. break;
  4309. }
  4310. }
  4311. HRESULT CDocObjectHost::_OnSaveAs(void)
  4312. {
  4313. HRESULT hres = S_OK;
  4314. TraceMsg(DM_SAVEASHACK, "DOH::_OnSaveAs called");
  4315. ASSERT(_pole);
  4316. if (_dwAppHack & BROWSERFLAG_MSHTML)
  4317. {
  4318. SaveBrowserFile( _hwnd, _pole );
  4319. }
  4320. else // old dochost stuff
  4321. {
  4322. TCHAR szSaveTo[MAX_PATH]; // ok with MAX_PATH
  4323. MLLoadString(IDS_DOCUMENT, szSaveTo, ARRAYSIZE(szSaveTo));
  4324. TCHAR szDesktop[MAX_PATH];
  4325. SHGetSpecialFolderPath(_hwnd, szDesktop, CSIDL_DESKTOPDIRECTORY, FALSE);
  4326. OPENFILENAME OFN;
  4327. OFN.lStructSize = sizeof(OPENFILENAME);
  4328. OFN.hwndOwner = _hwnd;
  4329. OFN.lpstrFileTitle = 0;
  4330. OFN.nMaxCustFilter = 0;
  4331. OFN.nFilterIndex = 0;
  4332. OFN.nMaxFile = ARRAYSIZE(szSaveTo);
  4333. OFN.lpfnHook = DocHostSaveAsOFNHook;
  4334. OFN.Flags = 0L;/* for now, since there's no readonly support */
  4335. OFN.lpstrTitle = NULL;
  4336. OFN.lpstrInitialDir = szDesktop;
  4337. OFN.lpstrFile = szSaveTo;
  4338. OFN.Flags = OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT | OFN_ENABLEHOOK | OFN_EXPLORER |
  4339. OFN_NOREADONLYRETURN | OFN_PATHMUSTEXIST;
  4340. OFN.lpstrFilter = NULL;
  4341. OFN.lpstrCustomFilter = NULL;
  4342. OFN.lpstrDefExt = TEXT(""); // no extension
  4343. TCHAR szValue[MAX_PATH+1]; // +1 for for double-null
  4344. TCHAR szExt[40];
  4345. HKEY hkey = _GetUserCLSIDKey(_pole, NULL, NULL);
  4346. if (hkey)
  4347. {
  4348. LONG cb = SIZEOF(szValue);
  4349. if (RegQueryValue(hkey, TEXT("DefaultExtension"), szValue, &cb) == ERROR_SUCCESS)
  4350. {
  4351. TraceMsg(DM_SAVEASHACK, "DOH::_OnSaveAs DefExt is %s", szValue);
  4352. // It is suposed to be like ".xls, Excel Workbook (*.xls)"
  4353. if (szValue[0]==TEXT('.')) {
  4354. StrCpyN(szExt, szValue+1, ARRAYSIZE(szExt));
  4355. LPTSTR pszEnd = StrChr(szExt, TEXT(','));
  4356. if (pszEnd) {
  4357. *pszEnd = 0;
  4358. }
  4359. OFN.lpstrDefExt = szExt;
  4360. OFN.lpstrFilter = szValue;
  4361. OFN.Flags &= ~OFN_ENABLEHOOK;
  4362. TraceMsg(DM_SAVEASHACK, "DOH::_OnSaveAs OFN.lpstrDefExt is %s", OFN.lpstrDefExt);
  4363. }
  4364. }
  4365. RegCloseKey(hkey);
  4366. }
  4367. if (GetSaveFileName(&OFN))
  4368. {
  4369. IPersistFile* ppf;
  4370. ASSERT(_pole);
  4371. hres = _pole->QueryInterface(IID_IPersistFile, (void **)&ppf);
  4372. if (SUCCEEDED(hres))
  4373. {
  4374. TraceMsg(DM_APPHACK, "APPHACK DOH SaveAs'ing to %s", szSaveTo);
  4375. hres = ppf->Save(szSaveTo, FALSE);
  4376. ppf->Release();
  4377. }
  4378. else
  4379. {
  4380. ASSERT(0);
  4381. }
  4382. }
  4383. else
  4384. {
  4385. hres = S_FALSE;
  4386. }
  4387. }
  4388. return hres;
  4389. }
  4390. #ifndef POSTPOSTSPLIT
  4391. HRESULT DropOnMailRecipient(IDataObject *pdtobj, DWORD grfKeyState)
  4392. {
  4393. IDropTarget *pdrop;
  4394. HRESULT hres = CoCreateInstance(CLSID_MailRecipient,
  4395. NULL, CLSCTX_INPROC_SERVER | CLSCTX_LOCAL_SERVER,
  4396. IID_IDropTarget, (void**)&pdrop);
  4397. if (SUCCEEDED(hres))
  4398. {
  4399. hres = SimulateDrop(pdrop, pdtobj, grfKeyState, NULL, NULL);
  4400. pdrop->Release();
  4401. }
  4402. return hres;
  4403. }
  4404. #endif // POSTPOSTSPLIT
  4405. void _EnableRemoveMenuItem(HMENU hmenu, DWORD cmdf, UINT uCmd)
  4406. {
  4407. if (!(cmdf & (OLECMDF_SUPPORTED | OLECMDF_ENABLED)))
  4408. RemoveMenu(hmenu, uCmd, MF_BYCOMMAND);
  4409. else
  4410. _EnableMenuItem(hmenu, uCmd,
  4411. cmdf & OLECMDF_ENABLED);
  4412. }
  4413. void CDocObjectHost::_OnInitMenuPopup(HMENU hmInit, int nIndex, BOOL fSystemMenu)
  4414. {
  4415. if (!_hmenuCur)
  4416. return;
  4417. DEBUG_CODE( _DumpMenus(TEXT("on _OnInitMenuPopup"), TRUE); )
  4418. if (GetMenuFromID(_hmenuCur, FCIDM_MENU_VIEW) == hmInit) {
  4419. OLECMD rgcmd1[] = {
  4420. { IDM_SCRIPTDEBUGGER, 0 },
  4421. };
  4422. DeleteMenu (hmInit, DVIDM_MSHTML_FIRST+IDM_SCRIPTDEBUGGER, MF_BYCOMMAND);
  4423. if (SUCCEEDED(QueryStatusDown(&CGID_MSHTML, ARRAYSIZE(rgcmd1), rgcmd1, NULL)) && (rgcmd1[0].cmdf & OLECMDF_ENABLED)) {
  4424. //
  4425. // We need the script debugger popup menu. We should check to see if this
  4426. // needs to be loaded.
  4427. //
  4428. HMENU hMenuDebugger;
  4429. MENUITEMINFO mii;
  4430. const UINT cchBuf = 128;
  4431. TCHAR szItem[cchBuf];
  4432. hMenuDebugger = LoadMenu(MLGetHinst(), MAKEINTRESOURCE(MENU_SCRDEBUG));
  4433. mii.fMask = MIIM_SUBMENU | MIIM_TYPE | MIIM_ID;
  4434. mii.fType = MFT_STRING;
  4435. mii.cch = cchBuf;
  4436. mii.dwTypeData = szItem;
  4437. mii.cbSize = sizeof(mii);
  4438. GetMenuItemInfo(hMenuDebugger, 0, TRUE, &mii);
  4439. mii.fMask |= MIIM_STATE;
  4440. mii.fState = MFS_ENABLED;
  4441. InsertMenuItem(hmInit, FCIDM_THEATER, FALSE, &mii);
  4442. OLECMD rgcmd[] = {
  4443. { IDM_BREAKATNEXT, 0 },
  4444. { IDM_LAUNCHDEBUGGER, 0 },
  4445. };
  4446. HRESULT hr = QueryStatusDown(&CGID_MSHTML, ARRAYSIZE(rgcmd), rgcmd, NULL);
  4447. _EnableMenuItem(mii.hSubMenu, DVIDM_MSHTML_FIRST+rgcmd[0].cmdID, SUCCEEDED(hr) && (rgcmd[0].cmdf & OLECMDF_ENABLED));
  4448. _EnableMenuItem(mii.hSubMenu, DVIDM_MSHTML_FIRST+rgcmd[1].cmdID, SUCCEEDED(hr) && (rgcmd[1].cmdf & OLECMDF_ENABLED));
  4449. }
  4450. if (_pmsot)
  4451. {
  4452. OLECMD rgcmd2[] = {
  4453. { IDM_VIEWSOURCE, 0 },
  4454. };
  4455. if (SHRestricted2(REST_NoViewSource, NULL, 0) == 0)
  4456. {
  4457. // we only want to modify the state of the view source item
  4458. // if it isn't restricted by the IEAK. if it's restricted, we
  4459. // need to leave it disabled regardles of what the object
  4460. // we're hosting says
  4461. HRESULT hr = _pmsot->QueryStatus(&CGID_MSHTML, ARRAYSIZE(rgcmd2), rgcmd2, NULL);
  4462. _EnableMenuItem(hmInit, DVIDM_MSHTML_FIRST + rgcmd2[0].cmdID,
  4463. SUCCEEDED(hr) && (rgcmd2[0].cmdf & OLECMDF_ENABLED));
  4464. }
  4465. }
  4466. }
  4467. else if (GetMenuFromID(_hmenuCur, FCIDM_MENU_FILE) == hmInit)
  4468. {
  4469. if (_pmsot)
  4470. {
  4471. TraceMsg(0, "sdv TR _OnInitMenuPopup : step 5");
  4472. OLECMD rgcmds[] = {
  4473. { OLECMDID_PRINT, 0 },
  4474. { OLECMDID_PAGESETUP, 0 },
  4475. { OLECMDID_PROPERTIES, 0 },
  4476. { OLECMDID_SAVE, 0 },
  4477. { OLECMDID_SAVEAS, 0 },
  4478. { OLECMDID_PRINTPREVIEW, 0 },
  4479. };
  4480. _pmsot->QueryStatus(NULL, ARRAYSIZE(rgcmds), rgcmds, NULL);
  4481. // Adding a comment for my sanity: we use SHDVID_PRINTFRAME instead
  4482. // of OLECMDID_PRINT because IE40 is going to support the printing
  4483. // of entire framesets, instead of the current behavior or forwarding
  4484. // the command to the active frame.
  4485. //
  4486. OLECMD rgcmds1[] = {
  4487. { SHDVID_PRINTFRAME, 0 },
  4488. };
  4489. _pmsot->QueryStatus(&CGID_ShellDocView, ARRAYSIZE(rgcmds1), rgcmds1, NULL);
  4490. //
  4491. // If OLECMDID_SAVEAS is not supported (neither ENABLED nor
  4492. // SUPPORTED is set) by the DocObject, check if the object
  4493. // support IPersistFile. If it does, enable it. Note that
  4494. // this mechanism allows the DocObject to disable this menu
  4495. // item (by setting only OLECMDF_SUPPORTED). (SatoNa)
  4496. //
  4497. ASSERT(rgcmds[4].cmdID == OLECMDID_SAVEAS);
  4498. // Only apply the save as restriction to the browser. If it is the
  4499. // browser, and save as is restricted, then make the item disappear.
  4500. if ( (_dwAppHack & BROWSERFLAG_MSHTML) &&
  4501. SHRestricted2( REST_NoBrowserSaveAs, NULL, 0 ))
  4502. rgcmds[4].cmdf &= ~(OLECMDF_ENABLED | OLECMDF_SUPPORTED);
  4503. else if (!(rgcmds[4].cmdf & (OLECMDF_ENABLED | OLECMDF_SUPPORTED)))
  4504. {
  4505. IPersistFile* ppf;
  4506. ASSERT(_pole);
  4507. HRESULT hresT = _pole->QueryInterface(IID_IPersistFile, (void **)&ppf);
  4508. if (SUCCEEDED(hresT))
  4509. {
  4510. TraceMsg(DM_APPHACK, "APPHACK DOH Enabling SaveAs menu for Excel95");
  4511. rgcmds[4].cmdf |= OLECMDF_ENABLED;
  4512. ppf->Release();
  4513. }
  4514. }
  4515. if (SHRestricted2(REST_NoPrinting, NULL, 0))
  4516. {
  4517. rgcmds[0].cmdf &= ~(OLECMDF_ENABLED | OLECMDF_SUPPORTED); // print
  4518. rgcmds[1].cmdf &= ~(OLECMDF_ENABLED | OLECMDF_SUPPORTED); // page setup
  4519. rgcmds[5].cmdf &= ~(OLECMDF_ENABLED | OLECMDF_SUPPORTED); // print preview
  4520. }
  4521. //
  4522. // APPHACK: Office apps do not enable "Save" correctly.
  4523. // Automatically enable it if the moniker is a FILE moniker
  4524. // AND the document has been altered by the user.
  4525. //
  4526. if (_fFileProtocol && _IsDirty(NULL))
  4527. {
  4528. if (!(rgcmds[3].cmdf & OLECMDF_ENABLED))
  4529. {
  4530. TraceMsg(DM_APPHACK, "APPHACK DOH Enabling Save for Office Apps");
  4531. }
  4532. rgcmds[3].cmdf |= OLECMDF_ENABLED;
  4533. }
  4534. // Remove/disable/enable the "Print" command as appropriate.
  4535. // Excel doesn't set SUPPORTED bit when it sets ENABLED bit
  4536. // so we have to check both bits.
  4537. _EnableRemoveMenuItem(hmInit, rgcmds[0].cmdf, DVIDM_PRINT);
  4538. _EnableMenuItem(hmInit, DVIDM_PAGESETUP,
  4539. (rgcmds[1].cmdf & OLECMDF_ENABLED));
  4540. _EnableMenuItem(hmInit, DVIDM_PROPERTIES,
  4541. (rgcmds[2].cmdf & OLECMDF_ENABLED));
  4542. _EnableRemoveMenuItem(hmInit, rgcmds[3].cmdf, DVIDM_SAVE);
  4543. _EnableRemoveMenuItem(hmInit, rgcmds[4].cmdf, DVIDM_SAVEASFILE);
  4544. _EnableRemoveMenuItem(hmInit, rgcmds[5].cmdf, DVIDM_PRINTPREVIEW);
  4545. _EnableRemoveMenuItem(hmInit, rgcmds1[0].cmdf, DVIDM_PRINTFRAME);
  4546. HMENU hmFileNew = SHGetMenuFromID(hmInit, DVIDM_NEW);
  4547. if (hmFileNew)
  4548. {
  4549. const static struct {
  4550. LPCTSTR pszClient;
  4551. UINT idCmd;
  4552. } s_Clients[] = {
  4553. { NEW_MAIL_DEF_KEY, DVIDM_NEWMESSAGE },
  4554. { NEW_CONTACTS_DEF_KEY, DVIDM_NEWCONTACT },
  4555. { NEW_NEWS_DEF_KEY, DVIDM_NEWPOST },
  4556. { NEW_APPOINTMENT_DEF_KEY, DVIDM_NEWAPPOINTMENT },
  4557. { NEW_MEETING_DEF_KEY, DVIDM_NEWMEETING },
  4558. { NEW_TASK_DEF_KEY, DVIDM_NEWTASK },
  4559. { NEW_TASKREQUEST_DEF_KEY, DVIDM_NEWTASKREQUEST },
  4560. { NEW_JOURNAL_DEF_KEY, DVIDM_NEWJOURNAL },
  4561. { NEW_NOTE_DEF_KEY, DVIDM_NEWNOTE },
  4562. { NEW_CALL_DEF_KEY, DVIDM_CALL }
  4563. };
  4564. BOOL bItemRemoved = FALSE;
  4565. for (int i = 0; i < ARRAYSIZE(s_Clients); i++)
  4566. {
  4567. if (!SHIsRegisteredClient(s_Clients[i].pszClient))
  4568. {
  4569. if (RemoveMenu(hmFileNew, s_Clients[i].idCmd, MF_BYCOMMAND))
  4570. bItemRemoved = TRUE;
  4571. }
  4572. }
  4573. // Menu item "File/New/Window Ctrl+N" needs to be disabled if the restriction is set
  4574. if( SHRestricted2W(REST_NoOpeninNewWnd, NULL, 0))
  4575. {
  4576. EnableMenuItem(hmFileNew, DVIDM_NEWWINDOW, MF_BYCOMMAND | MF_GRAYED);
  4577. }
  4578. if (bItemRemoved) // ensure the last item is not a separator
  4579. _SHPrettyMenu(hmFileNew);
  4580. }
  4581. }
  4582. }
  4583. else if (GetMenuFromID(_hmenuCur, FCIDM_VIEWFONTS) == hmInit
  4584. || GetMenuFromID(_hmenuCur, FCIDM_ENCODING) == hmInit)
  4585. {
  4586. if (_pmsot)
  4587. {
  4588. // Handling fonts popup in view menu
  4589. OLECMD rgcmd[] = {
  4590. { SHDVID_GETFONTMENU, 0 },
  4591. { SHDVID_GETMIMECSETMENU, 0 },
  4592. };
  4593. _pmsot->QueryStatus(&CGID_ShellDocView, ARRAYSIZE(rgcmd), rgcmd, NULL);
  4594. int idx = (GetMenuFromID(_hmenuCur, FCIDM_VIEWFONTS) == hmInit ? 0 : 1);
  4595. if (rgcmd[idx].cmdf & OLECMDF_ENABLED)
  4596. {
  4597. VARIANTARG v = {0};
  4598. HRESULT hr;
  4599. hr = _pmsot->Exec(&CGID_ShellDocView, rgcmd[idx].cmdID, 0, NULL, &v);
  4600. if (S_OK == hr)
  4601. {
  4602. // (on NT/Unix) DestroyMenu(hmInit) shouldn't work, because
  4603. // we're inside the processing of WM_INITMENUPOPUP message
  4604. // for hmInit. DestroyMenu will make the hmInit handle
  4605. // invalid.
  4606. //
  4607. // Instead of that we'll empty hmInit and copy hmenuFonts
  4608. // over. hmenuFonts will be destroyed to prevent the
  4609. // memory leak.
  4610. //
  4611. //
  4612. MENUITEMINFO mii;
  4613. UINT uItem = 0;
  4614. //$ WIN64: mshtml\src\site\base\formmso.cxx needs to return VT_INT_PTR instead
  4615. // HMENU hmenuFonts = (HMENU)v.byref;
  4616. HMENU hmenuFonts = (HMENU)LongToHandle(v.lVal);
  4617. // deleting menu while processing WM_INITMENUPOPUP
  4618. // can cause assertion failure on NT. However, copying
  4619. // submenu using InsertMenuItem() doesn't work on Win9x.
  4620. // see the comments above and Menu_Replace() in menu.cpp
  4621. //
  4622. if (!g_fRunningOnNT)
  4623. DestroyMenu(hmInit);
  4624. mii.cbSize = sizeof(mii);
  4625. mii.fMask = MIIM_ID|MIIM_SUBMENU;
  4626. while (GetMenuItemInfo(hmenuFonts, uItem, TRUE, &mii))
  4627. {
  4628. if (idx == 1 && mii.hSubMenu != NULL)
  4629. {
  4630. UINT uItemSub = 0;
  4631. HMENU hMenuSub = mii.hSubMenu;
  4632. while (GetMenuItemInfo(hMenuSub, uItemSub, TRUE, &mii))
  4633. {
  4634. mii.wID += DVIDM_MSHTML_FIRST;
  4635. SetMenuItemInfo(hMenuSub, uItemSub++, TRUE, &mii);
  4636. }
  4637. }
  4638. else
  4639. {
  4640. mii.wID += DVIDM_MSHTML_FIRST;
  4641. SetMenuItemInfo(hmenuFonts, uItem, TRUE, &mii);
  4642. }
  4643. uItem++;
  4644. }
  4645. if (!g_fRunningOnNT)
  4646. {
  4647. mii.cbSize = sizeof(mii);
  4648. mii.fMask = MIIM_SUBMENU;
  4649. mii.hSubMenu = hmenuFonts;
  4650. SetMenuItemInfo(_hmenuCur,
  4651. (idx == 0 ? FCIDM_VIEWFONTS:FCIDM_ENCODING),
  4652. FALSE, &mii);
  4653. }
  4654. else
  4655. {
  4656. Menu_Replace(hmInit, hmenuFonts);
  4657. DestroyMenu(hmenuFonts);
  4658. }
  4659. }
  4660. }
  4661. }
  4662. }
  4663. else if (GetMenuFromID(_hmenuCur, FCIDM_MENU_TOOLS) == hmInit ||
  4664. GetMenuFromID(_hmenuCur, FCIDM_MENU_HELP) == hmInit)
  4665. {
  4666. // Add Tools and help Menu Extensions
  4667. if (_pBrowsExt)
  4668. {
  4669. _pBrowsExt->OnCustomizableMenuPopup(_hmenuCur, hmInit);
  4670. }
  4671. }
  4672. }
  4673. //
  4674. // ATTEMPT: Handling WM_SETFOCUS message here caused several problems
  4675. // under IE 3.0. Since we can't find any code scenario that requires
  4676. // this code, I'm yanking out. If might introduce a new bug, but dealing
  4677. // with those bugs is probably better than dealing with this code.
  4678. // (SatoNa)
  4679. //
  4680. /*----------------------------------------------------------
  4681. Purpose: Determines if this message should be forwarded onto
  4682. the object.
  4683. Returns: TRUE if the message needs to be forwarded
  4684. */
  4685. BOOL CDocObjectHost::_ShouldForwardMenu(UINT uMsg, WPARAM wParam, LPARAM lParam)
  4686. {
  4687. switch (uMsg)
  4688. {
  4689. case WM_MENUSELECT:
  4690. {
  4691. // In USER menu bars, the first menuselect will be sent for the
  4692. // selected top-level menu item, in which case hmenu == _hmenuCur.
  4693. // We expect menubands to behave similarly.
  4694. //
  4695. // We check that hmenu == _hmenuCur because we only keep a list
  4696. // of the top-level popup menus. We don't keep track of any
  4697. // cascading submenus. We should only need to check who owns
  4698. // the menu at the initial popup, all subsequent messages for
  4699. // that menu should go to the same destination (frame or object).
  4700. //
  4701. // The same goes for CShellBrowser::_ShouldForwardMenu().
  4702. //
  4703. HMENU hmenu = GET_WM_MENUSELECT_HMENU(wParam, lParam);
  4704. if (hmenu && (MF_POPUP & GET_WM_MENUSELECT_FLAGS(wParam, lParam)))
  4705. {
  4706. HMENU hmenuSub = GetSubMenu(hmenu, GET_WM_MENUSELECT_CMD(wParam, lParam));
  4707. if (hmenu == _hmenuCur)
  4708. {
  4709. // Normal case, where we just look at the topmost popdown menus
  4710. _fForwardMenu = _menulist.IsObjectMenu(hmenuSub);
  4711. }
  4712. else if (_menulist.IsObjectMenu(hmenuSub))
  4713. {
  4714. // This happens if the cascading submenu (micro-merged help menu for
  4715. // example) should be forwarded on, but the parent menu should
  4716. // not.
  4717. _fForwardMenu = TRUE;
  4718. }
  4719. else if (GetMenuFromID(_hmenuCur, FCIDM_MENU_HELP) == hmenu
  4720. && !_menulist.IsObjectMenu(hmenu) )
  4721. {
  4722. // 80430 Appcompat: notice that our menu fowarding doesn't work for the
  4723. // micro-merged Help menu. If the user previously selected the merged
  4724. // submenu, and we end up here, it means a non-merged submenu was just
  4725. // selected and our _fForwardMenu was still set to TRUE. If we don't
  4726. // reset it, the next WM_INITMENUPOPUP gets forwarded, which crashes Visio.
  4727. //
  4728. // We know that a submenu of the Help menu has just popped up, and we know
  4729. // the submenu belongs to us. So don't forward to the docobj until the
  4730. // next popup.
  4731. _fForwardMenu = FALSE;
  4732. }
  4733. }
  4734. break;
  4735. }
  4736. case WM_COMMAND:
  4737. if (_fForwardMenu)
  4738. {
  4739. // Stop forwarding menu messages after WM_COMMAND
  4740. _fForwardMenu = FALSE;
  4741. // If it wasn't from an accelerator, forward it
  4742. if (0 == GET_WM_COMMAND_CMD(wParam, lParam))
  4743. return TRUE;
  4744. }
  4745. break;
  4746. }
  4747. return _fForwardMenu;
  4748. }
  4749. /*----------------------------------------------------------
  4750. Purpose: Forwards messages to the in-place object.
  4751. This is used to forward menu messages to the object for
  4752. menu bands, since the menu bands do not work with the
  4753. standard OLE FrameFilterWndProc.
  4754. Also, the help menu is sometimes a combination of the
  4755. object and the frame. This function will forward as
  4756. appropriate.
  4757. */
  4758. LRESULT CDocObjectHost::_ForwardObjectMsg(UINT uMsg, WPARAM wParam, LPARAM lParam)
  4759. {
  4760. LRESULT lRet = 0L;
  4761. IOleInPlaceActiveObject *piact = _xao.GetObject();
  4762. ASSERT(IS_VALID_CODE_PTR(piact, IOleInPlaceActiveObject));
  4763. if (piact)
  4764. {
  4765. HWND hwnd;
  4766. piact->GetWindow(&hwnd);
  4767. ASSERT(IS_VALID_HANDLE(hwnd, WND));
  4768. if (hwnd)
  4769. {
  4770. if (uMsg == WM_COMMAND)
  4771. PostMessage(hwnd, uMsg, wParam, lParam);
  4772. else
  4773. lRet = SendMessage(hwnd, uMsg, wParam, lParam);
  4774. }
  4775. }
  4776. return lRet;
  4777. }
  4778. void CDocObjectHost::_OnMenuSelect(UINT id, UINT mf, HMENU hmenu)
  4779. {
  4780. if (_psb)
  4781. {
  4782. if (IsInRange(id, DVIDM_MSHTML_FIRST, DVIDM_MSHTML_LAST))
  4783. {
  4784. if (_pcmdMergedMenu) {
  4785. OLECMD rgcmd = { id - DVIDM_MSHTML_FIRST, 0 };
  4786. struct {
  4787. OLECMDTEXT cmdtxt;
  4788. WCHAR szExtra[MAX_PATH];
  4789. } cmdt;
  4790. cmdt.cmdtxt.cmdtextf = OLECMDTEXTF_STATUS;
  4791. cmdt.cmdtxt.cwActual = 0;
  4792. cmdt.cmdtxt.cwBuf = MAX_PATH;
  4793. cmdt.cmdtxt.rgwz[0] = 0;
  4794. HRESULT hresT=_pcmdMergedMenu->QueryStatus(&CGID_MSHTML, 1, &rgcmd, &cmdt.cmdtxt);
  4795. if (SUCCEEDED(hresT) && cmdt.cmdtxt.rgwz[0]) {
  4796. _psb->SetStatusTextSB(cmdt.cmdtxt.rgwz);
  4797. } else {
  4798. TraceMsg(DM_ERROR, "CDOH::_OnMenuSelect QueryStatus failed %x %d",
  4799. hresT, cmdt.cmdtxt.cwActual);
  4800. }
  4801. }
  4802. else
  4803. // An ASSERT was replaced with this TraceMsg to allow testing on Win9x.
  4804. // 70240 which reported the assert was pushed to IE6.
  4805. TraceMsg(TF_WARNING, "CDocObjectHost::_OnMenuSelect _pcmdMergedMenu == NULL");
  4806. }
  4807. else if (IsInRange(id, DVIDM_MENUEXT_FIRST, DVIDM_MENUEXT_LAST))
  4808. {
  4809. // Menu Extensions go here
  4810. if (_pBrowsExt)
  4811. {
  4812. _pBrowsExt->OnMenuSelect(id);
  4813. }
  4814. }
  4815. else
  4816. {
  4817. WCHAR wszT[MAX_STATUS_SIZE];
  4818. if (MLLoadStringW(IDS_HELP_OF(id), wszT, ARRAYSIZE(wszT)))
  4819. {
  4820. _psb->SetStatusTextSB(wszT);
  4821. }
  4822. }
  4823. }
  4824. }
  4825. LRESULT CDocObjectHost::v_WndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
  4826. {
  4827. LRESULT lRet = 0L;
  4828. switch(uMsg)
  4829. {
  4830. case WM_TIMER:
  4831. if (wParam == IDTIMER_PROGRESS)
  4832. {
  4833. _OnSetProgressPos(0, PROGRESS_TICK);
  4834. break;
  4835. }
  4836. else if (wParam == IDTIMER_PROGRESSFULL)
  4837. {
  4838. _OnSetProgressPos(-2, PROGRESS_RESET);
  4839. break;
  4840. }
  4841. else
  4842. {
  4843. #ifdef TEST_DELAYED_SHOWMSOVIEW
  4844. MessageBeep(0);
  4845. KillTimer(_hwnd, 100);
  4846. ActivateMe(NULL);
  4847. break;
  4848. #else
  4849. ASSERT(FALSE);
  4850. break;
  4851. #endif // TEST_DELAYED_SHOWMSOVIEW
  4852. }
  4853. /* WM_PICS_ASYNCCOMPLETE is posted by the async thread fetching ratings
  4854. * from label bureaus, etc.
  4855. */
  4856. case WM_PICS_ASYNCCOMPLETE:
  4857. {
  4858. TraceMsg(DM_PICS, "CDOH::v_WndProc got WM_PICS_ASYNCCOMPLETE");
  4859. PicsQuery pq;
  4860. HRESULT hr;
  4861. LPVOID lpvRatingDetails;
  4862. DWORD dwSerialComplete = (DWORD)lParam;
  4863. CPicsProcessor * pPicsProc = NULL;
  4864. if (::_GetPicsQuery(dwSerialComplete, &pq)) {
  4865. ::_RemovePicsQuery(dwSerialComplete);
  4866. hr = (HRESULT)wParam;
  4867. lpvRatingDetails = pq.lpvRatingDetails;
  4868. }
  4869. else {
  4870. hr = E_FAIL;
  4871. lpvRatingDetails = NULL;
  4872. }
  4873. pPicsProc = _GetPicsProcessorFromSerialNumber(dwSerialComplete);
  4874. if (pPicsProc)
  4875. {
  4876. pPicsProc->_GotLabel(hr, lpvRatingDetails, PICS_WAIT_FOR_ASYNC);
  4877. }
  4878. else
  4879. {
  4880. TraceMsg( DM_PICS, "CDOH::v_WndProc no PicsProc for ASYNCCOMPLETE %x", dwSerialComplete);
  4881. if ( lpvRatingDetails )
  4882. {
  4883. ::RatingFreeDetails(lpvRatingDetails);
  4884. lpvRatingDetails = NULL;
  4885. }
  4886. }
  4887. break;
  4888. }
  4889. case WM_PICS_ROOTDOWNLOADCOMPLETE:
  4890. {
  4891. TraceMsg(DM_PICS, "CDOH::v_WndProc got WM_PICS_ROOTDOWNLOADCOMPLETE %x", lParam);
  4892. if (_PicsProcBase._pRootDownload != NULL)
  4893. {
  4894. _PicsProcBase._pRootDownload->CleanUp();
  4895. ATOMICRELEASET(_PicsProcBase._pRootDownload,CPicsRootDownload);
  4896. }
  4897. break;
  4898. }
  4899. /* WM_PICS_ALLCHECKSCOMPLETE is posted when we finally want to either
  4900. * cancel the navigation or go through with it, according to ratings
  4901. * checks. Posting a message allows all denial blocking message loops
  4902. * to unwind before we cancel navigation, which could otherwise delete
  4903. * objects that still have functions operating on them.
  4904. */
  4905. case WM_PICS_ALLCHECKSCOMPLETE:
  4906. TraceMsg(DM_PICS, "CDOH::v_WndProc got WM_PICS_ALLCHECKSCOMPLETE, lParam=%x", lParam);
  4907. if (lParam == IDOK) {
  4908. if (!_fSetTarget)
  4909. {
  4910. TraceMsg(DM_PICS, "CDOH::v_WndProc(WM_PICS_ASYNCCOMPLETE) execing SHDVID_ACTIVATEMENOW");
  4911. _pmsoctBrowser->Exec(&CGID_ShellDocView, SHDVID_ACTIVATEMENOW, NULL, NULL, NULL);
  4912. }
  4913. else {
  4914. TraceMsg(DM_PICS, "CDOH::v_WndProc(WM_PICS_ASYNCCOMPLETE) not execing SHDVID_ACTIVATEMENOW");
  4915. }
  4916. }
  4917. else {
  4918. ASSERT(!_fSetTarget);
  4919. TraceMsg(DM_PICS, "CDOH::v_WndProc(WM_PICS_ASYNCCOMPLETE) calling _CancelPendingNavigation");
  4920. _CancelPendingNavigation(FALSE);
  4921. // _pmsoctBrowser->Exec(NULL, OLECMDID_STOP, NULL, NULL, NULL);
  4922. }
  4923. break;
  4924. /* WM_PICS_DOBLOCKINGUI is posted when we decide we need to put up
  4925. * denial UI. Posting a message allows download of this object and
  4926. * other frames to continue while we post the UI, which in turn allows
  4927. * any denials from other frames to be coalesced into the one dialog.
  4928. */
  4929. case WM_PICS_DOBLOCKINGUI:
  4930. {
  4931. TraceMsg(DM_PICS, "CDOH::v_WndProc got WM_PICS_DOBLOCKINGUI %x", lParam);
  4932. CPicsProcessor * pPicsProc = _GetPicsProcessorFromKey(lParam);
  4933. if (pPicsProc)
  4934. {
  4935. UINT id = pPicsProc->_PicsBlockingDialog();
  4936. if (pPicsProc->_pPrivWindow)
  4937. {
  4938. ASSERT( _fDocCanNavigate );
  4939. TraceMsg(DM_PICS, "CDOH::v_WndProc(WM_PICS_DOBLOCKINGUI) posting WM_PICS_RESULTTOPRIVWIN");
  4940. if (!PostMessage( _hwnd, WM_PICS_RESULTTOPRIVWIN, id, lParam))
  4941. {
  4942. TraceMsg(DM_PICS, "CDOH::v_WndProc(WM_PICS_DOBLOCKINGUI) couldn't post message!");
  4943. }
  4944. }
  4945. else
  4946. {
  4947. TraceMsg(DM_PICS, "CDOH::v_WndProc(WM_PICS_DOBLOCKINGUI) posting WM_PICS_ALLCHECKSCOMPLETE");
  4948. if (!PostMessage(_hwnd, WM_PICS_ALLCHECKSCOMPLETE, 0, id))
  4949. {
  4950. TraceMsg(DM_PICS, "CDOH::v_WndProc(WM_PICS_DOBLOCKINGUI) couldn't post message!");
  4951. }
  4952. }
  4953. // We may have been terminated while the
  4954. // dialog was up -- finish cleaning up here.
  4955. if ( !pPicsProc->_fInDialog
  4956. && pPicsProc->_fTerminated
  4957. && pPicsProc != &_PicsProcBase)
  4958. {
  4959. delete pPicsProc;
  4960. }
  4961. }
  4962. else
  4963. {
  4964. TraceMsg( DM_PICS, "CDOH::v_WndProc no PicsProc for DOBLOCKINGUI");
  4965. }
  4966. }
  4967. break;
  4968. case WM_PICS_RESULTTOPRIVWIN:
  4969. {
  4970. ASSERT( _fDocCanNavigate );
  4971. TraceMsg(DM_PICS, "CDOH::v_WndProc got WM_PICS_RESULTTOPRIVWIN %x", lParam);
  4972. CPicsProcessor * pPicsProc = _GetPicsProcessorFromKey(lParam);
  4973. if (pPicsProc)
  4974. {
  4975. ASSERT( pPicsProc->_pPrivWindow );
  4976. IHTMLPrivateWindow * pPrivWindow = pPicsProc->_pPrivWindow;
  4977. pPrivWindow->AddRef();
  4978. if (pPicsProc->_pRootDownload != NULL)
  4979. {
  4980. pPicsProc->_pRootDownload->CleanUp();
  4981. ATOMICRELEASET(pPicsProc->_pRootDownload,CPicsRootDownload);
  4982. }
  4983. // Remove ourselves from the list
  4984. _RemovePicsProcessorByKey( lParam );
  4985. // Make Trident let go of our command target
  4986. pPrivWindow->SetPICSTarget(NULL);
  4987. // Tell the window the answer
  4988. pPrivWindow->PICSComplete( wParam == IDOK );
  4989. pPrivWindow->Release();
  4990. }
  4991. else
  4992. {
  4993. TraceMsg( DM_PICS, "CDOH::v_WndProc no PicsProc for WM_PICS_RESULTTOPRIVWIN");
  4994. }
  4995. }
  4996. break;
  4997. case WM_LBUTTONDOWN:
  4998. case WM_RBUTTONDOWN:
  4999. MessageBeep(0);
  5000. break;
  5001. case WM_MENUSELECT:
  5002. if (_ShouldForwardMenu(uMsg, wParam, lParam))
  5003. lRet = _ForwardObjectMsg(uMsg, wParam, lParam);
  5004. else
  5005. {
  5006. UINT uMenuFlags = GET_WM_MENUSELECT_FLAGS(wParam, lParam);
  5007. WORD wID = GET_WM_MENUSELECT_CMD(wParam, lParam);
  5008. HMENU hMenu = GET_WM_MENUSELECT_HMENU(wParam, lParam);
  5009. // Check for popup menus so we can display help strings for them
  5010. if (uMenuFlags & MF_POPUP)
  5011. {
  5012. MENUITEMINFO miiSubMenu;
  5013. miiSubMenu.cbSize = SIZEOF(MENUITEMINFO);
  5014. miiSubMenu.fMask = MIIM_SUBMENU|MIIM_ID;
  5015. if (GetMenuItemInfoWrap(hMenu, wID, TRUE, &miiSubMenu))
  5016. {
  5017. // Change the parameters to simulate a "normal" menu item
  5018. wID = (WORD)miiSubMenu.wID;
  5019. }
  5020. }
  5021. _OnMenuSelect(wID, uMenuFlags, hMenu);
  5022. }
  5023. break;
  5024. case WM_INITMENUPOPUP:
  5025. if (_ShouldForwardMenu(uMsg, wParam, lParam))
  5026. lRet = _ForwardObjectMsg(uMsg, wParam, lParam);
  5027. else
  5028. _OnInitMenuPopup((HMENU)wParam, LOWORD(lParam), HIWORD(lParam));
  5029. break;
  5030. case WM_DRAWITEM:
  5031. case WM_MEASUREITEM:
  5032. if (_ShouldForwardMenu(uMsg, wParam, lParam))
  5033. lRet = _ForwardObjectMsg(uMsg, wParam, lParam);
  5034. else
  5035. goto DoDefault;
  5036. break;
  5037. case WM_NOTIFY:
  5038. _OnNotify((LPNMHDR)lParam);
  5039. break;
  5040. case WM_COMMAND:
  5041. _OnCommand(HIWORD(wParam), LOWORD(wParam), (HWND)lParam);
  5042. break;
  5043. case WM_SIZE:
  5044. if (_pmsov)
  5045. {
  5046. RECT rcClient;
  5047. GetClientRect(_hwnd, &rcClient);
  5048. //
  5049. // We should call ResizeBorder only if the browser is
  5050. // not an IOleInPlaceUIWindow.
  5051. //
  5052. if (_pipu==NULL)
  5053. {
  5054. TraceMsg(TF_SHDUIACTIVATE, "DOH::WM_SIZE calling _piact->ResizeBorder");
  5055. _xao.ResizeBorder(&rcClient, &_dof, TRUE);
  5056. }
  5057. _rcView.left = _bwTools.left;
  5058. _rcView.top = _bwTools.top;
  5059. _rcView.right = rcClient.right - _bwTools.right;
  5060. _rcView.bottom = rcClient.bottom - _bwTools.bottom;
  5061. TraceMsg(TF_SHDUIACTIVATE, "DOH::WM_SIZE calling SetRect (%d, %d, %d, %d)", _rcView.left, _rcView.top, _rcView.right, _rcView.bottom);
  5062. _pmsov->SetRect(&_rcView);
  5063. }
  5064. _PlaceProgressBar(TRUE);
  5065. break;
  5066. //
  5067. // ATTEMPT: Handling WM_SETFOCUS message here caused several problems
  5068. // under IE 3.0. Since we can't find any code scenario that requires
  5069. // this code, I'm yanking out. If might introduce a new bug, but dealing
  5070. // with those bugs is probably better than dealing with this code.
  5071. // (SatoNa)
  5072. //
  5073. case WM_PRINT:
  5074. _OnPaint((HDC)wParam);
  5075. break;
  5076. case WM_QUERYNEWPALETTE:
  5077. case WM_PALETTECHANGED:
  5078. case WM_SYSCOLORCHANGE:
  5079. case WM_DISPLAYCHANGE:
  5080. case WM_ENTERSIZEMOVE:
  5081. case WM_EXITSIZEMOVE:
  5082. {
  5083. HWND hwndT;
  5084. if (_pole && SUCCEEDED(IUnknown_GetWindow(_pole, &hwndT)) && hwndT)
  5085. return SendMessage(hwndT, uMsg, wParam, lParam);
  5086. return 0;
  5087. }
  5088. case WM_PAINT:
  5089. PAINTSTRUCT ps;
  5090. HDC hdc;
  5091. hdc = BeginPaint(_hwnd, &ps);
  5092. // we don't need them to paint into our dc...
  5093. // docobj has own hwnd.
  5094. //_OnPaint(hdc);
  5095. EndPaint(_hwnd, &ps);
  5096. break;
  5097. case WM_LBUTTONUP:
  5098. if (_uState != SVUIA_ACTIVATE_FOCUS) {
  5099. SetFocus(_hwnd);
  5100. }
  5101. break;
  5102. case WM_ERASEBKGND:
  5103. // Checking _bsc._fBinding will catch the first page case.
  5104. if (_fDrawBackground ||
  5105. (!(_dwAppHack & BROWSERFLAG_NEVERERASEBKGND)
  5106. && ((_pmsov && _uState!=SVUIA_DEACTIVATE)
  5107. || _bsc._fBinding)))
  5108. {
  5109. PAINTMSG("WM_ERASEBKGND", this);
  5110. goto DoDefault;
  5111. }
  5112. // Don't draw WM_ERASEBKGND if we have no view activated.
  5113. return TRUE; // TRUE = fErased
  5114. case WM_HELP:
  5115. //
  5116. // Give it to the parent to do. we need to do this in case we're hosted as a
  5117. // control
  5118. //
  5119. {
  5120. IOleCommandTarget *pcmdtTop;
  5121. if (SUCCEEDED(QueryService(SID_STopLevelBrowser, IID_IOleCommandTarget, (void **)&pcmdtTop))) {
  5122. pcmdtTop->Exec(&CGID_ShellDocView, SHDVID_HELP, 0, NULL, NULL);
  5123. pcmdtTop->Release();
  5124. }
  5125. // do nothing in failure... let the parent own completely
  5126. }
  5127. break;
  5128. case WM_WININICHANGE:
  5129. _PlaceProgressBar(TRUE);
  5130. break;
  5131. default:
  5132. // Handle the MSWheel message
  5133. if ((uMsg == GetWheelMsg()) && _pole)
  5134. {
  5135. HWND hwndT;
  5136. // If for some reason our window has focus we just need to
  5137. // swallow the message. If we don't we may create an infinite loop
  5138. // because most clients send the message to the focus window.
  5139. if (GetFocus() == _hwnd)
  5140. return 1;
  5141. //
  5142. // try to find a window to forward along to
  5143. //
  5144. if (SUCCEEDED(IUnknown_GetWindow(_pole, &hwndT)))
  5145. {
  5146. PostMessage(hwndT, uMsg, wParam, lParam);
  5147. return 1;
  5148. }
  5149. // Fall through...
  5150. }
  5151. DoDefault:
  5152. return DefWindowProc(hwnd, uMsg, wParam, lParam);
  5153. }
  5154. return lRet;
  5155. }
  5156. const TCHAR c_szViewClass[] = TEXT("Shell DocObject View");
  5157. void CDocObjectHost::_RegisterWindowClass(void)
  5158. {
  5159. WNDCLASS wc = {0};
  5160. wc.style = CS_PARENTDC;
  5161. wc.lpfnWndProc = s_WndProc ;
  5162. //wc.cbClsExtra = 0;
  5163. wc.cbWndExtra = SIZEOF(CDocObjectHost*);
  5164. wc.hInstance = g_hinst ;
  5165. //wc.hIcon = NULL ;
  5166. //wc.hCursor = NULL;
  5167. wc.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
  5168. //wc.lpszMenuName = NULL ;
  5169. wc.lpszClassName = c_szViewClass;
  5170. SHRegisterClass(&wc);
  5171. }
  5172. void CDocObjectHost::_InitOleObject()
  5173. {
  5174. if (!_fClientSiteSet)
  5175. {
  5176. _fClientSiteSet = TRUE;
  5177. #ifdef DEBUG
  5178. IOleClientSite * pcliT = NULL;
  5179. if (SUCCEEDED(_pole->GetClientSite(&pcliT)) && pcliT)
  5180. {
  5181. // Trident now grabs the client site from the bind context.
  5182. // We don't want to hit this assertin this case (pcliT==this).
  5183. //
  5184. AssertMsg(IsSameObject(pcliT, SAFECAST(this, IOleClientSite*)),
  5185. TEXT("CDocObjectHost::_InitOleObject _pole (%x) already has a client site (%x) (this=%x)"),
  5186. _pole, pcliT, this);
  5187. pcliT->Release();
  5188. }
  5189. #endif
  5190. HRESULT hresT = _pole->SetClientSite(this);
  5191. if (FAILED(hresT))
  5192. {
  5193. TraceMsg(TF_SHDAPPHACK, "DOH::_InitOleObject SetClientSite failed (%x). Don't in-place navigate", hresT);
  5194. _dwAppHack |= BROWSERFLAG_DONTINPLACE;
  5195. }
  5196. ASSERT(NULL==_pvo);
  5197. _pole->QueryInterface(IID_IViewObject, (void **)&_pvo);
  5198. if (_pvo)
  5199. {
  5200. TraceMsg(DM_DEBUGTFRAME, "CDocObjectHost::_InitOleObject about call SetAdvise on %x (%x)", _pole, this);
  5201. _pvo->SetAdvise(DVASPECT_CONTENT, ADVF_PRIMEFIRST, this);
  5202. }
  5203. //
  5204. // According to SteveRa (Word developer), a word object has an
  5205. // internal flag which indicates whether or not it is created
  5206. // from a file. If that flag is set, UIActivate will open the
  5207. // window in Word. Calling SetHostName will reset that flag.
  5208. //
  5209. _GetAppHack(); // Make it sure that we have _dwAppHack
  5210. if (_fCallSetHostName())
  5211. {
  5212. TraceMsg(TF_SHDAPPHACK, "DOH::_InitOleObject calling SetHostName for Word95");
  5213. WCHAR wszTitle[128];
  5214. MLLoadStringW(IDS_TITLE, wszTitle, ARRAYSIZE(wszTitle));
  5215. _pole->SetHostNames(wszTitle, wszTitle);
  5216. }
  5217. }
  5218. }
  5219. //+-----------------------------------------------------------------------------
  5220. //
  5221. // IE Media Bar hook
  5222. // -----------------
  5223. // At least one and only one of the args must be non-null.
  5224. //
  5225. // If pbc is non-null:
  5226. // If this bind ctx is for a media url and was delegated to shdocvw from trident,
  5227. // trident has already stored the mime-type as a string on the bind ctx.
  5228. //
  5229. // If pwzMimeType is non-null:
  5230. // The given mime type is used
  5231. //
  5232. // Ask the media bar if it wants to handle this mime-type and if it does,
  5233. // return true, else return false.
  5234. //
  5235. //-------------------------------------------------------------------------------
  5236. BOOL CDocObjectHost::_DelegateToMediaBar(IBindCtx * pbc, LPCWSTR pwzMimeType)
  5237. {
  5238. USES_CONVERSION;
  5239. LPWSTR pstrMime = NULL;
  5240. TCHAR szURL[MAX_URL_STRING];
  5241. BOOL fRet = FALSE;
  5242. CComVariant svarMime(pstrMime);
  5243. CComPtr<IUnknown> spUnkObj;
  5244. CComPtr<IOleCommandTarget> spOCTMimeType;
  5245. CComPtr<IOleCommandTarget> spOCTMediaBar;
  5246. // We want to delegate only under the following conditions:
  5247. // 1. In Explorer or IE
  5248. // 2. If autoplay is enabled
  5249. // 3. If autoplay is not turned off for the first navigation
  5250. // 4. If NOT NT4 or IA64 (WMP7/8 doesn't support these platforms)
  5251. // 5. If WMP7/8 is present (if it isn't, we will try to fault-in once.)
  5252. // 6. the media bar isn't restricted
  5253. if (!(IsInternetExplorerApp()
  5254. && CMediaBarUtil::GetAutoplay()
  5255. && !SHRestricted2(REST_No_LaunchMediaBar, NULL, 0)
  5256. && CMediaBarUtil::IsWMP7OrGreaterCapable()
  5257. && FAILED(QueryService(CLSID_MediaBand, IID_PPV_ARG(IUnknown, &spUnkObj)))))
  5258. {
  5259. goto done;
  5260. }
  5261. // release so we can reuse the pointer later
  5262. spUnkObj.Release();
  5263. // get the current URL
  5264. if (FAILED(_GetCurrentPage(szURL, ARRAYSIZE(szURL), TRUE)))
  5265. goto done;
  5266. // At least one and only one of the args must be non-null.
  5267. if (pbc && !pwzMimeType)
  5268. {
  5269. // get the custom parameter that trident uses to set the media mime-type
  5270. // QI for IOleCommandTarged to access the mime-type string.
  5271. // get the mime-type string
  5272. if (FAILED(pbc->GetObjectParam(L"MediaBarMime", &spUnkObj))
  5273. || FAILED(spUnkObj->QueryInterface(IID_PPV_ARG(IOleCommandTarget, &spOCTMimeType)))
  5274. || FAILED(spOCTMimeType->Exec(&CGID_DownloadObjectBindContext, 0, NULL, NULL, &svarMime)))
  5275. goto done;
  5276. }
  5277. else if (!pbc && pwzMimeType)
  5278. {
  5279. svarMime = pwzMimeType;
  5280. }
  5281. else
  5282. {
  5283. ASSERT(FALSE && L"Either one of bind ctx or mime-type is expected");
  5284. goto done;
  5285. }
  5286. // proceed only if mime type string is available
  5287. if ((VT_BSTR == svarMime.vt)
  5288. && svarMime.bstrVal)
  5289. {
  5290. // Ask the media bar if it wants to handle this mime-type
  5291. BOOL fShouldPlay = FALSE;
  5292. BOOL fShow = TRUE;
  5293. CComVariant svarUrl;
  5294. HRESULT hr = S_OK;
  5295. svarUrl = !StrCmpNIW(WZ_RADIO_PROTOCOL, szURL, wcslen(WZ_RADIO_PROTOCOL)) ? (szURL + wcslen(WZ_RADIO_PROTOCOL)) : szURL;
  5296. if (!(V_BSTR(&svarMime) && V_BSTR(&svarUrl)))
  5297. goto done;
  5298. // check if we can play this mime type
  5299. hr = CMediaBarUtil::ShouldPlay(W2T(V_BSTR(&svarMime)), &fShouldPlay);
  5300. if (FAILED(hr)
  5301. || (!fShouldPlay))
  5302. {
  5303. goto done;
  5304. }
  5305. // ShouldPlay returns S_FALSE if this is the first time playing this mime type.
  5306. if (S_FALSE == hr)
  5307. {
  5308. BOOL bSaveSetting = FALSE;
  5309. LONGLONG iRetCode = PLAYMIME_NO;
  5310. iRetCode = DialogBoxParam(MLGetHinst(), MAKEINTRESOURCE(IDD_MEDIA_MIME), _hwnd, s_MimeDlgProc, NULL);
  5311. switch (iRetCode)
  5312. {
  5313. case PLAYMIME_YES:
  5314. {
  5315. fShouldPlay = TRUE;
  5316. bSaveSetting = FALSE;
  5317. }
  5318. break;
  5319. case PLAYMIME_YESSAVE:
  5320. {
  5321. fShouldPlay = TRUE;
  5322. bSaveSetting = TRUE;
  5323. }
  5324. break;
  5325. case PLAYMIME_NO:
  5326. {
  5327. fShouldPlay = FALSE;
  5328. bSaveSetting = FALSE;
  5329. }
  5330. break;
  5331. case PLAYMIME_NOSAVE:
  5332. {
  5333. fShouldPlay = FALSE;
  5334. bSaveSetting = TRUE;
  5335. }
  5336. break;
  5337. default:
  5338. {
  5339. ASSERT(FALSE && L"Unexpected return value");
  5340. }
  5341. break;
  5342. }
  5343. // check if the setting needs to be saved
  5344. if (TRUE == bSaveSetting)
  5345. {
  5346. DWORD dwVal = fShouldPlay ? 0x1 : 0x0;
  5347. hr = CMediaBarUtil::SetMediaRegValue(V_BSTR(&svarMime), REG_BINARY, (void*) &dwVal, (DWORD) 1, TRUE);
  5348. ASSERT(SUCCEEDED(hr));
  5349. }
  5350. // Bail if user told us not to play this mime type
  5351. if (!fShouldPlay)
  5352. goto done;
  5353. }
  5354. else
  5355. {
  5356. // "don't prompt" means "play all types", unless autoplay is turned off
  5357. // in which case we have already bailed
  5358. }
  5359. // Yay. They want to try out our feature. But WAIT. We need WMP7/8. Is that installed? No? Well, let's go get it.
  5360. // If the user decides _not_ to install WMP7, though, we should disable ourselves.
  5361. if (!CMediaBarUtil::IsWMP7OrGreaterInstalled())
  5362. {
  5363. if (!IsOS(OS_WHISTLERORGREATER))
  5364. {
  5365. // Here we do the stuff to web-jit WMP7. ISSUE: We assume that it'll always be on Whistler
  5366. uCLSSPEC ucs;
  5367. QUERYCONTEXT qc = { 0 };
  5368. ucs.tyspec = TYSPEC_CLSID;
  5369. ucs.tagged_union.clsid = CLSID_JITWMP8;
  5370. hr = FaultInIEFeature(_hwnd, &ucs, &qc, FIEF_FLAG_FORCE_JITUI);
  5371. }
  5372. if (!CMediaBarUtil::IsWMP7OrGreaterInstalled())
  5373. {
  5374. // We give up. Delegate. We'll never try autoplay again.
  5375. MLShellMessageBox(_hwnd, MAKEINTRESOURCE(IDS_MEDIABAR_NOWMP7), MAKEINTRESOURCE(IDS_MEDIABAR_NOWMP7TITLE), MB_OK);
  5376. CMediaBarUtil::ToggleAutoplay(FALSE);
  5377. goto done;
  5378. }
  5379. }
  5380. // QS for the media bar
  5381. if (FAILED(QueryService(SID_SMediaBar, IID_PPV_ARG(IOleCommandTarget, &spOCTMediaBar))))
  5382. {
  5383. // The media bar may not have been created yet
  5384. _ForceCreateMediaBar();
  5385. // QS for the media bar once again
  5386. if (FAILED(QueryService(SID_SMediaBar, IID_PPV_ARG(IOleCommandTarget, &spOCTMediaBar))))
  5387. goto done;
  5388. fShow = FALSE;
  5389. }
  5390. hr = IUnknown_Exec(spOCTMediaBar, &CGID_MediaBar, MBID_PLAY, 0, &svarMime, &svarUrl);
  5391. ASSERT(SUCCEEDED(hr));
  5392. // The Media Bar clears the URL if it accepts the navigation
  5393. if (VT_BSTR != svarUrl.vt)
  5394. {
  5395. // Cancel the navigation
  5396. fRet = TRUE;
  5397. // Ensure that the media bar is visible
  5398. if (fShow)
  5399. {
  5400. CComVariant svarPopout;
  5401. if (SUCCEEDED(IUnknown_Exec(spOCTMediaBar, &CGID_MediaBar, MBID_POPOUT, 0, NULL, &svarPopout))
  5402. && ((VT_BOOL!=svarPopout.vt)
  5403. || (VARIANT_FALSE==svarPopout.boolVal)))
  5404. {
  5405. _ForceCreateMediaBar();
  5406. }
  5407. }
  5408. }
  5409. }
  5410. done:
  5411. return fRet;
  5412. }
  5413. //+---------------------------------------------------------------------------------
  5414. //
  5415. // IE Media Bar Hook
  5416. // ------------------
  5417. //
  5418. // Force the Media Bar to be displayed
  5419. //
  5420. //----------------------------------------------------------------------------------
  5421. void CDocObjectHost::_ForceCreateMediaBar()
  5422. {
  5423. IUnknown_ShowBrowserBar(_psp, CLSID_MediaBand, TRUE);
  5424. }
  5425. //+---------------------------------------------------------------------------------
  5426. //
  5427. // IE Media Bar Hook
  5428. // ------------------
  5429. //
  5430. // Dialog proc for Media Bar per-mime-type dialog
  5431. //
  5432. //----------------------------------------------------------------------------------
  5433. INT_PTR CALLBACK
  5434. CDocObjectHost::s_MimeDlgProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
  5435. {
  5436. UINT id;
  5437. switch(uMsg)
  5438. {
  5439. case WM_INITDIALOG:
  5440. CheckDlgButton(hDlg, IDC_MEDIA_MIME_CHKBOX, TRUE); // The first option is always checked
  5441. if (!CMediaBarUtil::IsWMP7OrGreaterInstalled())
  5442. {
  5443. TCHAR szTemp[500];
  5444. if (MLLoadString(IDS_MEDIABAR_NEEDWMP7, szTemp, ARRAYSIZE(szTemp)))
  5445. {
  5446. SetDlgItemText(hDlg, IDC_MEDIABAR_EXTRA, szTemp);
  5447. }
  5448. }
  5449. return TRUE;
  5450. case WM_DESTROY:
  5451. return FALSE;
  5452. case WM_COMMAND:
  5453. {
  5454. id = GET_WM_COMMAND_ID(wParam, lParam);
  5455. switch (id)
  5456. {
  5457. case IDOK:
  5458. {
  5459. if (IsDlgButtonChecked(hDlg, IDC_MEDIA_MIME_CHKBOX))
  5460. {
  5461. id = PLAYMIME_YESSAVE;
  5462. }
  5463. else
  5464. {
  5465. id = PLAYMIME_YES;
  5466. }
  5467. EndDialog(hDlg, id);
  5468. }
  5469. break;
  5470. case IDCANCEL:
  5471. {
  5472. if (IsDlgButtonChecked(hDlg, IDC_MEDIA_MIME_CHKBOX))
  5473. {
  5474. id = PLAYMIME_NOSAVE;
  5475. }
  5476. else
  5477. {
  5478. id = PLAYMIME_NO;
  5479. }
  5480. EndDialog(hDlg, id);
  5481. }
  5482. break;
  5483. case IDC_MEDIA_MOREINFO:
  5484. {
  5485. SHHtmlHelpOnDemandWrap(GetParent(hDlg), TEXT("iexplore.chm > iedefault"), 0, (DWORD_PTR) TEXT("mediabar_settings.htm"), ML_CROSSCODEPAGE);
  5486. }
  5487. break;
  5488. }
  5489. }
  5490. break;
  5491. default:
  5492. return FALSE;
  5493. }
  5494. return TRUE;
  5495. }
  5496. HRESULT CDocObjectHost::SetTarget(IMoniker* pmk, UINT uiCP, LPCTSTR pszLocation, LPITEMIDLIST pidlKey,
  5497. IShellView* psvPrev, BOOL fFileProtocol)
  5498. {
  5499. HRESULT hres = NOERROR;
  5500. BOOL fLoadedHistory = FALSE;
  5501. ATOMICRELEASE(_pmkCur);
  5502. _pmkCur = pmk;
  5503. pmk->AddRef();
  5504. ILFree(_pidl);
  5505. _pidl = ILClone(pidlKey);
  5506. _fFileProtocol = fFileProtocol;
  5507. _pszLocation = pszLocation;
  5508. _uiCP = uiCP;
  5509. // this is only set if we did a successful LoadHistory()
  5510. _fIsHistoricalObject = FALSE;
  5511. if (_bsc._hszPostData)
  5512. {
  5513. GlobalFree(_bsc._hszPostData);
  5514. _bsc._hszPostData = NULL;
  5515. }
  5516. if (_bsc._pszHeaders)
  5517. {
  5518. LocalFree(_bsc._pszHeaders);
  5519. _bsc._pszHeaders = NULL;
  5520. }
  5521. ATOMICRELEASE(_bsc._pbc);
  5522. //
  5523. // this replaces the old style of caching.
  5524. // if something has been cached, it was cached
  5525. // way above us before we ever existed. now it is
  5526. // waiting for us.
  5527. //
  5528. IBrowserService * pbs;
  5529. IStream * pstm = NULL;
  5530. IBindCtx * pbcHistory = NULL;
  5531. if (SUCCEEDED(QueryService(SID_SShellBrowser, IID_IBrowserService, (void **)&pbs)))
  5532. {
  5533. // just in case there is one already there, like in the case of local anchor navigates
  5534. ATOMICRELEASE(_pole);
  5535. pbs->GetHistoryObject(&_pole, &pstm, &pbcHistory);
  5536. TraceMsg(TF_TRAVELLOG, "DOH::SetTarget History object: _pole = %X, pstm = %X, pbc = %X", _pole, pstm, pbcHistory);
  5537. pbs->Release();
  5538. }
  5539. if (_pole)
  5540. {
  5541. // some objects (MSHTML for one) need their clientsite before anything else.
  5542. // so we need to init first
  5543. _InitOleObject();
  5544. if (pstm)
  5545. {
  5546. IPersistHistory *pph;
  5547. if (SUCCEEDED(_pole->QueryInterface(IID_IPersistHistory, (void **)&pph)))
  5548. {
  5549. if (SUCCEEDED(pph->LoadHistory(pstm, pbcHistory)))
  5550. {
  5551. //
  5552. // this is to make sure that we wait for
  5553. // the pole to tell us when it is ready.
  5554. // when there is a pstm, that means that they may have
  5555. // to do a full reparse or whatever, and we cant make
  5556. // any assumptions about the readystate.
  5557. //
  5558. hres = S_FALSE;
  5559. _fIsHistoricalObject = TRUE;
  5560. _SetUpTransitionCapability();
  5561. fLoadedHistory = TRUE;
  5562. // we may need to redo the pics stuff too.
  5563. // PrepPicsForAsync();
  5564. TraceMsg(TF_TRAVELLOG, "DOH::SetTarget pph->LoadHistory Successful");
  5565. }
  5566. else
  5567. ATOMICRELEASE(_pole);
  5568. pph->Release();
  5569. }
  5570. ATOMICRELEASE(pstm);
  5571. }
  5572. else
  5573. hres = S_OK;
  5574. ATOMICRELEASE(pbcHistory);
  5575. // we shouldnt fail a load history, because the data in
  5576. // is just what the document gave us in SaveHistory...
  5577. AssertMsg(NULL != _pole, TEXT("DOH::SetTarget pph->LoadHistory Failed"));
  5578. // if we were already up and created, just scroll to it.
  5579. // if we were created DEACTIVATED, (possible in the ocx case)
  5580. // don't do this activation
  5581. if (_uState != SVUIA_DEACTIVATE && !DocCanHandleNavigation())
  5582. {
  5583. hres = _ActivateMsoView();
  5584. }
  5585. //
  5586. // allow navigation - when you're deactivated. So you can navigate an invisible WebOC.
  5587. // IE6 Bug# 5449
  5588. //
  5589. if ( DocCanHandleNavigation() ||
  5590. ( _fDocCanNavigate &&
  5591. _uState == SVUIA_DEACTIVATE &&
  5592. !fLoadedHistory ) )
  5593. {
  5594. // If the _fPrevDocHost flag is not
  5595. // set, we better be deactivated.
  5596. //
  5597. AssertMsg((_fPrevDocHost || _uState == SVUIA_DEACTIVATE),
  5598. _T("_fPrevDocHost is not set and we are activated"));
  5599. // If the document is handling the navigation,
  5600. // we must store the user entered URL here.
  5601. // Otherwise, if the navigation fails,
  5602. // the user-entered URL is NULL by the time
  5603. // _bsc._HandleFailedNavigationSearch is called,
  5604. //
  5605. VariantClear(&_varUserEnteredUrl);
  5606. _GetSearchString(_psp, &_varUserEnteredUrl);
  5607. WCHAR wzUrl[MAX_URL_STRING];
  5608. hres = IEGetNameAndFlagsEx(_pidl, SHGDN_FORPARSING, IEGDN_NOFRAGMENT, wzUrl, ARRAYSIZE(wzUrl), NULL);
  5609. if (S_OK == hres)
  5610. {
  5611. _EnableModeless(FALSE);
  5612. WCHAR wzLocation[MAX_URL_STRING] = {0};
  5613. IEILGetFragment(_pidl, wzLocation, SIZECHARS(wzLocation));
  5614. hres = _NavigateDocument(CComBSTR(wzUrl), CComBSTR(wzLocation));
  5615. _EnableModeless(TRUE);
  5616. }
  5617. }
  5618. }
  5619. if (!_pole)
  5620. {
  5621. ASSERT(!pstm);
  5622. ASSERT(!pbcHistory);
  5623. IBindCtx * pbc = NULL;
  5624. TraceMsg(TF_TRAVELLOG, "DOH::SetTarget No obj from TravelLog, calling pmk->BindToObject");
  5625. if (_psp)
  5626. {
  5627. hres = _psp->QueryService(SID_SShellBrowser, IID_IBindCtx, (void **)&pbc);
  5628. }
  5629. if (pbc == NULL)
  5630. {
  5631. hres = CreateBindCtx(0, &pbc);
  5632. }
  5633. else
  5634. {
  5635. hres = S_OK;
  5636. }
  5637. if (SUCCEEDED(hres))
  5638. {
  5639. HRESULT hr = E_FAIL;
  5640. IBindCtx * pbcAsync = NULL;
  5641. IBindCtx * pbcWrapper = NULL;
  5642. if (pbc)
  5643. {
  5644. // If the bind context supports IAsyncBindCtx, then it
  5645. // is a bind context that was created by UrlMon and passed
  5646. // to us to reuse. We must pass this bind context to UrlMon
  5647. // as-is and not wrapped in a BCW object.
  5648. // Note: IAsyncBindCtx has identicial interface as IBindCtx
  5649. //
  5650. hr = pbc->QueryInterface(IID_IAsyncBindCtx, (void**)&pbcAsync);
  5651. ATOMICRELEASE(pbcAsync);
  5652. }
  5653. if (SUCCEEDED(hr))
  5654. {
  5655. // If this is a media url delegated to shdocvw from trident,
  5656. // and if the IE Media Bar wants to handle the url, cancel
  5657. // the navigation, else continue the navigation.
  5658. if (_DelegateToMediaBar(pbc, NULL))
  5659. {
  5660. _CancelPendingNavigation(TRUE);
  5661. if (_pwb)
  5662. {
  5663. _pwb->SetNavigateState(BNS_NORMAL);
  5664. }
  5665. ATOMICRELEASE(pbc);
  5666. return S_FALSE;
  5667. }
  5668. else
  5669. {
  5670. ATOMICRELEASE(_pbcCur);
  5671. _fDelegatedNavigation = TRUE;
  5672. _pbcCur = pbc; // No need to AddRef - pbc is AddRef'ed by QS.
  5673. }
  5674. }
  5675. else
  5676. {
  5677. pbcWrapper = BCW_Create(pbc);
  5678. if (pbcWrapper == NULL)
  5679. {
  5680. pbcWrapper = pbc;
  5681. }
  5682. else
  5683. {
  5684. pbc->Release();
  5685. }
  5686. pbc = NULL;
  5687. hres = CreateAsyncBindCtxEx(pbcWrapper, 0, NULL, NULL, &pbcAsync, 0);
  5688. if (SUCCEEDED(hres))
  5689. {
  5690. ASSERT(pbcAsync);
  5691. ATOMICRELEASE(_pbcCur);
  5692. _pbcCur = pbcAsync;
  5693. _pbcCur->AddRef();
  5694. pbcWrapper->Release();
  5695. pbcWrapper = pbcAsync;
  5696. }
  5697. }
  5698. if (SUCCEEDED(hres))
  5699. {
  5700. #ifdef DEBUG
  5701. DWORD dwMksys;
  5702. hres = pmk->IsSystemMoniker(&dwMksys);
  5703. ASSERT((SUCCEEDED(hres) && dwMksys!=MKSYS_FILEMONIKER));
  5704. #endif
  5705. ASSERT(FALSE == _fSetTarget);
  5706. BOOL fWindowOpen = FALSE;
  5707. if (_pbcCur)
  5708. {
  5709. IUnknown * punkBindCtxParam = NULL;
  5710. hres = _pbcCur->GetObjectParam(KEY_BINDCONTEXTPARAM, &punkBindCtxParam);
  5711. if (SUCCEEDED(hres))
  5712. {
  5713. fWindowOpen = TRUE;
  5714. punkBindCtxParam->Release();
  5715. }
  5716. }
  5717. // If we are being called in response to window.open
  5718. // we create the document here and call InitNew on it
  5719. // to load about:blank. We do this so that the user won't
  5720. // see a transparent window while the URL is being
  5721. // located. When Trident calls Invoke to get the
  5722. // new window object, we will then load the real document.
  5723. //
  5724. if (fWindowOpen)
  5725. {
  5726. hres = _CreatePendingDocObject(TRUE, TRUE);
  5727. ASSERT(S_OK == hres && _punkPending);
  5728. if (_punkPending)
  5729. {
  5730. ATOMICRELEASE(_pole);
  5731. hres = _punkPending->QueryInterface(IID_IOleObject, (void**)&_pole);
  5732. ASSERT(SUCCEEDED(hres));
  5733. // IE Media Bar: turn auto-play off for the first navigation
  5734. // This is needed to make the target="_blank" feature work.
  5735. CMediaBarHelper::DisableFirstAutoPlay(_punkPending);
  5736. }
  5737. }
  5738. else
  5739. {
  5740. // Hack: The AddRef & Release protect against an error page
  5741. // navigation from freeing the pdoh out from under us (edwardp)
  5742. AddRef();
  5743. _fSetTarget = TRUE;
  5744. hres = _StartAsyncBinding(pmk, _pbcCur, psvPrev);
  5745. _fSetTarget = FALSE;
  5746. // Hack: Matching Release()
  5747. //
  5748. Release();
  5749. if (SUCCEEDED(hres))
  5750. {
  5751. hres = S_FALSE;
  5752. }
  5753. }
  5754. }
  5755. ATOMICRELEASE(pbcWrapper); // CreateAsyncBindCtx addrefs as well.
  5756. }
  5757. }
  5758. return hres;
  5759. }
  5760. #define USE_HISTBMOFFSET 0
  5761. #define USE_MYBMOFFSET 1
  5762. #define USE_STDBMOFFSET 2
  5763. void CDocObjectHost::_MergeToolbarSB()
  5764. {
  5765. }
  5766. HICON _LoadSmallIcon(int id)
  5767. {
  5768. return (HICON)LoadImage(HINST_THISDLL, MAKEINTRESOURCE(id),
  5769. IMAGE_ICON, GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CYSMICON), 0);
  5770. }
  5771. void _InitIcons(void)
  5772. {
  5773. ENTERCRITICAL;
  5774. if (g_hiconScriptErr == NULL)
  5775. {
  5776. g_hiconScriptErr = _LoadSmallIcon(IDI_STATE_SCRIPTERROR);
  5777. if (IS_BIDI_LOCALIZED_SYSTEM())
  5778. MirrorIcon(&g_hiconScriptErr, NULL);
  5779. }
  5780. if (!g_hiconSSL)
  5781. {
  5782. g_hiconSSL = _LoadSmallIcon(IDI_SSL);
  5783. if (IS_BIDI_LOCALIZED_SYSTEM())
  5784. MirrorIcon(&g_hiconSSL, NULL);
  5785. }
  5786. if (!g_hiconFortezza)
  5787. {
  5788. g_hiconFortezza = _LoadSmallIcon(IDI_FORTEZZA);
  5789. if (IS_BIDI_LOCALIZED_SYSTEM())
  5790. MirrorIcon(&g_hiconFortezza, NULL);
  5791. }
  5792. for (UINT id = IDI_STATE_FIRST; id <= IDI_STATE_LAST; id++)
  5793. {
  5794. if (!g_ahiconState[id-IDI_STATE_FIRST])
  5795. {
  5796. g_ahiconState[id-IDI_STATE_FIRST]= _LoadSmallIcon(id);
  5797. if (IS_BIDI_LOCALIZED_SYSTEM())
  5798. MirrorIcon(&g_ahiconState[id-IDI_STATE_FIRST], NULL);
  5799. }
  5800. }
  5801. if (!g_hiconOffline)
  5802. {
  5803. g_hiconOffline = _LoadSmallIcon(IDI_OFFLINE);
  5804. if (IS_BIDI_LOCALIZED_SYSTEM())
  5805. MirrorIcon(&g_hiconOffline, NULL);
  5806. }
  5807. if (!g_hiconPrinter)
  5808. {
  5809. g_hiconPrinter = _LoadSmallIcon(IDI_PRINTER);
  5810. if (IS_BIDI_LOCALIZED_SYSTEM())
  5811. MirrorIcon(&g_hiconPrinter, NULL);
  5812. }
  5813. if (!g_hiconPrivacyImpact)
  5814. {
  5815. g_hiconPrivacyImpact = _LoadSmallIcon( IDI_PRIVACY_IMPACT);
  5816. if (IS_BIDI_LOCALIZED_SYSTEM())
  5817. MirrorIcon(&g_hiconPrivacyImpact, NULL);
  5818. }
  5819. LEAVECRITICAL;
  5820. }
  5821. // This function initializes whatever the Class needs for manipulating the history
  5822. // we try to delay this till absolutely needed in order to not load
  5823. // wininet till the end
  5824. IUnknown *
  5825. CDocObjectHost::get_punkSFHistory()
  5826. {
  5827. if (_pocthf && !_punkSFHistory)
  5828. {
  5829. VARIANT var;
  5830. VariantInit(&var);
  5831. if (SUCCEEDED(_pocthf->Exec(&CGID_Explorer, SBCMDID_HISTSFOLDER, TRUE, NULL, &var)))
  5832. {
  5833. if (VT_UNKNOWN == var.vt && NULL != var.punkVal)
  5834. {
  5835. _punkSFHistory = var.punkVal;
  5836. _punkSFHistory->AddRef();
  5837. }
  5838. }
  5839. VariantClearLazy(&var);
  5840. }
  5841. return _punkSFHistory;
  5842. }
  5843. //
  5844. // This function (re)initializes CDocObjectHost object with the buddy
  5845. // IShellView (which is always CShellDocView) and the IShellBrowser.
  5846. // If this is the first time (_hwnd==NULL), it creates the view window
  5847. // and other associated windows as well. Otherwise (_hwnd!=NULL) -- it
  5848. // means this object is passed from one CDocViewObject to another because
  5849. // of intra-page jump -- we move it to the specified location (prcView)
  5850. // to make it really sure that we show it at the right place.
  5851. //
  5852. BOOL CDocObjectHost::InitHostWindow(IShellView* psv, IShellBrowser* psb,
  5853. LPRECT prcView)
  5854. {
  5855. HWND hwndParent;
  5856. IServiceProvider * pspTop;
  5857. IOleObject * pTopOleObject;
  5858. IOleClientSite * pOleClientSite;
  5859. _ResetOwners();
  5860. ASSERT(psv);
  5861. _psv = psv;
  5862. _psv->AddRef();
  5863. ASSERT(NULL==_pmsoctView);
  5864. _psv->QueryInterface(IID_IOleCommandTarget, (void **)&_pmsoctView);
  5865. ASSERT(NULL==_pdvs);
  5866. _psv->QueryInterface(IID_IDocViewSite, (void **)&_pdvs);
  5867. ASSERT(psb);
  5868. _psb = psb;
  5869. _psb->AddRef();
  5870. ASSERT(NULL==_pwb);
  5871. _psb->QueryInterface(IID_IBrowserService, (void **)&_pwb);
  5872. ASSERT(NULL==_pmsoctBrowser);
  5873. _psb->QueryInterface(IID_IOleCommandTarget, (void **)&_pmsoctBrowser);
  5874. ASSERT(NULL==_psp);
  5875. _psb->QueryInterface(IID_IServiceProvider, (void **)&_psp);
  5876. ASSERT(NULL==_pipu);
  5877. _psb->QueryInterface(IID_IOleInPlaceUIWindow, (void **)&_pipu);
  5878. ASSERT(_pipu);
  5879. _Init();
  5880. ASSERT(_psp);
  5881. if (_psp)
  5882. {
  5883. // Get the object that manages the extended buttons from the top-level browser
  5884. // But only if we don't already have it.
  5885. if (NULL == _pBrowsExt)
  5886. _psp->QueryService(SID_STopLevelBrowser, IID_IToolbarExt, (void **)&_pBrowsExt);
  5887. //
  5888. // LATER: I don't like that CDocObjectHost is directly accessing
  5889. // the automation service object to fire events. We should
  5890. // probably move all the progress UI code above IShellBrowser
  5891. // so that we don't need to do this shortcut. (SatoNa)
  5892. //
  5893. ASSERT(NULL==_peds);
  5894. _psp->QueryService(IID_IExpDispSupport, IID_IExpDispSupport, (void **)&_peds);
  5895. ASSERT(_peds);
  5896. ASSERT(NULL==_pedsHelper);
  5897. _peds->QueryInterface(IID_IExpDispSupportOC, (void **)&_pedsHelper);
  5898. ASSERT(NULL==_phf);
  5899. _psp->QueryService(SID_SHlinkFrame, IID_IHlinkFrame, (void **)&_phf);
  5900. if (_phf)
  5901. {
  5902. _phf->QueryInterface(IID_IUrlHistoryNotify, (void **)&_pocthf);
  5903. }
  5904. // _punkSFHistory was being initialized here - but in order to delay the load of wininet.dll
  5905. // we initialize it just before we use it
  5906. ASSERT(_pWebOCUIHandler == NULL);
  5907. ASSERT(_pWebOCUIHandler2 == NULL);
  5908. ASSERT(_pWebOCInPlaceSiteEx == NULL);
  5909. ASSERT(_fDocCanNavigate || _fWebOC == FALSE);
  5910. if (SUCCEEDED(_psp->QueryService(SID_STopLevelBrowser, IID_IServiceProvider, (void **)&pspTop)) && pspTop)
  5911. {
  5912. if (SUCCEEDED(pspTop->QueryService(SID_SContainerDispatch, IID_IOleObject, (void **)&pTopOleObject)) && pTopOleObject)
  5913. {
  5914. _fWebOC = TRUE; // there was a container so we're a WebOC
  5915. pTopOleObject->GetClientSite(&pOleClientSite);
  5916. if (pOleClientSite)
  5917. {
  5918. pOleClientSite->QueryInterface(IID_IDocHostUIHandler, (void**)&_pWebOCUIHandler);
  5919. pOleClientSite->QueryInterface(IID_IDocHostUIHandler2, (void**)&_pWebOCUIHandler2);
  5920. pOleClientSite->QueryInterface(IID_IDocHostShowUI, (void**)&_pWebOCShowUI);
  5921. pOleClientSite->QueryInterface(IID_IOleInPlaceSiteEx, (void**)&_pWebOCInPlaceSiteEx);
  5922. pOleClientSite->Release();
  5923. }
  5924. pTopOleObject->Release();
  5925. }
  5926. pspTop->Release();
  5927. }
  5928. }
  5929. _dhUIHandler.SetSite( (IDocHostUIHandler *) this); // Apparently we need to disamiguate the IUnknown reference.
  5930. _psb->GetWindow(&hwndParent);
  5931. if (!_hwnd) {
  5932. // There are several things we don't attempt to do when
  5933. // we're not toplevel. Frameset type DOH should never
  5934. // try to menu merge or dork with the statusbar.
  5935. // Do this before the CreateWindowEx call 'cuz during
  5936. // creation we party on the status bar.
  5937. {
  5938. IOleInPlaceSite* pparentsite = _GetParentSite();
  5939. if (pparentsite) {
  5940. _fHaveParentSite = TRUE;
  5941. pparentsite->Release();
  5942. }
  5943. }
  5944. _RegisterWindowClass();
  5945. // really create the window
  5946. DWORD dwStyle = WS_CHILD | WS_CLIPCHILDREN | WS_CLIPSIBLINGS | WS_VISIBLE | WS_TABSTOP;
  5947. //
  5948. // In Office 95, Excel and PowerPoint don't draw the client edge,
  5949. // while Word does draw the client edge. To avoid having double edges,
  5950. // we remove it for now. SriniK (Office) will find out which will be
  5951. // the standard for Office 96. (SatoNa)
  5952. //
  5953. _hwnd = SHNoFusionCreateWindowEx(0 /* WS_EX_CLIENTEDGE */,
  5954. c_szViewClass, NULL,
  5955. dwStyle,
  5956. prcView->left, prcView->top, prcView->right-prcView->left, prcView->bottom-prcView->top,
  5957. hwndParent,
  5958. (HMENU)0,
  5959. HINST_THISDLL,
  5960. (LPVOID)SAFECAST(this, CImpWndProc*));
  5961. if (!_hwnd) {
  5962. goto Bail;
  5963. }
  5964. UINT uiAcc = ACCEL_DOCVIEW;
  5965. if (SHRestricted(REST_NOFILEMENU))
  5966. uiAcc = ACCEL_DOCVIEW_NOFILEMENU;
  5967. if (_hacc)
  5968. {
  5969. DestroyAcceleratorTable(_hacc);
  5970. _hacc = NULL;
  5971. }
  5972. _hacc = LoadAccelerators(MLGetHinst(), MAKEINTRESOURCE(uiAcc));
  5973. _InitIcons();
  5974. } else {
  5975. ASSERT(GetParent(_hwnd) == hwndParent);
  5976. MoveWindow(_hwnd, prcView->left, prcView->top,
  5977. prcView->right-prcView->left, prcView->bottom - prcView->top, TRUE);
  5978. }
  5979. Bail:
  5980. return (bool) _hwnd;
  5981. }
  5982. void CDocObjectHost::_CleanupProgress(void)
  5983. {
  5984. TraceMsg(TF_SHDPROGRESS, "CDOH::CleanupProgress fTimer = %d, fFull = %d, hwndProg = %X", _fProgressTimer, _fProgressTimerFull, _hwndProgress);
  5985. if (_fProgressTimer)
  5986. {
  5987. KillTimer(_hwnd, IDTIMER_PROGRESS);
  5988. _fProgressTimer = FALSE;
  5989. }
  5990. if (_fProgressTimerFull)
  5991. {
  5992. // we are being stopped, and the hwnd is destroyed
  5993. // before we clear the status bar. zekel - 22-JUL-97
  5994. _OnSetProgressPos(-2, PROGRESS_RESET);
  5995. KillTimer(_hwnd, IDTIMER_PROGRESSFULL);
  5996. ASSERT(!_fProgressTimerFull);
  5997. }
  5998. _OnSetProgressMax(0);
  5999. _hwndProgress = NULL;
  6000. }
  6001. void CDocObjectHost::DestroyHostWindow()
  6002. {
  6003. // Turn off the simple mode when we are leaving.
  6004. if (_psb)
  6005. _psb->SendControlMsg(FCW_STATUS, SB_SIMPLE, 0, 0, NULL);
  6006. // really destroy the window
  6007. _fCanceledByBrowser = TRUE;
  6008. _bsc.AbortBinding();
  6009. _RemoveAllPicsProcessors();
  6010. _CloseMsoView();
  6011. //
  6012. // Notes: We need to delete OLE object from this side (container),
  6013. // otherwise, we leak because of circular reference.
  6014. //
  6015. _UnBind();
  6016. _CleanupProgress();
  6017. if (_hwndTooltip) {
  6018. DestroyWindow(_hwndTooltip);
  6019. _hwndTooltip = NULL;
  6020. }
  6021. //
  6022. // Note that we need to destroy the parent after destroying children.
  6023. //
  6024. // OLE seems to recurse back into this function when we destroy the hwnd
  6025. // and we try to destroy it a second time causing a RIP. Avoid this RIP
  6026. // by NULLing out our internal variables before we destroy the hwnds.
  6027. if (_hwnd) {
  6028. HWND hwndT = _hwnd;
  6029. _hwnd = NULL;
  6030. DestroyWindow(hwndT);
  6031. }
  6032. ATOMICRELEASE(_psp);
  6033. _ResetOwners();
  6034. }
  6035. //
  6036. // This member creates a view (IOleDocumentView) of the DocObject we have (_pole).
  6037. // This function is called only once from ::CreateViewWindow.
  6038. //
  6039. HRESULT CDocObjectHost::_CreateMsoView(void)
  6040. {
  6041. ASSERT(_pmsov == NULL);
  6042. ASSERT(_pmsoc == NULL);
  6043. HRESULT hres = OleRun(_pole);
  6044. if (SUCCEEDED(hres))
  6045. {
  6046. //// WARNING:
  6047. // if you add anything to here, you should also pass it along
  6048. // in _CreateDocObjHost
  6049. //
  6050. IOleDocument* pmsod = NULL;
  6051. hres = _pole->QueryInterface(IID_IOleDocument, (void **)&pmsod);
  6052. if (SUCCEEDED(hres)) {
  6053. hres = pmsod->CreateView(this, NULL ,0,&_pmsov);
  6054. if (SUCCEEDED(hres)) {
  6055. //
  6056. // HACK: Working about MSHTML bug (#28756). We really
  6057. // want to take this hack out before we ship. (SatoNa)
  6058. //
  6059. _pmsov->SetInPlaceSite(this);
  6060. } else {
  6061. TraceMsg(DM_ERROR, "DOH::_CreateMsoView pmsod->CreateView() ##FAILED## %x", hres);
  6062. }
  6063. if (SUCCEEDED(hres) && !_pmsot) {
  6064. _pmsov->QueryInterface(IID_IOleCommandTarget, (void **)&_pmsot);
  6065. }
  6066. if (SUCCEEDED(hres) && !_pmsoc) {
  6067. _pmsov->QueryInterface(IID_IOleControl, (void **)&_pmsoc);
  6068. }
  6069. #ifdef HLINK_EXTRA
  6070. if (_pihlbc)
  6071. {
  6072. if (_phls)
  6073. {
  6074. _phls->SetBrowseContext(_pihlbc);
  6075. }
  6076. ASSERT(_pmkCur);
  6077. hres = HlinkOnNavigate(this, _pihlbc, 0,
  6078. _pmkCur, NULL, NULL);
  6079. // TraceMsg(0, "sdv TR : _CreateMsoView HlinkOnNavigate returned %x", hres);
  6080. }
  6081. #endif // HLINK_EXTRA
  6082. pmsod->Release();
  6083. } else {
  6084. TraceMsg(DM_ERROR, "DOH::_CreateMsoView _pole->QI(IOleDocument) ##FAILED## %x", hres);
  6085. }
  6086. } else {
  6087. TraceMsg(DM_ERROR, "DOH::_CreateMsoView OleRun ##FAILED## %x", hres);
  6088. }
  6089. return hres;
  6090. }
  6091. HRESULT CDocObjectHost::_ForwardSetSecureLock(int lock)
  6092. {
  6093. HRESULT hr = E_FAIL;
  6094. TraceMsg(DM_SSL, "[%X}DOH::ForwardSecureLock() lock = %d",this, lock, hr);
  6095. VARIANT va = {0};
  6096. va.vt = VT_I4;
  6097. va.lVal = lock;
  6098. // we should only suggest if we are not the topframe
  6099. if (_psp && _psb && !IsTopFrameBrowser(_psp, _psb))
  6100. {
  6101. IOleCommandTarget *pmsoct;
  6102. if (SUCCEEDED(_psp->QueryService(SID_STopFrameBrowser, IID_IOleCommandTarget, (void **)&pmsoct)))
  6103. {
  6104. ASSERT(pmsoct);
  6105. if (lock < SECURELOCK_FIRSTSUGGEST)
  6106. va.lVal += SECURELOCK_FIRSTSUGGEST;
  6107. hr = pmsoct->Exec(&CGID_Explorer, SBCMDID_SETSECURELOCKICON, 0, &va, NULL);
  6108. pmsoct->Release();
  6109. }
  6110. }
  6111. else
  6112. if (_pmsoctBrowser)
  6113. hr = _pmsoctBrowser->Exec(&CGID_Explorer, SBCMDID_SETSECURELOCKICON, 0, &va, NULL);
  6114. return hr;
  6115. }
  6116. //
  6117. // This is the only method of IOleDocumentSite, which we MUST implement.
  6118. //
  6119. HRESULT CDocObjectHost::ActivateMe(IOleDocumentView *pviewToActivate)
  6120. {
  6121. TraceMsg(TF_SHDUIACTIVATE, "DOC::ActivateMe called when _pmsov is %x", _pmsov);
  6122. HRESULT hres = S_OK;
  6123. if (_pmsov==NULL) {
  6124. hres = _CreateMsoView();
  6125. #ifdef TEST_DELAYED_SHOWMSOVIEW
  6126. SetTimer(_hwnd, 100, 1500, NULL);
  6127. MessageBeep(0);
  6128. return hres;
  6129. #endif // TEST_DELAYED_SHOWMSOVIEW
  6130. }
  6131. if (SUCCEEDED(hres))
  6132. {
  6133. _ShowMsoView();
  6134. _MergeToolbarSB();
  6135. _InitToolbarButtons();
  6136. ASSERT(_pmsoctBrowser);
  6137. if (_fSetSecureLock)
  6138. _ForwardSetSecureLock(_eSecureLock);
  6139. }
  6140. return hres;
  6141. }
  6142. //Helper routine for QueryStatus for status messages
  6143. ULONG ulBufferSizeNeeded(wchar_t *wsz, int ids, ULONG ulBufferLen)
  6144. {
  6145. TraceMsg(0, "sdv TR ulBufferSizeNeeded called with (%x)", ids);
  6146. ASSERT(ulBufferLen > 0);
  6147. DWORD dwLen;
  6148. WCHAR szTemp[MAX_STATUS_SIZE+1];
  6149. dwLen = MLLoadStringW(ids, szTemp, MAX_STATUS_SIZE);
  6150. if (dwLen!= 0 && dwLen < (DWORD)ulBufferLen)
  6151. MoveMemory(wsz, szTemp, (dwLen+1) * sizeof(WCHAR)); // +1 for the NULL not included in LoadString count
  6152. else
  6153. *wsz = 0;
  6154. return ((ULONG)dwLen);
  6155. }
  6156. HRESULT CDocObjectHost::OnQueryStatus(const GUID *pguidCmdGroup, ULONG cCmds, OLECMD rgCmds[], OLECMDTEXT *pcmdtext, HRESULT hres)
  6157. {
  6158. if (pguidCmdGroup == NULL)
  6159. {
  6160. ULONG i;
  6161. if (rgCmds == NULL)
  6162. return E_INVALIDARG;
  6163. for (i=0 ; i<cCmds ; i++)
  6164. {
  6165. // ONLY say that we support the stuff we support in ::OnExec
  6166. switch (rgCmds[i].cmdID)
  6167. {
  6168. case OLECMDID_OPEN:
  6169. case OLECMDID_SAVE:
  6170. case OLECMDID_UPDATECOMMANDS:
  6171. case OLECMDID_SETPROGRESSMAX:
  6172. case OLECMDID_SETPROGRESSPOS:
  6173. case OLECMDID_SETPROGRESSTEXT:
  6174. case OLECMDID_SETTITLE:
  6175. rgCmds[i].cmdf = OLECMDF_ENABLED;
  6176. break;
  6177. default:
  6178. if (SUCCEEDED(hres))
  6179. {
  6180. // _pmsoctBrowser already filled this in
  6181. }
  6182. else
  6183. {
  6184. rgCmds[i].cmdf = 0;
  6185. }
  6186. break;
  6187. }
  6188. }
  6189. /* for now we deal only with status text*/
  6190. if (pcmdtext)
  6191. {
  6192. switch (rgCmds[i].cmdID)
  6193. {
  6194. case OLECMDID_OPEN:
  6195. case OLECMDID_SAVE:
  6196. pcmdtext->cwActual = ulBufferSizeNeeded(pcmdtext->rgwz,
  6197. IDS_HELP_OF(_MapFromMso(rgCmds[0].cmdID)),
  6198. pcmdtext->cwBuf);
  6199. break;
  6200. default:
  6201. if (SUCCEEDED(hres))
  6202. {
  6203. // _pmsoctBrowser already filled this in
  6204. }
  6205. else
  6206. {
  6207. pcmdtext->cmdtextf = OLECMDTEXTF_NONE;
  6208. pcmdtext->cwActual = 0;
  6209. if (pcmdtext->rgwz && pcmdtext->cwBuf>0)
  6210. *pcmdtext->rgwz = TEXT('\0');
  6211. }
  6212. break;
  6213. }
  6214. }
  6215. hres = S_OK;
  6216. }
  6217. else if (IsEqualGUID(*pguidCmdGroup, CLSID_InternetButtons) ||
  6218. IsEqualGUID(*pguidCmdGroup, CLSID_MSOButtons))
  6219. {
  6220. for (UINT i = 0 ; i < cCmds ; i++)
  6221. {
  6222. // CommandIDs from DVIDM_MENUEXT_FIRST to DVIDM_MENUEXT_LAST are reserved for toolbar extension buttons
  6223. // Do NOT use this range for constants within the scope of CLSID_InternetButtons/CLSID_MSOButtons!
  6224. if (IsInRange(rgCmds[i].cmdID, DVIDM_MENUEXT_FIRST, DVIDM_MENUEXT_LAST))
  6225. {
  6226. // We'll pass specificially this OLECMD through to the custom button
  6227. IUnknown_QueryStatus(_pBrowsExt, &CLSID_ToolbarExtButtons, 1, &rgCmds[i], pcmdtext);
  6228. }
  6229. else
  6230. {
  6231. switch (rgCmds[i].cmdID)
  6232. {
  6233. case DVIDM_PRINT:
  6234. case DVIDM_PRINTPREVIEW:
  6235. if (_pmsoctBrowser)
  6236. {
  6237. OLECMD ocButton;
  6238. static const int tbtab[] =
  6239. {
  6240. DVIDM_PRINT,
  6241. DVIDM_FONTS,
  6242. DVIDM_PRINTPREVIEW,
  6243. };
  6244. static const int cttab[] =
  6245. {
  6246. OLECMDID_PRINT,
  6247. OLECMDID_ZOOM,
  6248. OLECMDID_PRINTPREVIEW,
  6249. };
  6250. ocButton.cmdID = SHSearchMapInt(tbtab, cttab, ARRAYSIZE(tbtab), rgCmds[i].cmdID);
  6251. ocButton.cmdf = 0;
  6252. _pmsoctBrowser->QueryStatus(NULL, 1, &ocButton, NULL);
  6253. rgCmds[i].cmdf = ocButton.cmdf;
  6254. }
  6255. break;
  6256. case DVIDM_FONTS: // Always enable for IE5B2
  6257. case DVIDM_CUT:
  6258. case DVIDM_COPY:
  6259. case DVIDM_PASTE:
  6260. case DVIDM_ENCODING:
  6261. rgCmds[i].cmdf = OLECMDF_ENABLED;
  6262. break;
  6263. case DVIDM_SHOWTOOLS:
  6264. if (_ToolsButtonAvailable())
  6265. rgCmds[i].cmdf = OLECMDF_ENABLED;
  6266. break;
  6267. case DVIDM_MAILNEWS:
  6268. if (_MailButtonAvailable())
  6269. rgCmds[i].cmdf = OLECMDF_ENABLED;
  6270. break;
  6271. case DVIDM_DISCUSSIONS:
  6272. // In addition to enabled/disabled, discussions button is checked/unchecked
  6273. rgCmds[i].cmdf = _DiscussionsButtonCmdf();
  6274. break;
  6275. case DVIDM_EDITPAGE:
  6276. if (_psp)
  6277. {
  6278. // Temp code -- forward to itbar
  6279. // itbar edit code is moving here soon
  6280. IExplorerToolbar* pxtb;
  6281. if (SUCCEEDED(_psp->QueryService(SID_SExplorerToolbar, IID_IExplorerToolbar, (void **)&pxtb)))
  6282. {
  6283. OLECMD ocButton = { CITIDM_EDITPAGE, 0 };
  6284. IUnknown_QueryStatus(pxtb, &CGID_PrivCITCommands, 1, &ocButton, NULL);
  6285. rgCmds[i].cmdf = ocButton.cmdf;
  6286. pxtb->Release();
  6287. }
  6288. }
  6289. break;
  6290. }
  6291. }
  6292. }
  6293. hres = S_OK;
  6294. }
  6295. return hres;
  6296. }
  6297. HRESULT CDocObjectHost::QueryStatus(
  6298. /* [unique][in] */ const GUID *pguidCmdGroup,
  6299. /* [in] */ ULONG cCmds,
  6300. /* [out][in][size_is] */ OLECMD rgCmds[ ],
  6301. /* [unique][out][in] */ OLECMDTEXT *pcmdtext)
  6302. {
  6303. HRESULT hres = OLECMDERR_E_UNKNOWNGROUP;
  6304. // Now that BaseBrowser understands that CGID_MSHTML should be directed to the DocObject, we'll
  6305. // get caught in a loop if we send those Execs through here. Cut it off at the pass.
  6306. if (pguidCmdGroup && IsEqualGUID(CGID_MSHTML, *pguidCmdGroup))
  6307. return hres;
  6308. if (_pmsoctBrowser)
  6309. hres = _pmsoctBrowser->QueryStatus(pguidCmdGroup, cCmds, rgCmds, pcmdtext);
  6310. return OnQueryStatus(pguidCmdGroup, cCmds, rgCmds, pcmdtext, hres);
  6311. }
  6312. void CDocObjectHost::_OnSave(void)
  6313. {
  6314. if (_pole && _fFileProtocol)
  6315. {
  6316. IPersistFile * ppf = 0;
  6317. HRESULT hres = _pole->QueryInterface(IID_IPersistFile, (void **)&ppf);
  6318. if (SUCCEEDED(hres))
  6319. {
  6320. LPOLESTR pszDisplayName = NULL;
  6321. hres = _GetCurrentPageW(&pszDisplayName);
  6322. if (SUCCEEDED(hres))
  6323. {
  6324. // fRemember = TRUE for normal case
  6325. hres = ppf->Save(pszDisplayName, !_fCantSaveBack);
  6326. if (FAILED(hres))
  6327. {
  6328. TraceMsg(DM_ERROR, "DOH::_OnSave ppf->Save(psz, FALSE) failed with %x", hres);
  6329. }
  6330. OleFree(pszDisplayName);
  6331. }
  6332. ppf->Release();
  6333. }
  6334. }
  6335. }
  6336. HRESULT CDocObjectHost::_OnContentDisposition()
  6337. {
  6338. HRESULT hr = S_OK;
  6339. TCHAR szURL[MAX_URL_STRING];
  6340. HRESULT hresT;
  6341. hresT = _GetCurrentPage(szURL, ARRAYSIZE(szURL), TRUE);
  6342. if (SUCCEEDED(hresT))
  6343. {
  6344. TCHAR * pszURL;
  6345. UINT uRet;
  6346. IUnknown * punk;
  6347. if (_bsc._pszRedirectedURL && lstrlen(_bsc._pszRedirectedURL))
  6348. {
  6349. pszURL = _bsc._pszRedirectedURL;
  6350. }
  6351. else
  6352. {
  6353. pszURL = szURL;
  6354. }
  6355. hresT = QueryInterface(IID_IUnknown, (void**)&punk);
  6356. if (SUCCEEDED(hresT))
  6357. {
  6358. uRet = OpenSafeOpenDialog(_hwnd, DLG_SAFEOPEN, NULL, pszURL, NULL, NULL, NULL, _uiCP, punk);
  6359. switch(uRet)
  6360. {
  6361. case IDOK:
  6362. //
  6363. // Set this flag to avoid poppping this dialog box twice.
  6364. //
  6365. _fConfirmed = TRUE;
  6366. break; // continue download
  6367. case IDD_SAVEAS:
  6368. CDownLoad_OpenUI(_pmkCur, _bsc._pbc, FALSE, TRUE, NULL, NULL, NULL, NULL, NULL, _bsc._pszRedirectedURL, _uiCP, punk);
  6369. // fall thru to AbortBinding
  6370. case IDCANCEL:
  6371. _CancelPendingNavigation(FALSE);
  6372. hr = E_ABORT;
  6373. break;
  6374. }
  6375. punk->Release();
  6376. }
  6377. }
  6378. return hr;
  6379. }
  6380. void CDocObjectHost::_OnSetProgressPos(DWORD dwPos, DWORD state)
  6381. {
  6382. // trident will reset with -1
  6383. if (dwPos == -1)
  6384. state = PROGRESS_RESET;
  6385. switch(state)
  6386. {
  6387. case PROGRESS_RESET:
  6388. TraceMsg(TF_SHDPROGRESS, "DOH::OnSetProgressPos() RESET, timer = %d", _fProgressTimer);
  6389. if (_fProgressTimer)
  6390. {
  6391. KillTimer(_hwnd, IDTIMER_PROGRESS);
  6392. _fProgressTimer = FALSE;
  6393. }
  6394. if (_dwProgressMax)
  6395. {
  6396. // this will always finish up the progress bar
  6397. // so that when trident doesnt send us the last update
  6398. // we do it anyway
  6399. if (_fProgressTimerFull && dwPos == -2)
  6400. {
  6401. _fProgressTimerFull = FALSE;
  6402. KillTimer(_hwnd, IDTIMER_PROGRESSFULL);
  6403. _dwProgressPos = 0;
  6404. _OnSetProgressMax(0);
  6405. _fShowProgressCtl = FALSE;
  6406. _PlaceProgressBar(TRUE);
  6407. }
  6408. else if (!_fProgressTimerFull)
  6409. {
  6410. _OnSetProgressPos(0, PROGRESS_FULL);
  6411. _fProgressTimerFull = TRUE;
  6412. SetTimer(_hwnd, IDTIMER_PROGRESSFULL, 500, NULL);
  6413. }
  6414. }
  6415. else
  6416. {
  6417. _fShowProgressCtl = FALSE;
  6418. _PlaceProgressBar(TRUE);
  6419. }
  6420. break;
  6421. case PROGRESS_FINDING:
  6422. //this covers the first 10%
  6423. TraceMsg(TF_SHDPROGRESS, "DOH::OnSetProgressPos() FINDING, timer = %d", _fProgressTimer);
  6424. ASSERT(!dwPos);
  6425. if (!_fProgressTimer)
  6426. SetTimer(_hwnd, IDTIMER_PROGRESS, 500, NULL);
  6427. _fProgressTimer = TRUE;
  6428. _OnSetProgressMax(10000);
  6429. _dwProgressInc = PROGRESS_INCREMENT;
  6430. _dwProgressPos = 100;
  6431. _dwProgressTicks = 0;
  6432. _dwProgressMod = (PROGRESS_FINDMAX - _dwProgressPos) / (2 * _dwProgressInc);
  6433. break;
  6434. case PROGRESS_SENDING:
  6435. TraceMsg(TF_SHDPROGRESS, "DOH::OnSetProgressPos() SENDING, timer = %d, dwPos = %d", _fProgressTimer, dwPos);
  6436. ASSERT(!dwPos);
  6437. if (!_fProgressTimer)
  6438. SetTimer(_hwnd, IDTIMER_PROGRESS, 500, NULL);
  6439. _fProgressTimer = TRUE;
  6440. _OnSetProgressMax(10000);
  6441. _dwProgressInc = PROGRESS_INCREMENT;
  6442. _dwProgressTicks = 0;
  6443. //dwProgressPos is already set from FINDING
  6444. _dwProgressMod = (PROGRESS_SENDMAX - _dwProgressPos) / (2 * _dwProgressInc);
  6445. break;
  6446. case PROGRESS_RECEIVING:
  6447. TraceMsg(TF_SHDPROGRESS, "DOH::OnSetProgressPos() RECEIVING, timer = %d, dwPos = %d", _fProgressTimer, dwPos);
  6448. if (_fProgressTimer)
  6449. {
  6450. KillTimer(_hwnd, IDTIMER_PROGRESS);
  6451. _fProgressTimer = FALSE;
  6452. // this is the base spot on the progress bar for trident
  6453. _dwProgressBase = _dwProgressPos / PROGRESS_REBASE;
  6454. TraceMsg(TF_SHDPROGRESS, "DOH::OnSetProgressPos() Rebasing at %d%%", _dwProgressPos * 100/ PROGRESS_TOTALMAX);
  6455. }
  6456. // progress max should be set from outside of here....
  6457. _dwProgressPos = ADJUSTPROGRESSPOS(dwPos);
  6458. break;
  6459. case PROGRESS_TICK:
  6460. if (_fProgressTimer)
  6461. {
  6462. if (_dwProgressInc)
  6463. _dwProgressPos += _dwProgressInc;
  6464. // Else we post the still waiting message...
  6465. //
  6466. if (_dwProgressMod && 0 == (++_dwProgressTicks % _dwProgressMod))
  6467. {
  6468. // this means we are about half way.
  6469. _dwProgressInc /= 2;
  6470. }
  6471. TraceMsg(TF_SHDPROGRESS, "DOH::OnSetProgressPos() TICK, dwPos = %d, ticks = %d, inc = %d", _dwProgressPos, _dwProgressTicks, _dwProgressInc);
  6472. }
  6473. else
  6474. TraceMsg(TF_SHDPROGRESS, "DOH::OnSetProgressPos() TICKNOT");
  6475. break;
  6476. case PROGRESS_FULL:
  6477. {
  6478. _dwProgressPos = _dwProgressMax;
  6479. // if there are script errors, make sure the status
  6480. // bar is properly set (re: icon and text)
  6481. if (_pScriptErrList != NULL &&
  6482. !_pScriptErrList->IsEmpty())
  6483. {
  6484. TCHAR szMsg[MAX_PATH];
  6485. // set the script error icon
  6486. if (g_hiconScriptErr != NULL)
  6487. {
  6488. if (_psb != NULL)
  6489. {
  6490. _psb->SendControlMsg(FCW_STATUS,
  6491. SB_SETICON,
  6492. STATUS_PANE_NAVIGATION,
  6493. (LPARAM)g_hiconScriptErr,
  6494. NULL);
  6495. }
  6496. }
  6497. // set the script error text
  6498. MLLoadString(IDS_DONE_WITH_SCRIPT_ERRORS, szMsg, ARRAYSIZE(szMsg));
  6499. _SetPriorityStatusText(szMsg);
  6500. }
  6501. TraceMsg(TF_SHDPROGRESS, "DOH::OnSetProgressPos() FULL");
  6502. }
  6503. break;
  6504. default:
  6505. ASSERT(FALSE);
  6506. }
  6507. if (_hwndProgress)
  6508. {
  6509. _psb->SendControlMsg(FCW_PROGRESS, PBM_SETPOS, _dwProgressPos, 0, NULL);
  6510. TraceMsg(TF_SHDPROGRESS, "DOH::OnSetProgressPos() updating, pos = %d, %d%% full", _dwProgressPos, _dwProgressMax ? _dwProgressPos * 100/ _dwProgressMax : 0);
  6511. }
  6512. // fire an event that progress has changed
  6513. if (_peds)
  6514. {
  6515. // if we are sent a -1, we must forward the event on so that
  6516. // our host gets it too. some containers rely on this.
  6517. // specifically DevStudio's HTMLHelp
  6518. //
  6519. if (dwPos != -1)
  6520. dwPos = _dwProgressPos;
  6521. if (!_fUIActivatingView)
  6522. {
  6523. FireEvent_DoInvokeDwords(_peds,DISPID_PROGRESSCHANGE,dwPos,_dwProgressMax);
  6524. }
  6525. }
  6526. }
  6527. void CDocObjectHost::_OnSetProgressMax(DWORD dwMax)
  6528. {
  6529. // remember the maximum range so we have it when we want to fire progress events
  6530. if (_dwProgressMax != dwMax && _psb)
  6531. {
  6532. _dwProgressMax = dwMax;
  6533. TraceMsg(TF_SHDPROGRESS, "DOH::OnSetProgressMax() max = %d", _dwProgressMax);
  6534. if (!_hwndProgress) {
  6535. _psb->GetControlWindow(FCW_PROGRESS, &_hwndProgress);
  6536. }
  6537. if (_hwndProgress) {
  6538. _psb->SendControlMsg(FCW_PROGRESS, PBM_SETRANGE32, 0, dwMax, NULL);
  6539. TraceMsg(TF_SHDPROGRESS, "DOH::OnSetProgressMax() updating (%d of %d)", _dwProgressPos, _dwProgressMax);
  6540. }
  6541. else
  6542. TraceMsg(TF_SHDPROGRESS, "DOH::OnSetProgressMax() No hwndProgress");
  6543. }
  6544. }
  6545. UINT CDocObjectHost::_MapCommandID(UINT id, BOOL fToMsoCmd)
  6546. {
  6547. // HEY, this maps OLECMDID commands *only*
  6548. static const UINT s_aicmd[][2] = {
  6549. { DVIDM_PROPERTIES, OLECMDID_PROPERTIES },
  6550. { DVIDM_PRINT, OLECMDID_PRINT },
  6551. { DVIDM_PRINTPREVIEW, OLECMDID_PRINTPREVIEW },
  6552. { DVIDM_PAGESETUP, OLECMDID_PAGESETUP},
  6553. { DVIDM_SAVEASFILE, OLECMDID_SAVEAS },
  6554. { DVIDM_CUT, OLECMDID_CUT },
  6555. { DVIDM_COPY, OLECMDID_COPY },
  6556. { DVIDM_PASTE, OLECMDID_PASTE },
  6557. { DVIDM_REFRESH, OLECMDID_REFRESH },
  6558. { DVIDM_STOPDOWNLOAD, OLECMDID_STOP },
  6559. // subset - above this line document handles
  6560. { DVIDM_OPEN, OLECMDID_OPEN },
  6561. { DVIDM_SAVE, OLECMDID_SAVE },
  6562. { DVIDM_SHOWTOOLS, OLECMDID_HIDETOOLBARS },
  6563. };
  6564. #define CCMD_MAX (sizeof(s_aicmd)/sizeof(s_aicmd[0]))
  6565. UINT iFrom = fToMsoCmd ? 0 : 1;
  6566. for (UINT i = 0; i < CCMD_MAX; i++) {
  6567. if (s_aicmd[i][iFrom]==id) {
  6568. return s_aicmd[i][1-iFrom];
  6569. }
  6570. }
  6571. return (UINT)-1;
  6572. #undef CCMD_MAX
  6573. }
  6574. void CDocObjectHost::_InitToolbarButtons()
  6575. {
  6576. OLECMD acmd[] = {
  6577. { OLECMDID_ZOOM, 0 }, // Notes: This must be the first one
  6578. { OLECMDID_PRINT, 0 },
  6579. { OLECMDID_CUT, 0 },
  6580. { OLECMDID_COPY, 0 },
  6581. { OLECMDID_PASTE, 0 },
  6582. { OLECMDID_REFRESH, 0 },
  6583. { OLECMDID_STOP, 0 }, // Notes: This must be the last one
  6584. };
  6585. if (_pmsot) {
  6586. _pmsot->QueryStatus(NULL, ARRAYSIZE(acmd), acmd, NULL);
  6587. }
  6588. if (_pmsoctBrowser) {
  6589. // the browser may support stop also, so override the document
  6590. // with what the browser says. this is okay because the browser
  6591. // forwards stop back down the chain.
  6592. _pmsoctBrowser->QueryStatus(NULL, 1, &acmd[ARRAYSIZE(acmd)-1], NULL);
  6593. }
  6594. if (_psb)
  6595. {
  6596. for (int i=1; i<ARRAYSIZE(acmd); i++)
  6597. {
  6598. UINT idCmd = _MapFromMso(acmd[i].cmdID);
  6599. _psb->SendControlMsg(FCW_TOOLBAR, TB_ENABLEBUTTON, idCmd,
  6600. (LPARAM)acmd[i].cmdf, NULL);
  6601. }
  6602. }
  6603. // Check if ZOOM command is supported.
  6604. if (acmd[0].cmdf)
  6605. {
  6606. VARIANTARG var;
  6607. VariantInit(&var);
  6608. var.vt = VT_I4;
  6609. var.lVal = 0;
  6610. // get the current zoom depth
  6611. _pmsot->Exec(NULL, OLECMDID_ZOOM, OLECMDEXECOPT_DONTPROMPTUSER, NULL, &var);
  6612. if (var.vt == VT_I4)
  6613. {
  6614. _iZoom = var.lVal;
  6615. }
  6616. else
  6617. {
  6618. VariantClear(&var);
  6619. }
  6620. // get the current zoom range
  6621. var.vt = VT_I4;
  6622. var.lVal = 0;
  6623. _pmsot->Exec(NULL, OLECMDID_GETZOOMRANGE, OLECMDEXECOPT_DONTPROMPTUSER, NULL, &var);
  6624. if (var.vt == VT_I4)
  6625. {
  6626. _iZoomMin = (int)(short)LOWORD(var.lVal);
  6627. _iZoomMax = (int)(short)HIWORD(var.lVal);
  6628. }
  6629. else
  6630. {
  6631. VariantClear(&var);
  6632. }
  6633. }
  6634. }
  6635. void CDocObjectHost::_OnSetStatusText(VARIANTARG* pvarIn)
  6636. {
  6637. LPCWSTR pwch = VariantToStrCast(pvarIn);
  6638. if (pwch && _psb)
  6639. {
  6640. IShellView *psvActive;
  6641. _psb->QueryActiveShellView(&psvActive);
  6642. if (psvActive)
  6643. {
  6644. // Suppress sending status messages if we aren't the active view - else
  6645. // we could be reporting nasties from unapproved PICS pages
  6646. if (IsSameObject(_psv, psvActive))
  6647. {
  6648. TCHAR szHint[256];
  6649. if (pwch)
  6650. SHUnicodeToTChar(pwch, szHint, ARRAYSIZE(szHint));
  6651. else
  6652. szHint[0] = 0;
  6653. _SetStatusText(szHint);
  6654. }
  6655. psvActive->Release();
  6656. }
  6657. }
  6658. }
  6659. //
  6660. // This function returns TRUE if
  6661. // (1) the DocObject supports IPersistFile and
  6662. // (2) IPersistFile::IsDirty returns S_OK.
  6663. // Caller may pass pppf to retrieve IPersistFile*, which will be AddRef'ed
  6664. // and returned only when this function returns TRUE.
  6665. //
  6666. BOOL CDocObjectHost::_IsDirty(IPersistFile** pppf)
  6667. {
  6668. BOOL fDirty = FALSE; // Assume non-dirty
  6669. if (pppf)
  6670. *pppf = NULL;
  6671. if (_pole)
  6672. {
  6673. IPersistFile* ppf;
  6674. HRESULT hresT = _pole->QueryInterface(IID_PPV_ARG(IPersistFile, &ppf));
  6675. if (SUCCEEDED(hresT))
  6676. {
  6677. if (ppf->IsDirty()==S_OK)
  6678. {
  6679. fDirty = TRUE;
  6680. if (pppf)
  6681. {
  6682. *pppf = ppf;
  6683. ppf->AddRef();
  6684. }
  6685. }
  6686. ppf->Release();
  6687. }
  6688. }
  6689. return fDirty;
  6690. }
  6691. void CDocObjectHost::_OnSetTitle(VARIANTARG *pvTitle)
  6692. {
  6693. LPCWSTR pwch = VariantToStrCast(pvTitle);
  6694. if (pwch)
  6695. {
  6696. if (_pwb)
  6697. {
  6698. _pwb->SetTitle(_psv, pwch);
  6699. }
  6700. }
  6701. // tell our parent DocObjectView about this as well
  6702. if (_pdvs)
  6703. _pdvs->OnSetTitle(pvTitle);
  6704. }
  6705. void CDocObjectHost::_OnCodePageChange(const VARIANTARG* pvarargIn)
  6706. {
  6707. if (pvarargIn && pvarargIn->vt == VT_I4)
  6708. {
  6709. TraceMsg(DM_DOCCP, "CDOH::OnExec SHDVID_ONCOEPAGECHANGE got %d", pvarargIn->lVal);
  6710. VARIANT var = *pvarargIn;
  6711. //
  6712. // Since the UI (View->Fond) does not say "default codepage",
  6713. // we don't need to be smart about it.
  6714. //
  6715. // if ((UINT)var.lVal == GetACP()) {
  6716. // var.lVal = CP_ACP;
  6717. // }
  6718. //
  6719. // Change the 'current' codepage.
  6720. //
  6721. IBrowserService *pbs;
  6722. if (SUCCEEDED(QueryService(SID_STopLevelBrowser, IID_PPV_ARG(IBrowserService, &pbs))))
  6723. {
  6724. pbs->GetSetCodePage(&var, NULL);
  6725. pbs->Release();
  6726. }
  6727. //
  6728. // Write the codepage to the URL history
  6729. //
  6730. IUniformResourceLocator * purl = NULL;
  6731. HRESULT hresT = CoCreateInstance(CLSID_InternetShortcut, NULL,
  6732. CLSCTX_INPROC_SERVER,
  6733. IID_PPV_ARG(IUniformResourceLocator, &purl));
  6734. if (SUCCEEDED(hresT))
  6735. {
  6736. TCHAR szURL[MAX_URL_STRING];
  6737. _GetCurrentPage(szURL, ARRAYSIZE(szURL), TRUE);
  6738. _ValidateURL(szURL, UQF_DEFAULT);
  6739. hresT = purl->SetURL(szURL, 0);
  6740. if (SUCCEEDED(hresT))
  6741. {
  6742. IPropertySetStorage *ppropsetstg;
  6743. hresT = purl->QueryInterface(IID_PPV_ARG(IPropertySetStorage, &ppropsetstg));
  6744. if (SUCCEEDED(hresT))
  6745. {
  6746. IPropertyStorage *ppropstg;
  6747. hresT = ppropsetstg->Open(FMTID_InternetSite, STGM_READWRITE, &ppropstg);
  6748. if (SUCCEEDED(hresT))
  6749. {
  6750. const static PROPSPEC c_aprop[] = {
  6751. { PRSPEC_PROPID, PID_INTSITE_CODEPAGE},
  6752. };
  6753. PROPVARIANT prvar = { 0 };
  6754. prvar.vt = VT_UI4;
  6755. prvar.lVal = var.lVal;
  6756. hresT = ppropstg->WriteMultiple(1, c_aprop, &prvar, 0);
  6757. TraceMsg(DM_DOCCP, "CDOH::_OnCodePageChange WriteMultile returned %x", hresT);
  6758. ppropstg->Commit(STGC_DEFAULT);
  6759. ppropstg->Release();
  6760. }
  6761. else
  6762. {
  6763. TraceMsg(DM_WARNING, "CDOH::_OnCodePageChange Open failed %x", hresT);
  6764. }
  6765. ppropsetstg->Release();
  6766. }
  6767. else
  6768. {
  6769. TraceMsg(DM_WARNING, "CDOH::_OnCodePageChange QI failed %x", hresT);
  6770. }
  6771. }
  6772. else
  6773. {
  6774. TraceMsg(DM_WARNING, "CDOH::_OnCodePageChange SetURL failed %x", hresT);
  6775. }
  6776. purl->Release();
  6777. }
  6778. else
  6779. {
  6780. TraceMsg(DM_WARNING, "CDOH::_OnCodePageChange CoCreate failed %x", hresT);
  6781. }
  6782. }
  6783. else
  6784. {
  6785. ASSERT(0);
  6786. }
  6787. }
  6788. void CDocObjectHost::_MappedBrowserExec(DWORD nCmdID, DWORD nCmdexecopt)
  6789. {
  6790. if (_pmsoctBrowser)
  6791. {
  6792. DWORD nCmdIDCT = _MapToMso(nCmdID);
  6793. ASSERT(nCmdIDCT != -1); // if this rips, need to add missing case to _MapCommandID
  6794. OLECMD rgcmd = {nCmdIDCT, 0};
  6795. // Trident sometimes executes commands that are disabled (cut, paste) so
  6796. // ensure that the command is enabled first
  6797. BOOL fEnabled = (S_OK == _pmsoctBrowser->QueryStatus(NULL, 1, &rgcmd, NULL)) &&
  6798. (rgcmd.cmdf & OLECMDF_ENABLED);
  6799. // APPHACK - 80104 Visio doesn't return OLECMDF_ENABLED, but we need to
  6800. // be able to execute the command to show the toolbars because they start off hidden.
  6801. if (!fEnabled && (nCmdID == DVIDM_SHOWTOOLS) &&
  6802. (_GetAppHack() & BROWSERFLAG_ENABLETOOLSBTN))
  6803. {
  6804. fEnabled = TRUE;
  6805. }
  6806. if (fEnabled)
  6807. {
  6808. _pmsoctBrowser->Exec(NULL, nCmdIDCT, nCmdexecopt, NULL, NULL);
  6809. }
  6810. }
  6811. }
  6812. HRESULT CDocObjectHost::OnExec(const GUID *pguidCmdGroup, DWORD nCmdID, DWORD nCmdexecopt, VARIANTARG *pvarargIn, VARIANTARG *pvarargOut)
  6813. {
  6814. if (pguidCmdGroup == NULL)
  6815. {
  6816. // _InitToolbarButtons and _OnSetStatusText reference _psb directly
  6817. if (!_psb)
  6818. return E_FAIL;
  6819. switch (nCmdID)
  6820. {
  6821. //
  6822. // The containee has found an http-equiv meta tag; handle it
  6823. // appropriately (client pull, PICS, etc)
  6824. //
  6825. case OLECMDID_HTTPEQUIV:
  6826. case OLECMDID_HTTPEQUIV_DONE:
  6827. if (_pwb)
  6828. {
  6829. _pwb->OnHttpEquiv(_psv, (nCmdID == OLECMDID_HTTPEQUIV_DONE), pvarargIn, pvarargOut);
  6830. // Always return S_OK so that we don't try other codepath.
  6831. }
  6832. return S_OK;
  6833. case OLECMDID_PREREFRESH:
  6834. _fShowProgressCtl = TRUE;
  6835. _PlaceProgressBar(TRUE);
  6836. _OnSetProgressPos(0, PROGRESS_FINDING);
  6837. if (IsGlobalOffline())
  6838. {
  6839. // This is pointing to a web address and we're offline
  6840. // Ask the user if (s)he wants to go online
  6841. TCHAR szURL[MAX_URL_STRING];
  6842. if (SUCCEEDED(_GetCurrentPage(szURL, ARRAYSIZE(szURL), TRUE)) &&
  6843. UrlHitsNet(szURL))
  6844. {
  6845. if (InternetGoOnline(szURL, _hwnd, TRUE) && _psb)
  6846. {
  6847. // Tell all browser windows to update their title and status pane
  6848. SendShellIEBroadcastMessage(WM_WININICHANGE,0,0, 1000);
  6849. }
  6850. }
  6851. }
  6852. return S_OK;
  6853. case OLECMDID_REFRESH:
  6854. if (_pmsot)
  6855. _pmsot->Exec(pguidCmdGroup, nCmdID, nCmdexecopt, pvarargIn, pvarargOut);
  6856. return S_OK;
  6857. case OLECMDID_OPEN:
  6858. _OnOpen();
  6859. return S_OK;
  6860. case OLECMDID_SAVE:
  6861. _OnSave();
  6862. return S_OK;
  6863. case OLECMDID_CLOSE:
  6864. _OnClose();
  6865. return S_OK;
  6866. case OLECMDID_UPDATECOMMANDS:
  6867. _InitToolbarButtons();
  6868. return E_FAIL; // lie and say we don't do anything to forward the command on
  6869. case OLECMDID_SETPROGRESSMAX:
  6870. ASSERT(pvarargIn->vt == VT_I4);
  6871. TraceMsg(TF_SHDPROGRESS, "DOH::Exec() SETPROGRESSMAX = %d", pvarargIn->lVal );
  6872. if (pvarargIn->lVal)
  6873. _OnSetProgressMax(ADJUSTPROGRESSMAX((DWORD) pvarargIn->lVal));
  6874. return S_OK;
  6875. case OLECMDID_SETPROGRESSPOS:
  6876. ASSERT(pvarargIn->vt == VT_I4);
  6877. TraceMsg(TF_SHDPROGRESS, "DOH::Exec() SETPROGRESSPOS = %d", pvarargIn->lVal );
  6878. if (pvarargIn->lVal)
  6879. _OnSetProgressPos((DWORD) pvarargIn->lVal, PROGRESS_RECEIVING);
  6880. return S_OK;
  6881. case OLECMDID_SETPROGRESSTEXT:
  6882. _OnSetStatusText(pvarargIn);
  6883. return S_OK;
  6884. case OLECMDID_SETTITLE:
  6885. if (!pvarargIn)
  6886. return E_INVALIDARG;
  6887. _OnSetTitle(pvarargIn); // We are guaranteed to get atleast 1 OLECMDID_SETTITLE.
  6888. return S_OK;
  6889. // case OLECMDID_PRINT:
  6890. // In the up direction, this case is handled by the outermost frame as
  6891. // a request to print from the docobj. It handles it by sending an OLECMDID_PRINT
  6892. // back to the docobj to print. (Or, as in Binder, to all the docobjects.)
  6893. default:
  6894. return OLECMDERR_E_NOTSUPPORTED;
  6895. }
  6896. }
  6897. else if (IsEqualGUID(CGID_ShellDocView, *pguidCmdGroup))
  6898. {
  6899. switch (nCmdID)
  6900. {
  6901. case SHDVID_SSLSTATUS:
  6902. {
  6903. // Ask the user if (s)he wants to go online
  6904. TCHAR szURL[MAX_URL_STRING];
  6905. if (SUCCEEDED(_GetCurrentPage(szURL, ARRAYSIZE(szURL), TRUE)))
  6906. {
  6907. if (_bsc._pszRedirectedURL && *_bsc._pszRedirectedURL)
  6908. StrCpyN(szURL, _bsc._pszRedirectedURL, ARRAYSIZE(szURL));
  6909. ULONG_PTR uCookie = 0;
  6910. SHActivateContext(&uCookie);
  6911. InternetShowSecurityInfoByURL(szURL, _hwnd);
  6912. if (uCookie)
  6913. {
  6914. SHDeactivateContext(uCookie);
  6915. }
  6916. }
  6917. break;
  6918. }
  6919. case SHDVID_ZONESTATUS:
  6920. {
  6921. // Load the current url into the properties page
  6922. if (!SHRestricted2W(REST_NoBrowserOptions, NULL, 0))
  6923. {
  6924. TCHAR szBuf[MAX_URL_STRING];
  6925. _GetCurrentPage(szBuf, ARRAYSIZE(szBuf));
  6926. ULONG_PTR uCookie = 0;
  6927. SHActivateContext(&uCookie);
  6928. ZoneConfigureW(_hwnd, szBuf);
  6929. if (uCookie)
  6930. {
  6931. SHDeactivateContext(uCookie);
  6932. }
  6933. }
  6934. return S_OK;
  6935. }
  6936. case SHDVID_PRIVACYSTATUS:
  6937. {
  6938. IEnumPrivacyRecords *pEnum = NULL;
  6939. LPOLESTR pszName = NULL;
  6940. BOOL fReportAllSites = (nCmdexecopt == TRUE);
  6941. if(_pmkCur)
  6942. {
  6943. if(FAILED(_pmkCur->GetDisplayName(_pbcCur, NULL, &pszName)))
  6944. {
  6945. pszName = NULL;
  6946. }
  6947. }
  6948. if(_psp && SUCCEEDED(_psp->QueryService(IID_IEnumPrivacyRecords, IID_IEnumPrivacyRecords, (void **)&(pEnum))))
  6949. {
  6950. BOOL fImpacted;
  6951. if(fReportAllSites ||
  6952. (SUCCEEDED(pEnum->GetPrivacyImpacted(&fImpacted)) && fImpacted))
  6953. {
  6954. DoPrivacyDlg(_hwnd, pszName, pEnum, fReportAllSites);
  6955. }
  6956. pEnum->Release();
  6957. }
  6958. if(pszName)
  6959. {
  6960. OleFree(pszName);
  6961. }
  6962. return S_OK;
  6963. }
  6964. case SHDVID_QUERYMERGEDHELPMENU:
  6965. if (_hmenuMergedHelp)
  6966. {
  6967. pvarargOut->vt = VT_INT_PTR;
  6968. pvarargOut->byref = _hmenuMergedHelp;
  6969. return S_OK;
  6970. }
  6971. return S_FALSE;
  6972. case SHDVID_QUERYOBJECTSHELPMENU:
  6973. if (_hmenuObjHelp)
  6974. {
  6975. pvarargOut->vt = VT_INT_PTR;
  6976. pvarargOut->byref = _hmenuObjHelp;
  6977. return S_OK;
  6978. }
  6979. return S_FALSE;
  6980. case SHDVID_GETSYSIMAGEINDEX:
  6981. if (_dwAppHack & BROWSERFLAG_MSHTML) {
  6982. ASSERT(pvarargOut->vt==0);
  6983. pvarargOut->vt = VT_I4;
  6984. pvarargOut->lVal = _GetIEHTMLImageIndex();
  6985. return S_OK;
  6986. }
  6987. return E_FAIL;
  6988. case SHDVID_AMBIENTPROPCHANGE:
  6989. // An ambient property above us has changed, let the docobj know
  6990. if (_pmsoc)
  6991. {
  6992. ASSERT(pvarargIn->vt == VT_I4);
  6993. return(_pmsoc->OnAmbientPropertyChange(pvarargIn->lVal));
  6994. }
  6995. return E_FAIL;
  6996. case SHDVID_CANDOCOLORSCHANGE:
  6997. return IUnknown_Exec(_pole, pguidCmdGroup, nCmdID, nCmdexecopt, pvarargIn, pvarargOut);
  6998. case SHDVID_ONCOLORSCHANGE:
  6999. // this comes from trident and needs passing back up to our parent ...
  7000. if ( _pmsoctBrowser )
  7001. {
  7002. return _pmsoctBrowser->Exec( pguidCmdGroup, nCmdID, nCmdexecopt, pvarargIn, pvarargOut );
  7003. }
  7004. else
  7005. return E_FAIL;
  7006. case SHDVID_GETOPTIONSHWND:
  7007. if ( _pmsoctBrowser )
  7008. {
  7009. return _pmsoctBrowser->Exec( pguidCmdGroup, nCmdID, nCmdexecopt, pvarargIn, pvarargOut );
  7010. }
  7011. else
  7012. {
  7013. return E_FAIL;
  7014. }
  7015. case SHDVID_DOCWRITEABORT:
  7016. // pending DocObject wants to us to abort any binding and activate
  7017. // it directly
  7018. if (_bsc._pib && _bsc._fBinding && _punkPending && !_pole)
  7019. {
  7020. _bsc._fDocWriteAbort = 1;
  7021. _bsc.OnObjectAvailable(IID_IUnknown, _punkPending);
  7022. _bsc.AbortBinding();
  7023. }
  7024. // report READYSTATE_COMPLETE so that when document.open() falls
  7025. // back to READYSTATE_INTERACTIVE Trident doesn't get confused...
  7026. //
  7027. // chrisfra 4/15/97, is this the only way to force TRIDENT
  7028. // to not lose fact of download complete when document.open()
  7029. // falls back to READYSTATE_INTERACTIVE.
  7030. //
  7031. // During the above OnObjectAvailable call, we fire a READYSTATE_COMPLETE
  7032. // event if (1) object doesn't support it or (2) object already at it.
  7033. // (Neither of these should be the case, but we should be careful, eh?)
  7034. // We want to force a READYSTATE_COMPLETE here in other cases, so unhook
  7035. // the IPropertyNotifySink (to prevent multiple _COMPLETE events). If we
  7036. // unhook the sink, then we didn't fire _COMPLETE above, so fire it now.
  7037. //
  7038. if (_dwPropNotifyCookie)
  7039. {
  7040. _OnReadyState(READYSTATE_COMPLETE);
  7041. }
  7042. return S_OK;
  7043. case SHDVID_CANACTIVATENOW:
  7044. {
  7045. HRESULT hres = (_PicsProcBase._fPicsAccessAllowed && !_PicsProcBase._fbPicsWaitFlags && _pole && _fReadystateInteractiveProcessed) ? S_OK : S_FALSE;
  7046. TraceMsg(DM_PICS, "CDOH::OnExec(SHDVID_CANACTIVATENOW) returning %ls", (hres == S_OK) ? "S_OK" : "S_FALSE");
  7047. return hres;
  7048. }
  7049. case SHDVID_SETSECURELOCK:
  7050. {
  7051. //
  7052. // if we are already active, then we need to go ahead
  7053. // and forward this up the browser. otherwise, cache it
  7054. // and wait until activated to forward it
  7055. //
  7056. TraceMsg(DM_SSL, "[%X]DOH::Exec() SETSECURELOCK lock = %d", this, pvarargIn->lVal);
  7057. _fSetSecureLock = TRUE;
  7058. _eSecureLock = pvarargIn->lVal;
  7059. IShellView *psvActive;
  7060. if (_psb && SUCCEEDED(_psb->QueryActiveShellView(&psvActive) ))
  7061. {
  7062. if (psvActive && IsSameObject(_psv, psvActive))
  7063. _ForwardSetSecureLock(pvarargIn->lVal);
  7064. ATOMICRELEASE(psvActive);
  7065. }
  7066. return S_OK;
  7067. }
  7068. case SHDVID_FORWARDSECURELOCK:
  7069. _ForwardSetSecureLock(_fSetSecureLock ? _eSecureLock : SECURELOCK_SET_UNSECURE);
  7070. return S_OK;
  7071. case SHDVID_ONCODEPAGECHANGE:
  7072. _OnCodePageChange(pvarargIn);
  7073. return S_OK;
  7074. case SHDVID_DISPLAYSCRIPTERRORS:
  7075. case SHDVID_NAVIGATIONSTATUS:
  7076. {
  7077. // if we're a weboc then this script err list should be null
  7078. ASSERT(!_fWebOC || _pScriptErrList == NULL);
  7079. if (_pScriptErrList != NULL && !_pScriptErrList->IsEmpty())
  7080. {
  7081. // do the script error info dialog
  7082. _ScriptErr_Dlg(TRUE);
  7083. }
  7084. return S_OK;
  7085. }
  7086. break;
  7087. case SHDVID_RESETSTATUSBAR:
  7088. {
  7089. _ResetStatusBar();
  7090. return S_OK;
  7091. }
  7092. break;
  7093. default:
  7094. return OLECMDERR_E_NOTSUPPORTED;
  7095. }
  7096. }
  7097. else if (IsEqualGUID(CGID_Explorer, *pguidCmdGroup))
  7098. {
  7099. switch (nCmdID) {
  7100. case SBCMDID_MAYSAVECHANGES:
  7101. return _OnMaySaveChanges();
  7102. case SBCMDID_GETPANE:
  7103. switch(nCmdexecopt)
  7104. {
  7105. case PANE_NAVIGATION:
  7106. V_I4(pvarargOut) = STATUS_PANE_NAVIGATION;
  7107. return S_OK;
  7108. case PANE_PROGRESS:
  7109. V_I4(pvarargOut) = STATUS_PANE_PROGRESS;
  7110. return S_OK;
  7111. case PANE_ZONE:
  7112. V_I4(pvarargOut) = STATUS_PANE_ZONE;
  7113. return S_OK;
  7114. case PANE_OFFLINE:
  7115. V_I4(pvarargOut) = STATUS_PANE_OFFLINE;
  7116. return S_OK;
  7117. case PANE_PRINTER:
  7118. V_I4(pvarargOut) = STATUS_PANE_PRINTER;
  7119. return S_OK;
  7120. case PANE_SSL:
  7121. V_I4(pvarargOut) = STATUS_PANE_SSL;
  7122. return S_OK;
  7123. case PANE_PRIVACY:
  7124. V_I4(pvarargOut) = STATUS_PANE_PRIVACY;
  7125. return S_OK;
  7126. default:
  7127. V_I4(pvarargOut) = PANE_NONE;
  7128. return S_OK;
  7129. }
  7130. case SBCMDID_ONCLOSE:
  7131. _fClosing = TRUE;
  7132. return S_OK;
  7133. default:
  7134. return OLECMDERR_E_NOTSUPPORTED;
  7135. } // switch
  7136. }
  7137. else if (IsEqualGUID(CGID_DocHostCommandHandler, *pguidCmdGroup))
  7138. {
  7139. switch(nCmdID)
  7140. {
  7141. case OLECMDID_SAVEAS:
  7142. _OnSaveAs();
  7143. return S_OK;
  7144. case OLECMDID_SHOWSCRIPTERROR:
  7145. {
  7146. HRESULT hr;
  7147. hr = S_OK;
  7148. if (_fWebOC)
  7149. {
  7150. // we're a web oc.
  7151. // pass the handling of this script error to
  7152. // an appropriate CDocHostUIHandler
  7153. if (_pWebOCUIHandler != NULL)
  7154. {
  7155. IOleCommandTarget * pioct;
  7156. ASSERT(IS_VALID_CODE_PTR(_pWebOCUIHandler, IDocHostUIHandler));
  7157. hr = _pWebOCUIHandler->QueryInterface(IID_IOleCommandTarget, (void **) &pioct);
  7158. if (SUCCEEDED(hr))
  7159. {
  7160. hr = pioct->Exec(pguidCmdGroup, nCmdID, nCmdexecopt, pvarargIn, pvarargOut);
  7161. pioct->Release();
  7162. }
  7163. }
  7164. else
  7165. {
  7166. hr = _dhUIHandler.Exec(pguidCmdGroup, nCmdID, nCmdexecopt, pvarargIn, pvarargOut);
  7167. }
  7168. }
  7169. else
  7170. {
  7171. ASSERT(IS_VALID_READ_PTR(pvarargIn, VARIANTARG));
  7172. ASSERT(IS_VALID_WRITE_PTR(pvarargOut, VARIANTARG));
  7173. // we're not a web oc so we have to handle this
  7174. // ourselves, so cache the errors for later
  7175. // display in the new script error dialog
  7176. if (pvarargIn == NULL || pvarargOut == NULL)
  7177. {
  7178. hr = E_INVALIDARG;
  7179. }
  7180. if (SUCCEEDED(hr))
  7181. {
  7182. if (_pScriptErrList == NULL)
  7183. {
  7184. // create a new script error list
  7185. _pScriptErrList = new CScriptErrorList;
  7186. if (_pScriptErrList == NULL)
  7187. {
  7188. hr = E_OUTOFMEMORY;
  7189. }
  7190. }
  7191. if (SUCCEEDED(hr))
  7192. {
  7193. TCHAR szMsg[MAX_PATH];
  7194. // stuff the error icon into the status bar
  7195. if (g_hiconScriptErr != NULL)
  7196. {
  7197. if (_psb != NULL)
  7198. {
  7199. _psb->SendControlMsg(FCW_STATUS,
  7200. SB_SETICON,
  7201. STATUS_PANE_NAVIGATION,
  7202. (LPARAM)g_hiconScriptErr,
  7203. NULL);
  7204. }
  7205. }
  7206. // stuff the error text into the status bar
  7207. MLLoadString(IDS_SCRIPT_ERROR_ON_PAGE, szMsg, ARRAYSIZE(szMsg));
  7208. _SetPriorityStatusText(szMsg);
  7209. // stuff the error data into the cache
  7210. _ScriptErr_CacheInfo(pvarargIn);
  7211. // pop up the dialog
  7212. _ScriptErr_Dlg(FALSE);
  7213. V_VT(pvarargOut) = VT_BOOL;
  7214. if (_pScriptErrList->IsFull())
  7215. {
  7216. // stop running scripts
  7217. V_BOOL(pvarargOut) = VARIANT_FALSE;
  7218. }
  7219. else
  7220. {
  7221. // keep running scripts
  7222. V_BOOL(pvarargOut) = VARIANT_TRUE;
  7223. }
  7224. }
  7225. }
  7226. }
  7227. return hr;
  7228. }
  7229. break;
  7230. case OLECMDID_SHOWMESSAGE:
  7231. case OLECMDID_SHOWFIND:
  7232. case OLECMDID_SHOWPAGESETUP:
  7233. case OLECMDID_SHOWPRINT:
  7234. case OLECMDID_PROPERTIES:
  7235. {
  7236. return _dhUIHandler.Exec(pguidCmdGroup, nCmdID, nCmdexecopt, pvarargIn, pvarargOut);
  7237. }
  7238. break;
  7239. //
  7240. // Refresh the original page if an error page is dispalyed.
  7241. //
  7242. case IDM_REFRESH:
  7243. case IDM_REFRESH_TOP:
  7244. case IDM_REFRESH_TOP_FULL:
  7245. case IDM_REFRESH_THIS:
  7246. case IDM_REFRESH_THIS_FULL:
  7247. {
  7248. HRESULT hr = OLECMDERR_E_NOTSUPPORTED;
  7249. if (_pScriptErrList != NULL)
  7250. {
  7251. // clear out the script error list
  7252. _pScriptErrList->ClearErrorList();
  7253. _SetPriorityStatusText(NULL);
  7254. // reset the text and icon
  7255. _ResetStatusBar();
  7256. }
  7257. //
  7258. // If there is a refresh url for this object use it for the refresh.
  7259. // Otherwise fall through and let the client handle it.
  7260. //
  7261. if (_pwszRefreshUrl)
  7262. {
  7263. _fRefresh = TRUE;
  7264. _DoAsyncNavigation(_pwszRefreshUrl);
  7265. hr = S_OK;
  7266. }
  7267. else
  7268. {
  7269. //
  7270. // Non http errors (syntax, DNS, etc) are handled by a async nav
  7271. // to res://shdocvw/error.htm#originalurl. Handle the refresh
  7272. // for those pages here.
  7273. //
  7274. if (_pmkCur)
  7275. {
  7276. LPOLESTR pstrUrl;
  7277. if (SUCCEEDED(_pmkCur->GetDisplayName(_pbcCur, NULL, &pstrUrl)))
  7278. {
  7279. if (IsErrorUrl(pstrUrl) && _pszLocation && *_pszLocation)
  7280. {
  7281. //
  7282. // The error url has the form:
  7283. // "res://shdocvw.dll/http404.htm#http://foo.bar"
  7284. // Where foo.bar is the the url the user tried to navigate to.
  7285. // _pszLocation points to "#foo.bar"
  7286. DWORD dwScheme = GetUrlScheme(_pszLocation + 1);
  7287. BOOL fDoNavigation = ((URL_SCHEME_HTTP == dwScheme) ||
  7288. (URL_SCHEME_HTTPS == dwScheme) ||
  7289. (URL_SCHEME_FTP == dwScheme) ||
  7290. (URL_SCHEME_GOPHER == dwScheme));
  7291. //
  7292. if (fDoNavigation) // otherwise it's a security problem !
  7293. {
  7294. _fRefresh = TRUE;
  7295. _DoAsyncNavigation(_pszLocation + 1);
  7296. }
  7297. hr = S_OK;
  7298. }
  7299. OleFree(pstrUrl);
  7300. }
  7301. }
  7302. }
  7303. return hr;
  7304. break;
  7305. }
  7306. default:
  7307. return OLECMDERR_E_NOTSUPPORTED;
  7308. }
  7309. }
  7310. else if (IsEqualGUID(*pguidCmdGroup, CLSID_InternetButtons) ||
  7311. IsEqualGUID(*pguidCmdGroup, CLSID_MSOButtons))
  7312. {
  7313. UEMFireEvent(&UEMIID_BROWSER, UEME_UITOOLBAR, UEMF_XEVENT, UIG_OTHER, nCmdID);
  7314. if (nCmdexecopt == OLECMDEXECOPT_PROMPTUSER) {
  7315. // the user hit the drop down
  7316. if (_pmsoctBrowser && pvarargIn && pvarargIn->vt == VT_INT_PTR)
  7317. {
  7318. // v.vt = VT_INT_PTR;
  7319. POINT pt;
  7320. RECT* prc = (RECT*)pvarargIn->byref;
  7321. pt.x = prc->left;
  7322. pt.y = prc->bottom;
  7323. switch (nCmdID)
  7324. {
  7325. case DVIDM_MAILNEWS:
  7326. {
  7327. VARIANTARG v = {VT_I4};
  7328. v.lVal = MAKELONG(prc->left, prc->bottom);
  7329. _pmsoctBrowser->Exec(&CGID_Explorer, SBCMDID_DOMAILMENU, 0, &v, NULL);
  7330. break;
  7331. }
  7332. case DVIDM_FONTS:
  7333. {
  7334. VARIANTARG v = {VT_I4};
  7335. v.lVal = MAKELONG(prc->left, prc->bottom);
  7336. _pmsoctBrowser->Exec(&CGID_ShellDocView, SHDVID_FONTMENUOPEN, 0, &v, NULL);
  7337. break;
  7338. }
  7339. case DVIDM_ENCODING:
  7340. {
  7341. VARIANTARG v = {VT_I4};
  7342. v.lVal = MAKELONG(prc->left, prc->bottom);
  7343. _pmsoctBrowser->Exec(&CGID_ShellDocView, SHDVID_MIMECSETMENUOPEN, 0, &v, NULL);
  7344. break;
  7345. }
  7346. }
  7347. }
  7348. return S_OK;
  7349. }
  7350. // CommandIDs from DVIDM_MENUEXT_FIRST to DVIDM_MENUEXT_LAST are reserved for toolbar extension buttons
  7351. // Do NOT use this range for constants within the scope of CLSID_InternetButtons/CLSID_MSOButtons!
  7352. if (InRange(nCmdID, DVIDM_MENUEXT_FIRST, DVIDM_MENUEXT_LAST))
  7353. {
  7354. IUnknown_Exec(_pBrowsExt, &CLSID_ToolbarExtButtons, nCmdID, nCmdexecopt, pvarargIn, pvarargOut);
  7355. }
  7356. else
  7357. {
  7358. switch(nCmdID) {
  7359. case DVIDM_DISCUSSIONS:
  7360. if (_pmsoctBrowser)
  7361. _pmsoctBrowser->Exec(&CGID_Explorer, SBCMDID_DISCUSSIONBAND, OLECMDEXECOPT_DONTPROMPTUSER, NULL, NULL);
  7362. break;
  7363. case DVIDM_CUT:
  7364. case DVIDM_COPY:
  7365. case DVIDM_PASTE:
  7366. _MappedBrowserExec(nCmdID, 0);
  7367. break;
  7368. case DVIDM_PRINT:
  7369. case DVIDM_PRINTPREVIEW:
  7370. case DVIDM_SHOWTOOLS:
  7371. _MappedBrowserExec(nCmdID, OLECMDEXECOPT_DONTPROMPTUSER);
  7372. break;
  7373. case DVIDM_EDITPAGE:
  7374. if (_psp) {
  7375. // temp code -- forward to itbar
  7376. // itbar edit code is moving here soon
  7377. IExplorerToolbar* pxtb;
  7378. if (SUCCEEDED(_psp->QueryService(SID_SExplorerToolbar, IID_IExplorerToolbar, (void **)&pxtb))) {
  7379. IUnknown_Exec(pxtb, &CGID_PrivCITCommands, CITIDM_EDITPAGE, nCmdexecopt, pvarargIn, pvarargOut);
  7380. pxtb->Release();
  7381. }
  7382. }
  7383. break;
  7384. }
  7385. }
  7386. return S_OK;
  7387. }
  7388. else if (IsEqualGUID(IID_IExplorerToolbar, *pguidCmdGroup))
  7389. {
  7390. switch (nCmdID)
  7391. {
  7392. case ETCMDID_GETBUTTONS:
  7393. {
  7394. int nNumExtButtons = 0;
  7395. if (_pBrowsExt)
  7396. {
  7397. _pBrowsExt->GetNumButtons((UINT*)&nNumExtButtons);
  7398. }
  7399. int nNumButtons = nNumExtButtons + ARRAYSIZE(c_tbStd);
  7400. if ((_nNumButtons != nNumButtons) && (_ptbStd != NULL))
  7401. {
  7402. delete [] _ptbStd;
  7403. _ptbStd = NULL;
  7404. }
  7405. if (_ptbStd == NULL)
  7406. {
  7407. _ptbStd = new TBBUTTON[nNumButtons];
  7408. if (_ptbStd == NULL)
  7409. {
  7410. return E_OUTOFMEMORY;
  7411. }
  7412. _nNumButtons = nNumButtons;
  7413. }
  7414. memcpy(_ptbStd, c_tbStd, SIZEOF(TBBUTTON) * ARRAYSIZE(c_tbStd));
  7415. // Init the string ids
  7416. ASSERT(_ptbStd[6].idCommand == DVIDM_CUT);
  7417. ASSERT(_ptbStd[7].idCommand == DVIDM_COPY);
  7418. ASSERT(_ptbStd[8].idCommand == DVIDM_PASTE);
  7419. ASSERT(_ptbStd[9].idCommand == DVIDM_ENCODING);
  7420. ASSERT(_ptbStd[10].idCommand == DVIDM_PRINTPREVIEW);
  7421. if (-1 != _iString)
  7422. {
  7423. _ptbStd[6].iString = _iString;
  7424. _ptbStd[7].iString = _iString + 1;
  7425. _ptbStd[8].iString = _iString + 2;
  7426. _ptbStd[9].iString = _iString + 3;
  7427. _ptbStd[10].iString = _iString + 4;
  7428. }
  7429. else
  7430. {
  7431. _ptbStd[6].iString = _ptbStd[7].iString = _ptbStd[8].iString = _ptbStd[9].iString = _ptbStd[10].iString = -1;
  7432. }
  7433. if (_pBrowsExt)
  7434. {
  7435. _pBrowsExt->GetButtons(&_ptbStd[ARRAYSIZE(c_tbStd)], nNumExtButtons, FALSE);
  7436. }
  7437. ASSERT(_ptbStd[0].idCommand == DVIDM_SHOWTOOLS);
  7438. if (!_ToolsButtonAvailable())
  7439. _ptbStd[0].fsState |= TBSTATE_HIDDEN;
  7440. ASSERT(_ptbStd[1].idCommand == DVIDM_MAILNEWS);
  7441. if (!_MailButtonAvailable())
  7442. _ptbStd[1].fsState |= TBSTATE_HIDDEN;
  7443. ASSERT(_ptbStd[5].idCommand == DVIDM_DISCUSSIONS);
  7444. if (!_DiscussionsButtonAvailable())
  7445. _ptbStd[5].fsState |= TBSTATE_HIDDEN;
  7446. nNumButtons = RemoveHiddenButtons(_ptbStd, nNumButtons);
  7447. pvarargOut->vt = VT_BYREF;
  7448. pvarargOut->byref = (LPVOID)_ptbStd;
  7449. *pvarargIn->plVal = nNumButtons;
  7450. break;
  7451. }
  7452. case ETCMDID_RELOADBUTTONS:
  7453. _AddButtons(TRUE);
  7454. break;
  7455. }
  7456. return S_OK;
  7457. }
  7458. else if (IsEqualGUID(CGID_InternetExplorer, *pguidCmdGroup))
  7459. {
  7460. switch (nCmdID) {
  7461. case IECMDID_SET_INVOKE_DEFAULT_BROWSER_ON_NEW_WINDOW:
  7462. case IECMDID_GET_INVOKE_DEFAULT_BROWSER_ON_NEW_WINDOW:
  7463. case IECMDID_BEFORENAVIGATE_GETSHELLBROWSE:
  7464. case IECMDID_BEFORENAVIGATE_DOEXTERNALBROWSE:
  7465. case IECMDID_BEFORENAVIGATE_GETIDLIST:
  7466. if ( _pmsoctBrowser )
  7467. {
  7468. return _pmsoctBrowser->Exec( pguidCmdGroup, nCmdID, nCmdexecopt, pvarargIn, pvarargOut );
  7469. }
  7470. else
  7471. {
  7472. return E_FAIL;
  7473. }
  7474. default:
  7475. return OLECMDERR_E_NOTSUPPORTED;
  7476. }
  7477. }
  7478. return OLECMDERR_E_UNKNOWNGROUP;
  7479. }
  7480. HRESULT CDocObjectHost::_OnMaySaveChanges(void)
  7481. {
  7482. HRESULT hres = S_OK;
  7483. //
  7484. // ASSUMPTIONS:
  7485. // 1. Not supporting IPersistFile indicates we don't need to worry
  7486. // about prompting the user for "save as".
  7487. // 2. DocObject which returns S_OK for IPersistFile::S_OK implements
  7488. // OLECMDID_SAVEAS.
  7489. //
  7490. if (_fFileProtocol || _pmsot)
  7491. {
  7492. IPersistFile* ppf;
  7493. if (_IsDirty(&ppf))
  7494. {
  7495. ASSERT(ppf);
  7496. TCHAR szBuf[MAX_URL_STRING];
  7497. UINT id;
  7498. _GetCurrentPage(szBuf, ARRAYSIZE(szBuf));
  7499. id = MLShellMessageBox(_hwnd,
  7500. MAKEINTRESOURCE(IDS_MAYSAVEDOCUMENT), szBuf, MB_YESNOCANCEL);
  7501. switch(id) {
  7502. case IDCANCEL:
  7503. hres = S_FALSE;
  7504. break;
  7505. case IDYES:
  7506. if (_fFileProtocol) {
  7507. // 80105 APPHACK: Due to valid fixes in Urlmon, Visio is unable to save
  7508. // because we are loading the object with read-only flags. So we show
  7509. // the Save As dialog to let the user choose another filename.
  7510. if (_GetAppHack() & BROWSERFLAG_SAVEASWHENCLOSING)
  7511. {
  7512. if (_OnSaveAs() != S_OK)
  7513. hres = S_FALSE;
  7514. }
  7515. else
  7516. _OnSave();
  7517. } else {
  7518. HRESULT hresT=_pmsot->Exec(NULL, OLECMDID_SAVEAS, OLECMDEXECOPT_PROMPTUSER, NULL, NULL);
  7519. SAVEMSG("Exec(OLECMDID_SAVEAS) returned", hresT);
  7520. // Cancel the navigation if it failed.
  7521. if (FAILED(hresT)) {
  7522. // Beep if it is not canceled by the end user.
  7523. TraceMsg(DM_WARNING, "CDOH::_OnMaySaveChanges Exec(OELCMDID_SAVEAS) returned %x", hresT);
  7524. if (hresT != OLECMDERR_E_CANCELED) {
  7525. MessageBeep(0);
  7526. }
  7527. hres = S_FALSE;
  7528. }
  7529. }
  7530. break;
  7531. case IDNO:
  7532. //
  7533. // If user says 'No' to save changes to this page,
  7534. // we should remove it from the cache so that
  7535. // the user won't see that discarded change.
  7536. //
  7537. // (pri-2) This object discarding mechanism
  7538. // does not work for POSTed result, which is cached
  7539. // in the travel log.
  7540. //
  7541. break;
  7542. }
  7543. ppf->Release();
  7544. } else {
  7545. ASSERT(ppf==NULL);
  7546. }
  7547. }
  7548. //
  7549. // In addition, we give a chance to save the contents of the page (when
  7550. // the document is acted as a form -- data-bound Trident page is a good
  7551. // example) to the backend database.
  7552. //
  7553. if (hres == S_OK && _pmsot && (!_fDocCanNavigate || _fClosing))
  7554. {
  7555. VARIANT varOut = {0};
  7556. HRESULT hresT = _pmsot->Exec(NULL, OLECMDID_ONUNLOAD, OLECMDEXECOPT_PROMPTUSER, NULL, &varOut);
  7557. if (varOut.vt == VT_BOOL && varOut.boolVal != VARIANT_TRUE)
  7558. {
  7559. hres = S_FALSE;
  7560. }
  7561. }
  7562. return hres;
  7563. }
  7564. BOOL _ExecNearest(const GUID *pguidCmdGroup, DWORD nCmdID, BOOL fDown)
  7565. {
  7566. // Some commands we want to do in the closest frame to the docobj,
  7567. // some in the farthest-away frame, and some we want to handle
  7568. // in the top-most dochost. Look at the command to figure out
  7569. // the routing and then do it.
  7570. BOOL fNearest = FALSE; // most everything goes to the farthest-away frame
  7571. if (pguidCmdGroup==NULL)
  7572. {
  7573. switch(nCmdID)
  7574. {
  7575. case OLECMDID_OPEN:
  7576. case OLECMDID_SAVE:
  7577. case OLECMDID_SETTITLE:
  7578. case OLECMDID_HTTPEQUIV:
  7579. case OLECMDID_HTTPEQUIV_DONE:
  7580. fNearest = TRUE;
  7581. break;
  7582. // some are top-most down, so nearest depends on direction.
  7583. case OLECMDID_REFRESH:
  7584. // say top-most for commands that only work on the topmost guy.
  7585. // (ie, these probably should be implemented in CShellBrowser!)
  7586. // do this even though these are really "upwards-only" commands.
  7587. case OLECMDID_UPDATECOMMANDS:
  7588. case OLECMDID_SETPROGRESSMAX:
  7589. case OLECMDID_SETPROGRESSPOS:
  7590. case OLECMDID_SETPROGRESSTEXT:
  7591. case OLECMDID_SHOWSCRIPTERROR:
  7592. fNearest = fDown;
  7593. break;
  7594. }
  7595. }
  7596. else if (IsEqualGUID(CGID_ShellDocView, *pguidCmdGroup))
  7597. {
  7598. switch (nCmdID)
  7599. {
  7600. case SHDVID_AMBIENTPROPCHANGE:
  7601. case SHDVID_GETSYSIMAGEINDEX:
  7602. case SHDVID_DOCWRITEABORT:
  7603. case SHDVID_ONCODEPAGECHANGE:
  7604. case SHDVID_CANDOCOLORSCHANGE:
  7605. case SHDVID_SETSECURELOCK:
  7606. case SHDVID_QUERYMERGEDHELPMENU:
  7607. case SHDVID_QUERYOBJECTSHELPMENU:
  7608. fNearest = TRUE;
  7609. break;
  7610. case SHDVID_DISPLAYSCRIPTERRORS:
  7611. fNearest = fDown;
  7612. break;
  7613. }
  7614. }
  7615. else if (IsEqualGUID(CGID_Explorer, *pguidCmdGroup))
  7616. {
  7617. switch(nCmdID)
  7618. {
  7619. case SBCMDID_MAYSAVECHANGES: // since OLECMDID_SAVE is to the nearest frame
  7620. fNearest = TRUE;
  7621. break;
  7622. }
  7623. }
  7624. else if (IsEqualGUID(IID_IExplorerToolbar, *pguidCmdGroup) ||
  7625. IsEqualGUID(CLSID_InternetButtons, *pguidCmdGroup) ||
  7626. IsEqualGUID(CLSID_MSOButtons, *pguidCmdGroup))
  7627. {
  7628. fNearest = TRUE;
  7629. }
  7630. return fNearest;
  7631. }
  7632. HRESULT CDocObjectHost::Exec(const GUID * pguidCmdGroup,
  7633. DWORD nCmdID,
  7634. DWORD nCmdexecopt,
  7635. VARIANTARG * pvarargIn,
  7636. VARIANTARG * pvarargOut)
  7637. {
  7638. HRESULT hres = OLECMDERR_E_UNKNOWNGROUP;
  7639. if (pguidCmdGroup)
  7640. {
  7641. // Now that BaseBrowser understands that CGID_MSHTML should be directed to the DocObject, we'll
  7642. // get caught in a loop if we send those Execs through here. Cut it off at the pass.
  7643. if (IsEqualGUID(CGID_MSHTML, *pguidCmdGroup))
  7644. {
  7645. return hres;
  7646. }
  7647. else if (IsEqualGUID(CGID_DocHostCommandHandler, *pguidCmdGroup))
  7648. {
  7649. BOOL fHandled = FALSE;
  7650. HRESULT hr = _HandleDocHostCmds(nCmdID,
  7651. nCmdexecopt,
  7652. pvarargIn,
  7653. pvarargOut,
  7654. &fHandled);
  7655. if (fHandled)
  7656. {
  7657. return hr;
  7658. }
  7659. }
  7660. else if (IsEqualGUID(CGID_DocHostCmdPriv, *pguidCmdGroup))
  7661. {
  7662. BOOL fHandled = FALSE;
  7663. HRESULT hr = _HandleDocHostCmdPriv(nCmdID,
  7664. nCmdexecopt,
  7665. pvarargIn,
  7666. pvarargOut,
  7667. &fHandled);
  7668. if (fHandled)
  7669. {
  7670. return hr;
  7671. }
  7672. }
  7673. else if (IsEqualGUID(CGID_ShellDocView, *pguidCmdGroup))
  7674. {
  7675. if (_HandleShdocvwCmds(nCmdID, nCmdexecopt, pvarargIn, pvarargOut))
  7676. {
  7677. return S_OK;
  7678. }
  7679. }
  7680. }
  7681. BOOL fNearest = _ExecNearest(pguidCmdGroup, nCmdID, FALSE);
  7682. if (fNearest)
  7683. hres = OnExec(pguidCmdGroup, nCmdID, nCmdexecopt, pvarargIn, pvarargOut);
  7684. if (FAILED(hres) && _pmsoctBrowser)
  7685. {
  7686. hres = _pmsoctBrowser->Exec(pguidCmdGroup, nCmdID, nCmdexecopt,
  7687. pvarargIn, pvarargOut);
  7688. }
  7689. // If this is a command that puts up UI and the user presses
  7690. // cancel in the above call, we may try to handle the call here,
  7691. // and that would be bad. Steal OleCmdHRHandled() from MSHTML.
  7692. if (FAILED(hres) && !fNearest)
  7693. hres = OnExec(pguidCmdGroup, nCmdID, nCmdexecopt, pvarargIn, pvarargOut);
  7694. return hres;
  7695. }
  7696. //+---------------------------------------------------------------------------
  7697. //
  7698. // Member : CDocObjectHost::_HandleDocHostCmds
  7699. //
  7700. // Synopsis : Handles the CMD IDs for CGID_DocHostCommandHandler.
  7701. //
  7702. //+---------------------------------------------------------------------------
  7703. HRESULT
  7704. CDocObjectHost::_HandleDocHostCmds(DWORD nCmdID,
  7705. DWORD nCmdexecopt,
  7706. VARIANTARG * pvarargIn,
  7707. VARIANTARG * pvarargOut,
  7708. BOOL * pfHandled)
  7709. {
  7710. HRESULT hres = E_FAIL;
  7711. ASSERT(pfHandled);
  7712. *pfHandled = TRUE;
  7713. switch(nCmdID)
  7714. {
  7715. // Call from Trident printing with the page # of the currently spooling page.
  7716. // Convert it to a bool indicating whether or not to draw the print icon in the browser.
  7717. case OLECMDID_UPDATEPAGESTATUS:
  7718. hres = E_INVALIDARG;
  7719. if (pvarargIn && pvarargIn->vt == VT_I4)
  7720. {
  7721. VARIANTARG varIn;
  7722. V_VT(&varIn) = VT_BOOL;
  7723. V_BOOL(&varIn)= (pvarargIn->lVal > 0) ? VARIANT_TRUE : VARIANT_FALSE;
  7724. hres = _pmsoctBrowser->Exec(&CGID_ShellDocView,
  7725. SHDVID_SETPRINTSTATUS,
  7726. 0,
  7727. &varIn,
  7728. NULL);
  7729. }
  7730. break;
  7731. case OLECMDID_REFRESH:
  7732. // if the print Preview template is up, then we need to block refresh. IE bug (99685)
  7733. hres = _dhUIHandler.Exec(&CGID_DocHostCommandHandler,
  7734. OLECMDID_REFRESH,
  7735. nCmdexecopt, pvarargIn, pvarargOut);
  7736. break;
  7737. // Allow the command ID to be passed down the Exec chain.
  7738. //
  7739. default:
  7740. *pfHandled = FALSE;
  7741. break;
  7742. }
  7743. return hres;
  7744. }
  7745. //+---------------------------------------------------------------------------
  7746. //
  7747. // Member : CDocObjectHost::_HandleDocHostCmdPriv
  7748. //
  7749. // Synopsis : Handles the CMD IDs for CGID_DocHostCmdPriv
  7750. //
  7751. //+---------------------------------------------------------------------------
  7752. HRESULT
  7753. CDocObjectHost::_HandleDocHostCmdPriv(DWORD nCmdID,
  7754. DWORD nCmdexecopt,
  7755. VARIANTARG * pvarargIn,
  7756. VARIANTARG * pvarargOut,
  7757. BOOL * pfHandled)
  7758. {
  7759. HRESULT hres = E_FAIL;
  7760. ASSERT(pfHandled);
  7761. *pfHandled = TRUE;
  7762. switch(nCmdID)
  7763. {
  7764. case DOCHOST_DOCCANNAVIGATE:
  7765. {
  7766. // We only set the navigation window for the top-level browser.
  7767. // Even though the WebOC is no longer in frames, it can still
  7768. // be present on a web page as a view link or control.
  7769. //
  7770. DWORD dwFlags = 0;
  7771. if ( _pwb )
  7772. {
  7773. hres = _pwb->GetFlags(&dwFlags);
  7774. }
  7775. if ((dwFlags & BSF_TOPBROWSER) || _IsInBrowserBand())
  7776. {
  7777. ATOMICRELEASE(_pHTMLWindow);
  7778. if (pvarargIn && VT_UNKNOWN == V_VT(pvarargIn) && V_UNKNOWN(pvarargIn))
  7779. {
  7780. _fDocCanNavigate = TRUE;
  7781. hres = V_UNKNOWN(pvarargIn)->QueryInterface(IID_IHTMLWindow2,
  7782. (void**)&_pHTMLWindow);
  7783. }
  7784. else
  7785. {
  7786. _fDocCanNavigate = FALSE;
  7787. }
  7788. }
  7789. // Pass to the parent shell browser.
  7790. if (_pmsoctBrowser)
  7791. {
  7792. hres = _pmsoctBrowser->Exec(&CGID_DocHostCmdPriv, nCmdID,
  7793. nCmdexecopt, pvarargIn, pvarargOut);
  7794. }
  7795. }
  7796. break;
  7797. case DOCHOST_READYSTATE_INTERACTIVE:
  7798. if ( _pScriptErrList != NULL)
  7799. ClearScriptError();
  7800. hres = S_OK;
  7801. break;
  7802. case DOCHOST_NAVIGATION_ERROR:
  7803. hres = _HandleFailedNavigation(pvarargIn, pvarargOut );
  7804. break;
  7805. case DOCHOST_NOTE_ERROR_PAGE:
  7806. _fErrorPage = TRUE;
  7807. break;
  7808. case DOCHOST_CONTENTDISPOSITIONATTACH:
  7809. hres = _OnContentDisposition();
  7810. break;
  7811. case DOCHOST_RESETSEARCHINFO:
  7812. // Reset search info.
  7813. _bsc._SetSearchInfo(this, 0, FALSE, FALSE, FALSE);
  7814. break;
  7815. case DOCHOST_SENDINGREQUEST:
  7816. _OnSetProgressPos(0, PROGRESS_SENDING);
  7817. _fShowProgressCtl = TRUE;
  7818. _PlaceProgressBar(TRUE);
  7819. hres = S_OK;
  7820. break;
  7821. case DOCHOST_FINDINGRESOURCE:
  7822. _OnSetProgressPos(0, PROGRESS_FINDING);
  7823. _fShowProgressCtl = TRUE;
  7824. _PlaceProgressBar(TRUE);
  7825. hres = S_OK;
  7826. break;
  7827. // Allow the command ID to be passed down the Exec chain.
  7828. //
  7829. default:
  7830. *pfHandled = FALSE;
  7831. break;
  7832. }
  7833. return (S_FALSE == hres) ? S_OK : hres;
  7834. }
  7835. //+---------------------------------------------------------------------------
  7836. //
  7837. // Member : CDocObjectHost::_HandleShdocvwCmds
  7838. //
  7839. // Synopsis : Handles the CMD IDs for CGID_ShellDocView.
  7840. //
  7841. //+---------------------------------------------------------------------------
  7842. BOOL
  7843. CDocObjectHost::_HandleShdocvwCmds(DWORD nCmdID,
  7844. DWORD nCmdexecopt,
  7845. VARIANTARG * pvarargIn,
  7846. VARIANTARG * pvarargOut)
  7847. {
  7848. BOOL fHandled = TRUE;
  7849. switch(nCmdID)
  7850. {
  7851. case SHDVID_STARTPICSFORWINDOW:
  7852. _StartPicsForWindow(pvarargIn, pvarargOut);
  7853. break;
  7854. case SHDVID_CANCELPICSFORWINDOW:
  7855. _CancelPicsForWindow(pvarargIn);
  7856. break;
  7857. case SHDVID_ISPICSENABLED:
  7858. _IsPicsEnabled(pvarargOut);
  7859. break;
  7860. default:
  7861. fHandled = FALSE;
  7862. }
  7863. return fHandled;
  7864. }
  7865. //+-----------------------------------------------------------------------------
  7866. //
  7867. // Member : CDocObjectHost::_StartPicsForWindow
  7868. //
  7869. //+-----------------------------------------------------------------------------
  7870. void
  7871. CDocObjectHost::_StartPicsForWindow(VARIANTARG * pvarargIn, VARIANTARG * pvarargOut)
  7872. {
  7873. ASSERT(pvarargIn);
  7874. ASSERT(VT_UNKNOWN == V_VT(pvarargIn));
  7875. ASSERT(V_UNKNOWN(pvarargIn));
  7876. ASSERT(pvarargOut);
  7877. ASSERT(V_VT(pvarargOut) == VT_EMPTY);
  7878. IHTMLPrivateWindow * pPrivWin;
  7879. V_VT(pvarargOut) = VT_BOOL;
  7880. V_BOOL(pvarargOut) = VARIANT_FALSE;
  7881. if (SUCCEEDED(V_UNKNOWN(pvarargIn)->QueryInterface(IID_IHTMLPrivateWindow, (void**)&pPrivWin)))
  7882. {
  7883. // Ignore the HR
  7884. //
  7885. if (_StartSecondaryPicsProcessor(pPrivWin) == S_OK)
  7886. {
  7887. V_BOOL(pvarargOut) = VARIANT_TRUE;
  7888. }
  7889. pPrivWin->Release();
  7890. }
  7891. }
  7892. BOOL
  7893. CDocObjectHost::_IsInBrowserBand() const
  7894. {
  7895. if (_psp)
  7896. {
  7897. IShellBrowser * pShlBrowser;
  7898. HRESULT hr = _psp->QueryService(SID_SProxyBrowser,
  7899. IID_PPV_ARG(IShellBrowser, &pShlBrowser));
  7900. if (SUCCEEDED(hr))
  7901. {
  7902. pShlBrowser->Release();
  7903. return TRUE;
  7904. }
  7905. }
  7906. return FALSE;
  7907. }
  7908. //+-----------------------------------------------------------------------------
  7909. //
  7910. // Member : CDocObjectHost::_CancelPicsForWindow
  7911. //
  7912. //+-----------------------------------------------------------------------------
  7913. void
  7914. CDocObjectHost::_CancelPicsForWindow(VARIANTARG * pvarargIn)
  7915. {
  7916. ASSERT(pvarargIn);
  7917. ASSERT(VT_UNKNOWN == V_VT(pvarargIn));
  7918. ASSERT(V_UNKNOWN(pvarargIn));
  7919. IUnknown * pUnkPrivWin;
  7920. if (SUCCEEDED(V_UNKNOWN(pvarargIn)->QueryInterface(IID_IUnknown, (void**)&pUnkPrivWin)))
  7921. {
  7922. _RemovePicsProcessorByPrivWindowUnk(pUnkPrivWin);
  7923. pUnkPrivWin->Release();
  7924. }
  7925. }
  7926. //+-----------------------------------------------------------------------------
  7927. //
  7928. // Member : CDocObjectHost::_IsPicsEnabled
  7929. //
  7930. // Synopsis : Returns a variant that specifies whether or not PICS is enabled.
  7931. //
  7932. //+-----------------------------------------------------------------------------
  7933. void
  7934. CDocObjectHost::_IsPicsEnabled(VARIANTARG * pvarargOut)
  7935. {
  7936. ASSERT(pvarargOut);
  7937. ASSERT(VT_EMPTY == V_VT(pvarargOut));
  7938. V_VT(pvarargOut) = VT_BOOL;
  7939. V_BOOL(pvarargOut) = VARIANT_FALSE;
  7940. IRatingNotification* pRatingNotify;
  7941. HRESULT hres = QueryService(SID_SRatingNotification, IID_PPV_ARG(IRatingNotification, &pRatingNotify));
  7942. if (SUCCEEDED(hres))
  7943. {
  7944. V_BOOL(pvarargOut) = pRatingNotify->IsRatingsEnabled() ? VARIANT_FALSE : VARIANT_TRUE;
  7945. pRatingNotify->Release();
  7946. }
  7947. else
  7948. {
  7949. if (IS_RATINGS_ENABLED() && S_OK == ::RatingEnabledQuery())
  7950. {
  7951. V_BOOL(pvarargOut) = VARIANT_TRUE;
  7952. }
  7953. }
  7954. }
  7955. //+-----------------------------------------------------------------------------
  7956. //
  7957. // Member : CDocObjectHost::_UpdateState
  7958. //
  7959. // Synopsis : Updates the state of the dochost.
  7960. //
  7961. //+-----------------------------------------------------------------------------
  7962. HRESULT
  7963. CDocObjectHost::_UpdateState(LPITEMIDLIST pidl, BOOL fIsErrorUrl)
  7964. {
  7965. HRESULT hres;
  7966. if (_fSetSecureLock)
  7967. {
  7968. _ForwardSetSecureLock(_eSecureLock);
  7969. }
  7970. ASSERT(_pwb);
  7971. if (!fIsErrorUrl)
  7972. {
  7973. ResetRefreshUrl();
  7974. }
  7975. IMoniker * pmk;
  7976. BOOL fFileProtocol;
  7977. hres = ::_URLMONMonikerFromPidl(pidl, &pmk, &fFileProtocol);
  7978. if (S_OK == hres)
  7979. {
  7980. ATOMICRELEASE(_pmkCur);
  7981. _pmkCur = pmk;
  7982. DEBUG_CODE(_TraceMonikerDbg(_pmkCur, _T("CDocObjectHost::_UpdateState")));
  7983. }
  7984. _fFileProtocol = fFileProtocol;
  7985. // This is only set if we did a successful LoadHistory()
  7986. //
  7987. _fIsHistoricalObject = FALSE;
  7988. // This flag used to be set to false in IE5
  7989. // for each navigation because the dochost was
  7990. // destroyed and a new one was created. Now that Trident
  7991. // knows how to navigate, this flag doesn't get reset. This
  7992. // prevents activation of the view in the case where a
  7993. // modal dialog is being displayed.
  7994. //
  7995. _fReadystateInteractiveProcessed = FALSE;
  7996. return hres;
  7997. }
  7998. //+-----------------------------------------------------------------------------
  7999. //
  8000. // Member : CDocObjectHost::_Init
  8001. //
  8002. // Synopsis : Clears the cached redirection URL in case the previous navigation
  8003. // was a redirection. THis is needed so that further navigations to https://
  8004. // sites don't get the redirection URL as their SSL base.
  8005. //+-----------------------------------------------------------------------------
  8006. void
  8007. CDocObjectHost::_Init()
  8008. {
  8009. _fDelegatedNavigation = FALSE;
  8010. _fErrorPage = FALSE;
  8011. if (_bsc._pszRedirectedURL)
  8012. {
  8013. LocalFree(_bsc._pszRedirectedURL);
  8014. _bsc._pszRedirectedURL = NULL;
  8015. }
  8016. }
  8017. #ifdef DEBUG
  8018. void
  8019. CDocObjectHost::_TraceMonikerDbg(IMoniker * pmk, TCHAR * pszCaller) const
  8020. {
  8021. ASSERT(pmk);
  8022. LPOLESTR pstrDisplayName;
  8023. HRESULT hr = pmk->GetDisplayName(NULL, NULL, &pstrDisplayName);
  8024. if (S_OK == hr)
  8025. {
  8026. TraceMsg(DM_TRACE, "%ws - Moniker=\"%ws\"", pszCaller, pstrDisplayName);
  8027. OleFree(pstrDisplayName);
  8028. }
  8029. }
  8030. #endif
  8031. //
  8032. // Only available in the DDK so defined here
  8033. //
  8034. #define E_INVALID_SYNTAX 0x800401E4
  8035. //+-------------------------------------------------------------------------
  8036. //
  8037. // Member : CDocObjectHost::_HandleFailedNavigation
  8038. //
  8039. // Synopsis : Handles a failed navigation by initiating
  8040. // the AutoSearch function or displaying an
  8041. // error page.
  8042. //
  8043. // Scenario : - The user navigates to a bogus URL such as "sdfg".
  8044. // - _HandleFailedNavigation is called via Exec with
  8045. // DOCHOST_NAVIGATION_ERROR.
  8046. // - The AutoSearch initiates with a search index of 0.
  8047. // - AutoSearch expands the URL with the first
  8048. // UrlTemplate from the registry (usually www.%s.com).
  8049. // - Navigation to the new URL is attempted.
  8050. // - Upon failure, this method is called again with
  8051. // an error code of HTTP_STATUS_BAD_GATEWAY or
  8052. // HTTP_STATUS_GATEWAY_TIMEOUT.
  8053. // - The search index in the property bag is incremented (by
  8054. // two if it is currently 0.)
  8055. // - AutoSearch then tries the next UrlTemplate, and so on.
  8056. //
  8057. // If this method is called with an error code other than
  8058. // HTTP_STATUS_BAD_GATEWAY, HTTP_STATUS_GATEWAY_TIMEOUT,
  8059. // INET_E_RESOURCE_NOT_FOUND, INET_E_DATA_NOT_AVAILABLE or
  8060. // if the error code is INET_E_RESOURCE_NOT_FOUND or
  8061. // INET_E_DATA_NOT_AVAILABLEthe and the URL entered by the
  8062. // user contains a protocol identifier (e.g., http://) an
  8063. // error page contained in shdoclc.dll is displayed.
  8064. //
  8065. // Input : pvarargIn - a SafeArray that contains the following
  8066. // data in this order.
  8067. // 0 - Binding error or HTTP status code. (VT_I4)
  8068. // 1 - URL being navigated to. (VT_BSTR)
  8069. // 2 - IBinding interface (VT_UNKNOWN)
  8070. // 3 - IHTMLWindow2 of the current window (VT_UNKNOWN)
  8071. //
  8072. //-------------------------------------------------------------------------
  8073. HRESULT
  8074. CDocObjectHost::_HandleFailedNavigation(VARIANTARG * pvarargIn, VARIANTARG* pvarargOut /*=NULL*/)
  8075. {
  8076. HRESULT hr = E_FAIL;
  8077. ASSERT(pvarargIn);
  8078. ASSERT(_fDocCanNavigate);
  8079. if (pvarargIn && VT_ARRAY == V_VT(pvarargIn) && V_ARRAY(pvarargIn))
  8080. {
  8081. // Get the error code from the SafeArray.
  8082. //
  8083. CComVariant cvarErrorCode;
  8084. CComVariant cvarAddrBarNav;
  8085. CComVariant cvarRefresh;
  8086. long lIdx = 0;
  8087. DWORD dwError = ERRORPAGE_DNS;
  8088. BOOL fShouldDisplayError = TRUE;
  8089. BOOL fDidSuperNavigate = TRUE;
  8090. //
  8091. // We use to use the window only in one place. To avoid QI several times
  8092. // We QI just before the first use, and keep track if we were successful.
  8093. //
  8094. CComVariant cvarWindow;
  8095. IHTMLWindow2 * pCurrentWindow = NULL;
  8096. HRESULT hrWinQI = E_FAIL;
  8097. hr = SafeArrayGetElement(V_ARRAY(pvarargIn), &lIdx, &cvarErrorCode);
  8098. if (SUCCEEDED(hr) && V_VT(&cvarErrorCode) == VT_I4)
  8099. {
  8100. lIdx = 4;
  8101. hr = SafeArrayGetElement(V_ARRAY(pvarargIn), &lIdx, &cvarAddrBarNav);
  8102. if (SUCCEEDED(hr) && V_VT(&cvarAddrBarNav) == VT_BOOL)
  8103. {
  8104. // We fire NavigateError and if the host wishes to cancel
  8105. // we can skip the rest of this method.
  8106. BOOL fCancelAutoSearch = FALSE;
  8107. DWORD dwStatusCode = V_I4(&cvarErrorCode);
  8108. CComVariant cvarWindow;
  8109. // Get the pending URL from the SafeArray.
  8110. //
  8111. CComVariant cvarUrl;
  8112. lIdx = 1;
  8113. hr = SafeArrayGetElement(V_ARRAY(pvarargIn), &lIdx, &cvarUrl);
  8114. if (SUCCEEDED(hr) && (VT_BSTR == V_VT(&cvarUrl)) && V_BSTR(&cvarUrl))
  8115. {
  8116. // Get the current window from the SafeArray.
  8117. //
  8118. lIdx = 3;
  8119. hr = SafeArrayGetElement(V_ARRAY(pvarargIn), &lIdx, &cvarWindow);
  8120. if (SUCCEEDED(hr) && V_VT(&cvarWindow) == VT_UNKNOWN && V_UNKNOWN(&cvarWindow))
  8121. {
  8122. hr = V_UNKNOWN(&cvarWindow)->QueryInterface(IID_IHTMLWindow2, (void**)&pCurrentWindow);
  8123. _FireNavigateErrorHelper(SUCCEEDED(hr) ? pCurrentWindow : NULL,
  8124. dwStatusCode,
  8125. &fCancelAutoSearch,
  8126. V_BSTR(&cvarUrl));
  8127. hrWinQI = hr;
  8128. }
  8129. }
  8130. if (fCancelAutoSearch)
  8131. {
  8132. if (!_fCanceledByBrowser)
  8133. {
  8134. _CancelPendingNavigation(FALSE, TRUE);
  8135. }
  8136. return hr;
  8137. }
  8138. lIdx = 0;
  8139. switch (V_I4(&cvarErrorCode))
  8140. {
  8141. case HTTP_STATUS_BAD_GATEWAY:
  8142. case HTTP_STATUS_GATEWAY_TIMEOUT:
  8143. if (VARIANT_TRUE == V_BOOL(&cvarAddrBarNav))
  8144. {
  8145. hr = _DoAutoSearch(pvarargIn,
  8146. ++lIdx,
  8147. V_I4(&cvarErrorCode),
  8148. FALSE,
  8149. &fShouldDisplayError);
  8150. if ( fShouldDisplayError )
  8151. {
  8152. fDidSuperNavigate = FALSE;
  8153. }
  8154. }
  8155. break;
  8156. // Only autosearch if the error code is
  8157. // INET_E_RESOURCE_NOT_FOUND or INET_E_DATA_NOT_AVAILABLE
  8158. //
  8159. case INET_E_RESOURCE_NOT_FOUND:
  8160. case INET_E_DATA_NOT_AVAILABLE:
  8161. if (VARIANT_TRUE == V_BOOL(&cvarAddrBarNav))
  8162. {
  8163. hr = _DoAutoSearch(pvarargIn,
  8164. ++lIdx,
  8165. 0,
  8166. TRUE,
  8167. &fShouldDisplayError);
  8168. // We must reset here so that the index will be
  8169. // correct the next time around.
  8170. //
  8171. }
  8172. // Intentional fall-through
  8173. case INET_E_DOWNLOAD_FAILURE:
  8174. if (IsGlobalOffline())
  8175. break;
  8176. // otherwise fall through to do default handling
  8177. default:
  8178. if (hr || fShouldDisplayError)
  8179. {
  8180. if ( V_I4(&cvarErrorCode) >= HTTP_STATUS_BAD_REQUEST
  8181. && V_I4(&cvarErrorCode) <= HTTP_STATUS_LAST)
  8182. {
  8183. dwError = V_I4(&cvarErrorCode);
  8184. }
  8185. // Special for Trident Invalid Syntax
  8186. // Trident passes the raw hr to Shdocvw
  8187. // instead of the friendly code.
  8188. if (V_I4(&cvarErrorCode) == E_INVALID_SYNTAX)
  8189. {
  8190. dwError = ERRORPAGE_SYNTAX;
  8191. }
  8192. // Get the pending URL from the SafeArray.
  8193. //
  8194. CComVariant cvarUrl;
  8195. lIdx = 1;
  8196. hr = SafeArrayGetElement(V_ARRAY(pvarargIn), &lIdx, &cvarUrl);
  8197. if (SUCCEEDED(hr) && V_VT(&cvarUrl) == VT_BSTR && V_BSTR(&cvarUrl))
  8198. {
  8199. if (SUCCEEDED(hrWinQI))
  8200. {
  8201. //
  8202. // Get the refresh flag - indicating whether this is a refresh.
  8203. // ( this was originally set when we called SuperNavigate )
  8204. //
  8205. lIdx = 5;
  8206. hr = SafeArrayGetElement(V_ARRAY(pvarargIn), &lIdx, &cvarRefresh);
  8207. if (SUCCEEDED(hr))
  8208. {
  8209. hr = _DisplayHttpErrorPage(pCurrentWindow,
  8210. V_BSTR(&cvarUrl),
  8211. dwError,
  8212. V_BOOL(&cvarAddrBarNav),
  8213. V_BOOL(&cvarRefresh ) );
  8214. ATOMICRELEASE(pCurrentWindow);
  8215. }
  8216. }
  8217. }
  8218. }
  8219. break;
  8220. } // switch
  8221. if ( pvarargOut && ( V_VT( pvarargOut ) == VT_BOOL ) )
  8222. {
  8223. V_BOOL( pvarargOut ) = fDidSuperNavigate ? VARIANT_TRUE : VARIANT_FALSE;
  8224. }
  8225. } // if (SUCCEEDED(hr) && V_VT(&cvarAddrBarNav) == VT_BOOL)
  8226. } // if (SUCCEEDED(hr) && V_VT(&cvarErrorCode) == VT_I4)
  8227. }
  8228. return (S_FALSE == hr ? S_OK : hr);
  8229. }
  8230. //+------------------------------------------------------------------
  8231. //
  8232. // Member : CDocObjectHost::_DoAutoSearch
  8233. //
  8234. // Synopsis : Performs the autosearch function.
  8235. //
  8236. // Input : pvarargIn - a SafeArray of arguments. See
  8237. // _HandleFailedNavigation for info about
  8238. // the format of pvarargIn.
  8239. // lStartIdx - the position in the SafeArray where
  8240. // the data begins.
  8241. // dwStatusCode - the HTTP status code.
  8242. //
  8243. // Output : pfShouldDisplayError - TRUE if an error page
  8244. // should be displayed.
  8245. //
  8246. //------------------------------------------------------------------
  8247. HRESULT
  8248. CDocObjectHost::_DoAutoSearch(VARIANTARG * pvarargIn,
  8249. long lStartIdx,
  8250. DWORD dwStatusCode,
  8251. BOOL fAddMRU,
  8252. BOOL * pfShouldDisplayError)
  8253. {
  8254. ASSERT(pvarargIn);
  8255. ASSERT(_fDocCanNavigate);
  8256. ASSERT(pfShouldDisplayError);
  8257. *pfShouldDisplayError = TRUE;
  8258. // Url
  8259. CComVariant cvarUrl;
  8260. HRESULT hr = SafeArrayGetElement(V_ARRAY(pvarargIn), &lStartIdx, &cvarUrl);
  8261. if (SUCCEEDED(hr) && V_VT(&cvarUrl) == VT_BSTR && V_BSTR(&cvarUrl))
  8262. {
  8263. CComVariant cvarBinding;
  8264. IBinding * pBinding;
  8265. // Binding interface pointer
  8266. lStartIdx++;
  8267. hr = SafeArrayGetElement(V_ARRAY(pvarargIn), &lStartIdx, &cvarBinding);
  8268. if (SUCCEEDED(hr) && V_VT(&cvarBinding) == VT_UNKNOWN && V_UNKNOWN(&cvarBinding))
  8269. {
  8270. hr = V_UNKNOWN(&cvarBinding)->QueryInterface(IID_IBinding, (void**)&pBinding);
  8271. if (SUCCEEDED(hr))
  8272. {
  8273. hr = _bsc._HandleFailedNavigationSearch(pfShouldDisplayError, dwStatusCode, this, 0, V_BSTR(&cvarUrl),
  8274. L"Resource Not Found", pBinding, fAddMRU, TRUE);
  8275. if (hr == S_FALSE)
  8276. _fErrorPage = TRUE; // Don't update the history if no auto-search
  8277. ATOMICRELEASE(pBinding);
  8278. }
  8279. }
  8280. }
  8281. return (S_FALSE == hr ? S_OK : hr);
  8282. }
  8283. //+---------------------------------------------------------------
  8284. //
  8285. // Member : CDocObjectHost::_DisplayHttpErrorPage
  8286. //
  8287. // Synopsis : Displays the HTML page that corresponds to
  8288. // the given error code.
  8289. //
  8290. // Input : pCurrentWindow - the window to use for navigation.
  8291. // dwError - the error code.
  8292. //
  8293. //---------------------------------------------------------------
  8294. HRESULT
  8295. CDocObjectHost::_DisplayHttpErrorPage(IHTMLWindow2 * pCurrentWindow,
  8296. BSTR bstrUrl,
  8297. DWORD dwError,
  8298. BOOL fAddrBarNav,
  8299. BOOL fRefresh /*=FALSE*/)
  8300. {
  8301. HRESULT hr = E_FAIL;
  8302. TCHAR szErrorUrl[MAX_URL_STRING];
  8303. const WCHAR * const pszFmt = L"#%s";
  8304. IHTMLPrivateWindow * pPrivWindow = NULL;
  8305. ASSERT(pCurrentWindow);
  8306. ASSERT(_fDocCanNavigate);
  8307. _bsc._DontAddToMRU(this);
  8308. if (IsErrorHandled(dwError))
  8309. {
  8310. _fErrorPage = TRUE;
  8311. if (_bsc._DisplayFriendlyHttpErrors())
  8312. {
  8313. hr = MLBuildResURLWrap(_T("shdoclc.dll"),
  8314. HINST_THISDLL,
  8315. ML_CROSSCODEPAGE,
  8316. (TCHAR*)c_aErrorUrls[EUIndexFromError(dwError)].pszUrl,
  8317. szErrorUrl,
  8318. ARRAYSIZE(szErrorUrl),
  8319. _T("shdocvw.dll"));
  8320. if (SUCCEEDED(hr))
  8321. {
  8322. LPOLESTR pwszLocation = OLE2W(bstrUrl);
  8323. if (!IsFrameWindow(pCurrentWindow))
  8324. {
  8325. // Save the url the user attempted to navigate to. It will be used
  8326. // to refresh the page.
  8327. //
  8328. OleFree(_pwszRefreshUrl);
  8329. hr = SHStrDupW(OLE2W(bstrUrl), &_pwszRefreshUrl);
  8330. }
  8331. if (SUCCEEDED(hr))
  8332. {
  8333. int nLenWritten = lstrlen(szErrorUrl);
  8334. // Append the #<refresh URL>
  8335. //
  8336. wnsprintf(szErrorUrl + nLenWritten,
  8337. ARRAYSIZE(szErrorUrl) - nLenWritten,
  8338. pszFmt,
  8339. pwszLocation ? pwszLocation : L"");
  8340. hr = pCurrentWindow->QueryInterface(IID_IHTMLPrivateWindow,
  8341. (void**)&pPrivWindow);
  8342. if (SUCCEEDED(hr))
  8343. {
  8344. // Navigate to the URL
  8345. //
  8346. BSTR bstrErrorUrl = SysAllocString(szErrorUrl);
  8347. DWORD dwFlags = (fAddrBarNav ?
  8348. DOCNAVFLAG_DONTUPDATETLOG | DOCNAVFLAG_HTTPERRORPAGE :
  8349. DOCNAVFLAG_HTTPERRORPAGE) ;
  8350. if ( fRefresh )
  8351. dwFlags |= DOCNAVFLAG_REFRESH;
  8352. if (bstrErrorUrl)
  8353. {
  8354. hr = pPrivWindow->SuperNavigate(bstrErrorUrl,
  8355. NULL,
  8356. NULL,
  8357. NULL,
  8358. NULL,
  8359. NULL,
  8360. dwFlags);
  8361. SysFreeString(bstrErrorUrl);
  8362. }
  8363. pPrivWindow->Release();
  8364. }
  8365. }
  8366. }
  8367. }
  8368. }
  8369. return hr;
  8370. }
  8371. HRESULT CDocObjectHost::_GetUrlVariant(VARIANT *pvarargOut)
  8372. {
  8373. ASSERT( pvarargOut);
  8374. if (_pmkCur)
  8375. {
  8376. LPOLESTR pszDisplayName = NULL;
  8377. LPTSTR pszRedirectedURL = NULL;
  8378. if (_bsc._pszRedirectedURL && *_bsc._pszRedirectedURL)
  8379. pszRedirectedURL = _bsc._pszRedirectedURL;
  8380. if (pszRedirectedURL || SUCCEEDED(_GetCurrentPageW(&pszDisplayName, TRUE)))
  8381. {
  8382. pvarargOut->bstrVal = SysAllocString(pszRedirectedURL ? pszRedirectedURL : pszDisplayName);
  8383. if (pvarargOut->bstrVal)
  8384. pvarargOut->vt = VT_BSTR;
  8385. if (pszDisplayName)
  8386. OleFree(pszDisplayName);
  8387. }
  8388. }
  8389. return (pvarargOut->bstrVal == NULL) ? E_FAIL : S_OK;
  8390. }
  8391. HRESULT CDocObjectHost::_CoCreateHTMLDocument(REFIID riid, void ** ppvOut)
  8392. {
  8393. IOleCommandTarget* pcmd;
  8394. HRESULT hres = QueryService(SID_STopLevelBrowser, IID_IOleCommandTarget, (void **)&pcmd);
  8395. if (SUCCEEDED(hres)) {
  8396. VARIANT varOut = { 0 };
  8397. hres = pcmd->Exec(&CGID_Explorer, SBCMDID_COCREATEDOCUMENT, 0, NULL, &varOut);
  8398. if (SUCCEEDED(hres) && varOut.vt == VT_UNKNOWN) {
  8399. hres = varOut.punkVal->QueryInterface(riid, ppvOut);
  8400. // Clean it up by ourself so that we don't load OLEAUT32
  8401. varOut.punkVal->Release();
  8402. } else {
  8403. ASSERT(varOut.vt == VT_EMPTY);
  8404. VariantClear(&varOut);
  8405. }
  8406. pcmd->Release();
  8407. }
  8408. return hres;
  8409. }
  8410. HRESULT CDocObjectHost::_CreatePendingDocObject(BOOL fMustInit, BOOL fWindowOpen /* = FALSE */)
  8411. {
  8412. HRESULT hres = S_OK;
  8413. if (_punkPending == NULL)
  8414. {
  8415. hres = _CoCreateHTMLDocument(IID_IUnknown, (void **)&_punkPending);
  8416. _fPendingNeedsInit = 1; // lazy InitNew only if absolutely necessary
  8417. if (fWindowOpen)
  8418. {
  8419. IUnknown_Exec(_punkPending, &CGID_ShellDocView, SHDVID_WINDOWOPEN, 0, NULL, NULL);
  8420. }
  8421. }
  8422. if (_fPendingNeedsInit && fMustInit && SUCCEEDED(hres))
  8423. {
  8424. IOleObject * polePending;
  8425. #ifdef TRIDENT_NEEDS_LOCKRUNNING
  8426. IRunnableObject * pro;
  8427. #endif
  8428. _fCreatingPending = 1; // we are creating _punkPending
  8429. _fAbortCreatePending = 0;
  8430. _fPendingNeedsInit = 0;
  8431. IPersistStreamInit * pipsi;
  8432. hres = _punkPending->QueryInterface(IID_IPersistStreamInit, (void**)&pipsi);
  8433. if (SUCCEEDED(hres))
  8434. {
  8435. hres = pipsi->InitNew();
  8436. pipsi->Release();
  8437. }
  8438. // if the InitNew is a re-entrant request (such as doing execDown to get a securityctx
  8439. // while in the process of loading the document), trident will respond with E_PENDING
  8440. // since there is already a load in progress, this call/init is a timing issue, and
  8441. // we can use the exisitng one.
  8442. //
  8443. if (SUCCEEDED(hres) || hres==E_PENDING)
  8444. {
  8445. hres = _punkPending->QueryInterface(IID_IOleObject, (void**)&polePending);
  8446. if (SUCCEEDED(hres))
  8447. {
  8448. hres = polePending->SetClientSite(this);
  8449. polePending->Release();
  8450. }
  8451. #ifdef TRIDENT_NEEDS_LOCKRUNNING
  8452. // TRIDENT NO LONGER SUPPORTS IRunnableObject
  8453. // RegisterObjectParam/RevokeObjectParam calls LockRunning on object being
  8454. // registered. LockRunning(FALSE,FALSE) implied in the Revoke will result
  8455. // in OleClose being called on _punkPending if we haven't activated it
  8456. // by end of binding. Thus we must call LockRunning ourself
  8457. if (SUCCEEDED(hres))
  8458. {
  8459. hres = _punkPending->QueryInterface(IID_IRunnableObject, (void**)&pro);
  8460. if (SUCCEEDED(hres))
  8461. {
  8462. hres = pro->LockRunning(TRUE, TRUE);
  8463. pro->Release();
  8464. }
  8465. }
  8466. #endif
  8467. }
  8468. _fCreatingPending = 0;
  8469. _fPendingWasInited = 1;
  8470. if (FAILED(hres))
  8471. {
  8472. SAFERELEASE(_punkPending);
  8473. }
  8474. else if (_fAbortCreatePending)
  8475. {
  8476. // Detect AOL pumping messages and reentering and attempting to release
  8477. // _punkPending
  8478. _fAbortCreatePending = 0;
  8479. _ReleasePendingObject();
  8480. hres = E_FAIL;
  8481. }
  8482. else
  8483. {
  8484. // Pass URL for pending object to it in advance of IPersistMoniker::Load
  8485. //
  8486. // Notes: We don't want to call _GetUrlVariant which will load
  8487. // OLEAUT32.DLL
  8488. //
  8489. LPOLESTR pszDisplayName = NULL;
  8490. LPTSTR pszURL = NULL;
  8491. if (_bsc._pszRedirectedURL && *_bsc._pszRedirectedURL)
  8492. pszURL = _bsc._pszRedirectedURL;
  8493. if (pszURL || SUCCEEDED(_GetCurrentPageW(&pszDisplayName, TRUE)))
  8494. {
  8495. LBSTR::CString strDisplay;
  8496. strDisplay = ( pszURL ? pszURL : pszDisplayName );
  8497. VARIANT varIn;
  8498. varIn.vt = VT_BSTR;
  8499. varIn.bstrVal = strDisplay;
  8500. IUnknown_Exec(_punkPending, &CGID_ShellDocView, SHDVID_SETPENDINGURL, 0, &varIn, NULL);
  8501. if (pszDisplayName)
  8502. OleFree(pszDisplayName);
  8503. }
  8504. }
  8505. _fAbortCreatePending = 0;
  8506. }
  8507. return hres;
  8508. }
  8509. HRESULT
  8510. CDocObjectHost::_LoadDocument()
  8511. {
  8512. if (!_punkPending)
  8513. return E_FAIL;
  8514. IPersistMoniker * pPersistMk;
  8515. HRESULT hres = _punkPending->QueryInterface(IID_IPersistMoniker, (void**)&pPersistMk);
  8516. if (SUCCEEDED(hres))
  8517. {
  8518. ITridentService * pTridentSvc;
  8519. if ( _pwb )
  8520. {
  8521. hres = _pwb->QueryInterface(IID_ITridentService, (void**)&pTridentSvc);
  8522. }
  8523. else
  8524. {
  8525. TraceMsg( TF_ERROR, "CDocObjectHost::_LoadDocument() - _pwb is NULL!" );
  8526. hres = E_FAIL;
  8527. }
  8528. if (SUCCEEDED(hres))
  8529. {
  8530. BSTR bstrUrl;
  8531. hres = pTridentSvc->GetPendingUrl(&bstrUrl);
  8532. if (SUCCEEDED(hres))
  8533. {
  8534. IMoniker * pMoniker;
  8535. TCHAR *pstr;
  8536. // Parse the URL, removing any location info
  8537. pstr = wcsrchr(bstrUrl, '#');
  8538. if (pstr)
  8539. {
  8540. *pstr = '\0';
  8541. }
  8542. hres = CreateURLMoniker(NULL, bstrUrl, &pMoniker);
  8543. if (SUCCEEDED(hres))
  8544. {
  8545. ATOMICRELEASE(_pole);
  8546. hres = _punkPending->QueryInterface(IID_IOleObject, (void**)&_pole);
  8547. if (SUCCEEDED(hres))
  8548. {
  8549. _GetAppHack();
  8550. // Call _SetUpTransitionCapability() to set up the advisory sinks
  8551. // and set readystate to complete. If we don't do this here, the
  8552. // view will never be activated after the first navigation
  8553. // which means that the view will never switched and the
  8554. // new document will not be displayed. Also, setting readystate
  8555. // to complete here, is what prevents the window from being transparent
  8556. // when it is first opened.
  8557. //
  8558. _SetUpTransitionCapability(TRUE);
  8559. }
  8560. hres = pPersistMk->Load(TRUE, pMoniker, _pbcCur, 0);
  8561. pMoniker->Release();
  8562. }
  8563. SysFreeString(bstrUrl);
  8564. }
  8565. pTridentSvc->Release();
  8566. }
  8567. pPersistMk->Release();
  8568. }
  8569. return S_OK;
  8570. }
  8571. // called from CDocObjectView to exec and forward these calls down
  8572. //
  8573. HRESULT CDocObjectHost::ExecDown(const GUID *pguidCmdGroup, DWORD nCmdID, DWORD nCmdexecopt, VARIANTARG *pvarargIn, VARIANTARG *pvarargOut)
  8574. {
  8575. HRESULT hres = OLECMDERR_E_UNKNOWNGROUP;
  8576. // Special case Exec's that are used to fetch info on pending docobject
  8577. // for scripting access before OnObjectAvailable
  8578. if (pguidCmdGroup && IsEqualGUID(CGID_ShellDocView, *pguidCmdGroup))
  8579. {
  8580. switch(nCmdID)
  8581. {
  8582. case SHDVID_GETPENDINGOBJECT:
  8583. ASSERT( pvarargOut);
  8584. VariantClearLazy(pvarargOut);
  8585. if (_pole)
  8586. {
  8587. _pole->QueryInterface(IID_IUnknown, (void **) &(pvarargOut->punkVal));
  8588. // Check to see if this is a window.open case. If so,
  8589. // the document was created and Init'ed in SetTarget
  8590. // and the real Url will be loaded now.
  8591. //
  8592. if (_pbcCur)
  8593. {
  8594. IUnknown * punkBindCtxParam = NULL;
  8595. hres = _pbcCur->GetObjectParam(KEY_BINDCONTEXTPARAM, &punkBindCtxParam);
  8596. if (SUCCEEDED(hres))
  8597. {
  8598. punkBindCtxParam->Release();
  8599. _fWindowOpen = TRUE;
  8600. hres = _LoadDocument();
  8601. _ActivateMsoView();
  8602. }
  8603. }
  8604. }
  8605. else
  8606. {
  8607. _CreatePendingDocObject(TRUE);
  8608. if (_punkPending)
  8609. {
  8610. pvarargOut->punkVal = _punkPending;
  8611. _punkPending->AddRef();
  8612. }
  8613. else if (_pole)
  8614. {
  8615. _pole->QueryInterface(IID_IUnknown, (void **) &(pvarargOut->punkVal));
  8616. }
  8617. }
  8618. if (pvarargOut->punkVal != NULL)
  8619. {
  8620. pvarargOut->vt = VT_UNKNOWN;
  8621. hres = S_OK;
  8622. }
  8623. else
  8624. {
  8625. hres = E_FAIL;
  8626. }
  8627. return hres;
  8628. break;
  8629. case SHDVID_GETPENDINGURL:
  8630. ASSERT( pvarargOut);
  8631. VariantClearLazy(pvarargOut);
  8632. hres = _GetUrlVariant(pvarargOut);
  8633. return hres;
  8634. break;
  8635. default:
  8636. break;
  8637. }
  8638. }
  8639. BOOL fNearest = _ExecNearest(pguidCmdGroup, nCmdID, TRUE);
  8640. if (fNearest)
  8641. hres = OnExec(pguidCmdGroup, nCmdID, nCmdexecopt, pvarargIn, pvarargOut);
  8642. if (FAILED(hres) && _pmsot) {
  8643. hres = _pmsot->Exec(pguidCmdGroup, nCmdID, nCmdexecopt, pvarargIn, pvarargOut);
  8644. //
  8645. // APPHACK:
  8646. // PPT in Office 97 fails to print if we pass PRINTFLAG_PROMPTUSER
  8647. // and returns E_INVALIDARG. If we detect this case, we should retry
  8648. // without this flag. PPT will popup the print dialog. (SatoNa)
  8649. //
  8650. if (hres == E_INVALIDARG
  8651. && (_dwAppHack & BROWSERFLAG_PRINTPROMPTUI)
  8652. && pguidCmdGroup == NULL
  8653. && nCmdID == OLECMDID_PRINT)
  8654. {
  8655. TraceMsg(TF_SHDAPPHACK, "DOH::ExecDown(OLECMDID_PRINT) removing PRINTFLAG_PROMPTUSER");
  8656. nCmdexecopt &= ~OLECMDEXECOPT_DONTPROMPTUSER;
  8657. hres = _pmsot->Exec(pguidCmdGroup, nCmdID, nCmdexecopt, pvarargIn, pvarargOut);
  8658. }
  8659. }
  8660. if (FAILED(hres) && !fNearest)
  8661. hres = OnExec(pguidCmdGroup, nCmdID, nCmdexecopt, pvarargIn, pvarargOut);
  8662. return hres;
  8663. }
  8664. HRESULT CDocObjectHost::QueryStatusDown(const GUID *pguidCmdGroup, ULONG cCmds, OLECMD rgCmds[], OLECMDTEXT *pcmdtext)
  8665. {
  8666. HRESULT hres;
  8667. if (_pmsot)
  8668. hres = _pmsot->QueryStatus(pguidCmdGroup, cCmds, rgCmds, pcmdtext);
  8669. else if (pguidCmdGroup && IsEqualGUID(CGID_ShellDocView, *pguidCmdGroup))
  8670. hres = IUnknown_QueryStatus(_pole, pguidCmdGroup, cCmds, rgCmds, pcmdtext);
  8671. return OnQueryStatus(pguidCmdGroup, cCmds, rgCmds, pcmdtext, hres);
  8672. }
  8673. HRESULT CDocObjectHost::Invoke(DISPID dispidMember, REFIID iid, LCID lcid, WORD wFlags, DISPPARAMS FAR* pdispparams,
  8674. VARIANT FAR* pVarResult,EXCEPINFO FAR* pexcepinfo,UINT FAR* puArgErr)
  8675. {
  8676. if (!_peds)
  8677. return(E_NOTIMPL);
  8678. return _peds->OnInvoke(dispidMember, iid, lcid, wFlags, pdispparams, pVarResult,pexcepinfo,puArgErr);
  8679. }
  8680. //*** IOleControlSite {
  8681. HRESULT CDocObjectHost::OnControlInfoChanged()
  8682. {
  8683. HRESULT hres = E_NOTIMPL;
  8684. if (_pedsHelper)
  8685. {
  8686. hres = _pedsHelper->OnOnControlInfoChanged();
  8687. }
  8688. return(hres);
  8689. }
  8690. //*** CDOH::TranslateAccelerator (IOCS::TranslateAccelerator)
  8691. // NOTES
  8692. // trident (or any other DO that uses IOCS::TA) calls us back when TABing
  8693. // off the last link. to handle it, we flag it for our original caller
  8694. // (IOIPAO::TA), and then pretend we handled it by telling trident S_OK.
  8695. // trident returns S_OK to IOIPAO::TA, which checks the flag and says
  8696. // 'trident did *not* handle it' by returning S_FALSE. that propagates
  8697. // way up to the top where it sees it was a TAB so it does a CycleFocus.
  8698. //
  8699. // that's how we do it when we're top-level. when we're a frameset, we
  8700. // need to do it the 'real' way, sending it up to our parent IOCS.
  8701. HRESULT CDocObjectHost::TranslateAccelerator(MSG __RPC_FAR *pmsg,DWORD grfModifiers)
  8702. {
  8703. HRESULT hres = S_FALSE;
  8704. if (_peds) {
  8705. // try it the real way in case we're in a frameset
  8706. // top level: we'll do CImpIExpDispSupport::OnTA which does E_NOTIMPL,
  8707. // frameset: we'll do CWebBrowserOC::OnTA which talks to trident
  8708. // What if trident (or OC?) gives back E_NOTIMPL too?
  8709. TraceMsg(DM_FOCUS, "DOH::IOCS::TA peds!=NULL forward");
  8710. hres = _peds->OnTranslateAccelerator(pmsg, grfModifiers);
  8711. }
  8712. if (hres != S_OK) {
  8713. // we're at top level (E_NOTIMPL), so we can fake it
  8714. // (or alternately we're not, but our parent said S_FALSE)
  8715. #ifdef DEBUG
  8716. if (_peds && SUCCEEDED(hres)) {
  8717. // i'm curious if we ever hit this
  8718. TraceMsg(DM_WARNING, "DOH::IOCS::TA parent hres=%x (!=S_OK)", hres);
  8719. }
  8720. #endif
  8721. hres = S_FALSE;
  8722. if (IsVK_TABCycler(pmsg)) {
  8723. TraceMsg(TF_SHDUIACTIVATE, "DOH::TranslateAccelerator called with VK_TAB");
  8724. TraceMsg(DM_FOCUS, "DOH::IOCS::TA(wParam=VK_TAB) ret _fCycleFocus=TRUE hr=S_OK (lie)");
  8725. // defer it, set flag for CDOH::IOIPAO::TA, and pretend we handled it
  8726. ASSERT(!_fCycleFocus);
  8727. _fCycleFocus = TRUE;
  8728. hres = S_OK;
  8729. }
  8730. }
  8731. return hres;
  8732. }
  8733. // }
  8734. //========================================================================
  8735. // CDocObjectHost::CPicsProcessor
  8736. //========================================================================
  8737. CDocObjectHost::CPicsProcessor::CPicsProcessor()
  8738. {
  8739. _fPicsAccessAllowed = TRUE; /* assume no ratings checks unless we download */
  8740. _fInDialog = FALSE;
  8741. _fTerminated = FALSE;
  8742. _fbPicsWaitFlags = 0;
  8743. }
  8744. STDMETHODIMP CDocObjectHost::CPicsProcessor::QueryInterface(REFIID riid, void ** ppvObj)
  8745. {
  8746. if (IsEqualIID(riid, IID_IOleCommandTarget) ||
  8747. IsEqualIID(riid, IID_IUnknown))
  8748. {
  8749. *ppvObj = SAFECAST(this, IOleCommandTarget *);
  8750. }
  8751. else
  8752. {
  8753. *ppvObj = NULL;
  8754. return E_NOINTERFACE;
  8755. }
  8756. CDocObjectHost* pdoh = _pdoh;
  8757. return pdoh->AddRef();
  8758. }
  8759. STDMETHODIMP_(ULONG) CDocObjectHost::CPicsProcessor::AddRef(void)
  8760. {
  8761. return _pdoh->AddRef();
  8762. }
  8763. STDMETHODIMP_(ULONG) CDocObjectHost::CPicsProcessor::Release(void)
  8764. {
  8765. return _pdoh->Release();
  8766. }
  8767. STDMETHODIMP CDocObjectHost::CPicsProcessor::QueryStatus(const GUID *pguidCmdGroup,
  8768. ULONG cCmds, OLECMD rgCmds[], OLECMDTEXT *pcmdtext)
  8769. {
  8770. return E_NOTIMPL;
  8771. }
  8772. STDMETHODIMP CDocObjectHost::CPicsProcessor::Exec(const GUID *pguidCmdGroup,
  8773. DWORD nCmdID, DWORD nCmdexecopt, VARIANTARG *pvarargIn, VARIANTARG *pvarargOut)
  8774. {
  8775. if (IsEqualGUID(CGID_ShellDocView, *pguidCmdGroup))
  8776. {
  8777. switch (nCmdID)
  8778. {
  8779. case SHDVID_PICSLABELFOUND:
  8780. if (pvarargIn->vt == (VT_BSTR)) {
  8781. _dwPicsLabelSource = PICS_LABEL_FROM_PAGE;
  8782. _HandleInDocumentLabel(pvarargIn->bstrVal);
  8783. }
  8784. return NOERROR;
  8785. case SHDVID_PICSLABELFOUNDINHTTPHEADER:
  8786. if (pvarargIn->vt == (VT_BSTR)) {
  8787. _dwPicsLabelSource = PICS_LABEL_FROM_HEADER;
  8788. _HandleInDocumentLabel(pvarargIn->bstrVal);
  8789. }
  8790. return NOERROR;
  8791. case SHDVID_NOMOREPICSLABELS:
  8792. _HandleDocumentEnd();
  8793. return NOERROR;
  8794. default:
  8795. return OLECMDERR_E_NOTSUPPORTED;
  8796. }
  8797. }
  8798. return OLECMDERR_E_UNKNOWNGROUP;
  8799. }
  8800. UINT CDocObjectHost::CPicsProcessor::_PicsBlockingDialog()
  8801. {
  8802. LPCTSTR pszURL = _pszPicsURL;
  8803. TraceMsg(DM_PICS, "CDOH::CPP::_PicsBlockingDialog() %s", pszURL);
  8804. _StartPicsRootQuery(pszURL);
  8805. _pdoh->_fDrawBackground = TRUE;
  8806. ::InvalidateRect(_pdoh->_hwnd, NULL, TRUE); /* mega cheesy, but only way to get browser window erased */
  8807. /* This message loop is used to block in non-HTML cases, where we really
  8808. * want to block the download process until ratings are checked. In the
  8809. * HTML case, this function is never called until the wait flags are all
  8810. * clear, so the message loop is skipped and we go straight to the denial
  8811. * dialog.
  8812. */
  8813. while (_fbPicsWaitFlags) {
  8814. TraceMsg(DM_PICS, "CDOH::CPP::_PicsBlockingDialog entering msg loop, waitflags=%x", (DWORD)_fbPicsWaitFlags);
  8815. MSG msg;
  8816. if (GetMessage(&msg, NULL, 0, 0)) {
  8817. TranslateMessage(&msg);
  8818. DispatchMessage(&msg);
  8819. }
  8820. }
  8821. if (!_fPicsAccessAllowed) {
  8822. TraceMsg(DM_PICS, "CDOH::CPP::_PicsBlockingDialog, access denied");
  8823. BOOL fOldInDialog;
  8824. // If this is silent-mode (no UI == screensaver), always deny access
  8825. // without any dialog.
  8826. BOOL fFrameIsSilent = FALSE; // Assume non-silent
  8827. _pdoh->_GetOfflineSilent(NULL, &fFrameIsSilent);
  8828. if (fFrameIsSilent) {
  8829. TraceMsg(DM_PICS, "CDOH::CPP::_PicsBlockingDialog access denied in silent mode, aborting");
  8830. return IDCANCEL;
  8831. }
  8832. // Protect against us getting whacked out
  8833. // from under ourselves
  8834. fOldInDialog = _fInDialog;
  8835. _fInDialog = TRUE;
  8836. // This doesn't get down to trident to stop it from navigating.
  8837. // We need some sort of navigation freeze mechanism.
  8838. _pdoh->_EnableModeless(FALSE);
  8839. HRESULT hres = S_OK;
  8840. IOleCommandTarget *pcmdtTop;
  8841. if (SUCCEEDED(_pdoh->QueryService(SID_STopLevelBrowser, IID_IOleCommandTarget, (void **)&pcmdtTop))) {
  8842. VARIANTARG v = { 0 };
  8843. v.vt = VT_INT_PTR;
  8844. v.byref = _pRatingDetails;
  8845. hres = pcmdtTop->Exec(&CGID_ShellDocView, SHDVID_PICSBLOCKINGUI, 0, &v, NULL);
  8846. pcmdtTop->Release();
  8847. }
  8848. UINT uRet = (hres == S_OK) ? IDOK : IDCANCEL;
  8849. _pdoh->_EnableModeless(TRUE);
  8850. _fPicsAccessAllowed = (uRet == IDOK);
  8851. _fInDialog = fOldInDialog;
  8852. TraceMsg(DM_PICS, "CDOH::CPP::_PicsBlockingDialog returning %d", uRet);
  8853. return uRet;
  8854. }
  8855. else {
  8856. TraceMsg(DM_PICS, "CDOH::CPP::_PicsBlockingDialog, access allowed");
  8857. return IDOK;
  8858. }
  8859. }
  8860. HRESULT CDocObjectHost::CPicsProcessor::_StartPicsQuery(LPCOLESTR pwszRawURL)
  8861. {
  8862. #ifdef DEBUG
  8863. HRESULT hres;
  8864. IRatingNotification* pRatingNotify;
  8865. hres = _pdoh->QueryService(SID_SRatingNotification, IID_PPV_ARG(IRatingNotification, &pRatingNotify));
  8866. if (SUCCEEDED(hres))
  8867. {
  8868. ASSERT(S_OK == pRatingNotify->IsRatingsEnabled());
  8869. pRatingNotify->Release();
  8870. }
  8871. else
  8872. {
  8873. ASSERT(IS_RATINGS_ENABLED() && ::RatingEnabledQuery() == S_OK);
  8874. }
  8875. #endif DEBUG
  8876. TraceMsg(DM_PICS, "CDOH::CPP::_StartPicsQuery entered with ratings enabled");
  8877. BOOL fEnforce = TRUE;
  8878. if (_pszPicsURL != NULL) {
  8879. delete _pszPicsURL;
  8880. _pszPicsURL = NULL;
  8881. }
  8882. {
  8883. /* We have to call CoInternetGetSecurityUrl to convert pluggable
  8884. * protocols into known schemes, so we know whether we need to
  8885. * enforce ratings on them.
  8886. */
  8887. LPOLESTR pwszSecurityURL = NULL;
  8888. if (SUCCEEDED(CoInternetGetSecurityUrl(pwszRawURL, &pwszSecurityURL,
  8889. PSU_SECURITY_URL_ONLY, 0)))
  8890. {
  8891. // List of protocols for which we never enforce ratings.
  8892. if (!StrCmpNIW(pwszSecurityURL, L"file:", 5) ||
  8893. !StrCmpNIW(pwszSecurityURL, L"about:", 6) ||
  8894. !StrCmpNIW(pwszSecurityURL, L"mk:", 3)) {
  8895. fEnforce = FALSE;
  8896. }
  8897. else {
  8898. Str_SetPtr(&_pszPicsURL, pwszSecurityURL);
  8899. }
  8900. OleFree(pwszSecurityURL);
  8901. }
  8902. }
  8903. if (fEnforce) {
  8904. TraceMsg(DM_PICS, "CDOH::CPP::_StartPicsQuery (%s) turning on wait flags", _pszPicsURL);
  8905. _fbPicsWaitFlags = PICS_WAIT_FOR_ASYNC
  8906. | PICS_WAIT_FOR_INDOC
  8907. | PICS_WAIT_FOR_END
  8908. | PICS_WAIT_FOR_ROOT
  8909. ;
  8910. _fPicsAccessAllowed = 0;
  8911. HRESULT hr;
  8912. _dwPicsSerialNumber = ::_AddPicsQuery(_pdoh->_hwnd);
  8913. if (_dwPicsSerialNumber == 0)
  8914. hr = E_OUTOFMEMORY;
  8915. else
  8916. {
  8917. //
  8918. // The ratings apis are ansi.
  8919. //
  8920. CHAR szURL[MAX_URL_STRING];
  8921. SHUnicodeToAnsi(_pszPicsURL, szURL, ARRAYSIZE(szURL));
  8922. hr = RatingObtainQuery(szURL, _dwPicsSerialNumber, RatingObtainQueryCallback, &_hPicsQuery);
  8923. }
  8924. if (FAILED(hr)) {
  8925. TraceMsg(DM_PICS, "CDOH::CPP::_StartPicsQuery no async query queued");
  8926. ::_RemovePicsQuery(_dwPicsSerialNumber);
  8927. _dwPicsSerialNumber = 0;
  8928. _fbPicsWaitFlags &= ~PICS_WAIT_FOR_ASYNC;
  8929. }
  8930. else {
  8931. TraceMsg(DM_PICS, "CDOH::CPP::_StartPicsQuery async query queued");
  8932. }
  8933. }
  8934. else {
  8935. // JHarding: IF we're not enforcing, we need to tell anyone who's waiting on an answer.
  8936. return S_FALSE;
  8937. }
  8938. return S_OK;
  8939. }
  8940. void CDocObjectHost::CPicsProcessor::_HandleDocumentEnd(void)
  8941. {
  8942. BYTE bFlag = (_pRootDownload != NULL) ? PICS_WAIT_FOR_ROOT : PICS_WAIT_FOR_END;
  8943. TraceMsg(DM_PICS, "CDOH::CPP::_HandleDocumentEnd -- no more PICS labels from source %x", (DWORD)bFlag);
  8944. // If we have a private window, we'll make sure the root download is gone when we
  8945. // notify the window. This simplifies the lifetime of the secondary CPicsProcessors
  8946. if (!_pPrivWindow)
  8947. {
  8948. if (_pRootDownload != NULL) {
  8949. ::PostMessage(_pdoh->_hwnd, WM_PICS_ROOTDOWNLOADCOMPLETE, 0, 0);
  8950. }
  8951. else {
  8952. /* End of document; revoke the IOleCommandTarget we gave to the document,
  8953. * so it won't send us any more notifications.
  8954. */
  8955. VARIANTARG v;
  8956. v.vt = VT_UNKNOWN;
  8957. v.punkVal = NULL;
  8958. IUnknown_Exec(_pdoh->_pole, &CGID_ShellDocView, SHDVID_CANSUPPORTPICS, 0, &v, NULL);
  8959. }
  8960. }
  8961. else
  8962. {
  8963. if (_pRootDownload == NULL)
  8964. {
  8965. _pPrivWindow->SetPICSTarget(NULL);
  8966. }
  8967. }
  8968. if (!(_fbPicsWaitFlags & bFlag)) {
  8969. TraceMsg(DM_PICS, "CDOH::CPP::_HandleDocumentEnd skipping due to waitflags %x", (DWORD)_fbPicsWaitFlags);
  8970. return;
  8971. }
  8972. _fbPicsWaitFlags &= ~PICS_WAIT_FOR_INDOC; /* we know we won't get any more indoc labels */
  8973. LPVOID pDetails = NULL;
  8974. //
  8975. // Ratings has only ansi apis!
  8976. //
  8977. CHAR szURL[MAX_URL_STRING];
  8978. SHUnicodeToAnsi(_pszPicsURL, szURL, ARRAYSIZE(szURL));
  8979. HRESULT hres = ::RatingCheckUserAccess(NULL, szURL, NULL, NULL, _dwPicsLabelSource, &pDetails);
  8980. _GotLabel(hres, pDetails, bFlag);
  8981. if (_pRootDownload == NULL) {
  8982. if (_fbPicsWaitFlags)
  8983. _StartPicsRootQuery(_pszPicsURL);
  8984. }
  8985. }
  8986. void CDocObjectHost::CPicsProcessor::_GotLabel(HRESULT hres, LPVOID pDetails, BYTE bfSource)
  8987. {
  8988. TraceMsg(DM_PICS, "CDOH::CPP::_GotLabel hres=%x, source=%x, waitflags=%x", hres, (DWORD)bfSource, (DWORD)_fbPicsWaitFlags);
  8989. /* If we've already gotten a result from this or a more significant source,
  8990. * ignore this one.
  8991. */
  8992. if (!(_fbPicsWaitFlags & bfSource)) {
  8993. TraceMsg(DM_PICS, "CDOH::CPP::_GotLabel already got label from that source");
  8994. if (pDetails != NULL)
  8995. {
  8996. ::RatingFreeDetails(pDetails);
  8997. pDetails = NULL;
  8998. }
  8999. }
  9000. else {
  9001. /* If the result is an error somehow (label doesn't apply, etc.), and
  9002. * we can expect more labels from this source, then we don't do anything
  9003. * except save the rating details if we haven't got any yet.
  9004. */
  9005. if (FAILED(hres) && (PICS_MULTIPLE_FLAGS & bfSource)) {
  9006. TraceMsg(DM_PICS, "CDOH::CPP::_GotLabel label error and may be multiple");
  9007. if (_pRatingDetails == NULL)
  9008. {
  9009. _pRatingDetails = pDetails;
  9010. }
  9011. else
  9012. {
  9013. if ( pDetails )
  9014. {
  9015. ::RatingFreeDetails(pDetails);
  9016. pDetails = NULL;
  9017. }
  9018. }
  9019. }
  9020. else {
  9021. /* Either we got a definitive answer from this rating source, or
  9022. * this is the only answer we'll get from it. We clear at least
  9023. * the flag for this source so we know we've heard from it. If
  9024. * the response was not an error, then clear flags for all less
  9025. * significant sources as well, so that we'll ignore them. On
  9026. * the other hand, if this source returned an error, it didn't
  9027. * give us anything useful, so we keep looking at other sources.
  9028. */
  9029. if (SUCCEEDED(hres))
  9030. _fbPicsWaitFlags &= bfSource - 1;
  9031. else
  9032. _fbPicsWaitFlags &= ~bfSource;
  9033. TraceMsg(DM_PICS, "CDOH::CPP::_GotLabel, waitflags now %x", (DWORD)_fbPicsWaitFlags);
  9034. if (hres == S_OK) {
  9035. TraceMsg(DM_PICS, "CDOH::CPP::_GotLabel allowing access");
  9036. if ( pDetails )
  9037. {
  9038. ::RatingFreeDetails( pDetails ); /* don't need this if access allowed */
  9039. pDetails = NULL;
  9040. }
  9041. _fPicsAccessAllowed = 1;
  9042. }
  9043. else {
  9044. /* Access denied or error. Meaningful details from this result
  9045. * can override details from an earlier, less significant
  9046. * result. Only explicitly deny access if not an error,
  9047. * though (this handles the valid root label followed by
  9048. * invalid in-document label, for example).
  9049. */
  9050. if (pDetails != NULL) {
  9051. if (_pRatingDetails != NULL)
  9052. {
  9053. ::RatingFreeDetails(_pRatingDetails);
  9054. }
  9055. _pRatingDetails = pDetails;
  9056. }
  9057. if (SUCCEEDED(hres))
  9058. _fPicsAccessAllowed = 0;
  9059. }
  9060. }
  9061. }
  9062. // If we are a secondary processor (_pPrivWindow != NULL) then
  9063. // we always want to report when the check is complete
  9064. //
  9065. if ((_pPrivWindow || _pdoh->_fPicsBlockLate) && !_fbPicsWaitFlags)
  9066. {
  9067. _HandlePicsChecksComplete();
  9068. }
  9069. }
  9070. void CDocObjectHost::CPicsProcessor::_HandleInDocumentLabel(LPCTSTR pszLabel)
  9071. {
  9072. BYTE bFlag = (_pRootDownload != NULL) ? PICS_WAIT_FOR_ROOT : PICS_WAIT_FOR_INDOC;
  9073. TraceMsg(DM_PICS, "CDOH::CPP::_HandleInDocumentLabel source %x gave label %s", (DWORD)bFlag, pszLabel);
  9074. if (!(_fbPicsWaitFlags & bFlag)) {
  9075. TraceMsg(DM_PICS, "CDOH::CPP::_HandleInDocumentLabel rejecting based on waitflags %x", (DWORD)_fbPicsWaitFlags);
  9076. return;
  9077. }
  9078. LPVOID pDetails = NULL;
  9079. //
  9080. // Ratings has only ansi apis!
  9081. //
  9082. CHAR szURL[MAX_URL_STRING];
  9083. SHUnicodeToAnsi(_pszPicsURL, szURL, ARRAYSIZE(szURL));
  9084. UINT cbMultiByte = WideCharToMultiByte(CP_ACP, 0, pszLabel,
  9085. -1, NULL, 0, NULL, NULL);
  9086. if (cbMultiByte > 0) {
  9087. char *pszLabelAnsi = new char[cbMultiByte+1];
  9088. if (pszLabelAnsi != NULL)
  9089. {
  9090. if (WideCharToMultiByte(CP_ACP, 0, pszLabel, -1, pszLabelAnsi,
  9091. cbMultiByte+1, NULL, NULL))
  9092. {
  9093. HRESULT hres = ::RatingCheckUserAccess(NULL, szURL,
  9094. pszLabelAnsi, NULL, _dwPicsLabelSource,
  9095. &pDetails);
  9096. _GotLabel(hres, pDetails, bFlag);
  9097. }
  9098. delete [] pszLabelAnsi;
  9099. }
  9100. }
  9101. }
  9102. /* This function parses the URL being downloaded and, if the URL doesn't
  9103. * already refer to the root document of the site, sets up a subordinate
  9104. * CDocObjectHost to download that root document, so we can get ratings
  9105. * out of it.
  9106. */
  9107. void CDocObjectHost::CPicsProcessor::_StartPicsRootQuery(LPCTSTR pszURL)
  9108. {
  9109. if (_fbPicsWaitFlags & PICS_WAIT_FOR_ROOT) {
  9110. BOOL fQueued = FALSE;
  9111. TraceMsg(DM_PICS, "CDOH::CPP::_StartPicsRootQuery parsing %s", pszURL);
  9112. WCHAR wszRootURL[MAX_URL_STRING+1];
  9113. DWORD cchResult;
  9114. /* The pszURL we're passed is actually the result of calling
  9115. * CoInternetGetSecurityUrl, and so may not be the scheme that
  9116. * the caller is browsing to. To support pluggable protocols
  9117. * determining the root location themselves, we first use the
  9118. * URL reported by _GetCurrentPage, which may refer to a
  9119. * pluggable protocol; if that fails, we use the more standard
  9120. * URL.
  9121. */
  9122. HRESULT hres = INET_E_DEFAULT_ACTION;
  9123. LPOLESTR pwszURL = NULL;
  9124. if (SUCCEEDED(_pdoh->_GetCurrentPageW(&pwszURL, TRUE)))
  9125. {
  9126. hres = CoInternetParseUrl(pwszURL, PARSE_ROOTDOCUMENT, 0, wszRootURL,
  9127. ARRAYSIZE(wszRootURL), &cchResult, 0);
  9128. OleFree(pwszURL);
  9129. }
  9130. if (pszURL != NULL && (hres == INET_E_DEFAULT_ACTION || hres == E_FAIL)) {
  9131. /* Pluggable protocol doesn't support PARSE_ROOTDOCUMENT. Use the
  9132. * more standard URL we were supplied with.
  9133. */
  9134. hres = CoInternetParseUrl(pszURL, PARSE_ROOTDOCUMENT, 0, wszRootURL,
  9135. ARRAYSIZE(wszRootURL), &cchResult, 0);
  9136. }
  9137. if (SUCCEEDED(hres)) {
  9138. IMoniker *pmk = NULL;
  9139. hres = MonikerFromURL(wszRootURL, &pmk);
  9140. if (SUCCEEDED(hres)) {
  9141. BOOL fFrameIsSilent = FALSE;
  9142. BOOL fFrameIsOffline = FALSE;
  9143. _pdoh->_GetOfflineSilent(&fFrameIsOffline, &fFrameIsSilent);
  9144. _pRootDownload = new CPicsRootDownload(this, fFrameIsOffline, fFrameIsSilent);
  9145. if (_pRootDownload != NULL) {
  9146. TraceMsg(DM_PICS, "CDOH::CPP::_StartPicsRootQuery starting download");
  9147. hres = _pRootDownload->StartDownload(pmk);
  9148. if (SUCCEEDED(hres))
  9149. fQueued = TRUE;
  9150. }
  9151. }
  9152. if (pmk != NULL)
  9153. pmk->Release();
  9154. }
  9155. if (!fQueued) {
  9156. _fbPicsWaitFlags &= ~PICS_WAIT_FOR_ROOT;
  9157. TraceMsg(DM_PICS, "CDOH::CPP::_StartPicsRootQuery queueing failed, waitflags now %x", (DWORD)_fbPicsWaitFlags);
  9158. if (!_fbPicsWaitFlags) {
  9159. _HandlePicsChecksComplete();
  9160. }
  9161. }
  9162. }
  9163. else {
  9164. TraceMsg(DM_PICS, "CDOH::CPP::_StartPicsRootQuery no query queued, waitflags=%x", (DWORD)_fbPicsWaitFlags);
  9165. }
  9166. }
  9167. void CDocObjectHost::CPicsProcessor::_HandlePicsChecksComplete(void)
  9168. {
  9169. if (!_fPicsAccessAllowed)
  9170. {
  9171. TraceMsg(DM_PICS, "CDOH::CPP::_HandlePicsChecksComplete access denied, posting WM_PICS_DOBLOCKINGUI to hwnd %x", (DWORD_PTR)_pdoh->_hwnd);
  9172. /* Allow download of this and other frames to continue while we post
  9173. * the denial UI.
  9174. */
  9175. if (!PostMessage(_pdoh->_hwnd, WM_PICS_DOBLOCKINGUI, 0, _GetKey())) {
  9176. TraceMsg(DM_PICS, "CDOH::CPP::_HandlePicsChecksComplete couldn't post message!");
  9177. }
  9178. }
  9179. else
  9180. {
  9181. if( _pPrivWindow )
  9182. {
  9183. TraceMsg(DM_PICS, "CDOH::CPP::_HandlePicsChecksComplete access allowed, posting WM_PICS_RESULTTOPRIVWIN");
  9184. if (!PostMessage( _pdoh->_hwnd, WM_PICS_RESULTTOPRIVWIN, IDOK, _GetKey()))
  9185. {
  9186. TraceMsg(DM_PICS, "CDOH::CPP::_HandlePicsChecksComplete couldn't post message!");
  9187. }
  9188. }
  9189. else
  9190. {
  9191. TraceMsg(DM_PICS, "CDOH::CPP::_HandlePicsChecksComplete access allowed, execing ACTIVATEMENOW");
  9192. if (!_pdoh->_fSetTarget && _pdoh->_pmsoctBrowser)
  9193. {
  9194. _pdoh->_pmsoctBrowser->Exec(&CGID_ShellDocView, SHDVID_ACTIVATEMENOW, NULL, NULL, NULL);
  9195. }
  9196. }
  9197. }
  9198. }
  9199. void CDocObjectHost::CPicsProcessor::_ReInit()
  9200. {
  9201. TraceMsg(DM_PICS, "CDOH::CPP::_ReInit");
  9202. _fPicsAccessAllowed = TRUE;
  9203. _fInDialog = FALSE;
  9204. _fTerminated = FALSE;
  9205. _fbPicsWaitFlags = 0;
  9206. _dwPicsLabelSource = 0;
  9207. if (_pPrivWindow)
  9208. {
  9209. _pPrivWindow->SetPICSTarget(NULL);
  9210. _pPrivWindow->Release();
  9211. _pPrivWindow = NULL;
  9212. }
  9213. if (_pRootDownload != NULL) {
  9214. _pRootDownload->CleanUp();
  9215. ATOMICRELEASET(_pRootDownload,CPicsRootDownload);
  9216. }
  9217. _pPicsProcNext = NULL;
  9218. if (_pRatingDetails){
  9219. ::RatingFreeDetails(_pRatingDetails);
  9220. _pRatingDetails = NULL;
  9221. }
  9222. if (_dwPicsSerialNumber) {
  9223. ::_RemovePicsQuery(_dwPicsSerialNumber);
  9224. _dwPicsSerialNumber = 0;
  9225. }
  9226. if (_hPicsQuery)
  9227. {
  9228. RatingObtainCancel(_hPicsQuery);
  9229. _hPicsQuery = NULL;
  9230. }
  9231. if ( _pszPicsURL )
  9232. {
  9233. delete _pszPicsURL;
  9234. _pszPicsURL = NULL;
  9235. }
  9236. }
  9237. void
  9238. CDocObjectHost::CPicsProcessor::_Terminate()
  9239. {
  9240. ASSERT( this != &(_pdoh->_PicsProcBase) );
  9241. if (!_fInDialog)
  9242. {
  9243. delete this;
  9244. }
  9245. else
  9246. {
  9247. _fTerminated = TRUE;
  9248. }
  9249. }
  9250. CDocObjectHost::CPicsProcessor *
  9251. CDocObjectHost::_GetPicsProcessorFromKey(LONG_PTR lKey)
  9252. {
  9253. CPicsProcessor * ppp = &_PicsProcBase;
  9254. while( ppp )
  9255. {
  9256. if (ppp->_GetKey() == lKey)
  9257. return ppp;
  9258. ppp = ppp->_pPicsProcNext;
  9259. }
  9260. return NULL;
  9261. }
  9262. CDocObjectHost::CPicsProcessor *
  9263. CDocObjectHost::_GetPicsProcessorFromSerialNumber(DWORD dwSerial)
  9264. {
  9265. CPicsProcessor * ppp = &_PicsProcBase;
  9266. ASSERT( dwSerial != NULL );
  9267. while( ppp )
  9268. {
  9269. if (ppp->_dwPicsSerialNumber == dwSerial)
  9270. return ppp;
  9271. ppp = ppp->_pPicsProcNext;
  9272. }
  9273. return NULL;
  9274. }
  9275. void CDocObjectHost::_StartBasePicsProcessor()
  9276. {
  9277. HRESULT hres;
  9278. BOOL bRatingsEnabled;
  9279. IRatingNotification* pRatingNotify;
  9280. hres = QueryService(SID_SRatingNotification, IID_PPV_ARG(IRatingNotification, &pRatingNotify));
  9281. if (SUCCEEDED(hres))
  9282. {
  9283. bRatingsEnabled = pRatingNotify->IsRatingsEnabled() ? FALSE : TRUE;
  9284. pRatingNotify->Release();
  9285. }
  9286. else
  9287. {
  9288. bRatingsEnabled = IS_RATINGS_ENABLED() && ::RatingEnabledQuery() == S_OK;
  9289. }
  9290. if(bRatingsEnabled)
  9291. {
  9292. TraceMsg(DM_PICS, "CDOH::_StartBasePicsProcessor entered with ratings enabled");
  9293. LPOLESTR pwszRawURL = NULL;
  9294. if (SUCCEEDED(_GetCurrentPageW(&pwszRawURL, TRUE)))
  9295. {
  9296. _PicsProcBase._StartPicsQuery(pwszRawURL);
  9297. OleFree(pwszRawURL);
  9298. }
  9299. }
  9300. }
  9301. HRESULT CDocObjectHost::_StartSecondaryPicsProcessor(IHTMLPrivateWindow * pPrivWin)
  9302. {
  9303. HRESULT hr = S_FALSE;
  9304. ASSERT( pPrivWin );
  9305. HRESULT hres;
  9306. BOOL bRatingsEnabled;
  9307. IRatingNotification* pRatingNotify;
  9308. hres = QueryService(SID_SRatingNotification, IID_PPV_ARG(IRatingNotification, &pRatingNotify));
  9309. if (SUCCEEDED(hres))
  9310. {
  9311. bRatingsEnabled = pRatingNotify->IsRatingsEnabled() ? FALSE : TRUE;
  9312. pRatingNotify->Release();
  9313. }
  9314. else
  9315. {
  9316. bRatingsEnabled = IS_RATINGS_ENABLED() && ::RatingEnabledQuery() == S_OK;
  9317. }
  9318. if (bRatingsEnabled)
  9319. {
  9320. LPOLESTR pwszURL = NULL;
  9321. // CWindow::GetPendingUrl() has LPOLESTR * parameter.
  9322. hr = pPrivWin->GetPendingUrl( &pwszURL );
  9323. if ( SUCCEEDED(hr) && pwszURL )
  9324. {
  9325. CPicsProcessor * pPicsProc = new CPicsProcessor;
  9326. if( pPicsProc )
  9327. {
  9328. pPicsProc->_pdoh = this;
  9329. pPicsProc->_pPrivWindow = pPrivWin;
  9330. pPrivWin->AddRef();
  9331. pPicsProc->_dwKey = _dwPicsKeyBase++;
  9332. hr = pPicsProc->_StartPicsQuery( pwszURL );
  9333. if( hr == S_FALSE )
  9334. {
  9335. delete pPicsProc;
  9336. }
  9337. else
  9338. {
  9339. pPicsProc->_pPicsProcNext = _PicsProcBase._pPicsProcNext;
  9340. _PicsProcBase._pPicsProcNext = pPicsProc;
  9341. pPrivWin->SetPICSTarget( SAFECAST(pPicsProc, IOleCommandTarget *) );
  9342. }
  9343. }
  9344. else
  9345. {
  9346. hr = E_OUTOFMEMORY;
  9347. }
  9348. OleFree( pwszURL );
  9349. }
  9350. }
  9351. return hr;
  9352. }
  9353. HRESULT CDocObjectHost::_RemovePicsProcessorByKey(LONG_PTR lKey)
  9354. {
  9355. ASSERT( lKey != 0 );
  9356. // The base Proc has a 0 key and should never be removed
  9357. CPicsProcessor * ppp = &_PicsProcBase;
  9358. CPicsProcessor * pppLast = NULL;
  9359. while( ppp )
  9360. {
  9361. if (ppp->_GetKey() == lKey)
  9362. {
  9363. ASSERT(pppLast);
  9364. pppLast->_pPicsProcNext = ppp->_pPicsProcNext;
  9365. ppp->_Terminate();
  9366. return S_OK;
  9367. }
  9368. pppLast = ppp;
  9369. ppp = ppp->_pPicsProcNext;
  9370. }
  9371. return S_FALSE;
  9372. }
  9373. HRESULT CDocObjectHost::_RemovePicsProcessorByPrivWindowUnk(IUnknown* pUnkFind)
  9374. {
  9375. ASSERT( pUnkFind );
  9376. // The base Proc has a 0 key and should never be removed
  9377. CPicsProcessor * ppp = &_PicsProcBase;
  9378. CPicsProcessor * pppLast = NULL;
  9379. while( ppp )
  9380. {
  9381. if (ppp->_pPrivWindow)
  9382. {
  9383. IUnknown * pUnkThisOne;
  9384. if (SUCCEEDED( ppp->_pPrivWindow->QueryInterface( IID_IUnknown, (void**)&pUnkThisOne ) ))
  9385. {
  9386. if (pUnkThisOne == pUnkFind)
  9387. {
  9388. ASSERT(pppLast);
  9389. pppLast->_pPicsProcNext = ppp->_pPicsProcNext;
  9390. ppp->_Terminate();
  9391. pUnkThisOne->Release();
  9392. return S_OK;
  9393. }
  9394. pUnkThisOne->Release();
  9395. }
  9396. }
  9397. pppLast = ppp;
  9398. ppp = ppp->_pPicsProcNext;
  9399. }
  9400. return S_FALSE;
  9401. }
  9402. HRESULT CDocObjectHost::_RemoveAllPicsProcessors()
  9403. {
  9404. CPicsProcessor * ppp = &_PicsProcBase;
  9405. CPicsProcessor * pppNext;
  9406. while( ppp )
  9407. {
  9408. pppNext = ppp->_pPicsProcNext;
  9409. if (ppp != &_PicsProcBase)
  9410. ppp->_Terminate();
  9411. else
  9412. ppp->_ReInit();
  9413. ppp = pppNext;
  9414. }
  9415. return S_OK;
  9416. }
  9417. HRESULT CDocObjectFrame::QueryService(REFGUID guidService,
  9418. REFIID riid, void **ppvObj)
  9419. {
  9420. return _pdoh->QueryService(guidService, riid, ppvObj);
  9421. }
  9422. HRESULT CDocObjectFrame::QueryInterface(REFIID riid, void ** ppvObj)
  9423. {
  9424. if (IsEqualIID(riid, IID_IOleInPlaceFrame) ||
  9425. IsEqualIID(riid, IID_IOleInPlaceUIWindow) ||
  9426. IsEqualIID(riid, IID_IOleWindow) ||
  9427. IsEqualIID(riid, IID_IUnknown))
  9428. {
  9429. *ppvObj = SAFECAST(this, IOleInPlaceFrame*);
  9430. }
  9431. else if (IsEqualIID(riid, IID_IOleCommandTarget))
  9432. {
  9433. *ppvObj = SAFECAST(this, IOleCommandTarget*);
  9434. }
  9435. else if (IsEqualIID(riid, IID_IServiceProvider))
  9436. {
  9437. *ppvObj = SAFECAST(this, IServiceProvider*);
  9438. }
  9439. else if (IsEqualIID(riid, IID_IInternetSecurityMgrSite))
  9440. {
  9441. *ppvObj = SAFECAST(this, IInternetSecurityMgrSite*);
  9442. }
  9443. else
  9444. {
  9445. *ppvObj = NULL;
  9446. return E_NOINTERFACE;
  9447. }
  9448. _pdoh->AddRef();
  9449. return NOERROR;
  9450. }
  9451. ULONG CDocObjectFrame::AddRef(void)
  9452. {
  9453. return _pdoh->AddRef();
  9454. }
  9455. ULONG CDocObjectFrame::Release(void)
  9456. {
  9457. return _pdoh->Release();
  9458. }
  9459. HRESULT CDocObjectFrame::GetWindow(HWND * lphwnd)
  9460. {
  9461. DOFMSG(TEXT("GetWindow called"));
  9462. return _pdoh->_pipu ?
  9463. _pdoh->_pipu->GetWindow(lphwnd) :
  9464. _pdoh->_psb ? _pdoh->_psb->GetWindow(lphwnd) :
  9465. _pdoh->GetWindow(lphwnd);
  9466. }
  9467. HRESULT CDocObjectFrame::ContextSensitiveHelp(BOOL fEnterMode)
  9468. {
  9469. DOFMSG(TEXT("ContextSensitiveHelp called"));
  9470. return _pdoh->ContextSensitiveHelp(fEnterMode);
  9471. }
  9472. HRESULT CDocObjectFrame::GetBorder(LPRECT lprectBorder)
  9473. {
  9474. // DOFMSG(TEXT("GetBorder called"));
  9475. return _pdoh->_pipu ?
  9476. _pdoh->_pipu->GetBorder(lprectBorder) : E_UNEXPECTED;
  9477. }
  9478. HRESULT CDocObjectFrame::RequestBorderSpace(LPCBORDERWIDTHS pborderwidths)
  9479. {
  9480. DOFMSG(TEXT("RequestBorderSpace called"));
  9481. return _pdoh->_pipu ?
  9482. _pdoh->_pipu->RequestBorderSpace(pborderwidths) : E_UNEXPECTED;
  9483. }
  9484. HRESULT CDocObjectFrame::SetBorderSpace(LPCBORDERWIDTHS pborderwidths)
  9485. {
  9486. // DOFMSG(TEXT("SetBorderSpace called"));
  9487. return _pdoh->_pipu ?
  9488. _pdoh->_pipu->SetBorderSpace(pborderwidths) : E_UNEXPECTED;
  9489. }
  9490. HRESULT CDocObjectFrame::SetActiveObject(
  9491. IOleInPlaceActiveObject *pActiveObject, LPCOLESTR pszObjName)
  9492. {
  9493. DOFMSG(TEXT("SetActiveObject called"));
  9494. // Note that we need to call both.
  9495. _pdoh->_xao.SetActiveObject(pActiveObject);
  9496. if (_pdoh->_pipu) {
  9497. //
  9498. // Note that we should pass proxy IOleActiveObject pointer instead.
  9499. //
  9500. _pdoh->_pipu->SetActiveObject(pActiveObject ? &_pdoh->_xao : NULL, pszObjName);
  9501. }
  9502. return S_OK;
  9503. }
  9504. HRESULT CDocObjectFrame::InsertMenus(HMENU hmenuShared, LPOLEMENUGROUPWIDTHS lpMenuWidths)
  9505. {
  9506. DOFMSG2(TEXT("InsertMenus called with"), hmenuShared);
  9507. return _pdoh->_InsertMenus(hmenuShared, lpMenuWidths);
  9508. }
  9509. HRESULT CDocObjectFrame::SetMenu(HMENU hmenuShared, HOLEMENU holemenu, HWND hwndActiveObject)
  9510. {
  9511. DOFMSG2(TEXT("SetMenu called with"), hmenuShared);
  9512. return _pdoh->_SetMenu(hmenuShared, holemenu, hwndActiveObject);
  9513. }
  9514. HRESULT CDocObjectFrame::RemoveMenus(HMENU hmenuShared)
  9515. {
  9516. DOFMSG(TEXT("RemoveMenus called"));
  9517. return _pdoh->_RemoveMenus(hmenuShared);
  9518. }
  9519. HRESULT CDocObjectFrame::SetStatusText(LPCOLESTR pszStatusText)
  9520. {
  9521. DOFMSG(TEXT("SetStatusText called"));
  9522. return _pdoh->_SetStatusText(pszStatusText);
  9523. }
  9524. HRESULT CDocObjectFrame::EnableModeless(BOOL fEnable)
  9525. {
  9526. DOFMSG(TEXT("EnableModeless called"));
  9527. return _pdoh->_EnableModeless(fEnable);
  9528. }
  9529. // IOleInPlaceFrame::TranslateAccelerator
  9530. HRESULT CDocObjectFrame::TranslateAccelerator(LPMSG lpmsg, WORD wID)
  9531. {
  9532. // NOTES: This code remains as-is. If we have something special
  9533. // it should be done in CDocObjectHost::TranslateAccelerator
  9534. return _pdoh->_TranslateAccelerator(lpmsg, wID);
  9535. }
  9536. HRESULT CDocObjectFrame::QueryStatus(const GUID *pguidCmdGroup,
  9537. ULONG cCmds, OLECMD rgCmds[], OLECMDTEXT *pcmdtext)
  9538. {
  9539. DOFMSG(TEXT("QueryStatus called"));
  9540. return _pdoh->QueryStatus(pguidCmdGroup, cCmds, rgCmds, pcmdtext);
  9541. }
  9542. HRESULT CDocObjectFrame::Exec(const GUID *pguidCmdGroup,
  9543. DWORD nCmdID, DWORD nCmdexecopt, VARIANTARG *pvarargIn, VARIANTARG *pvarargOut)
  9544. {
  9545. DOFMSG(TEXT("Exec called"));
  9546. return _pdoh->Exec(pguidCmdGroup, nCmdID, nCmdexecopt, pvarargIn, pvarargOut);
  9547. }
  9548. //*** CPAO::TranslateAccelerator (IOIPAO::TranslateAccelerator)
  9549. //
  9550. HRESULT CProxyActiveObject::TranslateAccelerator(
  9551. LPMSG lpmsg)
  9552. {
  9553. HRESULT hres = E_FAIL;
  9554. // IShellBrowser is supporsed to call ISV::TranslateAcceleratorSV,
  9555. // but why not be nice?
  9556. ASSERT(!_pdoh->_fCycleFocus);
  9557. //
  9558. // Don't call DocObject's TranslateAccelarator with non-key messages.
  9559. // It's better to be IE compatible.
  9560. //
  9561. BOOL fKeybrdMsg = IsInRange(lpmsg->message, WM_KEYFIRST, WM_KEYLAST);
  9562. if (fKeybrdMsg && _piact && (hres = _piact->TranslateAccelerator(lpmsg)) == S_OK) {
  9563. if (_pdoh->_fCycleFocus) {
  9564. // we got called back by trident (IOCS::TA), but deferred it.
  9565. // time to pay the piper.
  9566. TraceMsg(DM_FOCUS, "DOH::IOIPAO::TA piao->TA==S_OK ret _fCycleFocus=FALSE hr=S_FALSE (piper)");
  9567. _pdoh->_fCycleFocus = FALSE;
  9568. return S_FALSE; // time to pay the piper
  9569. }
  9570. return S_OK;
  9571. }
  9572. if (_pdoh->_fCycleFocus) {
  9573. TraceMsg(DM_ERROR, "DOH::IOIPAO::TA _fCycleFocus && hres=%x (!=S_OK)", hres);
  9574. _pdoh->_fCycleFocus = FALSE;
  9575. return S_FALSE;
  9576. }
  9577. return _pdoh->TranslateHostAccelerators(lpmsg);
  9578. }
  9579. HRESULT CProxyActiveObject::OnFrameWindowActivate(
  9580. BOOL fActivate)
  9581. {
  9582. TraceMsg(TF_SHDUIACTIVATE, "CProxyAO::OnFrameWindowActivate called with %d (_piact=%x)",
  9583. fActivate, _piact);
  9584. if (_piact) {
  9585. return _piact->OnFrameWindowActivate(fActivate);
  9586. }
  9587. return S_OK;
  9588. }
  9589. HRESULT CProxyActiveObject::OnDocWindowActivate(
  9590. BOOL fActivate)
  9591. {
  9592. return S_OK;
  9593. }
  9594. HRESULT CProxyActiveObject::ResizeBorder(
  9595. LPCRECT prcBorder,
  9596. IOleInPlaceUIWindow *pUIWindow,
  9597. BOOL fFrameWindow)
  9598. {
  9599. if (_piact) {
  9600. //
  9601. // Note that we must pass our proxy frame instead!
  9602. //
  9603. return _piact->ResizeBorder(prcBorder, &_pdoh->_dof, TRUE);
  9604. }
  9605. return E_FAIL;
  9606. }
  9607. void CProxyActiveObject::SetActiveObject(IOleInPlaceActiveObject *piact )
  9608. {
  9609. if (_piact)
  9610. {
  9611. ATOMICRELEASE(_piact);
  9612. _hwnd = NULL;
  9613. }
  9614. if (piact) {
  9615. _piact = piact;
  9616. _piact->AddRef();
  9617. _piact->GetWindow(&_hwnd);
  9618. }
  9619. }
  9620. HRESULT CProxyActiveObject::EnableModeless(
  9621. BOOL fEnable)
  9622. {
  9623. // IShellBrowser is supporsed to call ISV::EnableModelessSV,
  9624. // but why not be nice?
  9625. HRESULT hres = S_OK;
  9626. if (_piact)
  9627. hres = _piact->EnableModeless(fEnable);
  9628. return hres;
  9629. }
  9630. HRESULT CProxyActiveObject::QueryInterface(REFIID riid, void ** ppvObj)
  9631. {
  9632. if (IsEqualIID(riid, IID_IOleInPlaceActiveObject) ||
  9633. IsEqualIID(riid, IID_IOleWindow) ||
  9634. IsEqualIID(riid, IID_IUnknown))
  9635. {
  9636. *ppvObj = SAFECAST(this, IOleInPlaceActiveObject*);
  9637. }
  9638. else
  9639. {
  9640. *ppvObj = NULL;
  9641. return E_NOINTERFACE;
  9642. }
  9643. _pdoh->AddRef();
  9644. return NOERROR;
  9645. }
  9646. ULONG CProxyActiveObject::AddRef(void)
  9647. {
  9648. return _pdoh->AddRef();
  9649. }
  9650. ULONG CProxyActiveObject::Release(void)
  9651. {
  9652. return _pdoh->Release();
  9653. }
  9654. HRESULT CProxyActiveObject::GetWindow(HWND * lphwnd)
  9655. {
  9656. return _pdoh->GetWindow(lphwnd);
  9657. }
  9658. HRESULT CProxyActiveObject::ContextSensitiveHelp(BOOL fEnterMode)
  9659. {
  9660. return _pdoh->ContextSensitiveHelp(fEnterMode);
  9661. }
  9662. #define ANIMATION_WND_WIDTH (100+3)
  9663. void CDocObjectHost::_PlaceProgressBar(BOOL fForcedLayout)
  9664. {
  9665. if (_psb) {
  9666. HWND hwndStatus = NULL;
  9667. _psb->GetControlWindow(FCW_STATUS, &hwndStatus);
  9668. if (hwndStatus) {
  9669. RECT rc;
  9670. INT_PTR fSimple = SendMessage(hwndStatus, SB_ISSIMPLE, 0, 0);
  9671. if (!fSimple || fForcedLayout) {
  9672. // While processing WM_SIZE, turn off the simple mode temporarily.
  9673. if (fSimple)
  9674. _psb->SendControlMsg(FCW_STATUS, SB_SIMPLE, 0, 0, NULL);
  9675. GetClientRect(hwndStatus, &rc);
  9676. const UINT cxZone = ZoneComputePaneSize(hwndStatus);
  9677. UINT cxProgressBar = (_fShowProgressCtl) ? 100 : 0;
  9678. INT nSBWidth = rc.right - rc.left;
  9679. INT arnRtEdge[STATUS_PANES] = {1};
  9680. INT nIconPaneWidth = GetSystemMetrics(SM_CXSMICON) +
  9681. (GetSystemMetrics(SM_CXEDGE) * 4);
  9682. INT nWidthReqd = cxZone + cxProgressBar + (nIconPaneWidth * 3);
  9683. arnRtEdge[STATUS_PANE_NAVIGATION] = max(1, nSBWidth - nWidthReqd);
  9684. nWidthReqd -= cxProgressBar;
  9685. arnRtEdge[STATUS_PANE_PROGRESS] = max(1, nSBWidth - nWidthReqd);
  9686. nWidthReqd -= (nIconPaneWidth);
  9687. arnRtEdge[STATUS_PANE_OFFLINE] = max(1, nSBWidth - nWidthReqd);
  9688. nWidthReqd -= (nIconPaneWidth);
  9689. arnRtEdge[STATUS_PANE_PRIVACY] = max(1, nSBWidth - nWidthReqd);
  9690. // nWidthReqd -= (nIconPaneWidth);
  9691. // arnRtEdge[STATUS_PANE_PRINTER] = max(1, nSBWidth - nWidthReqd);
  9692. nWidthReqd -= (nIconPaneWidth);
  9693. arnRtEdge[STATUS_PANE_SSL] = max(1, nSBWidth - nWidthReqd);
  9694. arnRtEdge[STATUS_PANE_ZONE] = -1;
  9695. LRESULT nParts = 0;
  9696. nParts = SendMessage(hwndStatus, SB_GETPARTS, 0, 0L);
  9697. if (nParts != STATUS_PANES)
  9698. {
  9699. for ( int n = 0; n < nParts; n++)
  9700. {
  9701. SendMessage(hwndStatus, SB_SETTEXT, n | SBT_NOTABPARSING, NULL);
  9702. SendMessage(hwndStatus, SB_SETICON, n, NULL);
  9703. }
  9704. SendMessage(hwndStatus, SB_SETPARTS, 0, 0L);
  9705. }
  9706. SendMessage(hwndStatus, SB_SETPARTS, STATUS_PANES, (LPARAM)arnRtEdge);
  9707. if (!_hwndProgress) {
  9708. _psb->GetControlWindow(FCW_PROGRESS, &_hwndProgress);
  9709. }
  9710. if (_hwndProgress) {
  9711. if (SendMessage(hwndStatus, SB_GETRECT, 1, (LPARAM)&rc))
  9712. {
  9713. InflateRect(&rc, -GetSystemMetrics(SM_CXEDGE), -GetSystemMetrics(SM_CYEDGE));
  9714. }
  9715. else
  9716. {
  9717. rc.left = rc.top = rc.right = rc.bottom = 0;
  9718. }
  9719. SetWindowPos(_hwndProgress, NULL,
  9720. rc.left, rc.top,
  9721. rc.right-rc.left, rc.bottom-rc.top,
  9722. SWP_NOZORDER | SWP_NOACTIVATE);
  9723. }
  9724. SendMessage(hwndStatus, SB_SETTEXT, 1 | SBT_NOTABPARSING, (LPARAM)TEXT(""));
  9725. SendMessage(hwndStatus, SB_SETMINHEIGHT, GetSystemMetrics(SM_CYSMICON) +
  9726. GetSystemMetrics(SM_CYBORDER) * 2, 0L);
  9727. // Restore
  9728. if (fSimple)
  9729. SendMessage(hwndStatus, SB_SIMPLE, TRUE, 0);
  9730. }
  9731. }
  9732. } else {
  9733. TraceMsg(TF_WARNING, "_PlaceProgressBar ASSERT(_psb) this=%x", this);
  9734. }
  9735. }
  9736. void CDocObjectHost::_ActivateOleObject(void)
  9737. {
  9738. HRESULT hres;
  9739. _pole->SetClientSite(NULL);
  9740. if (_fDontInPlaceNavigate())
  9741. {
  9742. TraceMsg(TF_SHDAPPHACK, "CDOH::_ActivateOleObject calling DoVerb because of _fDontInPlaceNavigate()");
  9743. }
  9744. _EnableModeless(FALSE);
  9745. hres = _pole->DoVerb(
  9746. _fUseOpenVerb() ? OLEIVERB_OPEN : OLEIVERB_PRIMARY,
  9747. NULL, NULL, (UINT)-1, NULL, NULL);
  9748. _EnableModeless(TRUE);
  9749. if (SUCCEEDED(hres))
  9750. {
  9751. CShdAdviseSink_Advise(_pwb, _pole);
  9752. }
  9753. #ifdef DEBUG
  9754. else if (!_fDelegatedNavigation)
  9755. {
  9756. TraceMsg(DM_ERROR, "CDOH::_ActivateOleObject DoVerb failed %x.", hres);
  9757. }
  9758. #endif
  9759. // We must release the OLE object to avoid calling Close
  9760. // from _UnBind.
  9761. _ReleaseOleObject();
  9762. _ReleasePendingObject();
  9763. }
  9764. void CDocObjectHost::ClearScriptError()
  9765. {
  9766. // clear out the script error list
  9767. _pScriptErrList->ClearErrorList();
  9768. _SetPriorityStatusText(NULL);
  9769. // reset the text and icon
  9770. _ResetStatusBar();
  9771. }
  9772. //
  9773. // The docobject's READYSTATE property may have changed
  9774. //
  9775. void CDocObjectHost::_OnReadyState(long lVal, BOOL fUpdateHistory /* = TRUE */)
  9776. {
  9777. // Forward this to the browser so we can source ReadyState events properly
  9778. // TRACE this zekel
  9779. if (_psb)
  9780. {
  9781. IDocNavigate *pdn;
  9782. if (SUCCEEDED(_psb->QueryInterface(IID_IDocNavigate, (void **)&pdn)))
  9783. {
  9784. ASSERT(_psv);
  9785. pdn->OnReadyStateChange(_psv, lVal);
  9786. pdn->Release();
  9787. }
  9788. }
  9789. // NOTE: The below code is rather wasteful. The OmWindow stuff
  9790. // should trigger off the above ReadyState code.
  9791. //
  9792. IShellHTMLWindowSupport *phtmlWS;
  9793. if (_psp && SUCCEEDED(_psp->QueryService(SID_SOmWindow, IID_IShellHTMLWindowSupport, (void**)&phtmlWS)))
  9794. {
  9795. phtmlWS->ReadyStateChangedTo(lVal, _psv);
  9796. phtmlWS->Release();
  9797. }
  9798. if ( (lVal == READYSTATE_INTERACTIVE)
  9799. && (_pScriptErrList != NULL))
  9800. {
  9801. ClearScriptError();
  9802. }
  9803. if (lVal >= READYSTATE_INTERACTIVE)
  9804. {
  9805. // Technically we can get this value multiple times,
  9806. // so make sure we call _Navigate only once.
  9807. //
  9808. if (!_fReadystateInteractiveProcessed)
  9809. {
  9810. _fReadystateInteractiveProcessed = TRUE;
  9811. _Navigate();
  9812. }
  9813. if (lVal == READYSTATE_COMPLETE)
  9814. {
  9815. _OnSetProgressPos(0, PROGRESS_RESET);
  9816. // We aren't going to commit error pages to the history
  9817. //
  9818. if (_pwb && !_fErrorPage && fUpdateHistory)
  9819. {
  9820. WCHAR szTitle[MAX_PATH]; // titles are only stored up to this size
  9821. if (SUCCEEDED(_pwb->GetTitle(_psv, szTitle, ARRAYSIZE(szTitle))))
  9822. {
  9823. // BharatS : 01/09/97 : There is no need to tie the updating of the title in the
  9824. // history to the updating of the INTSITE database. Thus the INTSITE database
  9825. // update can be moved out of AddUrlToUrlHistoryStg() in history.cpp when time permits
  9826. // to a more logical place such as someplace in dochost.cpp
  9827. //
  9828. _UpdateHistoryAndIntSiteDB(szTitle);
  9829. }
  9830. else
  9831. {
  9832. _UpdateHistoryAndIntSiteDB(NULL);
  9833. }
  9834. }
  9835. }
  9836. }
  9837. }
  9838. HRESULT CDocObjectHost::_OnChangedReadyState()
  9839. {
  9840. IDispatch * p_idispatch;
  9841. ASSERT(_pole || _fFriendlyError);
  9842. if (!_pole)
  9843. return E_UNEXPECTED;
  9844. if (SUCCEEDED(_pole->QueryInterface( IID_IDispatch, (void **) &p_idispatch)))
  9845. {
  9846. VARIANTARG va;
  9847. EXCEPINFO exInfo;
  9848. va.vt = 0;
  9849. if (EVAL(SUCCEEDED(p_idispatch->Invoke( DISPID_READYSTATE, IID_NULL, LOCALE_USER_DEFAULT, DISPATCH_PROPERTYGET, (DISPPARAMS *)&g_dispparamsNoArgs, &va, &exInfo, NULL))
  9850. && va.vt == VT_I4))
  9851. {
  9852. _OnReadyState(va.lVal);
  9853. // If we are hosting Trident's native frames build,
  9854. // we don't want to call _RemoveTransitionCapability().
  9855. //
  9856. if (!_fDocCanNavigate && va.lVal == READYSTATE_COMPLETE)
  9857. {
  9858. _RemoveTransitionCapability();
  9859. }
  9860. }
  9861. p_idispatch->Release();
  9862. }
  9863. return( NOERROR );
  9864. }
  9865. HRESULT CDocObjectHost::OnRequestEdit(DISPID dispid)
  9866. {
  9867. return E_NOTIMPL;
  9868. }
  9869. //
  9870. // OnChanged
  9871. //
  9872. // Notification from the DocObject that one of its
  9873. // properties has changed.
  9874. //
  9875. HRESULT CDocObjectHost::OnChanged(DISPID dispid)
  9876. {
  9877. if (DISPID_READYSTATE == dispid || DISPID_UNKNOWN == dispid)
  9878. return _OnChangedReadyState();
  9879. return S_OK;
  9880. }
  9881. extern BOOL _ValidateURL(LPTSTR pszName);
  9882. void CDocObjectHost::_UpdateHistoryAndIntSiteDB(LPCWSTR pwszTitle)
  9883. {
  9884. TCHAR szUrl[MAX_URL_STRING];
  9885. if (SUCCEEDED(_GetCurrentPage(szUrl, MAX_URL_STRING, TRUE)) &&
  9886. _ValidateURL(szUrl, UQF_DEFAULT))
  9887. {
  9888. // update history and intsite if this isn't a silent browse
  9889. BOOL bSilent = FALSE;
  9890. HRESULT hr = _GetOfflineSilent(NULL, &bSilent);
  9891. if (SUCCEEDED(hr) && (!bSilent))
  9892. {
  9893. BOOL fWriteHistory,
  9894. fSelectHistory;
  9895. fWriteHistory = TRUE;
  9896. fSelectHistory = TRUE;
  9897. if (NULL != _pocthf)
  9898. {
  9899. MSOCMD rgCmd[] = { { SBCMDID_WRITEHIST, 0 }, { SBCMDID_SELECTHISTPIDL, 0 } };
  9900. _pocthf->QueryStatus(&CGID_Explorer, ARRAYSIZE(rgCmd), rgCmd, NULL);
  9901. fWriteHistory = BOOLIFY(rgCmd[0].cmdf & MSOCMDF_ENABLED);
  9902. fSelectHistory = BOOLIFY(rgCmd[1].cmdf & MSOCMDF_ENABLED);
  9903. }
  9904. AddUrlToUrlHistoryStg(szUrl,
  9905. pwszTitle,
  9906. _psb,
  9907. fWriteHistory,
  9908. fSelectHistory ? _pocthf : NULL,
  9909. get_punkSFHistory(), NULL);
  9910. //
  9911. // Satona had the redirect code ifdef'd out, but for
  9912. // netscape compatibility, we need to update the history
  9913. // for the redirected URL as well. - zekel - 22-JUL-97
  9914. //
  9915. // If this page is a redirect, update intsite for destination too
  9916. INTERNET_CACHE_ENTRY_INFO *pCacheEntry = NULL;
  9917. WCHAR chBuf[MAX_CACHE_ENTRY_INFO_SIZE];
  9918. // Find entry in cache using redirect map
  9919. pCacheEntry = (INTERNET_CACHE_ENTRY_INFO *)chBuf;
  9920. DWORD dwSize = SIZEOF(chBuf);
  9921. BOOL fSuccess = GetUrlCacheEntryInfoEx(szUrl, pCacheEntry, &dwSize, NULL, 0, NULL, 0);
  9922. if (fSuccess)
  9923. {
  9924. // If we have a different url than we started with, update it too
  9925. if (StrCmp(szUrl, pCacheEntry->lpszSourceUrlName))
  9926. {
  9927. AddUrlToUrlHistoryStg(pCacheEntry->lpszSourceUrlName,
  9928. pwszTitle,
  9929. _psb,
  9930. fWriteHistory,
  9931. fSelectHistory ? _pocthf : NULL,
  9932. get_punkSFHistory(), NULL);
  9933. }
  9934. }
  9935. }
  9936. }
  9937. }
  9938. //
  9939. // CDocObjectHost::_SetUpTransitionCapability()
  9940. //
  9941. // Returns TRUE if all the following hold true:
  9942. // - object has readystate property
  9943. // - readystate property is currently < interactive
  9944. // - Object supports IPropertyNotifySink
  9945. // Then this object supports delayed switching when it
  9946. // it tells us that it is ready...
  9947. //
  9948. // This is how we switch pages only when the new page is ready to be
  9949. // switched to. Also, by doing this we can also make the switch smooth
  9950. // by applying graphical transitions.
  9951. //
  9952. BOOL CDocObjectHost::_SetUpTransitionCapability(BOOL fWindowOpen /* = FALSE */)
  9953. {
  9954. // By default DocObject doesn't have gray-flash communication
  9955. BOOL fSupportsReadystate = FALSE;
  9956. long lReadyState = 0; // Init to avoid a bogus C4701 warning
  9957. // Sanity Check
  9958. if (!_pole)
  9959. return(fSupportsReadystate);
  9960. // Check for proper readystate support
  9961. BOOL fReadyStateOK = FALSE;
  9962. IDispatch * p_idispatch;
  9963. if (SUCCEEDED(_pole->QueryInterface( IID_IDispatch, (void **) &p_idispatch )))
  9964. {
  9965. VARIANTARG va;
  9966. EXCEPINFO exInfo;
  9967. if (SUCCEEDED(p_idispatch->Invoke( DISPID_READYSTATE, IID_NULL, LOCALE_USER_DEFAULT, DISPATCH_PROPERTYGET, (DISPPARAMS *)&g_dispparamsNoArgs, &va, &exInfo, NULL)))
  9968. {
  9969. if ((va.vt == VT_I4) && (va.lVal < READYSTATE_COMPLETE))
  9970. {
  9971. lReadyState = fWindowOpen ? READYSTATE_COMPLETE : va.lVal;
  9972. fReadyStateOK = TRUE;
  9973. }
  9974. }
  9975. p_idispatch->Release();
  9976. }
  9977. if (fReadyStateOK)
  9978. {
  9979. // Check and Set-Up IPropertyNotifySink
  9980. if (SUCCEEDED(ConnectToConnectionPoint(SAFECAST(this, IPropertyNotifySink*), IID_IPropertyNotifySink, TRUE, _pole, &_dwPropNotifyCookie, NULL)))
  9981. {
  9982. fSupportsReadystate = TRUE;
  9983. _OnReadyState(lReadyState);
  9984. }
  9985. }
  9986. // If no ReadyState, we simulate it
  9987. if (!fSupportsReadystate)
  9988. {
  9989. if (fWindowOpen)
  9990. {
  9991. // Connect the property notify sink or we
  9992. // will never activate the pending view.
  9993. //
  9994. ConnectToConnectionPoint(SAFECAST(this, IPropertyNotifySink*),
  9995. IID_IPropertyNotifySink,
  9996. TRUE,
  9997. _pole,
  9998. &_dwPropNotifyCookie,
  9999. NULL);
  10000. }
  10001. _OnReadyState(READYSTATE_COMPLETE, !fWindowOpen);
  10002. }
  10003. return(fSupportsReadystate);
  10004. }
  10005. // This removes any property notify sink we set up
  10006. //
  10007. BOOL CDocObjectHost::_RemoveTransitionCapability()
  10008. {
  10009. BOOL fRet = FALSE;
  10010. if (_dwPropNotifyCookie)
  10011. {
  10012. ConnectToConnectionPoint(NULL, IID_IPropertyNotifySink, FALSE, _pole, &_dwPropNotifyCookie, NULL);
  10013. fRet = TRUE;
  10014. }
  10015. return(fRet);
  10016. }
  10017. HRESULT _GetRequestFlagFromPIB(IBinding *pib, DWORD *pdwOptions)
  10018. {
  10019. HRESULT hres = E_FAIL;
  10020. *pdwOptions = 0;
  10021. if (pib)
  10022. {
  10023. IWinInetInfo* pwinet;
  10024. hres = pib->QueryInterface(IID_IWinInetInfo, (void **)&pwinet);
  10025. if (SUCCEEDED(hres)) {
  10026. DWORD cbSize = SIZEOF(*pdwOptions);
  10027. hres = pwinet->QueryOption(INTERNET_OPTION_REQUEST_FLAGS,
  10028. (LPVOID)pdwOptions, &cbSize);
  10029. TraceMsg(TF_SHDNAVIGATE, "DOH::BSC::_HFNS() pwinet->QueryOptions hres=%x dwOptions=%x", hres, *pdwOptions);
  10030. pwinet->Release();
  10031. }
  10032. }
  10033. return hres;
  10034. }
  10035. void CDocObjectHost::_Navigate()
  10036. {
  10037. NAVMSG3(TEXT("_Navigate calling SHDVID_ACTIVATEMENOW"), 0, NULL);
  10038. if (_pmsoctBrowser)
  10039. {
  10040. VARIANT varSynch;
  10041. V_VT(&varSynch) = VT_BOOL;
  10042. V_BOOL(&varSynch) = _fDocCanNavigate ? VARIANT_TRUE : VARIANT_FALSE;
  10043. _pmsoctBrowser->Exec(&CGID_ShellDocView,
  10044. SHDVID_ACTIVATEMENOW,
  10045. NULL,
  10046. &varSynch,
  10047. NULL);
  10048. }
  10049. }
  10050. void CDocObjectHost::_NavigateFolder(BSTR bstrUrl)
  10051. {
  10052. // This code accesses one of IE's default behaviors which
  10053. // allows for navigation to a web folder.
  10054. // ------------------------------------------------------
  10055. Iwfolders * pWF = NULL;
  10056. IElementBehaviorFactory * pebf = NULL;
  10057. IElementBehavior * pPeer = NULL;
  10058. HWND hwndOwner = NULL;
  10059. IServiceProvider * psp = NULL;
  10060. IUnknown * punkwb = NULL;
  10061. // Make the peer factory
  10062. if ( !_psb || (FAILED(_psb->GetWindow (&hwndOwner))) ||
  10063. (FAILED(CoCreateInstance(CLSID_PeerFactory, NULL, CLSCTX_INPROC,
  10064. IID_IElementBehaviorFactory, (void **)&pebf))) ||
  10065. (FAILED(pebf->FindBehavior(L"httpFolder", NULL, NULL, &pPeer))) ||
  10066. (FAILED(pPeer->QueryInterface(IID_Iwfolders, (void **)&pWF))) ||
  10067. (FAILED(QueryService(SID_STopLevelBrowser, IID_IServiceProvider, (void **)&psp))) ||
  10068. (FAILED(psp->QueryService(SID_SContainerDispatch, IID_IUnknown, (void **)&punkwb))) )
  10069. {
  10070. WCHAR wszMessage[MAX_PATH];
  10071. WCHAR wszTitle[MAX_PATH];
  10072. MLLoadShellLangString(IDS_ERRORINTERNAL, wszMessage, ARRAYSIZE(wszMessage));
  10073. MLLoadShellLangString(IDS_NAME, wszTitle, ARRAYSIZE(wszTitle));
  10074. ULONG_PTR uCookie = 0;
  10075. SHActivateContext(&uCookie);
  10076. MessageBox(hwndOwner, wszMessage, wszTitle, MB_OK | MB_ICONERROR);
  10077. if (uCookie)
  10078. {
  10079. SHDeactivateContext(uCookie);
  10080. }
  10081. goto done;
  10082. }
  10083. // Sundown: coercion to unsigned long is valid for HWNDs
  10084. pWF->navigateNoSite(bstrUrl, NULL, PtrToUlong(hwndOwner), punkwb);
  10085. done:
  10086. if (pebf)
  10087. pebf->Release();
  10088. if (pPeer)
  10089. pPeer->Release();
  10090. if (pWF)
  10091. pWF->Release();
  10092. if (punkwb)
  10093. punkwb->Release();
  10094. if (psp)
  10095. psp->Release();
  10096. }
  10097. void CDocObjectHost::_CancelPendingNavigation(BOOL fAsyncDownload,
  10098. BOOL fSyncReally, /* = FALSE */
  10099. BOOL fDontShowNavCancelPage, /* = FALSE */
  10100. BOOL fForceClose /* = FALSE */)
  10101. {
  10102. ASSERT(_phf);
  10103. // TODO: We need to clean up the call to this method and eliminate need for fSyncReally
  10104. //
  10105. // Passing NULL for the 4th argument (instead of passing in a
  10106. // variant like we do in the case when fAsyncDownload is TRUE) looks plain wrong!
  10107. // See how this command+argument is interpreted in CBaseBrowser2::Exec.
  10108. // It is too close to RTM (of IE5.5) now to fix this. The net result is that
  10109. // when this function is called with fAsyncDownload=FALSE, we end up posting
  10110. // ASYNCOP_CANCELPENDINGNAVIGATION, which is just what the caller does not want.
  10111. // To workaround this, I have introduced the argument fSyncReally.
  10112. // the hlframe no longer knows if the clear was a cancel or a start of navigation
  10113. // because we don't call anything tosignal a successfull navigation
  10114. if (_pmsoctBrowser)
  10115. {
  10116. TraceMsg(DM_TRACE, "DOH::_CancelPendingNavigation calling _pmsc->Exec");
  10117. if (_pwb && fDontShowNavCancelPage)
  10118. {
  10119. _pwb->SetFlags(BSF_DONTSHOWNAVCANCELPAGE, BSF_DONTSHOWNAVCANCELPAGE);
  10120. }
  10121. if (fForceClose && _fWindowOpen) // Force the browser to close
  10122. {
  10123. HideBrowser(); // Makes the browser appear to go away faster.
  10124. _pmsoctBrowser->Exec(&CGID_Explorer, SBCMDID_CANCELANDCLOSE, 0, NULL, NULL);
  10125. }
  10126. else if (fAsyncDownload)
  10127. {
  10128. VARIANT var = {0};
  10129. var.vt = VT_I4;
  10130. ASSERT(var.lVal == FALSE); // asynd download is done.
  10131. _pmsoctBrowser->Exec(&CGID_Explorer, SBCMDID_CANCELNAVIGATION, 0, &var, NULL);
  10132. }
  10133. else if (fSyncReally)
  10134. {
  10135. VARIANT var = { 0 };
  10136. var.vt = VT_I4;
  10137. var.lVal = TRUE;
  10138. _pmsoctBrowser->Exec(&CGID_Explorer, SBCMDID_CANCELNAVIGATION, 0, &var, NULL);
  10139. }
  10140. else
  10141. {
  10142. // This actually causes an async cancel
  10143. //
  10144. _pmsoctBrowser->Exec(&CGID_Explorer, SBCMDID_CANCELNAVIGATION, 0, NULL, NULL);
  10145. }
  10146. }
  10147. // Release our navigation state.
  10148. // Doing a "fSyncReally" may cause us to lose our _phf member value. Check it again.
  10149. //
  10150. if (_phf)
  10151. {
  10152. _phf->Navigate(0, NULL, NULL, (IHlink*)-1);
  10153. }
  10154. }
  10155. void CDocObjectHost::_ResetStatusBar()
  10156. {
  10157. _SetStatusText(TEXT(""));
  10158. if (_psb)
  10159. _psb->SendControlMsg(FCW_STATUS, SB_SETICON, STATUS_PANE_NAVIGATION,
  10160. (LPARAM)g_ahiconState[IDI_STATE_NORMAL-IDI_STATE_FIRST], NULL);
  10161. return;
  10162. }
  10163. void CDocObjectHost::_DoAsyncNavigation(LPCTSTR pszURL)
  10164. {
  10165. if (_pmsoctBrowser) {
  10166. VARIANT vararg = {0};
  10167. vararg.vt = VT_BSTR;
  10168. vararg.bstrVal = SysAllocStringT(pszURL);
  10169. if (vararg.bstrVal)
  10170. {
  10171. TraceMsg(DM_TRACE, "DOH::_DoAsyncNavigation calling _pmsc->Exec");
  10172. _pmsoctBrowser->Exec(&CGID_Explorer, SBCMDID_ASYNCNAVIGATION, 0, &vararg, NULL);
  10173. VariantClear(&vararg);
  10174. }
  10175. }
  10176. }
  10177. // note: szError is never used, so don't waste time setting it
  10178. UINT SHIEErrorMsgBox(IShellBrowser* psb,
  10179. HWND hwndOwner, HRESULT hrError, LPCWSTR szError, LPCTSTR pszURLparam,
  10180. UINT idResource, UINT wFlags)
  10181. {
  10182. UINT uRet = IDCANCEL;
  10183. TCHAR szMsg[MAX_PATH];
  10184. LPCTSTR pszURL = TEXT("");
  10185. HWND hwndParent = hwndOwner;
  10186. IShellBrowser *psbParent = NULL;
  10187. // if a URL was specified, use it; otherwise use empty string
  10188. if (pszURLparam)
  10189. pszURL = pszURLparam;
  10190. //
  10191. // NOTES: This table of error code will be mapped to (IDS_ERRMSG_FIRST +
  10192. // offset) and we MLLoadString it.
  10193. //
  10194. const static c_ahres[] = {
  10195. HRESULT_FROM_WIN32(ERROR_INTERNET_INVALID_URL),
  10196. HRESULT_FROM_WIN32(ERROR_INTERNET_NAME_NOT_RESOLVED),
  10197. INET_E_UNKNOWN_PROTOCOL,
  10198. INET_E_REDIRECT_FAILED,
  10199. INET_E_DATA_NOT_AVAILABLE,
  10200. };
  10201. for (int i=0; i<ARRAYSIZE(c_ahres); i++) {
  10202. if (c_ahres[i]==hrError) {
  10203. MLLoadString(IDS_ERRMSG_FIRST+i, szMsg, ARRAYSIZE(szMsg));
  10204. break;
  10205. }
  10206. }
  10207. if (i >= ARRAYSIZE(c_ahres))
  10208. {
  10209. // Default message if FormatMessage doesn't recognize dwLastError
  10210. MLLoadString(IDS_UNDEFINEDERR, szMsg, ARRAYSIZE(szMsg));
  10211. if (hrError >= HRESULT_FROM_WIN32(INTERNET_ERROR_BASE)
  10212. && hrError <= HRESULT_FROM_WIN32(INTERNET_ERROR_LAST))
  10213. {
  10214. HMODULE hmod = GetModuleHandle(TEXT("WININET"));
  10215. ASSERT(hmod);
  10216. FormatMessage(FORMAT_MESSAGE_FROM_HMODULE, (LPCVOID)hmod, HRESULT_CODE(hrError), 0L,
  10217. szMsg, ARRAYSIZE(szMsg), NULL);
  10218. } else {
  10219. // See if one of the system components has an error message
  10220. // for this error. If not, szMsg will retain our default
  10221. // message to handle this.
  10222. FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, hrError, 0L,
  10223. szMsg, ARRAYSIZE(szMsg), NULL);
  10224. }
  10225. }
  10226. psbParent = psb;
  10227. if (psbParent)
  10228. {
  10229. psbParent->AddRef();
  10230. }
  10231. // Here we make an heroic effort to find a visible window to run the dialog against
  10232. // If we can't, then we bail, to avoid weird UI effect (particularly when the frametop
  10233. // browser is in kiosk mode
  10234. if (!IsWindowVisible(hwndParent))
  10235. {
  10236. if (NULL == psb || FAILED(psb->GetWindow(&hwndParent)) || !IsWindowVisible(hwndParent))
  10237. {
  10238. hwndParent = NULL;
  10239. ATOMICRELEASE(psbParent);
  10240. }
  10241. if (NULL == hwndParent && psb)
  10242. {
  10243. IUnknown_QueryService(psb, SID_STopFrameBrowser, IID_IShellBrowser, (void **)&psbParent);
  10244. if (NULL == psbParent || FAILED(psbParent->GetWindow(&hwndParent)) || !IsWindowVisible(hwndParent))
  10245. {
  10246. hwndParent = NULL;
  10247. }
  10248. }
  10249. }
  10250. if (hwndParent)
  10251. {
  10252. if (psbParent) {
  10253. psbParent->EnableModelessSB(FALSE);
  10254. }
  10255. uRet = MLShellMessageBox(hwndParent,
  10256. MAKEINTRESOURCE(idResource),
  10257. MAKEINTRESOURCE(IDS_TITLE),
  10258. wFlags, pszURL,szMsg);
  10259. if (psbParent) {
  10260. psbParent->EnableModelessSB(TRUE);
  10261. }
  10262. }
  10263. if (psbParent)
  10264. {
  10265. UINT cRef = psbParent->Release();
  10266. AssertMsg(cRef>0, TEXT("IE_ErrorMsgBox psb->Release returned 0."));
  10267. }
  10268. return uRet;
  10269. }
  10270. //
  10271. // See if the URL is of a type that we should
  10272. // ShellExecute()
  10273. //
  10274. HRESULT IsProtocolRegistered(LPCTSTR pcszProtocol);
  10275. BOOL ShouldShellExecURL(LPTSTR pszURL)
  10276. {
  10277. BOOL fRet = FALSE;
  10278. PARSEDURL pu = {sizeof(pu)};
  10279. HRESULT hr = ParseURL(pszURL, &pu);
  10280. if (SUCCEEDED(hr) && pu.nScheme != URL_SCHEME_SHELL)
  10281. {
  10282. TCHAR sz[MAX_PATH];
  10283. *sz = 0;
  10284. hr = StringCchCatN(sz, ARRAYSIZE(sz), pu.pszProtocol, pu.cchProtocol);
  10285. if (SUCCEEDED(hr))
  10286. {
  10287. hr = IsProtocolRegistered(sz);
  10288. if (SUCCEEDED(hr))
  10289. {
  10290. //
  10291. // HACKHACK - telnet.exe will fault on buffer overrun
  10292. // if the url is > 230. we special case here.
  10293. //
  10294. if (lstrlen(pszURL) <= 230 ||
  10295. (StrCmpI(sz, TEXT("telnet")) &&
  10296. StrCmpI(sz, TEXT("rlogin")) &&
  10297. StrCmpI(sz, TEXT("tn3270"))
  10298. )
  10299. )
  10300. {
  10301. fRet = TRUE;
  10302. }
  10303. }
  10304. }
  10305. }
  10306. return fRet;
  10307. }
  10308. //========================================================================
  10309. // class CShdAdviseSink
  10310. //========================================================================
  10311. class CShdAdviseSink : public IAdviseSink
  10312. {
  10313. public:
  10314. // *** IUnknown methods ***
  10315. virtual STDMETHODIMP QueryInterface(REFIID riid, void ** ppvObj);
  10316. virtual STDMETHODIMP_(ULONG) AddRef(void) ;
  10317. virtual STDMETHODIMP_(ULONG) Release(void);
  10318. // *** IAdviseSink methods ***
  10319. virtual void __stdcall OnDataChange(
  10320. FORMATETC *pFormatetc,
  10321. STGMEDIUM *pStgmed);
  10322. virtual void __stdcall OnViewChange(
  10323. DWORD dwAspect,
  10324. LONG lindex);
  10325. virtual void __stdcall OnRename(
  10326. IMoniker *pmk);
  10327. virtual void __stdcall OnSave( void);
  10328. virtual void __stdcall OnClose( void);
  10329. CShdAdviseSink(IBrowserService* pwb, IOleObject* pole);
  10330. ~CShdAdviseSink();
  10331. protected:
  10332. UINT _cRef;
  10333. IOleObject* _pole;
  10334. DWORD _dwConnection;
  10335. };
  10336. //
  10337. // We'd better maintain the list of those CShdAdviseSink
  10338. // per-thread so that we don't leak all those oleobjects when
  10339. // the thread is terminated before those objects are closed.
  10340. //
  10341. void CShdAdviseSink_Advise(IBrowserService* pwb, IOleObject* pole)
  10342. {
  10343. IAdviseSink* padv = new CShdAdviseSink(pwb, pole);
  10344. // If pole->Advise succeeds, it will addreff to IAdviseSink.
  10345. if (padv != NULL)
  10346. {
  10347. padv->Release();
  10348. }
  10349. }
  10350. CShdAdviseSink::CShdAdviseSink(IBrowserService* pwb, IOleObject* pole)
  10351. : _cRef(1)
  10352. {
  10353. ASSERT(pole);
  10354. TraceMsg(DM_ADVISE, "CShdAdviseSink(%x) being constructed", this);
  10355. HRESULT hres = pole->Advise(this, &_dwConnection);
  10356. if (SUCCEEDED(hres)) {
  10357. _pole = pole;
  10358. pole->AddRef();
  10359. TraceMsg(DM_ADVISE, "CShdAdviseSink(%x) called pole->Advise. new _cRef=%d (%x)", this, _cRef, _dwConnection);
  10360. }
  10361. }
  10362. CShdAdviseSink::~CShdAdviseSink()
  10363. {
  10364. TraceMsg(DM_ADVISE, "CShdAdviseSink(%x) being destroyed", this);
  10365. ATOMICRELEASE(_pole);
  10366. }
  10367. ULONG CShdAdviseSink::AddRef()
  10368. {
  10369. _cRef++;
  10370. TraceMsg(TF_SHDREF, "CShdAdviseSink(%x)::AddRef called, new _cRef=%d", this, _cRef);
  10371. return _cRef;
  10372. }
  10373. ULONG CShdAdviseSink::Release()
  10374. {
  10375. _cRef--;
  10376. TraceMsg(TF_SHDREF, "CShdAdviseSink(%x)::Release called, new _cRef=%d", this, _cRef);
  10377. if (_cRef > 0)
  10378. return _cRef;
  10379. delete this;
  10380. return 0;
  10381. }
  10382. HRESULT CShdAdviseSink::QueryInterface(REFIID riid, void ** ppvObj)
  10383. {
  10384. if (IsEqualIID(riid, IID_IAdviseSink) ||
  10385. IsEqualIID(riid, IID_IUnknown))
  10386. {
  10387. *ppvObj = (IAdviseSink*)this;
  10388. }
  10389. else
  10390. {
  10391. *ppvObj = NULL;
  10392. return E_NOINTERFACE;
  10393. }
  10394. AddRef();
  10395. return NOERROR;
  10396. }
  10397. void CShdAdviseSink::OnDataChange(
  10398. FORMATETC *pFormatetc,
  10399. STGMEDIUM *pStgmed)
  10400. {
  10401. }
  10402. void CShdAdviseSink::OnViewChange(
  10403. DWORD dwAspect,
  10404. LONG lindex)
  10405. {
  10406. }
  10407. void CShdAdviseSink::OnRename(
  10408. IMoniker *pmk)
  10409. {
  10410. }
  10411. void CShdAdviseSink::OnSave( void)
  10412. {
  10413. }
  10414. void CShdAdviseSink::OnClose( void)
  10415. {
  10416. TraceMsg(DM_ADVISE, "CShdAdviseSink(%x)::OnClose called. Calling Unadvise. _cRef=%d", this, _cRef);
  10417. HRESULT hres;
  10418. AddRef();
  10419. ASSERT(_pole);
  10420. if (_pole) // paranoia
  10421. {
  10422. hres = _pole->Unadvise(_dwConnection);
  10423. ATOMICRELEASE(_pole);
  10424. TraceMsg(DM_ADVISE, "CShdAdviseSink(%x)::OnClose. Called Unadvise(%x). new _cRef=%d", this, hres, _cRef);
  10425. }
  10426. Release();
  10427. }
  10428. /// adding property sheet pages
  10429. HRESULT CDocObjectHost::AddPages(LPFNADDPROPSHEETPAGE lpfnAddPage, LPARAM lParam)
  10430. {
  10431. HRESULT hres = S_OK;
  10432. IShellPropSheetExt *pspse;
  10433. /*
  10434. * Create a property sheet page for required page, including imported File
  10435. * Types property sheet.
  10436. */
  10437. // add stuff that the docobj itself has.
  10438. if (_pole)
  10439. {
  10440. if (SUCCEEDED(_pole->QueryInterface(IID_IShellPropSheetExt, (void **)&pspse)))
  10441. {
  10442. hres = pspse->AddPages(lpfnAddPage, lParam);
  10443. pspse->Release();
  10444. }
  10445. else
  10446. {
  10447. // Some docobjects don't know about IShellPropSheetExt (ie, Visual Basic),
  10448. // so do it ourselves.
  10449. if (NULL == _hinstInetCpl)
  10450. _hinstInetCpl = LoadLibrary(TEXT("inetcpl.cpl"));
  10451. if (_hinstInetCpl)
  10452. {
  10453. PFNADDINTERNETPROPERTYSHEETSEX pfnAddSheet = (PFNADDINTERNETPROPERTYSHEETSEX)GetProcAddress(_hinstInetCpl, STR_ADDINTERNETPROPSHEETSEX);
  10454. if (pfnAddSheet)
  10455. {
  10456. IEPROPPAGEINFO iepi = {0};
  10457. // we just want the security page.
  10458. iepi.cbSize = sizeof(iepi);
  10459. iepi.dwFlags = (DWORD)-1; // all pages
  10460. hres = pfnAddSheet(lpfnAddPage, lParam, 0, 0, &iepi);
  10461. }
  10462. // Don't FreeLibrary here, otherwise PropertyPage will GP-fault!
  10463. }
  10464. }
  10465. }
  10466. return hres;
  10467. }
  10468. //==========================================================================
  10469. // IDocHostUIHandler implementation
  10470. //==========================================================================
  10471. HRESULT CDocObjectHost::TranslateAccelerator(LPMSG lpMsg, const GUID *pguidCmdGroup, DWORD nCmdID)
  10472. {
  10473. if (_pWebOCUIHandler)
  10474. return _pWebOCUIHandler->TranslateAccelerator(lpMsg, pguidCmdGroup, nCmdID);
  10475. return _dhUIHandler.TranslateAccelerator(lpMsg, pguidCmdGroup, nCmdID);
  10476. }
  10477. HRESULT CDocObjectHost::GetDropTarget(IDropTarget *pDropTarget, IDropTarget **ppDropTarget)
  10478. {
  10479. // REVIEW: Does this apply anymore?
  10480. TraceMsg(DM_DOCHOSTUIHANDLER, "CDOH::GetDropTarget called");
  10481. HRESULT hres;
  10482. if (_pWebOCUIHandler)
  10483. {
  10484. hres = _pWebOCUIHandler->GetDropTarget(pDropTarget, ppDropTarget);
  10485. if (SUCCEEDED(hres))
  10486. return hres;
  10487. }
  10488. if (pDropTarget)
  10489. {
  10490. hres = S_OK;
  10491. IDropTarget *pdtFrame;
  10492. IDropTarget *pdt3;
  10493. IDropTarget *pdtBlocking;
  10494. QueryService(SID_STopFrameBrowser, IID_IDropTarget, (void **)&pdtFrame);
  10495. // hack: this is because we need to look all the way through to top parents for a containing drop target
  10496. // what we really need is a per dataobject drop target
  10497. //
  10498. // this is not required to be obtained
  10499. QueryService(SID_ITopViewHost, IID_IDropTarget, (void **)&pdt3);
  10500. if (IsSameObject(pdt3, pdtFrame)) {
  10501. ATOMICRELEASE(pdt3);
  10502. }
  10503. // allow constrained browser bands like Search to prevent drop
  10504. QueryService(SID_SDropBlocker, IID_IUnknown, (void **)&pdtBlocking);
  10505. if (pdtBlocking)
  10506. {
  10507. ATOMICRELEASE(pdt3);
  10508. pDropTarget = NULL;
  10509. }
  10510. if (pdtFrame)
  10511. {
  10512. *ppDropTarget = DropTargetWrap_CreateInstance(pDropTarget, pdtFrame, _hwnd, pdt3);
  10513. if (!*ppDropTarget)
  10514. hres = E_OUTOFMEMORY;
  10515. TraceMsg(DM_DOCHOSTUIHANDLER, "CDOH::GetDropTarget returning S_OK");
  10516. ASSERT(hres == S_OK);
  10517. pdtFrame->Release();
  10518. }
  10519. else
  10520. {
  10521. ASSERT(0);
  10522. hres = E_UNEXPECTED;
  10523. }
  10524. ATOMICRELEASE(pdtBlocking);
  10525. ATOMICRELEASE(pdt3);
  10526. }
  10527. else
  10528. {
  10529. hres = E_INVALIDARG;
  10530. }
  10531. return hres;
  10532. }
  10533. HRESULT CDocObjectHost::ShowUI(
  10534. DWORD dwID, IOleInPlaceActiveObject *pActiveObject,
  10535. IOleCommandTarget *pCommandTarget, IOleInPlaceFrame *pFrame,
  10536. IOleInPlaceUIWindow *pDoc)
  10537. {
  10538. if (_pWebOCUIHandler)
  10539. return _pWebOCUIHandler->ShowUI(dwID, pActiveObject, pCommandTarget, pFrame, pDoc);
  10540. if (_dwAppHack & BROWSERFLAG_MSHTML) // Who else will call on this interface?
  10541. {
  10542. if (_pmsoctBrowser)
  10543. {
  10544. TraceMsg(DM_PREMERGEDMENU, "DOH::ShowUI called this=%x pcmd=%x",
  10545. this,pCommandTarget);
  10546. VARIANT var = { 0 };
  10547. HRESULT hresT=_pmsoctBrowser->Exec(&CGID_Explorer, SBCMDID_SETMERGEDWEBMENU, 0, NULL, &var);
  10548. if (SUCCEEDED(hresT))
  10549. {
  10550. if (_pcmdMergedMenu)
  10551. {
  10552. // Tell Trident to stop calling us twice
  10553. TraceMsg(DM_WARNING, "DOH::ShowUI called twice! "
  10554. "this=%x pcmdCur=%x pcmdNew=%x",
  10555. this, _pcmdMergedMenu, pCommandTarget);
  10556. _pcmdMergedMenu->Release();
  10557. }
  10558. _pcmdMergedMenu = pCommandTarget;
  10559. _pcmdMergedMenu->AddRef();
  10560. ASSERT(var.vt == VT_INT_PTR);
  10561. _hmenuCur = (HMENU)var.byref;
  10562. DEBUG_CODE( _DumpMenus(TEXT("after ShowUI"), TRUE); )
  10563. return S_OK;
  10564. }
  10565. }
  10566. }
  10567. return S_FALSE;
  10568. }
  10569. HRESULT CDocObjectHost::HideUI(void)
  10570. {
  10571. if (_pWebOCUIHandler)
  10572. return _pWebOCUIHandler->HideUI();
  10573. if (_pcmdMergedMenu) {
  10574. _pcmdMergedMenu->Release();
  10575. _pcmdMergedMenu = NULL;
  10576. }
  10577. return S_FALSE;
  10578. }
  10579. HRESULT CDocObjectHost::GetHostInfo(DOCHOSTUIINFO *pInfo)
  10580. {
  10581. IServiceProvider * psp = NULL;
  10582. IWebBrowser2 * pwb = NULL;
  10583. VARIANT_BOOL b = VARIANT_FALSE;
  10584. DWORD dwFlagsWebOC = 0;
  10585. HRESULT hr;
  10586. if (_pWebOCUIHandler
  10587. && SUCCEEDED(_pWebOCUIHandler->GetHostInfo(pInfo))
  10588. )
  10589. {
  10590. dwFlagsWebOC = pInfo->dwFlags;
  10591. }
  10592. _dhUIHandler.GetHostInfo(pInfo);
  10593. // Merge flags
  10594. //
  10595. pInfo->dwFlags |= dwFlagsWebOC;
  10596. // Add the local machine flag, if we're in iexplore.exe or explorer.exe.
  10597. if (IsInternetExplorerApp())
  10598. pInfo->dwFlags |= DOCHOSTUIFLAG_LOCAL_MACHINE_ACCESS_CHECK;
  10599. // Get the top level browser
  10600. //
  10601. hr = QueryService(SID_STopLevelBrowser, IID_PPV_ARG(IServiceProvider, &psp));
  10602. if (hr)
  10603. goto Cleanup;
  10604. // Get the IWebBrowser2 object/interface
  10605. //
  10606. hr = psp->QueryService(SID_SContainerDispatch, IID_IWebBrowser2, (void **)&pwb);
  10607. if (hr)
  10608. goto Cleanup;
  10609. // Tell the browser what our dochost flags are
  10610. IEFrameAuto *pIEFrameAuto;
  10611. if (SUCCEEDED(pwb->QueryInterface(IID_PPV_ARG(IEFrameAuto, &pIEFrameAuto))))
  10612. {
  10613. pIEFrameAuto->SetDocHostFlags(pInfo->dwFlags);
  10614. pIEFrameAuto->Release();
  10615. }
  10616. // Is the browser in Theater Mode?
  10617. //
  10618. hr = pwb->get_TheaterMode(&b);
  10619. if (hr)
  10620. goto Cleanup;
  10621. // If so, turn on flat scrollbars.
  10622. //
  10623. if (b == VARIANT_TRUE)
  10624. pInfo->dwFlags |= DOCHOSTUIFLAG_FLAT_SCROLLBAR;
  10625. Cleanup:
  10626. ATOMICRELEASE(psp);
  10627. ATOMICRELEASE(pwb);
  10628. return S_OK;
  10629. }
  10630. HRESULT CDocObjectHost::ShowContextMenu(DWORD dwID, POINT *ppt, IUnknown *pcmdtReserved, IDispatch *pdispReserved)
  10631. {
  10632. HRESULT hr;
  10633. OLECMD rgcmd = { IDM_BROWSEMODE, 0 };
  10634. // If we're in the WebOC and it has a IDocHostUIHandler, use it.
  10635. //
  10636. if ( _pWebOCUIHandler && !SHRestricted2W(REST_NoBrowserContextMenu, NULL, 0))
  10637. {
  10638. hr = _pWebOCUIHandler->ShowContextMenu(dwID, ppt, pcmdtReserved, pdispReserved);
  10639. if (hr == S_OK)
  10640. goto Cleanup;
  10641. }
  10642. // Find out if the DocObject is in Edit mode
  10643. // Don't need apphack here as only Trident responds to CGID_MSHTML
  10644. //
  10645. hr = IUnknown_QueryStatus(pcmdtReserved, &CGID_MSHTML, 1, &rgcmd, NULL);
  10646. if ( hr == S_OK
  10647. && !(rgcmd.cmdf & OLECMDF_LATCHED)) // if not LATCHED means we're in edit mode.
  10648. {
  10649. hr = S_FALSE;
  10650. }
  10651. else
  10652. {
  10653. hr = _dhUIHandler.ShowContextMenu(dwID, ppt, pcmdtReserved, pdispReserved);
  10654. }
  10655. Cleanup:
  10656. return hr;
  10657. }
  10658. HRESULT CDocObjectHost::UpdateUI(void)
  10659. {
  10660. if (_pWebOCUIHandler)
  10661. return _pWebOCUIHandler->UpdateUI();
  10662. return _dhUIHandler.UpdateUI();
  10663. }
  10664. HRESULT CDocObjectHost::EnableModeless(BOOL fEnable)
  10665. {
  10666. if (_pWebOCUIHandler)
  10667. return _pWebOCUIHandler->EnableModeless(fEnable);
  10668. return _dhUIHandler.EnableModeless(fEnable);
  10669. }
  10670. HRESULT CDocObjectHost::OnDocWindowActivate(BOOL fActivate)
  10671. {
  10672. if (_pWebOCUIHandler)
  10673. return _pWebOCUIHandler->OnDocWindowActivate(fActivate);
  10674. return _dhUIHandler.OnDocWindowActivate(fActivate);
  10675. }
  10676. HRESULT CDocObjectHost::OnFrameWindowActivate(BOOL fActivate)
  10677. {
  10678. if (_pWebOCUIHandler)
  10679. return _pWebOCUIHandler->OnFrameWindowActivate(fActivate);
  10680. return _dhUIHandler.OnFrameWindowActivate(fActivate);
  10681. }
  10682. HRESULT CDocObjectHost::ResizeBorder( LPCRECT prcBorder, IOleInPlaceUIWindow *pUIWindow, BOOL fRameWindow)
  10683. {
  10684. if (_pWebOCUIHandler)
  10685. return _pWebOCUIHandler->ResizeBorder(prcBorder, pUIWindow, fRameWindow);
  10686. return _dhUIHandler.ResizeBorder(prcBorder, pUIWindow, fRameWindow);
  10687. }
  10688. HRESULT CDocObjectHost::GetOptionKeyPath(BSTR *pbstrKey, DWORD dw)
  10689. {
  10690. if (_pWebOCUIHandler)
  10691. return _pWebOCUIHandler->GetOptionKeyPath(pbstrKey, dw);
  10692. return _dhUIHandler.GetOptionKeyPath(pbstrKey, dw);
  10693. }
  10694. HRESULT CDocObjectHost::GetExternal(IDispatch **ppDisp)
  10695. {
  10696. if (_pWebOCUIHandler)
  10697. return _pWebOCUIHandler->GetExternal(ppDisp);
  10698. return _dhUIHandler.GetExternal(ppDisp);
  10699. }
  10700. HRESULT CDocObjectHost::TranslateUrl(DWORD dwTranslate, OLECHAR *pchURLIn, OLECHAR **ppchURLOut)
  10701. {
  10702. if (_pWebOCUIHandler)
  10703. return _pWebOCUIHandler->TranslateUrl(dwTranslate, pchURLIn, ppchURLOut);
  10704. return _dhUIHandler.TranslateUrl(dwTranslate, pchURLIn, ppchURLOut);
  10705. }
  10706. HRESULT CDocObjectHost::FilterDataObject(IDataObject *pDO, IDataObject **ppDORet)
  10707. {
  10708. if (_pWebOCUIHandler)
  10709. return _pWebOCUIHandler->FilterDataObject(pDO, ppDORet);
  10710. return _dhUIHandler.FilterDataObject(pDO, ppDORet);
  10711. }
  10712. HRESULT CDocObjectHost::GetOverrideKeyPath(LPOLESTR *pchKey, DWORD dw)
  10713. {
  10714. if (_pWebOCUIHandler2)
  10715. return _pWebOCUIHandler2->GetOverrideKeyPath(pchKey, dw);
  10716. return _dhUIHandler.GetOverrideKeyPath(pchKey, dw);
  10717. }
  10718. HRESULT CDocObjectHost::ShowMessage(HWND hwnd, LPOLESTR lpstrText, LPOLESTR lpstrCaption,
  10719. DWORD dwType, LPOLESTR lpstrHelpFile, DWORD dwHelpContext, LRESULT __RPC_FAR *plResult)
  10720. {
  10721. if (_pWebOCShowUI)
  10722. {
  10723. return _pWebOCShowUI->ShowMessage(hwnd, lpstrText, lpstrCaption, dwType,
  10724. lpstrHelpFile, dwHelpContext, plResult);
  10725. }
  10726. return E_FAIL;
  10727. }
  10728. HRESULT CDocObjectHost::ShowHelp(HWND hwnd, LPOLESTR pszHelpFile, UINT uCommand, DWORD dwData,
  10729. POINT ptMouse, IDispatch __RPC_FAR *pDispatchObjectHit)
  10730. {
  10731. if (_pWebOCShowUI)
  10732. {
  10733. return _pWebOCShowUI->ShowHelp(hwnd, pszHelpFile, uCommand, dwData, ptMouse,
  10734. pDispatchObjectHit);
  10735. }
  10736. return E_FAIL;
  10737. }
  10738. void
  10739. CDocObjectHost::HideBrowser() const
  10740. {
  10741. if (_psp && _fWindowOpen && !(_dwAppHack & BROWSERFLAG_DONTAUTOCLOSE))
  10742. {
  10743. IWebBrowser2 * pWebBrowser;
  10744. HRESULT hres = _psp->QueryService(SID_SWebBrowserApp,
  10745. IID_PPV_ARG(IWebBrowser2, &pWebBrowser));
  10746. if (SUCCEEDED(hres))
  10747. {
  10748. pWebBrowser->put_Visible(VARIANT_FALSE);
  10749. pWebBrowser->Release();
  10750. }
  10751. }
  10752. }
  10753. //
  10754. // support for script error caching and status bar notification
  10755. //
  10756. void
  10757. CDocObjectHost::_ScriptErr_Dlg(BOOL fOverridePerErrorMode)
  10758. {
  10759. // we can get reentered through the message pump ShowHTMLDialog runs
  10760. // therefore we might already have a dialog open when a second dialog
  10761. // is requested
  10762. if (_fScriptErrDlgOpen)
  10763. {
  10764. // a dialog is already open lower in the callstack
  10765. // request an up-to-date dialog be shown
  10766. // we have to do this because otherwise we might
  10767. // be in per-error-mode and miss some errors which
  10768. // arrived while the dialog lower in the callstack
  10769. // was open. note that we only do this if we're set
  10770. // to show notifications for every error.
  10771. _fShowScriptErrDlgAgain = SHRegGetBoolUSValue(szRegKey_SMIEM,
  10772. szRegVal_ErrDlgPerErr,
  10773. FALSE,
  10774. TRUE);
  10775. }
  10776. else
  10777. {
  10778. _fScriptErrDlgOpen = TRUE;
  10779. // keep showing dialogs as long as someone farther up the
  10780. // call stack keeps requesting them
  10781. do
  10782. {
  10783. BOOL fShowDlg;
  10784. _fShowScriptErrDlgAgain = FALSE;
  10785. // if the user double clicked on the status bar, then we
  10786. // show the dialog regardless of per-error-mode settings
  10787. if (fOverridePerErrorMode)
  10788. {
  10789. fShowDlg = TRUE;
  10790. // because of other script errors hitting the
  10791. // _fScriptErrDlgOpen code above, we can arrive
  10792. // here multiple times. The first time we show a
  10793. // dialog can be because the user requested it,
  10794. // but all subsequent times must be because we're
  10795. // in "show every error" mode.
  10796. fOverridePerErrorMode = FALSE;
  10797. }
  10798. else
  10799. {
  10800. fShowDlg = SHRegGetBoolUSValue(szRegKey_SMIEM,
  10801. szRegVal_ErrDlgPerErr,
  10802. FALSE,
  10803. TRUE);
  10804. }
  10805. if (fShowDlg)
  10806. {
  10807. HRESULT hr;
  10808. TCHAR szResURL[MAX_URL_STRING];
  10809. hr = MLBuildResURLWrap(TEXT("shdoclc.dll"),
  10810. HINST_THISDLL,
  10811. ML_CROSSCODEPAGE,
  10812. TEXT("ieerror.dlg"),
  10813. szResURL,
  10814. ARRAYSIZE(szResURL),
  10815. TEXT("shdocvw.dll"));
  10816. if (SUCCEEDED(hr))
  10817. {
  10818. IMoniker * pmk;
  10819. HWND hwnd;
  10820. hr = CreateURLMoniker(NULL, szResURL, &pmk);
  10821. if (SUCCEEDED(hr))
  10822. {
  10823. VARIANT varErrorCache;
  10824. V_VT(&varErrorCache) = VT_DISPATCH;
  10825. V_DISPATCH(&varErrorCache) = _pScriptErrList;
  10826. GetWindow(&hwnd);
  10827. ShowHTMLDialog(hwnd, pmk, &varErrorCache, L"help:no", NULL);
  10828. ATOMICRELEASE(pmk);
  10829. }
  10830. }
  10831. }
  10832. } while (_fShowScriptErrDlgAgain);
  10833. _fScriptErrDlgOpen = FALSE;
  10834. }
  10835. }
  10836. HRESULT
  10837. CDocObjectHost::_ScriptErr_CacheInfo(VARIANTARG *pvarIn)
  10838. {
  10839. IHTMLDocument2 * pOmDoc;
  10840. IHTMLWindow2 * pOmWindow;
  10841. IHTMLEventObj * pEventObj;
  10842. HRESULT hr;
  10843. TCHAR * apchNames[] =
  10844. { TEXT("errorLine"),
  10845. TEXT("errorCharacter"),
  10846. TEXT("errorCode"),
  10847. TEXT("errorMessage"),
  10848. TEXT("errorUrl")
  10849. };
  10850. DISPID aDispid[ARRAYSIZE(apchNames)];
  10851. VARIANT varOut[ARRAYSIZE(apchNames)];
  10852. int i;
  10853. pOmDoc = NULL;
  10854. pOmWindow = NULL;
  10855. pEventObj = NULL;
  10856. // load the script error object
  10857. hr = V_UNKNOWN(pvarIn)->QueryInterface(IID_IHTMLDocument2, (void **) &pOmDoc);
  10858. if (FAILED(hr))
  10859. {
  10860. return hr;
  10861. }
  10862. hr = pOmDoc->get_parentWindow(&pOmWindow);
  10863. ATOMICRELEASE(pOmDoc);
  10864. if (FAILED(hr))
  10865. {
  10866. return hr;
  10867. }
  10868. hr = pOmWindow->get_event(&pEventObj);
  10869. ATOMICRELEASE(pOmWindow);
  10870. if (FAILED(hr))
  10871. {
  10872. return hr;
  10873. }
  10874. //
  10875. // copy the interesting data out of the event object
  10876. //
  10877. for (i = 0; i < ARRAYSIZE(apchNames); i++)
  10878. {
  10879. DISPPARAMS params;
  10880. // get the property's dispid
  10881. hr = pEventObj->GetIDsOfNames(IID_NULL, &apchNames[i], 1, LOCALE_SYSTEM_DEFAULT, &aDispid[i]);
  10882. if (hr != S_OK)
  10883. {
  10884. ATOMICRELEASE(pEventObj);
  10885. return hr;
  10886. }
  10887. params.cArgs = 0;
  10888. params.cNamedArgs = 0;
  10889. hr = pEventObj->Invoke(aDispid[i], IID_NULL, LOCALE_SYSTEM_DEFAULT, DISPATCH_PROPERTYGET, &params, &varOut[i], NULL, NULL);
  10890. if (hr != S_OK)
  10891. {
  10892. ATOMICRELEASE(pEventObj);
  10893. return hr;
  10894. }
  10895. }
  10896. ATOMICRELEASE(pEventObj);
  10897. ASSERT(V_VT(&varOut[0]) == VT_I4);
  10898. ASSERT(V_VT(&varOut[1]) == VT_I4);
  10899. ASSERT(V_VT(&varOut[2]) == VT_I4);
  10900. ASSERT(V_VT(&varOut[3]) == VT_BSTR);
  10901. ASSERT(V_VT(&varOut[4]) == VT_BSTR);
  10902. ASSERT(ARRAYSIZE(apchNames) == 5);
  10903. hr = _pScriptErrList->AddNewErrorInfo(V_I4(&varOut[0]), // line
  10904. V_I4(&varOut[1]), // char
  10905. V_I4(&varOut[2]), // code
  10906. V_BSTR(&varOut[3]), // message
  10907. V_BSTR(&varOut[4])); // url
  10908. return hr;
  10909. }
  10910. //
  10911. // CScriptErrorList manages an array of _CScriptErrInfo objects
  10912. // the script error handler dialogs access this information
  10913. // when requested by the user
  10914. //
  10915. CScriptErrorList::CScriptErrorList() :
  10916. CImpIDispatch(LIBID_SHDocVw, 1, 1, IID_IScriptErrorList)
  10917. {
  10918. ASSERT(_lDispIndex == 0);
  10919. _ulRefCount = 1;
  10920. _hdpa = DPA_Create(4);
  10921. }
  10922. CScriptErrorList::~CScriptErrorList()
  10923. {
  10924. if (_hdpa != NULL)
  10925. {
  10926. ClearErrorList();
  10927. DPA_Destroy(_hdpa);
  10928. _hdpa = NULL;
  10929. }
  10930. }
  10931. HRESULT
  10932. CScriptErrorList::AddNewErrorInfo(LONG lLine,
  10933. LONG lChar,
  10934. LONG lCode,
  10935. BSTR strMsg,
  10936. BSTR strUrl)
  10937. {
  10938. HRESULT hr;
  10939. _CScriptErrInfo * pNewData;
  10940. if (strMsg == NULL || strUrl == NULL)
  10941. {
  10942. return E_INVALIDARG;
  10943. }
  10944. pNewData = new _CScriptErrInfo;
  10945. if (pNewData != NULL)
  10946. {
  10947. hr = pNewData->Init(lLine, lChar, lCode, strMsg, strUrl);
  10948. if (SUCCEEDED(hr))
  10949. {
  10950. if (_hdpa != NULL)
  10951. {
  10952. DPA_AppendPtr(_hdpa, (LPVOID)pNewData);
  10953. _lDispIndex = DPA_GetPtrCount(_hdpa)-1;
  10954. }
  10955. else
  10956. {
  10957. delete pNewData;
  10958. hr = E_FAIL;
  10959. }
  10960. }
  10961. else
  10962. {
  10963. delete pNewData;
  10964. }
  10965. }
  10966. else
  10967. {
  10968. hr = E_OUTOFMEMORY;
  10969. }
  10970. return hr;
  10971. }
  10972. void
  10973. CScriptErrorList::ClearErrorList()
  10974. {
  10975. if (_hdpa != NULL)
  10976. {
  10977. int iDel;
  10978. int cPtr;
  10979. cPtr = DPA_GetPtrCount(_hdpa);
  10980. // delete from end to beginning to avoid unnecessary packing
  10981. for (iDel = cPtr-1; iDel >= 0; iDel--)
  10982. {
  10983. delete ((_CScriptErrInfo *)DPA_GetPtr(_hdpa, iDel));
  10984. DPA_DeletePtr(_hdpa, iDel);
  10985. }
  10986. _lDispIndex = 0;
  10987. }
  10988. }
  10989. STDMETHODIMP
  10990. CScriptErrorList::QueryInterface(REFIID iid, void ** ppObj)
  10991. {
  10992. ASSERT(ppObj != NULL);
  10993. if (IsEqualIID(iid, IID_IUnknown) ||
  10994. IsEqualIID(iid, IID_IDispatch) ||
  10995. IsEqualIID(iid, IID_IScriptErrorList))
  10996. {
  10997. *ppObj = (IScriptErrorList *)this;
  10998. }
  10999. else
  11000. {
  11001. *ppObj = NULL;
  11002. return E_NOINTERFACE;
  11003. }
  11004. AddRef();
  11005. return S_OK;
  11006. }
  11007. STDMETHODIMP_(ULONG)
  11008. CScriptErrorList::AddRef()
  11009. {
  11010. _ulRefCount++;
  11011. return _ulRefCount;
  11012. }
  11013. STDMETHODIMP_(ULONG)
  11014. CScriptErrorList::Release()
  11015. {
  11016. _ulRefCount--;
  11017. if (_ulRefCount > 0)
  11018. {
  11019. return _ulRefCount;
  11020. }
  11021. delete this;
  11022. return 0;
  11023. }
  11024. STDMETHODIMP
  11025. CScriptErrorList::advanceError()
  11026. {
  11027. HRESULT hr;
  11028. hr = E_FAIL;
  11029. if (_hdpa != NULL)
  11030. {
  11031. int cPtr;
  11032. cPtr = DPA_GetPtrCount(_hdpa);
  11033. if (_lDispIndex < cPtr-1)
  11034. {
  11035. _lDispIndex++;
  11036. hr = S_OK;
  11037. }
  11038. }
  11039. return hr;
  11040. }
  11041. STDMETHODIMP
  11042. CScriptErrorList::retreatError()
  11043. {
  11044. if (_lDispIndex < 1)
  11045. {
  11046. return E_FAIL;
  11047. }
  11048. _lDispIndex--;
  11049. return S_OK;
  11050. }
  11051. STDMETHODIMP
  11052. CScriptErrorList::canAdvanceError(BOOL * pfCanAdvance)
  11053. {
  11054. HRESULT hr;
  11055. ASSERT(pfCanAdvance != NULL);
  11056. hr = E_FAIL;
  11057. if (_hdpa != NULL)
  11058. {
  11059. int cPtr;
  11060. cPtr = DPA_GetPtrCount(_hdpa);
  11061. *pfCanAdvance = _lDispIndex < cPtr-1;
  11062. hr = S_OK;
  11063. }
  11064. return hr;
  11065. }
  11066. STDMETHODIMP
  11067. CScriptErrorList::canRetreatError(BOOL * pfCanRetreat)
  11068. {
  11069. ASSERT(pfCanRetreat != NULL);
  11070. *pfCanRetreat = _lDispIndex > 0;
  11071. return S_OK;
  11072. }
  11073. STDMETHODIMP
  11074. CScriptErrorList::getErrorLine(LONG * plLine)
  11075. {
  11076. HRESULT hr;
  11077. ASSERT(plLine != NULL);
  11078. ASSERT(_lDispIndex >= 0);
  11079. hr = E_FAIL;
  11080. if (_hdpa != NULL)
  11081. {
  11082. int cPtr;
  11083. cPtr = DPA_GetPtrCount(_hdpa);
  11084. ASSERT(_lDispIndex < cPtr || _lDispIndex == 0);
  11085. if (cPtr > 0)
  11086. {
  11087. _CScriptErrInfo * pInfo;
  11088. pInfo = (_CScriptErrInfo *)DPA_GetPtr(_hdpa, _lDispIndex);
  11089. *plLine = pInfo->_lLine;
  11090. hr = S_OK;
  11091. }
  11092. }
  11093. return hr;
  11094. }
  11095. STDMETHODIMP
  11096. CScriptErrorList::getErrorChar(LONG * plChar)
  11097. {
  11098. HRESULT hr;
  11099. ASSERT(plChar != NULL);
  11100. ASSERT(_lDispIndex >= 0);
  11101. hr = E_FAIL;
  11102. if (_hdpa != NULL)
  11103. {
  11104. int cPtr;
  11105. cPtr = DPA_GetPtrCount(_hdpa);
  11106. ASSERT(_lDispIndex < cPtr || _lDispIndex == 0);
  11107. if (cPtr > 0)
  11108. {
  11109. _CScriptErrInfo * pInfo;
  11110. pInfo = (_CScriptErrInfo *)DPA_GetPtr(_hdpa, _lDispIndex);
  11111. *plChar = pInfo->_lChar;
  11112. hr = S_OK;
  11113. }
  11114. }
  11115. return hr;
  11116. }
  11117. STDMETHODIMP
  11118. CScriptErrorList::getErrorCode(LONG * plCode)
  11119. {
  11120. HRESULT hr;
  11121. ASSERT(plCode != NULL);
  11122. ASSERT(_lDispIndex >= 0);
  11123. hr = E_FAIL;
  11124. if (_hdpa != NULL)
  11125. {
  11126. int cPtr;
  11127. cPtr = DPA_GetPtrCount(_hdpa);
  11128. ASSERT(_lDispIndex < cPtr || _lDispIndex == 0);
  11129. if (cPtr > 0)
  11130. {
  11131. _CScriptErrInfo * pInfo;
  11132. pInfo = (_CScriptErrInfo *)DPA_GetPtr(_hdpa, _lDispIndex);
  11133. *plCode = pInfo->_lCode;
  11134. hr = S_OK;
  11135. }
  11136. }
  11137. return hr;
  11138. }
  11139. STDMETHODIMP
  11140. CScriptErrorList::getErrorMsg(BSTR * pstrMsg)
  11141. {
  11142. HRESULT hr;
  11143. ASSERT(pstrMsg != NULL);
  11144. ASSERT(_lDispIndex >= 0);
  11145. hr = E_FAIL;
  11146. if (_hdpa != NULL)
  11147. {
  11148. int cPtr;
  11149. cPtr = DPA_GetPtrCount(_hdpa);
  11150. ASSERT(_lDispIndex < cPtr || _lDispIndex == 0);
  11151. if (cPtr > 0)
  11152. {
  11153. _CScriptErrInfo * pInfo;
  11154. pInfo = (_CScriptErrInfo *)DPA_GetPtr(_hdpa, _lDispIndex);
  11155. *pstrMsg = SysAllocString(pInfo->_strMsg);
  11156. if (*pstrMsg != NULL)
  11157. {
  11158. hr = S_OK;
  11159. }
  11160. else
  11161. {
  11162. hr = E_OUTOFMEMORY;
  11163. }
  11164. }
  11165. }
  11166. return hr;
  11167. }
  11168. STDMETHODIMP
  11169. CScriptErrorList::getErrorUrl(BSTR * pstrUrl)
  11170. {
  11171. HRESULT hr;
  11172. ASSERT(pstrUrl != NULL);
  11173. ASSERT(_lDispIndex >= 0);
  11174. hr = E_FAIL;
  11175. if (_hdpa != NULL)
  11176. {
  11177. int cPtr;
  11178. cPtr = DPA_GetPtrCount(_hdpa);
  11179. ASSERT(_lDispIndex < cPtr || _lDispIndex == 0);
  11180. if (cPtr > 0)
  11181. {
  11182. _CScriptErrInfo * pInfo;
  11183. pInfo = (_CScriptErrInfo *)DPA_GetPtr(_hdpa, _lDispIndex);
  11184. *pstrUrl = SysAllocString(pInfo->_strUrl);
  11185. if (*pstrUrl != NULL)
  11186. {
  11187. hr = S_OK;
  11188. }
  11189. else
  11190. {
  11191. hr = E_OUTOFMEMORY;
  11192. }
  11193. }
  11194. }
  11195. return hr;
  11196. }
  11197. STDMETHODIMP
  11198. CScriptErrorList::getAlwaysShowLockState(BOOL * pfAlwaysShowLocked)
  11199. {
  11200. *pfAlwaysShowLocked = IsInetcplRestricted(TEXT("Advanced"));
  11201. return S_OK;
  11202. }
  11203. STDMETHODIMP
  11204. CScriptErrorList::getDetailsPaneOpen(BOOL * pfDetailsPaneOpen)
  11205. {
  11206. *pfDetailsPaneOpen =
  11207. SHRegGetBoolUSValue(szRegKey_SMIEM,
  11208. szRegVal_ErrDlgDetailsOpen,
  11209. FALSE,
  11210. FALSE);
  11211. return S_OK;
  11212. }
  11213. STDMETHODIMP
  11214. CScriptErrorList::setDetailsPaneOpen(BOOL fDetailsPaneOpen)
  11215. {
  11216. TCHAR szYes[] = TEXT("yes");
  11217. TCHAR szNo[] = TEXT("no");
  11218. LPTSTR pszVal;
  11219. int cbSize;
  11220. if (fDetailsPaneOpen)
  11221. {
  11222. pszVal = szYes;
  11223. cbSize = sizeof(szYes);
  11224. }
  11225. else
  11226. {
  11227. pszVal = szNo;
  11228. cbSize = sizeof(szNo);
  11229. }
  11230. SHRegSetUSValue(szRegKey_SMIEM,
  11231. szRegVal_ErrDlgDetailsOpen,
  11232. REG_SZ,
  11233. pszVal,
  11234. cbSize,
  11235. SHREGSET_HKCU | SHREGSET_FORCE_HKCU);
  11236. // even if it failed, we can't do anything about it...
  11237. return S_OK;
  11238. }
  11239. STDMETHODIMP
  11240. CScriptErrorList::getPerErrorDisplay(BOOL * pfPerErrorDisplay)
  11241. {
  11242. *pfPerErrorDisplay =
  11243. SHRegGetBoolUSValue(szRegKey_SMIEM,
  11244. szRegVal_ErrDlgPerErr,
  11245. FALSE,
  11246. FALSE);
  11247. return S_OK;
  11248. }
  11249. STDMETHODIMP
  11250. CScriptErrorList::setPerErrorDisplay(BOOL fPerErrorDisplay)
  11251. {
  11252. TCHAR szYes[] = TEXT("yes");
  11253. TCHAR szNo[] = TEXT("no");
  11254. LPTSTR pszVal;
  11255. int cbSize;
  11256. if (fPerErrorDisplay)
  11257. {
  11258. pszVal = szYes;
  11259. cbSize = sizeof(szYes);
  11260. }
  11261. else
  11262. {
  11263. pszVal = szNo;
  11264. cbSize = sizeof(szNo);
  11265. }
  11266. SHRegSetUSValue(szRegKey_SMIEM,
  11267. szRegVal_ErrDlgPerErr,
  11268. REG_SZ,
  11269. pszVal,
  11270. cbSize,
  11271. SHREGSET_HKCU | SHREGSET_FORCE_HKCU);
  11272. // even if it failed, we can't do anything about it...
  11273. return S_OK;
  11274. }
  11275. HRESULT
  11276. CScriptErrorList::_CScriptErrInfo::Init(LONG lLine,
  11277. LONG lChar,
  11278. LONG lCode,
  11279. BSTR strMsg,
  11280. BSTR strUrl)
  11281. {
  11282. ASSERT(_strMsg == NULL);
  11283. ASSERT(_strUrl == NULL);
  11284. _strMsg = SysAllocString(strMsg);
  11285. if (_strMsg == NULL)
  11286. {
  11287. return E_OUTOFMEMORY;
  11288. }
  11289. _strUrl = SysAllocString(strUrl);
  11290. if (_strUrl == NULL)
  11291. {
  11292. SysFreeString(_strMsg);
  11293. return E_OUTOFMEMORY;
  11294. }
  11295. _lLine = lLine;
  11296. _lChar = lChar;
  11297. _lCode = lCode;
  11298. return S_OK;
  11299. }
  11300. CScriptErrorList::_CScriptErrInfo::~_CScriptErrInfo()
  11301. {
  11302. if (_strMsg != NULL)
  11303. {
  11304. SysFreeString(_strMsg);
  11305. }
  11306. if (_strUrl != NULL)
  11307. {
  11308. SysFreeString(_strUrl);
  11309. }
  11310. }