Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

13569 lines
415 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. #include <strsafe.h>
  83. // temp, going away once itbar edit stuff moves here
  84. #define CITIDM_EDITPAGE 10
  85. // Command group for private communication with CITBar
  86. // 67077B95-4F9D-11D0-B884-00AA00B60104
  87. const GUID CGID_PrivCITCommands = { 0x67077B95L, 0x4F9D, 0x11D0, 0xB8, 0x84,
  88. 0x00, 0xAA, 0x00, 0xB6, 0x01, 0x04 };
  89. // end temp itbar stuff
  90. // Command group for accessing Bind Context Param set by Trident (Media Bar hook)
  91. // (copied from mshtml\src\other\include\othrguid.h)
  92. static const GUID CGID_DownloadObjectBindContext = { 0x3050f3df, 0x98b5, 0x11cf, 0xbb, 0x82,
  93. 0x00, 0xaa, 0x00, 0xbd, 0xce, 0x0b };
  94. static const GUID CLSID_JITWMP8 = { 0x6BF52A52, 0x394A, 0x11d3, 0xb1, 0x53, 0x00, 0xc0, 0x4f, 0x79, 0xfa, 0xa6 };
  95. #define DBG_ACCELENTRIES 2
  96. #define OPT_ACCELENTRIES 1
  97. #ifdef UNIX
  98. #include <unixstuff.h>
  99. #define EXPLORER_EXE "explorer"
  100. #define IEXPLORE_EXE "iexplorer"
  101. #define DBG_ACCELENTRIES_WITH_FILEMENU 8
  102. #define OPT_ACCELENTRIES_WITH_FILEMENU 7
  103. #else
  104. #define EXPLORER_EXE TEXT("explorer.exe")
  105. #define IEXPLORE_EXE TEXT("iexplore.exe")
  106. #define DBG_ACCELENTRIES_WITH_FILEMENU 6
  107. #define OPT_ACCELENTRIES_WITH_FILEMENU 5
  108. #endif /* UNIX */
  109. EXTERN_C const GUID IID_IDocHostObject = {0x67431840L, 0xC511, 0x11CF, 0x89, 0xA9, 0x00, 0xA0, 0xC9, 0x05, 0x41, 0x29};
  110. EXTERN_C const GUID IID_IMimeInfo = {0xF77459A0L, 0xBF9A, 0x11cf, 0xBA, 0x4E, 0x00, 0xC0, 0x4F, 0xD7, 0x08, 0x16};
  111. EXTERN_C const GUID IID_IsPicsBrowser = {0xF114C2C0L, 0x90BE, 0x11D0, 0x83, 0xB1, 0x00, 0xC0, 0x4F, 0xD7, 0x05, 0xB2};
  112. #include <shlwapi.h>
  113. #include <ratingsp.h>
  114. #include <ratings.h>
  115. #define DM_ZONECROSSING 0
  116. #define DM_SAVEASHACK 0
  117. #define DM_MIMEMAPPING 0
  118. #define DM_SELFASC TF_SHDBINDING
  119. #define DM_ACCEPTHEADER 0
  120. #define DM_DEBUGTFRAME 0
  121. #define DM_DOCHOSTUIHANDLER 0
  122. #define DM_PREMERGEDMENU 0
  123. #define DM_FOCUS 0
  124. #define DM_DOCCP 0
  125. #define DM_PICS 0
  126. #define DM_SSL 0
  127. #define KEY_BINDCONTEXTPARAM _T("BIND_CONTEXT_PARAM")
  128. // media bar entries
  129. #define WZ_RADIO_PROTOCOL L"vnd.ms.radio:"
  130. enum PlayMimeOptions {PLAYMIME_YES, PLAYMIME_NO, PLAYMIME_YESSAVE, PLAYMIME_NOSAVE};
  131. // WARNING: Never define it in shipping product.
  132. #ifdef DEBUG
  133. // #define TEST_DELAYED_SHOWMSOVIEW
  134. #endif
  135. void CShdAdviseSink_Advise(IBrowserService * pwb, IOleObject* pole);
  136. UINT MayOpenSafeOpenDialog(HWND hwndOwner,
  137. LPCTSTR pszFileClass,
  138. LPCTSTR pszURL,
  139. LPCTSTR pszCacheName,
  140. LPCTSTR pszDisplay,
  141. UINT uiCP,
  142. IUnknown * punk,
  143. IOleCommandTarget * pCmdTarget = NULL,
  144. BOOL fDisableOK = FALSE);
  145. LONG _GetSearchFormatString(DWORD dwIndex, LPTSTR psz, DWORD cbpsz);
  146. DWORD _GetErrorThreshold(DWORD dwError);
  147. BOOL IsRegisteredClient(LPCTSTR pszClient);
  148. HRESULT _GetSearchString(IServiceProvider * psp, VARIANT * pvarSearch);
  149. int EUIndexFromError(DWORD dwError);
  150. BOOL IsErrorHandled(DWORD dwError);
  151. HRESULT _GetSearchInfo(IServiceProvider * psp,
  152. LPDWORD pdwIndex,
  153. LPBOOL pfAllowSearch,
  154. LPBOOL pfContinueSearch,
  155. LPBOOL pfSentToEngine,
  156. VARIANT * pvarUrl);
  157. STDAPI _URLMONMonikerFromPidl(LPCITEMIDLIST pidl, IMoniker ** ppmk, BOOL * pfFileProtocol);
  158. LRESULT CALLBACK PolicyDlgProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam);
  159. // macros
  160. #define DO_SEARCH_ON_STATUSCODE(x) ((x == 0) || (x == HTTP_STATUS_BAD_GATEWAY) || (x == HTTP_STATUS_GATEWAY_TIMEOUT))
  161. // Suite Apps Registry keys
  162. #define NEW_MAIL_DEF_KEY TEXT("Mail")
  163. #define NEW_NEWS_DEF_KEY TEXT("News")
  164. #define NEW_CONTACTS_DEF_KEY TEXT("Contacts")
  165. #define NEW_CALL_DEF_KEY TEXT("Internet Call")
  166. #define NEW_APPOINTMENT_DEF_KEY TEXT("Appointment")
  167. #define NEW_MEETING_DEF_KEY TEXT("Meeting")
  168. #define NEW_TASK_DEF_KEY TEXT("Task")
  169. #define NEW_TASKREQUEST_DEF_KEY TEXT("Task Request")
  170. #define NEW_JOURNAL_DEF_KEY TEXT("Journal")
  171. #define NEW_NOTE_DEF_KEY TEXT("Note")
  172. #ifdef DEBUG
  173. DWORD g_dwPerf = 0;
  174. #endif
  175. // #include "..\shell32\fstreex.h" // for IDFOLDER
  176. // HACK:
  177. struct IDFOLDERA
  178. {
  179. WORD cb;
  180. BYTE bFlags;
  181. };
  182. typedef IDFOLDERA* LPIDFOLDERA;
  183. const ITEMIDLIST s_idNull = { {0} };
  184. //
  185. // Icons are globally shared among multiple threads.
  186. //
  187. HICON g_hiconSSL = NULL;
  188. HICON g_hiconFortezza = NULL;
  189. HICON g_hiconOffline = NULL;
  190. HICON g_hiconPrinter = NULL;
  191. HICON g_hiconScriptErr = NULL;
  192. HICON g_hiconPrivacyImpact = NULL;
  193. HICON g_ahiconState[IDI_STATE_LAST-IDI_STATE_FIRST+1] = { NULL };
  194. #define MAX_MIXED_STR_LEN 32
  195. // OpenUIURL is just a wrapper for OpenUI, calling CreateURLMoniker() if the
  196. // caller only has an URL.
  197. extern BOOL __cdecl _FormatMessage(LPCSTR szTemplate, LPSTR szBuf, UINT cchBuf, ...);
  198. #include "asyncrat.h"
  199. #define MAX_STATUS_SIZE 128
  200. //
  201. // Set this flag if we are going to use IHlinkBrowseContext in HLINK.DLL
  202. // #define HLINK_EXTRA
  203. //
  204. // Array of http error codes and file names.
  205. //
  206. extern ErrorUrls c_aErrorUrls[];
  207. #define DM_RECYCLE DM_TRACE
  208. #define DM_BINDAPPHACK TF_SHDAPPHACK
  209. #define DM_ADVISE TF_SHDLIFE
  210. #define DM_APPHACK DM_WARNING
  211. #define NAVMSG3(psz, x, y) TraceMsg(0, "shdv NAV::%s %x %x", psz, x, y)
  212. #define PAINTMSG(psz,x) TraceMsg(0, "shd TR-PAINT::%s %x", psz, x)
  213. #define JMPMSG(psz, psz2) TraceMsg(0, "shd TR-CDOV::%s %s", psz, psz2)
  214. #define JMPMSG2(psz, x) TraceMsg(0, "shd TR-CDOV::%s %x", psz, x)
  215. #define DOFMSG(psz) TraceMsg(0, "shd TR-DOF::%s", psz)
  216. #define DOFMSG2(psz, x) TraceMsg(0, "shd TR-DOF::%s %x", psz, x)
  217. #define URLMSG(psz) TraceMsg(TF_SHDBINDING, "shd TR-DOF::%s", psz)
  218. #define URLMSG2(psz, x) TraceMsg(TF_SHDBINDING, "shd TR-DOF::%s %x", psz, x)
  219. #define URLMSG3(psz, x, y) TraceMsg(TF_SHDBINDING, "shd TR-DOF::%s %x %x", psz, x, y)
  220. #define OIPSMSG(psz) TraceMsg(0, "shd TR-OIPS::%s", psz)
  221. #define OIPSMSG3(psz, sz, p) TraceMsg(0, "shd TR-OIPS::%s %s,%x", psz, sz,p)
  222. #define VIEWMSG(psz) TraceMsg(0, "sdv TR CDOV::%s", psz)
  223. #define VIEWMSG2(psz,xx) TraceMsg(0, "sdv TR CDOV::%s %x", psz,xx)
  224. #define OPENMSG(psz) TraceMsg(TF_SHDBINDING, "shd OPENING %s", psz)
  225. #define OPENMSG2(psz, x) TraceMsg(TF_SHDBINDING, "shd OPENING %s %x", psz, x)
  226. #define HFRMMSG(psz) TraceMsg(0, "shd HFRM::%s", psz)
  227. #define HFRMMSG2(psz, x, y) TraceMsg(0, "shd HFRM::%s %x %x", psz, x, y)
  228. #define MNKMSG(psz, psz2) TraceMsg(0, "shd MNK::%s (%s)", psz, psz2)
  229. #define CHAINMSG(psz, x) TraceMsg(0, "shd CHAIN::%s %x", psz, x)
  230. #define SHVMSG(psz, x, y) TraceMsg(0, "shd SHV::%s %x %x", psz, x, y)
  231. #define HOMEMSG(psz, psz2, x) TraceMsg(TF_SHDNAVIGATE, "shd HOME::%s %s %x", psz, psz2, x)
  232. #define SAVEMSG(psz, x) TraceMsg(0, "shd SAVE::%s %x", psz, x)
  233. #define PERFMSG(psz, x) TraceMsg(TF_SHDPERF, "PERF::%s %d msec", psz, x)
  234. static const TCHAR szRegKey_SMIEM[] = TEXT("Software\\Microsoft\\Internet Explorer\\Main");
  235. static const TCHAR szRegVal_ErrDlgPerErr[] = TEXT("Error Dlg Displayed On Every Error");
  236. static const TCHAR szRegVal_ErrDlgDetailsOpen[] = TEXT("Error Dlg Details Pane Open");
  237. ////////////////////////////////////////////////////////////
  238. // ShabbirS (980917) - BugFix# 34259
  239. // Repair menuitem in the Help Menu.
  240. typedef HRESULT (* FIXIEPROC) (BOOL, DWORD);
  241. void RepairIE()
  242. {
  243. HINSTANCE hIESetup;
  244. FIXIEPROC fpFixIE;
  245. hIESetup = LoadLibrary(L"IESetup.dll");
  246. if (hIESetup)
  247. {
  248. fpFixIE = (FIXIEPROC) GetProcAddress(hIESetup,"FixIE");
  249. if (fpFixIE)
  250. {
  251. fpFixIE(TRUE,0);
  252. }
  253. FreeLibrary(hIESetup);
  254. }
  255. }
  256. BOOL _IsDesktopItem(CDocObjectHost * pdoh)
  257. {
  258. BOOL fIsDesktopItem = FALSE;
  259. IServiceProvider * psb;
  260. ASSERT(pdoh);
  261. //Check if we are a desktop component.
  262. if (SUCCEEDED(pdoh->QueryService(SID_STopLevelBrowser, IID_IServiceProvider, (void **)&psb)))
  263. {
  264. LPTARGETFRAME2 ptgf;
  265. if (SUCCEEDED(psb->QueryService(IID_ITargetFrame2, IID_ITargetFrame2, (void **)&ptgf)))
  266. {
  267. DWORD dwOptions;
  268. if (SUCCEEDED(ptgf->GetFrameOptions(&dwOptions)))
  269. {
  270. //Is this a desktop component?
  271. if (IsFlagSet(dwOptions, FRAMEOPTIONS_DESKTOP))
  272. fIsDesktopItem = TRUE;
  273. }
  274. ptgf->Release();
  275. }
  276. psb->Release();
  277. }
  278. return fIsDesktopItem;
  279. }
  280. BOOL _IsImmediateParentDesktop(CDocObjectHost *pdoh, IServiceProvider *psp)
  281. {
  282. BOOL fImmediateParentIsDesktop = FALSE;
  283. LPTARGETFRAME2 ptgf;
  284. //First check if this is hosted on desktop.
  285. if (!_IsDesktopItem(pdoh))
  286. return FALSE; //This is not a desktop item. So, the immediate parent can't be desktop!
  287. //We know that this is a desktop item. Check if the immediate parent is desktop
  288. // or it is hosted too deep on desktop!
  289. if (psp && SUCCEEDED(psp->QueryService(IID_ITargetFrame2, IID_ITargetFrame2, (void **)&ptgf)))
  290. {
  291. IUnknown *pUnkParent;
  292. //Get it's immediate parent.
  293. if(SUCCEEDED(ptgf->GetParentFrame(&pUnkParent)))
  294. {
  295. if(pUnkParent)
  296. {
  297. //Has a parent. So, the immediate parent can't be desktop!
  298. pUnkParent->Release();
  299. fImmediateParentIsDesktop = FALSE;
  300. }
  301. else
  302. fImmediateParentIsDesktop = TRUE; //No parent. Must be a desktop comp.
  303. }
  304. ptgf->Release();
  305. }
  306. return(fImmediateParentIsDesktop);
  307. }
  308. // Gets the current display name in wide char
  309. //
  310. // If fURL is TRUE, it returns file-URL with file: prefix.
  311. //
  312. HRESULT CDocObjectHost::_GetCurrentPageW(LPOLESTR * ppszDisplayName, BOOL fURL)
  313. {
  314. HRESULT hres = E_FAIL;
  315. ASSERT(_pmkCur);
  316. *ppszDisplayName = NULL;
  317. if (_pmkCur) {
  318. IBindCtx* pbc;
  319. hres = CreateBindCtx(0, &pbc);
  320. if (SUCCEEDED(hres))
  321. {
  322. hres = _pmkCur->GetDisplayName(pbc, NULL, ppszDisplayName);
  323. //
  324. // special handling just for file: urls.
  325. //
  326. if (SUCCEEDED(hres) && _fFileProtocol)
  327. {
  328. ASSERT(*ppszDisplayName);
  329. WCHAR szText[MAX_URL_STRING];
  330. DWORD cchText = SIZECHARS(szText);
  331. if (!fURL)
  332. {
  333. hres = PathCreateFromUrlW(*ppszDisplayName, szText, &cchText, 0);
  334. }
  335. else
  336. {
  337. // we need this to be in the normalized form of the URL
  338. // for internal usage. urlmon keeps them in the funny PATHURL style
  339. hres = UrlCanonicalizeW(*ppszDisplayName, szText, &cchText, 0);
  340. }
  341. if (SUCCEEDED(hres))
  342. {
  343. UINT cchDisplayName = lstrlenW(*ppszDisplayName);
  344. if (cchText > cchDisplayName)
  345. {
  346. // need to resize
  347. CoTaskMemFree(*ppszDisplayName);
  348. *ppszDisplayName = (WCHAR *)CoTaskMemAlloc((cchText + 1) * SIZEOF(WCHAR));
  349. if (*ppszDisplayName)
  350. {
  351. // go ahead and copy it in
  352. StrCpyNW(*ppszDisplayName, szText, cchText + 1);
  353. }
  354. else
  355. hres = E_OUTOFMEMORY;
  356. }
  357. else
  358. {
  359. StrCpyNW(*ppszDisplayName, szText, cchDisplayName + 1);
  360. }
  361. }
  362. else
  363. OleFree(*ppszDisplayName);
  364. }
  365. pbc->Release();
  366. }
  367. }
  368. return hres;
  369. }
  370. //
  371. // We fire NavigateError in one location in DocObjectHost
  372. // However it is fired from (n) locations in DocHostBsc
  373. // so I have extracted the common code
  374. //
  375. void
  376. CDocObjectHost::_FireNavigateErrorHelper(IHTMLWindow2 * pHTMLWindow2,
  377. DWORD dwStatusCode,
  378. BOOL * pfCancelAutoSearch,
  379. BSTR bstrURL /* = NULL */)
  380. {
  381. ASSERT(!pHTMLWindow2 || !IsBadReadPtr(pHTMLWindow2, sizeof(IHTMLWindow2*)));
  382. ASSERT(dwStatusCode != 0);
  383. ASSERT(!IsBadWritePtr(pfCancelAutoSearch, sizeof(BOOL)));
  384. ASSERT(!bstrURL || !IsBadReadPtr(bstrURL, sizeof(BSTR)));
  385. if ( ! _pwb )
  386. {
  387. TraceMsg( TF_ERROR, "CDocObjectHost::_FireNavigateErrorHelper() - _pwb is NULL!" );
  388. return;
  389. }
  390. ITridentService2 * pTridentSvc2;
  391. HRESULT hres = _pwb->QueryInterface(IID_ITridentService2, (void**)&pTridentSvc2);
  392. if (SUCCEEDED(hres))
  393. {
  394. LPOLESTR pwzURL = NULL;
  395. BSTR bstrMkURL = NULL;
  396. BSTR bstrPidlURL = NULL;
  397. BSTR bstrFrameName = NULL;
  398. if (!bstrURL)
  399. {
  400. ASSERT(!_pmkCur || !IsBadReadPtr(_pmkCur, sizeof(_pmkCur)));
  401. ASSERT(!_pbcCur || !IsBadReadPtr(_pbcCur, sizeof(_pbcCur)));
  402. if (_pmkCur && _pbcCur)
  403. {
  404. EVAL(S_OK == _pmkCur->GetDisplayName(_pbcCur, NULL, &pwzURL));
  405. bstrMkURL = SysAllocString(pwzURL);
  406. }
  407. else if (_pidl)
  408. {
  409. TCHAR szUrl[MAX_URL_STRING];
  410. HRESULT hresGDN = IEGetDisplayName(_pidl, szUrl, SHGDN_FORPARSING);
  411. if (SUCCEEDED(hresGDN))
  412. {
  413. bstrPidlURL = SysAllocString(szUrl);
  414. }
  415. else
  416. {
  417. bstrPidlURL = SysAllocString(_T(""));
  418. }
  419. }
  420. }
  421. if (pHTMLWindow2)
  422. pHTMLWindow2->get_name(&bstrFrameName);
  423. pTridentSvc2->FireNavigateError(pHTMLWindow2,
  424. bstrURL ? bstrURL : bstrMkURL ? bstrMkURL : bstrPidlURL,
  425. bstrFrameName,
  426. dwStatusCode,
  427. pfCancelAutoSearch);
  428. pTridentSvc2->Release();
  429. OleFree(pwzURL);
  430. SysFreeString(bstrPidlURL);
  431. SysFreeString(bstrMkURL);
  432. SysFreeString(bstrFrameName);
  433. }
  434. }
  435. HRESULT CDocObjectHost::_GetCurrentPage(LPTSTR szBuf, UINT cchMax, BOOL fURL)
  436. {
  437. szBuf[0] = 0; // zero out buffer
  438. WCHAR * pszDisplayName;
  439. HRESULT hres = _GetCurrentPageW(&pszDisplayName, fURL);
  440. if (SUCCEEDED(hres))
  441. {
  442. StrCpyN(szBuf, pszDisplayName, cchMax);
  443. OleFree(pszDisplayName);
  444. }
  445. return hres;
  446. }
  447. void CDocObjectHost_GetCurrentPage(LPARAM that, LPTSTR szBuf, UINT cchMax)
  448. {
  449. CDocObjectHost* pdoh = (CDocObjectHost*)that;
  450. pdoh->_GetCurrentPage(szBuf, cchMax);
  451. }
  452. //========================================================================
  453. // CDocObjectHost members
  454. //========================================================================
  455. CDocObjectHost::CDocObjectHost(BOOL fWindowOpen /* = FALSE */) : _cRef(1), _uState(SVUIA_DEACTIVATE)
  456. {
  457. DllAddRef();
  458. TraceMsg(TF_SHDLIFE, "ctor CDocObjectHost %x", this);
  459. TraceMsg(DM_DEBUGTFRAME, "ctor CDocObjectHost %x, %x", this, &_bsc);
  460. // Initialize proxy objects (which are contained)
  461. _dof.Initialize(this);
  462. _xao.Initialize(this);
  463. #ifdef HLINK_EXTRA
  464. HRESULT hres = HlinkCreateBrowseContext(NULL, IID_IHlinkBrowseContext, (void **)&_pihlbc);
  465. TraceMsg(0, "sdv TR CDOV::constructor HlinkCreateBrowseContext returned %x", hres);
  466. #endif // HLINK_EXTRA
  467. ::_RefPicsQueries(); /* we'll free PICS async query list when last dochost is destroyed */
  468. _dwPicsKeyBase = 1;
  469. _pScriptErrList = NULL;
  470. _fScriptErrDlgOpen = FALSE;
  471. _strPriorityStatusText = NULL;
  472. _iString = -1;
  473. _uiCP = CP_ACP;
  474. _PicsProcBase._pdoh = this;
  475. VariantInit(&_varUserEnteredUrl);
  476. _fWindowOpen = fWindowOpen;
  477. ASSERT(!_fDocCanNavigate);
  478. ASSERT(!_fPrevDocHost);
  479. }
  480. CDocObjectHost::~CDocObjectHost()
  481. {
  482. ASSERT(_pole==NULL); // to catch extra release.
  483. ASSERT(_psp==NULL); // to cache extra release.
  484. ASSERT(_hwnd==NULL);
  485. ASSERT(_pmsoc==NULL);
  486. ASSERT(_pmsot==NULL);
  487. ASSERT(_pmsov==NULL);
  488. ASSERT(_pcmdMergedMenu==NULL);
  489. ASSERT(NULL == _pHTMLWindow);
  490. ASSERT(VT_EMPTY == V_VT(&_varUserEnteredUrl));
  491. if (_pScriptErrList != NULL)
  492. {
  493. _pScriptErrList->Release();
  494. }
  495. if (_strPriorityStatusText != NULL)
  496. {
  497. SysFreeString(_strPriorityStatusText);
  498. }
  499. #ifdef HLINK_EXTRA
  500. ASSERT(_phls == NULL);
  501. ATOMICRELEASE(_pihlbc);
  502. #endif // HLINK_EXTRA
  503. ::_ReleasePicsQueries();
  504. if ( _PicsProcBase._pRootDownload
  505. || _PicsProcBase._pPicsProcNext) {
  506. ASSERT(0); /* need to destroy this earlier to prevent Trident problems */
  507. _RemoveAllPicsProcessors();
  508. }
  509. if (_padvise) {
  510. _padvise->OnClose();
  511. ATOMICRELEASE(_padvise);
  512. }
  513. if (_pwszRefreshUrl)
  514. OleFree(_pwszRefreshUrl);
  515. if (_hmenuBrowser) {
  516. AssertMsg(0, TEXT("_hmenuBrowser should be NULL!"));
  517. DestroyMenu(_hmenuBrowser);
  518. }
  519. if (_hmenuFrame) {
  520. DestroyMenu(_hmenuFrame);
  521. }
  522. if (_hacc)
  523. {
  524. DestroyAcceleratorTable(_hacc);
  525. _hacc = NULL;
  526. }
  527. if (_hinstInetCpl)
  528. FreeLibrary(_hinstInetCpl);
  529. if (_ptbStd)
  530. delete [] _ptbStd;
  531. if (_pBrowsExt)
  532. {
  533. _pBrowsExt->Release();
  534. }
  535. ILFree(_pidl);
  536. _pidl = NULL;
  537. // Make it sure that View Window is released (and _psb)
  538. DestroyHostWindow(); // which will call _CloseMsoView and _UnBind
  539. _ResetOwners();
  540. TraceMsg(TF_SHDLIFE, "dtor CDocObjectHost %x", this);
  541. DllRelease();
  542. }
  543. #ifdef DEBUG
  544. /*----------------------------------------------------------
  545. Purpose: Dump the menu handles for this docobj. Optionally
  546. breaks after dumping handles.
  547. Returns:
  548. Cond: --
  549. */
  550. void
  551. CDocObjectHost::_DumpMenus(
  552. IN LPCTSTR pszMsg,
  553. IN BOOL bBreak)
  554. {
  555. if (IsFlagSet(g_dwDumpFlags, DF_DEBUGMENU))
  556. {
  557. ASSERT(pszMsg);
  558. TraceMsg(TF_ALWAYS, "DocHost: Dumping menus for %#08x %s", (LPVOID)this, pszMsg);
  559. TraceMsg(TF_ALWAYS, " _hmenuBrowser = %x, _hmenuSet = %x, _hmenuFrame = %x",
  560. _hmenuBrowser, _hmenuSet, _hmenuFrame);
  561. TraceMsg(TF_ALWAYS, " _hmenuCur = %x, _hmenuMergedHelp = %x, _hmenuObjHelp = %x",
  562. _hmenuCur, _hmenuMergedHelp, _hmenuObjHelp);
  563. _menulist.Dump(pszMsg);
  564. if (bBreak && IsFlagSet(g_dwBreakFlags, BF_ONDUMPMENU))
  565. DebugBreak();
  566. }
  567. }
  568. #endif
  569. HRESULT CDocObjectHost::QueryInterface(REFIID riid, void ** ppvObj)
  570. {
  571. static const QITAB qit[] = {
  572. QITABENTMULTI(CDocObjectHost, IOleInPlaceSite, IOleInPlaceSiteEx),
  573. QITABENTMULTI(CDocObjectHost, IOleWindow, IOleInPlaceSiteEx),
  574. QITABENT(CDocObjectHost, IOleClientSite),
  575. QITABENT(CDocObjectHost, IOleDocumentSite),
  576. QITABENT(CDocObjectHost, IOleCommandTarget),
  577. QITABENT(CDocObjectHost, IServiceProvider),
  578. QITABENT(CDocObjectHost, IViewObject),
  579. QITABENT(CDocObjectHost, IAdviseSink),
  580. QITABENT(CDocObjectHost, IDocHostObject),
  581. QITABENT(CDocObjectHost, IDocHostUIHandler),
  582. QITABENT(CDocObjectHost, IDocHostUIHandler2),
  583. QITABENT(CDocObjectHost, IDocHostShowUI),
  584. QITABENT(CDocObjectHost, IDispatch),
  585. QITABENT(CDocObjectHost, IPropertyNotifySink),
  586. QITABENT(CDocObjectHost, IOleControlSite),
  587. { 0 },
  588. };
  589. static const QITAB qit1[] = {
  590. QITABENT(CDocObjectHost, IOleInPlaceSiteEx),
  591. { 0 },
  592. };
  593. HRESULT hr = QISearch(this, qit, riid, ppvObj);
  594. if (hr == S_OK)
  595. return S_OK;
  596. if (_pWebOCInPlaceSiteEx)
  597. return QISearch(this, qit1, riid, ppvObj);
  598. return hr;
  599. }
  600. void CDocObjectHost::_ResetOwners()
  601. {
  602. _pszLocation = NULL;
  603. _uiCP = CP_ACP;
  604. _ReleasePendingObject();
  605. ATOMICRELEASE(_psv);
  606. ATOMICRELEASE(_pmsoctView);
  607. ATOMICRELEASE(_pdvs);
  608. ATOMICRELEASE(_psb);
  609. ATOMICRELEASE(_pwb);
  610. ATOMICRELEASE(_phf);
  611. ATOMICRELEASE(_pocthf);
  612. ATOMICRELEASE(_punkSFHistory);
  613. ATOMICRELEASE(_pmsoctBrowser);
  614. ATOMICRELEASE(_psp);
  615. ATOMICRELEASE(_peds);
  616. ATOMICRELEASE(_pedsHelper);
  617. ATOMICRELEASE(_pWebOCUIHandler);
  618. ATOMICRELEASE(_pWebOCUIHandler2);
  619. ATOMICRELEASE(_pWebOCShowUI);
  620. ATOMICRELEASE(_pWebOCInPlaceSiteEx);
  621. // Release cached OleInPlaceUIWindow of the browser
  622. ATOMICRELEASE(_pipu);
  623. // Tell embedded CDocHostUIHandler object to release its references on us.
  624. _dhUIHandler.SetSite(NULL);
  625. }
  626. ULONG CDocObjectHost::AddRef()
  627. {
  628. _cRef++;
  629. TraceMsg(TF_SHDREF, "CDocObjectHost(%x)::AddRef called, new _cRef=%d", this, _cRef);
  630. return _cRef;
  631. }
  632. ULONG CDocObjectHost::Release()
  633. {
  634. _cRef--;
  635. TraceMsg(TF_SHDREF, "CDocObjectHost(%x)::Release called, new _cRef=%d", this, _cRef);
  636. if (_cRef > 0)
  637. return _cRef;
  638. delete this;
  639. return 0;
  640. }
  641. // cut & paste from browseui\itbar.cpp
  642. int RemoveHiddenButtons(TBBUTTON* ptbn, int iCount)
  643. {
  644. int i;
  645. int iTotal = 0;
  646. TBBUTTON* ptbn1 = ptbn;
  647. for (i = 0; i < iCount; i++, ptbn1++) {
  648. if (!(ptbn1->fsState & TBSTATE_HIDDEN)) {
  649. if (ptbn1 != ptbn) {
  650. *ptbn = *ptbn1;
  651. }
  652. ptbn++;
  653. iTotal++;
  654. }
  655. }
  656. return iTotal;
  657. }
  658. // We use two different image lists in the TBBUTTON array. The bitmaps for browser-specific buttons
  659. // cut/copy/paste have been moved to shdocvw, and are therefore obtained from a second image list.
  660. // MAKELONG(0,1) accesses the first image from this second list. Without a call to MAKELONG there is
  661. // a 0 in the upper integer, thereby referencing the first list by default.
  662. static const TBBUTTON c_tbStd[] = {
  663. {10, DVIDM_SHOWTOOLS, TBSTATE_ENABLED, BTNS_BUTTON, {0,0}, 0, 10},
  664. {13, DVIDM_MAILNEWS, TBSTATE_ENABLED, BTNS_WHOLEDROPDOWN, {0,0}, 0, 13 },
  665. { 8, DVIDM_FONTS, TBSTATE_ENABLED, BTNS_WHOLEDROPDOWN, {0,0}, 0, 8 },
  666. { 7, DVIDM_PRINT, TBSTATE_ENABLED, BTNS_BUTTON, {0,0}, 0, 7 },
  667. { 9, DVIDM_EDITPAGE, TBSTATE_ENABLED, BTNS_BUTTON, {0,0}, 0, 9 },
  668. {15, DVIDM_DISCUSSIONS, TBSTATE_ENABLED, BTNS_BUTTON, {0,0}, 0, 15 },
  669. {MAKELONG(0,1), DVIDM_CUT, TBSTATE_ENABLED, BTNS_BUTTON, {0,0}, 0, 0 },
  670. {MAKELONG(1,1), DVIDM_COPY, TBSTATE_ENABLED, BTNS_BUTTON, {0,0}, 0, 0 },
  671. {MAKELONG(2,1), DVIDM_PASTE, TBSTATE_ENABLED, BTNS_BUTTON, {0,0}, 0, 0 },
  672. {MAKELONG(3,1), DVIDM_ENCODING, TBSTATE_ENABLED, BTNS_WHOLEDROPDOWN, {0,0}, 0, 0 },
  673. {MAKELONG(5,1), DVIDM_PRINTPREVIEW, TBSTATE_ENABLED, BTNS_BUTTON, {0,0}, 0, 0 },
  674. };
  675. // c_tbStd and c_rest need to match exactly
  676. static const BROWSER_RESTRICTIONS c_rest[] = {
  677. REST_BTN_TOOLS,
  678. REST_BTN_MAIL,
  679. REST_BTN_FONTS,
  680. REST_BTN_PRINT,
  681. REST_BTN_EDIT,
  682. REST_BTN_DISCUSSIONS,
  683. REST_BTN_CUT,
  684. REST_BTN_COPY,
  685. REST_BTN_PASTE,
  686. REST_BTN_ENCODING,
  687. REST_BTN_PRINTPREVIEW,
  688. };
  689. #ifdef DEBUG
  690. void _AssertRestrictionOrderIsCorrect()
  691. {
  692. COMPILETIME_ASSERT(ARRAYSIZE(c_tbStd) == ARRAYSIZE(c_rest));
  693. for (UINT i = 0; i < ARRAYSIZE(c_tbStd); i++)
  694. {
  695. // If any of these rip, it means that c_rest and c_tbStd have
  696. // gotten out of sync. Need to fix up c_rest to match c_tbStd.
  697. switch (c_tbStd[i].idCommand)
  698. {
  699. case DVIDM_SHOWTOOLS: ASSERT(c_rest[i] == REST_BTN_TOOLS); break;
  700. case DVIDM_MAILNEWS: ASSERT(c_rest[i] == REST_BTN_MAIL); break;
  701. case DVIDM_FONTS: ASSERT(c_rest[i] == REST_BTN_FONTS); break;
  702. case DVIDM_PRINT: ASSERT(c_rest[i] == REST_BTN_PRINT); break;
  703. case DVIDM_EDITPAGE: ASSERT(c_rest[i] == REST_BTN_EDIT); break;
  704. case DVIDM_DISCUSSIONS: ASSERT(c_rest[i] == REST_BTN_DISCUSSIONS); break;
  705. case DVIDM_CUT: ASSERT(c_rest[i] == REST_BTN_CUT); break;
  706. case DVIDM_COPY: ASSERT(c_rest[i] == REST_BTN_COPY); break;
  707. case DVIDM_PASTE: ASSERT(c_rest[i] == REST_BTN_PASTE); break;
  708. case DVIDM_ENCODING: ASSERT(c_rest[i] == REST_BTN_ENCODING); break;
  709. case DVIDM_PRINTPREVIEW: ASSERT(c_rest[i] == REST_BTN_PRINTPREVIEW); break;
  710. default: ASSERT(0); break;
  711. }
  712. }
  713. }
  714. #endif
  715. BYTE _BtnStateFromRestIfAvailable(BOOL fAvailable, DWORD dwRest)
  716. {
  717. if (fAvailable)
  718. return SHBtnStateFromRestriction(dwRest, TBSTATE_ENABLED);
  719. return TBSTATE_HIDDEN;
  720. }
  721. BOOL CDocObjectHost::_ToolsButtonAvailable()
  722. {
  723. OLECMD rgcmd = { OLECMDID_HIDETOOLBARS, 0 };
  724. if (_pmsoctBrowser)
  725. _pmsoctBrowser->QueryStatus(NULL, 1, &rgcmd, NULL);
  726. return (rgcmd.cmdf & OLECMDF_SUPPORTED);
  727. }
  728. __inline BYTE CDocObjectHost::_DefToolsButtonState(DWORD dwRest)
  729. {
  730. BOOL fAvailable = _ToolsButtonAvailable();
  731. return _BtnStateFromRestIfAvailable(fAvailable, dwRest);
  732. }
  733. static const TCHAR c_szRegKeyCoolbar[] = TEXT("Software\\Microsoft\\Internet Explorer\\Toolbar");
  734. BYTE CDocObjectHost::_DefFontsButtonState(DWORD dwRest)
  735. {
  736. BYTE fsState = TBSTATE_ENABLED;
  737. // default to whatever the IE4 reg key specifies,
  738. // or FALSE if reg key not present (clean install)
  739. if (!SHRegGetBoolUSValue(c_szRegKeyCoolbar, TEXT("ShowFonts"), FALSE, FALSE))
  740. fsState |= TBSTATE_HIDDEN;
  741. return SHBtnStateFromRestriction(dwRest, fsState);
  742. }
  743. DWORD CDocObjectHost::_DiscussionsButtonCmdf()
  744. {
  745. if (SHRegGetBoolUSValue(c_szRegKeyCoolbar,
  746. TEXT("ShowDiscussionButton"), FALSE, TRUE) &&
  747. _pmsoctBrowser) {
  748. OLECMD rgcmds[] = {
  749. { SBCMDID_DISCUSSIONBAND, 0 },
  750. };
  751. static const int buttonsInternal[] = {
  752. DVIDM_DISCUSSIONS,
  753. };
  754. _pmsoctBrowser->QueryStatus(&CGID_Explorer, ARRAYSIZE(rgcmds), rgcmds, NULL);
  755. return rgcmds[0].cmdf;
  756. }
  757. return 0;
  758. }
  759. __inline BOOL CDocObjectHost::_DiscussionsButtonAvailable()
  760. {
  761. return (_DiscussionsButtonCmdf() & OLECMDF_SUPPORTED);
  762. }
  763. __inline BYTE CDocObjectHost::_DefDiscussionsButtonState(DWORD dwRest)
  764. {
  765. BOOL fAvailable = _DiscussionsButtonAvailable();
  766. return _BtnStateFromRestIfAvailable(fAvailable, dwRest);
  767. }
  768. BOOL CDocObjectHost::_MailButtonAvailable()
  769. {
  770. OLECMD rgcmdMailFavs[] = { { SBCMDID_DOMAILMENU, 0} };
  771. if (_pmsoctBrowser)
  772. _pmsoctBrowser->QueryStatus(&CGID_Explorer, ARRAYSIZE(rgcmdMailFavs), rgcmdMailFavs, NULL);
  773. if (rgcmdMailFavs[0].cmdf & OLECMDF_ENABLED)
  774. return TRUE;
  775. return FALSE;
  776. }
  777. __inline BYTE CDocObjectHost::_DefMailButtonState(DWORD dwRest)
  778. {
  779. BOOL fAvailable = _MailButtonAvailable();
  780. return _BtnStateFromRestIfAvailable(fAvailable, dwRest);
  781. }
  782. // We default the edit button to visible if there is an html editer registered
  783. BOOL CDocObjectHost::_EditButtonAvailable()
  784. {
  785. DWORD cchVerb;
  786. return (SUCCEEDED(AssocQueryString(0, ASSOCSTR_COMMAND, TEXT(".htm"), TEXT("edit"), NULL, &cchVerb)) ||
  787. SUCCEEDED(AssocQueryString(0, ASSOCSTR_COMMAND, TEXT("htmlfile"), TEXT("edit"), NULL, &cchVerb)));
  788. }
  789. __inline BYTE CDocObjectHost::_DefEditButtonState(DWORD dwRest)
  790. {
  791. BYTE fsState;
  792. if (_EditButtonAvailable())
  793. fsState = TBSTATE_ENABLED;
  794. else
  795. fsState = TBSTATE_HIDDEN;
  796. return SHBtnStateFromRestriction(dwRest, fsState);
  797. }
  798. void CDocObjectHost::_MarkDefaultButtons(PTBBUTTON tbStd)
  799. {
  800. // We're assuming tbStd is the same size as c_tbStd
  801. #ifdef DEBUG
  802. _AssertRestrictionOrderIsCorrect();
  803. #endif
  804. DWORD dwRest[ARRAYSIZE(c_tbStd)];
  805. BOOL fCheckRestriction = SHRestricted2(REST_SPECIFYDEFAULTBUTTONS, NULL, 0);
  806. for (UINT i = 0; i < ARRAYSIZE(c_rest); i++) {
  807. if (fCheckRestriction)
  808. dwRest[i] = SHRestricted2(c_rest[i], NULL, 0);
  809. else
  810. dwRest[i] = RESTOPT_BTN_STATE_DEFAULT;
  811. }
  812. // We want the Cut, Copy, Paste buttons to default off of the toolbar
  813. // (but available in the view-toolbars-customize dialog)
  814. // We set the state of the buttons to TBSTATE_HIDDEN here, but leave them alone
  815. // in ETCMDID_GETBUTTONS so that they appear in the customize dialog.
  816. ASSERT(tbStd[6].idCommand == DVIDM_CUT);
  817. ASSERT(tbStd[7].idCommand == DVIDM_COPY);
  818. ASSERT(tbStd[8].idCommand == DVIDM_PASTE);
  819. ASSERT(tbStd[9].idCommand == DVIDM_ENCODING);
  820. ASSERT(tbStd[10].idCommand == DVIDM_PRINTPREVIEW);
  821. for (i = 6; i <= 10; i++)
  822. tbStd[i].fsState = SHBtnStateFromRestriction(dwRest[i], tbStd[i].fsState | TBSTATE_HIDDEN);
  823. ASSERT(tbStd[0].idCommand == DVIDM_SHOWTOOLS);
  824. tbStd[0].fsState = _DefToolsButtonState(dwRest[0]);
  825. ASSERT(tbStd[1].idCommand == DVIDM_MAILNEWS);
  826. tbStd[1].fsState = _DefMailButtonState(dwRest[1]);
  827. ASSERT(tbStd[2].idCommand == DVIDM_FONTS);
  828. tbStd[2].fsState = _DefFontsButtonState(dwRest[2]);
  829. ASSERT(tbStd[3].idCommand == DVIDM_PRINT);
  830. tbStd[3].fsState = SHBtnStateFromRestriction(dwRest[3], TBSTATE_ENABLED);
  831. ASSERT(tbStd[4].idCommand == DVIDM_EDITPAGE);
  832. tbStd[4].fsState = _DefEditButtonState(dwRest[4]);
  833. ASSERT(tbStd[5].idCommand == DVIDM_DISCUSSIONS);
  834. tbStd[5].fsState = _DefDiscussionsButtonState(dwRest[5]);
  835. }
  836. const GUID* CDocObjectHost::_GetButtonCommandGroup()
  837. {
  838. if (_ToolsButtonAvailable())
  839. return &CLSID_MSOButtons;
  840. else
  841. return &CLSID_InternetButtons;
  842. }
  843. void CDocObjectHost::_AddButtons(BOOL fForceReload)
  844. {
  845. if (!_pBrowsExt)
  846. return;
  847. IExplorerToolbar* pxtb;
  848. if (_psp && SUCCEEDED(_psp->QueryService(SID_SExplorerToolbar, IID_IExplorerToolbar, (void **)&pxtb)))
  849. {
  850. const GUID* pguid = _GetButtonCommandGroup();
  851. HRESULT hr = pxtb->SetCommandTarget((IOleCommandTarget*)this, pguid, 0);
  852. if (!fForceReload && hr == S_FALSE) {
  853. // Another dochost already merged the buttons into the toolbar under the
  854. // same command group, so don't bother re-merging. We just need to initialize
  855. // _iString, since we're skipping the call to _pBrowsExt->InitButtons below.
  856. VARIANT var = { VT_I4 };
  857. IUnknown_Exec(_pBrowsExt, &CLSID_PrivBrowsExtCommands, PBEC_GETSTRINGINDEX, 0, &var, NULL); // should always succeed
  858. _iString = var.lVal;
  859. } else {
  860. UINT nNumExtButtons = 0;
  861. _pBrowsExt->GetNumButtons(&nNumExtButtons);
  862. int nNumButtons = nNumExtButtons + ARRAYSIZE(c_tbStd);
  863. // GetTBArray insures that tbStd != NULL, so we don't need that check here
  864. TBBUTTON *tbStd = new TBBUTTON[nNumButtons];
  865. if (tbStd != NULL)
  866. {
  867. memcpy(tbStd, c_tbStd, SIZEOF(TBBUTTON) * ARRAYSIZE(c_tbStd));
  868. UINT iStringIndex = (UINT)-1; // result of adding the string buffer to the toolbar string list
  869. HRESULT hr = _pBrowsExt->InitButtons(pxtb, &iStringIndex, pguid);
  870. ASSERT(tbStd[6].idCommand == DVIDM_CUT);
  871. ASSERT(tbStd[7].idCommand == DVIDM_COPY);
  872. ASSERT(tbStd[8].idCommand == DVIDM_PASTE);
  873. ASSERT(tbStd[9].idCommand == DVIDM_ENCODING);
  874. ASSERT(tbStd[10].idCommand == DVIDM_PRINTPREVIEW);
  875. if (SUCCEEDED(hr) && iStringIndex != -1)
  876. {
  877. tbStd[6].iString = iStringIndex;
  878. tbStd[7].iString = iStringIndex + 1;
  879. tbStd[8].iString = iStringIndex + 2;
  880. tbStd[9].iString = iStringIndex + 3;
  881. tbStd[10].iString = iStringIndex+ 4;
  882. _iString = (int)iStringIndex;
  883. }
  884. else
  885. {
  886. tbStd[6].iString = tbStd[7].iString = tbStd[8].iString = tbStd[9].iString = tbStd[10].iString = -1;
  887. _iString = -1;
  888. }
  889. // Add custom buttons to the toolbar array. We pass in the nNumButtons
  890. // as a *sanity check*...
  891. _pBrowsExt->GetButtons(&tbStd[ARRAYSIZE(c_tbStd)], nNumExtButtons, TRUE);
  892. _MarkDefaultButtons(tbStd);
  893. nNumButtons = RemoveHiddenButtons(tbStd, nNumButtons);
  894. pxtb->AddButtons(pguid, nNumButtons, tbStd);
  895. delete [] tbStd;
  896. }
  897. }
  898. pxtb->Release();
  899. }
  900. }
  901. HRESULT CDocObjectHost::UIActivate(UINT uState, BOOL fPrevViewIsDocView)
  902. {
  903. TraceMsg(TF_SHDUIACTIVATE, "DOH::UIActivate called %d->%d (this=%x)",
  904. _uState, uState, this);
  905. HRESULT hres = S_OK;
  906. UINT uStatePrev = _uState;
  907. // We are supposed to update the menu
  908. if (uState != _uState)
  909. {
  910. // There was a state transition.
  911. //
  912. _uState = uState;
  913. // If the new state is SVUIA_DEACTIVATE
  914. //
  915. if (_uState == SVUIA_DEACTIVATE)
  916. {
  917. //
  918. // When we are deactivating (we are navigating away)
  919. // we UIDeactivate the current MsoView.
  920. //
  921. _UIDeactivateMsoView();
  922. _IPDeactivateMsoView(_pmsov);
  923. _DestroyBrowserMenu();
  924. }
  925. else if (_uState == SVUIA_INPLACEACTIVATE && uStatePrev == SVUIA_ACTIVATE_FOCUS)
  926. {
  927. // Transition from SVUIA_ACTIVATE_FOCUS->SVUIA_INPLACEACTIVATE
  928. //
  929. // If we set this DONT_UIDEACTIVATE, then we stop calling
  930. // UIActivate(FALSE) when a DocObject in a frameset looses a focus.
  931. // It will solve some problems with Office apps (Excel, PPT), which
  932. // InPlaceDeactivate when we call UIActivate(FALSE). We want to treat
  933. // it as a bug, but unfortunately DocObject spec says that's OK.
  934. //
  935. // Putting this work around, however, slightly confuses MSHTML
  936. // (both classic and Trident). Once it's UIActivated, it keep
  937. // thinking that it's UIActivated and never calls onUIActivate.
  938. // Until we figure out what's the right implementation,
  939. // we can't turn this on. (SatoNa -- 11/04/96).
  940. //
  941. _GetAppHack(); // get if we don't have it yet.
  942. if (_dwAppHack & BROWSERFLAG_DONTUIDEACTIVATE) {
  943. //
  944. // HACK: We are supposed to just call UIActivate(FALSE) when
  945. // another DocObject (in the case of a frame set) became
  946. // UIActivated. Excel/PPT, however, InplaceDeactivate instead.
  947. // To work around, SriniK suggested us to call
  948. // OnDocWindowActivate(FALSE). (SatoNa)
  949. //
  950. IOleInPlaceActiveObject* piact = _xao.GetObject(); // no AddRef
  951. TraceMsg(TF_SHDAPPHACK, "DOH::UIActivate APPHACK calling %x->OnDocWindowActivate (this=%x)",
  952. piact, this);
  953. if (piact)
  954. {
  955. piact->OnDocWindowActivate(FALSE);
  956. }
  957. }
  958. else if (!(_dwAppHack & BROWSERFLAG_DONTDEACTIVATEMSOVIEW))
  959. {
  960. // HACK: In Excel, if we deactiveate the view, it never gets focus again
  961. // fix for the bug: #20906
  962. // Also, we don't want to deactivate the view
  963. // if the document is currently navigating.
  964. //
  965. _UIDeactivateMsoView();
  966. }
  967. else
  968. {
  969. // We're transitioning from SVUIA_ACTIVATE_FOCUS->SVUIA_INPLACEACTIVATE
  970. // and BROWSERFLAG_DONTDEACTIVATEMSOVIEW is set.
  971. // call the object's IOleInPlactActiveObject::OnFrameWindowActivate(FALSE);
  972. IOleInPlaceActiveObject* piact = _xao.GetObject(); // no AddRef
  973. if (piact)
  974. {
  975. piact->OnFrameWindowActivate(FALSE);
  976. }
  977. }
  978. }
  979. else if (uStatePrev == SVUIA_DEACTIVATE)
  980. {
  981. //
  982. // If UIActivate is called either
  983. // (1) when the binding is pending; _bsc._pbc!=NULL
  984. // (2) when the async binding is done; _bsc._pole!=NULL
  985. //
  986. SHVMSG("UIActivate about to call _Bind", _bsc._pbc, NULL);
  987. if (_pole == NULL && _bsc._pbc)
  988. {
  989. ASSERT(_pmkCur);
  990. IBindCtx* pbc = _bsc._pbc;
  991. pbc->AddRef();
  992. HRESULT hresT = _BindSync(_pmkCur, _bsc._pbc, _bsc._psvPrev);
  993. pbc->Release();
  994. ASSERT(_bsc._pbc==NULL);
  995. ASSERT(_bsc._psvPrev==NULL);
  996. ASSERT(_bsc._pbscChained==NULL);
  997. }
  998. hres = _EnsureActivateMsoView();
  999. // We are being asked to UI activate and we are currently deactivated. Show
  1000. // the view now.
  1001. if (SUCCEEDED(hres) && DocCanHandleNavigation())
  1002. {
  1003. _ShowMsoView();
  1004. }
  1005. _AddButtons(FALSE);
  1006. }
  1007. else
  1008. {
  1009. // opening a new document for 1st time (to UIActive or IPActive)
  1010. goto GoSetFocus;
  1011. }
  1012. }
  1013. else
  1014. {
  1015. TraceMsg(TF_SHDUIACTIVATE, "DOH:::UIActivate -- same uState (%x)", _uState);
  1016. GoSetFocus:
  1017. if ((_uState == SVUIA_ACTIVATE_FOCUS)) {
  1018. // see if object is already UIActive.
  1019. if (_ActiveHwnd()) {
  1020. // if it is, we have an hwnd and all we need to do
  1021. // is SetFocus (for compatibility w/ weird guys...)
  1022. if ( IsChildOrSelf( _ActiveHwnd(), GetFocus() ) != S_OK )
  1023. {
  1024. TraceMsg(TF_SHDUIACTIVATE, "DOH:::UIActivate -- calling SetFocus(%x)", _ActiveHwnd());
  1025. SetFocus(_ActiveHwnd());
  1026. }
  1027. }
  1028. else {
  1029. // we're in the OC, and it's IPActive not UIActive.
  1030. // (either that or it's the very 1st time for the main view).
  1031. // NOTE: Due to CBaseBrowser code that defers SVUIA_ACTIVATE_FOCUS until
  1032. // application is active, we can have a top level docobject go
  1033. // SVUIA_INPLACEACTIVE and then on activation of the window,
  1034. // we transition to SVUIA_ACTIVATE_FOCUS, thus never UIActivating
  1035. // the docobject (cf: BUG 62138)
  1036. hres = _DoVerbHelper(FALSE);
  1037. }
  1038. }
  1039. }
  1040. if ((_uState == SVUIA_INPLACEACTIVATE) || (_uState == SVUIA_ACTIVATE_FOCUS))
  1041. _PlaceProgressBar();
  1042. return hres;
  1043. }
  1044. //*** _DoVerbHelper -- DoVerb w/ various hacks
  1045. // NOTES
  1046. // do comments in _OnSetFocus apply here?
  1047. HRESULT CDocObjectHost::_DoVerbHelper(BOOL fOC)
  1048. {
  1049. HRESULT hres = E_FAIL;
  1050. LONG iVerb = OLEIVERB_SHOW;
  1051. MSG msg;
  1052. LPMSG pmsg = NULL;
  1053. if (_pole)
  1054. {
  1055. if (_uState == SVUIA_INPLACEACTIVATE)
  1056. {
  1057. iVerb = OLEIVERB_INPLACEACTIVATE;
  1058. }
  1059. else if ((_uState == SVUIA_ACTIVATE_FOCUS))
  1060. {
  1061. iVerb = OLEIVERB_UIACTIVATE;
  1062. }
  1063. else
  1064. {
  1065. TraceMsg(TF_ERROR, "DOC::_DoVerbHelper untested (and probably the wrong iVerb mapping)");
  1066. }
  1067. if (_pedsHelper)
  1068. {
  1069. if (SUCCEEDED(_pedsHelper->GetDoVerbMSG(&msg)))
  1070. {
  1071. pmsg = &msg;
  1072. }
  1073. }
  1074. hres = _pole->DoVerb(iVerb, pmsg, this, (UINT)-1, _hwnd, &_rcView);
  1075. if (hres == OLEOBJ_E_INVALIDVERB && iVerb == OLEIVERB_INPLACEACTIVATE)
  1076. {
  1077. hres = _pole->DoVerb(OLEIVERB_SHOW, pmsg, this, (UINT)-1, _hwnd, &_rcView);
  1078. }
  1079. if (FAILED(hres))
  1080. {
  1081. TraceMsg(DM_ERROR, "DOC::_DoVerbHelper _pole->DoVerb ##FAILED## %x", hres);
  1082. }
  1083. }
  1084. return hres;
  1085. }
  1086. void CDocObjectHost::_IPDeactivateMsoView(IOleDocumentView* pmsov)
  1087. {
  1088. IInitViewLinkedWebOC* pInitViewLinkedWebOC;
  1089. BOOL fIsViewLinked = FALSE;
  1090. TraceMsg(TF_SHDUIACTIVATE, "DOH::_IPDeactivateMsoView called (this==%x)", this);
  1091. if (pmsov)
  1092. {
  1093. // Because of NativeFrames, in the viewlinked WebOC case, the ReleaseShellView does not
  1094. // Deactivate the DocumentView. The sequence of these events is critical to Application
  1095. // Compatibility. So we force the show before the InPlaceDeactivate if we have a viewlinked WebOC.
  1096. ASSERT(_pwb);
  1097. HRESULT hres = E_FAIL;
  1098. if ( _pwb )
  1099. {
  1100. hres = _pwb->QueryInterface(IID_IInitViewLinkedWebOC, (void**)&pInitViewLinkedWebOC);
  1101. }
  1102. if (SUCCEEDED(hres))
  1103. {
  1104. hres = pInitViewLinkedWebOC->IsViewLinkedWebOC(&fIsViewLinked);
  1105. if (SUCCEEDED(hres) && fIsViewLinked)
  1106. {
  1107. pmsov->Show(FALSE);
  1108. }
  1109. pInitViewLinkedWebOC->Release();
  1110. }
  1111. IOleInPlaceObject* pipo = NULL;
  1112. HRESULT hresT = _pole->QueryInterface(IID_IOleInPlaceObject, (void **)&pipo);
  1113. if (SUCCEEDED(hresT))
  1114. {
  1115. pipo->InPlaceDeactivate();
  1116. pipo->Release();
  1117. }
  1118. if (!fIsViewLinked)
  1119. pmsov->Show(FALSE);
  1120. }
  1121. }
  1122. void CDocObjectHost::_UIDeactivateMsoView(void)
  1123. {
  1124. TraceMsg(TF_SHDUIACTIVATE, "DOH::_UIDeactivateMsoView called (this==%x)", this);
  1125. if (_pmsov)
  1126. {
  1127. _pmsov->UIActivate(FALSE);
  1128. }
  1129. }
  1130. //
  1131. // Hide the office toolbar
  1132. //
  1133. void CDocObjectHost::_HideOfficeToolbars(void)
  1134. {
  1135. if (_pmsot) {
  1136. OLECMD rgcmd = { OLECMDID_HIDETOOLBARS, 0 };
  1137. _pmsot->QueryStatus(NULL, 1, &rgcmd, NULL);
  1138. // LATCHED means hidden
  1139. rgcmd.cmdf &= (OLECMDF_SUPPORTED | OLECMDF_LATCHED);
  1140. // If it's supported and visible (not LATCHED), toggle it.
  1141. if (rgcmd.cmdf == OLECMDF_SUPPORTED) {
  1142. _pmsot->Exec(NULL, OLECMDID_HIDETOOLBARS, OLECMDEXECOPT_DONTPROMPTUSER, NULL, NULL);
  1143. }
  1144. }
  1145. }
  1146. void CDocObjectHost::_ShowMsoView(void)
  1147. {
  1148. HRESULT hres;
  1149. //
  1150. // HACK: Word97 UIDeactivate when we call SetInPlaceSite even with the
  1151. // same in-place site.
  1152. //
  1153. IOleInPlaceSite* psite;
  1154. hres = _pmsov->GetInPlaceSite(&psite);
  1155. if (SUCCEEDED(hres) && psite) {
  1156. if (psite!=this) {
  1157. _pmsov->SetInPlaceSite(this);
  1158. } else {
  1159. TraceMsg(TF_SHDAPPHACK, "DOH::_ShowMsoView not calling SetInPlaceSite because it's already set");
  1160. }
  1161. psite->Release();
  1162. } else {
  1163. _pmsov->SetInPlaceSite(this);
  1164. }
  1165. GetClientRect(_hwnd, &_rcView);
  1166. if ((_uState != SVUIA_INPLACEACTIVATE)
  1167. || !(_dwAppHack & BROWSERFLAG_MSHTML) // or if it's not Trident (office apps expect this call)
  1168. )
  1169. {
  1170. // Trident is sending progress changed messages here -- and causing Compuserve a problem.
  1171. // Flag the fact that we're UIActivating them, and suppress forwarding ProgressChanged
  1172. // messages to our container when this flag is true. (IE v4.1 bug 54787)
  1173. //
  1174. _fUIActivatingView = TRUE;
  1175. _pmsov->UIActivate(TRUE);
  1176. _fUIActivatingView = FALSE;
  1177. }
  1178. //
  1179. // HACK:
  1180. //
  1181. // We call _HideOfficeToolbars when our OnUIActivate is called.
  1182. // SriniK suggested us to do it in order to avoid flashing.
  1183. // It works well with Excel (3404), but does not work with Word.
  1184. // Word does not hide its toolbars correctly. To work around that
  1185. // bug, we call _HideofficeToolbars here again.
  1186. //
  1187. _HideOfficeToolbars();
  1188. hres = _pmsov->SetRect(&_rcView);
  1189. if (FAILED(hres)) {
  1190. TraceMsg(DM_ERROR, "DOC::_ShowMsoView _pmsov->SetRect ##FAILED## %x", hres);
  1191. }
  1192. if (FAILED(hres) && _uState == SVUIA_INPLACEACTIVATE) {
  1193. TraceMsg(TF_SHDAPPHACK, "APPHACK# DOH::_ShowMsoView calling UIActivate");
  1194. // HACKHACK: for word. they refuse to show if they aren't UIActivated.
  1195. // if the setrect fails, and we didn't do a UIActivate, do it now.
  1196. _fDontInplaceActivate = TRUE;
  1197. TraceMsg(TF_SHDAPPHACK, "HACK: CDOH::_ShowMsoView calling UIActive(TRUE) to work around Word bug");
  1198. _pmsov->UIActivate(TRUE);
  1199. _pmsov->SetRect(&_rcView);
  1200. }
  1201. // This is the other case where Trident sends Progress changed messages.
  1202. //
  1203. _fUIActivatingView = TRUE;
  1204. hres = _pmsov->Show(TRUE);
  1205. _fUIActivatingView = FALSE;
  1206. if (FAILED(hres)) {
  1207. TraceMsg(DM_ERROR, "DOH::_ShowMsoView _pmsov->Show ##FAILED## %x", hres);
  1208. }
  1209. _fDrawBackground = FALSE; /* now that we've shown the object, no need to paint our own background */
  1210. }
  1211. HRESULT CDocObjectHost::_ActivateMsoView()
  1212. {
  1213. _EnableModeless(FALSE);
  1214. #ifdef DEBUG
  1215. PERFMSG(TEXT("_ActivateMsoView"), GetCurrentTime() - g_dwPerf);
  1216. g_dwPerf = GetCurrentTime();
  1217. #endif
  1218. HRESULT hres = NOERROR;
  1219. if (!DocCanHandleNavigation() || _fWindowOpen)
  1220. {
  1221. if (!_phls)
  1222. {
  1223. _pole->QueryInterface(IID_IHlinkSource, (void **)&_phls);
  1224. }
  1225. if (_phls && !_fIsHistoricalObject)
  1226. {
  1227. //
  1228. // Special test case for IHlinkFrame marshaling.
  1229. //
  1230. hres = _phls->Navigate(0, _pszLocation);
  1231. //
  1232. // If this is one of our internal error pages, we can ignore the
  1233. // failure on the bogus location. In this case pwszLocation will
  1234. // be the original url that failed preceeded with a '#'.
  1235. //
  1236. LPOLESTR pwszUrl;
  1237. if (FAILED(hres) && SUCCEEDED(_GetCurrentPageW(&pwszUrl, TRUE)))
  1238. {
  1239. // if it begins with res: it may be our erro page
  1240. if (pwszUrl[0] == L'r' && pwszUrl[1] == L'e' && IsErrorUrl(pwszUrl))
  1241. {
  1242. // It's our internal error page, so ignore the error
  1243. hres = S_OK;
  1244. }
  1245. OleFree(pwszUrl);
  1246. }
  1247. #ifdef DEBUG
  1248. if (!_fWindowOpen && FAILED(hres))
  1249. {
  1250. TraceMsg(DM_ERROR, "DOC::_ActivateMsoView _phls->Navigate(%s) ##FAILED## %x",
  1251. _pszLocation ? _pszLocation : TEXT(""), hres);
  1252. }
  1253. #endif
  1254. }
  1255. else
  1256. {
  1257. // todo: use _DoVerbHelper? (but careful! ACT_FOCUS different)
  1258. LONG iVerb = OLEIVERB_SHOW;
  1259. MSG msg;
  1260. LPMSG pmsg = NULL;
  1261. if (_uState == SVUIA_INPLACEACTIVATE) {
  1262. iVerb = OLEIVERB_INPLACEACTIVATE;
  1263. }
  1264. if (_pedsHelper)
  1265. {
  1266. if (SUCCEEDED(_pedsHelper->GetDoVerbMSG(&msg)))
  1267. {
  1268. pmsg = &msg;
  1269. }
  1270. }
  1271. hres = _pole->DoVerb(iVerb, pmsg, this, (UINT)-1, _hwnd, &_rcView);
  1272. if (hres == OLEOBJ_E_INVALIDVERB && iVerb == OLEIVERB_INPLACEACTIVATE)
  1273. hres = _pole->DoVerb(OLEIVERB_SHOW, pmsg, this, (UINT)-1, _hwnd, &_rcView);
  1274. if (FAILED(hres)) {
  1275. TraceMsg(DM_ERROR, "DOC::_ActivateMsoView _pole->DoVerb ##FAILED## %x", hres);
  1276. }
  1277. }
  1278. }
  1279. _fPrevDocHost = TRUE;
  1280. // the doc is activated
  1281. if (SUCCEEDED(hres))
  1282. {
  1283. _ReleasePendingObject();
  1284. if (_fHaveParentSite)
  1285. {
  1286. _HideOfficeToolbars();
  1287. }
  1288. }
  1289. _EnableModeless(TRUE);
  1290. return hres;
  1291. }
  1292. void CDocObjectHost::OnInitialUpdate()
  1293. {
  1294. _fWindowOpen = FALSE;
  1295. ResetRefreshUrl();
  1296. }
  1297. void CDocObjectHost::ResetRefreshUrl()
  1298. {
  1299. if (_pwszRefreshUrl)
  1300. {
  1301. OleFree(_pwszRefreshUrl);
  1302. _pwszRefreshUrl = NULL;
  1303. }
  1304. }
  1305. //+---------------------------------------------------------------------------
  1306. //
  1307. // Member : CDocObjectHost::_NavigateDocument
  1308. //
  1309. // Synopsis : Navigates the document to the given URL
  1310. //
  1311. //+---------------------------------------------------------------------------
  1312. HRESULT
  1313. CDocObjectHost::_NavigateDocument(BSTR bstrUrl, BSTR bstrLocation)
  1314. {
  1315. HRESULT hres = E_FAIL;
  1316. DWORD dwFlags = 0;
  1317. IHTMLPrivateWindow * pPrivWindow = NULL;
  1318. ASSERT(_fDocCanNavigate && (_fPrevDocHost || _uState == SVUIA_DEACTIVATE));
  1319. ASSERT(_pHTMLWindow);
  1320. // Waiting for the real navigate call so we don't get duplicate events
  1321. if (_pwb)
  1322. {
  1323. _pwb->SetNavigateState(BNS_NORMAL);
  1324. }
  1325. if (_pHTMLWindow) // Stress fix
  1326. {
  1327. hres = _pHTMLWindow->QueryInterface(IID_IHTMLPrivateWindow, (void**)&pPrivWindow);
  1328. if (S_OK == hres)
  1329. {
  1330. CComBSTR cbstrShortCut;
  1331. IBindStatusCallback * pBindStatusCallback;
  1332. LPTSTR pszHeaders = NULL;
  1333. LPBYTE pPostData = NULL;
  1334. DWORD cbPostData = 0;
  1335. STGMEDIUM stgPostData;
  1336. BOOL fHavePostStg = FALSE;
  1337. BSTR bstrHeaders = NULL;
  1338. VARIANT vaHeaders = {0};
  1339. SAFEARRAY * psaPostData = NULL;
  1340. VARIANT vaPostData = {0};
  1341. if (SUCCEEDED(IUnknown_QueryService(_phf, SID_SHlinkFrame, IID_PPV_ARG(IBindStatusCallback, &pBindStatusCallback))))
  1342. {
  1343. GetHeadersAndPostData(pBindStatusCallback, &pszHeaders, &stgPostData, &cbPostData, NULL);
  1344. pBindStatusCallback->Release();
  1345. fHavePostStg = TRUE;
  1346. if (stgPostData.tymed == TYMED_HGLOBAL)
  1347. {
  1348. pPostData = (LPBYTE) stgPostData.hGlobal;
  1349. if (pPostData && cbPostData)
  1350. {
  1351. // make a SAFEARRAY for post data
  1352. psaPostData = MakeSafeArrayFromData(pPostData, cbPostData);
  1353. // put the post data SAFEARRAY into a variant so we can pass through automation
  1354. if (psaPostData)
  1355. {
  1356. V_VT(&vaPostData) = VT_ARRAY | VT_UI1;
  1357. V_ARRAY(&vaPostData) = psaPostData;
  1358. }
  1359. }
  1360. }
  1361. if (pszHeaders && pszHeaders[0])
  1362. {
  1363. bstrHeaders = SysAllocStringT(pszHeaders);
  1364. V_VT(&vaHeaders) = VT_BSTR;
  1365. V_BSTR(&vaHeaders) = bstrHeaders;
  1366. }
  1367. }
  1368. _GetShortCutPath(&cbstrShortCut);
  1369. _GetDocNavFlags(&dwFlags);
  1370. // Do the navigate
  1371. //
  1372. hres = pPrivWindow->SuperNavigate(bstrUrl,
  1373. bstrLocation,
  1374. cbstrShortCut,
  1375. NULL,
  1376. &vaPostData,
  1377. &vaHeaders,
  1378. dwFlags);
  1379. pPrivWindow->Release();
  1380. if (fHavePostStg)
  1381. {
  1382. ReleaseStgMedium(&stgPostData);
  1383. }
  1384. if (bstrHeaders)
  1385. {
  1386. SysFreeString(bstrHeaders);
  1387. }
  1388. if (V_ARRAY(&vaPostData))
  1389. {
  1390. ASSERT(V_VT(&vaPostData) == (VT_ARRAY | VT_UI1));
  1391. VariantClearLazy(&vaPostData);
  1392. }
  1393. _fRefresh = FALSE; // clear the refresh flag.
  1394. }
  1395. }
  1396. return hres;
  1397. }
  1398. //+---------------------------------------------------------------------------
  1399. //
  1400. // Member : CDocObjectHost::_GetShortCutPath
  1401. //
  1402. // Synopsis : Returns the shortcut path.
  1403. //
  1404. //+---------------------------------------------------------------------------
  1405. void
  1406. CDocObjectHost::_GetShortCutPath(BSTR * pbstrShortCutPath)
  1407. {
  1408. HRESULT hres;
  1409. VARIANT varShortCutPath = {0};
  1410. IOleCommandTarget * pcmdt;
  1411. ASSERT(pbstrShortCutPath);
  1412. *pbstrShortCutPath = NULL;
  1413. hres = QueryService(SID_SHlinkFrame, IID_IOleCommandTarget, (void **)&pcmdt);
  1414. if (S_OK == hres)
  1415. {
  1416. hres = pcmdt->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. else if (_pocthf)
  1422. {
  1423. VariantClear(&varShortCutPath);
  1424. // if we couldn't find it on that service, try the cached HLink interface
  1425. // this is necessary for ND & Mars which provide a different implementation for the HLink interface
  1426. hres = _pocthf->Exec(&CGID_Explorer, SBCMDID_GETSHORTCUTPATH, 0, NULL, &varShortCutPath);
  1427. if (S_OK == hres && VT_BSTR == V_VT(&varShortCutPath) && V_BSTR(&varShortCutPath))
  1428. {
  1429. *pbstrShortCutPath = SysAllocString(V_BSTR(&varShortCutPath));
  1430. }
  1431. }
  1432. pcmdt->Release();
  1433. }
  1434. VariantClear(&varShortCutPath);
  1435. }
  1436. //+---------------------------------------------------------------------------
  1437. //
  1438. // Member : CDocObjectHost::_GetDocNavFlags
  1439. //
  1440. // Synopsis : Returns the flags for navigation.
  1441. //
  1442. //+---------------------------------------------------------------------------
  1443. void
  1444. CDocObjectHost::_GetDocNavFlags(DWORD * pdwDocNavFlags)
  1445. {
  1446. // Find out if we are in the middle of an autosearch.
  1447. // If we are, set the necessary document flags.
  1448. //
  1449. HRESULT hr;
  1450. DWORD dwSuffixIdx = -1;
  1451. BOOL fAllowSearch = FALSE;
  1452. BOOL fContinueSearch = FALSE;
  1453. DWORD dwNavFlags = 0;
  1454. ASSERT(pdwDocNavFlags);
  1455. hr = _GetSearchInfo(_psp, &dwSuffixIdx, &fAllowSearch,
  1456. &fContinueSearch, NULL, NULL);
  1457. if (SUCCEEDED(hr) && dwSuffixIdx > 1 && fContinueSearch)
  1458. {
  1459. // We aren't really in an autosearch, but are in
  1460. // a redirection from an autosearch (i.e., there is
  1461. // a long standing bug where the MSN autosearch page
  1462. // is placed in the travel log. When you press back,
  1463. // the search is restarted. However, if the search
  1464. // info is not reset here, the suffix index is incorrect.
  1465. //
  1466. if (!fAllowSearch)
  1467. {
  1468. _bsc._SetSearchInfo(this, 0, fAllowSearch, fContinueSearch, FALSE);
  1469. }
  1470. }
  1471. // Check to see if the navigation should be suppressed from the history
  1472. //
  1473. if ( _pwb && (S_OK == _pwb->GetFlags(&dwNavFlags))
  1474. && (dwNavFlags & BSF_NAVNOHISTORY))
  1475. {
  1476. *pdwDocNavFlags |= DOCNAVFLAG_DONTUPDATETLOG;
  1477. }
  1478. if ( _fRefresh )
  1479. {
  1480. *pdwDocNavFlags |= DOCNAVFLAG_REFRESH;
  1481. }
  1482. }
  1483. HRESULT CDocObjectHost::_EnsureActivateMsoView()
  1484. {
  1485. HRESULT hres = E_FAIL;
  1486. // if we've got an ole object and
  1487. // either we don't have a view, or we don't have an active view..
  1488. // do the activation
  1489. if (_pole)
  1490. {
  1491. if (!_pmsov || !_ActiveObject()) {
  1492. hres = _ActivateMsoView();
  1493. // Note that we should not UIActivate it here. We should wait
  1494. // until the DocObject calls our ActivateMe
  1495. // _ShowMsoView();
  1496. }
  1497. }
  1498. return hres;
  1499. }
  1500. //
  1501. // This member closes the MsoView window and releases interface
  1502. // pointers. This is essentially the reverse of _CreateMsoView.
  1503. //
  1504. void CDocObjectHost::_CloseMsoView(void)
  1505. {
  1506. ATOMICRELEASE(_pmsot);
  1507. if (_pmsov)
  1508. {
  1509. VIEWMSG(TEXT("_CloseMsoView calling pmsov->UIActivate(FALSE)"));
  1510. IOleDocumentView* pmsov = _pmsov;
  1511. _pmsov = NULL;
  1512. _fDontInplaceActivate = FALSE;
  1513. #ifdef DONT_UIDEACTIVATE
  1514. if (_uState != SVUIA_DEACTIVATE)
  1515. pmsov->UIActivate(FALSE);
  1516. #else // DONT_UIDEACTIVATE
  1517. if (_uState == SVUIA_ACTIVATE_FOCUS)
  1518. pmsov->UIActivate(FALSE);
  1519. #endif // DONT_UIDEACTIVATE
  1520. _IPDeactivateMsoView(pmsov);
  1521. pmsov->CloseView(0);
  1522. pmsov->SetInPlaceSite(NULL);
  1523. pmsov->Release();
  1524. VIEWMSG(TEXT("_CloseMsoView called pmsov->Release()"));
  1525. }
  1526. ATOMICRELEASE(_pmsoc);
  1527. }
  1528. void CDocObjectHost::_OnPaint(HDC hdc)
  1529. {
  1530. if (_pmsov && !_ActiveObject())
  1531. {
  1532. HRESULT hres;
  1533. RECT rcClient;
  1534. GetClientRect(_hwnd, &rcClient);
  1535. hres = OleDraw(_pmsov, DVASPECT_CONTENT, hdc, &rcClient);
  1536. TraceMsg(0, "shd TR ::_OnPaint OleDraw returns %x", hres);
  1537. }
  1538. }
  1539. HRESULT _GetDefaultLocation(LPWSTR pszPath, DWORD cchPathSizeIn, UINT id)
  1540. {
  1541. WCHAR szPath[MAX_URL_STRING];
  1542. DWORD cbSize = SIZEOF(szPath);
  1543. DWORD cchPathSize = cchPathSizeIn;
  1544. HRESULT hres = E_FAIL;
  1545. HKEY hkey;
  1546. // Share this code!!!
  1547. // This is Internet Explorer Specific
  1548. HKEY hkeyroot = id == IDP_CHANNELGUIDE ? HKEY_CURRENT_USER : HKEY_LOCAL_MACHINE;
  1549. if (RegOpenKeyW(hkeyroot,
  1550. L"Software\\Microsoft\\Internet Explorer\\Main",
  1551. &hkey)==ERROR_SUCCESS)
  1552. {
  1553. DWORD dwType;
  1554. LPCWSTR pszName;
  1555. switch(id) {
  1556. default:
  1557. ASSERT(0);
  1558. case DVIDM_GOHOME:
  1559. pszName = L"Default_Page_URL";
  1560. break;
  1561. case DVIDM_GOSEARCH:
  1562. pszName = L"Default_Search_URL";
  1563. break;
  1564. case IDP_UPDATE:
  1565. pszName = L"Default_Update_URL";
  1566. break;
  1567. case IDP_CHANNELGUIDE:
  1568. pszName = L"ChannelsURL";
  1569. break;
  1570. }
  1571. if (RegQueryValueExW(hkey, pszName,
  1572. 0, &dwType, (LPBYTE)szPath, &cbSize)==ERROR_SUCCESS)
  1573. {
  1574. // When reading a URL from registry, treat it like it was typed
  1575. // in on the address bar.
  1576. hres = S_OK;
  1577. if(!ParseURLFromOutsideSourceW(szPath, pszPath, &cchPathSize, NULL))
  1578. StrCpyNW(pszPath, szPath, cchPathSizeIn);
  1579. if(IsFileUrlW(pszPath))
  1580. {
  1581. cchPathSize = cchPathSizeIn;
  1582. hres = PathCreateFromUrlW(pszPath, pszPath, &cchPathSize, 0);
  1583. }
  1584. }
  1585. RegCloseKey(hkey);
  1586. }
  1587. HOMEMSG("_GetStdLocation returning",
  1588. (SUCCEEDED(hres) ? pszPath : TEXT("Error")), hres);
  1589. return hres;
  1590. }
  1591. HRESULT _GetStdLocation(LPTSTR pszPath, DWORD cchPathSize, UINT id)
  1592. {
  1593. TCHAR szPathTemp[MAX_URL_STRING];
  1594. DWORD cchTempSize = ARRAYSIZE(szPathTemp);
  1595. HRESULT hres = E_FAIL;
  1596. LPCWSTR pszName = NULL;
  1597. ASSERT(cchPathSize >= cchTempSize); // If we hit this, we will truncate the URL in some cases.
  1598. ASSERT(pszPath && (cchPathSize > 0)); // Not Optional
  1599. pszPath[0] = TEXT('\0');
  1600. // Share this code!!!
  1601. // This is Internet Explorer Specific
  1602. switch(id) {
  1603. default:
  1604. ASSERT(0);
  1605. case DVIDM_GOHOME:
  1606. pszName = L"Start Page";
  1607. break;
  1608. case DVIDM_GOFIRSTHOME:
  1609. case DVIDM_GOFIRSTHOMERO:
  1610. pszName = L"First Home Page";
  1611. break;
  1612. case DVIDM_GOSEARCH:
  1613. pszName = L"Search Page";
  1614. break;
  1615. case DVIDM_SEARCHBAR:
  1616. pszName = L"Search Bar";
  1617. break;
  1618. case DVIDM_GOLOCALPAGE:
  1619. pszName = L"Local Page";
  1620. break;
  1621. }
  1622. hres = URLSubRegQuery(szRegKey_SMIEM, pszName, TRUE,
  1623. szPathTemp, cchTempSize, URLSUB_ALL);
  1624. if (FAILED(hres) &&
  1625. ((DVIDM_GOFIRSTHOME == id) || (DVIDM_GOFIRSTHOMERO == id)))
  1626. {
  1627. // The First Home key doesn't exist so use the home key.
  1628. pszName = TEXT("Start Page");
  1629. hres = URLSubRegQuery(szRegKey_SMIEM, pszName, TRUE,
  1630. szPathTemp, cchTempSize, URLSUB_ALL);
  1631. id = DVIDM_GOHOME;
  1632. }
  1633. if (SUCCEEDED(hres))
  1634. {
  1635. // When reading a URL from registry, treat it like it was typed
  1636. // in on the address bar.
  1637. // Recursion block. If requesting the home page, and the home page is "about:home", substitute
  1638. // "about:blank" (otherwise we'll recurse to death)
  1639. if (DVIDM_GOHOME == id && !StrCmpI(szPathTemp, TEXT("about:home")) )
  1640. {
  1641. StrCpyN(szPathTemp, TEXT("about:blank"), MAX_URL_STRING);
  1642. }
  1643. if(ParseURLFromOutsideSourceW(szPathTemp, pszPath, &cchPathSize, NULL))
  1644. {
  1645. if(IsFileUrlW(pszPath))
  1646. hres = PathCreateFromUrlW(pszPath, pszPath, &cchPathSize, 0);
  1647. }
  1648. }
  1649. if (DVIDM_GOFIRSTHOME == id) // Delete that FIRSTHOME key
  1650. {
  1651. HUSKEY hUSKey;
  1652. if (ERROR_SUCCESS == SHRegOpenUSKey(szRegKey_SMIEM, KEY_WRITE, NULL, &hUSKey, FALSE))
  1653. {
  1654. SHRegDeleteUSValue(hUSKey, TEXT("First Home Page"), SHREGDEL_DEFAULT);
  1655. SHRegCloseUSKey(hUSKey);
  1656. }
  1657. hres = S_OK;
  1658. }
  1659. HOMEMSG("_GetStdLocation returning",
  1660. (SUCCEEDED(hres) ? pszPath : TEXT("Error")), hres);
  1661. return hres;
  1662. }
  1663. HRESULT WINAPI _GetDefaultLocation(UINT idp, LPWSTR pszPath, UINT cchMax)
  1664. {
  1665. switch (idp)
  1666. {
  1667. case IDP_UPDATE:
  1668. case IDP_CHANNELGUIDE:
  1669. URLSubLoadString(NULL, IDS_DEF_UPDATE+(idp-IDP_UPDATE), pszPath, cchMax, URLSUB_ALL);
  1670. break;
  1671. default:
  1672. _GetDefaultLocation(pszPath, cchMax, (idp == IDP_SEARCH) ? DVIDM_GOSEARCH : DVIDM_GOHOME);
  1673. break;
  1674. }
  1675. return S_OK;
  1676. }
  1677. HRESULT WINAPI SHDGetPageLocation(HWND hwndOwner, UINT idp, LPWSTR pszPath, UINT cchMax, LPITEMIDLIST *ppidlOut)
  1678. {
  1679. TCHAR szBuf[MAX_URL_STRING];
  1680. if (pszPath==NULL) {
  1681. pszPath = szBuf;
  1682. cchMax = ARRAYSIZE(szBuf);
  1683. }
  1684. *pszPath = L'\0';
  1685. *ppidlOut = NULL;
  1686. HRESULT hres = S_OK;
  1687. switch (idp) {
  1688. case IDP_UPDATE:
  1689. case IDP_CHANNELGUIDE:
  1690. ASSERT(IDP_CHANNELGUIDE-IDP_UPDATE == IDS_DEF_CHANNELGUIDE-IDS_DEF_UPDATE);
  1691. if (FAILED(hres = _GetDefaultLocation(pszPath, cchMax, idp)))
  1692. {
  1693. hres = _GetDefaultLocation(idp, pszPath, cchMax);
  1694. }
  1695. break;
  1696. default:
  1697. ASSERT(idp==IDP_START || idp==IDP_SEARCH);
  1698. hres = _GetStdLocation(pszPath, cchMax,
  1699. (idp == IDP_SEARCH) ? DVIDM_GOSEARCH : DVIDM_GOHOME);
  1700. if (FAILED(hres))
  1701. {
  1702. hres = _GetDefaultLocation(idp, pszPath, cchMax);
  1703. }
  1704. break;
  1705. }
  1706. if (SUCCEEDED(hres))
  1707. {
  1708. hres = IECreateFromPath(pszPath, ppidlOut);
  1709. if (FAILED(hres))
  1710. {
  1711. // IECreateFromPath() above could have failed if the default location
  1712. // was invalid. (Like file://server_no_exist/
  1713. _GetDefaultLocation(idp, pszPath, cchMax);
  1714. hres = IECreateFromPath(pszPath, ppidlOut);
  1715. }
  1716. HOMEMSG("SHDGetPageLocation SHILCreateFromPage returned", pszPath, hres);
  1717. }
  1718. return hres;
  1719. }
  1720. void CDocObjectHost::_ChainBSC()
  1721. {
  1722. if (!_bsc._pbscChained && _phf)
  1723. {
  1724. // Get "chaigned" bind status, if any
  1725. IServiceProvider * psp = NULL;
  1726. HRESULT hres = _phf->QueryInterface(IID_IServiceProvider, (void **)&psp);
  1727. CHAINMSG("_StartAsyncBinding hlf->QI returns", hres);
  1728. if (SUCCEEDED(hres))
  1729. {
  1730. ASSERT(NULL == _bsc._pbscChained);
  1731. hres = psp->QueryService(SID_SHlinkFrame, IID_IBindStatusCallback, (void **)&_bsc._pbscChained);
  1732. CHAINMSG("_StartAsyncBinding psp(hlf)->QS returns", hres);
  1733. psp->Release();
  1734. if (SUCCEEDED(hres))
  1735. {
  1736. ASSERT(NULL==_bsc._pnegotiateChained);
  1737. _bsc._pbscChained->QueryInterface(IID_IHttpNegotiate, (void **)&_bsc._pnegotiateChained);
  1738. }
  1739. }
  1740. }
  1741. }
  1742. //
  1743. // WARNING: Following two global variables are shared among multiple-threads
  1744. // in a thread. Therefore, all right-access must be serialized and all read
  1745. // access should be blocked when right is going on.
  1746. //
  1747. // Right now, we just initialize them once (based on the registry setting)
  1748. // and never update. It allows us to simplify the code quite a bit. If we
  1749. // need to update, then _RegisterMediaTypeClass should be changed significantlly
  1750. // so that we can safely handle multiple access to those hdsa's. (SatoNa)
  1751. //
  1752. HDSA g_hdsaCls = NULL;
  1753. HDSA g_hdsaStr = NULL;
  1754. BOOL CDocObjectHost::_BuildClassMapping(void)
  1755. {
  1756. if (g_hdsaCls)
  1757. {
  1758. return DSA_GetItemCount(g_hdsaCls) == DSA_GetItemCount(g_hdsaStr);
  1759. }
  1760. ENTERCRITICAL;
  1761. if (!g_hdsaCls) {
  1762. g_hdsaStr = DSA_Create(SIZEOF(LPCSTR), 32);
  1763. if (g_hdsaStr)
  1764. {
  1765. HDSA hdsaCls = DSA_Create(SIZEOF(CLSID), 32);
  1766. if (hdsaCls)
  1767. {
  1768. HKEY hkey;
  1769. if (RegOpenKey(HKEY_LOCAL_MACHINE,
  1770. TEXT("Software\\Microsoft\\Internet Explorer\\MediaTypeClass"),
  1771. &hkey) == ERROR_SUCCESS)
  1772. {
  1773. TCHAR szCLSID[64]; // enough for "{CLSID}"
  1774. for (int iKey=0;
  1775. RegEnumKey(hkey, iKey, szCLSID, SIZEOF(szCLSID)/sizeof(szCLSID[0]))==ERROR_SUCCESS;
  1776. iKey++)
  1777. {
  1778. CLSID clsid;
  1779. if (FAILED(CLSIDFromString(szCLSID, &clsid))) {
  1780. TraceMsg(DM_WARNING, "CDOH::_RMTC CLSIDFromString(%x) failed", szCLSID);
  1781. continue;
  1782. }
  1783. TraceMsg(DM_MIMEMAPPING, "CDOH::_RMTC RegEnumKey found %s", szCLSID);
  1784. HKEY hkeyCLSID;
  1785. if (RegOpenKey(hkey, szCLSID, &hkeyCLSID) == ERROR_SUCCESS)
  1786. {
  1787. for (int iValue=0; ; iValue++)
  1788. {
  1789. CHAR szFormatName[128];
  1790. DWORD dwType;
  1791. DWORD cchValueName = ARRAYSIZE(szFormatName);
  1792. //
  1793. // Keep the name ansi because it needs to get
  1794. // passed to urlmon's RegisterMediaTypeClass as
  1795. // ansi.
  1796. //
  1797. if (RegEnumValueA(hkeyCLSID, iValue, szFormatName, &cchValueName, NULL,
  1798. &dwType, NULL, NULL)==ERROR_SUCCESS)
  1799. {
  1800. TraceMsg(DM_MIMEMAPPING, "CDOH::_RMTC RegEnumValue found %s", szFormatName);
  1801. LPSTR psz = StrDupA(szFormatName);
  1802. if (psz) {
  1803. DSA_InsertItem(hdsaCls, 0xffff, &clsid);
  1804. if (DSA_InsertItem(g_hdsaStr, 0xffff, &psz)<0) {
  1805. LocalFree(psz);
  1806. psz = NULL;
  1807. break;
  1808. }
  1809. }
  1810. } else {
  1811. break;
  1812. }
  1813. }
  1814. RegCloseKey(hkeyCLSID);
  1815. } else {
  1816. TraceMsg(DM_WARNING, "CDOH::_RMTC RegOpenKey(%s) failed", szCLSID);
  1817. }
  1818. }
  1819. RegCloseKey(hkey);
  1820. } else {
  1821. TraceMsg(0, "CDOH::_RMTC RegOpenKey(MediaTypeClass) failed");
  1822. }
  1823. //
  1824. // Update g_hdsaCls at the end so that other thread won't
  1825. // access while we are adding items.
  1826. //
  1827. g_hdsaCls = hdsaCls;
  1828. ASSERT(DSA_GetItemCount(g_hdsaCls)==DSA_GetItemCount(g_hdsaStr));
  1829. }
  1830. }
  1831. }
  1832. LEAVECRITICAL;
  1833. return (g_hdsaCls && DSA_GetItemCount(g_hdsaCls)==DSA_GetItemCount(g_hdsaStr));
  1834. }
  1835. HRESULT CDocObjectHost::_RegisterMediaTypeClass(IBindCtx* pbc)
  1836. {
  1837. HRESULT hres = S_FALSE; // Assume no mapping
  1838. if (_BuildClassMapping() && DSA_GetItemCount(g_hdsaCls)) {
  1839. //
  1840. // WARNING: This code assumes that g_hdsaCls/g_hdsaStr never
  1841. // changes once they are initializes. Read notes above
  1842. // those global variables for detail.
  1843. //
  1844. hres = RegisterMediaTypeClass(pbc,
  1845. DSA_GetItemCount(g_hdsaCls),
  1846. (LPCSTR*)DSA_GetItemPtr(g_hdsaStr, 0),
  1847. (CLSID*)DSA_GetItemPtr(g_hdsaCls, 0), 0);
  1848. TraceMsg(DM_MIMEMAPPING, "CDOH::_StartAsyncBinding RegisterMTC returns %x", hres);
  1849. }
  1850. // Now see if the container has anything that needs to be registered
  1851. //
  1852. if (_psp)
  1853. {
  1854. IMimeInfo * pIMimeInfo;
  1855. hres = _psp->QueryService(SID_IMimeInfo, IID_IMimeInfo, (void **)&pIMimeInfo);
  1856. if (SUCCEEDED(hres))
  1857. {
  1858. UINT cTypes = 0;
  1859. LPCSTR *ppszTypes = NULL;
  1860. CLSID *pclsIDs= NULL;
  1861. ASSERT(pIMimeInfo);
  1862. hres = pIMimeInfo->GetMimeCLSIDMapping(&cTypes, &ppszTypes, &pclsIDs);
  1863. if (SUCCEEDED(hres)) {
  1864. if (cTypes && ppszTypes && pclsIDs) {
  1865. // Last one to register wins, so if the container wants to override what is
  1866. // already registered this should do it.
  1867. // URLMon will handle the duplicates corectly.
  1868. //
  1869. hres = RegisterMediaTypeClass(pbc, cTypes, ppszTypes, pclsIDs, 0);
  1870. TraceMsg(DM_MIMEMAPPING, "CDOH::_StartAsyncBinding RegisterMTC for Container returns %x", hres);
  1871. }
  1872. // RegisterMediaTypeClass should have made copies
  1873. // so free the containers allocations as it expects us to do
  1874. //
  1875. // CoTaskMemFree(NULL) is OK
  1876. //
  1877. CoTaskMemFree(ppszTypes);
  1878. CoTaskMemFree(pclsIDs);
  1879. }
  1880. pIMimeInfo->Release();
  1881. } else {
  1882. hres = S_FALSE;
  1883. }
  1884. }
  1885. return hres;
  1886. }
  1887. HRESULT _RegisterAcceptHeaders(IBindCtx* pbc, IShellBrowser* psb)
  1888. {
  1889. return RegisterDefaultAcceptHeaders(pbc, psb);
  1890. }
  1891. HRESULT GetAmbientBoolProp(IExpDispSupport* peds, DISPID dispid, BOOL *pb)
  1892. {
  1893. VARIANT var = {0};
  1894. // Assume failure
  1895. *pb = FALSE;
  1896. HRESULT hres = peds->OnInvoke(dispid, IID_NULL, NULL, DISPATCH_PROPERTYGET, (DISPPARAMS *)&g_dispparamsNoArgs, &var, NULL, NULL);
  1897. if (SUCCEEDED(hres))
  1898. {
  1899. // VB returns success with VT_EMPTY, so we can't assert here
  1900. if (var.vt == VT_BOOL)
  1901. {
  1902. *pb = (var.boolVal) ? TRUE : FALSE;
  1903. }
  1904. else
  1905. {
  1906. // Even though VB says VT_EMPTY, we don't know what other containers
  1907. // might shove in here. Make sure we clean up.
  1908. //
  1909. VariantClear(&var);
  1910. }
  1911. }
  1912. else
  1913. {
  1914. hres = E_FAIL;
  1915. }
  1916. return hres;
  1917. }
  1918. HRESULT CDocObjectHost::_GetOfflineSilent(BOOL *pbIsOffline, BOOL *pbIsSilent)
  1919. {
  1920. if (_peds)
  1921. {
  1922. if (pbIsOffline)
  1923. GetAmbientBoolProp(_peds, DISPID_AMBIENT_OFFLINEIFNOTCONNECTED, pbIsOffline);
  1924. if (pbIsSilent)
  1925. GetAmbientBoolProp(_peds, DISPID_AMBIENT_SILENT, pbIsSilent);
  1926. }
  1927. else
  1928. {
  1929. if (pbIsOffline)
  1930. *pbIsOffline = FALSE;
  1931. if (pbIsSilent)
  1932. *pbIsSilent = FALSE;
  1933. }
  1934. return S_OK;
  1935. }
  1936. /*
  1937. Callback function for RatingObtainQuery
  1938. */
  1939. void RatingObtainQueryCallback(DWORD dwUserData, HRESULT hr, LPCSTR pszRating, LPVOID lpvInpageRating)
  1940. {
  1941. TraceMsg(DM_PICS, "RatingObtainQueryCallback given result %x", hr);
  1942. /* WARNING: This function is called by MSRATING.DLL on a separate thread,
  1943. * not the main message loop thread. Touch nothing in important data
  1944. * structures not protected by critical sections!
  1945. *
  1946. * Merely format up a windows message with the info we have; we'll handle
  1947. * this in the main thread, if we ever get there.
  1948. *
  1949. * Note that pszRating is ignored, we count on the ratings engine to have
  1950. * called RatingCheckUserAccess for us and provide the HRESULT.
  1951. */
  1952. if (!::_PostPicsMessage(dwUserData, hr, lpvInpageRating))
  1953. {
  1954. if ( lpvInpageRating )
  1955. {
  1956. ::RatingFreeDetails(lpvInpageRating);
  1957. lpvInpageRating = NULL;
  1958. }
  1959. }
  1960. }
  1961. HRESULT CDocObjectHost::_StartAsyncBinding(IMoniker * pmk, IBindCtx * pbc, IShellView * psvPrev)
  1962. {
  1963. URLMSG(TEXT("_StartAsyncBinding called"));
  1964. HRESULT hres;
  1965. ASSERT(_bsc._pbc == NULL && _pole == NULL);
  1966. _bsc._RegisterObjectParam(pbc);
  1967. //
  1968. // Associate the client site as an object parameter to this
  1969. // bind context so that Trident can pick it up while processing
  1970. // IPersistMoniker::Load().
  1971. //
  1972. pbc->RegisterObjectParam(WSZGUID_OPID_DocObjClientSite, SAFECAST(this, IOleClientSite*));
  1973. _ChainBSC();
  1974. IUnknown * punk = NULL;
  1975. _bsc._pbc = pbc;
  1976. pbc->AddRef();
  1977. // Decide right here whether or not this frame is offline
  1978. BOOL bFrameIsOffline = FALSE;
  1979. BOOL bFrameIsSilent = FALSE;
  1980. this->_GetOfflineSilent(&bFrameIsOffline, &bFrameIsSilent);
  1981. _bsc._bFrameIsOffline = bFrameIsOffline ? TRUE : FALSE;
  1982. _bsc._bFrameIsSilent = bFrameIsSilent ? TRUE : FALSE;
  1983. BOOL bSuppressUI = (_bsc._bFrameIsSilent || _IsDesktopItem(SAFECAST(this, CDocObjectHost*))) ? TRUE : FALSE;
  1984. #ifdef DEBUG
  1985. PERFMSG(TEXT("_StartAsyncBinding Calling pmk->BindToObject"), GetCurrentTime()-g_dwPerf);
  1986. g_dwPerf = GetCurrentTime();
  1987. #endif
  1988. #ifdef DEBUG
  1989. if (g_dwPrototype & 0x00000800) {
  1990. TraceMsg(DM_TRACE, "CDOH::_StartAsyncBinding skipping CLSID mapping");
  1991. }
  1992. else
  1993. #endif
  1994. {
  1995. // Register overriding mime->CLSID mapping
  1996. _RegisterMediaTypeClass(pbc);
  1997. }
  1998. // Register accept headers
  1999. _RegisterAcceptHeaders(pbc, _psb);
  2000. if (_pwb)
  2001. {
  2002. _pwb->SetNavigateState(BNS_BEGIN_NAVIGATE);
  2003. }
  2004. _StartBasePicsProcessor();
  2005. //
  2006. // Crazy sync/async behavior of URLMON. - zekel - 6-AUG-97
  2007. // any of the following may occur:
  2008. //
  2009. // 1. SUCCESS or FAILURE: we receive sync E_PENDING from BindToObject,
  2010. // and then get an Async HRESULT on OnStopBinding().
  2011. // this is the most common case and the basic design.
  2012. //
  2013. // 2. SUCCESS: we receive sync S_OK from BindToObject and
  2014. // need to complete the async behavior on our BSCB ourself
  2015. // since urlmon started but did not finish.
  2016. //
  2017. // 3. SUCCESS: while inside BindToObject(), we receive sync S_OK
  2018. // from OnStopBinding(), and then BindToObject returns with S_OK.
  2019. //
  2020. // 4. FAILURE: simplest case is an error being returned from BindToObject()
  2021. // but without an any OnStopBinding() so we need to complete
  2022. // the async behavior on our BSCB ourself since urlmon started but did not finish.
  2023. // this usually occurs when accessing local files.
  2024. //
  2025. // 5. FAILURE: while inside BindToObject(), we receive sync S_OK from OnStopBinding(),
  2026. // and then BindToObject returns with some other error that needs to be handled.
  2027. // this occurs with some malformed urls.
  2028. //
  2029. // 6. FAILURE: while inside BindToObject(), we receive a sync error from OnStopBinding(),
  2030. // and then BindToObject returns with some other error (usually E_FAIL).
  2031. // we need to trust the first one. this occurs when wininet
  2032. // returns syncronous errors, and its error is the one returned in OnStopBinding()
  2033. //
  2034. // 7. FAILURE: while inside BindToObject(), we receive a sync error from OnStopBinding(),
  2035. // and then BindToObject returns with E_PENDING. which we think means everything
  2036. // is going great, and urlmon thinks it is done. this happens with a file: to
  2037. // a resource that is not hostable. we need to show the download UI.
  2038. //
  2039. // in order to support all the errors in the most consistent and safe manner,
  2040. // we defer any errors in OnStopBinding() if they are delivered synchronously
  2041. // on BindToObject(). the OnStopBinding() error always overrides the BindToObject()
  2042. // error, but any error will always override any success.
  2043. //
  2044. ASSERT(S_OK == _hrOnStopBinding);
  2045. _fSyncBindToObject = TRUE;
  2046. URLMSG(TEXT("_StartAsyncBinding calling pmk->BindToObject"));
  2047. hres = pmk->BindToObject(pbc, NULL, IID_IUnknown, (void**)&punk);
  2048. URLMSG3(TEXT("_StartAsyncBinding pmk->BindToObject returned"), hres, punk);
  2049. _fSyncBindToObject = FALSE;
  2050. if (SUCCEEDED(_hrOnStopBinding) && (SUCCEEDED(hres) || hres==E_PENDING))
  2051. {
  2052. hres = S_OK;
  2053. if (_bsc._pbc) {
  2054. //
  2055. // In case OnStopBinding hasn't been called.
  2056. //
  2057. if (!_pole)
  2058. {
  2059. if (psvPrev)
  2060. {
  2061. _bsc._psvPrev = psvPrev;
  2062. psvPrev->AddRef();
  2063. }
  2064. }
  2065. else
  2066. {
  2067. URLMSG3(TEXT("_StartAsyncBinding we've already got _pole"), hres, _pole);
  2068. }
  2069. //
  2070. // If moniker happen to return the object synchronously, emulate
  2071. // OnDataAvailable callback and OnStopBinding.
  2072. //
  2073. if (punk)
  2074. {
  2075. _bsc.OnObjectAvailable(IID_IUnknown, punk);
  2076. _bsc.OnStopBinding(hres, NULL);
  2077. punk->Release();
  2078. ASSERT(_bsc._pbc==NULL);
  2079. }
  2080. }
  2081. else
  2082. {
  2083. //
  2084. // OnStopBinding has been already called.
  2085. //
  2086. if (punk)
  2087. {
  2088. AssertMsg(0, TEXT("CDOH::_StartAsyncBinding pmk->BindToObject returned punk after calling OnStopBinding")); // Probably URLMON bug.
  2089. punk->Release();
  2090. }
  2091. }
  2092. }
  2093. else
  2094. {
  2095. // Binding failed.
  2096. TraceMsg(DM_WARNING, "CDOH::_StartAsyncBinding failed (%x)", hres);
  2097. //
  2098. // Urlmon is inconsistent in it's error handling - zekel - 4-AUG-97
  2099. // urlmon can return errors in three different ways from BindToObject()
  2100. // 1. it can return back a simple syncronous error. without calling OnStopBinding()
  2101. //
  2102. // 2. it can return a sync error,
  2103. // but call OnStopBinding() with S_OK first on the same thread;
  2104. //
  2105. // 3. it can return a sync error,
  2106. // but also call OnStopBinding() with the real Error first on the same thread.
  2107. //
  2108. // 4. it can return E_PENDING,
  2109. // but already have called OnStopBinding() with the real error.
  2110. //
  2111. // SOLUTIONS:
  2112. // in all cases of error in OnStopBinding(), we will now postpone the OnStopBinding processing util after
  2113. // we have returned from the BindToObject(). we try to use the best error.
  2114. // we allow successful OnStopBinding() to pass through unmolested, and trap
  2115. // the error here if necessary.
  2116. //
  2117. if (FAILED(_hrOnStopBinding))
  2118. hres = _hrOnStopBinding;
  2119. if (_bsc._pbc)
  2120. _bsc.OnStopBinding(hres, NULL);
  2121. else if (!bSuppressUI)
  2122. {
  2123. //
  2124. // OnStopBinding was already called, but with a success
  2125. // so we need to handle the error here. this happens
  2126. // with some invalid URLs like http:/server
  2127. //
  2128. BOOL fCancelErrorPage = FALSE;
  2129. _FireNavigateErrorHelper(NULL, ERRORPAGE_SYNTAX, &fCancelErrorPage);
  2130. if (fCancelErrorPage)
  2131. {
  2132. _CancelPendingNavigation(TRUE, FALSE);
  2133. }
  2134. else
  2135. {
  2136. // Fix for W98 webtv app. If we're in a frame don't
  2137. // blow away the frame set to dispaly the error.
  2138. //
  2139. if (!_fHaveParentSite)
  2140. {
  2141. _bsc._NavigateToErrorPage(ERRORPAGE_SYNTAX, this, FALSE);
  2142. }
  2143. }
  2144. }
  2145. ASSERT(_bsc._pbc==NULL);
  2146. }
  2147. return hres;
  2148. }
  2149. void CDocObjectHost::_ReleasePendingObject(BOOL fIfInited)
  2150. {
  2151. HRESULT hres;
  2152. IOleObject *polePending;
  2153. #ifdef TRIDENT_NEEDS_LOCKRUNNING
  2154. IRunnableObject *pro;
  2155. #endif
  2156. if (fIfInited == FALSE && _fPendingWasInited == FALSE)
  2157. return;
  2158. if (_punkPending)
  2159. {
  2160. if (_fCreatingPending)
  2161. {
  2162. _fAbortCreatePending = 1;
  2163. return;
  2164. }
  2165. if (!_fPendingNeedsInit && !IsSameObject(_punkPending, _pole))
  2166. {
  2167. hres = _punkPending->QueryInterface(IID_IOleObject, (void **) &polePending);
  2168. if (SUCCEEDED(hres)) {
  2169. LPOLECLIENTSITE pcs;
  2170. if (SUCCEEDED(polePending->GetClientSite(&pcs)) && pcs)
  2171. {
  2172. if (pcs == SAFECAST(this, LPOLECLIENTSITE))
  2173. {
  2174. polePending->SetClientSite(NULL);
  2175. }
  2176. pcs->Release();
  2177. }
  2178. polePending->Release();
  2179. }
  2180. }
  2181. #ifdef TRIDENT_NEEDS_LOCKRUNNING
  2182. // TRIDENT NO LONGER SUPPORTS IRunnableObject
  2183. hres = _punkPending->QueryInterface(IID_IRunnableObject, (void **) &pro);
  2184. if (SUCCEEDED(hres))
  2185. {
  2186. hres = pro->LockRunning(FALSE, TRUE);
  2187. pro->Release();
  2188. }
  2189. #endif
  2190. SAFERELEASE(_punkPending);
  2191. _fPendingWasInited = FALSE;
  2192. }
  2193. }
  2194. void CDocObjectHost::_ReleaseOleObject(BOOL fIfInited)
  2195. {
  2196. TraceMsg(DM_DEBUGTFRAME, "CDocObjectHost::_ReleaseOleObject called %x (%x)", _pole, this);
  2197. // Minimize impact by cleaning up in affected cases only.
  2198. if (fIfInited == FALSE && _fPendingWasInited == FALSE)
  2199. return;
  2200. // release _pole object and all the associated QI'ed pointers
  2201. if (_phls) {
  2202. _phls->SetBrowseContext(NULL); // probably no need
  2203. ATOMICRELEASE(_phls);
  2204. }
  2205. if (_pvo) {
  2206. IAdviseSink *pSink;
  2207. // paranoia: only blow away the advise sink if it is still us
  2208. if (SUCCEEDED(_pvo->GetAdvise(NULL, NULL, &pSink)) && pSink) {
  2209. if (pSink == (IAdviseSink *)this) {
  2210. _pvo->SetAdvise(0, 0, NULL);
  2211. } else {
  2212. ASSERT(0); // do we really hit this case?
  2213. }
  2214. pSink->Release();
  2215. }
  2216. ATOMICRELEASE(_pvo);
  2217. }
  2218. if (_pole)
  2219. {
  2220. LPOLECLIENTSITE pcs;
  2221. if (SUCCEEDED(_pole->GetClientSite(&pcs)) && pcs)
  2222. {
  2223. if (IsSameObject(pcs, SAFECAST(this, LPOLECLIENTSITE)))
  2224. {
  2225. _pole->SetClientSite(NULL);
  2226. }
  2227. pcs->Release();
  2228. }
  2229. // Notes: Make it sure that we don't hold a bogus _pole even
  2230. // for a moment (while we call Release).
  2231. ATOMICRELEASE(_pole);
  2232. }
  2233. }
  2234. //
  2235. // This member releases all the interfaces to the DocObject, which is
  2236. // essentially the reverse of _Bind.
  2237. //
  2238. void CDocObjectHost::_UnBind(void)
  2239. {
  2240. ATOMICRELEASE(_pHTMLWindow);
  2241. ATOMICRELEASE(_pmsot);
  2242. VariantClear(&_varUserEnteredUrl);
  2243. ASSERT(!_pmsov); // paranoia
  2244. ATOMICRELEASE(_pmsov);
  2245. ASSERT(!_pmsoc); // paranoia
  2246. ATOMICRELEASE(_pmsoc);
  2247. _xao.SetActiveObject(NULL);
  2248. if (_pole)
  2249. {
  2250. // Just in case we're destroyed while we were waiting
  2251. // for the docobj to display itself.
  2252. //
  2253. _RemoveTransitionCapability();
  2254. //
  2255. // If this is NOT MSHTML, cache the OLE server so that we don't
  2256. // need to restart or load the OLE server again.
  2257. //
  2258. if (!(_dwAppHack & (BROWSERFLAG_MSHTML | BROWSERFLAG_DONTCACHESERVER)))
  2259. {
  2260. IBrowserService *pbs;
  2261. if (SUCCEEDED(QueryService(SID_STopLevelBrowser, IID_IBrowserService, (void **)&pbs)))
  2262. {
  2263. pbs->CacheOLEServer(_pole);
  2264. pbs->Release();
  2265. }
  2266. }
  2267. TraceMsg(DM_ADVISE, "CDocObjectHost::_UnBind about to call Close of %x", _pole);
  2268. _pole->Close(OLECLOSE_NOSAVE);
  2269. _ReleaseOleObject();
  2270. }
  2271. _ReleasePendingObject();
  2272. ATOMICRELEASE(_pstg);
  2273. ATOMICRELEASE(_pbcCur);
  2274. ATOMICRELEASE(_pmkCur);
  2275. }
  2276. //
  2277. // HACK: If we open Excel95 objects directly, Excel goes crazy and eventually
  2278. // hit GPF. Here is the background info, I've got Office guys (SatoNa).
  2279. //
  2280. // From: Rajeev Misra (Xenix)
  2281. //
  2282. // 1) Excel does not handle the foll. case very well. Taking a normal file
  2283. // loading it through IPersistFile:Load and then bringing it up as an
  2284. // embedded object. The code was always tested so that the embedded
  2285. // objects always got loaded through ScPrsLoad. I am seeing a bunch of
  2286. // asserts in Excel that say that this assumption is being destroyed.
  2287. // ASSERT(_pole);
  2288. //
  2289. // From: Srini Koppolu
  2290. //
  2291. // For you, there is only one case, i.e. you always deal with the files. Then your code should look like this
  2292. //
  2293. // CreateFileMoniker from the file
  2294. // pUIActiveObject->OnFrameWindowActivate(FALSE);
  2295. // pmk->BindToObject(IID_IDataObject, &pdobj)
  2296. // pUIActiveObject->OnFrameWindowActivate(TRUE);
  2297. // OleCreateFromData()
  2298. //
  2299. // OnFrameWindowActivate is done to take care of another excel problem.
  2300. // If you currently have and Excel object UIActive in you and you try to
  2301. // do IPersistFile::Load on Excel, then it will cause problems.
  2302. //
  2303. void CDocObjectHost::_AppHackForExcel95(void)
  2304. {
  2305. ASSERT(_pole);
  2306. HRESULT hres;
  2307. IDataObject* pdt = NULL;
  2308. hres = _pole->QueryInterface(IID_IDataObject, (void **)&pdt);
  2309. TraceMsg(DM_BINDAPPHACK, "_PostBindAppHack -- QI(IOleDataObject) returned %x", hres);
  2310. if (SUCCEEDED(hres))
  2311. {
  2312. ASSERT(_pstg==NULL);
  2313. hres = StgCreateDocfile(NULL,
  2314. STGM_DIRECT | STGM_CREATE | STGM_READWRITE
  2315. | STGM_SHARE_EXCLUSIVE | STGM_DELETEONRELEASE,
  2316. 0, &_pstg);
  2317. TraceMsg(DM_BINDAPPHACK, "_PostBindAppHack StgCreateDocFile(NULL) returned %x", hres);
  2318. if (SUCCEEDED(hres))
  2319. {
  2320. IOleObject* poleCopy = NULL;
  2321. hres = OleCreateFromData(pdt, IID_IOleObject, OLERENDER_NONE,
  2322. NULL, this, _pstg, (void **)&poleCopy);
  2323. TraceMsg(DM_BINDAPPHACK, "_PostBindAppHack OleCreateFromData(IOleObject) returned %x", hres);
  2324. if (SUCCEEDED(hres)) {
  2325. _fCantSaveBack = TRUE;
  2326. ATOMICRELEASE(_pole);
  2327. _pole = poleCopy;
  2328. }
  2329. }
  2330. pdt->Release();
  2331. }
  2332. }
  2333. //
  2334. // This function get the UserClassID from the object and opens the regkey
  2335. // for that CLSID and returns. If pdwAppHack is non-NULL AND CLSID is
  2336. // CLSID_HTMLDocument, we skip all and returns the default apphack flag.
  2337. // This is a perf optimization, but prevents us from setting browser
  2338. // flags for Trident, which is fine. (SatoNa)
  2339. //
  2340. HKEY _GetUserCLSIDKey(IOleObject* pole, const CLSID* pclsid, DWORD* pdwAppHack)
  2341. {
  2342. HKEY hkey = NULL; // assume error
  2343. HRESULT hres;
  2344. CLSID clsid = CLSID_NULL;
  2345. if (pole)
  2346. {
  2347. hres = pole->GetUserClassID(&clsid);
  2348. // GetUserClassID is optional, can return E_FAIL, then is defined to be
  2349. // the same as that returned by IPersist::GetClassID. cf, msdev documentation
  2350. // for GetUserClassID
  2351. if (FAILED(hres))
  2352. {
  2353. hres = IUnknown_GetClassID(pole, &clsid);
  2354. }
  2355. }
  2356. else if (pclsid)
  2357. {
  2358. clsid = *pclsid;
  2359. hres = S_OK;
  2360. }
  2361. else
  2362. {
  2363. return NULL;
  2364. }
  2365. //
  2366. // Notice that we check for two CLSIDs to see if this is MSHTML.
  2367. //
  2368. if (pdwAppHack)
  2369. {
  2370. static const IID IID_IVBOleObj =
  2371. {0xb88c9640, 0x14e0, 0x11d0, { 0xb3, 0x49, 0x0, 0xa0, 0xc9, 0xa, 0xea, 0x82 } };
  2372. IUnknown * pVBOleObj;
  2373. if ( IsEqualGUID(clsid, CLSID_HTMLDocument)
  2374. || IsEqualGUID(clsid, CLSID_MHTMLDocument)
  2375. || IsEqualGUID(clsid, CLSID_HTMLPluginDocument) )
  2376. {
  2377. TraceMsg(TF_SHDAPPHACK, "_GetUserCLSID this is Trident. Skip opening reg key");
  2378. *pdwAppHack = BROWSERFLAG_NEVERERASEBKGND | BROWSERFLAG_SUPPORTTOP
  2379. | BROWSERFLAG_MSHTML;
  2380. return NULL;
  2381. }
  2382. else if (pole && SUCCEEDED(pole->QueryInterface(IID_IVBOleObj, (void**)&pVBOleObj) ))
  2383. {
  2384. // If the object answers to IID_IVBOleObj, it's a VB doc object and shouldn't be cached.
  2385. //
  2386. pVBOleObj->Release();
  2387. *pdwAppHack = BROWSERFLAG_DONTCACHESERVER;
  2388. }
  2389. }
  2390. //
  2391. // HACK: MSHTML.DLL does not implement GetUserClassID, but
  2392. // returns S_OK. That's why we need to check for CLSID_NULL.
  2393. //
  2394. if (SUCCEEDED(hres) && !IsEqualGUID(clsid, CLSID_NULL)) {
  2395. TCHAR szBuf[50]; // 50 is enough for GUID
  2396. SHStringFromGUID(clsid, szBuf, ARRAYSIZE(szBuf));
  2397. TraceMsg(DM_BINDAPPHACK, "_PostBindAppHack GetUserClassID = %s", szBuf);
  2398. TCHAR szKey[60]; // 60 is enough for CLSID\\{CLSID_XX}
  2399. wnsprintf(szKey, ARRAYSIZE(szKey), TEXT("CLSID\\%s"), szBuf);
  2400. if (RegOpenKey(HKEY_CLASSES_ROOT, szKey, &hkey)!=ERROR_SUCCESS)
  2401. {
  2402. TraceMsg(DM_WARNING, "_GetUserCLSIDKey RegOpenKey(%s) failed", szKey);
  2403. // I don't trust RegOpenKey.
  2404. hkey = NULL;
  2405. }
  2406. }
  2407. return hkey;
  2408. }
  2409. BOOL _GetAppHackKey(LPCTSTR pszProgID, DWORD* pdwData)
  2410. {
  2411. BOOL fSuccess = FALSE;
  2412. HKEY hkey;
  2413. if (RegOpenKey(HKEY_CLASSES_ROOT, pszProgID, &hkey)==ERROR_SUCCESS)
  2414. {
  2415. DWORD dwType;
  2416. DWORD cbSize = SIZEOF(*pdwData);
  2417. if (RegQueryValueEx(hkey, TEXT("BrowserFlags"), NULL,
  2418. &dwType, (LPBYTE)pdwData, &cbSize)==ERROR_SUCCESS
  2419. && (dwType==REG_DWORD || (dwType==REG_BINARY && cbSize==SIZEOF(*pdwData))))
  2420. {
  2421. fSuccess = TRUE;
  2422. }
  2423. else
  2424. {
  2425. //
  2426. // Unlike IE3, we make it absolutely sure that the type of object
  2427. // has either "DocObject" key or "BrowseInPlace" key under the
  2428. // ProgID. We can't rely on QI(IID_IOleDocument) because MFC 4.2
  2429. // has a bug and returns S_OK to it. As far as I know, MS-Paint
  2430. // and OmniPage pro are affected by this. We could individually
  2431. // address each of them, but it's probably impossible to catch
  2432. // all. This change has a small risk of breaking existing DocObject
  2433. // server which does not have neither key. If we find such a
  2434. // server, we'll address those individually (which is much easier
  2435. // than covering all MFC apps). (SatoNa)
  2436. //
  2437. TCHAR ach[MAX_PATH];
  2438. LONG cb;
  2439. BOOL fBrowsable = FALSE;
  2440. if ((cb=SIZEOF(ach)) && RegQueryValue(hkey, TEXT("DocObject"), ach, &cb) == ERROR_SUCCESS)
  2441. fBrowsable = TRUE;
  2442. else if ((cb=SIZEOF(ach)) && RegQueryValue(hkey, TEXT("BrowseInPlace"), ach, &cb) == ERROR_SUCCESS)
  2443. fBrowsable = TRUE;
  2444. if (!fBrowsable) {
  2445. TraceMsg(DM_WARNING, "_GetAppHackKey this is neither DocObject or BrowseInPlace");
  2446. *pdwData = BROWSERFLAG_DONTINPLACE;
  2447. }
  2448. }
  2449. RegCloseKey(hkey);
  2450. }
  2451. return fSuccess;
  2452. }
  2453. void GetAppHackFlags(IOleObject* pole, const CLSID* pclsid, DWORD* pdwAppHack)
  2454. {
  2455. HKEY hkey = _GetUserCLSIDKey(pole, pclsid, pdwAppHack);
  2456. if (hkey)
  2457. {
  2458. TCHAR szValue[MAX_PATH];
  2459. LONG cb = SIZEOF(szValue);
  2460. if (RegQueryValue(hkey, TEXT("ProgID"), szValue, &cb) == ERROR_SUCCESS)
  2461. {
  2462. //
  2463. // First, check if we have an BrowserFlags flag in the registry.
  2464. // If there is, use it. Otherwise, try hard-coded progIDs as
  2465. // we did in IE 3.0
  2466. //
  2467. _GetAppHackKey(szValue, pdwAppHack);
  2468. if (!(*pdwAppHack & BROWSERFLAG_REPLACE)) {
  2469. typedef struct _APPHACK {
  2470. LPCTSTR pszProgID;
  2471. DWORD dwAppHack;
  2472. } APPHACK;
  2473. //
  2474. // We no longer need to disable in-place activation of
  2475. // MS-PAINT because we look for "BrowseInPlace" or
  2476. // "DocObject" key
  2477. //
  2478. // { "Paint.Picture", BROWSERFLAG_DONTINPLACE },
  2479. //
  2480. const static APPHACK s_aah[] = {
  2481. { TEXT("Excel.Sheet.5"), BROWSERFLAG_OPENCOPY },
  2482. { TEXT("Excel.Chart.5"), BROWSERFLAG_OPENCOPY },
  2483. { TEXT("SoundRec"), BROWSERFLAG_OPENVERB },
  2484. { TEXT("Word.Document.6"), BROWSERFLAG_SETHOSTNAME },
  2485. { TEXT("Word.Document.8"), BROWSERFLAG_DONTUIDEACTIVATE | BROWSERFLAG_SETHOSTNAME },
  2486. { TEXT("PowerPoint.Show.8"), BROWSERFLAG_DONTUIDEACTIVATE | BROWSERFLAG_PRINTPROMPTUI },
  2487. { TEXT("Excel.Sheet.8"), BROWSERFLAG_DONTDEACTIVATEMSOVIEW | BROWSERFLAG_INITNEWTOKEEP },
  2488. { TEXT("Excel.Chart.8"), BROWSERFLAG_DONTDEACTIVATEMSOVIEW | BROWSERFLAG_INITNEWTOKEEP },
  2489. { TEXT("ABCFlowCharter6.Document"), BROWSERFLAG_DONTINPLACE },
  2490. { TEXT("ABCFlowCharter7.Document"), BROWSERFLAG_DONTINPLACE },
  2491. { TEXT("FlowCharter7.Document"), BROWSERFLAG_DONTINPLACE },
  2492. { TEXT("ChannelFile"), BROWSERFLAG_DONTAUTOCLOSE },
  2493. { TEXT("Visio.Drawing.5"), BROWSERFLAG_ENABLETOOLSBTN | BROWSERFLAG_SAVEASWHENCLOSING },
  2494. { TEXT("Visio.Drawing.4"), BROWSERFLAG_ENABLETOOLSBTN | BROWSERFLAG_SAVEASWHENCLOSING }
  2495. };
  2496. const static TCHAR s_ActiveMoveCtx[] = TEXT("AMOVIE.ActiveMovieControl");
  2497. if (!StrCmpN(szValue, s_ActiveMoveCtx, ARRAYSIZE(s_ActiveMoveCtx)-1))
  2498. {
  2499. *pdwAppHack = BROWSERFLAG_DONTAUTOCLOSE;
  2500. }
  2501. else
  2502. {
  2503. for (int i=0; i<ARRAYSIZE(s_aah); i++) {
  2504. if (StrCmp(szValue, s_aah[i].pszProgID)==0)
  2505. {
  2506. *pdwAppHack |= s_aah[i].dwAppHack;
  2507. break;
  2508. }
  2509. }
  2510. }
  2511. }
  2512. TraceMsg(DM_BINDAPPHACK, "_GetAppHack ProgID=%s, *pdwAppHack=%x",
  2513. szValue, *pdwAppHack);
  2514. } else {
  2515. TraceMsg(DM_BINDAPPHACK, "_GetAppHack RegQueryValue(ProgID) failed");
  2516. }
  2517. RegCloseKey(hkey);
  2518. }
  2519. }
  2520. DWORD CDocObjectHost::_GetAppHack(void)
  2521. {
  2522. ASSERT(_pole);
  2523. if (!_fHaveAppHack && _pole)
  2524. {
  2525. _dwAppHack = 0; // Assume no hack
  2526. _fHaveAppHack = TRUE;
  2527. ::GetAppHackFlags(_pole, NULL, &_dwAppHack);
  2528. }
  2529. return _pole ? _dwAppHack : 0;
  2530. }
  2531. void CDocObjectHost::_PostBindAppHack(void)
  2532. {
  2533. _GetAppHack();
  2534. if (_fAppHackForExcel()) {
  2535. _AppHackForExcel95();
  2536. }
  2537. }
  2538. //
  2539. // This member binds to the object specified by a moniker.
  2540. //
  2541. HRESULT CDocObjectHost::_BindSync(IMoniker* pmk, IBindCtx* pbc, IShellView* psvPrev)
  2542. {
  2543. ASSERT(pbc || !_pole);
  2544. HRESULT hres = S_OK;
  2545. ASSERT(_pole==NULL);
  2546. // Check if we are in the middle of asynchronous binding
  2547. if (_bsc._fBinding)
  2548. {
  2549. // Yes, wait until it's done or canceled/stopped
  2550. URLMSG(TEXT("_Bind called in the middle of async-binding. Wait in a message loop"));
  2551. while(_bsc._fBinding)
  2552. {
  2553. MSG msg;
  2554. if (GetMessage(&msg, NULL, 0, 0))
  2555. {
  2556. TranslateMessage(&msg);
  2557. DispatchMessage(&msg);
  2558. }
  2559. }
  2560. if (!_pole)
  2561. {
  2562. hres = E_FAIL; // Get the error code from OnStopBinding
  2563. }
  2564. }
  2565. else
  2566. {
  2567. // No, bind synchronously
  2568. URLMSG(TEXT("_Bind. Performing syncronous binding"));
  2569. hres = pmk->BindToObject(pbc, NULL, IID_IOleObject, (void **)&_pole);
  2570. }
  2571. TraceMsg(0, "sdv TR : _Bind -- pmk->BindToObject(IOleObject) returned %x", hres);
  2572. _OnBound(hres);
  2573. return hres;
  2574. }
  2575. void CDocObjectHost::_OnBound(HRESULT hres)
  2576. {
  2577. if (SUCCEEDED(hres)) {
  2578. _PostBindAppHack();
  2579. _InitOleObject();
  2580. }
  2581. }
  2582. //
  2583. // This function returns TRUE if the specified file's open command is
  2584. // associated with "explorer.exe" or "iexplore.exe".
  2585. //
  2586. // NOTES: It does not check if the "open" command is actually the default
  2587. // or not, but that's sufficient in 99.99 cases.
  2588. //
  2589. BOOL IsAssociatedWithIE(LPCWSTR szPath)
  2590. {
  2591. LPCTSTR pszExtension = PathFindExtension(szPath);
  2592. BOOL bRet = FALSE;
  2593. TCHAR szBuf[MAX_PATH];
  2594. TCHAR szExt[_MAX_EXT];
  2595. DWORD cchBuf = ARRAYSIZE(szBuf);
  2596. if (SUCCEEDED(AssocQueryString(0, ASSOCSTR_COMMAND, szExt, TEXT("open"), szBuf, &cchBuf)))
  2597. {
  2598. TraceMsg(TF_SHDBINDING, "IsAssociatedWithIE(%s) found %s as open command", szPath, szBuf);
  2599. LPCTSTR pszFound;
  2600. if ( (pszFound=StrStrI(szBuf, IEXPLORE_EXE))
  2601. || (pszFound=StrStrI(szBuf, EXPLORER_EXE)) )
  2602. {
  2603. if (pszFound==szBuf || *(pszFound - 1)==TEXT('\\'))
  2604. {
  2605. bRet = TRUE;
  2606. }
  2607. }
  2608. }
  2609. TraceMsg(DM_SELFASC, "IsAssociatedWithIE(%s) returning %d", szPath, bRet);
  2610. return bRet;
  2611. }
  2612. HRESULT CDocObjectHost::_MayHaveVirus(REFCLSID rclsid)
  2613. {
  2614. //
  2615. // We'll call this function twice if the file is associated
  2616. // with a bogus CLSID (such as ImageComposer).
  2617. //
  2618. if (_fConfirmed)
  2619. {
  2620. TraceMsg(TF_SHDAPPHACK, "CDOH::_MayHaveVirus called twice. Return S_OK");
  2621. return S_OK;
  2622. }
  2623. TraceMsg(TF_SHDPROGRESS, "DOH::_MayHaveVirus called");
  2624. LPWSTR pwzProgID = NULL;
  2625. HRESULT hresT = E_FAIL;
  2626. if (SUCCEEDED(ProgIDFromCLSID(rclsid, &pwzProgID)))
  2627. {
  2628. if ( StrCmpI(pwzProgID, TEXT("htmlfile")) != 0
  2629. && StrCmpI(pwzProgID, TEXT("htmlfile_FullWindowEmbed")) != 0
  2630. && StrCmpI(pwzProgID, TEXT("mhtmlfile")) != 0
  2631. && StrCmpI(pwzProgID, TEXT("xmlfile")) != 0
  2632. && StrCmpI(pwzProgID, TEXT("xslfile")) != 0)
  2633. {
  2634. TCHAR szURL[MAX_URL_STRING];
  2635. TCHAR * pszURL = szURL;
  2636. hresT = _GetCurrentPage(szURL, ARRAYSIZE(szURL), TRUE);
  2637. if (SUCCEEDED(hresT))
  2638. {
  2639. UINT uRet = IDOK;
  2640. if (_PicsProcBase._fbPicsWaitFlags || !_PicsProcBase._fPicsAccessAllowed)
  2641. {
  2642. _PicsProcBase._fbPicsWaitFlags &= ~(PICS_WAIT_FOR_INDOC | PICS_WAIT_FOR_END); /* indoc ratings only on htmlfile */
  2643. TraceMsg(DM_PICS, "CDOH::_MayHaveVirus found non-HTML, waitflags now %x", (DWORD)_PicsProcBase._fbPicsWaitFlags);
  2644. uRet = _PicsProcBase._PicsBlockingDialog();
  2645. }
  2646. if (uRet == IDOK)
  2647. {
  2648. TraceMsg(TF_SHDPROGRESS, "DOH::_MayHaveVirus calling MayOpenSafeDialogOpenDialog(%s)", pwzProgID);
  2649. if (_bsc._pszRedirectedURL && *_bsc._pszRedirectedURL)
  2650. pszURL = _bsc._pszRedirectedURL;
  2651. IUnknown * punk;
  2652. BOOL fDisableOpen = TRUE;
  2653. LPCTSTR pszExt = NULL;
  2654. if (_bsc._pszCacheFileName)
  2655. pszExt = PathFindExtension(_bsc._pszCacheFileName);
  2656. else if (pszURL)
  2657. pszExt = PathFindExtension(pszURL);
  2658. if (pszExt)
  2659. {
  2660. TCHAR szClassName[MAX_PATH];
  2661. DWORD cbSize = SIZEOF(szClassName);
  2662. // if the ProgIDs don't match then disable the open button
  2663. if (ERROR_SUCCESS == SHGetValue(HKEY_CLASSES_ROOT, pszExt, NULL, NULL, szClassName, &cbSize))
  2664. fDisableOpen = StrCmpI(pwzProgID, szClassName);
  2665. }
  2666. QueryInterface(IID_IUnknown, (void**)&punk);
  2667. uRet = MayOpenSafeOpenDialog(_hwnd, pwzProgID, pszURL, _bsc._pszCacheFileName, NULL, _uiCP, punk, _pmsoctBrowser, fDisableOpen);
  2668. ATOMICRELEASE(punk);
  2669. _fCalledMayOpenSafeDlg = TRUE;
  2670. }
  2671. switch(uRet)
  2672. {
  2673. case IDIGNORE:
  2674. //
  2675. // allow the safeopen dlg to pop up later if necessary
  2676. //
  2677. _fCalledMayOpenSafeDlg = FALSE;
  2678. _fConfirmed = FALSE;
  2679. break; // continue download
  2680. case IDOK:
  2681. //
  2682. // Set this flag to avoid poppping this dialog box twice.
  2683. //
  2684. _fConfirmed = TRUE;
  2685. break; // continue download
  2686. case IDD_SAVEAS:
  2687. IUnknown *punk;
  2688. hresT = QueryInterface(IID_IUnknown, (void**)&punk);
  2689. if(SUCCEEDED(hresT))
  2690. {
  2691. CDownLoad_OpenUI(_pmkCur, _bsc._pbc, FALSE, TRUE, NULL, NULL, NULL, NULL, NULL, _bsc._pszRedirectedURL, _uiCP, punk);
  2692. punk->Release();
  2693. }
  2694. // fall through to abort binding.
  2695. case IDCANCEL:
  2696. hresT = HRESULT_FROM_WIN32(ERROR_CANCELLED);
  2697. break;
  2698. }
  2699. }
  2700. else
  2701. {
  2702. TraceMsg(DM_ERROR, "DOH::_MayHaveVirus _GetCurrentPage failed %x", hresT);
  2703. }
  2704. }
  2705. else
  2706. {
  2707. TraceMsg(TF_SHDPROGRESS, "DOH::_MayHaveVirus this is htmlfile -- don't call MayOpenSafeDialogOpenDialog");
  2708. _fPicsBlockLate = TRUE;
  2709. }
  2710. OleFree(pwzProgID);
  2711. }
  2712. return hresT;
  2713. }
  2714. STDMETHODIMP CDocObjectHost::SaveObject(void)
  2715. {
  2716. TraceMsg(0, "sdv TR: CDOV::SaveObject called");
  2717. // Implemente it later.
  2718. return S_OK;
  2719. }
  2720. STDMETHODIMP CDocObjectHost::GetMoniker(DWORD dwAssign,
  2721. DWORD dwWhichMoniker,
  2722. IMoniker **ppmk)
  2723. {
  2724. HRESULT hres = E_INVALIDARG;
  2725. *ppmk = NULL;
  2726. TraceMsg(TF_SHDBINDING, "CDOH::GetMoniker called dwWhichMoniker=%x", dwWhichMoniker);
  2727. switch(dwWhichMoniker)
  2728. {
  2729. case OLEWHICHMK_OBJREL:
  2730. case OLEWHICHMK_OBJFULL:
  2731. if (_pmkCur)
  2732. {
  2733. *ppmk = _pmkCur;
  2734. _pmkCur->AddRef();
  2735. hres = S_OK;
  2736. }
  2737. else
  2738. {
  2739. hres = E_UNEXPECTED;
  2740. }
  2741. break;
  2742. }
  2743. return hres;
  2744. }
  2745. STDMETHODIMP CDocObjectHost::GetContainer(
  2746. IOleContainer **ppContainer)
  2747. {
  2748. // According to CKindel, we should implement this method
  2749. // as the way for a DocObject to access IDispatch interface of
  2750. // the container (i.e., frame). I'm currently thinking leaving
  2751. // all it's non-IUnknown memeber unimplemented. If there is no
  2752. // need to enumerates objects, we can simply QI from IShellBrowser
  2753. // to IOleContainer and return it. (SatoNa)
  2754. //
  2755. // NOTE: If trident calls this after DestroyHostWindow, we have nothing
  2756. // to give out. Hopefully this is not bad. (MikeSh)
  2757. TraceMsg(0, "sdv TR: CDOV::GetContainer called");
  2758. if (_psb)
  2759. return _psb->QueryInterface(IID_IOleContainer, (void **)ppContainer);
  2760. return E_FAIL;
  2761. }
  2762. STDMETHODIMP CDocObjectHost::ShowObject(void)
  2763. {
  2764. TraceMsg(0, "sdv TR: CDOV::ShowObject called");
  2765. return E_NOTIMPL; // As specified in Kraig's document
  2766. }
  2767. STDMETHODIMP CDocObjectHost::OnShowWindow(BOOL fShow)
  2768. {
  2769. TraceMsg(TF_SHDUIACTIVATE, "DOH::OnShowWindow(%d) called (this=%x)", fShow, this);
  2770. return E_NOTIMPL; // As specified in Kraig's document
  2771. }
  2772. STDMETHODIMP CDocObjectHost::RequestNewObjectLayout(void)
  2773. {
  2774. TraceMsg(0, "sdv TR: CDOV::RequestNewObjectLayout called");
  2775. return E_NOTIMPL; // As specified in Kraig's document
  2776. }
  2777. //
  2778. // This is the standard way for non-active embedding to access
  2779. // the IHlinkFrame interface. We happened to use our QI to implement
  2780. // this, but the semantics of QueryService is different from QI.
  2781. // It does not necessary return the same object.
  2782. //
  2783. HRESULT CDocObjectHost::QueryService(REFGUID guidService, REFIID riid, void **ppvObj)
  2784. {
  2785. if( IsEqualGUID(guidService, IID_IElementNamespaceTable) )
  2786. {
  2787. return IUnknown_QueryService(_pole, IID_IElementNamespaceTable, riid, ppvObj);
  2788. }
  2789. // In order for the context menu to work correctly inside IFrames, we
  2790. // need to fail a certain query ONLY for IFrames on desktop.
  2791. else if (!IsEqualGUID(guidService, CLSID_HTMLDocument) || !_IsImmediateParentDesktop(this, _psp))
  2792. {
  2793. //
  2794. // Delegate ISP to the _psb.
  2795. //
  2796. if (_psb && _psp)
  2797. return _psp->QueryService(guidService, riid, ppvObj);
  2798. }
  2799. *ppvObj = NULL;
  2800. return E_NOINTERFACE;
  2801. }
  2802. /*----------------------------------------------------------
  2803. Purpose: Remove the submenu(s) that are in _hmenuFrame
  2804. from _hmenuBrowser.
  2805. */
  2806. void CDocObjectHost::_RemoveFrameSubMenus(void)
  2807. {
  2808. HMENU hmenu;
  2809. ASSERT(IS_VALID_HANDLE(_hmenuBrowser, MENU));
  2810. ASSERT(IS_VALID_HANDLE(_hmenuFrame, MENU));
  2811. // The file menu in _hmenuBrowser consists of the file menu from
  2812. // _hmenuFrame and IShellBrowser. The part added by _hmenuFrame
  2813. // includes a submenu (Send To), which must be removed before
  2814. // _hmenuBrowser is destroyed.
  2815. // We could just explicitly remove the Send To submenu. But to
  2816. // prevent the expensive bug hunt that it took to find this in the
  2817. // first place, we're going to iterate thru the menu and, for
  2818. // any submenus that belong to our template, we'll remove them.
  2819. int citemFile = 0;
  2820. UINT nID = 0;
  2821. // Get the count of menu items in our template's File menu and
  2822. // the ID of the first menu item.
  2823. hmenu = GetMenuFromID(_hmenuFrame, FCIDM_MENU_FILE);
  2824. if (hmenu)
  2825. {
  2826. citemFile = GetMenuItemCount(hmenu);
  2827. nID = GetMenuItemID(hmenu, 0);
  2828. }
  2829. // Now look at the browser menu's File menu and, starting at
  2830. // nID, remove any submenus.
  2831. hmenu = GetMenuFromID(_hmenuBrowser, FCIDM_MENU_FILE);
  2832. if (hmenu)
  2833. {
  2834. int citem = GetMenuItemCount(hmenu);
  2835. int iTop;
  2836. int i;
  2837. // Where does our template file menu start?
  2838. for (iTop = 0; iTop < citem; iTop++)
  2839. {
  2840. if (GetMenuItemID(hmenu, iTop) == nID)
  2841. {
  2842. // Start at where our template file menu ends and work up
  2843. for (i = iTop + citemFile - 1; 0 < citemFile ; i--, citemFile--)
  2844. {
  2845. HMENU hmenuSub = GetSubMenu(hmenu, i);
  2846. if (hmenuSub)
  2847. RemoveMenu(hmenu, i, MF_BYPOSITION);
  2848. }
  2849. break;
  2850. }
  2851. }
  2852. }
  2853. }
  2854. /*----------------------------------------------------------
  2855. Purpose: Destroy the browser menu.
  2856. */
  2857. HRESULT CDocObjectHost::_DestroyBrowserMenu(void)
  2858. {
  2859. TraceMsg(TF_SHDUIACTIVATE, "DOH::_DestroyBrowserMenu called");
  2860. if (_hmenuBrowser) {
  2861. // First remove any submenus that are held by other menus,
  2862. // so we don't blow them away.
  2863. _RemoveFrameSubMenus();
  2864. if (EVAL(_psb)) {
  2865. _psb->RemoveMenusSB(_hmenuBrowser);
  2866. }
  2867. DestroyMenu(_hmenuBrowser);
  2868. _hmenuBrowser = NULL;
  2869. }
  2870. return S_OK;
  2871. }
  2872. HRESULT CDocObjectHost::_CreateBrowserMenu(LPOLEMENUGROUPWIDTHS pmw)
  2873. {
  2874. TraceMsg(TF_SHDUIACTIVATE, "DOH::_CreateBrowserMenu called");
  2875. if (_hmenuBrowser) {
  2876. return S_OK;
  2877. }
  2878. _hmenuBrowser = CreateMenu();
  2879. if (!_hmenuBrowser) {
  2880. return E_OUTOFMEMORY;
  2881. }
  2882. HRESULT hres = E_FAIL;
  2883. // Allow IShellBrowser a chance to add its menus
  2884. if (EVAL(_psb))
  2885. hres = _psb->InsertMenusSB(_hmenuBrowser, pmw);
  2886. // HACK: Win95 explorer returns E_NOTIMPL
  2887. if (hres==E_NOTIMPL) {
  2888. hres = S_OK;
  2889. }
  2890. if (SUCCEEDED(hres)) {
  2891. // Load our menu if not loaded yet
  2892. if (!_hmenuFrame)
  2893. {
  2894. _hmenuFrame = LoadMenu(MLGetHinst(), MAKEINTRESOURCE(MID_FOCUS));
  2895. }
  2896. // Get the "File" sub-menu from the shell browser.
  2897. MENUITEMINFO mii;
  2898. mii.cbSize = sizeof(mii);
  2899. mii.fMask = MIIM_SUBMENU;
  2900. if (GetMenuItemInfo(_hmenuBrowser, FCIDM_MENU_FILE, FALSE, &mii))
  2901. {
  2902. HMENU hmenuFileBrowse = mii.hSubMenu;
  2903. // Merge our menuitems into this submenu.
  2904. if (_hmenuFrame)
  2905. {
  2906. MENUITEMINFO miiItem;
  2907. miiItem.cbSize = SIZEOF(MENUITEMINFO);
  2908. miiItem.fMask = MIIM_SUBMENU;
  2909. if (GetMenuItemInfo(_hmenuFrame, FCIDM_MENU_FILE, FALSE, &miiItem))
  2910. {
  2911. TCHAR szItem[128];
  2912. HMENU hmenuFileT = miiItem.hSubMenu;
  2913. UINT citem = GetMenuItemCount(hmenuFileT);
  2914. for (int i=citem-1; i>=0 ; i--)
  2915. {
  2916. // We need to reset for each item.
  2917. miiItem.fMask = MIIM_STATE | MIIM_ID | MIIM_SUBMENU | MIIM_CHECKMARKS | MIIM_TYPE | MIIM_DATA;
  2918. miiItem.fType = MFT_STRING;
  2919. miiItem.cch = ARRAYSIZE(szItem);
  2920. miiItem.dwTypeData = szItem;
  2921. miiItem.dwItemData = 0;
  2922. if (GetMenuItemInfo(hmenuFileT, i, TRUE, &miiItem)) {
  2923. InsertMenuItem(hmenuFileBrowse, 0, TRUE, &miiItem);
  2924. }
  2925. }
  2926. }
  2927. }
  2928. }
  2929. else
  2930. {
  2931. TraceMsg(TF_SHDUIACTIVATE, "DOH::_CreateBrowseMenu parent has no File menu (it's probably a browser OC)");
  2932. ASSERT(0); // DocObject in OC is not supposed to call InsertMenus.
  2933. }
  2934. }
  2935. DEBUG_CODE( _DumpMenus(TEXT("after _CreateBrowserMenu"), TRUE); )
  2936. return hres;
  2937. }
  2938. //
  2939. // IOleInPlaceFrame::InsertMenus equivalent
  2940. //
  2941. HRESULT CDocObjectHost::_InsertMenus(
  2942. /* [in] */ HMENU hmenuShared,
  2943. /* [out][in] */ LPOLEMENUGROUPWIDTHS lpMenuWidths)
  2944. {
  2945. HRESULT hres = S_OK;
  2946. int nMenuOffset = 0;
  2947. TraceMsg(TF_SHDUIACTIVATE, "DOH::InsertMenus called (this=%x)", this);
  2948. // Assume error (no menu merge)
  2949. lpMenuWidths->width[0] = 0;
  2950. lpMenuWidths->width[2] = 0;
  2951. lpMenuWidths->width[4] = 0;
  2952. lpMenuWidths->width[5] = 0;
  2953. // be extra safe and don't attempt menu merging if we're not top level
  2954. if (_fHaveParentSite)
  2955. return S_OK;
  2956. OLEMENUGROUPWIDTHS mw = { {0} };
  2957. hres = _CreateBrowserMenu(&mw);
  2958. if (FAILED(hres)) {
  2959. TraceMsg(DM_ERROR, "DOH::InsertMenus _CreateBrpwserMenu failed");
  2960. return hres;
  2961. }
  2962. // Get the "File" sub-menu from the shell browser.
  2963. MENUITEMINFO mii;
  2964. TCHAR szSubMenu[128];
  2965. mii.cbSize = SIZEOF(mii);
  2966. mii.fMask = MIIM_SUBMENU|MIIM_TYPE|MIIM_ID;
  2967. mii.cch = ARRAYSIZE(szSubMenu);
  2968. mii.dwTypeData = szSubMenu;
  2969. if (EVAL(GetMenuItemInfo(_hmenuBrowser, FCIDM_MENU_FILE, FALSE, &mii)))
  2970. {
  2971. ASSERT(szSubMenu == mii.dwTypeData);
  2972. InsertMenuItem(hmenuShared, nMenuOffset++, TRUE, &mii);
  2973. lpMenuWidths->width[0] = 1;
  2974. }
  2975. // Note that we need to re-initialize mii
  2976. mii.cch = ARRAYSIZE(szSubMenu);
  2977. if (EVAL(GetMenuItemInfo(_hmenuBrowser, FCIDM_MENU_EXPLORE, FALSE, &mii)))
  2978. {
  2979. // GetMenuItemInfo is recursive (why?). The item it retrieves
  2980. // for FCIDM_MENU_EXPLORE can either be the top level Go menu, or if that
  2981. // does not exist (NT5 case), it returns the Go To submenu of View.
  2982. //
  2983. // Code has been added in in the SetMenu implementations of Shell Browser
  2984. // and Dochost to detect the second case, because the menu dispatch list
  2985. // does not recognize this kind of menu merging (80734).
  2986. DeleteMenu(mii.hSubMenu, FCIDM_PREVIOUSFOLDER, MF_BYCOMMAND);
  2987. InsertMenuItem(hmenuShared, nMenuOffset++, TRUE, &mii);
  2988. lpMenuWidths->width[4]++;
  2989. }
  2990. mii.cch = ARRAYSIZE(szSubMenu);
  2991. if (EVAL(GetMenuItemInfo(_hmenuBrowser, FCIDM_MENU_FAVORITES, FALSE, &mii)))
  2992. {
  2993. InsertMenuItem(hmenuShared, nMenuOffset++, TRUE, &mii);
  2994. lpMenuWidths->width[4]++;
  2995. }
  2996. if (_hmenuFrame)
  2997. {
  2998. // Micro-merge the help menu.
  2999. mii.cch = ARRAYSIZE(szSubMenu);
  3000. if (EVAL(GetMenuItemInfo(_hmenuFrame, FCIDM_MENU_HELP, FALSE, &mii)))
  3001. {
  3002. InsertMenuItem(hmenuShared, nMenuOffset++, TRUE, &mii);
  3003. lpMenuWidths->width[5]++;
  3004. }
  3005. }
  3006. DEBUG_CODE( _DumpMenus(TEXT("after InsertMenus"), TRUE); )
  3007. return hres;
  3008. }
  3009. /*----------------------------------------------------------
  3010. Purpose: Different objects may add their own Help menu (like
  3011. Word and Excel). This function detects if the object
  3012. added its own help menu, or if it added items to our
  3013. help menu, or if it is just using our help menu.
  3014. If they added their own help menu, we remove ours.
  3015. */
  3016. void CDocObjectHost::_CompleteHelpMenuMerge(HMENU hmenu)
  3017. {
  3018. HMENU hmenuHelp;
  3019. MENUITEMINFO mii;
  3020. TCHAR szSubMenu[80];
  3021. mii.cbSize = SIZEOF(mii);
  3022. mii.fMask = MIIM_SUBMENU;
  3023. // see if they added anything to our menu
  3024. if (GetMenuItemInfo(_hmenuFrame, FCIDM_MENU_HELP, FALSE, &mii))
  3025. {
  3026. hmenuHelp = mii.hSubMenu;
  3027. int iMenuCount = GetMenuItemCount(mii.hSubMenu);
  3028. // Did the number of items in the help menu change?
  3029. if (iMenuCount != HELP_ITEM_COUNT) {
  3030. // Yes; that means they added something. This has been micro-merged.
  3031. _hmenuMergedHelp = mii.hSubMenu;
  3032. _hmenuObjHelp = GetSubMenu(mii.hSubMenu, iMenuCount -1);
  3033. goto Bail;
  3034. }
  3035. // Our menu didn't change. Now find out if they added their own
  3036. // help menu or if we ARE the help. If they added their own, we need
  3037. // to remove our help menu.
  3038. _hmenuMergedHelp = NULL;
  3039. _hmenuObjHelp = NULL;
  3040. int iCount = GetMenuItemCount(hmenu) - 1;
  3041. int i;
  3042. for (i = iCount ; i >= 0 ; i--) {
  3043. mii.fMask = MIIM_SUBMENU|MIIM_TYPE;
  3044. mii.cch = ARRAYSIZE(szSubMenu);
  3045. mii.dwTypeData = szSubMenu;
  3046. if (GetMenuItemInfo(hmenu, i, TRUE, &mii)) {
  3047. if (mii.hSubMenu == hmenuHelp) {
  3048. BOOL bRemove = FALSE;
  3049. if (iCount != i) {
  3050. // if we're not the last one, then we're not it
  3051. bRemove = TRUE;
  3052. } else {
  3053. // if we are the last one see if the help menu was added
  3054. // right before us
  3055. TCHAR szMenuTitle[80];
  3056. mii.cch = ARRAYSIZE(szMenuTitle);
  3057. mii.dwTypeData = szMenuTitle;
  3058. if (GetMenuItemInfo(hmenu, i-1, TRUE, &mii)) {
  3059. if (!StrCmpI(szMenuTitle, szSubMenu)) {
  3060. // same menu string yank ours
  3061. bRemove = TRUE;
  3062. }
  3063. }
  3064. }
  3065. if (bRemove) {
  3066. RemoveMenu(hmenu, i, MF_BYPOSITION);
  3067. }
  3068. }
  3069. }
  3070. }
  3071. }
  3072. Bail:;
  3073. DEBUG_CODE( _DumpMenus(TEXT("after _CompleteHelpMenuMerge"), TRUE); )
  3074. }
  3075. //
  3076. // IOleInPlaceFrame::SetMenu equivalent
  3077. //
  3078. HRESULT CDocObjectHost::_SetMenu(
  3079. /* [in] */ HMENU hmenuShared, OPTIONAL
  3080. /* [in] */ HOLEMENU holemenu, OPTIONAL
  3081. /* [in] */ HWND hwndActiveObject)
  3082. {
  3083. TraceMsg(TF_SHDUIACTIVATE, "DOH::SetMenus(%x) called (this=%x)",
  3084. hmenuShared, this);
  3085. // be extra safe and don't attempt menu merging if we're not top level
  3086. if (_fHaveParentSite)
  3087. return S_OK;
  3088. // A NULL hmenuShared means to reinstate the container's original menu.
  3089. if (hmenuShared)
  3090. {
  3091. // Clean up duplicate help menus
  3092. _CompleteHelpMenuMerge(hmenuShared);
  3093. }
  3094. // Simply forwarding it to IShellBrowser
  3095. _hmenuSet = hmenuShared;
  3096. HRESULT hres = E_FAIL;
  3097. if (EVAL(_psb))
  3098. hres = _psb->SetMenuSB(hmenuShared, holemenu, hwndActiveObject);
  3099. if (SUCCEEDED(hres))
  3100. {
  3101. // need to tell the shell browser that we want doc obj style menu merging
  3102. if (_pmsoctBrowser)
  3103. _pmsoctBrowser->Exec(&CGID_Explorer, SBCMDID_ACTIVEOBJECTMENUS, 0, NULL, NULL);
  3104. // Compose our list of object/frame menus, so our menuband
  3105. // can dispatch the messages correctly. Essentially this is
  3106. // the same as the contents of holemenu, but since we don't
  3107. // have access to the internal struct, we must derive this
  3108. // info ourselves.
  3109. _menulist.Set(hmenuShared, _hmenuBrowser);
  3110. if (_hmenuMergedHelp)
  3111. _menulist.RemoveMenu(_hmenuMergedHelp);
  3112. if (_hmenuObjHelp)
  3113. _menulist.AddMenu(_hmenuObjHelp);
  3114. _hmenuCur = hmenuShared;
  3115. HWND hwndFrame;
  3116. _psb->GetWindow(&hwndFrame);
  3117. // 80734: Was the Go To menu taken from the View menu and grafted onto the
  3118. // main menu by DocHost? The menulist won't detect this graft, so we have
  3119. // to check ourselves and make sure it's not marked as belonging to the
  3120. // docobject.
  3121. //
  3122. // This test is duplicated in CShellBrowser2::SetMenuSB
  3123. MENUITEMINFO mii;
  3124. mii.cbSize = SIZEOF(mii);
  3125. mii.fMask = MIIM_SUBMENU;
  3126. if (hmenuShared && _hmenuBrowser &&
  3127. GetMenuItemInfo(hmenuShared, FCIDM_MENU_EXPLORE, FALSE, &mii))
  3128. {
  3129. HMENU hmenuGo = mii.hSubMenu;
  3130. if (GetMenuItemInfo(_hmenuBrowser, FCIDM_MENU_EXPLORE, FALSE, &mii) &&
  3131. mii.hSubMenu == hmenuGo && _menulist.IsObjectMenu(hmenuGo))
  3132. {
  3133. _menulist.RemoveMenu(hmenuGo);
  3134. }
  3135. }
  3136. // (scotth): why are we calling this, since this isn't compatible
  3137. // with menubands? That's the whole reason we have _menulist.
  3138. hres = OleSetMenuDescriptor(holemenu, hwndFrame, hwndActiveObject, &_dof, _ActiveObject());
  3139. }
  3140. DEBUG_CODE( _DumpMenus(TEXT("after SetMenu"), TRUE); )
  3141. return hres;
  3142. }
  3143. void CDocObjectHost::_SetStatusText(LPCSTR pszText)
  3144. {
  3145. if (_psb)
  3146. {
  3147. WPARAM wParam = STATUS_PANE_NAVIGATION;
  3148. if (g_bBiDiW95Loc && *pszText)
  3149. {
  3150. char szBuf[256];
  3151. szBuf[0] = szBuf[1] = TEXT('\t');
  3152. StrCpyNA(&szBuf[2], pszText, ARRAYSIZE(szBuf)-2);
  3153. pszText = szBuf;
  3154. wParam = SBT_RTLREADING;
  3155. }
  3156. _psb->SendControlMsg(FCW_STATUS, SB_SETTEXT, wParam | SBT_NOTABPARSING, (LPARAM)pszText, NULL);
  3157. _psb->SendControlMsg(FCW_STATUS, SB_SETTIPTEXT, wParam, (LPARAM)pszText, NULL);
  3158. }
  3159. }
  3160. /*----------------------------------------------------------
  3161. Purpose: Returns TRUE if the given menu belongs to the browser
  3162. (as opposed to the object)
  3163. */
  3164. BOOL CDocObjectHost::_IsMenuShared(HMENU hmenu)
  3165. {
  3166. ASSERT(hmenu);
  3167. // (scotth): can we use _menulist here? (it would be faster)
  3168. if (_hmenuBrowser) {
  3169. for (int i = GetMenuItemCount(_hmenuBrowser) - 1 ; i >= 0; i--) {
  3170. if (GetSubMenu(_hmenuBrowser, i) == hmenu)
  3171. return TRUE;
  3172. }
  3173. }
  3174. // We have to special case the help menu. It's possible that the
  3175. // help menu in the shared menu actually came from _hmenuFrame
  3176. // (not _hmenuBrowser). We need to detect this case, otherwise
  3177. // the help menu gets destroyed but it is still referenced in
  3178. // _hmenuFrame.
  3179. MENUITEMINFO mii;
  3180. mii.cbSize = SIZEOF(mii);
  3181. mii.fMask = MIIM_SUBMENU;
  3182. ASSERT(IS_VALID_HANDLE(_hmenuFrame, MENU));
  3183. // Is this our help menu from _hmenuFrame?
  3184. if (GetMenuItemInfo(_hmenuFrame, FCIDM_MENU_HELP, FALSE, &mii) &&
  3185. mii.hSubMenu == hmenu)
  3186. {
  3187. // Yes
  3188. return TRUE;
  3189. }
  3190. return FALSE;
  3191. }
  3192. //
  3193. // IOleInPlaceFrame::RemoveMenus equivalent
  3194. //
  3195. HRESULT CDocObjectHost::_RemoveMenus(/* [in] */ HMENU hmenuShared)
  3196. {
  3197. TraceMsg(TF_SHDUIACTIVATE, "DOH::RemoveMenus called (this=%x)", this);
  3198. // be extra safe and don't attempt menu merging if we're not top level
  3199. if (_fHaveParentSite)
  3200. return S_OK;
  3201. ASSERT(GetMenuItemCount(hmenuShared) != (UINT)-1);
  3202. //
  3203. // It is ok to simply remove sub-menus here.
  3204. // because ours are shared with the _hmenuBrowser
  3205. // and destroying that below will take care of cleanup.
  3206. // However, we need to only remove menus that are ours.
  3207. //
  3208. for (int i = (int)GetMenuItemCount(hmenuShared) - 1 ; i >= 0; i--)
  3209. {
  3210. // TraceMsg(0, "sdv TR - ::RemoveMenus calling RemoveMenu(0)");
  3211. HMENU hmenu = GetSubMenu(hmenuShared, i);
  3212. if (hmenu && _IsMenuShared(hmenu)) {
  3213. RemoveMenu(hmenuShared, i, MF_BYPOSITION);
  3214. }
  3215. }
  3216. // TraceMsg(0, "sdv TR - ::RemoveMenus exiting");
  3217. return S_OK;
  3218. }
  3219. //
  3220. // IOleInPlaceFrame::SetStatusText equivalent
  3221. //
  3222. HRESULT CDocObjectHost::_SetStatusText(/* [in] */ LPCOLESTR pszStatusText)
  3223. {
  3224. LPCOLESTR pszForward;
  3225. if (_psb != NULL)
  3226. {
  3227. // if it's NULL or just "" then give precedence to
  3228. // _strPriorityStatusText, otherwise we display
  3229. // whatever we're given
  3230. if (pszStatusText != NULL && pszStatusText[0] != TEXT('\0') ||
  3231. _strPriorityStatusText == NULL)
  3232. {
  3233. pszForward = pszStatusText;
  3234. }
  3235. else
  3236. {
  3237. pszForward = _strPriorityStatusText;
  3238. }
  3239. _psb->SetStatusTextSB(pszForward);
  3240. }
  3241. // Always return S_OK or scripting will put up an error dialog.
  3242. return S_OK;
  3243. }
  3244. void CDocObjectHost::_SetPriorityStatusText(LPCOLESTR pszPriorityStatusText)
  3245. {
  3246. // if they gave us a new string, replace the old one,
  3247. // otherwise just NULL out the old one
  3248. if (_strPriorityStatusText != NULL)
  3249. {
  3250. SysFreeString(_strPriorityStatusText);
  3251. }
  3252. if (pszPriorityStatusText != NULL)
  3253. {
  3254. _strPriorityStatusText = SysAllocString(pszPriorityStatusText);
  3255. }
  3256. else
  3257. {
  3258. _strPriorityStatusText = NULL;
  3259. }
  3260. _SetStatusText(_strPriorityStatusText);
  3261. }
  3262. HRESULT CDocObjectHost::_EnableModeless(/* [in] */ BOOL fEnable)
  3263. {
  3264. TraceMsg(0, "sdv TR - ::EnableModeless called");
  3265. // Note that we used call _CancelPendingNavigation here.
  3266. // We do it in CBaseBrowser:::EnableModelesSB intead. (Satona)
  3267. // Simply forwarding it (which is not implemented)
  3268. if (EVAL(_psb))
  3269. return _psb->EnableModelessSB(fEnable);
  3270. return E_FAIL;
  3271. }
  3272. HRESULT CDocObjectHost::TranslateHostAccelerators(LPMSG lpmsg)
  3273. {
  3274. if (_hacc && ::TranslateAccelerator(_hwnd, _hacc, lpmsg)) {
  3275. return S_OK;
  3276. }
  3277. return S_FALSE;
  3278. }
  3279. // IOleInPlaceFrame equivalent ::TranslateAccelerator
  3280. // Forwarding it from DocObject -> Browser
  3281. HRESULT CDocObjectHost::_TranslateAccelerator(
  3282. /* [in] */ LPMSG lpmsg,
  3283. /* [in] */ WORD wID)
  3284. {
  3285. // TranslateAccelerator goes to the guy with the focus first
  3286. if (EVAL(_psb))
  3287. if (S_OK == _psb->TranslateAcceleratorSB(lpmsg, wID))
  3288. return S_OK;
  3289. #ifdef DEBUG
  3290. if (lpmsg->message == WM_KEYDOWN) {
  3291. TraceMsg(0, "CDocObjectHost::TrAcc(UP) called");
  3292. }
  3293. #endif
  3294. return TranslateHostAccelerators(lpmsg);
  3295. }
  3296. // IViewObject
  3297. HRESULT CDocObjectHost::Draw(DWORD dwDrawAspect, LONG lindex, void *pvAspect,
  3298. DVTARGETDEVICE *ptd, HDC hicTargetDev, HDC hdcDraw,
  3299. const RECTL *lprcBounds, const RECTL *lprcWBounds,
  3300. BOOL (*pfnContinue)(ULONG_PTR), ULONG_PTR dwContinue)
  3301. {
  3302. if (_pvo && lprcBounds)
  3303. {
  3304. if (_uState == SVUIA_DEACTIVATE && _hwnd)
  3305. {
  3306. HRESULT hresT = S_OK;
  3307. RECT rcClient;
  3308. GetClientRect(_hwnd, &rcClient);
  3309. //
  3310. // We should not call SetExtent with an empty rectangle.
  3311. // It happens when we print a page with a floating frame.
  3312. //
  3313. if (rcClient.right > 0 && rcClient.bottom > 0)
  3314. {
  3315. SIZEL sizel;
  3316. sizel.cx = MulDiv( rcClient.right, 2540, GetDeviceCaps( hdcDraw, LOGPIXELSX ) );
  3317. sizel.cy = MulDiv( rcClient.bottom, 2540, GetDeviceCaps( hdcDraw, LOGPIXELSY ) );
  3318. hresT = _pole->SetExtent(DVASPECT_CONTENT, &sizel);
  3319. }
  3320. #ifdef DEBUG
  3321. MoveToEx(hdcDraw, lprcBounds->left, lprcBounds->top, NULL);
  3322. LineTo(hdcDraw, lprcBounds->right, lprcBounds->bottom);
  3323. LineTo(hdcDraw, lprcBounds->left, lprcBounds->bottom);
  3324. LineTo(hdcDraw, lprcBounds->right, lprcBounds->top);
  3325. #endif
  3326. if (hresT!=S_OK) {
  3327. TraceMsg(DM_ERROR, "CDOH::Draw SetExtent returns non S_OK %x", hresT);
  3328. }
  3329. }
  3330. return _pvo->Draw(dwDrawAspect, lindex, pvAspect, ptd, hicTargetDev,
  3331. hdcDraw, lprcBounds, lprcWBounds, pfnContinue, dwContinue);
  3332. }
  3333. return OLE_E_BLANK;
  3334. }
  3335. HRESULT CDocObjectHost::GetColorSet(DWORD dwAspect, LONG lindex,
  3336. void *pvAspect, DVTARGETDEVICE *ptd, HDC hicTargetDev,
  3337. LOGPALETTE **ppColorSet)
  3338. {
  3339. if (_pvo)
  3340. {
  3341. return _pvo->GetColorSet(dwAspect, lindex, pvAspect, ptd, hicTargetDev,
  3342. ppColorSet);
  3343. }
  3344. if (ppColorSet)
  3345. *ppColorSet = NULL;
  3346. return S_FALSE;
  3347. }
  3348. HRESULT CDocObjectHost::Freeze(DWORD, LONG, void *, DWORD *pdwFreeze)
  3349. {
  3350. if (pdwFreeze)
  3351. *pdwFreeze = 0;
  3352. return E_NOTIMPL;
  3353. }
  3354. HRESULT CDocObjectHost::Unfreeze(DWORD)
  3355. {
  3356. return E_NOTIMPL;
  3357. }
  3358. HRESULT CDocObjectHost::SetAdvise(DWORD dwAspect, DWORD advf,
  3359. IAdviseSink *pSink)
  3360. {
  3361. if (dwAspect != DVASPECT_CONTENT)
  3362. return DV_E_DVASPECT;
  3363. if (advf & ~(ADVF_PRIMEFIRST | ADVF_ONLYONCE))
  3364. return E_INVALIDARG;
  3365. if (pSink != _padvise)
  3366. {
  3367. ATOMICRELEASE(_padvise);
  3368. _padvise = pSink;
  3369. if (_padvise)
  3370. _padvise->AddRef();
  3371. }
  3372. if (_padvise)
  3373. {
  3374. _advise_aspect = dwAspect;
  3375. _advise_advf = advf;
  3376. if (advf & ADVF_PRIMEFIRST)
  3377. OnViewChange(_advise_aspect, -1);
  3378. }
  3379. else
  3380. _advise_aspect = _advise_advf = 0;
  3381. return S_OK;
  3382. }
  3383. HRESULT CDocObjectHost::GetAdvise(DWORD *pdwAspect, DWORD *padvf,
  3384. IAdviseSink **ppSink)
  3385. {
  3386. if (pdwAspect)
  3387. *pdwAspect = _advise_aspect;
  3388. if (padvf)
  3389. *padvf = _advise_advf;
  3390. if (ppSink)
  3391. {
  3392. if (_padvise)
  3393. _padvise->AddRef();
  3394. *ppSink = _padvise;
  3395. }
  3396. return S_OK;
  3397. }
  3398. // IAdviseSink
  3399. void CDocObjectHost::OnDataChange(FORMATETC *, STGMEDIUM *)
  3400. {
  3401. }
  3402. void CDocObjectHost::OnViewChange(DWORD dwAspect, LONG lindex)
  3403. {
  3404. dwAspect &= _advise_aspect;
  3405. if (dwAspect && _padvise)
  3406. {
  3407. IAdviseSink *pSink = _padvise;
  3408. IUnknown *punkRelease;
  3409. if (_advise_advf & ADVF_ONLYONCE)
  3410. {
  3411. punkRelease = pSink;
  3412. _padvise = NULL;
  3413. _advise_aspect = _advise_advf = 0;
  3414. }
  3415. else
  3416. punkRelease = NULL;
  3417. pSink->OnViewChange(dwAspect, lindex);
  3418. if (punkRelease)
  3419. punkRelease->Release();
  3420. }
  3421. }
  3422. void CDocObjectHost::OnRename(IMoniker *)
  3423. {
  3424. }
  3425. void CDocObjectHost::OnSave()
  3426. {
  3427. }
  3428. void CDocObjectHost::OnClose()
  3429. {
  3430. //
  3431. // the doc object below went away so tell our advisee something changed
  3432. //
  3433. if (_padvise)
  3434. OnViewChange(_advise_aspect, -1);
  3435. }
  3436. // IOleWindow
  3437. HRESULT CDocObjectHost::GetWindow(HWND * lphwnd)
  3438. {
  3439. *lphwnd = _hwnd;
  3440. return S_OK;
  3441. }
  3442. HRESULT CDocObjectHost::ContextSensitiveHelp(BOOL fEnterMode)
  3443. {
  3444. // NOTES: This is optional
  3445. return E_NOTIMPL; // As specified in Kraig's document (optional)
  3446. }
  3447. // IOleInPlaceSite
  3448. HRESULT CDocObjectHost::CanInPlaceActivate(void)
  3449. {
  3450. OIPSMSG(TEXT("CanInPlaceActivate called"));
  3451. return S_OK;
  3452. }
  3453. HRESULT CDocObjectHost::OnInPlaceActivate(void)
  3454. {
  3455. OIPSMSG(TEXT("OnInPlaceActivate called"));
  3456. return S_OK;
  3457. }
  3458. HRESULT CDocObjectHost::OnUIActivate( void)
  3459. {
  3460. TraceMsg(TF_SHDUIACTIVATE, "-----------------------------------");
  3461. TraceMsg(TF_SHDUIACTIVATE, "OH::OnUIActivate called (this=%x)", this);
  3462. //
  3463. // Hide Office toolbars early enough so that it won't flash.
  3464. //
  3465. _HideOfficeToolbars();
  3466. // REVIEW:
  3467. // Should we remove 'our' menu here instead?
  3468. //
  3469. // [Copied from OLE 2.01 Spec]
  3470. // The container should remove any UI associated with its own
  3471. // activation. This is significant if the container is itself
  3472. // an embedded object.
  3473. //
  3474. OIPSMSG(TEXT("OnUIActivate called"));
  3475. if (EVAL(_psb))
  3476. {
  3477. // If we had the DocObject in SVUIA_INPLACEACTIVATE send it to SVUIA_ACTIVATE_FOCUS
  3478. //
  3479. // NOTES: Unlike IE3.0, we don't call _psv->UIActivate which has a side
  3480. // effect. We just update the _uState.
  3481. //
  3482. // _psv->UIActivate(SVUIA_ACTIVATE_FOCUS);
  3483. //
  3484. _uState = SVUIA_ACTIVATE_FOCUS;
  3485. return _psb->OnViewWindowActive(_psv);
  3486. }
  3487. return E_FAIL;
  3488. }
  3489. void CDocObjectHost::_GetClipRect(RECT* prc)
  3490. {
  3491. GetClientRect(_hwnd, prc);
  3492. prc->right -= _bwTools.right;
  3493. prc->bottom -= _bwTools.bottom;
  3494. }
  3495. IOleInPlaceSite* CDocObjectHost::_GetParentSite()
  3496. {
  3497. IOleInPlaceSite* pparentsite = NULL; // the parent's inplace site
  3498. if (_pwb)
  3499. {
  3500. _pwb->GetParentSite(&pparentsite);
  3501. }
  3502. return pparentsite;
  3503. }
  3504. HRESULT CDocObjectHost::GetWindowContext(
  3505. /* [out] */ IOleInPlaceFrame **ppFrame,
  3506. /* [out] */ IOleInPlaceUIWindow **ppDoc,
  3507. /* [out] */ LPRECT lprcPosRect,
  3508. /* [out] */ LPRECT lprcClipRect,
  3509. /* [out][in] */ LPOLEINPLACEFRAMEINFO lpFrameInfo)
  3510. {
  3511. OIPSMSG(TEXT("GetWindowContext called"));
  3512. // Todo: verify that lpFrameInfo->cb is the correct size!
  3513. // TraceMsg(0, "sdv TR - ::GetWindowContext called with lpFI->cb=%d (%d)",
  3514. // lpFrameInfo->cb, sizeof(*lpFrameInfo));
  3515. *ppFrame = &_dof; AddRef();
  3516. *ppDoc = NULL; // indicating that doc window == frame window
  3517. _GetClipRect(lprcClipRect);
  3518. lpFrameInfo->fMDIApp = FALSE;
  3519. //
  3520. // If the frame has IOleInPlaceUIWindow (both IE and Shell have),
  3521. // return that hwnd as hwndFrame so that OLE's menu dispatching
  3522. // code works correctly.
  3523. //
  3524. _dof.GetWindow(&lpFrameInfo->hwndFrame);
  3525. //
  3526. // We need to find out (from SriniK or KraigB), what is the
  3527. // implecation of this accelerator. Dealing with Word, it seems that
  3528. // Word does not call our TranslateAccelerator at all, unless the key
  3529. // stroke is the accelerator. If that's the spec. (of DocObject),
  3530. // there is no way to process the accelerator of the browser.
  3531. //
  3532. lpFrameInfo->haccel = _hacc;
  3533. if (!SHRestricted(REST_NOFILEMENU))
  3534. {
  3535. #ifdef DEBUG
  3536. lpFrameInfo->cAccelEntries = DBG_ACCELENTRIES_WITH_FILEMENU; // WARNING: see shdocvw.rc, ACCELL_DOCVIEW
  3537. #else
  3538. lpFrameInfo->cAccelEntries = OPT_ACCELENTRIES_WITH_FILEMENU; // WARNING: see shdocvw.rc, ACCELL_DOCVIEW
  3539. #endif
  3540. }
  3541. else
  3542. {
  3543. #ifdef DEBUG
  3544. lpFrameInfo->cAccelEntries = DBG_ACCELENTRIES; // WARNING: see shdocvw.rc, ACCELL_DOCVIEW
  3545. #else
  3546. lpFrameInfo->cAccelEntries = OPT_ACCELENTRIES; // WARNING: see shdocvw.rc, ACCELL_DOCVIEW
  3547. #endif
  3548. }
  3549. *lprcPosRect = _rcView;
  3550. return S_OK;
  3551. }
  3552. HRESULT CDocObjectHost::Scroll(
  3553. /* [in] */ SIZE scrollExtant)
  3554. {
  3555. TraceMsg(0, "sdv TR - ::Scroll called");
  3556. return E_NOTIMPL; // As specified in Kraig's document
  3557. }
  3558. HRESULT CDocObjectHost::OnUIDeactivate(
  3559. /* [in] */ BOOL fUndoable)
  3560. {
  3561. TraceMsg(TF_SHDUIACTIVATE, "DOH::OnUIDeactivate called (this=%x)", this);
  3562. DEBUG_CODE( _DumpMenus(TEXT("on OnUIDeactivate"), TRUE); )
  3563. if (_hmenuSet) {
  3564. OIPSMSG(TEXT("OnUIDeactivate We need to SetMenu(NULL, NULL, NULL)"));
  3565. _SetMenu(NULL, NULL, NULL);
  3566. }
  3567. return S_OK;
  3568. }
  3569. HRESULT CDocObjectHost::OnInPlaceDeactivate( void)
  3570. {
  3571. OIPSMSG(TEXT("OnInPlaceDeactivate called"));
  3572. return S_OK;
  3573. }
  3574. HRESULT CDocObjectHost::DiscardUndoState( void)
  3575. {
  3576. TraceMsg(0, "sdv TR - ::DiscardUndoState called");
  3577. return S_OK;
  3578. }
  3579. HRESULT CDocObjectHost::DeactivateAndUndo( void)
  3580. {
  3581. TraceMsg(0, "sdv TR - ::DeactivateAndUndo called");
  3582. return S_OK;
  3583. }
  3584. HRESULT CDocObjectHost::OnPosRectChange(
  3585. /* [in] */ LPCRECT lprcPosRect)
  3586. {
  3587. return E_NOTIMPL; // As specified in Kraig's document
  3588. }
  3589. HRESULT CDocObjectHost::OnInPlaceActivateEx(
  3590. /* [out] */ BOOL __RPC_FAR *pfNoRedraw,
  3591. /* [in] */ DWORD dwFlags)
  3592. {
  3593. OIPSMSG(TEXT("OnInPlaceActivateEx called"));
  3594. return S_OK;
  3595. }
  3596. HRESULT CDocObjectHost::OnInPlaceDeactivateEx(
  3597. /* [in] */ BOOL fNoRedraw)
  3598. {
  3599. OIPSMSG(TEXT("OnInPlaceDeactivateEx called"));
  3600. return S_OK;
  3601. }
  3602. HRESULT CDocObjectHost::RequestUIActivate( void)
  3603. {
  3604. if (_pWebOCInPlaceSiteEx)
  3605. return _pWebOCInPlaceSiteEx->RequestUIActivate();
  3606. else
  3607. return TRUE;
  3608. }
  3609. void CDocObjectHost::_OnNotify(LPNMHDR lpnm)
  3610. {
  3611. switch(lpnm->code) {
  3612. case TBN_BEGINDRAG:
  3613. #define ptbn ((LPTBNOTIFY)lpnm)
  3614. _OnMenuSelect(ptbn->iItem, 0, NULL);
  3615. break;
  3616. }
  3617. }
  3618. void MapAtToNull(LPTSTR psz)
  3619. {
  3620. while (*psz)
  3621. {
  3622. if (*psz == TEXT('@'))
  3623. {
  3624. LPTSTR pszNext = CharNext(psz);
  3625. *psz = 0;
  3626. psz = pszNext;
  3627. }
  3628. else
  3629. {
  3630. psz = CharNext(psz);
  3631. }
  3632. }
  3633. }
  3634. void BrowsePushed(HWND hDlg)
  3635. {
  3636. TCHAR szText[MAX_PATH];
  3637. DWORD cchText = ARRAYSIZE(szText);
  3638. TCHAR szFilter[MAX_PATH];
  3639. TCHAR szTitle[MAX_PATH];
  3640. LPITEMIDLIST pidl;
  3641. LPCITEMIDLIST pidlChild;
  3642. IShellFolder * pSF;
  3643. // load the filter and then replace all the @ characters with NULL. The end of the string will be doubly
  3644. // null-terminated
  3645. MLLoadShellLangString(IDS_BROWSEFILTER, szFilter, ARRAYSIZE(szFilter));
  3646. MapAtToNull(szFilter);
  3647. GetDlgItemText(hDlg, IDD_COMMAND, szText, ARRAYSIZE(szText));
  3648. PathUnquoteSpaces(szText);
  3649. // eliminate the "file://" stuff if necessary
  3650. if (IsFileUrlW(szText))
  3651. PathCreateFromUrl(szText, szText, &cchText, 0);
  3652. MLLoadShellLangString(IDS_TITLE, szTitle, ARRAYSIZE(szTitle));
  3653. if (GetFileNameFromBrowse(hDlg, szText, ARRAYSIZE(szText), NULL,
  3654. TEXT(".htm"), szFilter, szTitle))
  3655. {
  3656. if (SUCCEEDED(IECreateFromPath(szText, &pidl)))
  3657. {
  3658. if (SUCCEEDED(IEBindToParentFolder(pidl, &pSF, &pidlChild)))
  3659. {
  3660. HWND hWndCombo = GetDlgItem(hDlg, IDD_COMMAND);
  3661. COMBOBOXEXITEM cbexItem = {0};
  3662. cbexItem.mask = CBEIF_TEXT | CBEIF_IMAGE | CBEIF_SELECTEDIMAGE;
  3663. cbexItem.pszText = szText;
  3664. cbexItem.cchTextMax = ARRAYSIZE(szText);
  3665. cbexItem.iItem = -1;
  3666. cbexItem.iImage = IEMapPIDLToSystemImageListIndex(pSF, pidlChild, &cbexItem.iSelectedImage);
  3667. INT_PTR iPosition = SendMessage(hWndCombo, CBEM_INSERTITEM, (WPARAM)0, (LPARAM)(LPVOID)&cbexItem);
  3668. SendMessage(hWndCombo, CB_SETCURSEL, (WPARAM)iPosition, (LPARAM)0);
  3669. pSF->Release();
  3670. }
  3671. ILFree(pidl);
  3672. }
  3673. else
  3674. {
  3675. PathUnquoteSpaces(szText);
  3676. SetDlgItemText(hDlg, IDD_COMMAND, szText);
  3677. }
  3678. EnableOKButtonFromID(hDlg, IDD_COMMAND);
  3679. // place the focus on OK
  3680. SendMessage(hDlg, WM_NEXTDLGCTL, (WPARAM)GetDlgItem(hDlg, IDOK), TRUE);
  3681. }
  3682. }
  3683. struct SOpenDlg {
  3684. TCHAR szURL[MAX_URL_STRING];
  3685. IAddressEditBox *paebox; // Object that controls ComboBoxEx
  3686. IBandSite *pbs; // Used in AEBox Init call (used as a Connection Site)
  3687. IWinEventHandler *pweh; // Used to funnel IDD_COMMAND messages to the AEBox
  3688. };
  3689. const DWORD c_mapCtrlToContextIds[] = { 0, 0 };
  3690. const DWORD c_aRunHelpIds[] = {
  3691. IDD_ICON, NO_HELP,
  3692. IDD_PROMPT, NO_HELP,
  3693. IDD_RUNDLGOPENPROMPT, IDH_IE_RUN_COMMAND,
  3694. IDD_COMMAND, IDH_IE_RUN_COMMAND,
  3695. IDD_BROWSE, IDH_RUNBROWSE,
  3696. IDC_ASWEBFOLDER, IDH_WEB_FOLDERS_CKBOX,
  3697. 0, 0
  3698. };
  3699. #ifndef UNIX
  3700. HRESULT OpenDlgOnWebFolderOK(HWND hDlg, SOpenDlg * podlg)
  3701. {
  3702. ASSERT(podlg);
  3703. HRESULT hr = S_OK;
  3704. HWND hWndOpenBox = GetDlgItem(hDlg, IDD_COMMAND);
  3705. ComboBox_GetText(hWndOpenBox, podlg->szURL, ARRAYSIZE(podlg->szURL));
  3706. PathRemoveBlanks(podlg->szURL);
  3707. // int iScheme = GetUrlScheme(podlg->szURL);
  3708. // if ((URL_SCHEME_HTTP != iScheme) &&
  3709. // (URL_SCHEME_HTTPS != iScheme))
  3710. // {
  3711. // no, we don't support that protocol!!
  3712. // WCHAR wszMessage[MAX_PATH];
  3713. // WCHAR wszTitle[MAX_PATH];
  3714. // WCHAR wszErrorMessage[MAX_PATH + MAX_URL_STRING + 1];
  3715. // MLLoadShellLangString(IDS_ERRORBADURL, wszMessage, ARRAYSIZE(wszMessage));
  3716. // MLLoadShellLangString(IDS_ERRORBADURLTITLE, wszTitle, ARRAYSIZE(wszTitle));
  3717. // wnsprintf(wszErrorMessage, ARRAYSIZE(wszErrorMessage), wszMessage, podlg->szURL);
  3718. // MessageBox(hDlg, wszErrorMessage, wszTitle, MB_OK | MB_ICONERROR);
  3719. // hr = E_FAIL;
  3720. // }
  3721. return hr;
  3722. }
  3723. #endif // UNIX
  3724. HRESULT OpenDlgOnOK(HWND hDlg, SOpenDlg * podlg)
  3725. {
  3726. ASSERT(podlg);
  3727. HRESULT hr = S_OK;
  3728. /*
  3729. Try to use newer parsing code if we have an AddressEditBox object
  3730. */
  3731. if (podlg->paebox)
  3732. hr = podlg->paebox->ParseNow(SHURL_FLAGS_NONE);
  3733. else
  3734. {
  3735. HWND hWndOpenBox = GetDlgItem(hDlg, IDD_COMMAND);
  3736. ComboBox_GetText(hWndOpenBox, podlg->szURL, ARRAYSIZE(podlg->szURL));
  3737. PathRemoveBlanks(podlg->szURL);
  3738. }
  3739. return hr;
  3740. }
  3741. void CleanUpAutoComplete(SOpenDlg *podlg)
  3742. {
  3743. ATOMICRELEASE(podlg->paebox);
  3744. ATOMICRELEASE(podlg->pweh);
  3745. ATOMICRELEASE(podlg->pbs);
  3746. ZeroMemory((PVOID)podlg, SIZEOF(SOpenDlg));
  3747. }
  3748. BOOL_PTR CALLBACK CDocObjectHost::s_RunDlgProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
  3749. {
  3750. SOpenDlg* podlg = (SOpenDlg*)GetWindowLongPtr(hDlg, DWLP_USER);
  3751. switch (uMsg)
  3752. {
  3753. case WM_DESTROY:
  3754. SHRemoveDefaultDialogFont(hDlg);
  3755. return FALSE;
  3756. case WM_INITDIALOG:
  3757. {
  3758. ASSERT(lParam);
  3759. HWND hWndOpenBox = GetDlgItem(hDlg, IDD_COMMAND);
  3760. HWND hWndEditBox = (HWND)SendMessage(hWndOpenBox, CBEM_GETEDITCONTROL, 0,0);
  3761. SetWindowLongPtr(hDlg, DWLP_USER, lParam);
  3762. podlg = (SOpenDlg *)lParam;
  3763. // cross-lang platform support
  3764. SHSetDefaultDialogFont(hDlg, IDD_COMMAND);
  3765. if (podlg->paebox)
  3766. {
  3767. if ( FAILED(podlg->paebox->Init(hWndOpenBox, hWndEditBox, AEB_INIT_DEFAULT | AEB_INIT_NOASYNC, podlg->pbs)) ||
  3768. FAILED(IUnknown_SetOwner(podlg->paebox, podlg->pbs)))
  3769. CleanUpAutoComplete(podlg);
  3770. }
  3771. #ifdef UNIX
  3772. // BUG BUG : Win32 should also verify and take this change.
  3773. // IEUNIX : Limiting text, faulting under stress test. Need to set
  3774. // this limit.
  3775. SendMessage(hWndOpenBox, CB_LIMITTEXT, CBEMAXSTRLEN-1, 0L);
  3776. #endif
  3777. EnableWindow(GetDlgItem(hDlg, IDOK), FALSE);
  3778. if (SHRestricted(REST_NORUN))
  3779. EnableWindow(GetDlgItem(hDlg, IDC_ASWEBFOLDER), FALSE); // disable open as web folder
  3780. break;
  3781. }
  3782. case WM_HELP:
  3783. SHWinHelpOnDemandWrap((HWND) ((LPHELPINFO) lParam)->hItemHandle, c_szHelpFile,
  3784. HELP_WM_HELP, (DWORD_PTR)(LPTSTR) c_aRunHelpIds);
  3785. break;
  3786. case WM_CONTEXTMENU: // right mouse click
  3787. SHWinHelpOnDemandWrap((HWND) wParam, c_szHelpFile, HELP_CONTEXTMENU,
  3788. (DWORD_PTR)(LPTSTR) c_aRunHelpIds);
  3789. break;
  3790. case WM_COMMAND:
  3791. switch (GET_WM_COMMAND_ID(wParam, lParam))
  3792. {
  3793. case IDHELP:
  3794. break;
  3795. case IDD_BROWSE:
  3796. BrowsePushed(hDlg);
  3797. break;
  3798. case IDD_COMMAND:
  3799. switch (GET_WM_COMMAND_CMD(wParam, lParam))
  3800. {
  3801. case CBN_SELCHANGE:
  3802. break;
  3803. case CBN_EDITCHANGE:
  3804. case CBN_SELENDOK:
  3805. if (podlg->pweh)
  3806. podlg->pweh->OnWinEvent(hDlg, uMsg, wParam, lParam, NULL);
  3807. EnableOKButtonFromID(hDlg, IDD_COMMAND);
  3808. break;
  3809. default:
  3810. if (podlg->pweh)
  3811. podlg->pweh->OnWinEvent(hDlg, uMsg, wParam, lParam, NULL);
  3812. break;
  3813. }
  3814. break;
  3815. case IDOK:
  3816. {
  3817. // UNIX doesn't support this checkbox -- so we don't need
  3818. // to check.
  3819. #ifndef UNIX
  3820. HWND hwndCheckBox = GetDlgItem(hDlg, IDC_ASWEBFOLDER);
  3821. if (hwndCheckBox)
  3822. {
  3823. LRESULT lrState = SendMessage(hwndCheckBox, BM_GETCHECK,
  3824. 0, 0);
  3825. if (lrState == BST_CHECKED)
  3826. {
  3827. if (SUCCEEDED(OpenDlgOnWebFolderOK(hDlg, podlg)))
  3828. EndDialog(hDlg, IDC_ASWEBFOLDER);
  3829. break;
  3830. }
  3831. else
  3832. #endif
  3833. if (FAILED(OpenDlgOnOK(hDlg, podlg)))
  3834. break;
  3835. #ifndef UNIX
  3836. }
  3837. #endif
  3838. }
  3839. // Fall through to IDCANCEL to close dlg
  3840. case IDCANCEL:
  3841. EndDialog(hDlg, GET_WM_COMMAND_ID(wParam, lParam));
  3842. break;
  3843. default:
  3844. return FALSE;
  3845. }
  3846. break;
  3847. default:
  3848. return FALSE;
  3849. }
  3850. return TRUE;
  3851. }
  3852. void CDocObjectHost::_Navigate(LPCWSTR pwszURL)
  3853. {
  3854. IWebBrowser2* pwb2;
  3855. if (SUCCEEDED(IUnknown_QueryService(_psb, SID_SContainerDispatch, IID_IWebBrowser2, (void **)&pwb2)))
  3856. {
  3857. //
  3858. // HACK: We are not passing BSTR, but LPWSTR, which
  3859. // will work as far as IWebBrowser2 can handle
  3860. // NULL-terminated string correctly.
  3861. //
  3862. pwb2->Navigate((BSTR)pwszURL, NULL, NULL, NULL, NULL);
  3863. pwb2->Release();
  3864. }
  3865. }
  3866. HRESULT CDocObjectHost::_PrepFileOpenAddrBand(IAddressEditBox ** ppaeb, IWinEventHandler ** ppweh, IBandSite ** ppbs)
  3867. {
  3868. HRESULT hr;
  3869. *ppaeb = NULL;
  3870. *ppweh = NULL;
  3871. *ppbs = NULL;
  3872. // If our CoCreateInstance fails, s_rundlgproc will know because paebox
  3873. // will be NULL
  3874. hr = CoCreateInstance(CLSID_AddressEditBox, NULL, CLSCTX_INPROC_SERVER, IID_IAddressEditBox, (void **)ppaeb);
  3875. if (EVAL(SUCCEEDED(hr)))
  3876. {
  3877. IServiceProvider *pspT;
  3878. hr = (*ppaeb)->QueryInterface(IID_IWinEventHandler, (void **)ppweh);
  3879. // Travel up the object hierarchy, and obtain the same pointer that
  3880. // the address bar was ::Init'ed with
  3881. // WARNING: This is not optional. The addressband will fault if this fails.
  3882. if (EVAL(SUCCEEDED(hr) && _psp))
  3883. {
  3884. hr = _psp->QueryService(SID_SExplorerToolbar, IID_IServiceProvider, (void **)&pspT);
  3885. // In framed cases, CBaseBrowser2::QueryService() will filter out SID_SExplorerToolbar
  3886. // because it's afraid of Toolbars appearing in the frame. We won't have that problem,
  3887. // so we may need to go the TopLevelBrowser first and then ask around there.
  3888. if (FAILED(hr))
  3889. {
  3890. IServiceProvider *pspT2;
  3891. hr = _psp->QueryService(SID_STopLevelBrowser, IID_IServiceProvider, (void **)&pspT2);
  3892. if (EVAL(SUCCEEDED(hr)))
  3893. {
  3894. hr = pspT2->QueryService(SID_SExplorerToolbar, IID_IServiceProvider, (void **)&pspT);
  3895. pspT2->Release();
  3896. }
  3897. }
  3898. if (EVAL(SUCCEEDED(hr)))
  3899. {
  3900. if (EVAL(SUCCEEDED(hr = pspT->QueryService(IID_IBandSite, IID_IBandSite, (void **)ppbs))))
  3901. {
  3902. IDeskBand *pdbT;
  3903. // Had to include "ITBAR.H" to access CBIDX_ADDDRESS
  3904. // HACKHACK
  3905. #define CBIDX_ADDRESS 4
  3906. // If any of the following fails, I don't care because the MRU can be out of
  3907. // synch.
  3908. if (SUCCEEDED((*ppbs)->QueryBand(CBIDX_ADDRESS, &pdbT, NULL, NULL, 0)))
  3909. {
  3910. IUnknown_Exec(pdbT, &CGID_AddressEditBox, AECMDID_SAVE, 0, NULL, NULL);
  3911. pdbT->Release();
  3912. }
  3913. }
  3914. pspT->Release();
  3915. }
  3916. }
  3917. }
  3918. if (FAILED(hr))
  3919. {
  3920. ATOMICRELEASE(*ppaeb);
  3921. ATOMICRELEASE(*ppweh);
  3922. ATOMICRELEASE(*ppbs);
  3923. }
  3924. return hr;
  3925. }
  3926. void CDocObjectHost::_OnOpen(void)
  3927. {
  3928. HWND hwndFrame;
  3929. SOpenDlg odlg ={0};
  3930. _psb->GetWindow(&hwndFrame);
  3931. if (SHIsRestricted2W(_hwnd, REST_NoFileOpen, NULL, 0))
  3932. return;
  3933. if (EVAL(SUCCEEDED(_PrepFileOpenAddrBand(&(odlg.paebox), &odlg.pweh, &odlg.pbs))))
  3934. {
  3935. // TODO: Make it a helper member, which notifies up and down.
  3936. _psb->EnableModelessSB(FALSE);
  3937. #ifdef UNIX
  3938. UINT iRet;
  3939. if (TRUE || MwCurrentLook() == LOOK_MOTIF)
  3940. iRet = DialogBoxParam(MLGetHinst(),
  3941. MAKEINTRESOURCE(DLG_RUNMOTIF),
  3942. hwndFrame,
  3943. s_RunDlgProc,
  3944. (LPARAM)&odlg);
  3945. else
  3946. iRet = DialogBoxParam(MLGetHinst(),
  3947. MAKEINTRESOURCE(DLG_RUN),
  3948. hwndFrame,
  3949. s_RunDlgProc,
  3950. (LPARAM)&odlg);
  3951. #else
  3952. INT_PTR iRet = DialogBoxParam(MLGetHinst(), MAKEINTRESOURCE(DLG_RUN), hwndFrame, s_RunDlgProc, (LPARAM)&odlg);
  3953. #endif /* UNIX */
  3954. _psb->EnableModelessSB(TRUE);
  3955. if (iRet==IDOK)
  3956. {
  3957. if (g_dwStopWatchMode) // Perf mode to mark start time
  3958. StopWatch_MarkSameFrameStart(hwndFrame);
  3959. if (odlg.paebox)
  3960. odlg.paebox->Execute(SHURL_EXECFLAGS_NONE);
  3961. else
  3962. _Navigate(odlg.szURL);
  3963. }
  3964. #ifndef UNIX
  3965. if (iRet == IDC_ASWEBFOLDER)
  3966. {
  3967. BSTR bstrUrl = SysAllocString(odlg.szURL);
  3968. if (bstrUrl != NULL)
  3969. {
  3970. _NavigateFolder(bstrUrl);
  3971. SysFreeString(bstrUrl);
  3972. }
  3973. }
  3974. #endif /*!UNIX*/
  3975. IUnknown_SetOwner(odlg.paebox, NULL);
  3976. }
  3977. // Cleanup ref counts
  3978. CleanUpAutoComplete(&odlg);
  3979. }
  3980. void CDocObjectHost::_OnClose() const
  3981. {
  3982. ASSERT(_pwb);
  3983. if (!_HideBrowserBar())
  3984. {
  3985. HRESULT hr = E_FAIL;
  3986. HWND hwnd = NULL;
  3987. IOleWindow * pOleWindow;
  3988. if ( _pwb )
  3989. {
  3990. hr = _pwb->QueryInterface(IID_PPV_ARG(IOleWindow, &pOleWindow));
  3991. }
  3992. if (SUCCEEDED(hr))
  3993. {
  3994. pOleWindow->GetWindow(&hwnd);
  3995. pOleWindow->Release();
  3996. if ( hwnd )
  3997. {
  3998. PostMessage(hwnd, WM_CLOSE, 0, 0);
  3999. }
  4000. }
  4001. }
  4002. }
  4003. BOOL CDocObjectHost::_HideBrowserBar() const
  4004. {
  4005. ASSERT(_pwb);
  4006. // Get the proxy browser. We only have
  4007. // a proxy browser if we are in a band.
  4008. //
  4009. IShellBrowser * pPrxyBrowser;
  4010. HRESULT hr = IUnknown_QueryService(_pwb,
  4011. SID_SProxyBrowser,
  4012. IID_IShellBrowser,
  4013. (void**)&pPrxyBrowser);
  4014. if (SUCCEEDED(hr))
  4015. {
  4016. hr = IUnknown_ShowBrowserBar(_psb, CLSID_SearchBand, FALSE);
  4017. }
  4018. return (SUCCEEDED(hr) ? TRUE : FALSE);
  4019. }
  4020. void CDocObjectHost::_OnImportExport(HWND hwnd)
  4021. {
  4022. RunImportExportFavoritesWizard(hwnd);
  4023. }
  4024. UINT_PTR CALLBACK DocHostSaveAsOFNHook(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam)
  4025. {
  4026. switch (msg)
  4027. {
  4028. case WM_INITDIALOG:
  4029. {
  4030. /* Hide the "Save as Type" text box */
  4031. CommDlg_OpenSave_HideControl(GetParent(hDlg), stc2);
  4032. /* Hide the listbox with save type extensions */
  4033. CommDlg_OpenSave_HideControl(GetParent(hDlg), cmb1);
  4034. /* Hide the Open as read-only control */
  4035. CommDlg_OpenSave_HideControl(GetParent(hDlg), chx1);
  4036. break;
  4037. }
  4038. default:
  4039. break;
  4040. }
  4041. return FALSE;
  4042. }
  4043. #define IDS_HELPURL_SUPPORT IDS_HELPMSWEB+4
  4044. #define SZ_REGKEY_HELPURL_OVERRIDE TEXT("Software\\Microsoft\\Internet Explorer\\Help_Menu_URLs")
  4045. #define SZ_REGVAL_HELPURL_SUPPORT TEXT("Online_Support")
  4046. #define SZ_REGVAL_HELPURL_TEMPLATE TEXT("%d")
  4047. void CDocObjectHost::_OnHelpGoto(UINT idRes)
  4048. {
  4049. HRESULT hr = E_FAIL;
  4050. WCHAR szURL[MAX_PATH]; // this is enough for our own
  4051. // First try to get a copy from the registry because this is where Admins (with the IEAK) over ride
  4052. // our default values.
  4053. // We special case the Online_Support URL because it was supported in IE3.
  4054. if (IDS_HELPURL_SUPPORT == idRes)
  4055. {
  4056. hr = URLSubRegQuery(SZ_REGKEY_HELPURL_OVERRIDE, SZ_REGVAL_HELPURL_SUPPORT, TRUE, szURL, ARRAYSIZE(szURL), URLSUB_ALL);
  4057. }
  4058. else
  4059. {
  4060. WCHAR szValue[MAX_PATH];
  4061. wnsprintfW(szValue, ARRAYSIZE(szValue), SZ_REGVAL_HELPURL_TEMPLATE, (idRes - IDS_HELPMSWEB + 1));
  4062. hr = URLSubRegQuery(SZ_REGKEY_HELPURL_OVERRIDE, szValue, TRUE, szURL, ARRAYSIZE(szURL), URLSUB_ALL);
  4063. }
  4064. if (FAILED(hr))
  4065. hr = URLSubLoadString(NULL, idRes, szURL, ARRAYSIZE(szURL), URLSUB_ALL);
  4066. if (SUCCEEDED(hr))
  4067. {
  4068. _Navigate(szURL);
  4069. }
  4070. }
  4071. STDAPI_(void) IEAboutBox( HWND hWnd );
  4072. // WM_COMMAND from _WndProc - execs are going down
  4073. void CDocObjectHost::_OnCommand(UINT wNotify, UINT id, HWND hwndControl)
  4074. {
  4075. if (_ShouldForwardMenu(WM_COMMAND, MAKEWPARAM(id, wNotify), (LPARAM)hwndControl))
  4076. {
  4077. _ForwardObjectMsg(WM_COMMAND, MAKEWPARAM(id, wNotify), (LPARAM)hwndControl);
  4078. return;
  4079. }
  4080. switch(id)
  4081. {
  4082. case DVIDM_HELPTUTORIAL:
  4083. _OnHelpGoto(IDS_HELPTUTORIAL);
  4084. break;
  4085. // ShabbirS (980917): BugFix# 34259 - Repair IE option.
  4086. case DVIDM_HELPREPAIR:
  4087. RepairIE();
  4088. break;
  4089. case DVIDM_HELPABOUT:
  4090. IEAboutBox( _hwnd );
  4091. break;
  4092. case DVIDM_HELPSEARCH:
  4093. {
  4094. #ifdef UNIX
  4095. ContentHelp(_psb);
  4096. break;
  4097. #else
  4098. uCLSSPEC ucs;
  4099. QUERYCONTEXT qc = { 0 };
  4100. ucs.tyspec = TYSPEC_CLSID;
  4101. ucs.tagged_union.clsid = CLSID_IEHelp;
  4102. HRESULT hres = FaultInIEFeature(_hwnd, &ucs, &qc, FIEF_FLAG_FORCE_JITUI);
  4103. if ( SUCCEEDED( hres ) )
  4104. {
  4105. // MLHtmlHelp runs on a separate thread and should therefore be
  4106. // safe against the kinds of message loops problems indicated above
  4107. ULONG_PTR uCookie = 0;
  4108. SHActivateContext(&uCookie);
  4109. MLHtmlHelp(_hwnd, TEXT("iexplore.chm > iedefault"), HH_DISPLAY_TOPIC, 0, ML_CROSSCODEPAGE);
  4110. if (uCookie)
  4111. {
  4112. SHDeactivateContext(uCookie);
  4113. }
  4114. }
  4115. else
  4116. {
  4117. TraceMsg( TF_WARNING, "CDocObjectHost::_OnCommand() - FaultInIEFeature() Failed with hr=0x%x!", hres );
  4118. }
  4119. break;
  4120. #endif
  4121. }
  4122. case DVIDM_DHFAVORITES:
  4123. _pmsoctBrowser->Exec(&CGID_Explorer, SBCMDID_ADDTOFAVORITES, OLECMDEXECOPT_PROMPTUSER, NULL, NULL);
  4124. break;
  4125. case DVIDM_GOHOME:
  4126. case DVIDM_GOSEARCH:
  4127. {
  4128. TCHAR szPath[MAX_URL_STRING];
  4129. LPITEMIDLIST pidl;
  4130. HRESULT hres = SHDGetPageLocation(_hwnd,
  4131. (id==DVIDM_GOSEARCH) ? IDP_SEARCH : IDP_START,
  4132. szPath, ARRAYSIZE(szPath), &pidl);
  4133. if (SUCCEEDED(hres))
  4134. {
  4135. _psb->BrowseObject(pidl, SBSP_ABSOLUTE | SBSP_SAMEBROWSER);
  4136. ILFree(pidl);
  4137. }
  4138. else
  4139. {
  4140. TCHAR szMessage[256];
  4141. BOOL fSuccess = FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM,
  4142. NULL, hres, 0, szMessage, ARRAYSIZE(szMessage), (va_list *)&szPath);
  4143. if (!fSuccess)
  4144. szMessage[0] = 0;
  4145. MLShellMessageBox(_hwnd,
  4146. MAKEINTRESOURCE(IDS_CANTACCESSDOCUMENT),
  4147. szPath, MB_OK | MB_SETFOREGROUND | MB_ICONSTOP, szMessage);
  4148. }
  4149. }
  4150. break;
  4151. case DVIDM_STOPDOWNLOAD:
  4152. // We need to tell the container to cancel a pending navigation
  4153. // if any. Notice that the Cancel button serves for two purposes:
  4154. // (1) canceling a pending navigation
  4155. // (2) cancel any downloading
  4156. if (_psb)
  4157. _CancelPendingNavigation(FALSE);
  4158. goto TryDocument;
  4159. case DVIDM_NEWWINDOW:
  4160. // make sure the top level browser gets cloned, not an explorer bar
  4161. IShellBrowser* psbTop;
  4162. if (!SHIsRestricted2W(_hwnd, REST_NoOpeninNewWnd, NULL, 0) &&
  4163. !SHIsRestricted2W(_hwnd, REST_NoFileNew, NULL, 0) &&
  4164. EVAL(SUCCEEDED(_psp->QueryService(SID_STopLevelBrowser, IID_IShellBrowser, (void **)&psbTop))) && psbTop)
  4165. {
  4166. BOOL fHandled = FALSE;
  4167. if (_pWebOCUIHandler)
  4168. {
  4169. // Give the WebOC host a chance to handle this command, since it may
  4170. // not want an IE window to be created
  4171. if (S_OK == IUnknown_Exec(_pWebOCUIHandler, &CGID_DocHostCommandHandler,
  4172. IDM_NEW_TOPLEVELWINDOW, 0, NULL, NULL))
  4173. {
  4174. fHandled = TRUE;
  4175. }
  4176. }
  4177. if (!fHandled)
  4178. {
  4179. // tell the top level browser to save its window size to the registry so
  4180. // that our new window can pick it up and cascade properly
  4181. IUnknown_Exec(psbTop, &CGID_Explorer, SBCMDID_SUGGESTSAVEWINPOS, 0, NULL, NULL);
  4182. psbTop->BrowseObject(&s_idNull, SBSP_RELATIVE|SBSP_NEWBROWSER);
  4183. psbTop->Release();
  4184. }
  4185. }
  4186. break;
  4187. case DVIDM_OPEN:
  4188. _OnOpen();
  4189. break;
  4190. case DVIDM_SAVE:
  4191. if (!SHIsRestricted2W(_hwnd, REST_NoBrowserSaveAs, NULL, 0))
  4192. {
  4193. // There's a scenario where the XML MimeViewer, when aggregating Trident, answers "disabled" to
  4194. // OLECMDID_SAVE. However, since we don't call QueryStatus on the ACCELERATOR key sequence,
  4195. // we end up calling into Trident's IPersistFile::Save(), overwriting the XML file with the converted
  4196. // HTML.
  4197. //
  4198. // The right thing to do is to QS and beep if disabled.
  4199. //
  4200. if (_dwAppHack & BROWSERFLAG_MSHTML)
  4201. {
  4202. if (_pmsot)
  4203. {
  4204. OLECMD rgcmds[] = { { OLECMDID_SAVE, 0 }, };
  4205. _pmsot->QueryStatus(NULL, ARRAYSIZE(rgcmds), rgcmds, NULL);
  4206. if (!(rgcmds[0].cmdf & OLECMDF_ENABLED))
  4207. {
  4208. // If SAVE is disabled, provide user feedback.
  4209. MessageBeep(0);
  4210. break;
  4211. }
  4212. }
  4213. }
  4214. _OnSave();
  4215. }
  4216. break;
  4217. case DVIDM_DESKTOPSHORTCUT:
  4218. IUnknown_Exec(_psb, &CGID_Explorer, SBCMDID_CREATESHORTCUT, 0, NULL, NULL);
  4219. break;
  4220. case DVIDM_SENDPAGE:
  4221. IUnknown_Exec(_psb, &CGID_Explorer, SBCMDID_SENDPAGE, 0, NULL, NULL);
  4222. break;
  4223. case DVIDM_SENDSHORTCUT:
  4224. IUnknown_Exec(_psb, &CGID_Explorer, SBCMDID_SENDSHORTCUT, 0, NULL, NULL);
  4225. break;
  4226. case DVIDM_NEWMESSAGE:
  4227. #ifdef UNIX
  4228. if ( OEHandlesMail() )
  4229. _UnixSendDocToOE(NULL, 0, MAIL_ACTION_SEND);
  4230. else
  4231. SendDocToMailRecipient(NULL, 0, MAIL_ACTION_SEND);
  4232. #else
  4233. if (FAILED(DropOnMailRecipient(NULL, 0)))
  4234. {
  4235. SHRunIndirectRegClientCommand(_hwnd, NEW_MAIL_DEF_KEY);
  4236. }
  4237. #endif
  4238. break;
  4239. case DVIDM_NEWPOST:
  4240. #ifdef UNIX
  4241. if (!CheckAndExecNewsScript(_hwnd))
  4242. #endif
  4243. SHRunIndirectRegClientCommand(_hwnd, NEW_NEWS_DEF_KEY);
  4244. break;
  4245. case DVIDM_NEWCONTACT:
  4246. SHRunIndirectRegClientCommand(_hwnd, NEW_CONTACTS_DEF_KEY);
  4247. break;
  4248. case DVIDM_NEWAPPOINTMENT:
  4249. SHRunIndirectRegClientCommand(_hwnd, NEW_APPOINTMENT_DEF_KEY);
  4250. break;
  4251. case DVIDM_NEWMEETING:
  4252. SHRunIndirectRegClientCommand(_hwnd, NEW_MEETING_DEF_KEY);
  4253. break;
  4254. case DVIDM_NEWTASK:
  4255. SHRunIndirectRegClientCommand(_hwnd, NEW_TASK_DEF_KEY);
  4256. break;
  4257. case DVIDM_NEWTASKREQUEST:
  4258. SHRunIndirectRegClientCommand(_hwnd, NEW_TASKREQUEST_DEF_KEY);
  4259. break;
  4260. case DVIDM_NEWJOURNAL:
  4261. SHRunIndirectRegClientCommand(_hwnd, NEW_JOURNAL_DEF_KEY);
  4262. break;
  4263. case DVIDM_NEWNOTE:
  4264. SHRunIndirectRegClientCommand(_hwnd, NEW_NOTE_DEF_KEY);
  4265. break;
  4266. case DVIDM_CALL:
  4267. SHRunIndirectRegClientCommand(_hwnd, NEW_CALL_DEF_KEY);
  4268. break;
  4269. case DVIDM_SAVEASFILE:
  4270. //
  4271. // Handle the case where DocObject does not support "SaveAs"
  4272. // and we have enabled the menuitem anyway.
  4273. //
  4274. if (SHIsRestricted2W(_hwnd, REST_NoBrowserSaveAs, NULL, 0))
  4275. break;
  4276. if (_pmsot)
  4277. {
  4278. OLECMD rgcmds[] = { { OLECMDID_SAVEAS, 0 }, };
  4279. _pmsot->QueryStatus(NULL, ARRAYSIZE(rgcmds), rgcmds, NULL);
  4280. ASSERT(rgcmds[0].cmdf & OLECMDF_ENABLED);
  4281. if (!(rgcmds[0].cmdf & OLECMDF_ENABLED))
  4282. _OnSaveAs();
  4283. else
  4284. goto TryDocument;
  4285. }
  4286. break;
  4287. case DVIDM_IMPORTEXPORT:
  4288. _OnImportExport(_hwnd);
  4289. break;
  4290. default:
  4291. if (IsInRange(id, DVIDM_HELPMSWEB, DVIDM_HELPMSWEBLAST))
  4292. {
  4293. #ifndef UNIX
  4294. if (id == FCIDM_HELPNETSCAPEUSERS)
  4295. SHHtmlHelpOnDemandWrap(_hwnd, TEXT("iexplore.chm > iedefault"), HH_DISPLAY_TOPIC, (DWORD_PTR) TEXT("lvg_nscp.htm"), ML_CROSSCODEPAGE);
  4296. else
  4297. #else
  4298. if (id == FCIDM_HELPNETSCAPEUSERS)
  4299. UnixHelp(L"Netscape User Help", _psb);
  4300. else
  4301. #endif
  4302. _OnHelpGoto(IDS_HELPMSWEB + (id - DVIDM_HELPMSWEB));
  4303. }
  4304. else if (IsInRange(id, DVIDM_MSHTML_FIRST, DVIDM_MSHTML_LAST))
  4305. {
  4306. TraceMsg(DM_PREMERGEDMENU, "Processing merged menuitem %d", id - DVIDM_MSHTML_FIRST);
  4307. ASSERT(_pcmdMergedMenu);
  4308. if (_pcmdMergedMenu) {
  4309. HRESULT hresT=_pcmdMergedMenu->Exec(&CGID_MSHTML, id - DVIDM_MSHTML_FIRST, 0, NULL, NULL);
  4310. if (FAILED(hresT)) {
  4311. TraceMsg(DM_ERROR, "CDOH::_OnCommand _pcmdMergedMenu->Exec(%d) failed %x",
  4312. id - DVIDM_MSHTML_FIRST, hresT);
  4313. }
  4314. }
  4315. }
  4316. else if (IsInRange (id, DVIDM_MENUEXT_FIRST, DVIDM_MENUEXT_LAST))
  4317. {
  4318. // Menu Extensions
  4319. IUnknown_Exec(_pBrowsExt, &CLSID_ToolbarExtButtons, id, 0, NULL, NULL);
  4320. }
  4321. else
  4322. {
  4323. TryDocument:
  4324. if (_pmsot)
  4325. {
  4326. // Check if we need to call object's Exec.
  4327. UINT idMso = _MapToMso(id);
  4328. if (idMso != (UINT)-1)
  4329. {
  4330. // Yes. Call it.
  4331. _pmsot->Exec(NULL, idMso, OLECMDEXECOPT_PROMPTUSER, NULL, NULL);
  4332. }
  4333. else if (id == DVIDM_PRINTFRAME)
  4334. {
  4335. _pmsot->Exec(&CGID_ShellDocView, SHDVID_PRINTFRAME, OLECMDEXECOPT_PROMPTUSER, NULL, NULL);
  4336. }
  4337. }
  4338. }
  4339. break;
  4340. }
  4341. }
  4342. HRESULT CDocObjectHost::_OnSaveAs(void)
  4343. {
  4344. HRESULT hres = S_OK;
  4345. TraceMsg(DM_SAVEASHACK, "DOH::_OnSaveAs called");
  4346. ASSERT(_pole);
  4347. if (_dwAppHack & BROWSERFLAG_MSHTML)
  4348. {
  4349. SaveBrowserFile( _hwnd, _pole );
  4350. }
  4351. else // old dochost stuff
  4352. {
  4353. TCHAR szSaveTo[MAX_PATH]; // ok with MAX_PATH
  4354. MLLoadString(IDS_DOCUMENT, szSaveTo, ARRAYSIZE(szSaveTo));
  4355. TCHAR szDesktop[MAX_PATH];
  4356. SHGetSpecialFolderPath(_hwnd, szDesktop, CSIDL_DESKTOPDIRECTORY, FALSE);
  4357. OPENFILENAME OFN;
  4358. OFN.lStructSize = sizeof(OPENFILENAME);
  4359. OFN.hwndOwner = _hwnd;
  4360. OFN.lpstrFileTitle = 0;
  4361. OFN.nMaxCustFilter = 0;
  4362. OFN.nFilterIndex = 0;
  4363. OFN.nMaxFile = ARRAYSIZE(szSaveTo);
  4364. OFN.lpfnHook = DocHostSaveAsOFNHook;
  4365. OFN.Flags = 0L;/* for now, since there's no readonly support */
  4366. OFN.lpstrTitle = NULL;
  4367. OFN.lpstrInitialDir = szDesktop;
  4368. OFN.lpstrFile = szSaveTo;
  4369. OFN.Flags = OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT | OFN_ENABLEHOOK | OFN_EXPLORER |
  4370. OFN_NOREADONLYRETURN | OFN_PATHMUSTEXIST;
  4371. OFN.lpstrFilter = NULL;
  4372. OFN.lpstrCustomFilter = NULL;
  4373. OFN.lpstrDefExt = TEXT(""); // no extension
  4374. TCHAR szValue[MAX_PATH+1]; // +1 for for double-null
  4375. TCHAR szExt[40];
  4376. HKEY hkey = _GetUserCLSIDKey(_pole, NULL, NULL);
  4377. if (hkey)
  4378. {
  4379. LONG cb = SIZEOF(szValue);
  4380. if (RegQueryValue(hkey, TEXT("DefaultExtension"), szValue, &cb) == ERROR_SUCCESS)
  4381. {
  4382. TraceMsg(DM_SAVEASHACK, "DOH::_OnSaveAs DefExt is %s", szValue);
  4383. // It is suposed to be like ".xls, Excel Workbook (*.xls)"
  4384. if (szValue[0]==TEXT('.')) {
  4385. StrCpyN(szExt, szValue+1, ARRAYSIZE(szExt));
  4386. LPTSTR pszEnd = StrChr(szExt, TEXT(','));
  4387. if (pszEnd) {
  4388. *pszEnd = 0;
  4389. }
  4390. OFN.lpstrDefExt = szExt;
  4391. OFN.lpstrFilter = szValue;
  4392. OFN.Flags &= ~OFN_ENABLEHOOK;
  4393. TraceMsg(DM_SAVEASHACK, "DOH::_OnSaveAs OFN.lpstrDefExt is %s", OFN.lpstrDefExt);
  4394. }
  4395. }
  4396. }
  4397. if (GetSaveFileName(&OFN))
  4398. {
  4399. IPersistFile* ppf;
  4400. ASSERT(_pole);
  4401. hres = _pole->QueryInterface(IID_IPersistFile, (void **)&ppf);
  4402. if (SUCCEEDED(hres))
  4403. {
  4404. TraceMsg(DM_APPHACK, "APPHACK DOH SaveAs'ing to %s", szSaveTo);
  4405. hres = ppf->Save(szSaveTo, FALSE);
  4406. ppf->Release();
  4407. }
  4408. else
  4409. {
  4410. ASSERT(0);
  4411. }
  4412. }
  4413. else
  4414. {
  4415. hres = S_FALSE;
  4416. }
  4417. }
  4418. return hres;
  4419. }
  4420. #ifndef POSTPOSTSPLIT
  4421. HRESULT DropOnMailRecipient(IDataObject *pdtobj, DWORD grfKeyState)
  4422. {
  4423. IDropTarget *pdrop;
  4424. HRESULT hres = CoCreateInstance(CLSID_MailRecipient,
  4425. NULL, CLSCTX_INPROC_SERVER | CLSCTX_LOCAL_SERVER,
  4426. IID_IDropTarget, (void**)&pdrop);
  4427. if (SUCCEEDED(hres))
  4428. {
  4429. hres = SimulateDrop(pdrop, pdtobj, grfKeyState, NULL, NULL);
  4430. pdrop->Release();
  4431. }
  4432. return hres;
  4433. }
  4434. HRESULT SendDocToMailRecipient(LPCITEMIDLIST pidl, UINT uiCodePage, DWORD grfKeyState)
  4435. {
  4436. #ifndef UNIX
  4437. IDataObject *pdtobj;
  4438. HRESULT hres = GetDataObjectForPidl(pidl, &pdtobj);
  4439. if (SUCCEEDED(hres))
  4440. {
  4441. IQueryCodePage * pQcp;
  4442. if (SUCCEEDED(pdtobj->QueryInterface(IID_IQueryCodePage, (void **)&pQcp)))
  4443. {
  4444. pQcp->SetCodePage(uiCodePage);
  4445. pQcp->Release();
  4446. }
  4447. hres = DropOnMailRecipient(pdtobj, grfKeyState);
  4448. pdtobj->Release();
  4449. }
  4450. return hres;
  4451. #else
  4452. return UnixSendDocToMailRecipient(pidl, uiCodePage, grfKeyState);
  4453. #endif
  4454. }
  4455. #endif
  4456. void _EnableRemoveMenuItem(HMENU hmenu, DWORD cmdf, UINT uCmd)
  4457. {
  4458. if (!(cmdf & (OLECMDF_SUPPORTED | OLECMDF_ENABLED)))
  4459. RemoveMenu(hmenu, uCmd, MF_BYCOMMAND);
  4460. else
  4461. _EnableMenuItem(hmenu, uCmd,
  4462. cmdf & OLECMDF_ENABLED);
  4463. }
  4464. void CDocObjectHost::_OnInitMenuPopup(HMENU hmInit, int nIndex, BOOL fSystemMenu)
  4465. {
  4466. if (!_hmenuCur)
  4467. return;
  4468. DEBUG_CODE( _DumpMenus(TEXT("on _OnInitMenuPopup"), TRUE); )
  4469. if (GetMenuFromID(_hmenuCur, FCIDM_MENU_VIEW) == hmInit) {
  4470. OLECMD rgcmd1[] = {
  4471. { IDM_SCRIPTDEBUGGER, 0 },
  4472. };
  4473. DeleteMenu (hmInit, DVIDM_MSHTML_FIRST+IDM_SCRIPTDEBUGGER, MF_BYCOMMAND);
  4474. if (SUCCEEDED(QueryStatusDown(&CGID_MSHTML, ARRAYSIZE(rgcmd1), rgcmd1, NULL)) && (rgcmd1[0].cmdf & OLECMDF_ENABLED)) {
  4475. //
  4476. // We need the script debugger popup menu. We should check to see if this
  4477. // needs to be loaded.
  4478. //
  4479. HMENU hMenuDebugger;
  4480. MENUITEMINFO mii;
  4481. const UINT cchBuf = 128;
  4482. TCHAR szItem[cchBuf];
  4483. hMenuDebugger = LoadMenu(MLGetHinst(), MAKEINTRESOURCE(MENU_SCRDEBUG));
  4484. mii.fMask = MIIM_SUBMENU | MIIM_TYPE | MIIM_ID;
  4485. mii.fType = MFT_STRING;
  4486. mii.cch = cchBuf;
  4487. mii.dwTypeData = szItem;
  4488. mii.cbSize = sizeof(mii);
  4489. GetMenuItemInfo(hMenuDebugger, 0, TRUE, &mii);
  4490. mii.fMask |= MIIM_STATE;
  4491. mii.fState = MFS_ENABLED;
  4492. InsertMenuItem(hmInit, FCIDM_THEATER, FALSE, &mii);
  4493. OLECMD rgcmd[] = {
  4494. { IDM_BREAKATNEXT, 0 },
  4495. { IDM_LAUNCHDEBUGGER, 0 },
  4496. };
  4497. HRESULT hr = QueryStatusDown(&CGID_MSHTML, ARRAYSIZE(rgcmd), rgcmd, NULL);
  4498. _EnableMenuItem(mii.hSubMenu, DVIDM_MSHTML_FIRST+rgcmd[0].cmdID, SUCCEEDED(hr) && (rgcmd[0].cmdf & OLECMDF_ENABLED));
  4499. _EnableMenuItem(mii.hSubMenu, DVIDM_MSHTML_FIRST+rgcmd[1].cmdID, SUCCEEDED(hr) && (rgcmd[1].cmdf & OLECMDF_ENABLED));
  4500. }
  4501. if (_pmsot)
  4502. {
  4503. OLECMD rgcmd2[] = {
  4504. { IDM_VIEWSOURCE, 0 },
  4505. };
  4506. if (SHRestricted2(REST_NoViewSource, NULL, 0) == 0)
  4507. {
  4508. // we only want to modify the state of the view source item
  4509. // if it isn't restricted by the IEAK. if it's restricted, we
  4510. // need to leave it disabled regardles of what the object
  4511. // we're hosting says
  4512. HRESULT hr = _pmsot->QueryStatus(&CGID_MSHTML, ARRAYSIZE(rgcmd2), rgcmd2, NULL);
  4513. _EnableMenuItem(hmInit, DVIDM_MSHTML_FIRST + rgcmd2[0].cmdID,
  4514. SUCCEEDED(hr) && (rgcmd2[0].cmdf & OLECMDF_ENABLED));
  4515. }
  4516. }
  4517. }
  4518. else if (GetMenuFromID(_hmenuCur, FCIDM_MENU_FILE) == hmInit)
  4519. {
  4520. if (_pmsot)
  4521. {
  4522. TraceMsg(0, "sdv TR _OnInitMenuPopup : step 5");
  4523. OLECMD rgcmds[] = {
  4524. { OLECMDID_PRINT, 0 },
  4525. { OLECMDID_PAGESETUP, 0 },
  4526. { OLECMDID_PROPERTIES, 0 },
  4527. { OLECMDID_SAVE, 0 },
  4528. { OLECMDID_SAVEAS, 0 },
  4529. { OLECMDID_PRINTPREVIEW, 0 },
  4530. };
  4531. _pmsot->QueryStatus(NULL, ARRAYSIZE(rgcmds), rgcmds, NULL);
  4532. // Adding a comment for my sanity: we use SHDVID_PRINTFRAME instead
  4533. // of OLECMDID_PRINT because IE40 is going to support the printing
  4534. // of entire framesets, instead of the current behavior or forwarding
  4535. // the command to the active frame.
  4536. //
  4537. OLECMD rgcmds1[] = {
  4538. { SHDVID_PRINTFRAME, 0 },
  4539. };
  4540. _pmsot->QueryStatus(&CGID_ShellDocView, ARRAYSIZE(rgcmds1), rgcmds1, NULL);
  4541. //
  4542. // If OLECMDID_SAVEAS is not supported (neither ENABLED nor
  4543. // SUPPORTED is set) by the DocObject, check if the object
  4544. // support IPersistFile. If it does, enable it. Note that
  4545. // this mechanism allows the DocObject to disable this menu
  4546. // item (by setting only OLECMDF_SUPPORTED). (SatoNa)
  4547. //
  4548. ASSERT(rgcmds[4].cmdID == OLECMDID_SAVEAS);
  4549. // Only apply the save as restriction to the browser. If it is the
  4550. // browser, and save as is restricted, then make the item disappear.
  4551. if ( (_dwAppHack & BROWSERFLAG_MSHTML) &&
  4552. SHRestricted2( REST_NoBrowserSaveAs, NULL, 0 ))
  4553. rgcmds[4].cmdf &= ~(OLECMDF_ENABLED | OLECMDF_SUPPORTED);
  4554. else if (!(rgcmds[4].cmdf & (OLECMDF_ENABLED | OLECMDF_SUPPORTED)))
  4555. {
  4556. IPersistFile* ppf;
  4557. ASSERT(_pole);
  4558. HRESULT hresT = _pole->QueryInterface(IID_IPersistFile, (void **)&ppf);
  4559. if (SUCCEEDED(hresT))
  4560. {
  4561. TraceMsg(DM_APPHACK, "APPHACK DOH Enabling SaveAs menu for Excel95");
  4562. rgcmds[4].cmdf |= OLECMDF_ENABLED;
  4563. ppf->Release();
  4564. }
  4565. }
  4566. if (SHRestricted2(REST_NoPrinting, NULL, 0))
  4567. {
  4568. rgcmds[0].cmdf &= ~(OLECMDF_ENABLED | OLECMDF_SUPPORTED); // print
  4569. rgcmds[1].cmdf &= ~(OLECMDF_ENABLED | OLECMDF_SUPPORTED); // page setup
  4570. rgcmds[5].cmdf &= ~(OLECMDF_ENABLED | OLECMDF_SUPPORTED); // print preview
  4571. }
  4572. //
  4573. // APPHACK: Office apps do not enable "Save" correctly.
  4574. // Automatically enable it if the moniker is a FILE moniker
  4575. // AND the document has been altered by the user.
  4576. //
  4577. if (_fFileProtocol && _IsDirty(NULL))
  4578. {
  4579. if (!(rgcmds[3].cmdf & OLECMDF_ENABLED))
  4580. {
  4581. TraceMsg(DM_APPHACK, "APPHACK DOH Enabling Save for Office Apps");
  4582. }
  4583. rgcmds[3].cmdf |= OLECMDF_ENABLED;
  4584. }
  4585. // Remove/disable/enable the "Print" command as appropriate.
  4586. // Excel doesn't set SUPPORTED bit when it sets ENABLED bit
  4587. // so we have to check both bits.
  4588. _EnableRemoveMenuItem(hmInit, rgcmds[0].cmdf, DVIDM_PRINT);
  4589. _EnableMenuItem(hmInit, DVIDM_PAGESETUP,
  4590. (rgcmds[1].cmdf & OLECMDF_ENABLED));
  4591. _EnableMenuItem(hmInit, DVIDM_PROPERTIES,
  4592. (rgcmds[2].cmdf & OLECMDF_ENABLED));
  4593. _EnableRemoveMenuItem(hmInit, rgcmds[3].cmdf, DVIDM_SAVE);
  4594. _EnableRemoveMenuItem(hmInit, rgcmds[4].cmdf, DVIDM_SAVEASFILE);
  4595. _EnableRemoveMenuItem(hmInit, rgcmds[5].cmdf, DVIDM_PRINTPREVIEW);
  4596. _EnableRemoveMenuItem(hmInit, rgcmds1[0].cmdf, DVIDM_PRINTFRAME);
  4597. HMENU hmFileNew = SHGetMenuFromID(hmInit, DVIDM_NEW);
  4598. if (hmFileNew)
  4599. {
  4600. const static struct {
  4601. LPCTSTR pszClient;
  4602. UINT idCmd;
  4603. } s_Clients[] = {
  4604. { NEW_MAIL_DEF_KEY, DVIDM_NEWMESSAGE },
  4605. { NEW_CONTACTS_DEF_KEY, DVIDM_NEWCONTACT },
  4606. { NEW_NEWS_DEF_KEY, DVIDM_NEWPOST },
  4607. { NEW_APPOINTMENT_DEF_KEY, DVIDM_NEWAPPOINTMENT },
  4608. { NEW_MEETING_DEF_KEY, DVIDM_NEWMEETING },
  4609. { NEW_TASK_DEF_KEY, DVIDM_NEWTASK },
  4610. { NEW_TASKREQUEST_DEF_KEY, DVIDM_NEWTASKREQUEST },
  4611. { NEW_JOURNAL_DEF_KEY, DVIDM_NEWJOURNAL },
  4612. { NEW_NOTE_DEF_KEY, DVIDM_NEWNOTE },
  4613. { NEW_CALL_DEF_KEY, DVIDM_CALL }
  4614. };
  4615. BOOL bItemRemoved = FALSE;
  4616. for (int i = 0; i < ARRAYSIZE(s_Clients); i++)
  4617. {
  4618. if (!SHIsRegisteredClient(s_Clients[i].pszClient))
  4619. {
  4620. if (RemoveMenu(hmFileNew, s_Clients[i].idCmd, MF_BYCOMMAND))
  4621. bItemRemoved = TRUE;
  4622. }
  4623. }
  4624. // Menu item "File/New/Window Ctrl+N" needs to be disabled if the restriction is set
  4625. if( SHRestricted2W(REST_NoOpeninNewWnd, NULL, 0))
  4626. {
  4627. EnableMenuItem(hmFileNew, DVIDM_NEWWINDOW, MF_BYCOMMAND | MF_GRAYED);
  4628. }
  4629. if (bItemRemoved) // ensure the last item is not a separator
  4630. _SHPrettyMenu(hmFileNew);
  4631. }
  4632. }
  4633. }
  4634. else if (GetMenuFromID(_hmenuCur, FCIDM_VIEWFONTS) == hmInit
  4635. || GetMenuFromID(_hmenuCur, FCIDM_ENCODING) == hmInit)
  4636. {
  4637. if (_pmsot)
  4638. {
  4639. // Handling fonts popup in view menu
  4640. OLECMD rgcmd[] = {
  4641. { SHDVID_GETFONTMENU, 0 },
  4642. { SHDVID_GETMIMECSETMENU, 0 },
  4643. };
  4644. _pmsot->QueryStatus(&CGID_ShellDocView, ARRAYSIZE(rgcmd), rgcmd, NULL);
  4645. int idx = (GetMenuFromID(_hmenuCur, FCIDM_VIEWFONTS) == hmInit ? 0 : 1);
  4646. if (rgcmd[idx].cmdf & OLECMDF_ENABLED)
  4647. {
  4648. VARIANTARG v = {0};
  4649. HRESULT hr;
  4650. hr = _pmsot->Exec(&CGID_ShellDocView, rgcmd[idx].cmdID, 0, NULL, &v);
  4651. if (S_OK == hr)
  4652. {
  4653. // (on NT/Unix) DestroyMenu(hmInit) shouldn't work, because
  4654. // we're inside the processing of WM_INITMENUPOPUP message
  4655. // for hmInit. DestroyMenu will make the hmInit handle
  4656. // invalid.
  4657. //
  4658. // Instead of that we'll empty hmInit and copy hmenuFonts
  4659. // over. hmenuFonts will be destroyed to prevent the
  4660. // memory leak.
  4661. //
  4662. //
  4663. MENUITEMINFO mii;
  4664. UINT uItem = 0;
  4665. //$ WIN64: mshtml\src\site\base\formmso.cxx needs to return VT_INT_PTR instead
  4666. // HMENU hmenuFonts = (HMENU)v.byref;
  4667. HMENU hmenuFonts = (HMENU)LongToHandle(v.lVal);
  4668. #ifndef UNIX
  4669. // deleting menu while processing WM_INITMENUPOPUP
  4670. // can cause assertion failure on NT. However, copying
  4671. // submenu using InsertMenuItem() doesn't work on Win9x.
  4672. // see the comments above and Menu_Replace() in menu.cpp
  4673. //
  4674. if (!g_fRunningOnNT)
  4675. DestroyMenu(hmInit);
  4676. #endif
  4677. mii.cbSize = sizeof(mii);
  4678. mii.fMask = MIIM_ID|MIIM_SUBMENU;
  4679. while (GetMenuItemInfo(hmenuFonts, uItem, TRUE, &mii))
  4680. {
  4681. if (idx == 1 && mii.hSubMenu != NULL)
  4682. {
  4683. UINT uItemSub = 0;
  4684. HMENU hMenuSub = mii.hSubMenu;
  4685. while (GetMenuItemInfo(hMenuSub, uItemSub, TRUE, &mii))
  4686. {
  4687. mii.wID += DVIDM_MSHTML_FIRST;
  4688. SetMenuItemInfo(hMenuSub, uItemSub++, TRUE, &mii);
  4689. }
  4690. }
  4691. else
  4692. {
  4693. mii.wID += DVIDM_MSHTML_FIRST;
  4694. SetMenuItemInfo(hmenuFonts, uItem, TRUE, &mii);
  4695. }
  4696. uItem++;
  4697. }
  4698. #ifndef UNIX
  4699. if (!g_fRunningOnNT)
  4700. {
  4701. mii.cbSize = sizeof(mii);
  4702. mii.fMask = MIIM_SUBMENU;
  4703. mii.hSubMenu = hmenuFonts;
  4704. SetMenuItemInfo(_hmenuCur,
  4705. (idx == 0 ? FCIDM_VIEWFONTS:FCIDM_ENCODING),
  4706. FALSE, &mii);
  4707. }
  4708. else
  4709. #endif
  4710. {
  4711. Menu_Replace(hmInit, hmenuFonts);
  4712. DestroyMenu(hmenuFonts);
  4713. }
  4714. }
  4715. }
  4716. }
  4717. }
  4718. else if (GetMenuFromID(_hmenuCur, FCIDM_MENU_TOOLS) == hmInit ||
  4719. GetMenuFromID(_hmenuCur, FCIDM_MENU_HELP) == hmInit)
  4720. {
  4721. // Add Tools and help Menu Extensions
  4722. if (_pBrowsExt)
  4723. {
  4724. _pBrowsExt->OnCustomizableMenuPopup(_hmenuCur, hmInit);
  4725. }
  4726. }
  4727. }
  4728. //
  4729. // ATTEMPT: Handling WM_SETFOCUS message here caused several problems
  4730. // under IE 3.0. Since we can't find any code scenario that requires
  4731. // this code, I'm yanking out. If might introduce a new bug, but dealing
  4732. // with those bugs is probably better than dealing with this code.
  4733. // (SatoNa)
  4734. //
  4735. /*----------------------------------------------------------
  4736. Purpose: Determines if this message should be forwarded onto
  4737. the object.
  4738. Returns: TRUE if the message needs to be forwarded
  4739. */
  4740. BOOL CDocObjectHost::_ShouldForwardMenu(UINT uMsg, WPARAM wParam, LPARAM lParam)
  4741. {
  4742. switch (uMsg)
  4743. {
  4744. case WM_MENUSELECT:
  4745. {
  4746. // In USER menu bars, the first menuselect will be sent for the
  4747. // selected top-level menu item, in which case hmenu == _hmenuCur.
  4748. // We expect menubands to behave similarly.
  4749. //
  4750. // We check that hmenu == _hmenuCur because we only keep a list
  4751. // of the top-level popup menus. We don't keep track of any
  4752. // cascading submenus. We should only need to check who owns
  4753. // the menu at the initial popup, all subsequent messages for
  4754. // that menu should go to the same destination (frame or object).
  4755. //
  4756. // The same goes for CShellBrowser::_ShouldForwardMenu().
  4757. //
  4758. HMENU hmenu = GET_WM_MENUSELECT_HMENU(wParam, lParam);
  4759. if (hmenu && (MF_POPUP & GET_WM_MENUSELECT_FLAGS(wParam, lParam)))
  4760. {
  4761. HMENU hmenuSub = GetSubMenu(hmenu, GET_WM_MENUSELECT_CMD(wParam, lParam));
  4762. if (hmenu == _hmenuCur)
  4763. {
  4764. // Normal case, where we just look at the topmost popdown menus
  4765. _fForwardMenu = _menulist.IsObjectMenu(hmenuSub);
  4766. }
  4767. else if (_menulist.IsObjectMenu(hmenuSub))
  4768. {
  4769. // This happens if the cascading submenu (micro-merged help menu for
  4770. // example) should be forwarded on, but the parent menu should
  4771. // not.
  4772. _fForwardMenu = TRUE;
  4773. }
  4774. else if (GetMenuFromID(_hmenuCur, FCIDM_MENU_HELP) == hmenu
  4775. && !_menulist.IsObjectMenu(hmenu) )
  4776. {
  4777. // 80430 Appcompat: notice that our menu fowarding doesn't work for the
  4778. // micro-merged Help menu. If the user previously selected the merged
  4779. // submenu, and we end up here, it means a non-merged submenu was just
  4780. // selected and our _fForwardMenu was still set to TRUE. If we don't
  4781. // reset it, the next WM_INITMENUPOPUP gets forwarded, which crashes Visio.
  4782. //
  4783. // We know that a submenu of the Help menu has just popped up, and we know
  4784. // the submenu belongs to us. So don't forward to the docobj until the
  4785. // next popup.
  4786. _fForwardMenu = FALSE;
  4787. }
  4788. }
  4789. break;
  4790. }
  4791. case WM_COMMAND:
  4792. if (_fForwardMenu)
  4793. {
  4794. // Stop forwarding menu messages after WM_COMMAND
  4795. _fForwardMenu = FALSE;
  4796. // If it wasn't from an accelerator, forward it
  4797. if (0 == GET_WM_COMMAND_CMD(wParam, lParam))
  4798. return TRUE;
  4799. }
  4800. break;
  4801. }
  4802. return _fForwardMenu;
  4803. }
  4804. /*----------------------------------------------------------
  4805. Purpose: Forwards messages to the in-place object.
  4806. This is used to forward menu messages to the object for
  4807. menu bands, since the menu bands do not work with the
  4808. standard OLE FrameFilterWndProc.
  4809. Also, the help menu is sometimes a combination of the
  4810. object and the frame. This function will forward as
  4811. appropriate.
  4812. */
  4813. LRESULT CDocObjectHost::_ForwardObjectMsg(UINT uMsg, WPARAM wParam, LPARAM lParam)
  4814. {
  4815. LRESULT lRet = 0L;
  4816. IOleInPlaceActiveObject *piact = _xao.GetObject();
  4817. ASSERT(IS_VALID_CODE_PTR(piact, IOleInPlaceActiveObject));
  4818. if (piact)
  4819. {
  4820. HWND hwnd;
  4821. piact->GetWindow(&hwnd);
  4822. ASSERT(IS_VALID_HANDLE(hwnd, WND));
  4823. if (hwnd)
  4824. {
  4825. if (uMsg == WM_COMMAND)
  4826. PostMessage(hwnd, uMsg, wParam, lParam);
  4827. else
  4828. lRet = SendMessage(hwnd, uMsg, wParam, lParam);
  4829. }
  4830. }
  4831. return lRet;
  4832. }
  4833. void CDocObjectHost::_OnMenuSelect(UINT id, UINT mf, HMENU hmenu)
  4834. {
  4835. if (_psb)
  4836. {
  4837. if (IsInRange(id, DVIDM_MSHTML_FIRST, DVIDM_MSHTML_LAST))
  4838. {
  4839. if (_pcmdMergedMenu) {
  4840. OLECMD rgcmd = { id - DVIDM_MSHTML_FIRST, 0 };
  4841. struct {
  4842. OLECMDTEXT cmdtxt;
  4843. WCHAR szExtra[MAX_PATH];
  4844. } cmdt;
  4845. cmdt.cmdtxt.cmdtextf = OLECMDTEXTF_STATUS;
  4846. cmdt.cmdtxt.cwActual = 0;
  4847. cmdt.cmdtxt.cwBuf = MAX_PATH;
  4848. cmdt.cmdtxt.rgwz[0] = 0;
  4849. HRESULT hresT=_pcmdMergedMenu->QueryStatus(&CGID_MSHTML, 1, &rgcmd, &cmdt.cmdtxt);
  4850. if (SUCCEEDED(hresT) && cmdt.cmdtxt.rgwz[0]) {
  4851. _psb->SetStatusTextSB(cmdt.cmdtxt.rgwz);
  4852. } else {
  4853. TraceMsg(DM_ERROR, "CDOH::_OnMenuSelect QueryStatus failed %x %d",
  4854. hresT, cmdt.cmdtxt.cwActual);
  4855. }
  4856. }
  4857. else
  4858. // An ASSERT was replaced with this TraceMsg to allow testing on Win9x.
  4859. // 70240 which reported the assert was pushed to IE6.
  4860. TraceMsg(TF_WARNING, "CDocObjectHost::_OnMenuSelect _pcmdMergedMenu == NULL");
  4861. }
  4862. else if (IsInRange(id, DVIDM_MENUEXT_FIRST, DVIDM_MENUEXT_LAST))
  4863. {
  4864. // Menu Extensions go here
  4865. if (_pBrowsExt)
  4866. {
  4867. _pBrowsExt->OnMenuSelect(id);
  4868. }
  4869. }
  4870. else
  4871. {
  4872. WCHAR wszT[MAX_STATUS_SIZE];
  4873. if (MLLoadStringW(IDS_HELP_OF(id), wszT, ARRAYSIZE(wszT)))
  4874. {
  4875. _psb->SetStatusTextSB(wszT);
  4876. }
  4877. }
  4878. }
  4879. }
  4880. LRESULT CDocObjectHost::v_WndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
  4881. {
  4882. LRESULT lRet = 0L;
  4883. switch(uMsg)
  4884. {
  4885. case WM_TIMER:
  4886. if (wParam == IDTIMER_PROGRESS)
  4887. {
  4888. _OnSetProgressPos(0, PROGRESS_TICK);
  4889. break;
  4890. }
  4891. else if (wParam == IDTIMER_PROGRESSFULL)
  4892. {
  4893. _OnSetProgressPos(-2, PROGRESS_RESET);
  4894. break;
  4895. }
  4896. else
  4897. {
  4898. #ifdef TEST_DELAYED_SHOWMSOVIEW
  4899. MessageBeep(0);
  4900. KillTimer(_hwnd, 100);
  4901. ActivateMe(NULL);
  4902. break;
  4903. #else
  4904. ASSERT(FALSE);
  4905. break;
  4906. #endif // TEST_DELAYED_SHOWMSOVIEW
  4907. }
  4908. /* WM_PICS_ASYNCCOMPLETE is posted by the async thread fetching ratings
  4909. * from label bureaus, etc.
  4910. */
  4911. case WM_PICS_ASYNCCOMPLETE:
  4912. {
  4913. TraceMsg(DM_PICS, "CDOH::v_WndProc got WM_PICS_ASYNCCOMPLETE");
  4914. PicsQuery pq;
  4915. HRESULT hr;
  4916. LPVOID lpvRatingDetails;
  4917. DWORD dwSerialComplete = (DWORD)lParam;
  4918. CPicsProcessor * pPicsProc = NULL;
  4919. if (::_GetPicsQuery(dwSerialComplete, &pq)) {
  4920. ::_RemovePicsQuery(dwSerialComplete);
  4921. hr = (HRESULT)wParam;
  4922. lpvRatingDetails = pq.lpvRatingDetails;
  4923. }
  4924. else {
  4925. hr = E_FAIL;
  4926. lpvRatingDetails = NULL;
  4927. }
  4928. pPicsProc = _GetPicsProcessorFromSerialNumber(dwSerialComplete);
  4929. if (pPicsProc)
  4930. {
  4931. pPicsProc->_GotLabel(hr, lpvRatingDetails, PICS_WAIT_FOR_ASYNC);
  4932. }
  4933. else
  4934. {
  4935. TraceMsg( DM_PICS, "CDOH::v_WndProc no PicsProc for ASYNCCOMPLETE %x", dwSerialComplete);
  4936. if ( lpvRatingDetails )
  4937. {
  4938. ::RatingFreeDetails(lpvRatingDetails);
  4939. lpvRatingDetails = NULL;
  4940. }
  4941. }
  4942. break;
  4943. }
  4944. case WM_PICS_ROOTDOWNLOADCOMPLETE:
  4945. {
  4946. TraceMsg(DM_PICS, "CDOH::v_WndProc got WM_PICS_ROOTDOWNLOADCOMPLETE %x", lParam);
  4947. if (_PicsProcBase._pRootDownload != NULL)
  4948. {
  4949. _PicsProcBase._pRootDownload->CleanUp();
  4950. ATOMICRELEASET(_PicsProcBase._pRootDownload,CPicsRootDownload);
  4951. }
  4952. break;
  4953. }
  4954. /* WM_PICS_ALLCHECKSCOMPLETE is posted when we finally want to either
  4955. * cancel the navigation or go through with it, according to ratings
  4956. * checks. Posting a message allows all denial blocking message loops
  4957. * to unwind before we cancel navigation, which could otherwise delete
  4958. * objects that still have functions operating on them.
  4959. */
  4960. case WM_PICS_ALLCHECKSCOMPLETE:
  4961. TraceMsg(DM_PICS, "CDOH::v_WndProc got WM_PICS_ALLCHECKSCOMPLETE, lParam=%x", lParam);
  4962. if (lParam == IDOK) {
  4963. if (!_fSetTarget)
  4964. {
  4965. TraceMsg(DM_PICS, "CDOH::v_WndProc(WM_PICS_ASYNCCOMPLETE) execing SHDVID_ACTIVATEMENOW");
  4966. _pmsoctBrowser->Exec(&CGID_ShellDocView, SHDVID_ACTIVATEMENOW, NULL, NULL, NULL);
  4967. }
  4968. else {
  4969. TraceMsg(DM_PICS, "CDOH::v_WndProc(WM_PICS_ASYNCCOMPLETE) not execing SHDVID_ACTIVATEMENOW");
  4970. }
  4971. }
  4972. else {
  4973. ASSERT(!_fSetTarget);
  4974. TraceMsg(DM_PICS, "CDOH::v_WndProc(WM_PICS_ASYNCCOMPLETE) calling _CancelPendingNavigation");
  4975. _CancelPendingNavigation(FALSE);
  4976. // _pmsoctBrowser->Exec(NULL, OLECMDID_STOP, NULL, NULL, NULL);
  4977. }
  4978. break;
  4979. /* WM_PICS_DOBLOCKINGUI is posted when we decide we need to put up
  4980. * denial UI. Posting a message allows download of this object and
  4981. * other frames to continue while we post the UI, which in turn allows
  4982. * any denials from other frames to be coalesced into the one dialog.
  4983. */
  4984. case WM_PICS_DOBLOCKINGUI:
  4985. {
  4986. TraceMsg(DM_PICS, "CDOH::v_WndProc got WM_PICS_DOBLOCKINGUI %x", lParam);
  4987. CPicsProcessor * pPicsProc = _GetPicsProcessorFromKey(lParam);
  4988. if (pPicsProc)
  4989. {
  4990. UINT id = pPicsProc->_PicsBlockingDialog();
  4991. if (pPicsProc->_pPrivWindow)
  4992. {
  4993. ASSERT( _fDocCanNavigate );
  4994. TraceMsg(DM_PICS, "CDOH::v_WndProc(WM_PICS_DOBLOCKINGUI) posting WM_PICS_RESULTTOPRIVWIN");
  4995. if (!PostMessage( _hwnd, WM_PICS_RESULTTOPRIVWIN, id, lParam))
  4996. {
  4997. TraceMsg(DM_PICS, "CDOH::v_WndProc(WM_PICS_DOBLOCKINGUI) couldn't post message!");
  4998. }
  4999. }
  5000. else
  5001. {
  5002. TraceMsg(DM_PICS, "CDOH::v_WndProc(WM_PICS_DOBLOCKINGUI) posting WM_PICS_ALLCHECKSCOMPLETE");
  5003. if (!PostMessage(_hwnd, WM_PICS_ALLCHECKSCOMPLETE, 0, id))
  5004. {
  5005. TraceMsg(DM_PICS, "CDOH::v_WndProc(WM_PICS_DOBLOCKINGUI) couldn't post message!");
  5006. }
  5007. }
  5008. // We may have been terminated while the
  5009. // dialog was up -- finish cleaning up here.
  5010. if ( !pPicsProc->_fInDialog
  5011. && pPicsProc->_fTerminated
  5012. && pPicsProc != &_PicsProcBase)
  5013. {
  5014. delete pPicsProc;
  5015. }
  5016. }
  5017. else
  5018. {
  5019. TraceMsg( DM_PICS, "CDOH::v_WndProc no PicsProc for DOBLOCKINGUI");
  5020. }
  5021. }
  5022. break;
  5023. case WM_PICS_RESULTTOPRIVWIN:
  5024. {
  5025. ASSERT( _fDocCanNavigate );
  5026. TraceMsg(DM_PICS, "CDOH::v_WndProc got WM_PICS_RESULTTOPRIVWIN %x", lParam);
  5027. CPicsProcessor * pPicsProc = _GetPicsProcessorFromKey(lParam);
  5028. if (pPicsProc)
  5029. {
  5030. ASSERT( pPicsProc->_pPrivWindow );
  5031. IHTMLPrivateWindow * pPrivWindow = pPicsProc->_pPrivWindow;
  5032. pPrivWindow->AddRef();
  5033. if (pPicsProc->_pRootDownload != NULL)
  5034. {
  5035. pPicsProc->_pRootDownload->CleanUp();
  5036. ATOMICRELEASET(pPicsProc->_pRootDownload,CPicsRootDownload);
  5037. }
  5038. // Remove ourselves from the list
  5039. _RemovePicsProcessorByKey( lParam );
  5040. // Make Trident let go of our command target
  5041. pPrivWindow->SetPICSTarget(NULL);
  5042. // Tell the window the answer
  5043. pPrivWindow->PICSComplete( wParam == IDOK );
  5044. pPrivWindow->Release();
  5045. }
  5046. else
  5047. {
  5048. TraceMsg( DM_PICS, "CDOH::v_WndProc no PicsProc for WM_PICS_RESULTTOPRIVWIN");
  5049. }
  5050. }
  5051. break;
  5052. case WM_LBUTTONDOWN:
  5053. case WM_RBUTTONDOWN:
  5054. MessageBeep(0);
  5055. break;
  5056. case WM_MENUSELECT:
  5057. if (_ShouldForwardMenu(uMsg, wParam, lParam))
  5058. lRet = _ForwardObjectMsg(uMsg, wParam, lParam);
  5059. else
  5060. {
  5061. UINT uMenuFlags = GET_WM_MENUSELECT_FLAGS(wParam, lParam);
  5062. WORD wID = GET_WM_MENUSELECT_CMD(wParam, lParam);
  5063. HMENU hMenu = GET_WM_MENUSELECT_HMENU(wParam, lParam);
  5064. // Check for popup menus so we can display help strings for them
  5065. if (uMenuFlags & MF_POPUP)
  5066. {
  5067. MENUITEMINFO miiSubMenu;
  5068. miiSubMenu.cbSize = SIZEOF(MENUITEMINFO);
  5069. miiSubMenu.fMask = MIIM_SUBMENU|MIIM_ID;
  5070. if (GetMenuItemInfoWrap(hMenu, wID, TRUE, &miiSubMenu))
  5071. {
  5072. // Change the parameters to simulate a "normal" menu item
  5073. wID = (WORD)miiSubMenu.wID;
  5074. }
  5075. }
  5076. _OnMenuSelect(wID, uMenuFlags, hMenu);
  5077. }
  5078. break;
  5079. case WM_INITMENUPOPUP:
  5080. if (_ShouldForwardMenu(uMsg, wParam, lParam))
  5081. lRet = _ForwardObjectMsg(uMsg, wParam, lParam);
  5082. else
  5083. _OnInitMenuPopup((HMENU)wParam, LOWORD(lParam), HIWORD(lParam));
  5084. break;
  5085. case WM_DRAWITEM:
  5086. case WM_MEASUREITEM:
  5087. if (_ShouldForwardMenu(uMsg, wParam, lParam))
  5088. lRet = _ForwardObjectMsg(uMsg, wParam, lParam);
  5089. else
  5090. goto DoDefault;
  5091. break;
  5092. case WM_NOTIFY:
  5093. _OnNotify((LPNMHDR)lParam);
  5094. break;
  5095. case WM_COMMAND:
  5096. _OnCommand(HIWORD(wParam), LOWORD(wParam), (HWND)lParam);
  5097. break;
  5098. case WM_SIZE:
  5099. if (_pmsov)
  5100. {
  5101. RECT rcClient;
  5102. GetClientRect(_hwnd, &rcClient);
  5103. //
  5104. // We should call ResizeBorder only if the browser is
  5105. // not an IOleInPlaceUIWindow.
  5106. //
  5107. if (_pipu==NULL)
  5108. {
  5109. TraceMsg(TF_SHDUIACTIVATE, "DOH::WM_SIZE calling _piact->ResizeBorder");
  5110. _xao.ResizeBorder(&rcClient, &_dof, TRUE);
  5111. }
  5112. _rcView.left = _bwTools.left;
  5113. _rcView.top = _bwTools.top;
  5114. _rcView.right = rcClient.right - _bwTools.right;
  5115. _rcView.bottom = rcClient.bottom - _bwTools.bottom;
  5116. TraceMsg(TF_SHDUIACTIVATE, "DOH::WM_SIZE calling SetRect (%d, %d, %d, %d)", _rcView.left, _rcView.top, _rcView.right, _rcView.bottom);
  5117. _pmsov->SetRect(&_rcView);
  5118. }
  5119. _PlaceProgressBar(TRUE);
  5120. break;
  5121. //
  5122. // ATTEMPT: Handling WM_SETFOCUS message here caused several problems
  5123. // under IE 3.0. Since we can't find any code scenario that requires
  5124. // this code, I'm yanking out. If might introduce a new bug, but dealing
  5125. // with those bugs is probably better than dealing with this code.
  5126. // (SatoNa)
  5127. //
  5128. case WM_PRINT:
  5129. _OnPaint((HDC)wParam);
  5130. break;
  5131. case WM_QUERYNEWPALETTE:
  5132. case WM_PALETTECHANGED:
  5133. case WM_SYSCOLORCHANGE:
  5134. case WM_DISPLAYCHANGE:
  5135. case WM_ENTERSIZEMOVE:
  5136. case WM_EXITSIZEMOVE:
  5137. {
  5138. HWND hwndT;
  5139. if (_pole && SUCCEEDED(IUnknown_GetWindow(_pole, &hwndT)) && hwndT)
  5140. return SendMessage(hwndT, uMsg, wParam, lParam);
  5141. return 0;
  5142. }
  5143. case WM_PAINT:
  5144. PAINTSTRUCT ps;
  5145. HDC hdc;
  5146. hdc = BeginPaint(_hwnd, &ps);
  5147. // we don't need them to paint into our dc...
  5148. // docobj has own hwnd.
  5149. //_OnPaint(hdc);
  5150. EndPaint(_hwnd, &ps);
  5151. break;
  5152. case WM_LBUTTONUP:
  5153. if (_uState != SVUIA_ACTIVATE_FOCUS) {
  5154. SetFocus(_hwnd);
  5155. }
  5156. break;
  5157. case WM_ERASEBKGND:
  5158. // Checking _bsc._fBinding will catch the first page case.
  5159. if (_fDrawBackground ||
  5160. (!(_dwAppHack & BROWSERFLAG_NEVERERASEBKGND)
  5161. && ((_pmsov && _uState!=SVUIA_DEACTIVATE)
  5162. || _bsc._fBinding)))
  5163. {
  5164. PAINTMSG("WM_ERASEBKGND", this);
  5165. goto DoDefault;
  5166. }
  5167. // Don't draw WM_ERASEBKGND if we have no view activated.
  5168. return TRUE; // TRUE = fErased
  5169. case WM_HELP:
  5170. //
  5171. // Give it to the parent to do. we need to do this in case we're hosted as a
  5172. // control
  5173. //
  5174. {
  5175. IOleCommandTarget *pcmdtTop;
  5176. if (SUCCEEDED(QueryService(SID_STopLevelBrowser, IID_IOleCommandTarget, (void **)&pcmdtTop))) {
  5177. pcmdtTop->Exec(&CGID_ShellDocView, SHDVID_HELP, 0, NULL, NULL);
  5178. pcmdtTop->Release();
  5179. }
  5180. // do nothing in failure... let the parent own completely
  5181. }
  5182. break;
  5183. case WM_WININICHANGE:
  5184. _PlaceProgressBar(TRUE);
  5185. break;
  5186. default:
  5187. // Handle the MSWheel message
  5188. if ((uMsg == GetWheelMsg()) && _pole)
  5189. {
  5190. HWND hwndT;
  5191. // If for some reason our window has focus we just need to
  5192. // swallow the message. If we don't we may create an infinite loop
  5193. // because most clients send the message to the focus window.
  5194. if (GetFocus() == _hwnd)
  5195. return 1;
  5196. //
  5197. // try to find a window to forward along to
  5198. //
  5199. if (SUCCEEDED(IUnknown_GetWindow(_pole, &hwndT)))
  5200. {
  5201. PostMessage(hwndT, uMsg, wParam, lParam);
  5202. return 1;
  5203. }
  5204. // Fall through...
  5205. }
  5206. DoDefault:
  5207. return DefWindowProc(hwnd, uMsg, wParam, lParam);
  5208. }
  5209. return lRet;
  5210. }
  5211. const TCHAR c_szViewClass[] = TEXT("Shell DocObject View");
  5212. void CDocObjectHost::_RegisterWindowClass(void)
  5213. {
  5214. WNDCLASS wc = {0};
  5215. wc.style = CS_PARENTDC;
  5216. wc.lpfnWndProc = s_WndProc ;
  5217. //wc.cbClsExtra = 0;
  5218. wc.cbWndExtra = SIZEOF(CDocObjectHost*);
  5219. wc.hInstance = g_hinst ;
  5220. //wc.hIcon = NULL ;
  5221. //wc.hCursor = NULL;
  5222. wc.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
  5223. //wc.lpszMenuName = NULL ;
  5224. wc.lpszClassName = c_szViewClass;
  5225. SHRegisterClass(&wc);
  5226. }
  5227. void CDocObjectHost::_InitOleObject()
  5228. {
  5229. if (!_fClientSiteSet)
  5230. {
  5231. _fClientSiteSet = TRUE;
  5232. #ifdef DEBUG
  5233. IOleClientSite * pcliT = NULL;
  5234. if (SUCCEEDED(_pole->GetClientSite(&pcliT)) && pcliT)
  5235. {
  5236. // Trident now grabs the client site from the bind context.
  5237. // We don't want to hit this assertin this case (pcliT==this).
  5238. //
  5239. AssertMsg(IsSameObject(pcliT, SAFECAST(this, IOleClientSite*)),
  5240. TEXT("CDocObjectHost::_InitOleObject _pole (%x) already has a client site (%x) (this=%x)"),
  5241. _pole, pcliT, this);
  5242. pcliT->Release();
  5243. }
  5244. #endif
  5245. HRESULT hresT = _pole->SetClientSite(this);
  5246. if (FAILED(hresT))
  5247. {
  5248. TraceMsg(TF_SHDAPPHACK, "DOH::_InitOleObject SetClientSite failed (%x). Don't in-place navigate", hresT);
  5249. _dwAppHack |= BROWSERFLAG_DONTINPLACE;
  5250. }
  5251. ASSERT(NULL==_pvo);
  5252. _pole->QueryInterface(IID_IViewObject, (void **)&_pvo);
  5253. if (_pvo)
  5254. {
  5255. TraceMsg(DM_DEBUGTFRAME, "CDocObjectHost::_InitOleObject about call SetAdvise on %x (%x)", _pole, this);
  5256. _pvo->SetAdvise(DVASPECT_CONTENT, ADVF_PRIMEFIRST, this);
  5257. }
  5258. //
  5259. // According to SteveRa (Word developer), a word object has an
  5260. // internal flag which indicates whether or not it is created
  5261. // from a file. If that flag is set, UIActivate will open the
  5262. // window in Word. Calling SetHostName will reset that flag.
  5263. //
  5264. _GetAppHack(); // Make it sure that we have _dwAppHack
  5265. if (_fCallSetHostName())
  5266. {
  5267. TraceMsg(TF_SHDAPPHACK, "DOH::_InitOleObject calling SetHostName for Word95");
  5268. WCHAR wszTitle[128];
  5269. MLLoadStringW(IDS_TITLE, wszTitle, ARRAYSIZE(wszTitle));
  5270. _pole->SetHostNames(wszTitle, wszTitle);
  5271. }
  5272. }
  5273. }
  5274. BOOL CDocObjectHost::_OperationIsHyperlink()
  5275. {
  5276. _ChainBSC();
  5277. DWORD dw = 0;
  5278. BINDINFO bindinfo;
  5279. ZeroMemory(&bindinfo, sizeof(BINDINFO));
  5280. bindinfo.cbSize = sizeof(BINDINFO);
  5281. HRESULT hr = _bsc.GetBindInfo(&dw, &bindinfo);
  5282. if (SUCCEEDED(hr))
  5283. {
  5284. ReleaseBindInfo(&bindinfo);
  5285. return BOOLIFY(dw & BINDF_HYPERLINK);
  5286. }
  5287. return FALSE;
  5288. }
  5289. //+-----------------------------------------------------------------------------
  5290. //
  5291. // IE Media Bar hook
  5292. // -----------------
  5293. // At least one and only one of the args must be non-null.
  5294. //
  5295. // If pbc is non-null:
  5296. // If this bind ctx is for a media url and was delegated to shdocvw from trident,
  5297. // trident has already stored the mime-type as a string on the bind ctx.
  5298. //
  5299. // If pwzMimeType is non-null:
  5300. // The given mime type is used
  5301. //
  5302. // Ask the media bar if it wants to handle this mime-type and if it does,
  5303. // return true, else return false.
  5304. //
  5305. //-------------------------------------------------------------------------------
  5306. BOOL CDocObjectHost::_DelegateToMediaBar(IBindCtx * pbc, LPCWSTR pwzMimeType)
  5307. {
  5308. USES_CONVERSION;
  5309. LPWSTR pstrMime = NULL;
  5310. TCHAR szURL[MAX_URL_STRING];
  5311. BOOL fRet = FALSE;
  5312. CComVariant svarMime(pstrMime);
  5313. CComPtr<IUnknown> spUnkObj;
  5314. CComPtr<IOleCommandTarget> spOCTMimeType;
  5315. CComPtr<IOleCommandTarget> spOCTMediaBar;
  5316. // We want to delegate only under the following conditions:
  5317. // 1. In Explorer or IE
  5318. // 2. If autoplay is enabled
  5319. // 3. If autoplay is not turned off for the first navigation
  5320. // 4. If NOT NT4 or IA64 (WMP7/8 doesn't support these platforms)
  5321. // 5. If WMP7/8 is present (if it isn't, we will try to fault-in once.)
  5322. // 6. the media bar isn't restricted
  5323. if (!(IsInternetExplorerApp()
  5324. && CMediaBarUtil::GetAutoplay()
  5325. && !SHRestricted2(REST_No_LaunchMediaBar, NULL, 0)
  5326. && CMediaBarUtil::IsWMP7OrGreaterCapable()
  5327. && FAILED(QueryService(CLSID_MediaBand, IID_PPV_ARG(IUnknown, &spUnkObj)))))
  5328. {
  5329. goto done;
  5330. }
  5331. // release so we can reuse the pointer later
  5332. spUnkObj.Release();
  5333. // get the current URL
  5334. if (FAILED(_GetCurrentPage(szURL, ARRAYSIZE(szURL), TRUE)))
  5335. goto done;
  5336. // At least one and only one of the args must be non-null.
  5337. if (pbc && !pwzMimeType)
  5338. {
  5339. // get the custom parameter that trident uses to set the media mime-type
  5340. // QI for IOleCommandTarged to access the mime-type string.
  5341. // get the mime-type string
  5342. if (FAILED(pbc->GetObjectParam(L"MediaBarMime", &spUnkObj))
  5343. || FAILED(spUnkObj->QueryInterface(IID_PPV_ARG(IOleCommandTarget, &spOCTMimeType)))
  5344. || FAILED(spOCTMimeType->Exec(&CGID_DownloadObjectBindContext, 0, NULL, NULL, &svarMime)))
  5345. goto done;
  5346. }
  5347. else if (!pbc && pwzMimeType)
  5348. {
  5349. svarMime = pwzMimeType;
  5350. }
  5351. else
  5352. {
  5353. ASSERT(FALSE && L"Either one of bind ctx or mime-type is expected");
  5354. goto done;
  5355. }
  5356. // proceed only if mime type string is available
  5357. if ((VT_BSTR == svarMime.vt)
  5358. && svarMime.bstrVal)
  5359. {
  5360. // Ask the media bar if it wants to handle this mime-type
  5361. BOOL fShouldPlay = FALSE;
  5362. BOOL fShow = TRUE;
  5363. CComVariant svarUrl;
  5364. HRESULT hr = S_OK;
  5365. svarUrl = !StrCmpNIW(WZ_RADIO_PROTOCOL, szURL, wcslen(WZ_RADIO_PROTOCOL)) ? (szURL + wcslen(WZ_RADIO_PROTOCOL)) : szURL;
  5366. if (!(V_BSTR(&svarMime) && V_BSTR(&svarUrl)))
  5367. goto done;
  5368. // check if we can play this mime type
  5369. hr = CMediaBarUtil::ShouldPlay(W2T(V_BSTR(&svarMime)), &fShouldPlay);
  5370. if (FAILED(hr)
  5371. || (!fShouldPlay))
  5372. {
  5373. goto done;
  5374. }
  5375. // ShouldPlay returns S_FALSE if this is the first time playing this mime type.
  5376. if (S_FALSE == hr)
  5377. {
  5378. BOOL bSaveSetting = FALSE;
  5379. LONGLONG iRetCode = PLAYMIME_NO;
  5380. iRetCode = DialogBoxParam(MLGetHinst(), MAKEINTRESOURCE(IDD_MEDIA_MIME), _hwnd, s_MimeDlgProc, NULL);
  5381. switch (iRetCode)
  5382. {
  5383. case PLAYMIME_YES:
  5384. {
  5385. fShouldPlay = TRUE;
  5386. bSaveSetting = FALSE;
  5387. }
  5388. break;
  5389. case PLAYMIME_YESSAVE:
  5390. {
  5391. fShouldPlay = TRUE;
  5392. bSaveSetting = TRUE;
  5393. }
  5394. break;
  5395. case PLAYMIME_NO:
  5396. {
  5397. fShouldPlay = FALSE;
  5398. bSaveSetting = FALSE;
  5399. }
  5400. break;
  5401. case PLAYMIME_NOSAVE:
  5402. {
  5403. fShouldPlay = FALSE;
  5404. bSaveSetting = TRUE;
  5405. }
  5406. break;
  5407. default:
  5408. {
  5409. ASSERT(FALSE && L"Unexpected return value");
  5410. }
  5411. break;
  5412. }
  5413. // check if the setting needs to be saved
  5414. if (TRUE == bSaveSetting)
  5415. {
  5416. DWORD dwVal = fShouldPlay ? 0x1 : 0x0;
  5417. hr = CMediaBarUtil::SetMediaRegValue(V_BSTR(&svarMime), REG_BINARY, (void*) &dwVal, (DWORD) 1, TRUE);
  5418. ASSERT(SUCCEEDED(hr));
  5419. }
  5420. // Bail if user told us not to play this mime type
  5421. if (!fShouldPlay)
  5422. goto done;
  5423. }
  5424. else
  5425. {
  5426. // "don't prompt" means "play all types", unless autoplay is turned off
  5427. // in which case we have already bailed
  5428. }
  5429. // Yay. They want to try out our feature. But WAIT. We need WMP7/8. Is that installed? No? Well, let's go get it.
  5430. // If the user decides _not_ to install WMP7, though, we should disable ourselves.
  5431. if (!CMediaBarUtil::IsWMP7OrGreaterInstalled())
  5432. {
  5433. if (!IsOS(OS_WHISTLERORGREATER))
  5434. {
  5435. // Here we do the stuff to web-jit WMP7. ISSUE: We assume that it'll always be on Whistler
  5436. uCLSSPEC ucs;
  5437. QUERYCONTEXT qc = { 0 };
  5438. ucs.tyspec = TYSPEC_CLSID;
  5439. ucs.tagged_union.clsid = CLSID_JITWMP8;
  5440. hr = FaultInIEFeature(_hwnd, &ucs, &qc, FIEF_FLAG_FORCE_JITUI);
  5441. }
  5442. if (!CMediaBarUtil::IsWMP7OrGreaterInstalled())
  5443. {
  5444. // We give up. Delegate. We'll never try autoplay again.
  5445. MLShellMessageBox(_hwnd, MAKEINTRESOURCE(IDS_MEDIABAR_NOWMP7), MAKEINTRESOURCE(IDS_MEDIABAR_NOWMP7TITLE), MB_OK);
  5446. CMediaBarUtil::ToggleAutoplay(FALSE);
  5447. goto done;
  5448. }
  5449. }
  5450. // QS for the media bar
  5451. if (FAILED(QueryService(SID_SMediaBar, IID_PPV_ARG(IOleCommandTarget, &spOCTMediaBar))))
  5452. {
  5453. // The media bar may not have been created yet
  5454. _ForceCreateMediaBar();
  5455. // QS for the media bar once again
  5456. if (FAILED(QueryService(SID_SMediaBar, IID_PPV_ARG(IOleCommandTarget, &spOCTMediaBar))))
  5457. goto done;
  5458. fShow = FALSE;
  5459. }
  5460. hr = IUnknown_Exec(spOCTMediaBar, &CGID_MediaBar, MBID_PLAY, 0, &svarMime, &svarUrl);
  5461. ASSERT(SUCCEEDED(hr));
  5462. // The Media Bar clears the URL if it accepts the navigation
  5463. if (VT_BSTR != svarUrl.vt)
  5464. {
  5465. // Cancel the navigation
  5466. fRet = TRUE;
  5467. // Ensure that the media bar is visible
  5468. if (fShow)
  5469. {
  5470. CComVariant svarPopout;
  5471. if (SUCCEEDED(IUnknown_Exec(spOCTMediaBar, &CGID_MediaBar, MBID_POPOUT, 0, NULL, &svarPopout))
  5472. && ((VT_BOOL!=svarPopout.vt)
  5473. || (VARIANT_FALSE==svarPopout.boolVal)))
  5474. {
  5475. _ForceCreateMediaBar();
  5476. }
  5477. }
  5478. }
  5479. }
  5480. done:
  5481. return fRet;
  5482. }
  5483. //+---------------------------------------------------------------------------------
  5484. //
  5485. // IE Media Bar Hook
  5486. // ------------------
  5487. //
  5488. // Force the Media Bar to be displayed
  5489. //
  5490. //----------------------------------------------------------------------------------
  5491. void CDocObjectHost::_ForceCreateMediaBar()
  5492. {
  5493. IUnknown_ShowBrowserBar(_psp, CLSID_MediaBand, TRUE);
  5494. }
  5495. //+---------------------------------------------------------------------------------
  5496. //
  5497. // IE Media Bar Hook
  5498. // ------------------
  5499. //
  5500. // Dialog proc for Media Bar per-mime-type dialog
  5501. //
  5502. //----------------------------------------------------------------------------------
  5503. INT_PTR CALLBACK
  5504. CDocObjectHost::s_MimeDlgProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
  5505. {
  5506. UINT id;
  5507. switch(uMsg)
  5508. {
  5509. case WM_INITDIALOG:
  5510. CheckDlgButton(hDlg, IDC_MEDIA_MIME_CHKBOX, TRUE); // The first option is always checked
  5511. if (!CMediaBarUtil::IsWMP7OrGreaterInstalled())
  5512. {
  5513. TCHAR szTemp[500];
  5514. if (MLLoadString(IDS_MEDIABAR_NEEDWMP7, szTemp, ARRAYSIZE(szTemp)))
  5515. {
  5516. SetDlgItemText(hDlg, IDC_MEDIABAR_EXTRA, szTemp);
  5517. }
  5518. }
  5519. return TRUE;
  5520. case WM_DESTROY:
  5521. return FALSE;
  5522. case WM_COMMAND:
  5523. {
  5524. id = GET_WM_COMMAND_ID(wParam, lParam);
  5525. switch (id)
  5526. {
  5527. case IDOK:
  5528. {
  5529. if (IsDlgButtonChecked(hDlg, IDC_MEDIA_MIME_CHKBOX))
  5530. {
  5531. id = PLAYMIME_YESSAVE;
  5532. }
  5533. else
  5534. {
  5535. id = PLAYMIME_YES;
  5536. }
  5537. EndDialog(hDlg, id);
  5538. }
  5539. break;
  5540. case IDCANCEL:
  5541. {
  5542. if (IsDlgButtonChecked(hDlg, IDC_MEDIA_MIME_CHKBOX))
  5543. {
  5544. id = PLAYMIME_NOSAVE;
  5545. }
  5546. else
  5547. {
  5548. id = PLAYMIME_NO;
  5549. }
  5550. EndDialog(hDlg, id);
  5551. }
  5552. break;
  5553. case IDC_MEDIA_MOREINFO:
  5554. {
  5555. SHHtmlHelpOnDemandWrap(GetParent(hDlg), TEXT("iexplore.chm > iedefault"), 0, (DWORD_PTR) TEXT("mediabar_settings.htm"), ML_CROSSCODEPAGE);
  5556. }
  5557. break;
  5558. }
  5559. }
  5560. break;
  5561. default:
  5562. return FALSE;
  5563. }
  5564. return TRUE;
  5565. }
  5566. HRESULT CDocObjectHost::SetTarget(IMoniker* pmk, UINT uiCP, LPCTSTR pszLocation, LPITEMIDLIST pidlKey,
  5567. IShellView* psvPrev, BOOL fFileProtocol)
  5568. {
  5569. HRESULT hres = NOERROR;
  5570. BOOL fLoadedHistory = FALSE;
  5571. ATOMICRELEASE(_pmkCur);
  5572. _pmkCur = pmk;
  5573. pmk->AddRef();
  5574. ILFree(_pidl);
  5575. _pidl = ILClone(pidlKey);
  5576. _fFileProtocol = fFileProtocol;
  5577. _pszLocation = pszLocation;
  5578. _uiCP = uiCP;
  5579. // this is only set if we did a successful LoadHistory()
  5580. _fIsHistoricalObject = FALSE;
  5581. if (_bsc._hszPostData)
  5582. {
  5583. GlobalFree(_bsc._hszPostData);
  5584. _bsc._hszPostData = NULL;
  5585. }
  5586. if (_bsc._pszHeaders)
  5587. {
  5588. LocalFree(_bsc._pszHeaders);
  5589. _bsc._pszHeaders = NULL;
  5590. }
  5591. ATOMICRELEASE(_bsc._pbc);
  5592. //
  5593. // this replaces the old style of caching.
  5594. // if something has been cached, it was cached
  5595. // way above us before we ever existed. now it is
  5596. // waiting for us.
  5597. //
  5598. IBrowserService * pbs;
  5599. IStream * pstm = NULL;
  5600. IBindCtx * pbcHistory = NULL;
  5601. if (SUCCEEDED(QueryService(SID_SShellBrowser, IID_IBrowserService, (void **)&pbs)))
  5602. {
  5603. // just in case there is one already there, like in the case of local anchor navigates
  5604. ATOMICRELEASE(_pole);
  5605. pbs->GetHistoryObject(&_pole, &pstm, &pbcHistory);
  5606. TraceMsg(TF_TRAVELLOG, "DOH::SetTarget History object: _pole = %X, pstm = %X, pbc = %X", _pole, pstm, pbcHistory);
  5607. pbs->Release();
  5608. }
  5609. if (_pole)
  5610. {
  5611. // some objects (MSHTML for one) need their clientsite before anything else.
  5612. // so we need to init first
  5613. _InitOleObject();
  5614. if (pstm)
  5615. {
  5616. IPersistHistory *pph;
  5617. if (SUCCEEDED(_pole->QueryInterface(IID_IPersistHistory, (void **)&pph)))
  5618. {
  5619. if (SUCCEEDED(pph->LoadHistory(pstm, pbcHistory)))
  5620. {
  5621. //
  5622. // this is to make sure that we wait for
  5623. // the pole to tell us when it is ready.
  5624. // when there is a pstm, that means that they may have
  5625. // to do a full reparse or whatever, and we cant make
  5626. // any assumptions about the readystate.
  5627. //
  5628. hres = S_FALSE;
  5629. _fIsHistoricalObject = TRUE;
  5630. _SetUpTransitionCapability();
  5631. fLoadedHistory = TRUE;
  5632. // we may need to redo the pics stuff too.
  5633. // PrepPicsForAsync();
  5634. TraceMsg(TF_TRAVELLOG, "DOH::SetTarget pph->LoadHistory Successful");
  5635. }
  5636. else
  5637. ATOMICRELEASE(_pole);
  5638. pph->Release();
  5639. }
  5640. ATOMICRELEASE(pstm);
  5641. }
  5642. else
  5643. hres = S_OK;
  5644. ATOMICRELEASE(pbcHistory);
  5645. // we shouldnt fail a load history, because the data in
  5646. // is just what the document gave us in SaveHistory...
  5647. AssertMsg(NULL != _pole, TEXT("DOH::SetTarget pph->LoadHistory Failed"));
  5648. // if we were already up and created, just scroll to it.
  5649. // if we were created DEACTIVATED, (possible in the ocx case)
  5650. // don't do this activation
  5651. if (_uState != SVUIA_DEACTIVATE && !DocCanHandleNavigation())
  5652. {
  5653. hres = _ActivateMsoView();
  5654. }
  5655. //
  5656. // allow navigation - when you're deactivated. So you can navigate an invisible WebOC.
  5657. // IE6 Bug# 5449
  5658. //
  5659. if ( DocCanHandleNavigation() ||
  5660. ( _fDocCanNavigate &&
  5661. _uState == SVUIA_DEACTIVATE &&
  5662. !fLoadedHistory ) )
  5663. {
  5664. // If the _fPrevDocHost flag is not
  5665. // set, we better be deactivated.
  5666. //
  5667. AssertMsg((_fPrevDocHost || _uState == SVUIA_DEACTIVATE),
  5668. _T("_fPrevDocHost is not set and we are activated"));
  5669. // If the document is handling the navigation,
  5670. // we must store the user entered URL here.
  5671. // Otherwise, if the navigation fails,
  5672. // the user-entered URL is NULL by the time
  5673. // _bsc._HandleFailedNavigationSearch is called,
  5674. //
  5675. VariantClear(&_varUserEnteredUrl);
  5676. _GetSearchString(_psp, &_varUserEnteredUrl);
  5677. WCHAR wzUrl[MAX_URL_STRING];
  5678. hres = IEGetNameAndFlagsEx(_pidl, SHGDN_FORPARSING, IEGDN_NOFRAGMENT, wzUrl, ARRAYSIZE(wzUrl), NULL);
  5679. if (S_OK == hres)
  5680. {
  5681. _EnableModeless(FALSE);
  5682. WCHAR wzLocation[MAX_URL_STRING] = {0};
  5683. IEILGetFragment(_pidl, wzLocation, SIZECHARS(wzLocation));
  5684. hres = _NavigateDocument(CComBSTR(wzUrl), CComBSTR(wzLocation));
  5685. _EnableModeless(TRUE);
  5686. }
  5687. }
  5688. }
  5689. if (!_pole)
  5690. {
  5691. ASSERT(!pstm);
  5692. ASSERT(!pbcHistory);
  5693. IBindCtx * pbc = NULL;
  5694. TraceMsg(TF_TRAVELLOG, "DOH::SetTarget No obj from TravelLog, calling pmk->BindToObject");
  5695. if (_psp)
  5696. {
  5697. hres = _psp->QueryService(SID_SShellBrowser, IID_IBindCtx, (void **)&pbc);
  5698. }
  5699. if (pbc == NULL)
  5700. {
  5701. hres = CreateBindCtx(0, &pbc);
  5702. }
  5703. else
  5704. {
  5705. hres = S_OK;
  5706. }
  5707. if (SUCCEEDED(hres))
  5708. {
  5709. HRESULT hr = E_FAIL;
  5710. IBindCtx * pbcAsync = NULL;
  5711. IBindCtx * pbcWrapper = NULL;
  5712. if (pbc)
  5713. {
  5714. // If the bind context supports IAsyncBindCtx, then it
  5715. // is a bind context that was created by UrlMon and passed
  5716. // to us to reuse. We must pass this bind context to UrlMon
  5717. // as-is and not wrapped in a BCW object.
  5718. // Note: IAsyncBindCtx has identicial interface as IBindCtx
  5719. //
  5720. hr = pbc->QueryInterface(IID_IAsyncBindCtx, (void**)&pbcAsync);
  5721. ATOMICRELEASE(pbcAsync);
  5722. }
  5723. if (SUCCEEDED(hr))
  5724. {
  5725. // If this is a media url delegated to shdocvw from trident,
  5726. // and if the IE Media Bar wants to handle the url, cancel
  5727. // the navigation, else continue the navigation.
  5728. if (_DelegateToMediaBar(pbc, NULL))
  5729. {
  5730. _CancelPendingNavigation(TRUE);
  5731. if (_pwb)
  5732. {
  5733. _pwb->SetNavigateState(BNS_NORMAL);
  5734. }
  5735. ATOMICRELEASE(pbc);
  5736. return S_FALSE;
  5737. }
  5738. else
  5739. {
  5740. ATOMICRELEASE(_pbcCur);
  5741. _fDelegatedNavigation = TRUE;
  5742. _pbcCur = pbc; // No need to AddRef - pbc is AddRef'ed by QS.
  5743. }
  5744. }
  5745. else
  5746. {
  5747. pbcWrapper = BCW_Create(pbc);
  5748. if (pbcWrapper == NULL)
  5749. {
  5750. pbcWrapper = pbc;
  5751. }
  5752. else
  5753. {
  5754. pbc->Release();
  5755. }
  5756. pbc = NULL;
  5757. hres = CreateAsyncBindCtxEx(pbcWrapper, 0, NULL, NULL, &pbcAsync, 0);
  5758. if (SUCCEEDED(hres))
  5759. {
  5760. ASSERT(pbcAsync);
  5761. ATOMICRELEASE(_pbcCur);
  5762. _pbcCur = pbcAsync;
  5763. _pbcCur->AddRef();
  5764. pbcWrapper->Release();
  5765. pbcWrapper = pbcAsync;
  5766. }
  5767. }
  5768. if (SUCCEEDED(hres))
  5769. {
  5770. #ifdef DEBUG
  5771. DWORD dwMksys;
  5772. hres = pmk->IsSystemMoniker(&dwMksys);
  5773. ASSERT((SUCCEEDED(hres) && dwMksys!=MKSYS_FILEMONIKER));
  5774. #endif
  5775. ASSERT(FALSE == _fSetTarget);
  5776. BOOL fWindowOpen = FALSE;
  5777. if (_pbcCur)
  5778. {
  5779. IUnknown * punkBindCtxParam = NULL;
  5780. hres = _pbcCur->GetObjectParam(KEY_BINDCONTEXTPARAM, &punkBindCtxParam);
  5781. if (SUCCEEDED(hres))
  5782. {
  5783. fWindowOpen = TRUE;
  5784. punkBindCtxParam->Release();
  5785. }
  5786. }
  5787. // If we are being called in response to window.open
  5788. // we create the document here and call InitNew on it
  5789. // to load about:blank. We do this so that the user won't
  5790. // see a transparent window while the URL is being
  5791. // located. When Trident calls Invoke to get the
  5792. // new window object, we will then load the real document.
  5793. //
  5794. if (fWindowOpen)
  5795. {
  5796. hres = _CreatePendingDocObject(TRUE, TRUE);
  5797. ASSERT(S_OK == hres && _punkPending);
  5798. if (_punkPending)
  5799. {
  5800. ATOMICRELEASE(_pole);
  5801. hres = _punkPending->QueryInterface(IID_IOleObject, (void**)&_pole);
  5802. ASSERT(SUCCEEDED(hres));
  5803. // IE Media Bar: turn auto-play off for the first navigation
  5804. // This is needed to make the target="_blank" feature work.
  5805. CMediaBarHelper::DisableFirstAutoPlay(_punkPending);
  5806. }
  5807. }
  5808. else
  5809. {
  5810. // Hack: The AddRef & Release protect against an error page
  5811. // navigation from freeing the pdoh out from under us (edwardp)
  5812. AddRef();
  5813. _fSetTarget = TRUE;
  5814. hres = _StartAsyncBinding(pmk, _pbcCur, psvPrev);
  5815. _fSetTarget = FALSE;
  5816. // Hack: Matching Release()
  5817. //
  5818. Release();
  5819. if (SUCCEEDED(hres))
  5820. {
  5821. hres = S_FALSE;
  5822. }
  5823. }
  5824. }
  5825. ATOMICRELEASE(pbcWrapper); // CreateAsyncBindCtx addrefs as well.
  5826. }
  5827. }
  5828. return hres;
  5829. }
  5830. #define USE_HISTBMOFFSET 0
  5831. #define USE_MYBMOFFSET 1
  5832. #define USE_STDBMOFFSET 2
  5833. void CDocObjectHost::_MergeToolbarSB()
  5834. {
  5835. }
  5836. HICON _LoadSmallIcon(int id)
  5837. {
  5838. return (HICON)LoadImage(HINST_THISDLL, MAKEINTRESOURCE(id),
  5839. IMAGE_ICON, GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CYSMICON), 0);
  5840. }
  5841. void _InitIcons(void)
  5842. {
  5843. ENTERCRITICAL;
  5844. if (g_hiconScriptErr == NULL)
  5845. {
  5846. g_hiconScriptErr = _LoadSmallIcon(IDI_STATE_SCRIPTERROR);
  5847. if (IS_BIDI_LOCALIZED_SYSTEM())
  5848. MirrorIcon(&g_hiconScriptErr, NULL);
  5849. }
  5850. if (!g_hiconSSL)
  5851. {
  5852. g_hiconSSL = _LoadSmallIcon(IDI_SSL);
  5853. if (IS_BIDI_LOCALIZED_SYSTEM())
  5854. MirrorIcon(&g_hiconSSL, NULL);
  5855. }
  5856. if (!g_hiconFortezza)
  5857. {
  5858. g_hiconFortezza = _LoadSmallIcon(IDI_FORTEZZA);
  5859. if (IS_BIDI_LOCALIZED_SYSTEM())
  5860. MirrorIcon(&g_hiconFortezza, NULL);
  5861. }
  5862. for (UINT id = IDI_STATE_FIRST; id <= IDI_STATE_LAST; id++)
  5863. {
  5864. if (!g_ahiconState[id-IDI_STATE_FIRST])
  5865. {
  5866. g_ahiconState[id-IDI_STATE_FIRST]= _LoadSmallIcon(id);
  5867. if (IS_BIDI_LOCALIZED_SYSTEM())
  5868. MirrorIcon(&g_ahiconState[id-IDI_STATE_FIRST], NULL);
  5869. }
  5870. }
  5871. if (!g_hiconOffline)
  5872. {
  5873. g_hiconOffline = _LoadSmallIcon(IDI_OFFLINE);
  5874. if (IS_BIDI_LOCALIZED_SYSTEM())
  5875. MirrorIcon(&g_hiconOffline, NULL);
  5876. }
  5877. if (!g_hiconPrinter)
  5878. {
  5879. g_hiconPrinter = _LoadSmallIcon(IDI_PRINTER);
  5880. if (IS_BIDI_LOCALIZED_SYSTEM())
  5881. MirrorIcon(&g_hiconPrinter, NULL);
  5882. }
  5883. if (!g_hiconPrivacyImpact)
  5884. {
  5885. g_hiconPrivacyImpact = _LoadSmallIcon( IDI_PRIVACY_IMPACT);
  5886. if (IS_BIDI_LOCALIZED_SYSTEM())
  5887. MirrorIcon(&g_hiconPrivacyImpact, NULL);
  5888. }
  5889. LEAVECRITICAL;
  5890. }
  5891. // This function initializes whatever the Class needs for manipulating the history
  5892. // we try to delay this till absolutely needed in order to not load
  5893. // wininet till the end
  5894. IUnknown *
  5895. CDocObjectHost::get_punkSFHistory()
  5896. {
  5897. if (_pocthf && !_punkSFHistory)
  5898. {
  5899. VARIANT var;
  5900. VariantInit(&var);
  5901. if (SUCCEEDED(_pocthf->Exec(&CGID_Explorer, SBCMDID_HISTSFOLDER, TRUE, NULL, &var)))
  5902. {
  5903. if (VT_UNKNOWN == var.vt && NULL != var.punkVal)
  5904. {
  5905. _punkSFHistory = var.punkVal;
  5906. _punkSFHistory->AddRef();
  5907. }
  5908. }
  5909. VariantClearLazy(&var);
  5910. }
  5911. return _punkSFHistory;
  5912. }
  5913. //
  5914. // This function (re)initializes CDocObjectHost object with the buddy
  5915. // IShellView (which is always CShellDocView) and the IShellBrowser.
  5916. // If this is the first time (_hwnd==NULL), it creates the view window
  5917. // and other associated windows as well. Otherwise (_hwnd!=NULL) -- it
  5918. // means this object is passed from one CDocViewObject to another because
  5919. // of intra-page jump -- we move it to the specified location (prcView)
  5920. // to make it really sure that we show it at the right place.
  5921. //
  5922. BOOL CDocObjectHost::InitHostWindow(IShellView* psv, IShellBrowser* psb,
  5923. LPRECT prcView)
  5924. {
  5925. HWND hwndParent;
  5926. IServiceProvider * pspTop;
  5927. IOleObject * pTopOleObject;
  5928. IOleClientSite * pOleClientSite;
  5929. _ResetOwners();
  5930. ASSERT(psv);
  5931. _psv = psv;
  5932. _psv->AddRef();
  5933. ASSERT(NULL==_pmsoctView);
  5934. _psv->QueryInterface(IID_IOleCommandTarget, (void **)&_pmsoctView);
  5935. ASSERT(NULL==_pdvs);
  5936. _psv->QueryInterface(IID_IDocViewSite, (void **)&_pdvs);
  5937. ASSERT(psb);
  5938. _psb = psb;
  5939. _psb->AddRef();
  5940. ASSERT(NULL==_pwb);
  5941. _psb->QueryInterface(IID_IBrowserService, (void **)&_pwb);
  5942. ASSERT(NULL==_pmsoctBrowser);
  5943. _psb->QueryInterface(IID_IOleCommandTarget, (void **)&_pmsoctBrowser);
  5944. ASSERT(NULL==_psp);
  5945. _psb->QueryInterface(IID_IServiceProvider, (void **)&_psp);
  5946. ASSERT(NULL==_pipu);
  5947. _psb->QueryInterface(IID_IOleInPlaceUIWindow, (void **)&_pipu);
  5948. ASSERT(_pipu);
  5949. _Init();
  5950. ASSERT(_psp);
  5951. if (_psp)
  5952. {
  5953. // Get the object that manages the extended buttons from the top-level browser
  5954. // But only if we don't already have it.
  5955. if (NULL == _pBrowsExt)
  5956. _psp->QueryService(SID_STopLevelBrowser, IID_IToolbarExt, (void **)&_pBrowsExt);
  5957. //
  5958. // LATER: I don't like that CDocObjectHost is directly accessing
  5959. // the automation service object to fire events. We should
  5960. // probably move all the progress UI code above IShellBrowser
  5961. // so that we don't need to do this shortcut. (SatoNa)
  5962. //
  5963. ASSERT(NULL==_peds);
  5964. _psp->QueryService(IID_IExpDispSupport, IID_IExpDispSupport, (void **)&_peds);
  5965. ASSERT(_peds);
  5966. ASSERT(NULL==_pedsHelper);
  5967. _peds->QueryInterface(IID_IExpDispSupportOC, (void **)&_pedsHelper);
  5968. ASSERT(NULL==_phf);
  5969. _psp->QueryService(SID_SHlinkFrame, IID_IHlinkFrame, (void **)&_phf);
  5970. if (_phf)
  5971. {
  5972. _phf->QueryInterface(IID_IUrlHistoryNotify, (void **)&_pocthf);
  5973. }
  5974. // _punkSFHistory was being initialized here - but in order to delay the load of wininet.dll
  5975. // we initialize it just before we use it
  5976. ASSERT(_pWebOCUIHandler == NULL);
  5977. ASSERT(_pWebOCUIHandler2 == NULL);
  5978. ASSERT(_pWebOCInPlaceSiteEx == NULL);
  5979. ASSERT(_fDocCanNavigate || _fWebOC == FALSE);
  5980. if (SUCCEEDED(_psp->QueryService(SID_STopLevelBrowser, IID_IServiceProvider, (void **)&pspTop)) && pspTop)
  5981. {
  5982. if (SUCCEEDED(pspTop->QueryService(SID_SContainerDispatch, IID_IOleObject, (void **)&pTopOleObject)) && pTopOleObject)
  5983. {
  5984. _fWebOC = TRUE; // there was a container so we're a WebOC
  5985. pTopOleObject->GetClientSite(&pOleClientSite);
  5986. if (pOleClientSite)
  5987. {
  5988. pOleClientSite->QueryInterface(IID_IDocHostUIHandler, (void**)&_pWebOCUIHandler);
  5989. pOleClientSite->QueryInterface(IID_IDocHostUIHandler2, (void**)&_pWebOCUIHandler2);
  5990. pOleClientSite->QueryInterface(IID_IDocHostShowUI, (void**)&_pWebOCShowUI);
  5991. pOleClientSite->QueryInterface(IID_IOleInPlaceSiteEx, (void**)&_pWebOCInPlaceSiteEx);
  5992. pOleClientSite->Release();
  5993. }
  5994. pTopOleObject->Release();
  5995. }
  5996. pspTop->Release();
  5997. }
  5998. }
  5999. _dhUIHandler.SetSite( (IDocHostUIHandler *) this); // Apparently we need to disamiguate the IUnknown reference.
  6000. _psb->GetWindow(&hwndParent);
  6001. if (!_hwnd) {
  6002. // There are several things we don't attempt to do when
  6003. // we're not toplevel. Frameset type DOH should never
  6004. // try to menu merge or dork with the statusbar.
  6005. // Do this before the CreateWindowEx call 'cuz during
  6006. // creation we party on the status bar.
  6007. {
  6008. IOleInPlaceSite* pparentsite = _GetParentSite();
  6009. if (pparentsite) {
  6010. _fHaveParentSite = TRUE;
  6011. pparentsite->Release();
  6012. }
  6013. }
  6014. _RegisterWindowClass();
  6015. // really create the window
  6016. DWORD dwStyle = WS_CHILD | WS_CLIPCHILDREN | WS_CLIPSIBLINGS | WS_VISIBLE | WS_TABSTOP;
  6017. //
  6018. // In Office 95, Excel and PowerPoint don't draw the client edge,
  6019. // while Word does draw the client edge. To avoid having double edges,
  6020. // we remove it for now. SriniK (Office) will find out which will be
  6021. // the standard for Office 96. (SatoNa)
  6022. //
  6023. _hwnd = SHNoFusionCreateWindowEx(0 /* WS_EX_CLIENTEDGE */,
  6024. c_szViewClass, NULL,
  6025. dwStyle,
  6026. prcView->left, prcView->top, prcView->right-prcView->left, prcView->bottom-prcView->top,
  6027. hwndParent,
  6028. (HMENU)0,
  6029. HINST_THISDLL,
  6030. (LPVOID)SAFECAST(this, CImpWndProc*));
  6031. if (!_hwnd) {
  6032. goto Bail;
  6033. }
  6034. UINT uiAcc = ACCEL_DOCVIEW;
  6035. if (SHRestricted(REST_NOFILEMENU))
  6036. uiAcc = ACCEL_DOCVIEW_NOFILEMENU;
  6037. if (_hacc)
  6038. {
  6039. DestroyAcceleratorTable(_hacc);
  6040. _hacc = NULL;
  6041. }
  6042. _hacc = LoadAccelerators(MLGetHinst(), MAKEINTRESOURCE(uiAcc));
  6043. _InitIcons();
  6044. } else {
  6045. ASSERT(GetParent(_hwnd) == hwndParent);
  6046. MoveWindow(_hwnd, prcView->left, prcView->top,
  6047. prcView->right-prcView->left, prcView->bottom - prcView->top, TRUE);
  6048. }
  6049. Bail:
  6050. return (bool) _hwnd;
  6051. }
  6052. void CDocObjectHost::_CleanupProgress(void)
  6053. {
  6054. TraceMsg(TF_SHDPROGRESS, "CDOH::CleanupProgress fTimer = %d, fFull = %d, hwndProg = %X", _fProgressTimer, _fProgressTimerFull, _hwndProgress);
  6055. if (_fProgressTimer)
  6056. {
  6057. KillTimer(_hwnd, IDTIMER_PROGRESS);
  6058. _fProgressTimer = FALSE;
  6059. }
  6060. if (_fProgressTimerFull)
  6061. {
  6062. // we are being stopped, and the hwnd is destroyed
  6063. // before we clear the status bar. zekel - 22-JUL-97
  6064. _OnSetProgressPos(-2, PROGRESS_RESET);
  6065. KillTimer(_hwnd, IDTIMER_PROGRESSFULL);
  6066. ASSERT(!_fProgressTimerFull);
  6067. }
  6068. _OnSetProgressMax(0);
  6069. _hwndProgress = NULL;
  6070. }
  6071. void CDocObjectHost::DestroyHostWindow()
  6072. {
  6073. // Turn off the simple mode when we are leaving.
  6074. if (_psb)
  6075. _psb->SendControlMsg(FCW_STATUS, SB_SIMPLE, 0, 0, NULL);
  6076. // really destroy the window
  6077. _fCanceledByBrowser = TRUE;
  6078. _bsc.AbortBinding();
  6079. _RemoveAllPicsProcessors();
  6080. _CloseMsoView();
  6081. //
  6082. // Notes: We need to delete OLE object from this side (container),
  6083. // otherwise, we leak because of circular reference.
  6084. //
  6085. _UnBind();
  6086. _CleanupProgress();
  6087. if (_hwndTooltip) {
  6088. DestroyWindow(_hwndTooltip);
  6089. _hwndTooltip = NULL;
  6090. }
  6091. //
  6092. // Note that we need to destroy the parent after destroying children.
  6093. //
  6094. // OLE seems to recurse back into this function when we destroy the hwnd
  6095. // and we try to destroy it a second time causing a RIP. Avoid this RIP
  6096. // by NULLing out our internal variables before we destroy the hwnds.
  6097. if (_hwnd) {
  6098. HWND hwndT = _hwnd;
  6099. _hwnd = NULL;
  6100. DestroyWindow(hwndT);
  6101. }
  6102. ATOMICRELEASE(_psp);
  6103. _ResetOwners();
  6104. }
  6105. //
  6106. // This member creates a view (IOleDocumentView) of the DocObject we have (_pole).
  6107. // This function is called only once from ::CreateViewWindow.
  6108. //
  6109. HRESULT CDocObjectHost::_CreateMsoView(void)
  6110. {
  6111. ASSERT(_pmsov == NULL);
  6112. ASSERT(_pmsoc == NULL);
  6113. HRESULT hres = OleRun(_pole);
  6114. if (SUCCEEDED(hres))
  6115. {
  6116. //// WARNING:
  6117. // if you add anything to here, you should also pass it along
  6118. // in _CreateDocObjHost
  6119. //
  6120. IOleDocument* pmsod = NULL;
  6121. hres = _pole->QueryInterface(IID_IOleDocument, (void **)&pmsod);
  6122. if (SUCCEEDED(hres)) {
  6123. hres = pmsod->CreateView(this, NULL ,0,&_pmsov);
  6124. if (SUCCEEDED(hres)) {
  6125. //
  6126. // HACK: Working about MSHTML bug (#28756). We really
  6127. // want to take this hack out before we ship. (SatoNa)
  6128. //
  6129. _pmsov->SetInPlaceSite(this);
  6130. } else {
  6131. TraceMsg(DM_ERROR, "DOH::_CreateMsoView pmsod->CreateView() ##FAILED## %x", hres);
  6132. }
  6133. if (SUCCEEDED(hres) && !_pmsot) {
  6134. _pmsov->QueryInterface(IID_IOleCommandTarget, (void **)&_pmsot);
  6135. }
  6136. if (SUCCEEDED(hres) && !_pmsoc) {
  6137. _pmsov->QueryInterface(IID_IOleControl, (void **)&_pmsoc);
  6138. }
  6139. #ifdef HLINK_EXTRA
  6140. if (_pihlbc)
  6141. {
  6142. if (_phls)
  6143. {
  6144. _phls->SetBrowseContext(_pihlbc);
  6145. }
  6146. ASSERT(_pmkCur);
  6147. hres = HlinkOnNavigate(this, _pihlbc, 0,
  6148. _pmkCur, NULL, NULL);
  6149. // TraceMsg(0, "sdv TR : _CreateMsoView HlinkOnNavigate returned %x", hres);
  6150. }
  6151. #endif // HLINK_EXTRA
  6152. pmsod->Release();
  6153. } else {
  6154. TraceMsg(DM_ERROR, "DOH::_CreateMsoView _pole->QI(IOleDocument) ##FAILED## %x", hres);
  6155. }
  6156. } else {
  6157. TraceMsg(DM_ERROR, "DOH::_CreateMsoView OleRun ##FAILED## %x", hres);
  6158. }
  6159. return hres;
  6160. }
  6161. HRESULT CDocObjectHost::_ForwardSetSecureLock(int lock)
  6162. {
  6163. HRESULT hr = E_FAIL;
  6164. TraceMsg(DM_SSL, "[%X}DOH::ForwardSecureLock() lock = %d",this, lock, hr);
  6165. VARIANT va = {0};
  6166. va.vt = VT_I4;
  6167. va.lVal = lock;
  6168. // we should only suggest if we are not the topframe
  6169. if (_psp && _psb && !IsTopFrameBrowser(_psp, _psb))
  6170. {
  6171. IOleCommandTarget *pmsoct;
  6172. if (SUCCEEDED(_psp->QueryService(SID_STopFrameBrowser, IID_IOleCommandTarget, (void **)&pmsoct)))
  6173. {
  6174. ASSERT(pmsoct);
  6175. if (lock < SECURELOCK_FIRSTSUGGEST)
  6176. va.lVal += SECURELOCK_FIRSTSUGGEST;
  6177. hr = pmsoct->Exec(&CGID_Explorer, SBCMDID_SETSECURELOCKICON, 0, &va, NULL);
  6178. pmsoct->Release();
  6179. }
  6180. }
  6181. else
  6182. if (_pmsoctBrowser)
  6183. hr = _pmsoctBrowser->Exec(&CGID_Explorer, SBCMDID_SETSECURELOCKICON, 0, &va, NULL);
  6184. return hr;
  6185. }
  6186. //
  6187. // This is the only method of IOleDocumentSite, which we MUST implement.
  6188. //
  6189. HRESULT CDocObjectHost::ActivateMe(IOleDocumentView *pviewToActivate)
  6190. {
  6191. TraceMsg(TF_SHDUIACTIVATE, "DOC::ActivateMe called when _pmsov is %x", _pmsov);
  6192. HRESULT hres = S_OK;
  6193. if (_pmsov==NULL) {
  6194. hres = _CreateMsoView();
  6195. #ifdef TEST_DELAYED_SHOWMSOVIEW
  6196. SetTimer(_hwnd, 100, 1500, NULL);
  6197. MessageBeep(0);
  6198. return hres;
  6199. #endif // TEST_DELAYED_SHOWMSOVIEW
  6200. }
  6201. if (SUCCEEDED(hres))
  6202. {
  6203. _ShowMsoView();
  6204. _MergeToolbarSB();
  6205. _InitToolbarButtons();
  6206. ASSERT(_pmsoctBrowser);
  6207. if (_fSetSecureLock)
  6208. _ForwardSetSecureLock(_eSecureLock);
  6209. }
  6210. return hres;
  6211. }
  6212. //Helper routine for QueryStatus for status messages
  6213. ULONG ulBufferSizeNeeded(wchar_t *wsz, int ids, ULONG ulBufferLen)
  6214. {
  6215. TraceMsg(0, "sdv TR ulBufferSizeNeeded called with (%x)", ids);
  6216. DWORD dwLen;
  6217. WCHAR szTemp[MAX_STATUS_SIZE+1];
  6218. dwLen = MLLoadStringW(ids, szTemp, MAX_STATUS_SIZE);
  6219. dwLen += 1; // for NULL terminator
  6220. if (dwLen <= (DWORD)ulBufferLen)
  6221. MoveMemory(wsz, szTemp, dwLen * sizeof(WCHAR));
  6222. else
  6223. *wsz = 0;
  6224. return ((ULONG)dwLen);
  6225. }
  6226. HRESULT CDocObjectHost::OnQueryStatus(const GUID *pguidCmdGroup, ULONG cCmds, OLECMD rgCmds[], OLECMDTEXT *pcmdtext, HRESULT hres)
  6227. {
  6228. if (pguidCmdGroup == NULL)
  6229. {
  6230. ULONG i;
  6231. if (rgCmds == NULL)
  6232. return E_INVALIDARG;
  6233. for (i=0 ; i<cCmds ; i++)
  6234. {
  6235. // ONLY say that we support the stuff we support in ::OnExec
  6236. switch (rgCmds[i].cmdID)
  6237. {
  6238. case OLECMDID_OPEN:
  6239. case OLECMDID_SAVE:
  6240. case OLECMDID_UPDATECOMMANDS:
  6241. case OLECMDID_SETPROGRESSMAX:
  6242. case OLECMDID_SETPROGRESSPOS:
  6243. case OLECMDID_SETPROGRESSTEXT:
  6244. case OLECMDID_SETTITLE:
  6245. rgCmds[i].cmdf = OLECMDF_ENABLED;
  6246. break;
  6247. default:
  6248. if (SUCCEEDED(hres))
  6249. {
  6250. // _pmsoctBrowser already filled this in
  6251. }
  6252. else
  6253. {
  6254. rgCmds[i].cmdf = 0;
  6255. }
  6256. break;
  6257. }
  6258. }
  6259. /* for now we deal only with status text*/
  6260. if (pcmdtext)
  6261. {
  6262. switch (rgCmds[i].cmdID)
  6263. {
  6264. case OLECMDID_OPEN:
  6265. case OLECMDID_SAVE:
  6266. pcmdtext->cwActual = ulBufferSizeNeeded(pcmdtext->rgwz,
  6267. IDS_HELP_OF(_MapFromMso(rgCmds[0].cmdID)),
  6268. pcmdtext->cwBuf);
  6269. break;
  6270. default:
  6271. if (SUCCEEDED(hres))
  6272. {
  6273. // _pmsoctBrowser already filled this in
  6274. }
  6275. else
  6276. {
  6277. pcmdtext->cmdtextf = OLECMDTEXTF_NONE;
  6278. pcmdtext->cwActual = 0;
  6279. if (pcmdtext->rgwz && pcmdtext->cwBuf>0)
  6280. *pcmdtext->rgwz = TEXT('\0');
  6281. }
  6282. break;
  6283. }
  6284. }
  6285. hres = S_OK;
  6286. }
  6287. else if (IsEqualGUID(*pguidCmdGroup, CLSID_InternetButtons) ||
  6288. IsEqualGUID(*pguidCmdGroup, CLSID_MSOButtons))
  6289. {
  6290. for (UINT i = 0 ; i < cCmds ; i++)
  6291. {
  6292. // CommandIDs from DVIDM_MENUEXT_FIRST to DVIDM_MENUEXT_LAST are reserved for toolbar extension buttons
  6293. // Do NOT use this range for constants within the scope of CLSID_InternetButtons/CLSID_MSOButtons!
  6294. if (IsInRange(rgCmds[i].cmdID, DVIDM_MENUEXT_FIRST, DVIDM_MENUEXT_LAST))
  6295. {
  6296. // We'll pass specificially this OLECMD through to the custom button
  6297. IUnknown_QueryStatus(_pBrowsExt, &CLSID_ToolbarExtButtons, 1, &rgCmds[i], pcmdtext);
  6298. }
  6299. else
  6300. {
  6301. switch (rgCmds[i].cmdID)
  6302. {
  6303. case DVIDM_PRINT:
  6304. case DVIDM_PRINTPREVIEW:
  6305. if (_pmsoctBrowser)
  6306. {
  6307. OLECMD ocButton;
  6308. static const int tbtab[] =
  6309. {
  6310. DVIDM_PRINT,
  6311. DVIDM_FONTS,
  6312. DVIDM_PRINTPREVIEW,
  6313. };
  6314. static const int cttab[] =
  6315. {
  6316. OLECMDID_PRINT,
  6317. OLECMDID_ZOOM,
  6318. OLECMDID_PRINTPREVIEW,
  6319. };
  6320. ocButton.cmdID = SHSearchMapInt(tbtab, cttab, ARRAYSIZE(tbtab), rgCmds[i].cmdID);
  6321. ocButton.cmdf = 0;
  6322. _pmsoctBrowser->QueryStatus(NULL, 1, &ocButton, NULL);
  6323. rgCmds[i].cmdf = ocButton.cmdf;
  6324. }
  6325. break;
  6326. case DVIDM_FONTS: // Always enable for IE5B2
  6327. case DVIDM_CUT:
  6328. case DVIDM_COPY:
  6329. case DVIDM_PASTE:
  6330. case DVIDM_ENCODING:
  6331. rgCmds[i].cmdf = OLECMDF_ENABLED;
  6332. break;
  6333. case DVIDM_SHOWTOOLS:
  6334. if (_ToolsButtonAvailable())
  6335. rgCmds[i].cmdf = OLECMDF_ENABLED;
  6336. break;
  6337. case DVIDM_MAILNEWS:
  6338. if (_MailButtonAvailable())
  6339. rgCmds[i].cmdf = OLECMDF_ENABLED;
  6340. break;
  6341. case DVIDM_DISCUSSIONS:
  6342. // In addition to enabled/disabled, discussions button is checked/unchecked
  6343. rgCmds[i].cmdf = _DiscussionsButtonCmdf();
  6344. break;
  6345. case DVIDM_EDITPAGE:
  6346. if (_psp)
  6347. {
  6348. // Temp code -- forward to itbar
  6349. // itbar edit code is moving here soon
  6350. IExplorerToolbar* pxtb;
  6351. if (SUCCEEDED(_psp->QueryService(SID_SExplorerToolbar, IID_IExplorerToolbar, (void **)&pxtb)))
  6352. {
  6353. OLECMD ocButton = { CITIDM_EDITPAGE, 0 };
  6354. IUnknown_QueryStatus(pxtb, &CGID_PrivCITCommands, 1, &ocButton, NULL);
  6355. rgCmds[i].cmdf = ocButton.cmdf;
  6356. pxtb->Release();
  6357. }
  6358. }
  6359. break;
  6360. }
  6361. }
  6362. }
  6363. hres = S_OK;
  6364. }
  6365. return hres;
  6366. }
  6367. HRESULT CDocObjectHost::QueryStatus(
  6368. /* [unique][in] */ const GUID *pguidCmdGroup,
  6369. /* [in] */ ULONG cCmds,
  6370. /* [out][in][size_is] */ OLECMD rgCmds[ ],
  6371. /* [unique][out][in] */ OLECMDTEXT *pcmdtext)
  6372. {
  6373. HRESULT hres = OLECMDERR_E_UNKNOWNGROUP;
  6374. // Now that BaseBrowser understands that CGID_MSHTML should be directed to the DocObject, we'll
  6375. // get caught in a loop if we send those Execs through here. Cut it off at the pass.
  6376. if (pguidCmdGroup && IsEqualGUID(CGID_MSHTML, *pguidCmdGroup))
  6377. return hres;
  6378. if (_pmsoctBrowser)
  6379. hres = _pmsoctBrowser->QueryStatus(pguidCmdGroup, cCmds, rgCmds, pcmdtext);
  6380. return OnQueryStatus(pguidCmdGroup, cCmds, rgCmds, pcmdtext, hres);
  6381. }
  6382. void CDocObjectHost::_OnSave(void)
  6383. {
  6384. if (_pole && _fFileProtocol)
  6385. {
  6386. IPersistFile * ppf = 0;
  6387. HRESULT hres = _pole->QueryInterface(IID_IPersistFile, (void **)&ppf);
  6388. if (SUCCEEDED(hres))
  6389. {
  6390. LPOLESTR pszDisplayName = NULL;
  6391. hres = _GetCurrentPageW(&pszDisplayName);
  6392. if (SUCCEEDED(hres))
  6393. {
  6394. // fRemember = TRUE for normal case
  6395. hres = ppf->Save(pszDisplayName, !_fCantSaveBack);
  6396. if (FAILED(hres))
  6397. {
  6398. TraceMsg(DM_ERROR, "DOH::_OnSave ppf->Save(psz, FALSE) failed with %x", hres);
  6399. }
  6400. OleFree(pszDisplayName);
  6401. }
  6402. ppf->Release();
  6403. }
  6404. }
  6405. }
  6406. HRESULT CDocObjectHost::_OnContentDisposition()
  6407. {
  6408. HRESULT hr = S_OK;
  6409. TCHAR szURL[MAX_URL_STRING];
  6410. HRESULT hresT;
  6411. hresT = _GetCurrentPage(szURL, ARRAYSIZE(szURL), TRUE);
  6412. if (SUCCEEDED(hresT))
  6413. {
  6414. TCHAR * pszURL;
  6415. UINT uRet;
  6416. IUnknown * punk;
  6417. if (_bsc._pszRedirectedURL && lstrlen(_bsc._pszRedirectedURL))
  6418. {
  6419. pszURL = _bsc._pszRedirectedURL;
  6420. }
  6421. else
  6422. {
  6423. pszURL = szURL;
  6424. }
  6425. hresT = QueryInterface(IID_IUnknown, (void**)&punk);
  6426. if (SUCCEEDED(hresT))
  6427. {
  6428. uRet = OpenSafeOpenDialog(_hwnd, DLG_SAFEOPEN, NULL, pszURL, NULL, NULL, NULL, _uiCP, punk);
  6429. switch(uRet)
  6430. {
  6431. case IDOK:
  6432. //
  6433. // Set this flag to avoid poppping this dialog box twice.
  6434. //
  6435. _fConfirmed = TRUE;
  6436. break; // continue download
  6437. case IDD_SAVEAS:
  6438. CDownLoad_OpenUI(_pmkCur, _bsc._pbc, FALSE, TRUE, NULL, NULL, NULL, NULL, NULL, _bsc._pszRedirectedURL, _uiCP, punk);
  6439. // fall thru to AbortBinding
  6440. case IDCANCEL:
  6441. _CancelPendingNavigation(FALSE);
  6442. hr = E_ABORT;
  6443. break;
  6444. }
  6445. punk->Release();
  6446. }
  6447. }
  6448. return hr;
  6449. }
  6450. void CDocObjectHost::_OnSetProgressPos(DWORD dwPos, DWORD state)
  6451. {
  6452. // trident will reset with -1
  6453. if (dwPos == -1)
  6454. state = PROGRESS_RESET;
  6455. switch(state)
  6456. {
  6457. case PROGRESS_RESET:
  6458. TraceMsg(TF_SHDPROGRESS, "DOH::OnSetProgressPos() RESET, timer = %d", _fProgressTimer);
  6459. if (_fProgressTimer)
  6460. {
  6461. KillTimer(_hwnd, IDTIMER_PROGRESS);
  6462. _fProgressTimer = FALSE;
  6463. }
  6464. if (_dwProgressMax)
  6465. {
  6466. // this will always finish up the progress bar
  6467. // so that when trident doesnt send us the last update
  6468. // we do it anyway
  6469. if (_fProgressTimerFull && dwPos == -2)
  6470. {
  6471. _fProgressTimerFull = FALSE;
  6472. KillTimer(_hwnd, IDTIMER_PROGRESSFULL);
  6473. _dwProgressPos = 0;
  6474. _OnSetProgressMax(0);
  6475. _fShowProgressCtl = FALSE;
  6476. _PlaceProgressBar(TRUE);
  6477. }
  6478. else if (!_fProgressTimerFull)
  6479. {
  6480. _OnSetProgressPos(0, PROGRESS_FULL);
  6481. _fProgressTimerFull = TRUE;
  6482. SetTimer(_hwnd, IDTIMER_PROGRESSFULL, 500, NULL);
  6483. }
  6484. }
  6485. else
  6486. {
  6487. _fShowProgressCtl = FALSE;
  6488. _PlaceProgressBar(TRUE);
  6489. }
  6490. break;
  6491. case PROGRESS_FINDING:
  6492. //this covers the first 10%
  6493. TraceMsg(TF_SHDPROGRESS, "DOH::OnSetProgressPos() FINDING, timer = %d", _fProgressTimer);
  6494. ASSERT(!dwPos);
  6495. if (!_fProgressTimer)
  6496. SetTimer(_hwnd, IDTIMER_PROGRESS, 500, NULL);
  6497. _fProgressTimer = TRUE;
  6498. _OnSetProgressMax(10000);
  6499. _dwProgressInc = PROGRESS_INCREMENT;
  6500. _dwProgressPos = 100;
  6501. _dwProgressTicks = 0;
  6502. _dwProgressMod = (PROGRESS_FINDMAX - _dwProgressPos) / (2 * _dwProgressInc);
  6503. break;
  6504. case PROGRESS_SENDING:
  6505. TraceMsg(TF_SHDPROGRESS, "DOH::OnSetProgressPos() SENDING, timer = %d, dwPos = %d", _fProgressTimer, dwPos);
  6506. ASSERT(!dwPos);
  6507. if (!_fProgressTimer)
  6508. SetTimer(_hwnd, IDTIMER_PROGRESS, 500, NULL);
  6509. _fProgressTimer = TRUE;
  6510. _OnSetProgressMax(10000);
  6511. _dwProgressInc = PROGRESS_INCREMENT;
  6512. _dwProgressTicks = 0;
  6513. //dwProgressPos is already set from FINDING
  6514. _dwProgressMod = (PROGRESS_SENDMAX - _dwProgressPos) / (2 * _dwProgressInc);
  6515. break;
  6516. case PROGRESS_RECEIVING:
  6517. TraceMsg(TF_SHDPROGRESS, "DOH::OnSetProgressPos() RECEIVING, timer = %d, dwPos = %d", _fProgressTimer, dwPos);
  6518. if (_fProgressTimer)
  6519. {
  6520. KillTimer(_hwnd, IDTIMER_PROGRESS);
  6521. _fProgressTimer = FALSE;
  6522. // this is the base spot on the progress bar for trident
  6523. _dwProgressBase = _dwProgressPos / PROGRESS_REBASE;
  6524. TraceMsg(TF_SHDPROGRESS, "DOH::OnSetProgressPos() Rebasing at %d%%", _dwProgressPos * 100/ PROGRESS_TOTALMAX);
  6525. }
  6526. // progress max should be set from outside of here....
  6527. _dwProgressPos = ADJUSTPROGRESSPOS(dwPos);
  6528. break;
  6529. case PROGRESS_TICK:
  6530. if (_fProgressTimer)
  6531. {
  6532. if (_dwProgressInc)
  6533. _dwProgressPos += _dwProgressInc;
  6534. // Else we post the still waiting message...
  6535. //
  6536. if (_dwProgressMod && 0 == (++_dwProgressTicks % _dwProgressMod))
  6537. {
  6538. // this means we are about half way.
  6539. _dwProgressInc /= 2;
  6540. }
  6541. TraceMsg(TF_SHDPROGRESS, "DOH::OnSetProgressPos() TICK, dwPos = %d, ticks = %d, inc = %d", _dwProgressPos, _dwProgressTicks, _dwProgressInc);
  6542. }
  6543. else
  6544. TraceMsg(TF_SHDPROGRESS, "DOH::OnSetProgressPos() TICKNOT");
  6545. break;
  6546. case PROGRESS_FULL:
  6547. {
  6548. _dwProgressPos = _dwProgressMax;
  6549. // if there are script errors, make sure the status
  6550. // bar is properly set (re: icon and text)
  6551. if (_pScriptErrList != NULL &&
  6552. !_pScriptErrList->IsEmpty())
  6553. {
  6554. TCHAR szMsg[MAX_PATH];
  6555. // set the script error icon
  6556. if (g_hiconScriptErr != NULL)
  6557. {
  6558. if (_psb != NULL)
  6559. {
  6560. _psb->SendControlMsg(FCW_STATUS,
  6561. SB_SETICON,
  6562. STATUS_PANE_NAVIGATION,
  6563. (LPARAM)g_hiconScriptErr,
  6564. NULL);
  6565. }
  6566. }
  6567. // set the script error text
  6568. MLLoadString(IDS_DONE_WITH_SCRIPT_ERRORS, szMsg, ARRAYSIZE(szMsg));
  6569. _SetPriorityStatusText(szMsg);
  6570. }
  6571. TraceMsg(TF_SHDPROGRESS, "DOH::OnSetProgressPos() FULL");
  6572. }
  6573. break;
  6574. default:
  6575. ASSERT(FALSE);
  6576. }
  6577. if (_hwndProgress)
  6578. {
  6579. _psb->SendControlMsg(FCW_PROGRESS, PBM_SETPOS, _dwProgressPos, 0, NULL);
  6580. TraceMsg(TF_SHDPROGRESS, "DOH::OnSetProgressPos() updating, pos = %d, %d%% full", _dwProgressPos, _dwProgressMax ? _dwProgressPos * 100/ _dwProgressMax : 0);
  6581. }
  6582. // fire an event that progress has changed
  6583. if (_peds)
  6584. {
  6585. // if we are sent a -1, we must forward the event on so that
  6586. // our host gets it too. some containers rely on this.
  6587. // specifically DevStudio's HTMLHelp
  6588. //
  6589. if (dwPos != -1)
  6590. dwPos = _dwProgressPos;
  6591. if (!_fUIActivatingView)
  6592. {
  6593. FireEvent_DoInvokeDwords(_peds,DISPID_PROGRESSCHANGE,dwPos,_dwProgressMax);
  6594. }
  6595. }
  6596. }
  6597. void CDocObjectHost::_OnSetProgressMax(DWORD dwMax)
  6598. {
  6599. // remember the maximum range so we have it when we want to fire progress events
  6600. if (_dwProgressMax != dwMax && _psb)
  6601. {
  6602. _dwProgressMax = dwMax;
  6603. TraceMsg(TF_SHDPROGRESS, "DOH::OnSetProgressMax() max = %d", _dwProgressMax);
  6604. if (!_hwndProgress) {
  6605. _psb->GetControlWindow(FCW_PROGRESS, &_hwndProgress);
  6606. }
  6607. if (_hwndProgress) {
  6608. _psb->SendControlMsg(FCW_PROGRESS, PBM_SETRANGE32, 0, dwMax, NULL);
  6609. TraceMsg(TF_SHDPROGRESS, "DOH::OnSetProgressMax() updating (%d of %d)", _dwProgressPos, _dwProgressMax);
  6610. }
  6611. else
  6612. TraceMsg(TF_SHDPROGRESS, "DOH::OnSetProgressMax() No hwndProgress");
  6613. }
  6614. }
  6615. UINT CDocObjectHost::_MapCommandID(UINT id, BOOL fToMsoCmd)
  6616. {
  6617. // HEY, this maps OLECMDID commands *only*
  6618. static const UINT s_aicmd[][2] = {
  6619. { DVIDM_PROPERTIES, OLECMDID_PROPERTIES },
  6620. { DVIDM_PRINT, OLECMDID_PRINT },
  6621. { DVIDM_PRINTPREVIEW, OLECMDID_PRINTPREVIEW },
  6622. { DVIDM_PAGESETUP, OLECMDID_PAGESETUP},
  6623. { DVIDM_SAVEASFILE, OLECMDID_SAVEAS },
  6624. { DVIDM_CUT, OLECMDID_CUT },
  6625. { DVIDM_COPY, OLECMDID_COPY },
  6626. { DVIDM_PASTE, OLECMDID_PASTE },
  6627. { DVIDM_REFRESH, OLECMDID_REFRESH },
  6628. { DVIDM_STOPDOWNLOAD, OLECMDID_STOP },
  6629. // subset - above this line document handles
  6630. { DVIDM_OPEN, OLECMDID_OPEN },
  6631. { DVIDM_SAVE, OLECMDID_SAVE },
  6632. { DVIDM_SHOWTOOLS, OLECMDID_HIDETOOLBARS },
  6633. };
  6634. #define CCMD_MAX (sizeof(s_aicmd)/sizeof(s_aicmd[0]))
  6635. UINT iFrom = fToMsoCmd ? 0 : 1;
  6636. for (UINT i = 0; i < CCMD_MAX; i++) {
  6637. if (s_aicmd[i][iFrom]==id) {
  6638. return s_aicmd[i][1-iFrom];
  6639. }
  6640. }
  6641. return (UINT)-1;
  6642. #undef CCMD_MAX
  6643. }
  6644. void CDocObjectHost::_InitToolbarButtons()
  6645. {
  6646. OLECMD acmd[] = {
  6647. { OLECMDID_ZOOM, 0 }, // Notes: This must be the first one
  6648. { OLECMDID_PRINT, 0 },
  6649. { OLECMDID_CUT, 0 },
  6650. { OLECMDID_COPY, 0 },
  6651. { OLECMDID_PASTE, 0 },
  6652. { OLECMDID_REFRESH, 0 },
  6653. { OLECMDID_STOP, 0 }, // Notes: This must be the last one
  6654. };
  6655. if (_pmsot) {
  6656. _pmsot->QueryStatus(NULL, ARRAYSIZE(acmd), acmd, NULL);
  6657. }
  6658. if (_pmsoctBrowser) {
  6659. // the browser may support stop also, so override the document
  6660. // with what the browser says. this is okay because the browser
  6661. // forwards stop back down the chain.
  6662. _pmsoctBrowser->QueryStatus(NULL, 1, &acmd[ARRAYSIZE(acmd)-1], NULL);
  6663. }
  6664. if (_psb)
  6665. {
  6666. for (int i=1; i<ARRAYSIZE(acmd); i++)
  6667. {
  6668. UINT idCmd = _MapFromMso(acmd[i].cmdID);
  6669. _psb->SendControlMsg(FCW_TOOLBAR, TB_ENABLEBUTTON, idCmd,
  6670. (LPARAM)acmd[i].cmdf, NULL);
  6671. }
  6672. }
  6673. // Check if ZOOM command is supported.
  6674. if (acmd[0].cmdf)
  6675. {
  6676. VARIANTARG var;
  6677. VariantInit(&var);
  6678. var.vt = VT_I4;
  6679. var.lVal = 0;
  6680. // get the current zoom depth
  6681. _pmsot->Exec(NULL, OLECMDID_ZOOM, OLECMDEXECOPT_DONTPROMPTUSER, NULL, &var);
  6682. if (var.vt == VT_I4)
  6683. {
  6684. _iZoom = var.lVal;
  6685. }
  6686. else
  6687. {
  6688. VariantClear(&var);
  6689. }
  6690. // get the current zoom range
  6691. var.vt = VT_I4;
  6692. var.lVal = 0;
  6693. _pmsot->Exec(NULL, OLECMDID_GETZOOMRANGE, OLECMDEXECOPT_DONTPROMPTUSER, NULL, &var);
  6694. if (var.vt == VT_I4)
  6695. {
  6696. _iZoomMin = (int)(short)LOWORD(var.lVal);
  6697. _iZoomMax = (int)(short)HIWORD(var.lVal);
  6698. }
  6699. else
  6700. {
  6701. VariantClear(&var);
  6702. }
  6703. }
  6704. }
  6705. void CDocObjectHost::_OnSetStatusText(VARIANTARG* pvarIn)
  6706. {
  6707. LPCWSTR pwch = VariantToStrCast(pvarIn);
  6708. if (pwch && _psb)
  6709. {
  6710. IShellView *psvActive;
  6711. _psb->QueryActiveShellView(&psvActive);
  6712. if (psvActive)
  6713. {
  6714. // Suppress sending status messages if we aren't the active view - else
  6715. // we could be reporting nasties from unapproved PICS pages
  6716. if (IsSameObject(_psv, psvActive))
  6717. {
  6718. TCHAR szHint[256];
  6719. if (pwch)
  6720. SHUnicodeToTChar(pwch, szHint, ARRAYSIZE(szHint));
  6721. else
  6722. szHint[0] = 0;
  6723. _SetStatusText(szHint);
  6724. }
  6725. psvActive->Release();
  6726. }
  6727. }
  6728. }
  6729. //
  6730. // This function returns TRUE if
  6731. // (1) the DocObject supports IPersistFile and
  6732. // (2) IPersistFile::IsDirty returns S_OK.
  6733. // Caller may pass pppf to retrieve IPersistFile*, which will be AddRef'ed
  6734. // and returned only when this function returns TRUE.
  6735. //
  6736. BOOL CDocObjectHost::_IsDirty(IPersistFile** pppf)
  6737. {
  6738. BOOL fDirty = FALSE; // Assume non-dirty
  6739. if (pppf)
  6740. *pppf = NULL;
  6741. if (_pole)
  6742. {
  6743. IPersistFile* ppf;
  6744. HRESULT hresT = _pole->QueryInterface(IID_PPV_ARG(IPersistFile, &ppf));
  6745. if (SUCCEEDED(hresT))
  6746. {
  6747. if (ppf->IsDirty()==S_OK)
  6748. {
  6749. fDirty = TRUE;
  6750. if (pppf)
  6751. {
  6752. *pppf = ppf;
  6753. ppf->AddRef();
  6754. }
  6755. }
  6756. ppf->Release();
  6757. }
  6758. }
  6759. return fDirty;
  6760. }
  6761. void CDocObjectHost::_OnSetTitle(VARIANTARG *pvTitle)
  6762. {
  6763. LPCWSTR pwch = VariantToStrCast(pvTitle);
  6764. if (pwch)
  6765. {
  6766. if (_pwb)
  6767. {
  6768. _pwb->SetTitle(_psv, pwch);
  6769. }
  6770. }
  6771. // tell our parent DocObjectView about this as well
  6772. if (_pdvs)
  6773. _pdvs->OnSetTitle(pvTitle);
  6774. }
  6775. void CDocObjectHost::_OnCodePageChange(const VARIANTARG* pvarargIn)
  6776. {
  6777. if (pvarargIn && pvarargIn->vt == VT_I4)
  6778. {
  6779. TraceMsg(DM_DOCCP, "CDOH::OnExec SHDVID_ONCOEPAGECHANGE got %d", pvarargIn->lVal);
  6780. VARIANT var = *pvarargIn;
  6781. //
  6782. // Since the UI (View->Fond) does not say "default codepage",
  6783. // we don't need to be smart about it.
  6784. //
  6785. // if ((UINT)var.lVal == GetACP()) {
  6786. // var.lVal = CP_ACP;
  6787. // }
  6788. //
  6789. // Change the 'current' codepage.
  6790. //
  6791. IBrowserService *pbs;
  6792. if (SUCCEEDED(QueryService(SID_STopLevelBrowser, IID_PPV_ARG(IBrowserService, &pbs))))
  6793. {
  6794. pbs->GetSetCodePage(&var, NULL);
  6795. pbs->Release();
  6796. }
  6797. //
  6798. // Write the codepage to the URL history
  6799. //
  6800. IUniformResourceLocator * purl = NULL;
  6801. HRESULT hresT = CoCreateInstance(CLSID_InternetShortcut, NULL,
  6802. CLSCTX_INPROC_SERVER,
  6803. IID_PPV_ARG(IUniformResourceLocator, &purl));
  6804. if (SUCCEEDED(hresT))
  6805. {
  6806. TCHAR szURL[MAX_URL_STRING];
  6807. _GetCurrentPage(szURL, ARRAYSIZE(szURL), TRUE);
  6808. _ValidateURL(szURL, UQF_DEFAULT);
  6809. hresT = purl->SetURL(szURL, 0);
  6810. if (SUCCEEDED(hresT))
  6811. {
  6812. IPropertySetStorage *ppropsetstg;
  6813. hresT = purl->QueryInterface(IID_PPV_ARG(IPropertySetStorage, &ppropsetstg));
  6814. if (SUCCEEDED(hresT))
  6815. {
  6816. IPropertyStorage *ppropstg;
  6817. hresT = ppropsetstg->Open(FMTID_InternetSite, STGM_READWRITE, &ppropstg);
  6818. if (SUCCEEDED(hresT))
  6819. {
  6820. const static PROPSPEC c_aprop[] = {
  6821. { PRSPEC_PROPID, PID_INTSITE_CODEPAGE},
  6822. };
  6823. PROPVARIANT prvar = { 0 };
  6824. prvar.vt = VT_UI4;
  6825. prvar.lVal = var.lVal;
  6826. hresT = ppropstg->WriteMultiple(1, c_aprop, &prvar, 0);
  6827. TraceMsg(DM_DOCCP, "CDOH::_OnCodePageChange WriteMultile returned %x", hresT);
  6828. ppropstg->Commit(STGC_DEFAULT);
  6829. ppropstg->Release();
  6830. }
  6831. else
  6832. {
  6833. TraceMsg(DM_WARNING, "CDOH::_OnCodePageChange Open failed %x", hresT);
  6834. }
  6835. ppropsetstg->Release();
  6836. }
  6837. else
  6838. {
  6839. TraceMsg(DM_WARNING, "CDOH::_OnCodePageChange QI failed %x", hresT);
  6840. }
  6841. }
  6842. else
  6843. {
  6844. TraceMsg(DM_WARNING, "CDOH::_OnCodePageChange SetURL failed %x", hresT);
  6845. }
  6846. purl->Release();
  6847. }
  6848. else
  6849. {
  6850. TraceMsg(DM_WARNING, "CDOH::_OnCodePageChange CoCreate failed %x", hresT);
  6851. }
  6852. }
  6853. else
  6854. {
  6855. ASSERT(0);
  6856. }
  6857. }
  6858. void CDocObjectHost::_MappedBrowserExec(DWORD nCmdID, DWORD nCmdexecopt)
  6859. {
  6860. if (_pmsoctBrowser)
  6861. {
  6862. DWORD nCmdIDCT = _MapToMso(nCmdID);
  6863. ASSERT(nCmdIDCT != -1); // if this rips, need to add missing case to _MapCommandID
  6864. OLECMD rgcmd = {nCmdIDCT, 0};
  6865. // Trident sometimes executes commands that are disabled (cut, paste) so
  6866. // ensure that the command is enabled first
  6867. BOOL fEnabled = (S_OK == _pmsoctBrowser->QueryStatus(NULL, 1, &rgcmd, NULL)) &&
  6868. (rgcmd.cmdf & OLECMDF_ENABLED);
  6869. // APPHACK - 80104 Visio doesn't return OLECMDF_ENABLED, but we need to
  6870. // be able to execute the command to show the toolbars because they start off hidden.
  6871. if (!fEnabled && (nCmdID == DVIDM_SHOWTOOLS) &&
  6872. (_GetAppHack() & BROWSERFLAG_ENABLETOOLSBTN))
  6873. {
  6874. fEnabled = TRUE;
  6875. }
  6876. if (fEnabled)
  6877. {
  6878. _pmsoctBrowser->Exec(NULL, nCmdIDCT, nCmdexecopt, NULL, NULL);
  6879. }
  6880. }
  6881. }
  6882. HRESULT CDocObjectHost::OnExec(const GUID *pguidCmdGroup, DWORD nCmdID, DWORD nCmdexecopt, VARIANTARG *pvarargIn, VARIANTARG *pvarargOut)
  6883. {
  6884. if (pguidCmdGroup == NULL)
  6885. {
  6886. // _InitToolbarButtons and _OnSetStatusText reference _psb directly
  6887. if (!_psb)
  6888. return E_FAIL;
  6889. switch (nCmdID)
  6890. {
  6891. //
  6892. // The containee has found an http-equiv meta tag; handle it
  6893. // appropriately (client pull, PICS, etc)
  6894. //
  6895. case OLECMDID_HTTPEQUIV:
  6896. case OLECMDID_HTTPEQUIV_DONE:
  6897. if (_pwb)
  6898. {
  6899. _pwb->OnHttpEquiv(_psv, (nCmdID == OLECMDID_HTTPEQUIV_DONE), pvarargIn, pvarargOut);
  6900. // Always return S_OK so that we don't try other codepath.
  6901. }
  6902. return S_OK;
  6903. case OLECMDID_PREREFRESH:
  6904. _fShowProgressCtl = TRUE;
  6905. _PlaceProgressBar(TRUE);
  6906. _OnSetProgressPos(0, PROGRESS_FINDING);
  6907. if (IsGlobalOffline())
  6908. {
  6909. // This is pointing to a web address and we're offline
  6910. // Ask the user if (s)he wants to go online
  6911. TCHAR szURL[MAX_URL_STRING];
  6912. if (SUCCEEDED(_GetCurrentPage(szURL, ARRAYSIZE(szURL), TRUE)) &&
  6913. UrlHitsNet(szURL))
  6914. {
  6915. if (InternetGoOnline(szURL, _hwnd, TRUE) && _psb)
  6916. {
  6917. // Tell all browser windows to update their title and status pane
  6918. SendShellIEBroadcastMessage(WM_WININICHANGE,0,0, 1000);
  6919. }
  6920. }
  6921. }
  6922. return S_OK;
  6923. case OLECMDID_REFRESH:
  6924. if (_pmsot)
  6925. _pmsot->Exec(pguidCmdGroup, nCmdID, nCmdexecopt, pvarargIn, pvarargOut);
  6926. return S_OK;
  6927. case OLECMDID_OPEN:
  6928. _OnOpen();
  6929. return S_OK;
  6930. case OLECMDID_SAVE:
  6931. _OnSave();
  6932. return S_OK;
  6933. case OLECMDID_CLOSE:
  6934. _OnClose();
  6935. return S_OK;
  6936. case OLECMDID_UPDATECOMMANDS:
  6937. _InitToolbarButtons();
  6938. return E_FAIL; // lie and say we don't do anything to forward the command on
  6939. case OLECMDID_SETPROGRESSMAX:
  6940. ASSERT(pvarargIn->vt == VT_I4);
  6941. TraceMsg(TF_SHDPROGRESS, "DOH::Exec() SETPROGRESSMAX = %d", pvarargIn->lVal );
  6942. if (pvarargIn->lVal)
  6943. _OnSetProgressMax(ADJUSTPROGRESSMAX((DWORD) pvarargIn->lVal));
  6944. return S_OK;
  6945. case OLECMDID_SETPROGRESSPOS:
  6946. ASSERT(pvarargIn->vt == VT_I4);
  6947. TraceMsg(TF_SHDPROGRESS, "DOH::Exec() SETPROGRESSPOS = %d", pvarargIn->lVal );
  6948. if (pvarargIn->lVal)
  6949. _OnSetProgressPos((DWORD) pvarargIn->lVal, PROGRESS_RECEIVING);
  6950. return S_OK;
  6951. case OLECMDID_SETPROGRESSTEXT:
  6952. _OnSetStatusText(pvarargIn);
  6953. return S_OK;
  6954. case OLECMDID_SETTITLE:
  6955. if (!pvarargIn)
  6956. return E_INVALIDARG;
  6957. _OnSetTitle(pvarargIn); // We are guaranteed to get atleast 1 OLECMDID_SETTITLE.
  6958. return S_OK;
  6959. // case OLECMDID_PRINT:
  6960. // In the up direction, this case is handled by the outermost frame as
  6961. // a request to print from the docobj. It handles it by sending an OLECMDID_PRINT
  6962. // back to the docobj to print. (Or, as in Binder, to all the docobjects.)
  6963. default:
  6964. return OLECMDERR_E_NOTSUPPORTED;
  6965. }
  6966. }
  6967. else if (IsEqualGUID(CGID_ShellDocView, *pguidCmdGroup))
  6968. {
  6969. switch (nCmdID)
  6970. {
  6971. case SHDVID_SSLSTATUS:
  6972. {
  6973. // Ask the user if (s)he wants to go online
  6974. TCHAR szURL[MAX_URL_STRING];
  6975. if (SUCCEEDED(_GetCurrentPage(szURL, ARRAYSIZE(szURL), TRUE)))
  6976. {
  6977. if (_bsc._pszRedirectedURL && *_bsc._pszRedirectedURL)
  6978. StrCpyN(szURL, _bsc._pszRedirectedURL, ARRAYSIZE(szURL));
  6979. ULONG_PTR uCookie = 0;
  6980. SHActivateContext(&uCookie);
  6981. InternetShowSecurityInfoByURL(szURL, _hwnd);
  6982. if (uCookie)
  6983. {
  6984. SHDeactivateContext(uCookie);
  6985. }
  6986. }
  6987. break;
  6988. }
  6989. case SHDVID_ZONESTATUS:
  6990. {
  6991. // Load the current url into the properties page
  6992. if (!SHRestricted2W(REST_NoBrowserOptions, NULL, 0))
  6993. {
  6994. TCHAR szBuf[MAX_URL_STRING];
  6995. _GetCurrentPage(szBuf, ARRAYSIZE(szBuf));
  6996. ULONG_PTR uCookie = 0;
  6997. SHActivateContext(&uCookie);
  6998. ZoneConfigureW(_hwnd, szBuf);
  6999. if (uCookie)
  7000. {
  7001. SHDeactivateContext(uCookie);
  7002. }
  7003. }
  7004. return S_OK;
  7005. }
  7006. case SHDVID_PRIVACYSTATUS:
  7007. {
  7008. IEnumPrivacyRecords *pEnum = NULL;
  7009. LPOLESTR pszName = NULL;
  7010. BOOL fReportAllSites = (nCmdexecopt == TRUE);
  7011. if(_pmkCur)
  7012. {
  7013. if(FAILED(_pmkCur->GetDisplayName(_pbcCur, NULL, &pszName)))
  7014. {
  7015. pszName = NULL;
  7016. }
  7017. }
  7018. if(_psp && SUCCEEDED(_psp->QueryService(IID_IEnumPrivacyRecords, IID_IEnumPrivacyRecords, (void **)&(pEnum))))
  7019. {
  7020. BOOL fImpacted;
  7021. if(fReportAllSites ||
  7022. (SUCCEEDED(pEnum->GetPrivacyImpacted(&fImpacted)) && fImpacted))
  7023. {
  7024. DoPrivacyDlg(_hwnd, pszName, pEnum, fReportAllSites);
  7025. }
  7026. pEnum->Release();
  7027. }
  7028. if(pszName)
  7029. {
  7030. OleFree(pszName);
  7031. }
  7032. return S_OK;
  7033. }
  7034. case SHDVID_QUERYMERGEDHELPMENU:
  7035. if (_hmenuMergedHelp)
  7036. {
  7037. pvarargOut->vt = VT_INT_PTR;
  7038. pvarargOut->byref = _hmenuMergedHelp;
  7039. return S_OK;
  7040. }
  7041. return S_FALSE;
  7042. case SHDVID_QUERYOBJECTSHELPMENU:
  7043. if (_hmenuObjHelp)
  7044. {
  7045. pvarargOut->vt = VT_INT_PTR;
  7046. pvarargOut->byref = _hmenuObjHelp;
  7047. return S_OK;
  7048. }
  7049. return S_FALSE;
  7050. case SHDVID_GETSYSIMAGEINDEX:
  7051. if (_dwAppHack & BROWSERFLAG_MSHTML) {
  7052. ASSERT(pvarargOut->vt==0);
  7053. pvarargOut->vt = VT_I4;
  7054. pvarargOut->lVal = _GetIEHTMLImageIndex();
  7055. return S_OK;
  7056. }
  7057. return E_FAIL;
  7058. case SHDVID_AMBIENTPROPCHANGE:
  7059. // An ambient property above us has changed, let the docobj know
  7060. if (_pmsoc)
  7061. {
  7062. ASSERT(pvarargIn->vt == VT_I4);
  7063. return(_pmsoc->OnAmbientPropertyChange(pvarargIn->lVal));
  7064. }
  7065. return E_FAIL;
  7066. case SHDVID_CANDOCOLORSCHANGE:
  7067. return IUnknown_Exec(_pole, pguidCmdGroup, nCmdID, nCmdexecopt, pvarargIn, pvarargOut);
  7068. case SHDVID_ONCOLORSCHANGE:
  7069. // this comes from trident and needs passing back up to our parent ...
  7070. if ( _pmsoctBrowser )
  7071. {
  7072. return _pmsoctBrowser->Exec( pguidCmdGroup, nCmdID, nCmdexecopt, pvarargIn, pvarargOut );
  7073. }
  7074. else
  7075. return E_FAIL;
  7076. case SHDVID_GETOPTIONSHWND:
  7077. if ( _pmsoctBrowser )
  7078. {
  7079. return _pmsoctBrowser->Exec( pguidCmdGroup, nCmdID, nCmdexecopt, pvarargIn, pvarargOut );
  7080. }
  7081. else
  7082. {
  7083. return E_FAIL;
  7084. }
  7085. case SHDVID_DOCWRITEABORT:
  7086. // pending DocObject wants to us to abort any binding and activate
  7087. // it directly
  7088. if (_bsc._pib && _bsc._fBinding && _punkPending && !_pole)
  7089. {
  7090. _bsc._fDocWriteAbort = 1;
  7091. _bsc.OnObjectAvailable(IID_IUnknown, _punkPending);
  7092. _bsc.AbortBinding();
  7093. }
  7094. // report READYSTATE_COMPLETE so that when document.open() falls
  7095. // back to READYSTATE_INTERACTIVE Trident doesn't get confused...
  7096. //
  7097. // chrisfra 4/15/97, is this the only way to force TRIDENT
  7098. // to not lose fact of download complete when document.open()
  7099. // falls back to READYSTATE_INTERACTIVE.
  7100. //
  7101. // During the above OnObjectAvailable call, we fire a READYSTATE_COMPLETE
  7102. // event if (1) object doesn't support it or (2) object already at it.
  7103. // (Neither of these should be the case, but we should be careful, eh?)
  7104. // We want to force a READYSTATE_COMPLETE here in other cases, so unhook
  7105. // the IPropertyNotifySink (to prevent multiple _COMPLETE events). If we
  7106. // unhook the sink, then we didn't fire _COMPLETE above, so fire it now.
  7107. //
  7108. if (_dwPropNotifyCookie)
  7109. {
  7110. _OnReadyState(READYSTATE_COMPLETE);
  7111. }
  7112. return S_OK;
  7113. case SHDVID_CANACTIVATENOW:
  7114. {
  7115. HRESULT hres = (_PicsProcBase._fPicsAccessAllowed && !_PicsProcBase._fbPicsWaitFlags && _pole && _fReadystateInteractiveProcessed) ? S_OK : S_FALSE;
  7116. TraceMsg(DM_PICS, "CDOH::OnExec(SHDVID_CANACTIVATENOW) returning %ls", (hres == S_OK) ? "S_OK" : "S_FALSE");
  7117. return hres;
  7118. }
  7119. case SHDVID_SETSECURELOCK:
  7120. {
  7121. //
  7122. // if we are already active, then we need to go ahead
  7123. // and forward this up the browser. otherwise, cache it
  7124. // and wait until activated to forward it
  7125. //
  7126. TraceMsg(DM_SSL, "[%X]DOH::Exec() SETSECURELOCK lock = %d", this, pvarargIn->lVal);
  7127. _fSetSecureLock = TRUE;
  7128. _eSecureLock = pvarargIn->lVal;
  7129. IShellView *psvActive;
  7130. if (_psb && SUCCEEDED(_psb->QueryActiveShellView(&psvActive) ))
  7131. {
  7132. if (psvActive && IsSameObject(_psv, psvActive))
  7133. _ForwardSetSecureLock(pvarargIn->lVal);
  7134. ATOMICRELEASE(psvActive);
  7135. }
  7136. return S_OK;
  7137. }
  7138. case SHDVID_FORWARDSECURELOCK:
  7139. _ForwardSetSecureLock(_fSetSecureLock ? _eSecureLock : SECURELOCK_SET_UNSECURE);
  7140. return S_OK;
  7141. case SHDVID_ONCODEPAGECHANGE:
  7142. _OnCodePageChange(pvarargIn);
  7143. return S_OK;
  7144. case SHDVID_DISPLAYSCRIPTERRORS:
  7145. case SHDVID_NAVIGATIONSTATUS:
  7146. {
  7147. // if we're a weboc then this script err list should be null
  7148. ASSERT(!_fWebOC || _pScriptErrList == NULL);
  7149. if (_pScriptErrList != NULL && !_pScriptErrList->IsEmpty())
  7150. {
  7151. // do the script error info dialog
  7152. _ScriptErr_Dlg(TRUE);
  7153. }
  7154. return S_OK;
  7155. }
  7156. break;
  7157. case SHDVID_RESETSTATUSBAR:
  7158. {
  7159. _ResetStatusBar();
  7160. return S_OK;
  7161. }
  7162. break;
  7163. default:
  7164. return OLECMDERR_E_NOTSUPPORTED;
  7165. }
  7166. }
  7167. else if (IsEqualGUID(CGID_Explorer, *pguidCmdGroup))
  7168. {
  7169. switch (nCmdID) {
  7170. case SBCMDID_MAYSAVECHANGES:
  7171. return _OnMaySaveChanges();
  7172. case SBCMDID_GETPANE:
  7173. switch(nCmdexecopt)
  7174. {
  7175. case PANE_NAVIGATION:
  7176. V_I4(pvarargOut) = STATUS_PANE_NAVIGATION;
  7177. return S_OK;
  7178. case PANE_PROGRESS:
  7179. V_I4(pvarargOut) = STATUS_PANE_PROGRESS;
  7180. return S_OK;
  7181. case PANE_ZONE:
  7182. V_I4(pvarargOut) = STATUS_PANE_ZONE;
  7183. return S_OK;
  7184. case PANE_OFFLINE:
  7185. V_I4(pvarargOut) = STATUS_PANE_OFFLINE;
  7186. return S_OK;
  7187. case PANE_PRINTER:
  7188. V_I4(pvarargOut) = STATUS_PANE_PRINTER;
  7189. return S_OK;
  7190. case PANE_SSL:
  7191. V_I4(pvarargOut) = STATUS_PANE_SSL;
  7192. return S_OK;
  7193. case PANE_PRIVACY:
  7194. V_I4(pvarargOut) = STATUS_PANE_PRIVACY;
  7195. return S_OK;
  7196. default:
  7197. V_I4(pvarargOut) = PANE_NONE;
  7198. return S_OK;
  7199. }
  7200. case SBCMDID_ONCLOSE:
  7201. _fClosing = TRUE;
  7202. return S_OK;
  7203. default:
  7204. return OLECMDERR_E_NOTSUPPORTED;
  7205. } // switch
  7206. }
  7207. else if (IsEqualGUID(CGID_DocHostCommandHandler, *pguidCmdGroup))
  7208. {
  7209. switch(nCmdID)
  7210. {
  7211. case OLECMDID_SAVEAS:
  7212. _OnSaveAs();
  7213. return S_OK;
  7214. case OLECMDID_SHOWSCRIPTERROR:
  7215. {
  7216. HRESULT hr;
  7217. hr = S_OK;
  7218. if (_fWebOC)
  7219. {
  7220. // we're a web oc.
  7221. // pass the handling of this script error to
  7222. // an appropriate CDocHostUIHandler
  7223. if (_pWebOCUIHandler != NULL)
  7224. {
  7225. IOleCommandTarget * pioct;
  7226. ASSERT(IS_VALID_CODE_PTR(_pWebOCUIHandler, IDocHostUIHandler));
  7227. hr = _pWebOCUIHandler->QueryInterface(IID_IOleCommandTarget, (void **) &pioct);
  7228. if (SUCCEEDED(hr))
  7229. {
  7230. hr = pioct->Exec(pguidCmdGroup, nCmdID, nCmdexecopt, pvarargIn, pvarargOut);
  7231. pioct->Release();
  7232. }
  7233. }
  7234. else
  7235. {
  7236. hr = _dhUIHandler.Exec(pguidCmdGroup, nCmdID, nCmdexecopt, pvarargIn, pvarargOut);
  7237. }
  7238. }
  7239. else
  7240. {
  7241. ASSERT(IS_VALID_READ_PTR(pvarargIn, VARIANTARG));
  7242. ASSERT(IS_VALID_WRITE_PTR(pvarargOut, VARIANTARG));
  7243. // we're not a web oc so we have to handle this
  7244. // ourselves, so cache the errors for later
  7245. // display in the new script error dialog
  7246. if (pvarargIn == NULL || pvarargOut == NULL)
  7247. {
  7248. hr = E_INVALIDARG;
  7249. }
  7250. if (SUCCEEDED(hr))
  7251. {
  7252. if (_pScriptErrList == NULL)
  7253. {
  7254. // create a new script error list
  7255. _pScriptErrList = new CScriptErrorList;
  7256. if (_pScriptErrList == NULL)
  7257. {
  7258. hr = E_OUTOFMEMORY;
  7259. }
  7260. }
  7261. if (SUCCEEDED(hr))
  7262. {
  7263. TCHAR szMsg[MAX_PATH];
  7264. // stuff the error icon into the status bar
  7265. if (g_hiconScriptErr != NULL)
  7266. {
  7267. if (_psb != NULL)
  7268. {
  7269. _psb->SendControlMsg(FCW_STATUS,
  7270. SB_SETICON,
  7271. STATUS_PANE_NAVIGATION,
  7272. (LPARAM)g_hiconScriptErr,
  7273. NULL);
  7274. }
  7275. }
  7276. // stuff the error text into the status bar
  7277. MLLoadString(IDS_SCRIPT_ERROR_ON_PAGE, szMsg, ARRAYSIZE(szMsg));
  7278. _SetPriorityStatusText(szMsg);
  7279. // stuff the error data into the cache
  7280. _ScriptErr_CacheInfo(pvarargIn);
  7281. // pop up the dialog
  7282. _ScriptErr_Dlg(FALSE);
  7283. V_VT(pvarargOut) = VT_BOOL;
  7284. if (_pScriptErrList->IsFull())
  7285. {
  7286. // stop running scripts
  7287. V_BOOL(pvarargOut) = VARIANT_FALSE;
  7288. }
  7289. else
  7290. {
  7291. // keep running scripts
  7292. V_BOOL(pvarargOut) = VARIANT_TRUE;
  7293. }
  7294. }
  7295. }
  7296. }
  7297. return hr;
  7298. }
  7299. break;
  7300. case OLECMDID_SHOWMESSAGE:
  7301. case OLECMDID_SHOWFIND:
  7302. case OLECMDID_SHOWPAGESETUP:
  7303. case OLECMDID_SHOWPRINT:
  7304. case OLECMDID_PROPERTIES:
  7305. {
  7306. return _dhUIHandler.Exec(pguidCmdGroup, nCmdID, nCmdexecopt, pvarargIn, pvarargOut);
  7307. }
  7308. break;
  7309. //
  7310. // Refresh the original page if an error page is dispalyed.
  7311. //
  7312. case IDM_REFRESH:
  7313. case IDM_REFRESH_TOP:
  7314. case IDM_REFRESH_TOP_FULL:
  7315. case IDM_REFRESH_THIS:
  7316. case IDM_REFRESH_THIS_FULL:
  7317. {
  7318. HRESULT hr = OLECMDERR_E_NOTSUPPORTED;
  7319. if (_pScriptErrList != NULL)
  7320. {
  7321. // clear out the script error list
  7322. _pScriptErrList->ClearErrorList();
  7323. _SetPriorityStatusText(NULL);
  7324. // reset the text and icon
  7325. _ResetStatusBar();
  7326. }
  7327. //
  7328. // If there is a refresh url for this object use it for the refresh.
  7329. // Otherwise fall through and let the client handle it.
  7330. //
  7331. if (_pwszRefreshUrl)
  7332. {
  7333. _fRefresh = TRUE;
  7334. _DoAsyncNavigation(_pwszRefreshUrl);
  7335. hr = S_OK;
  7336. }
  7337. else
  7338. {
  7339. //
  7340. // Non http errors (syntax, DNS, etc) are handled by a async nav
  7341. // to res://shdocvw/error.htm#originalurl. Handle the refresh
  7342. // for those pages here.
  7343. //
  7344. if (_pmkCur)
  7345. {
  7346. LPOLESTR pstrUrl;
  7347. if (SUCCEEDED(_pmkCur->GetDisplayName(_pbcCur, NULL, &pstrUrl)))
  7348. {
  7349. if (IsErrorUrl(pstrUrl) && _pszLocation && *_pszLocation)
  7350. {
  7351. //
  7352. // The error url has the form:
  7353. // "res://shdocvw.dll/http404.htm#http://foo.bar"
  7354. // Where foo.bar is the the url the user tried to navigate to.
  7355. // _pszLocation points to "#foo.bar"
  7356. DWORD dwScheme = GetUrlScheme(_pszLocation + 1);
  7357. BOOL fDoNavigation = ((URL_SCHEME_HTTP == dwScheme) ||
  7358. (URL_SCHEME_HTTPS == dwScheme) ||
  7359. (URL_SCHEME_FTP == dwScheme) ||
  7360. (URL_SCHEME_GOPHER == dwScheme));
  7361. //
  7362. if (fDoNavigation) // otherwise it's a security problem !
  7363. {
  7364. _fRefresh = TRUE;
  7365. _DoAsyncNavigation(_pszLocation + 1);
  7366. }
  7367. hr = S_OK;
  7368. }
  7369. OleFree(pstrUrl);
  7370. }
  7371. }
  7372. }
  7373. return hr;
  7374. break;
  7375. }
  7376. default:
  7377. return OLECMDERR_E_NOTSUPPORTED;
  7378. }
  7379. }
  7380. else if (IsEqualGUID(*pguidCmdGroup, CLSID_InternetButtons) ||
  7381. IsEqualGUID(*pguidCmdGroup, CLSID_MSOButtons))
  7382. {
  7383. UEMFireEvent(&UEMIID_BROWSER, UEME_UITOOLBAR, UEMF_XEVENT, UIG_OTHER, nCmdID);
  7384. if (nCmdexecopt == OLECMDEXECOPT_PROMPTUSER) {
  7385. // the user hit the drop down
  7386. if (_pmsoctBrowser && pvarargIn && pvarargIn->vt == VT_INT_PTR)
  7387. {
  7388. // v.vt = VT_INT_PTR;
  7389. POINT pt;
  7390. RECT* prc = (RECT*)pvarargIn->byref;
  7391. pt.x = prc->left;
  7392. pt.y = prc->bottom;
  7393. switch (nCmdID)
  7394. {
  7395. case DVIDM_MAILNEWS:
  7396. {
  7397. VARIANTARG v = {VT_I4};
  7398. v.lVal = MAKELONG(prc->left, prc->bottom);
  7399. _pmsoctBrowser->Exec(&CGID_Explorer, SBCMDID_DOMAILMENU, 0, &v, NULL);
  7400. break;
  7401. }
  7402. case DVIDM_FONTS:
  7403. {
  7404. VARIANTARG v = {VT_I4};
  7405. v.lVal = MAKELONG(prc->left, prc->bottom);
  7406. _pmsoctBrowser->Exec(&CGID_ShellDocView, SHDVID_FONTMENUOPEN, 0, &v, NULL);
  7407. break;
  7408. }
  7409. case DVIDM_ENCODING:
  7410. {
  7411. VARIANTARG v = {VT_I4};
  7412. v.lVal = MAKELONG(prc->left, prc->bottom);
  7413. _pmsoctBrowser->Exec(&CGID_ShellDocView, SHDVID_MIMECSETMENUOPEN, 0, &v, NULL);
  7414. break;
  7415. }
  7416. }
  7417. }
  7418. return S_OK;
  7419. }
  7420. // CommandIDs from DVIDM_MENUEXT_FIRST to DVIDM_MENUEXT_LAST are reserved for toolbar extension buttons
  7421. // Do NOT use this range for constants within the scope of CLSID_InternetButtons/CLSID_MSOButtons!
  7422. if (InRange(nCmdID, DVIDM_MENUEXT_FIRST, DVIDM_MENUEXT_LAST))
  7423. {
  7424. IUnknown_Exec(_pBrowsExt, &CLSID_ToolbarExtButtons, nCmdID, nCmdexecopt, pvarargIn, pvarargOut);
  7425. }
  7426. else
  7427. {
  7428. switch(nCmdID) {
  7429. case DVIDM_DISCUSSIONS:
  7430. if (_pmsoctBrowser)
  7431. _pmsoctBrowser->Exec(&CGID_Explorer, SBCMDID_DISCUSSIONBAND, OLECMDEXECOPT_DONTPROMPTUSER, NULL, NULL);
  7432. break;
  7433. case DVIDM_CUT:
  7434. case DVIDM_COPY:
  7435. case DVIDM_PASTE:
  7436. _MappedBrowserExec(nCmdID, 0);
  7437. break;
  7438. case DVIDM_PRINT:
  7439. case DVIDM_PRINTPREVIEW:
  7440. case DVIDM_SHOWTOOLS:
  7441. _MappedBrowserExec(nCmdID, OLECMDEXECOPT_DONTPROMPTUSER);
  7442. break;
  7443. case DVIDM_EDITPAGE:
  7444. if (_psp) {
  7445. // temp code -- forward to itbar
  7446. // itbar edit code is moving here soon
  7447. IExplorerToolbar* pxtb;
  7448. if (SUCCEEDED(_psp->QueryService(SID_SExplorerToolbar, IID_IExplorerToolbar, (void **)&pxtb))) {
  7449. IUnknown_Exec(pxtb, &CGID_PrivCITCommands, CITIDM_EDITPAGE, nCmdexecopt, pvarargIn, pvarargOut);
  7450. pxtb->Release();
  7451. }
  7452. }
  7453. break;
  7454. }
  7455. }
  7456. return S_OK;
  7457. }
  7458. else if (IsEqualGUID(IID_IExplorerToolbar, *pguidCmdGroup))
  7459. {
  7460. switch (nCmdID)
  7461. {
  7462. case ETCMDID_GETBUTTONS:
  7463. {
  7464. int nNumExtButtons = 0;
  7465. if (_pBrowsExt)
  7466. {
  7467. _pBrowsExt->GetNumButtons((UINT*)&nNumExtButtons);
  7468. }
  7469. int nNumButtons = nNumExtButtons + ARRAYSIZE(c_tbStd);
  7470. if ((_nNumButtons != nNumButtons) && (_ptbStd != NULL))
  7471. {
  7472. delete [] _ptbStd;
  7473. _ptbStd = NULL;
  7474. }
  7475. if (_ptbStd == NULL)
  7476. {
  7477. _ptbStd = new TBBUTTON[nNumButtons];
  7478. if (_ptbStd == NULL)
  7479. {
  7480. return E_OUTOFMEMORY;
  7481. }
  7482. _nNumButtons = nNumButtons;
  7483. }
  7484. memcpy(_ptbStd, c_tbStd, SIZEOF(TBBUTTON) * ARRAYSIZE(c_tbStd));
  7485. // Init the string ids
  7486. ASSERT(_ptbStd[6].idCommand == DVIDM_CUT);
  7487. ASSERT(_ptbStd[7].idCommand == DVIDM_COPY);
  7488. ASSERT(_ptbStd[8].idCommand == DVIDM_PASTE);
  7489. ASSERT(_ptbStd[9].idCommand == DVIDM_ENCODING);
  7490. ASSERT(_ptbStd[10].idCommand == DVIDM_PRINTPREVIEW);
  7491. if (-1 != _iString)
  7492. {
  7493. _ptbStd[6].iString = _iString;
  7494. _ptbStd[7].iString = _iString + 1;
  7495. _ptbStd[8].iString = _iString + 2;
  7496. _ptbStd[9].iString = _iString + 3;
  7497. _ptbStd[10].iString = _iString + 4;
  7498. }
  7499. else
  7500. {
  7501. _ptbStd[6].iString = _ptbStd[7].iString = _ptbStd[8].iString = _ptbStd[9].iString = _ptbStd[10].iString = -1;
  7502. }
  7503. if (_pBrowsExt)
  7504. {
  7505. _pBrowsExt->GetButtons(&_ptbStd[ARRAYSIZE(c_tbStd)], nNumExtButtons, FALSE);
  7506. }
  7507. ASSERT(_ptbStd[0].idCommand == DVIDM_SHOWTOOLS);
  7508. if (!_ToolsButtonAvailable())
  7509. _ptbStd[0].fsState |= TBSTATE_HIDDEN;
  7510. ASSERT(_ptbStd[1].idCommand == DVIDM_MAILNEWS);
  7511. if (!_MailButtonAvailable())
  7512. _ptbStd[1].fsState |= TBSTATE_HIDDEN;
  7513. ASSERT(_ptbStd[5].idCommand == DVIDM_DISCUSSIONS);
  7514. if (!_DiscussionsButtonAvailable())
  7515. _ptbStd[5].fsState |= TBSTATE_HIDDEN;
  7516. nNumButtons = RemoveHiddenButtons(_ptbStd, nNumButtons);
  7517. pvarargOut->vt = VT_BYREF;
  7518. pvarargOut->byref = (LPVOID)_ptbStd;
  7519. *pvarargIn->plVal = nNumButtons;
  7520. break;
  7521. }
  7522. case ETCMDID_RELOADBUTTONS:
  7523. _AddButtons(TRUE);
  7524. break;
  7525. }
  7526. return S_OK;
  7527. }
  7528. else if (IsEqualGUID(CGID_InternetExplorer, *pguidCmdGroup))
  7529. {
  7530. switch (nCmdID) {
  7531. case IECMDID_BEFORENAVIGATE_GETSHELLBROWSE:
  7532. case IECMDID_BEFORENAVIGATE_DOEXTERNALBROWSE:
  7533. case IECMDID_BEFORENAVIGATE_GETIDLIST:
  7534. if ( _pmsoctBrowser )
  7535. {
  7536. return _pmsoctBrowser->Exec( pguidCmdGroup, nCmdID, nCmdexecopt, pvarargIn, pvarargOut );
  7537. }
  7538. else
  7539. {
  7540. return E_FAIL;
  7541. }
  7542. default:
  7543. return OLECMDERR_E_NOTSUPPORTED;
  7544. }
  7545. }
  7546. return OLECMDERR_E_UNKNOWNGROUP;
  7547. }
  7548. HRESULT CDocObjectHost::_OnMaySaveChanges(void)
  7549. {
  7550. HRESULT hres = S_OK;
  7551. //
  7552. // ASSUMPTIONS:
  7553. // 1. Not supporting IPersistFile indicates we don't need to worry
  7554. // about prompting the user for "save as".
  7555. // 2. DocObject which returns S_OK for IPersistFile::S_OK implements
  7556. // OLECMDID_SAVEAS.
  7557. //
  7558. if (_fFileProtocol || _pmsot)
  7559. {
  7560. IPersistFile* ppf;
  7561. if (_IsDirty(&ppf))
  7562. {
  7563. ASSERT(ppf);
  7564. TCHAR szBuf[MAX_URL_STRING];
  7565. UINT id;
  7566. _GetCurrentPage(szBuf, ARRAYSIZE(szBuf));
  7567. id = MLShellMessageBox(_hwnd,
  7568. MAKEINTRESOURCE(IDS_MAYSAVEDOCUMENT), szBuf, MB_YESNOCANCEL);
  7569. switch(id) {
  7570. case IDCANCEL:
  7571. hres = S_FALSE;
  7572. break;
  7573. case IDYES:
  7574. if (_fFileProtocol) {
  7575. // 80105 APPHACK: Due to valid fixes in Urlmon, Visio is unable to save
  7576. // because we are loading the object with read-only flags. So we show
  7577. // the Save As dialog to let the user choose another filename.
  7578. if (_GetAppHack() & BROWSERFLAG_SAVEASWHENCLOSING)
  7579. {
  7580. if (_OnSaveAs() != S_OK)
  7581. hres = S_FALSE;
  7582. }
  7583. else
  7584. _OnSave();
  7585. } else {
  7586. HRESULT hresT=_pmsot->Exec(NULL, OLECMDID_SAVEAS, OLECMDEXECOPT_PROMPTUSER, NULL, NULL);
  7587. SAVEMSG("Exec(OLECMDID_SAVEAS) returned", hresT);
  7588. // Cancel the navigation if it failed.
  7589. if (FAILED(hresT)) {
  7590. // Beep if it is not canceled by the end user.
  7591. TraceMsg(DM_WARNING, "CDOH::_OnMaySaveChanges Exec(OELCMDID_SAVEAS) returned %x", hresT);
  7592. if (hresT != OLECMDERR_E_CANCELED) {
  7593. MessageBeep(0);
  7594. }
  7595. hres = S_FALSE;
  7596. }
  7597. }
  7598. break;
  7599. case IDNO:
  7600. //
  7601. // If user says 'No' to save changes to this page,
  7602. // we should remove it from the cache so that
  7603. // the user won't see that discarded change.
  7604. //
  7605. // (pri-2) This object discarding mechanism
  7606. // does not work for POSTed result, which is cached
  7607. // in the travel log.
  7608. //
  7609. break;
  7610. }
  7611. ppf->Release();
  7612. } else {
  7613. ASSERT(ppf==NULL);
  7614. }
  7615. }
  7616. //
  7617. // In addition, we give a chance to save the contents of the page (when
  7618. // the document is acted as a form -- data-bound Trident page is a good
  7619. // example) to the backend database.
  7620. //
  7621. if (hres == S_OK && _pmsot && (!_fDocCanNavigate || _fClosing))
  7622. {
  7623. VARIANT varOut = {0};
  7624. HRESULT hresT = _pmsot->Exec(NULL, OLECMDID_ONUNLOAD, OLECMDEXECOPT_PROMPTUSER, NULL, &varOut);
  7625. if (varOut.vt == VT_BOOL && varOut.boolVal != VARIANT_TRUE)
  7626. {
  7627. hres = S_FALSE;
  7628. }
  7629. }
  7630. return hres;
  7631. }
  7632. BOOL _ExecNearest(const GUID *pguidCmdGroup, DWORD nCmdID, BOOL fDown)
  7633. {
  7634. // Some commands we want to do in the closest frame to the docobj,
  7635. // some in the farthest-away frame, and some we want to handle
  7636. // in the top-most dochost. Look at the command to figure out
  7637. // the routing and then do it.
  7638. BOOL fNearest = FALSE; // most everything goes to the farthest-away frame
  7639. if (pguidCmdGroup==NULL)
  7640. {
  7641. switch(nCmdID)
  7642. {
  7643. case OLECMDID_OPEN:
  7644. case OLECMDID_SAVE:
  7645. case OLECMDID_SETTITLE:
  7646. case OLECMDID_HTTPEQUIV:
  7647. case OLECMDID_HTTPEQUIV_DONE:
  7648. fNearest = TRUE;
  7649. break;
  7650. // some are top-most down, so nearest depends on direction.
  7651. case OLECMDID_REFRESH:
  7652. // say top-most for commands that only work on the topmost guy.
  7653. // (ie, these probably should be implemented in CShellBrowser!)
  7654. // do this even though these are really "upwards-only" commands.
  7655. case OLECMDID_UPDATECOMMANDS:
  7656. case OLECMDID_SETPROGRESSMAX:
  7657. case OLECMDID_SETPROGRESSPOS:
  7658. case OLECMDID_SETPROGRESSTEXT:
  7659. case OLECMDID_SHOWSCRIPTERROR:
  7660. fNearest = fDown;
  7661. break;
  7662. }
  7663. }
  7664. else if (IsEqualGUID(CGID_ShellDocView, *pguidCmdGroup))
  7665. {
  7666. switch (nCmdID)
  7667. {
  7668. case SHDVID_AMBIENTPROPCHANGE:
  7669. case SHDVID_GETSYSIMAGEINDEX:
  7670. case SHDVID_DOCWRITEABORT:
  7671. case SHDVID_ONCODEPAGECHANGE:
  7672. case SHDVID_CANDOCOLORSCHANGE:
  7673. case SHDVID_SETSECURELOCK:
  7674. case SHDVID_QUERYMERGEDHELPMENU:
  7675. case SHDVID_QUERYOBJECTSHELPMENU:
  7676. fNearest = TRUE;
  7677. break;
  7678. case SHDVID_DISPLAYSCRIPTERRORS:
  7679. fNearest = fDown;
  7680. break;
  7681. }
  7682. }
  7683. else if (IsEqualGUID(CGID_Explorer, *pguidCmdGroup))
  7684. {
  7685. switch(nCmdID)
  7686. {
  7687. case SBCMDID_MAYSAVECHANGES: // since OLECMDID_SAVE is to the nearest frame
  7688. fNearest = TRUE;
  7689. break;
  7690. }
  7691. }
  7692. else if (IsEqualGUID(IID_IExplorerToolbar, *pguidCmdGroup) ||
  7693. IsEqualGUID(CLSID_InternetButtons, *pguidCmdGroup) ||
  7694. IsEqualGUID(CLSID_MSOButtons, *pguidCmdGroup))
  7695. {
  7696. fNearest = TRUE;
  7697. }
  7698. return fNearest;
  7699. }
  7700. HRESULT CDocObjectHost::Exec(const GUID * pguidCmdGroup,
  7701. DWORD nCmdID,
  7702. DWORD nCmdexecopt,
  7703. VARIANTARG * pvarargIn,
  7704. VARIANTARG * pvarargOut)
  7705. {
  7706. HRESULT hres = OLECMDERR_E_UNKNOWNGROUP;
  7707. if (pguidCmdGroup)
  7708. {
  7709. // Now that BaseBrowser understands that CGID_MSHTML should be directed to the DocObject, we'll
  7710. // get caught in a loop if we send those Execs through here. Cut it off at the pass.
  7711. if (IsEqualGUID(CGID_MSHTML, *pguidCmdGroup))
  7712. {
  7713. return hres;
  7714. }
  7715. else if (IsEqualGUID(CGID_DocHostCommandHandler, *pguidCmdGroup))
  7716. {
  7717. BOOL fHandled = FALSE;
  7718. HRESULT hr = _HandleDocHostCmds(nCmdID,
  7719. nCmdexecopt,
  7720. pvarargIn,
  7721. pvarargOut,
  7722. &fHandled);
  7723. if (fHandled)
  7724. {
  7725. return hr;
  7726. }
  7727. }
  7728. else if (IsEqualGUID(CGID_DocHostCmdPriv, *pguidCmdGroup))
  7729. {
  7730. BOOL fHandled = FALSE;
  7731. HRESULT hr = _HandleDocHostCmdPriv(nCmdID,
  7732. nCmdexecopt,
  7733. pvarargIn,
  7734. pvarargOut,
  7735. &fHandled);
  7736. if (fHandled)
  7737. {
  7738. return hr;
  7739. }
  7740. }
  7741. else if (IsEqualGUID(CGID_ShellDocView, *pguidCmdGroup))
  7742. {
  7743. if (_HandleShdocvwCmds(nCmdID, nCmdexecopt, pvarargIn, pvarargOut))
  7744. {
  7745. return S_OK;
  7746. }
  7747. }
  7748. }
  7749. BOOL fNearest = _ExecNearest(pguidCmdGroup, nCmdID, FALSE);
  7750. if (fNearest)
  7751. hres = OnExec(pguidCmdGroup, nCmdID, nCmdexecopt, pvarargIn, pvarargOut);
  7752. if (FAILED(hres) && _pmsoctBrowser)
  7753. {
  7754. hres = _pmsoctBrowser->Exec(pguidCmdGroup, nCmdID, nCmdexecopt,
  7755. pvarargIn, pvarargOut);
  7756. }
  7757. // If this is a command that puts up UI and the user presses
  7758. // cancel in the above call, we may try to handle the call here,
  7759. // and that would be bad. Steal OleCmdHRHandled() from MSHTML.
  7760. if (FAILED(hres) && !fNearest)
  7761. hres = OnExec(pguidCmdGroup, nCmdID, nCmdexecopt, pvarargIn, pvarargOut);
  7762. return hres;
  7763. }
  7764. //+---------------------------------------------------------------------------
  7765. //
  7766. // Member : CDocObjectHost::_HandleDocHostCmds
  7767. //
  7768. // Synopsis : Handles the CMD IDs for CGID_DocHostCommandHandler.
  7769. //
  7770. //+---------------------------------------------------------------------------
  7771. HRESULT
  7772. CDocObjectHost::_HandleDocHostCmds(DWORD nCmdID,
  7773. DWORD nCmdexecopt,
  7774. VARIANTARG * pvarargIn,
  7775. VARIANTARG * pvarargOut,
  7776. BOOL * pfHandled)
  7777. {
  7778. HRESULT hres = E_FAIL;
  7779. ASSERT(pfHandled);
  7780. *pfHandled = TRUE;
  7781. switch(nCmdID)
  7782. {
  7783. // Call from Trident printing with the page # of the currently spooling page.
  7784. // Convert it to a bool indicating whether or not to draw the print icon in the browser.
  7785. case OLECMDID_UPDATEPAGESTATUS:
  7786. hres = E_INVALIDARG;
  7787. if (pvarargIn && pvarargIn->vt == VT_I4)
  7788. {
  7789. VARIANTARG varIn;
  7790. V_VT(&varIn) = VT_BOOL;
  7791. V_BOOL(&varIn)= (pvarargIn->lVal > 0) ? VARIANT_TRUE : VARIANT_FALSE;
  7792. hres = _pmsoctBrowser->Exec(&CGID_ShellDocView,
  7793. SHDVID_SETPRINTSTATUS,
  7794. 0,
  7795. &varIn,
  7796. NULL);
  7797. }
  7798. break;
  7799. case OLECMDID_REFRESH:
  7800. // if the print Preview template is up, then we need to block refresh. IE bug (99685)
  7801. hres = _dhUIHandler.Exec(&CGID_DocHostCommandHandler,
  7802. OLECMDID_REFRESH,
  7803. nCmdexecopt, pvarargIn, pvarargOut);
  7804. break;
  7805. // Allow the command ID to be passed down the Exec chain.
  7806. //
  7807. default:
  7808. *pfHandled = FALSE;
  7809. break;
  7810. }
  7811. return hres;
  7812. }
  7813. //+---------------------------------------------------------------------------
  7814. //
  7815. // Member : CDocObjectHost::_HandleDocHostCmdPriv
  7816. //
  7817. // Synopsis : Handles the CMD IDs for CGID_DocHostCmdPriv
  7818. //
  7819. //+---------------------------------------------------------------------------
  7820. HRESULT
  7821. CDocObjectHost::_HandleDocHostCmdPriv(DWORD nCmdID,
  7822. DWORD nCmdexecopt,
  7823. VARIANTARG * pvarargIn,
  7824. VARIANTARG * pvarargOut,
  7825. BOOL * pfHandled)
  7826. {
  7827. HRESULT hres = E_FAIL;
  7828. ASSERT(pfHandled);
  7829. *pfHandled = TRUE;
  7830. switch(nCmdID)
  7831. {
  7832. case DOCHOST_DOCCANNAVIGATE:
  7833. {
  7834. // We only set the navigation window for the top-level browser.
  7835. // Even though the WebOC is no longer in frames, it can still
  7836. // be present on a web page as a view link or control.
  7837. //
  7838. DWORD dwFlags = 0;
  7839. if ( _pwb )
  7840. {
  7841. hres = _pwb->GetFlags(&dwFlags);
  7842. }
  7843. if ((dwFlags & BSF_TOPBROWSER) || _IsInBrowserBand())
  7844. {
  7845. ATOMICRELEASE(_pHTMLWindow);
  7846. if (pvarargIn && VT_UNKNOWN == V_VT(pvarargIn) && V_UNKNOWN(pvarargIn))
  7847. {
  7848. _fDocCanNavigate = TRUE;
  7849. hres = V_UNKNOWN(pvarargIn)->QueryInterface(IID_IHTMLWindow2,
  7850. (void**)&_pHTMLWindow);
  7851. }
  7852. else
  7853. {
  7854. _fDocCanNavigate = FALSE;
  7855. }
  7856. }
  7857. // Pass to the parent shell browser.
  7858. if (_pmsoctBrowser)
  7859. {
  7860. hres = _pmsoctBrowser->Exec(&CGID_DocHostCmdPriv, nCmdID,
  7861. nCmdexecopt, pvarargIn, pvarargOut);
  7862. }
  7863. }
  7864. break;
  7865. case DOCHOST_READYSTATE_INTERACTIVE:
  7866. if ( _pScriptErrList != NULL)
  7867. ClearScriptError();
  7868. hres = S_OK;
  7869. break;
  7870. case DOCHOST_NAVIGATION_ERROR:
  7871. hres = _HandleFailedNavigation(pvarargIn, pvarargOut );
  7872. break;
  7873. case DOCHOST_NOTE_ERROR_PAGE:
  7874. _fErrorPage = TRUE;
  7875. break;
  7876. case DOCHOST_CONTENTDISPOSITIONATTACH:
  7877. hres = _OnContentDisposition();
  7878. break;
  7879. case DOCHOST_RESETSEARCHINFO:
  7880. // Reset search info.
  7881. _bsc._SetSearchInfo(this, 0, FALSE, FALSE, FALSE);
  7882. break;
  7883. case DOCHOST_SENDINGREQUEST:
  7884. _OnSetProgressPos(0, PROGRESS_SENDING);
  7885. _fShowProgressCtl = TRUE;
  7886. _PlaceProgressBar(TRUE);
  7887. hres = S_OK;
  7888. break;
  7889. case DOCHOST_FINDINGRESOURCE:
  7890. _OnSetProgressPos(0, PROGRESS_FINDING);
  7891. _fShowProgressCtl = TRUE;
  7892. _PlaceProgressBar(TRUE);
  7893. hres = S_OK;
  7894. break;
  7895. // Allow the command ID to be passed down the Exec chain.
  7896. //
  7897. default:
  7898. *pfHandled = FALSE;
  7899. break;
  7900. }
  7901. return (S_FALSE == hres) ? S_OK : hres;
  7902. }
  7903. //+---------------------------------------------------------------------------
  7904. //
  7905. // Member : CDocObjectHost::_HandleShdocvwCmds
  7906. //
  7907. // Synopsis : Handles the CMD IDs for CGID_ShellDocView.
  7908. //
  7909. //+---------------------------------------------------------------------------
  7910. BOOL
  7911. CDocObjectHost::_HandleShdocvwCmds(DWORD nCmdID,
  7912. DWORD nCmdexecopt,
  7913. VARIANTARG * pvarargIn,
  7914. VARIANTARG * pvarargOut)
  7915. {
  7916. BOOL fHandled = TRUE;
  7917. switch(nCmdID)
  7918. {
  7919. case SHDVID_STARTPICSFORWINDOW:
  7920. _StartPicsForWindow(pvarargIn, pvarargOut);
  7921. break;
  7922. case SHDVID_CANCELPICSFORWINDOW:
  7923. _CancelPicsForWindow(pvarargIn);
  7924. break;
  7925. case SHDVID_ISPICSENABLED:
  7926. _IsPicsEnabled(pvarargOut);
  7927. break;
  7928. default:
  7929. fHandled = FALSE;
  7930. }
  7931. return fHandled;
  7932. }
  7933. //+-----------------------------------------------------------------------------
  7934. //
  7935. // Member : CDocObjectHost::_StartPicsForWindow
  7936. //
  7937. //+-----------------------------------------------------------------------------
  7938. void
  7939. CDocObjectHost::_StartPicsForWindow(VARIANTARG * pvarargIn, VARIANTARG * pvarargOut)
  7940. {
  7941. ASSERT(pvarargIn);
  7942. ASSERT(VT_UNKNOWN == V_VT(pvarargIn));
  7943. ASSERT(V_UNKNOWN(pvarargIn));
  7944. ASSERT(pvarargOut);
  7945. ASSERT(V_VT(pvarargOut) == VT_EMPTY);
  7946. IHTMLPrivateWindow * pPrivWin;
  7947. V_VT(pvarargOut) = VT_BOOL;
  7948. V_BOOL(pvarargOut) = VARIANT_FALSE;
  7949. if (SUCCEEDED(V_UNKNOWN(pvarargIn)->QueryInterface(IID_IHTMLPrivateWindow, (void**)&pPrivWin)))
  7950. {
  7951. // Ignore the HR
  7952. //
  7953. if (_StartSecondaryPicsProcessor(pPrivWin) == S_OK)
  7954. {
  7955. V_BOOL(pvarargOut) = VARIANT_TRUE;
  7956. }
  7957. pPrivWin->Release();
  7958. }
  7959. }
  7960. BOOL
  7961. CDocObjectHost::_IsInBrowserBand() const
  7962. {
  7963. if (_psp)
  7964. {
  7965. IShellBrowser * pShlBrowser;
  7966. HRESULT hr = _psp->QueryService(SID_SProxyBrowser,
  7967. IID_PPV_ARG(IShellBrowser, &pShlBrowser));
  7968. if (SUCCEEDED(hr))
  7969. {
  7970. pShlBrowser->Release();
  7971. return TRUE;
  7972. }
  7973. }
  7974. return FALSE;
  7975. }
  7976. //+-----------------------------------------------------------------------------
  7977. //
  7978. // Member : CDocObjectHost::_CancelPicsForWindow
  7979. //
  7980. //+-----------------------------------------------------------------------------
  7981. void
  7982. CDocObjectHost::_CancelPicsForWindow(VARIANTARG * pvarargIn)
  7983. {
  7984. ASSERT(pvarargIn);
  7985. ASSERT(VT_UNKNOWN == V_VT(pvarargIn));
  7986. ASSERT(V_UNKNOWN(pvarargIn));
  7987. IUnknown * pUnkPrivWin;
  7988. if (SUCCEEDED(V_UNKNOWN(pvarargIn)->QueryInterface(IID_IUnknown, (void**)&pUnkPrivWin)))
  7989. {
  7990. _RemovePicsProcessorByPrivWindowUnk(pUnkPrivWin);
  7991. pUnkPrivWin->Release();
  7992. }
  7993. }
  7994. //+-----------------------------------------------------------------------------
  7995. //
  7996. // Member : CDocObjectHost::_IsPicsEnabled
  7997. //
  7998. // Synopsis : Returns a variant that specifies whether or not PICS is enabled.
  7999. //
  8000. //+-----------------------------------------------------------------------------
  8001. void
  8002. CDocObjectHost::_IsPicsEnabled(VARIANTARG * pvarargOut)
  8003. {
  8004. ASSERT(pvarargOut);
  8005. ASSERT(VT_EMPTY == V_VT(pvarargOut));
  8006. V_VT(pvarargOut) = VT_BOOL;
  8007. V_BOOL(pvarargOut) = VARIANT_FALSE;
  8008. IRatingNotification* pRatingNotify;
  8009. HRESULT hres = QueryService(SID_SRatingNotification, IID_PPV_ARG(IRatingNotification, &pRatingNotify));
  8010. if (SUCCEEDED(hres))
  8011. {
  8012. V_BOOL(pvarargOut) = pRatingNotify->IsRatingsEnabled() ? VARIANT_FALSE : VARIANT_TRUE;
  8013. pRatingNotify->Release();
  8014. }
  8015. else
  8016. {
  8017. if (IS_RATINGS_ENABLED() && S_OK == ::RatingEnabledQuery())
  8018. {
  8019. V_BOOL(pvarargOut) = VARIANT_TRUE;
  8020. }
  8021. }
  8022. }
  8023. //+-----------------------------------------------------------------------------
  8024. //
  8025. // Member : CDocObjectHost::_UpdateState
  8026. //
  8027. // Synopsis : Updates the state of the dochost.
  8028. //
  8029. //+-----------------------------------------------------------------------------
  8030. HRESULT
  8031. CDocObjectHost::_UpdateState(LPITEMIDLIST pidl, BOOL fIsErrorUrl)
  8032. {
  8033. HRESULT hres;
  8034. if (_fSetSecureLock)
  8035. {
  8036. _ForwardSetSecureLock(_eSecureLock);
  8037. }
  8038. ASSERT(_pwb);
  8039. if (!fIsErrorUrl)
  8040. {
  8041. ResetRefreshUrl();
  8042. }
  8043. IMoniker * pmk;
  8044. BOOL fFileProtocol;
  8045. hres = ::_URLMONMonikerFromPidl(pidl, &pmk, &fFileProtocol);
  8046. if (S_OK == hres)
  8047. {
  8048. ATOMICRELEASE(_pmkCur);
  8049. _pmkCur = pmk;
  8050. DEBUG_CODE(_TraceMonikerDbg(_pmkCur, _T("CDocObjectHost::_UpdateState")));
  8051. }
  8052. _fFileProtocol = fFileProtocol;
  8053. // This is only set if we did a successful LoadHistory()
  8054. //
  8055. _fIsHistoricalObject = FALSE;
  8056. // This flag used to be set to false in IE5
  8057. // for each navigation because the dochost was
  8058. // destroyed and a new one was created. Now that Trident
  8059. // knows how to navigate, this flag doesn't get reset. This
  8060. // prevents activation of the view in the case where a
  8061. // modal dialog is being displayed.
  8062. //
  8063. _fReadystateInteractiveProcessed = FALSE;
  8064. return hres;
  8065. }
  8066. //+-----------------------------------------------------------------------------
  8067. //
  8068. // Member : CDocObjectHost::_Init
  8069. //
  8070. // Synopsis : Clears the cached redirection URL in case the previous navigation
  8071. // was a redirection. THis is needed so that further navigations to https://
  8072. // sites don't get the redirection URL as their SSL base.
  8073. //+-----------------------------------------------------------------------------
  8074. void
  8075. CDocObjectHost::_Init()
  8076. {
  8077. _fDelegatedNavigation = FALSE;
  8078. _fErrorPage = FALSE;
  8079. if (_bsc._pszRedirectedURL)
  8080. {
  8081. LocalFree(_bsc._pszRedirectedURL);
  8082. _bsc._pszRedirectedURL = NULL;
  8083. }
  8084. }
  8085. #ifdef DEBUG
  8086. void
  8087. CDocObjectHost::_TraceMonikerDbg(IMoniker * pmk, TCHAR * pszCaller) const
  8088. {
  8089. ASSERT(pmk);
  8090. LPOLESTR pstrDisplayName;
  8091. HRESULT hr = pmk->GetDisplayName(NULL, NULL, &pstrDisplayName);
  8092. if (S_OK == hr)
  8093. {
  8094. TraceMsg(DM_TRACE, "%ws - Moniker=\"%ws\"", pszCaller, pstrDisplayName);
  8095. OleFree(pstrDisplayName);
  8096. }
  8097. }
  8098. #endif
  8099. //+-------------------------------------------------------------------------
  8100. //
  8101. // Member : CDocObjectHost::_HandleFailedNavigation
  8102. //
  8103. // Synopsis : Handles a failed navigation by initiating
  8104. // the AutoSearch function or displaying an
  8105. // error page.
  8106. //
  8107. // Scenario : - The user navigates to a bogus URL such as "sdfg".
  8108. // - _HandleFailedNavigation is called via Exec with
  8109. // DOCHOST_NAVIGATION_ERROR.
  8110. // - The AutoSearch initiates with a search index of 0.
  8111. // - AutoSearch expands the URL with the first
  8112. // UrlTemplate from the registry (usually www.%s.com).
  8113. // - Navigation to the new URL is attempted.
  8114. // - Upon failure, this method is called again with
  8115. // an error code of HTTP_STATUS_BAD_GATEWAY or
  8116. // HTTP_STATUS_GATEWAY_TIMEOUT.
  8117. // - The search index in the property bag is incremented (by
  8118. // two if it is currently 0.)
  8119. // - AutoSearch then tries the next UrlTemplate, and so on.
  8120. //
  8121. // If this method is called with an error code other than
  8122. // HTTP_STATUS_BAD_GATEWAY, HTTP_STATUS_GATEWAY_TIMEOUT,
  8123. // INET_E_RESOURCE_NOT_FOUND, INET_E_DATA_NOT_AVAILABLE or
  8124. // if the error code is INET_E_RESOURCE_NOT_FOUND or
  8125. // INET_E_DATA_NOT_AVAILABLEthe and the URL entered by the
  8126. // user contains a protocol identifier (e.g., http://) an
  8127. // error page contained in shdoclc.dll is displayed.
  8128. //
  8129. // Input : pvarargIn - a SafeArray that contains the following
  8130. // data in this order.
  8131. // 0 - Binding error or HTTP status code. (VT_I4)
  8132. // 1 - URL being navigated to. (VT_BSTR)
  8133. // 2 - IBinding interface (VT_UNKNOWN)
  8134. // 3 - IHTMLWindow2 of the current window (VT_UNKNOWN)
  8135. //
  8136. //-------------------------------------------------------------------------
  8137. HRESULT
  8138. CDocObjectHost::_HandleFailedNavigation(VARIANTARG * pvarargIn, VARIANTARG* pvarargOut /*=NULL*/)
  8139. {
  8140. HRESULT hr = E_FAIL;
  8141. ASSERT(pvarargIn);
  8142. ASSERT(_fDocCanNavigate);
  8143. if (pvarargIn && VT_ARRAY == V_VT(pvarargIn) && V_ARRAY(pvarargIn))
  8144. {
  8145. // Get the error code from the SafeArray.
  8146. //
  8147. CComVariant cvarErrorCode;
  8148. CComVariant cvarAddrBarNav;
  8149. CComVariant cvarRefresh;
  8150. long lIdx = 0;
  8151. DWORD dwError = ERRORPAGE_DNS;
  8152. BOOL fShouldDisplayError = TRUE;
  8153. BOOL fDidSuperNavigate = TRUE;
  8154. //
  8155. // We use to use the window only in one place. To avoid QI several times
  8156. // We QI just before the first use, and keep track if we were successful.
  8157. //
  8158. CComVariant cvarWindow;
  8159. IHTMLWindow2 * pCurrentWindow = NULL;
  8160. HRESULT hrWinQI = E_FAIL;
  8161. hr = SafeArrayGetElement(V_ARRAY(pvarargIn), &lIdx, &cvarErrorCode);
  8162. if (SUCCEEDED(hr) && V_VT(&cvarErrorCode) == VT_I4)
  8163. {
  8164. lIdx = 4;
  8165. hr = SafeArrayGetElement(V_ARRAY(pvarargIn), &lIdx, &cvarAddrBarNav);
  8166. if (SUCCEEDED(hr) && V_VT(&cvarAddrBarNav) == VT_BOOL)
  8167. {
  8168. // We fire NavigateError and if the host wishes to cancel
  8169. // we can skip the rest of this method.
  8170. BOOL fCancelAutoSearch = FALSE;
  8171. DWORD dwStatusCode = V_I4(&cvarErrorCode);
  8172. CComVariant cvarWindow;
  8173. // Get the pending URL from the SafeArray.
  8174. //
  8175. CComVariant cvarUrl;
  8176. lIdx = 1;
  8177. hr = SafeArrayGetElement(V_ARRAY(pvarargIn), &lIdx, &cvarUrl);
  8178. if (SUCCEEDED(hr) && (VT_BSTR == V_VT(&cvarUrl)) && V_BSTR(&cvarUrl))
  8179. {
  8180. // Get the current window from the SafeArray.
  8181. //
  8182. lIdx = 3;
  8183. hr = SafeArrayGetElement(V_ARRAY(pvarargIn), &lIdx, &cvarWindow);
  8184. if (SUCCEEDED(hr) && V_VT(&cvarWindow) == VT_UNKNOWN && V_UNKNOWN(&cvarWindow))
  8185. {
  8186. hr = V_UNKNOWN(&cvarWindow)->QueryInterface(IID_IHTMLWindow2, (void**)&pCurrentWindow);
  8187. _FireNavigateErrorHelper(SUCCEEDED(hr) ? pCurrentWindow : NULL,
  8188. dwStatusCode,
  8189. &fCancelAutoSearch,
  8190. V_BSTR(&cvarUrl));
  8191. hrWinQI = hr;
  8192. }
  8193. }
  8194. if (fCancelAutoSearch)
  8195. {
  8196. if (!_fCanceledByBrowser)
  8197. {
  8198. _CancelPendingNavigation(FALSE, TRUE);
  8199. }
  8200. return hr;
  8201. }
  8202. lIdx = 0;
  8203. switch (V_I4(&cvarErrorCode))
  8204. {
  8205. case HTTP_STATUS_BAD_GATEWAY:
  8206. case HTTP_STATUS_GATEWAY_TIMEOUT:
  8207. if (VARIANT_TRUE == V_BOOL(&cvarAddrBarNav))
  8208. {
  8209. hr = _DoAutoSearch(pvarargIn,
  8210. ++lIdx,
  8211. V_I4(&cvarErrorCode),
  8212. FALSE,
  8213. &fShouldDisplayError);
  8214. if ( fShouldDisplayError )
  8215. {
  8216. fDidSuperNavigate = FALSE;
  8217. }
  8218. }
  8219. break;
  8220. // Only autosearch if the error code is
  8221. // INET_E_RESOURCE_NOT_FOUND or INET_E_DATA_NOT_AVAILABLE
  8222. //
  8223. case INET_E_RESOURCE_NOT_FOUND:
  8224. case INET_E_DATA_NOT_AVAILABLE:
  8225. if (VARIANT_TRUE == V_BOOL(&cvarAddrBarNav))
  8226. {
  8227. hr = _DoAutoSearch(pvarargIn,
  8228. ++lIdx,
  8229. 0,
  8230. TRUE,
  8231. &fShouldDisplayError);
  8232. // We must reset here so that the index will be
  8233. // correct the next time around.
  8234. //
  8235. }
  8236. // Intentional fall-through
  8237. case INET_E_DOWNLOAD_FAILURE:
  8238. if (IsGlobalOffline())
  8239. break;
  8240. // otherwise fall through to do default handling
  8241. default:
  8242. if (hr || fShouldDisplayError)
  8243. {
  8244. if ( V_I4(&cvarErrorCode) >= HTTP_STATUS_BAD_REQUEST
  8245. && V_I4(&cvarErrorCode) <= HTTP_STATUS_LAST)
  8246. {
  8247. dwError = V_I4(&cvarErrorCode);
  8248. }
  8249. // Get the pending URL from the SafeArray.
  8250. //
  8251. CComVariant cvarUrl;
  8252. lIdx = 1;
  8253. hr = SafeArrayGetElement(V_ARRAY(pvarargIn), &lIdx, &cvarUrl);
  8254. if (SUCCEEDED(hr) && V_VT(&cvarUrl) == VT_BSTR && V_BSTR(&cvarUrl))
  8255. {
  8256. if (SUCCEEDED(hrWinQI))
  8257. {
  8258. //
  8259. // Get the refresh flag - indicating whether this is a refresh.
  8260. // ( this was originally set when we called SuperNavigate )
  8261. //
  8262. lIdx = 5;
  8263. hr = SafeArrayGetElement(V_ARRAY(pvarargIn), &lIdx, &cvarRefresh);
  8264. if (SUCCEEDED(hr))
  8265. {
  8266. hr = _DisplayHttpErrorPage(pCurrentWindow,
  8267. V_BSTR(&cvarUrl),
  8268. dwError,
  8269. V_BOOL(&cvarAddrBarNav),
  8270. V_BOOL(&cvarRefresh ) );
  8271. ATOMICRELEASE(pCurrentWindow);
  8272. }
  8273. }
  8274. }
  8275. }
  8276. break;
  8277. } // switch
  8278. if ( pvarargOut && ( V_VT( pvarargOut ) == VT_BOOL ) )
  8279. {
  8280. V_BOOL( pvarargOut ) = fDidSuperNavigate ? VARIANT_TRUE : VARIANT_FALSE;
  8281. }
  8282. } // if (SUCCEEDED(hr) && V_VT(&cvarAddrBarNav) == VT_BOOL)
  8283. } // if (SUCCEEDED(hr) && V_VT(&cvarErrorCode) == VT_I4)
  8284. }
  8285. return (S_FALSE == hr ? S_OK : hr);
  8286. }
  8287. //+------------------------------------------------------------------
  8288. //
  8289. // Member : CDocObjectHost::_DoAutoSearch
  8290. //
  8291. // Synopsis : Performs the autosearch function.
  8292. //
  8293. // Input : pvarargIn - a SafeArray of arguments. See
  8294. // _HandleFailedNavigation for info about
  8295. // the format of pvarargIn.
  8296. // lStartIdx - the position in the SafeArray where
  8297. // the data begins.
  8298. // dwStatusCode - the HTTP status code.
  8299. //
  8300. // Output : pfShouldDisplayError - TRUE if an error page
  8301. // should be displayed.
  8302. //
  8303. //------------------------------------------------------------------
  8304. HRESULT
  8305. CDocObjectHost::_DoAutoSearch(VARIANTARG * pvarargIn,
  8306. long lStartIdx,
  8307. DWORD dwStatusCode,
  8308. BOOL fAddMRU,
  8309. BOOL * pfShouldDisplayError)
  8310. {
  8311. ASSERT(pvarargIn);
  8312. ASSERT(_fDocCanNavigate);
  8313. ASSERT(pfShouldDisplayError);
  8314. *pfShouldDisplayError = TRUE;
  8315. // Url
  8316. CComVariant cvarUrl;
  8317. HRESULT hr = SafeArrayGetElement(V_ARRAY(pvarargIn), &lStartIdx, &cvarUrl);
  8318. if (SUCCEEDED(hr) && V_VT(&cvarUrl) == VT_BSTR && V_BSTR(&cvarUrl))
  8319. {
  8320. CComVariant cvarBinding;
  8321. IBinding * pBinding;
  8322. // Binding interface pointer
  8323. lStartIdx++;
  8324. hr = SafeArrayGetElement(V_ARRAY(pvarargIn), &lStartIdx, &cvarBinding);
  8325. if (SUCCEEDED(hr) && V_VT(&cvarBinding) == VT_UNKNOWN && V_UNKNOWN(&cvarBinding))
  8326. {
  8327. hr = V_UNKNOWN(&cvarBinding)->QueryInterface(IID_IBinding, (void**)&pBinding);
  8328. if (SUCCEEDED(hr))
  8329. {
  8330. hr = _bsc._HandleFailedNavigationSearch(pfShouldDisplayError, dwStatusCode, this, 0, V_BSTR(&cvarUrl),
  8331. L"Resource Not Found", pBinding, fAddMRU, TRUE);
  8332. if (hr == S_FALSE)
  8333. _fErrorPage = TRUE; // Don't update the history if no auto-search
  8334. ATOMICRELEASE(pBinding);
  8335. }
  8336. }
  8337. }
  8338. return (S_FALSE == hr ? S_OK : hr);
  8339. }
  8340. //+---------------------------------------------------------------
  8341. //
  8342. // Member : CDocObjectHost::_DisplayHttpErrorPage
  8343. //
  8344. // Synopsis : Displays the HTML page that corresponds to
  8345. // the given error code.
  8346. //
  8347. // Input : pCurrentWindow - the window to use for navigation.
  8348. // dwError - the error code.
  8349. //
  8350. //---------------------------------------------------------------
  8351. HRESULT
  8352. CDocObjectHost::_DisplayHttpErrorPage(IHTMLWindow2 * pCurrentWindow,
  8353. BSTR bstrUrl,
  8354. DWORD dwError,
  8355. BOOL fAddrBarNav,
  8356. BOOL fRefresh /*=FALSE*/)
  8357. {
  8358. HRESULT hr = E_FAIL;
  8359. TCHAR szErrorUrl[MAX_URL_STRING];
  8360. const WCHAR * const pszFmt = L"#%s";
  8361. IHTMLPrivateWindow * pPrivWindow = NULL;
  8362. ASSERT(pCurrentWindow);
  8363. ASSERT(_fDocCanNavigate);
  8364. _bsc._DontAddToMRU(this);
  8365. if (IsErrorHandled(dwError))
  8366. {
  8367. _fErrorPage = TRUE;
  8368. if (_bsc._DisplayFriendlyHttpErrors())
  8369. {
  8370. hr = MLBuildResURLWrap(_T("shdoclc.dll"),
  8371. HINST_THISDLL,
  8372. ML_CROSSCODEPAGE,
  8373. (TCHAR*)c_aErrorUrls[EUIndexFromError(dwError)].pszUrl,
  8374. szErrorUrl,
  8375. ARRAYSIZE(szErrorUrl),
  8376. _T("shdocvw.dll"));
  8377. if (SUCCEEDED(hr))
  8378. {
  8379. LPOLESTR pwszLocation = OLE2W(bstrUrl);
  8380. if (!IsFrameWindow(pCurrentWindow))
  8381. {
  8382. // Save the url the user attempted to navigate to. It will be used
  8383. // to refresh the page.
  8384. //
  8385. OleFree(_pwszRefreshUrl);
  8386. hr = SHStrDupW(OLE2W(bstrUrl), &_pwszRefreshUrl);
  8387. }
  8388. if (SUCCEEDED(hr))
  8389. {
  8390. int nLenWritten = lstrlen(szErrorUrl);
  8391. // Append the #<refresh URL>
  8392. //
  8393. wnsprintf(szErrorUrl + nLenWritten,
  8394. ARRAYSIZE(szErrorUrl) - nLenWritten,
  8395. pszFmt,
  8396. pwszLocation ? pwszLocation : L"");
  8397. hr = pCurrentWindow->QueryInterface(IID_IHTMLPrivateWindow,
  8398. (void**)&pPrivWindow);
  8399. if (SUCCEEDED(hr))
  8400. {
  8401. // Navigate to the URL
  8402. //
  8403. BSTR bstrErrorUrl = SysAllocString(szErrorUrl);
  8404. DWORD dwFlags = (fAddrBarNav ?
  8405. DOCNAVFLAG_DONTUPDATETLOG | DOCNAVFLAG_HTTPERRORPAGE :
  8406. DOCNAVFLAG_HTTPERRORPAGE) ;
  8407. if ( fRefresh )
  8408. dwFlags |= DOCNAVFLAG_REFRESH;
  8409. if (bstrErrorUrl)
  8410. {
  8411. hr = pPrivWindow->SuperNavigate(bstrErrorUrl,
  8412. NULL,
  8413. NULL,
  8414. NULL,
  8415. NULL,
  8416. NULL,
  8417. dwFlags);
  8418. SysFreeString(bstrErrorUrl);
  8419. }
  8420. pPrivWindow->Release();
  8421. }
  8422. }
  8423. }
  8424. }
  8425. }
  8426. return hr;
  8427. }
  8428. HRESULT CDocObjectHost::_GetUrlVariant(VARIANT *pvarargOut)
  8429. {
  8430. ASSERT( pvarargOut);
  8431. if (_pmkCur)
  8432. {
  8433. LPOLESTR pszDisplayName = NULL;
  8434. LPTSTR pszRedirectedURL = NULL;
  8435. if (_bsc._pszRedirectedURL && *_bsc._pszRedirectedURL)
  8436. pszRedirectedURL = _bsc._pszRedirectedURL;
  8437. if (pszRedirectedURL || SUCCEEDED(_GetCurrentPageW(&pszDisplayName, TRUE)))
  8438. {
  8439. pvarargOut->bstrVal = SysAllocString(pszRedirectedURL ? pszRedirectedURL : pszDisplayName);
  8440. if (pvarargOut->bstrVal)
  8441. pvarargOut->vt = VT_BSTR;
  8442. if (pszDisplayName)
  8443. OleFree(pszDisplayName);
  8444. }
  8445. }
  8446. return (pvarargOut->bstrVal == NULL) ? E_FAIL : S_OK;
  8447. }
  8448. HRESULT CDocObjectHost::_CoCreateHTMLDocument(REFIID riid, void ** ppvOut)
  8449. {
  8450. IOleCommandTarget* pcmd;
  8451. HRESULT hres = QueryService(SID_STopLevelBrowser, IID_IOleCommandTarget, (void **)&pcmd);
  8452. if (SUCCEEDED(hres)) {
  8453. VARIANT varOut = { 0 };
  8454. hres = pcmd->Exec(&CGID_Explorer, SBCMDID_COCREATEDOCUMENT, 0, NULL, &varOut);
  8455. if (SUCCEEDED(hres) && varOut.vt == VT_UNKNOWN) {
  8456. hres = varOut.punkVal->QueryInterface(riid, ppvOut);
  8457. // Clean it up by ourself so that we don't load OLEAUT32
  8458. varOut.punkVal->Release();
  8459. } else {
  8460. ASSERT(varOut.vt == VT_EMPTY);
  8461. VariantClear(&varOut);
  8462. }
  8463. pcmd->Release();
  8464. }
  8465. return hres;
  8466. }
  8467. HRESULT CDocObjectHost::_CreatePendingDocObject(BOOL fMustInit, BOOL fWindowOpen /* = FALSE */)
  8468. {
  8469. HRESULT hres = S_OK;
  8470. if (_punkPending == NULL)
  8471. {
  8472. hres = _CoCreateHTMLDocument(IID_IUnknown, (void **)&_punkPending);
  8473. _fPendingNeedsInit = 1; // lazy InitNew only if absolutely necessary
  8474. if (fWindowOpen)
  8475. {
  8476. IUnknown_Exec(_punkPending, &CGID_ShellDocView, SHDVID_WINDOWOPEN, 0, NULL, NULL);
  8477. }
  8478. }
  8479. if (_fPendingNeedsInit && fMustInit && SUCCEEDED(hres))
  8480. {
  8481. IOleObject * polePending;
  8482. #ifdef TRIDENT_NEEDS_LOCKRUNNING
  8483. IRunnableObject * pro;
  8484. #endif
  8485. _fCreatingPending = 1; // we are creating _punkPending
  8486. _fAbortCreatePending = 0;
  8487. _fPendingNeedsInit = 0;
  8488. IPersistStreamInit * pipsi;
  8489. hres = _punkPending->QueryInterface(IID_IPersistStreamInit, (void**)&pipsi);
  8490. if (SUCCEEDED(hres))
  8491. {
  8492. hres = pipsi->InitNew();
  8493. pipsi->Release();
  8494. }
  8495. // if the InitNew is a re-entrant request (such as doing execDown to get a securityctx
  8496. // while in the process of loading the document), trident will respond with E_PENDING
  8497. // since there is already a load in progress, this call/init is a timing issue, and
  8498. // we can use the exisitng one.
  8499. //
  8500. if (SUCCEEDED(hres) || hres==E_PENDING)
  8501. {
  8502. hres = _punkPending->QueryInterface(IID_IOleObject, (void**)&polePending);
  8503. if (SUCCEEDED(hres))
  8504. {
  8505. hres = polePending->SetClientSite(this);
  8506. polePending->Release();
  8507. }
  8508. #ifdef TRIDENT_NEEDS_LOCKRUNNING
  8509. // TRIDENT NO LONGER SUPPORTS IRunnableObject
  8510. // RegisterObjectParam/RevokeObjectParam calls LockRunning on object being
  8511. // registered. LockRunning(FALSE,FALSE) implied in the Revoke will result
  8512. // in OleClose being called on _punkPending if we haven't activated it
  8513. // by end of binding. Thus we must call LockRunning ourself
  8514. if (SUCCEEDED(hres))
  8515. {
  8516. hres = _punkPending->QueryInterface(IID_IRunnableObject, (void**)&pro);
  8517. if (SUCCEEDED(hres))
  8518. {
  8519. hres = pro->LockRunning(TRUE, TRUE);
  8520. pro->Release();
  8521. }
  8522. }
  8523. #endif
  8524. }
  8525. _fCreatingPending = 0;
  8526. _fPendingWasInited = 1;
  8527. if (FAILED(hres))
  8528. {
  8529. SAFERELEASE(_punkPending);
  8530. }
  8531. else if (_fAbortCreatePending)
  8532. {
  8533. // Detect AOL pumping messages and reentering and attempting to release
  8534. // _punkPending
  8535. _fAbortCreatePending = 0;
  8536. _ReleasePendingObject();
  8537. hres = E_FAIL;
  8538. }
  8539. else
  8540. {
  8541. // Pass URL for pending object to it in advance of IPersistMoniker::Load
  8542. //
  8543. // Notes: We don't want to call _GetUrlVariant which will load
  8544. // OLEAUT32.DLL
  8545. //
  8546. LPOLESTR pszDisplayName = NULL;
  8547. LPTSTR pszURL = NULL;
  8548. if (_bsc._pszRedirectedURL && *_bsc._pszRedirectedURL)
  8549. pszURL = _bsc._pszRedirectedURL;
  8550. if (pszURL || SUCCEEDED(_GetCurrentPageW(&pszDisplayName, TRUE)))
  8551. {
  8552. LBSTR::CString strDisplay;
  8553. strDisplay = ( pszURL ? pszURL : pszDisplayName );
  8554. VARIANT varIn;
  8555. varIn.vt = VT_BSTR;
  8556. varIn.bstrVal = strDisplay;
  8557. IUnknown_Exec(_punkPending, &CGID_ShellDocView, SHDVID_SETPENDINGURL, 0, &varIn, NULL);
  8558. if (pszDisplayName)
  8559. OleFree(pszDisplayName);
  8560. }
  8561. }
  8562. _fAbortCreatePending = 0;
  8563. }
  8564. return hres;
  8565. }
  8566. HRESULT
  8567. CDocObjectHost::_LoadDocument()
  8568. {
  8569. if (!_punkPending)
  8570. return E_FAIL;
  8571. IPersistMoniker * pPersistMk;
  8572. HRESULT hres = _punkPending->QueryInterface(IID_IPersistMoniker, (void**)&pPersistMk);
  8573. if (SUCCEEDED(hres))
  8574. {
  8575. ITridentService * pTridentSvc;
  8576. if ( _pwb )
  8577. {
  8578. hres = _pwb->QueryInterface(IID_ITridentService, (void**)&pTridentSvc);
  8579. }
  8580. else
  8581. {
  8582. TraceMsg( TF_ERROR, "CDocObjectHost::_LoadDocument() - _pwb is NULL!" );
  8583. hres = E_FAIL;
  8584. }
  8585. if (SUCCEEDED(hres))
  8586. {
  8587. BSTR bstrUrl;
  8588. hres = pTridentSvc->GetPendingUrl(&bstrUrl);
  8589. if (SUCCEEDED(hres))
  8590. {
  8591. IMoniker * pMoniker;
  8592. TCHAR *pstr;
  8593. // Parse the URL, removing any location info
  8594. pstr = wcsrchr(bstrUrl, '#');
  8595. if (pstr)
  8596. {
  8597. *pstr = '\0';
  8598. }
  8599. hres = CreateURLMoniker(NULL, bstrUrl, &pMoniker);
  8600. if (SUCCEEDED(hres))
  8601. {
  8602. ATOMICRELEASE(_pole);
  8603. hres = _punkPending->QueryInterface(IID_IOleObject, (void**)&_pole);
  8604. if (SUCCEEDED(hres))
  8605. {
  8606. _GetAppHack();
  8607. // Call _SetUpTransitionCapability() to set up the advisory sinks
  8608. // and set readystate to complete. If we don't do this here, the
  8609. // view will never be activated after the first navigation
  8610. // which means that the view will never switched and the
  8611. // new document will not be displayed. Also, setting readystate
  8612. // to complete here, is what prevents the window from being transparent
  8613. // when it is first opened.
  8614. //
  8615. _SetUpTransitionCapability(TRUE);
  8616. }
  8617. hres = pPersistMk->Load(TRUE, pMoniker, _pbcCur, 0);
  8618. pMoniker->Release();
  8619. }
  8620. SysFreeString(bstrUrl);
  8621. }
  8622. pTridentSvc->Release();
  8623. }
  8624. pPersistMk->Release();
  8625. }
  8626. return S_OK;
  8627. }
  8628. // called from CDocObjectView to exec and forward these calls down
  8629. //
  8630. HRESULT CDocObjectHost::ExecDown(const GUID *pguidCmdGroup, DWORD nCmdID, DWORD nCmdexecopt, VARIANTARG *pvarargIn, VARIANTARG *pvarargOut)
  8631. {
  8632. HRESULT hres = OLECMDERR_E_UNKNOWNGROUP;
  8633. // Special case Exec's that are used to fetch info on pending docobject
  8634. // for scripting access before OnObjectAvailable
  8635. if (pguidCmdGroup && IsEqualGUID(CGID_ShellDocView, *pguidCmdGroup))
  8636. {
  8637. switch(nCmdID)
  8638. {
  8639. case SHDVID_GETPENDINGOBJECT:
  8640. ASSERT( pvarargOut);
  8641. VariantClearLazy(pvarargOut);
  8642. if (_pole)
  8643. {
  8644. _pole->QueryInterface(IID_IUnknown, (void **) &(pvarargOut->punkVal));
  8645. // Check to see if this is a window.open case. If so,
  8646. // the document was created and Init'ed in SetTarget
  8647. // and the real Url will be loaded now.
  8648. //
  8649. if (_pbcCur)
  8650. {
  8651. IUnknown * punkBindCtxParam = NULL;
  8652. hres = _pbcCur->GetObjectParam(KEY_BINDCONTEXTPARAM, &punkBindCtxParam);
  8653. if (SUCCEEDED(hres))
  8654. {
  8655. punkBindCtxParam->Release();
  8656. _fWindowOpen = TRUE;
  8657. hres = _LoadDocument();
  8658. _ActivateMsoView();
  8659. }
  8660. }
  8661. }
  8662. else
  8663. {
  8664. _CreatePendingDocObject(TRUE);
  8665. if (_punkPending)
  8666. {
  8667. pvarargOut->punkVal = _punkPending;
  8668. _punkPending->AddRef();
  8669. }
  8670. else if (_pole)
  8671. {
  8672. _pole->QueryInterface(IID_IUnknown, (void **) &(pvarargOut->punkVal));
  8673. }
  8674. }
  8675. if (pvarargOut->punkVal != NULL)
  8676. {
  8677. pvarargOut->vt = VT_UNKNOWN;
  8678. hres = S_OK;
  8679. }
  8680. else
  8681. {
  8682. hres = E_FAIL;
  8683. }
  8684. return hres;
  8685. break;
  8686. case SHDVID_GETPENDINGURL:
  8687. ASSERT( pvarargOut);
  8688. VariantClearLazy(pvarargOut);
  8689. hres = _GetUrlVariant(pvarargOut);
  8690. return hres;
  8691. break;
  8692. default:
  8693. break;
  8694. }
  8695. }
  8696. BOOL fNearest = _ExecNearest(pguidCmdGroup, nCmdID, TRUE);
  8697. if (fNearest)
  8698. hres = OnExec(pguidCmdGroup, nCmdID, nCmdexecopt, pvarargIn, pvarargOut);
  8699. if (FAILED(hres) && _pmsot) {
  8700. hres = _pmsot->Exec(pguidCmdGroup, nCmdID, nCmdexecopt, pvarargIn, pvarargOut);
  8701. //
  8702. // APPHACK:
  8703. // PPT in Office 97 fails to print if we pass PRINTFLAG_PROMPTUSER
  8704. // and returns E_INVALIDARG. If we detect this case, we should retry
  8705. // without this flag. PPT will popup the print dialog. (SatoNa)
  8706. //
  8707. if (hres == E_INVALIDARG
  8708. && (_dwAppHack & BROWSERFLAG_PRINTPROMPTUI)
  8709. && pguidCmdGroup == NULL
  8710. && nCmdID == OLECMDID_PRINT)
  8711. {
  8712. TraceMsg(TF_SHDAPPHACK, "DOH::ExecDown(OLECMDID_PRINT) removing PRINTFLAG_PROMPTUSER");
  8713. nCmdexecopt &= ~OLECMDEXECOPT_DONTPROMPTUSER;
  8714. hres = _pmsot->Exec(pguidCmdGroup, nCmdID, nCmdexecopt, pvarargIn, pvarargOut);
  8715. }
  8716. }
  8717. if (FAILED(hres) && !fNearest)
  8718. hres = OnExec(pguidCmdGroup, nCmdID, nCmdexecopt, pvarargIn, pvarargOut);
  8719. return hres;
  8720. }
  8721. HRESULT CDocObjectHost::QueryStatusDown(const GUID *pguidCmdGroup, ULONG cCmds, OLECMD rgCmds[], OLECMDTEXT *pcmdtext)
  8722. {
  8723. HRESULT hres;
  8724. if (_pmsot)
  8725. hres = _pmsot->QueryStatus(pguidCmdGroup, cCmds, rgCmds, pcmdtext);
  8726. else if (pguidCmdGroup && IsEqualGUID(CGID_ShellDocView, *pguidCmdGroup))
  8727. hres = IUnknown_QueryStatus(_pole, pguidCmdGroup, cCmds, rgCmds, pcmdtext);
  8728. return OnQueryStatus(pguidCmdGroup, cCmds, rgCmds, pcmdtext, hres);
  8729. }
  8730. HRESULT CDocObjectHost::Invoke(DISPID dispidMember, REFIID iid, LCID lcid, WORD wFlags, DISPPARAMS FAR* pdispparams,
  8731. VARIANT FAR* pVarResult,EXCEPINFO FAR* pexcepinfo,UINT FAR* puArgErr)
  8732. {
  8733. if (!_peds)
  8734. return(E_NOTIMPL);
  8735. return _peds->OnInvoke(dispidMember, iid, lcid, wFlags, pdispparams, pVarResult,pexcepinfo,puArgErr);
  8736. }
  8737. //*** IOleControlSite {
  8738. HRESULT CDocObjectHost::OnControlInfoChanged()
  8739. {
  8740. HRESULT hres = E_NOTIMPL;
  8741. if (_pedsHelper)
  8742. {
  8743. hres = _pedsHelper->OnOnControlInfoChanged();
  8744. }
  8745. return(hres);
  8746. }
  8747. //*** CDOH::TranslateAccelerator (IOCS::TranslateAccelerator)
  8748. // NOTES
  8749. // trident (or any other DO that uses IOCS::TA) calls us back when TABing
  8750. // off the last link. to handle it, we flag it for our original caller
  8751. // (IOIPAO::TA), and then pretend we handled it by telling trident S_OK.
  8752. // trident returns S_OK to IOIPAO::TA, which checks the flag and says
  8753. // 'trident did *not* handle it' by returning S_FALSE. that propagates
  8754. // way up to the top where it sees it was a TAB so it does a CycleFocus.
  8755. //
  8756. // that's how we do it when we're top-level. when we're a frameset, we
  8757. // need to do it the 'real' way, sending it up to our parent IOCS.
  8758. HRESULT CDocObjectHost::TranslateAccelerator(MSG __RPC_FAR *pmsg,DWORD grfModifiers)
  8759. {
  8760. HRESULT hres = S_FALSE;
  8761. if (_peds) {
  8762. // try it the real way in case we're in a frameset
  8763. // top level: we'll do CImpIExpDispSupport::OnTA which does E_NOTIMPL,
  8764. // frameset: we'll do CWebBrowserOC::OnTA which talks to trident
  8765. // What if trident (or OC?) gives back E_NOTIMPL too?
  8766. TraceMsg(DM_FOCUS, "DOH::IOCS::TA peds!=NULL forward");
  8767. hres = _peds->OnTranslateAccelerator(pmsg, grfModifiers);
  8768. }
  8769. if (hres != S_OK) {
  8770. // we're at top level (E_NOTIMPL), so we can fake it
  8771. // (or alternately we're not, but our parent said S_FALSE)
  8772. #ifdef DEBUG
  8773. if (_peds && SUCCEEDED(hres)) {
  8774. // i'm curious if we ever hit this
  8775. TraceMsg(DM_WARNING, "DOH::IOCS::TA parent hres=%x (!=S_OK)", hres);
  8776. }
  8777. #endif
  8778. hres = S_FALSE;
  8779. if (IsVK_TABCycler(pmsg)) {
  8780. TraceMsg(TF_SHDUIACTIVATE, "DOH::TranslateAccelerator called with VK_TAB");
  8781. TraceMsg(DM_FOCUS, "DOH::IOCS::TA(wParam=VK_TAB) ret _fCycleFocus=TRUE hr=S_OK (lie)");
  8782. // defer it, set flag for CDOH::IOIPAO::TA, and pretend we handled it
  8783. ASSERT(!_fCycleFocus);
  8784. _fCycleFocus = TRUE;
  8785. hres = S_OK;
  8786. }
  8787. }
  8788. return hres;
  8789. }
  8790. // }
  8791. //========================================================================
  8792. // CDocObjectHost::CPicsProcessor
  8793. //========================================================================
  8794. CDocObjectHost::CPicsProcessor::CPicsProcessor()
  8795. {
  8796. _fPicsAccessAllowed = TRUE; /* assume no ratings checks unless we download */
  8797. _fInDialog = FALSE;
  8798. _fTerminated = FALSE;
  8799. _fbPicsWaitFlags = 0;
  8800. }
  8801. STDMETHODIMP CDocObjectHost::CPicsProcessor::QueryInterface(REFIID riid, void ** ppvObj)
  8802. {
  8803. if (IsEqualIID(riid, IID_IOleCommandTarget) ||
  8804. IsEqualIID(riid, IID_IUnknown))
  8805. {
  8806. *ppvObj = SAFECAST(this, IOleCommandTarget *);
  8807. }
  8808. else
  8809. {
  8810. *ppvObj = NULL;
  8811. return E_NOINTERFACE;
  8812. }
  8813. CDocObjectHost* pdoh = _pdoh;
  8814. return pdoh->AddRef();
  8815. }
  8816. STDMETHODIMP_(ULONG) CDocObjectHost::CPicsProcessor::AddRef(void)
  8817. {
  8818. return _pdoh->AddRef();
  8819. }
  8820. STDMETHODIMP_(ULONG) CDocObjectHost::CPicsProcessor::Release(void)
  8821. {
  8822. return _pdoh->Release();
  8823. }
  8824. STDMETHODIMP CDocObjectHost::CPicsProcessor::QueryStatus(const GUID *pguidCmdGroup,
  8825. ULONG cCmds, OLECMD rgCmds[], OLECMDTEXT *pcmdtext)
  8826. {
  8827. return E_NOTIMPL;
  8828. }
  8829. STDMETHODIMP CDocObjectHost::CPicsProcessor::Exec(const GUID *pguidCmdGroup,
  8830. DWORD nCmdID, DWORD nCmdexecopt, VARIANTARG *pvarargIn, VARIANTARG *pvarargOut)
  8831. {
  8832. if (IsEqualGUID(CGID_ShellDocView, *pguidCmdGroup))
  8833. {
  8834. switch (nCmdID)
  8835. {
  8836. case SHDVID_PICSLABELFOUND:
  8837. if (pvarargIn->vt == (VT_BSTR)) {
  8838. _dwPicsLabelSource = PICS_LABEL_FROM_PAGE;
  8839. _HandleInDocumentLabel(pvarargIn->bstrVal);
  8840. }
  8841. return NOERROR;
  8842. case SHDVID_PICSLABELFOUNDINHTTPHEADER:
  8843. if (pvarargIn->vt == (VT_BSTR)) {
  8844. _dwPicsLabelSource = PICS_LABEL_FROM_HEADER;
  8845. _HandleInDocumentLabel(pvarargIn->bstrVal);
  8846. }
  8847. return NOERROR;
  8848. case SHDVID_NOMOREPICSLABELS:
  8849. _HandleDocumentEnd();
  8850. return NOERROR;
  8851. default:
  8852. return OLECMDERR_E_NOTSUPPORTED;
  8853. }
  8854. }
  8855. return OLECMDERR_E_UNKNOWNGROUP;
  8856. }
  8857. UINT CDocObjectHost::CPicsProcessor::_PicsBlockingDialog()
  8858. {
  8859. LPCTSTR pszURL = _pszPicsURL;
  8860. TraceMsg(DM_PICS, "CDOH::CPP::_PicsBlockingDialog() %s", pszURL);
  8861. _StartPicsRootQuery(pszURL);
  8862. _pdoh->_fDrawBackground = TRUE;
  8863. ::InvalidateRect(_pdoh->_hwnd, NULL, TRUE); /* mega cheesy, but only way to get browser window erased */
  8864. /* This message loop is used to block in non-HTML cases, where we really
  8865. * want to block the download process until ratings are checked. In the
  8866. * HTML case, this function is never called until the wait flags are all
  8867. * clear, so the message loop is skipped and we go straight to the denial
  8868. * dialog.
  8869. */
  8870. while (_fbPicsWaitFlags) {
  8871. TraceMsg(DM_PICS, "CDOH::CPP::_PicsBlockingDialog entering msg loop, waitflags=%x", (DWORD)_fbPicsWaitFlags);
  8872. MSG msg;
  8873. if (GetMessage(&msg, NULL, 0, 0)) {
  8874. TranslateMessage(&msg);
  8875. DispatchMessage(&msg);
  8876. }
  8877. }
  8878. if (!_fPicsAccessAllowed) {
  8879. TraceMsg(DM_PICS, "CDOH::CPP::_PicsBlockingDialog, access denied");
  8880. BOOL fOldInDialog;
  8881. // If this is silent-mode (no UI == screensaver), always deny access
  8882. // without any dialog.
  8883. BOOL fFrameIsSilent = FALSE; // Assume non-silent
  8884. _pdoh->_GetOfflineSilent(NULL, &fFrameIsSilent);
  8885. if (fFrameIsSilent) {
  8886. TraceMsg(DM_PICS, "CDOH::CPP::_PicsBlockingDialog access denied in silent mode, aborting");
  8887. return IDCANCEL;
  8888. }
  8889. // Protect against us getting whacked out
  8890. // from under ourselves
  8891. fOldInDialog = _fInDialog;
  8892. _fInDialog = TRUE;
  8893. // This doesn't get down to trident to stop it from navigating.
  8894. // We need some sort of navigation freeze mechanism.
  8895. _pdoh->_EnableModeless(FALSE);
  8896. HRESULT hres = S_OK;
  8897. IOleCommandTarget *pcmdtTop;
  8898. if (SUCCEEDED(_pdoh->QueryService(SID_STopLevelBrowser, IID_IOleCommandTarget, (void **)&pcmdtTop))) {
  8899. VARIANTARG v = { 0 };
  8900. v.vt = VT_INT_PTR;
  8901. v.byref = _pRatingDetails;
  8902. hres = pcmdtTop->Exec(&CGID_ShellDocView, SHDVID_PICSBLOCKINGUI, 0, &v, NULL);
  8903. pcmdtTop->Release();
  8904. }
  8905. UINT uRet = (hres == S_OK) ? IDOK : IDCANCEL;
  8906. _pdoh->_EnableModeless(TRUE);
  8907. _fPicsAccessAllowed = (uRet == IDOK);
  8908. _fInDialog = fOldInDialog;
  8909. TraceMsg(DM_PICS, "CDOH::CPP::_PicsBlockingDialog returning %d", uRet);
  8910. return uRet;
  8911. }
  8912. else {
  8913. TraceMsg(DM_PICS, "CDOH::CPP::_PicsBlockingDialog, access allowed");
  8914. return IDOK;
  8915. }
  8916. }
  8917. HRESULT CDocObjectHost::CPicsProcessor::_StartPicsQuery(LPCOLESTR pwszRawURL)
  8918. {
  8919. #ifdef DEBUG
  8920. HRESULT hres;
  8921. IRatingNotification* pRatingNotify;
  8922. hres = _pdoh->QueryService(SID_SRatingNotification, IID_PPV_ARG(IRatingNotification, &pRatingNotify));
  8923. if (SUCCEEDED(hres))
  8924. {
  8925. ASSERT(S_OK == pRatingNotify->IsRatingsEnabled());
  8926. pRatingNotify->Release();
  8927. }
  8928. else
  8929. {
  8930. ASSERT(IS_RATINGS_ENABLED() && ::RatingEnabledQuery() == S_OK);
  8931. }
  8932. #endif DEBUG
  8933. TraceMsg(DM_PICS, "CDOH::CPP::_StartPicsQuery entered with ratings enabled");
  8934. BOOL fEnforce = TRUE;
  8935. if (_pszPicsURL != NULL) {
  8936. delete _pszPicsURL;
  8937. _pszPicsURL = NULL;
  8938. }
  8939. {
  8940. /* We have to call CoInternetGetSecurityUrl to convert pluggable
  8941. * protocols into known schemes, so we know whether we need to
  8942. * enforce ratings on them.
  8943. */
  8944. LPOLESTR pwszSecurityURL = NULL;
  8945. if (SUCCEEDED(CoInternetGetSecurityUrl(pwszRawURL, &pwszSecurityURL,
  8946. PSU_SECURITY_URL_ONLY, 0)))
  8947. {
  8948. // List of protocols for which we never enforce ratings.
  8949. if (!StrCmpNIW(pwszSecurityURL, L"file:", 5) ||
  8950. !StrCmpNIW(pwszSecurityURL, L"about:", 6) ||
  8951. !StrCmpNIW(pwszSecurityURL, L"mk:", 3)) {
  8952. fEnforce = FALSE;
  8953. }
  8954. else {
  8955. Str_SetPtr(&_pszPicsURL, pwszSecurityURL);
  8956. }
  8957. OleFree(pwszSecurityURL);
  8958. }
  8959. }
  8960. if (fEnforce) {
  8961. TraceMsg(DM_PICS, "CDOH::CPP::_StartPicsQuery (%s) turning on wait flags", _pszPicsURL);
  8962. _fbPicsWaitFlags = PICS_WAIT_FOR_ASYNC
  8963. | PICS_WAIT_FOR_INDOC
  8964. | PICS_WAIT_FOR_END
  8965. | PICS_WAIT_FOR_ROOT
  8966. ;
  8967. _fPicsAccessAllowed = 0;
  8968. HRESULT hr;
  8969. _dwPicsSerialNumber = ::_AddPicsQuery(_pdoh->_hwnd);
  8970. if (_dwPicsSerialNumber == 0)
  8971. hr = E_OUTOFMEMORY;
  8972. else
  8973. {
  8974. //
  8975. // The ratings apis are ansi.
  8976. //
  8977. CHAR szURL[MAX_URL_STRING];
  8978. SHUnicodeToAnsi(_pszPicsURL, szURL, ARRAYSIZE(szURL));
  8979. hr = RatingObtainQuery(szURL, _dwPicsSerialNumber, RatingObtainQueryCallback, &_hPicsQuery);
  8980. }
  8981. if (FAILED(hr)) {
  8982. TraceMsg(DM_PICS, "CDOH::CPP::_StartPicsQuery no async query queued");
  8983. ::_RemovePicsQuery(_dwPicsSerialNumber);
  8984. _dwPicsSerialNumber = 0;
  8985. _fbPicsWaitFlags &= ~PICS_WAIT_FOR_ASYNC;
  8986. }
  8987. else {
  8988. TraceMsg(DM_PICS, "CDOH::CPP::_StartPicsQuery async query queued");
  8989. }
  8990. }
  8991. else {
  8992. // JHarding: IF we're not enforcing, we need to tell anyone who's waiting on an answer.
  8993. return S_FALSE;
  8994. }
  8995. return S_OK;
  8996. }
  8997. void CDocObjectHost::CPicsProcessor::_HandleDocumentEnd(void)
  8998. {
  8999. BYTE bFlag = (_pRootDownload != NULL) ? PICS_WAIT_FOR_ROOT : PICS_WAIT_FOR_END;
  9000. TraceMsg(DM_PICS, "CDOH::CPP::_HandleDocumentEnd -- no more PICS labels from source %x", (DWORD)bFlag);
  9001. // If we have a private window, we'll make sure the root download is gone when we
  9002. // notify the window. This simplifies the lifetime of the secondary CPicsProcessors
  9003. if (!_pPrivWindow)
  9004. {
  9005. if (_pRootDownload != NULL) {
  9006. ::PostMessage(_pdoh->_hwnd, WM_PICS_ROOTDOWNLOADCOMPLETE, 0, 0);
  9007. }
  9008. else {
  9009. /* End of document; revoke the IOleCommandTarget we gave to the document,
  9010. * so it won't send us any more notifications.
  9011. */
  9012. VARIANTARG v;
  9013. v.vt = VT_UNKNOWN;
  9014. v.punkVal = NULL;
  9015. IUnknown_Exec(_pdoh->_pole, &CGID_ShellDocView, SHDVID_CANSUPPORTPICS, 0, &v, NULL);
  9016. }
  9017. }
  9018. else
  9019. {
  9020. if (_pRootDownload == NULL)
  9021. {
  9022. _pPrivWindow->SetPICSTarget(NULL);
  9023. }
  9024. }
  9025. if (!(_fbPicsWaitFlags & bFlag)) {
  9026. TraceMsg(DM_PICS, "CDOH::CPP::_HandleDocumentEnd skipping due to waitflags %x", (DWORD)_fbPicsWaitFlags);
  9027. return;
  9028. }
  9029. _fbPicsWaitFlags &= ~PICS_WAIT_FOR_INDOC; /* we know we won't get any more indoc labels */
  9030. LPVOID pDetails = NULL;
  9031. //
  9032. // Ratings has only ansi apis!
  9033. //
  9034. CHAR szURL[MAX_URL_STRING];
  9035. SHUnicodeToAnsi(_pszPicsURL, szURL, ARRAYSIZE(szURL));
  9036. HRESULT hres = ::RatingCheckUserAccess(NULL, szURL, NULL, NULL, _dwPicsLabelSource, &pDetails);
  9037. _GotLabel(hres, pDetails, bFlag);
  9038. if (_pRootDownload == NULL) {
  9039. if (_fbPicsWaitFlags)
  9040. _StartPicsRootQuery(_pszPicsURL);
  9041. }
  9042. }
  9043. void CDocObjectHost::CPicsProcessor::_GotLabel(HRESULT hres, LPVOID pDetails, BYTE bfSource)
  9044. {
  9045. TraceMsg(DM_PICS, "CDOH::CPP::_GotLabel hres=%x, source=%x, waitflags=%x", hres, (DWORD)bfSource, (DWORD)_fbPicsWaitFlags);
  9046. /* If we've already gotten a result from this or a more significant source,
  9047. * ignore this one.
  9048. */
  9049. if (!(_fbPicsWaitFlags & bfSource)) {
  9050. TraceMsg(DM_PICS, "CDOH::CPP::_GotLabel already got label from that source");
  9051. if (pDetails != NULL)
  9052. {
  9053. ::RatingFreeDetails(pDetails);
  9054. pDetails = NULL;
  9055. }
  9056. }
  9057. else {
  9058. /* If the result is an error somehow (label doesn't apply, etc.), and
  9059. * we can expect more labels from this source, then we don't do anything
  9060. * except save the rating details if we haven't got any yet.
  9061. */
  9062. if (FAILED(hres) && (PICS_MULTIPLE_FLAGS & bfSource)) {
  9063. TraceMsg(DM_PICS, "CDOH::CPP::_GotLabel label error and may be multiple");
  9064. if (_pRatingDetails == NULL)
  9065. {
  9066. _pRatingDetails = pDetails;
  9067. }
  9068. else
  9069. {
  9070. if ( pDetails )
  9071. {
  9072. ::RatingFreeDetails(pDetails);
  9073. pDetails = NULL;
  9074. }
  9075. }
  9076. }
  9077. else {
  9078. /* Either we got a definitive answer from this rating source, or
  9079. * this is the only answer we'll get from it. We clear at least
  9080. * the flag for this source so we know we've heard from it. If
  9081. * the response was not an error, then clear flags for all less
  9082. * significant sources as well, so that we'll ignore them. On
  9083. * the other hand, if this source returned an error, it didn't
  9084. * give us anything useful, so we keep looking at other sources.
  9085. */
  9086. if (SUCCEEDED(hres))
  9087. _fbPicsWaitFlags &= bfSource - 1;
  9088. else
  9089. _fbPicsWaitFlags &= ~bfSource;
  9090. TraceMsg(DM_PICS, "CDOH::CPP::_GotLabel, waitflags now %x", (DWORD)_fbPicsWaitFlags);
  9091. if (hres == S_OK) {
  9092. TraceMsg(DM_PICS, "CDOH::CPP::_GotLabel allowing access");
  9093. if ( pDetails )
  9094. {
  9095. ::RatingFreeDetails( pDetails ); /* don't need this if access allowed */
  9096. pDetails = NULL;
  9097. }
  9098. _fPicsAccessAllowed = 1;
  9099. }
  9100. else {
  9101. /* Access denied or error. Meaningful details from this result
  9102. * can override details from an earlier, less significant
  9103. * result. Only explicitly deny access if not an error,
  9104. * though (this handles the valid root label followed by
  9105. * invalid in-document label, for example).
  9106. */
  9107. if (pDetails != NULL) {
  9108. if (_pRatingDetails != NULL)
  9109. {
  9110. ::RatingFreeDetails(_pRatingDetails);
  9111. }
  9112. _pRatingDetails = pDetails;
  9113. }
  9114. if (SUCCEEDED(hres))
  9115. _fPicsAccessAllowed = 0;
  9116. }
  9117. }
  9118. }
  9119. // If we are a secondary processor (_pPrivWindow != NULL) then
  9120. // we always want to report when the check is complete
  9121. //
  9122. if ((_pPrivWindow || _pdoh->_fPicsBlockLate) && !_fbPicsWaitFlags)
  9123. {
  9124. _HandlePicsChecksComplete();
  9125. }
  9126. }
  9127. void CDocObjectHost::CPicsProcessor::_HandleInDocumentLabel(LPCTSTR pszLabel)
  9128. {
  9129. BYTE bFlag = (_pRootDownload != NULL) ? PICS_WAIT_FOR_ROOT : PICS_WAIT_FOR_INDOC;
  9130. TraceMsg(DM_PICS, "CDOH::CPP::_HandleInDocumentLabel source %x gave label %s", (DWORD)bFlag, pszLabel);
  9131. if (!(_fbPicsWaitFlags & bFlag)) {
  9132. TraceMsg(DM_PICS, "CDOH::CPP::_HandleInDocumentLabel rejecting based on waitflags %x", (DWORD)_fbPicsWaitFlags);
  9133. return;
  9134. }
  9135. LPVOID pDetails = NULL;
  9136. //
  9137. // Ratings has only ansi apis!
  9138. //
  9139. CHAR szURL[MAX_URL_STRING];
  9140. SHUnicodeToAnsi(_pszPicsURL, szURL, ARRAYSIZE(szURL));
  9141. UINT cbMultiByte = WideCharToMultiByte(CP_ACP, 0, pszLabel,
  9142. -1, NULL, 0, NULL, NULL);
  9143. if (cbMultiByte > 0) {
  9144. char *pszLabelAnsi = new char[cbMultiByte+1];
  9145. if (pszLabelAnsi != NULL)
  9146. {
  9147. if (WideCharToMultiByte(CP_ACP, 0, pszLabel, -1, pszLabelAnsi,
  9148. cbMultiByte+1, NULL, NULL))
  9149. {
  9150. HRESULT hres = ::RatingCheckUserAccess(NULL, szURL,
  9151. pszLabelAnsi, NULL, _dwPicsLabelSource,
  9152. &pDetails);
  9153. _GotLabel(hres, pDetails, bFlag);
  9154. }
  9155. delete [] pszLabelAnsi;
  9156. }
  9157. }
  9158. }
  9159. /* This function parses the URL being downloaded and, if the URL doesn't
  9160. * already refer to the root document of the site, sets up a subordinate
  9161. * CDocObjectHost to download that root document, so we can get ratings
  9162. * out of it.
  9163. */
  9164. void CDocObjectHost::CPicsProcessor::_StartPicsRootQuery(LPCTSTR pszURL)
  9165. {
  9166. if (_fbPicsWaitFlags & PICS_WAIT_FOR_ROOT) {
  9167. BOOL fQueued = FALSE;
  9168. TraceMsg(DM_PICS, "CDOH::CPP::_StartPicsRootQuery parsing %s", pszURL);
  9169. WCHAR wszRootURL[MAX_URL_STRING+1];
  9170. DWORD cchResult;
  9171. /* The pszURL we're passed is actually the result of calling
  9172. * CoInternetGetSecurityUrl, and so may not be the scheme that
  9173. * the caller is browsing to. To support pluggable protocols
  9174. * determining the root location themselves, we first use the
  9175. * URL reported by _GetCurrentPage, which may refer to a
  9176. * pluggable protocol; if that fails, we use the more standard
  9177. * URL.
  9178. */
  9179. HRESULT hres = INET_E_DEFAULT_ACTION;
  9180. LPOLESTR pwszURL = NULL;
  9181. if (SUCCEEDED(_pdoh->_GetCurrentPageW(&pwszURL, TRUE)))
  9182. {
  9183. hres = CoInternetParseUrl(pwszURL, PARSE_ROOTDOCUMENT, 0, wszRootURL,
  9184. ARRAYSIZE(wszRootURL), &cchResult, 0);
  9185. OleFree(pwszURL);
  9186. }
  9187. if (pszURL != NULL && (hres == INET_E_DEFAULT_ACTION || hres == E_FAIL)) {
  9188. /* Pluggable protocol doesn't support PARSE_ROOTDOCUMENT. Use the
  9189. * more standard URL we were supplied with.
  9190. */
  9191. hres = CoInternetParseUrl(pszURL, PARSE_ROOTDOCUMENT, 0, wszRootURL,
  9192. ARRAYSIZE(wszRootURL), &cchResult, 0);
  9193. }
  9194. if (SUCCEEDED(hres)) {
  9195. IMoniker *pmk = NULL;
  9196. hres = MonikerFromURL(wszRootURL, &pmk);
  9197. if (SUCCEEDED(hres)) {
  9198. BOOL fFrameIsSilent = FALSE;
  9199. BOOL fFrameIsOffline = FALSE;
  9200. _pdoh->_GetOfflineSilent(&fFrameIsOffline, &fFrameIsSilent);
  9201. _pRootDownload = new CPicsRootDownload(this, fFrameIsOffline, fFrameIsSilent);
  9202. if (_pRootDownload != NULL) {
  9203. TraceMsg(DM_PICS, "CDOH::CPP::_StartPicsRootQuery starting download");
  9204. hres = _pRootDownload->StartDownload(pmk);
  9205. if (SUCCEEDED(hres))
  9206. fQueued = TRUE;
  9207. }
  9208. }
  9209. if (pmk != NULL)
  9210. pmk->Release();
  9211. }
  9212. if (!fQueued) {
  9213. _fbPicsWaitFlags &= ~PICS_WAIT_FOR_ROOT;
  9214. TraceMsg(DM_PICS, "CDOH::CPP::_StartPicsRootQuery queueing failed, waitflags now %x", (DWORD)_fbPicsWaitFlags);
  9215. if (!_fbPicsWaitFlags) {
  9216. _HandlePicsChecksComplete();
  9217. }
  9218. }
  9219. }
  9220. else {
  9221. TraceMsg(DM_PICS, "CDOH::CPP::_StartPicsRootQuery no query queued, waitflags=%x", (DWORD)_fbPicsWaitFlags);
  9222. }
  9223. }
  9224. void CDocObjectHost::CPicsProcessor::_HandlePicsChecksComplete(void)
  9225. {
  9226. if (!_fPicsAccessAllowed)
  9227. {
  9228. TraceMsg(DM_PICS, "CDOH::CPP::_HandlePicsChecksComplete access denied, posting WM_PICS_DOBLOCKINGUI to hwnd %x", (DWORD_PTR)_pdoh->_hwnd);
  9229. /* Allow download of this and other frames to continue while we post
  9230. * the denial UI.
  9231. */
  9232. if (!PostMessage(_pdoh->_hwnd, WM_PICS_DOBLOCKINGUI, 0, _GetKey())) {
  9233. TraceMsg(DM_PICS, "CDOH::CPP::_HandlePicsChecksComplete couldn't post message!");
  9234. }
  9235. }
  9236. else
  9237. {
  9238. if( _pPrivWindow )
  9239. {
  9240. TraceMsg(DM_PICS, "CDOH::CPP::_HandlePicsChecksComplete access allowed, posting WM_PICS_RESULTTOPRIVWIN");
  9241. if (!PostMessage( _pdoh->_hwnd, WM_PICS_RESULTTOPRIVWIN, IDOK, _GetKey()))
  9242. {
  9243. TraceMsg(DM_PICS, "CDOH::CPP::_HandlePicsChecksComplete couldn't post message!");
  9244. }
  9245. }
  9246. else
  9247. {
  9248. TraceMsg(DM_PICS, "CDOH::CPP::_HandlePicsChecksComplete access allowed, execing ACTIVATEMENOW");
  9249. if (!_pdoh->_fSetTarget && _pdoh->_pmsoctBrowser)
  9250. {
  9251. _pdoh->_pmsoctBrowser->Exec(&CGID_ShellDocView, SHDVID_ACTIVATEMENOW, NULL, NULL, NULL);
  9252. }
  9253. }
  9254. }
  9255. }
  9256. void CDocObjectHost::CPicsProcessor::_ReInit()
  9257. {
  9258. TraceMsg(DM_PICS, "CDOH::CPP::_ReInit");
  9259. _fPicsAccessAllowed = TRUE;
  9260. _fInDialog = FALSE;
  9261. _fTerminated = FALSE;
  9262. _fbPicsWaitFlags = 0;
  9263. _dwPicsLabelSource = 0;
  9264. if (_pPrivWindow)
  9265. {
  9266. _pPrivWindow->SetPICSTarget(NULL);
  9267. _pPrivWindow->Release();
  9268. _pPrivWindow = NULL;
  9269. }
  9270. if (_pRootDownload != NULL) {
  9271. _pRootDownload->CleanUp();
  9272. ATOMICRELEASET(_pRootDownload,CPicsRootDownload);
  9273. }
  9274. _pPicsProcNext = NULL;
  9275. if (_pRatingDetails){
  9276. ::RatingFreeDetails(_pRatingDetails);
  9277. _pRatingDetails = NULL;
  9278. }
  9279. if (_dwPicsSerialNumber) {
  9280. ::_RemovePicsQuery(_dwPicsSerialNumber);
  9281. _dwPicsSerialNumber = 0;
  9282. }
  9283. if (_hPicsQuery)
  9284. {
  9285. RatingObtainCancel(_hPicsQuery);
  9286. _hPicsQuery = NULL;
  9287. }
  9288. if ( _pszPicsURL )
  9289. {
  9290. delete _pszPicsURL;
  9291. _pszPicsURL = NULL;
  9292. }
  9293. }
  9294. void
  9295. CDocObjectHost::CPicsProcessor::_Terminate()
  9296. {
  9297. ASSERT( this != &(_pdoh->_PicsProcBase) );
  9298. if (!_fInDialog)
  9299. {
  9300. delete this;
  9301. }
  9302. else
  9303. {
  9304. _fTerminated = TRUE;
  9305. }
  9306. }
  9307. CDocObjectHost::CPicsProcessor *
  9308. CDocObjectHost::_GetPicsProcessorFromKey(LONG_PTR lKey)
  9309. {
  9310. CPicsProcessor * ppp = &_PicsProcBase;
  9311. while( ppp )
  9312. {
  9313. if (ppp->_GetKey() == lKey)
  9314. return ppp;
  9315. ppp = ppp->_pPicsProcNext;
  9316. }
  9317. return NULL;
  9318. }
  9319. CDocObjectHost::CPicsProcessor *
  9320. CDocObjectHost::_GetPicsProcessorFromSerialNumber(DWORD dwSerial)
  9321. {
  9322. CPicsProcessor * ppp = &_PicsProcBase;
  9323. ASSERT( dwSerial != NULL );
  9324. while( ppp )
  9325. {
  9326. if (ppp->_dwPicsSerialNumber == dwSerial)
  9327. return ppp;
  9328. ppp = ppp->_pPicsProcNext;
  9329. }
  9330. return NULL;
  9331. }
  9332. void CDocObjectHost::_StartBasePicsProcessor()
  9333. {
  9334. HRESULT hres;
  9335. BOOL bRatingsEnabled;
  9336. IRatingNotification* pRatingNotify;
  9337. hres = QueryService(SID_SRatingNotification, IID_PPV_ARG(IRatingNotification, &pRatingNotify));
  9338. if (SUCCEEDED(hres))
  9339. {
  9340. bRatingsEnabled = pRatingNotify->IsRatingsEnabled() ? FALSE : TRUE;
  9341. pRatingNotify->Release();
  9342. }
  9343. else
  9344. {
  9345. bRatingsEnabled = IS_RATINGS_ENABLED() && ::RatingEnabledQuery() == S_OK;
  9346. }
  9347. if(bRatingsEnabled)
  9348. {
  9349. TraceMsg(DM_PICS, "CDOH::_StartBasePicsProcessor entered with ratings enabled");
  9350. LPOLESTR pwszRawURL = NULL;
  9351. if (SUCCEEDED(_GetCurrentPageW(&pwszRawURL, TRUE)))
  9352. {
  9353. _PicsProcBase._StartPicsQuery(pwszRawURL);
  9354. OleFree(pwszRawURL);
  9355. }
  9356. }
  9357. }
  9358. HRESULT CDocObjectHost::_StartSecondaryPicsProcessor(IHTMLPrivateWindow * pPrivWin)
  9359. {
  9360. HRESULT hr = S_FALSE;
  9361. ASSERT( pPrivWin );
  9362. HRESULT hres;
  9363. BOOL bRatingsEnabled;
  9364. IRatingNotification* pRatingNotify;
  9365. hres = QueryService(SID_SRatingNotification, IID_PPV_ARG(IRatingNotification, &pRatingNotify));
  9366. if (SUCCEEDED(hres))
  9367. {
  9368. bRatingsEnabled = pRatingNotify->IsRatingsEnabled() ? FALSE : TRUE;
  9369. pRatingNotify->Release();
  9370. }
  9371. else
  9372. {
  9373. bRatingsEnabled = IS_RATINGS_ENABLED() && ::RatingEnabledQuery() == S_OK;
  9374. }
  9375. if (bRatingsEnabled)
  9376. {
  9377. LPOLESTR pwszURL = NULL;
  9378. // CWindow::GetPendingUrl() has LPOLESTR * parameter.
  9379. hr = pPrivWin->GetPendingUrl( &pwszURL );
  9380. if ( SUCCEEDED(hr) && pwszURL )
  9381. {
  9382. CPicsProcessor * pPicsProc = new CPicsProcessor;
  9383. if( pPicsProc )
  9384. {
  9385. pPicsProc->_pdoh = this;
  9386. pPicsProc->_pPrivWindow = pPrivWin;
  9387. pPrivWin->AddRef();
  9388. pPicsProc->_dwKey = _dwPicsKeyBase++;
  9389. hr = pPicsProc->_StartPicsQuery( pwszURL );
  9390. if( hr == S_FALSE )
  9391. {
  9392. delete pPicsProc;
  9393. }
  9394. else
  9395. {
  9396. pPicsProc->_pPicsProcNext = _PicsProcBase._pPicsProcNext;
  9397. _PicsProcBase._pPicsProcNext = pPicsProc;
  9398. pPrivWin->SetPICSTarget( SAFECAST(pPicsProc, IOleCommandTarget *) );
  9399. }
  9400. }
  9401. else
  9402. {
  9403. hr = E_OUTOFMEMORY;
  9404. }
  9405. OleFree( pwszURL );
  9406. }
  9407. }
  9408. return hr;
  9409. }
  9410. HRESULT CDocObjectHost::_RemovePicsProcessorByKey(LONG_PTR lKey)
  9411. {
  9412. ASSERT( lKey != 0 );
  9413. // The base Proc has a 0 key and should never be removed
  9414. CPicsProcessor * ppp = &_PicsProcBase;
  9415. CPicsProcessor * pppLast = NULL;
  9416. while( ppp )
  9417. {
  9418. if (ppp->_GetKey() == lKey)
  9419. {
  9420. ASSERT(pppLast);
  9421. pppLast->_pPicsProcNext = ppp->_pPicsProcNext;
  9422. ppp->_Terminate();
  9423. return S_OK;
  9424. }
  9425. pppLast = ppp;
  9426. ppp = ppp->_pPicsProcNext;
  9427. }
  9428. return S_FALSE;
  9429. }
  9430. HRESULT CDocObjectHost::_RemovePicsProcessorByPrivWindowUnk(IUnknown* pUnkFind)
  9431. {
  9432. ASSERT( pUnkFind );
  9433. // The base Proc has a 0 key and should never be removed
  9434. CPicsProcessor * ppp = &_PicsProcBase;
  9435. CPicsProcessor * pppLast = NULL;
  9436. while( ppp )
  9437. {
  9438. if (ppp->_pPrivWindow)
  9439. {
  9440. IUnknown * pUnkThisOne;
  9441. if (SUCCEEDED( ppp->_pPrivWindow->QueryInterface( IID_IUnknown, (void**)&pUnkThisOne ) ))
  9442. {
  9443. if (pUnkThisOne == pUnkFind)
  9444. {
  9445. ASSERT(pppLast);
  9446. pppLast->_pPicsProcNext = ppp->_pPicsProcNext;
  9447. ppp->_Terminate();
  9448. pUnkThisOne->Release();
  9449. return S_OK;
  9450. }
  9451. pUnkThisOne->Release();
  9452. }
  9453. }
  9454. pppLast = ppp;
  9455. ppp = ppp->_pPicsProcNext;
  9456. }
  9457. return S_FALSE;
  9458. }
  9459. HRESULT CDocObjectHost::_RemoveAllPicsProcessors()
  9460. {
  9461. CPicsProcessor * ppp = &_PicsProcBase;
  9462. CPicsProcessor * pppNext;
  9463. while( ppp )
  9464. {
  9465. pppNext = ppp->_pPicsProcNext;
  9466. if (ppp != &_PicsProcBase)
  9467. ppp->_Terminate();
  9468. else
  9469. ppp->_ReInit();
  9470. ppp = pppNext;
  9471. }
  9472. return S_OK;
  9473. }
  9474. HRESULT CDocObjectFrame::QueryService(REFGUID guidService,
  9475. REFIID riid, void **ppvObj)
  9476. {
  9477. return _pdoh->QueryService(guidService, riid, ppvObj);
  9478. }
  9479. HRESULT CDocObjectFrame::QueryInterface(REFIID riid, void ** ppvObj)
  9480. {
  9481. if (IsEqualIID(riid, IID_IOleInPlaceFrame) ||
  9482. IsEqualIID(riid, IID_IOleInPlaceUIWindow) ||
  9483. IsEqualIID(riid, IID_IOleWindow) ||
  9484. IsEqualIID(riid, IID_IUnknown))
  9485. {
  9486. *ppvObj = SAFECAST(this, IOleInPlaceFrame*);
  9487. }
  9488. else if (IsEqualIID(riid, IID_IOleCommandTarget))
  9489. {
  9490. *ppvObj = SAFECAST(this, IOleCommandTarget*);
  9491. }
  9492. else if (IsEqualIID(riid, IID_IServiceProvider))
  9493. {
  9494. *ppvObj = SAFECAST(this, IServiceProvider*);
  9495. }
  9496. else if (IsEqualIID(riid, IID_IInternetSecurityMgrSite))
  9497. {
  9498. *ppvObj = SAFECAST(this, IInternetSecurityMgrSite*);
  9499. }
  9500. else
  9501. {
  9502. *ppvObj = NULL;
  9503. return E_NOINTERFACE;
  9504. }
  9505. _pdoh->AddRef();
  9506. return NOERROR;
  9507. }
  9508. ULONG CDocObjectFrame::AddRef(void)
  9509. {
  9510. return _pdoh->AddRef();
  9511. }
  9512. ULONG CDocObjectFrame::Release(void)
  9513. {
  9514. return _pdoh->Release();
  9515. }
  9516. HRESULT CDocObjectFrame::GetWindow(HWND * lphwnd)
  9517. {
  9518. DOFMSG(TEXT("GetWindow called"));
  9519. return _pdoh->_pipu ?
  9520. _pdoh->_pipu->GetWindow(lphwnd) :
  9521. _pdoh->_psb ? _pdoh->_psb->GetWindow(lphwnd) :
  9522. _pdoh->GetWindow(lphwnd);
  9523. }
  9524. HRESULT CDocObjectFrame::ContextSensitiveHelp(BOOL fEnterMode)
  9525. {
  9526. DOFMSG(TEXT("ContextSensitiveHelp called"));
  9527. return _pdoh->ContextSensitiveHelp(fEnterMode);
  9528. }
  9529. HRESULT CDocObjectFrame::GetBorder(LPRECT lprectBorder)
  9530. {
  9531. // DOFMSG(TEXT("GetBorder called"));
  9532. return _pdoh->_pipu ?
  9533. _pdoh->_pipu->GetBorder(lprectBorder) : E_UNEXPECTED;
  9534. }
  9535. HRESULT CDocObjectFrame::RequestBorderSpace(LPCBORDERWIDTHS pborderwidths)
  9536. {
  9537. DOFMSG(TEXT("RequestBorderSpace called"));
  9538. return _pdoh->_pipu ?
  9539. _pdoh->_pipu->RequestBorderSpace(pborderwidths) : E_UNEXPECTED;
  9540. }
  9541. HRESULT CDocObjectFrame::SetBorderSpace(LPCBORDERWIDTHS pborderwidths)
  9542. {
  9543. // DOFMSG(TEXT("SetBorderSpace called"));
  9544. return _pdoh->_pipu ?
  9545. _pdoh->_pipu->SetBorderSpace(pborderwidths) : E_UNEXPECTED;
  9546. }
  9547. HRESULT CDocObjectFrame::SetActiveObject(
  9548. IOleInPlaceActiveObject *pActiveObject, LPCOLESTR pszObjName)
  9549. {
  9550. DOFMSG(TEXT("SetActiveObject called"));
  9551. // Note that we need to call both.
  9552. _pdoh->_xao.SetActiveObject(pActiveObject);
  9553. if (_pdoh->_pipu) {
  9554. //
  9555. // Note that we should pass proxy IOleActiveObject pointer instead.
  9556. //
  9557. _pdoh->_pipu->SetActiveObject(pActiveObject ? &_pdoh->_xao : NULL, pszObjName);
  9558. }
  9559. return S_OK;
  9560. }
  9561. HRESULT CDocObjectFrame::InsertMenus(HMENU hmenuShared, LPOLEMENUGROUPWIDTHS lpMenuWidths)
  9562. {
  9563. DOFMSG2(TEXT("InsertMenus called with"), hmenuShared);
  9564. return _pdoh->_InsertMenus(hmenuShared, lpMenuWidths);
  9565. }
  9566. HRESULT CDocObjectFrame::SetMenu(HMENU hmenuShared, HOLEMENU holemenu, HWND hwndActiveObject)
  9567. {
  9568. DOFMSG2(TEXT("SetMenu called with"), hmenuShared);
  9569. return _pdoh->_SetMenu(hmenuShared, holemenu, hwndActiveObject);
  9570. }
  9571. HRESULT CDocObjectFrame::RemoveMenus(HMENU hmenuShared)
  9572. {
  9573. DOFMSG(TEXT("RemoveMenus called"));
  9574. return _pdoh->_RemoveMenus(hmenuShared);
  9575. }
  9576. HRESULT CDocObjectFrame::SetStatusText(LPCOLESTR pszStatusText)
  9577. {
  9578. DOFMSG(TEXT("SetStatusText called"));
  9579. return _pdoh->_SetStatusText(pszStatusText);
  9580. }
  9581. HRESULT CDocObjectFrame::EnableModeless(BOOL fEnable)
  9582. {
  9583. DOFMSG(TEXT("EnableModeless called"));
  9584. return _pdoh->_EnableModeless(fEnable);
  9585. }
  9586. // IOleInPlaceFrame::TranslateAccelerator
  9587. HRESULT CDocObjectFrame::TranslateAccelerator(LPMSG lpmsg, WORD wID)
  9588. {
  9589. // NOTES: This code remains as-is. If we have something special
  9590. // it should be done in CDocObjectHost::TranslateAccelerator
  9591. return _pdoh->_TranslateAccelerator(lpmsg, wID);
  9592. }
  9593. HRESULT CDocObjectFrame::QueryStatus(const GUID *pguidCmdGroup,
  9594. ULONG cCmds, OLECMD rgCmds[], OLECMDTEXT *pcmdtext)
  9595. {
  9596. DOFMSG(TEXT("QueryStatus called"));
  9597. return _pdoh->QueryStatus(pguidCmdGroup, cCmds, rgCmds, pcmdtext);
  9598. }
  9599. HRESULT CDocObjectFrame::Exec(const GUID *pguidCmdGroup,
  9600. DWORD nCmdID, DWORD nCmdexecopt, VARIANTARG *pvarargIn, VARIANTARG *pvarargOut)
  9601. {
  9602. DOFMSG(TEXT("Exec called"));
  9603. return _pdoh->Exec(pguidCmdGroup, nCmdID, nCmdexecopt, pvarargIn, pvarargOut);
  9604. }
  9605. //*** CPAO::TranslateAccelerator (IOIPAO::TranslateAccelerator)
  9606. //
  9607. HRESULT CProxyActiveObject::TranslateAccelerator(
  9608. LPMSG lpmsg)
  9609. {
  9610. HRESULT hres = E_FAIL;
  9611. // IShellBrowser is supporsed to call ISV::TranslateAcceleratorSV,
  9612. // but why not be nice?
  9613. ASSERT(!_pdoh->_fCycleFocus);
  9614. //
  9615. // Don't call DocObject's TranslateAccelarator with non-key messages.
  9616. // It's better to be IE compatible.
  9617. //
  9618. BOOL fKeybrdMsg = IsInRange(lpmsg->message, WM_KEYFIRST, WM_KEYLAST);
  9619. if (fKeybrdMsg && _piact && (hres = _piact->TranslateAccelerator(lpmsg)) == S_OK) {
  9620. if (_pdoh->_fCycleFocus) {
  9621. // we got called back by trident (IOCS::TA), but deferred it.
  9622. // time to pay the piper.
  9623. TraceMsg(DM_FOCUS, "DOH::IOIPAO::TA piao->TA==S_OK ret _fCycleFocus=FALSE hr=S_FALSE (piper)");
  9624. _pdoh->_fCycleFocus = FALSE;
  9625. return S_FALSE; // time to pay the piper
  9626. }
  9627. return S_OK;
  9628. }
  9629. if (_pdoh->_fCycleFocus) {
  9630. TraceMsg(DM_ERROR, "DOH::IOIPAO::TA _fCycleFocus && hres=%x (!=S_OK)", hres);
  9631. _pdoh->_fCycleFocus = FALSE;
  9632. return S_FALSE;
  9633. }
  9634. return _pdoh->TranslateHostAccelerators(lpmsg);
  9635. }
  9636. HRESULT CProxyActiveObject::OnFrameWindowActivate(
  9637. BOOL fActivate)
  9638. {
  9639. TraceMsg(TF_SHDUIACTIVATE, "CProxyAO::OnFrameWindowActivate called with %d (_piact=%x)",
  9640. fActivate, _piact);
  9641. if (_piact) {
  9642. return _piact->OnFrameWindowActivate(fActivate);
  9643. }
  9644. return S_OK;
  9645. }
  9646. HRESULT CProxyActiveObject::OnDocWindowActivate(
  9647. BOOL fActivate)
  9648. {
  9649. return S_OK;
  9650. }
  9651. HRESULT CProxyActiveObject::ResizeBorder(
  9652. LPCRECT prcBorder,
  9653. IOleInPlaceUIWindow *pUIWindow,
  9654. BOOL fFrameWindow)
  9655. {
  9656. if (_piact) {
  9657. //
  9658. // Note that we must pass our proxy frame instead!
  9659. //
  9660. return _piact->ResizeBorder(prcBorder, &_pdoh->_dof, TRUE);
  9661. }
  9662. return E_FAIL;
  9663. }
  9664. void CProxyActiveObject::SetActiveObject(IOleInPlaceActiveObject *piact )
  9665. {
  9666. if (_piact)
  9667. {
  9668. ATOMICRELEASE(_piact);
  9669. _hwnd = NULL;
  9670. }
  9671. if (piact) {
  9672. _piact = piact;
  9673. _piact->AddRef();
  9674. _piact->GetWindow(&_hwnd);
  9675. }
  9676. }
  9677. HRESULT CProxyActiveObject::EnableModeless(
  9678. BOOL fEnable)
  9679. {
  9680. // IShellBrowser is supporsed to call ISV::EnableModelessSV,
  9681. // but why not be nice?
  9682. HRESULT hres = S_OK;
  9683. if (_piact)
  9684. hres = _piact->EnableModeless(fEnable);
  9685. return hres;
  9686. }
  9687. HRESULT CProxyActiveObject::QueryInterface(REFIID riid, void ** ppvObj)
  9688. {
  9689. if (IsEqualIID(riid, IID_IOleInPlaceActiveObject) ||
  9690. IsEqualIID(riid, IID_IOleWindow) ||
  9691. IsEqualIID(riid, IID_IUnknown))
  9692. {
  9693. *ppvObj = SAFECAST(this, IOleInPlaceActiveObject*);
  9694. }
  9695. else
  9696. {
  9697. *ppvObj = NULL;
  9698. return E_NOINTERFACE;
  9699. }
  9700. _pdoh->AddRef();
  9701. return NOERROR;
  9702. }
  9703. ULONG CProxyActiveObject::AddRef(void)
  9704. {
  9705. return _pdoh->AddRef();
  9706. }
  9707. ULONG CProxyActiveObject::Release(void)
  9708. {
  9709. return _pdoh->Release();
  9710. }
  9711. HRESULT CProxyActiveObject::GetWindow(HWND * lphwnd)
  9712. {
  9713. return _pdoh->GetWindow(lphwnd);
  9714. }
  9715. HRESULT CProxyActiveObject::ContextSensitiveHelp(BOOL fEnterMode)
  9716. {
  9717. return _pdoh->ContextSensitiveHelp(fEnterMode);
  9718. }
  9719. #define ANIMATION_WND_WIDTH (100+3)
  9720. void CDocObjectHost::_PlaceProgressBar(BOOL fForcedLayout)
  9721. {
  9722. if (_psb) {
  9723. HWND hwndStatus = NULL;
  9724. _psb->GetControlWindow(FCW_STATUS, &hwndStatus);
  9725. if (hwndStatus) {
  9726. RECT rc;
  9727. INT_PTR fSimple = SendMessage(hwndStatus, SB_ISSIMPLE, 0, 0);
  9728. if (!fSimple || fForcedLayout) {
  9729. // While processing WM_SIZE, turn off the simple mode temporarily.
  9730. if (fSimple)
  9731. _psb->SendControlMsg(FCW_STATUS, SB_SIMPLE, 0, 0, NULL);
  9732. GetClientRect(hwndStatus, &rc);
  9733. const UINT cxZone = ZoneComputePaneSize(hwndStatus);
  9734. UINT cxProgressBar = (_fShowProgressCtl) ? 100 : 0;
  9735. INT nSBWidth = rc.right - rc.left;
  9736. INT arnRtEdge[STATUS_PANES] = {1};
  9737. INT nIconPaneWidth = GetSystemMetrics(SM_CXSMICON) +
  9738. (GetSystemMetrics(SM_CXEDGE) * 4);
  9739. INT nWidthReqd = cxZone + cxProgressBar + (nIconPaneWidth * 3);
  9740. arnRtEdge[STATUS_PANE_NAVIGATION] = max(1, nSBWidth - nWidthReqd);
  9741. nWidthReqd -= cxProgressBar;
  9742. arnRtEdge[STATUS_PANE_PROGRESS] = max(1, nSBWidth - nWidthReqd);
  9743. nWidthReqd -= (nIconPaneWidth);
  9744. arnRtEdge[STATUS_PANE_OFFLINE] = max(1, nSBWidth - nWidthReqd);
  9745. nWidthReqd -= (nIconPaneWidth);
  9746. arnRtEdge[STATUS_PANE_PRIVACY] = max(1, nSBWidth - nWidthReqd);
  9747. // nWidthReqd -= (nIconPaneWidth);
  9748. // arnRtEdge[STATUS_PANE_PRINTER] = max(1, nSBWidth - nWidthReqd);
  9749. nWidthReqd -= (nIconPaneWidth);
  9750. arnRtEdge[STATUS_PANE_SSL] = max(1, nSBWidth - nWidthReqd);
  9751. arnRtEdge[STATUS_PANE_ZONE] = -1;
  9752. LRESULT nParts = 0;
  9753. nParts = SendMessage(hwndStatus, SB_GETPARTS, 0, 0L);
  9754. if (nParts != STATUS_PANES)
  9755. {
  9756. for ( int n = 0; n < nParts; n++)
  9757. {
  9758. SendMessage(hwndStatus, SB_SETTEXT, n | SBT_NOTABPARSING, NULL);
  9759. SendMessage(hwndStatus, SB_SETICON, n, NULL);
  9760. }
  9761. SendMessage(hwndStatus, SB_SETPARTS, 0, 0L);
  9762. }
  9763. SendMessage(hwndStatus, SB_SETPARTS, STATUS_PANES, (LPARAM)arnRtEdge);
  9764. if (!_hwndProgress) {
  9765. _psb->GetControlWindow(FCW_PROGRESS, &_hwndProgress);
  9766. }
  9767. if (_hwndProgress) {
  9768. if (SendMessage(hwndStatus, SB_GETRECT, 1, (LPARAM)&rc))
  9769. {
  9770. InflateRect(&rc, -GetSystemMetrics(SM_CXEDGE), -GetSystemMetrics(SM_CYEDGE));
  9771. }
  9772. else
  9773. {
  9774. rc.left = rc.top = rc.right = rc.bottom = 0;
  9775. }
  9776. SetWindowPos(_hwndProgress, NULL,
  9777. rc.left, rc.top,
  9778. rc.right-rc.left, rc.bottom-rc.top,
  9779. SWP_NOZORDER | SWP_NOACTIVATE);
  9780. }
  9781. SendMessage(hwndStatus, SB_SETTEXT, 1 | SBT_NOTABPARSING, (LPARAM)TEXT(""));
  9782. SendMessage(hwndStatus, SB_SETMINHEIGHT, GetSystemMetrics(SM_CYSMICON) +
  9783. GetSystemMetrics(SM_CYBORDER) * 2, 0L);
  9784. // Restore
  9785. if (fSimple)
  9786. SendMessage(hwndStatus, SB_SIMPLE, TRUE, 0);
  9787. }
  9788. }
  9789. } else {
  9790. TraceMsg(TF_WARNING, "_PlaceProgressBar ASSERT(_psb) this=%x", this);
  9791. }
  9792. }
  9793. void CDocObjectHost::_ActivateOleObject(void)
  9794. {
  9795. HRESULT hres;
  9796. _pole->SetClientSite(NULL);
  9797. if (_fDontInPlaceNavigate())
  9798. {
  9799. TraceMsg(TF_SHDAPPHACK, "CDOH::_ActivateOleObject calling DoVerb because of _fDontInPlaceNavigate()");
  9800. }
  9801. _EnableModeless(FALSE);
  9802. hres = _pole->DoVerb(
  9803. _fUseOpenVerb() ? OLEIVERB_OPEN : OLEIVERB_PRIMARY,
  9804. NULL, NULL, (UINT)-1, NULL, NULL);
  9805. _EnableModeless(TRUE);
  9806. if (SUCCEEDED(hres))
  9807. {
  9808. CShdAdviseSink_Advise(_pwb, _pole);
  9809. }
  9810. #ifdef DEBUG
  9811. else if (!_fDelegatedNavigation)
  9812. {
  9813. TraceMsg(DM_ERROR, "CDOH::_ActivateOleObject DoVerb failed %x.", hres);
  9814. }
  9815. #endif
  9816. // We must release the OLE object to avoid calling Close
  9817. // from _UnBind.
  9818. _ReleaseOleObject();
  9819. _ReleasePendingObject();
  9820. }
  9821. void CDocObjectHost::ClearScriptError()
  9822. {
  9823. // clear out the script error list
  9824. _pScriptErrList->ClearErrorList();
  9825. _SetPriorityStatusText(NULL);
  9826. // reset the text and icon
  9827. _ResetStatusBar();
  9828. }
  9829. //
  9830. // The docobject's READYSTATE property may have changed
  9831. //
  9832. void CDocObjectHost::_OnReadyState(long lVal, BOOL fUpdateHistory /* = TRUE */)
  9833. {
  9834. // Forward this to the browser so we can source ReadyState events properly
  9835. // TRACE this zekel
  9836. if (_psb)
  9837. {
  9838. IDocNavigate *pdn;
  9839. if (SUCCEEDED(_psb->QueryInterface(IID_IDocNavigate, (void **)&pdn)))
  9840. {
  9841. ASSERT(_psv);
  9842. pdn->OnReadyStateChange(_psv, lVal);
  9843. pdn->Release();
  9844. }
  9845. }
  9846. // NOTE: The below code is rather wasteful. The OmWindow stuff
  9847. // should trigger off the above ReadyState code.
  9848. //
  9849. IShellHTMLWindowSupport *phtmlWS;
  9850. if (_psp && SUCCEEDED(_psp->QueryService(SID_SOmWindow, IID_IShellHTMLWindowSupport, (void**)&phtmlWS)))
  9851. {
  9852. phtmlWS->ReadyStateChangedTo(lVal, _psv);
  9853. phtmlWS->Release();
  9854. }
  9855. if ( (lVal == READYSTATE_INTERACTIVE)
  9856. && (_pScriptErrList != NULL))
  9857. {
  9858. ClearScriptError();
  9859. }
  9860. if (lVal >= READYSTATE_INTERACTIVE)
  9861. {
  9862. // Technically we can get this value multiple times,
  9863. // so make sure we call _Navigate only once.
  9864. //
  9865. if (!_fReadystateInteractiveProcessed)
  9866. {
  9867. _fReadystateInteractiveProcessed = TRUE;
  9868. _Navigate();
  9869. }
  9870. if (lVal == READYSTATE_COMPLETE)
  9871. {
  9872. _OnSetProgressPos(0, PROGRESS_RESET);
  9873. // We aren't going to commit error pages to the history
  9874. //
  9875. if (_pwb && !_fErrorPage && fUpdateHistory)
  9876. {
  9877. WCHAR szTitle[MAX_PATH]; // titles are only stored up to this size
  9878. if (SUCCEEDED(_pwb->GetTitle(_psv, szTitle, ARRAYSIZE(szTitle))))
  9879. {
  9880. // BharatS : 01/09/97 : There is no need to tie the updating of the title in the
  9881. // history to the updating of the INTSITE database. Thus the INTSITE database
  9882. // update can be moved out of AddUrlToUrlHistoryStg() in history.cpp when time permits
  9883. // to a more logical place such as someplace in dochost.cpp
  9884. //
  9885. _UpdateHistoryAndIntSiteDB(szTitle);
  9886. }
  9887. else
  9888. {
  9889. _UpdateHistoryAndIntSiteDB(NULL);
  9890. }
  9891. }
  9892. }
  9893. }
  9894. }
  9895. HRESULT CDocObjectHost::_OnChangedReadyState()
  9896. {
  9897. IDispatch * p_idispatch;
  9898. ASSERT(_pole || _fFriendlyError);
  9899. if (!_pole)
  9900. return E_UNEXPECTED;
  9901. if (SUCCEEDED(_pole->QueryInterface( IID_IDispatch, (void **) &p_idispatch)))
  9902. {
  9903. VARIANTARG va;
  9904. EXCEPINFO exInfo;
  9905. va.vt = 0;
  9906. if (EVAL(SUCCEEDED(p_idispatch->Invoke( DISPID_READYSTATE, IID_NULL, LOCALE_USER_DEFAULT, DISPATCH_PROPERTYGET, (DISPPARAMS *)&g_dispparamsNoArgs, &va, &exInfo, NULL))
  9907. && va.vt == VT_I4))
  9908. {
  9909. _OnReadyState(va.lVal);
  9910. // If we are hosting Trident's native frames build,
  9911. // we don't want to call _RemoveTransitionCapability().
  9912. //
  9913. if (!_fDocCanNavigate && va.lVal == READYSTATE_COMPLETE)
  9914. {
  9915. _RemoveTransitionCapability();
  9916. }
  9917. }
  9918. p_idispatch->Release();
  9919. }
  9920. return( NOERROR );
  9921. }
  9922. HRESULT CDocObjectHost::OnRequestEdit(DISPID dispid)
  9923. {
  9924. return E_NOTIMPL;
  9925. }
  9926. //
  9927. // OnChanged
  9928. //
  9929. // Notification from the DocObject that one of its
  9930. // properties has changed.
  9931. //
  9932. HRESULT CDocObjectHost::OnChanged(DISPID dispid)
  9933. {
  9934. if (DISPID_READYSTATE == dispid || DISPID_UNKNOWN == dispid)
  9935. return _OnChangedReadyState();
  9936. return S_OK;
  9937. }
  9938. extern BOOL _ValidateURL(LPTSTR pszName);
  9939. void CDocObjectHost::_UpdateHistoryAndIntSiteDB(LPCWSTR pwszTitle)
  9940. {
  9941. TCHAR szUrl[MAX_URL_STRING];
  9942. if (SUCCEEDED(_GetCurrentPage(szUrl, MAX_URL_STRING, TRUE)) &&
  9943. _ValidateURL(szUrl, UQF_DEFAULT))
  9944. {
  9945. // update history and intsite if this isn't a silent browse
  9946. BOOL bSilent = FALSE;
  9947. HRESULT hr = _GetOfflineSilent(NULL, &bSilent);
  9948. if (SUCCEEDED(hr) && (!bSilent))
  9949. {
  9950. BOOL fWriteHistory,
  9951. fSelectHistory;
  9952. fWriteHistory = TRUE;
  9953. fSelectHistory = TRUE;
  9954. if (NULL != _pocthf)
  9955. {
  9956. MSOCMD rgCmd[] = { { SBCMDID_WRITEHIST, 0 }, { SBCMDID_SELECTHISTPIDL, 0 } };
  9957. _pocthf->QueryStatus(&CGID_Explorer, ARRAYSIZE(rgCmd), rgCmd, NULL);
  9958. fWriteHistory = BOOLIFY(rgCmd[0].cmdf & MSOCMDF_ENABLED);
  9959. fSelectHistory = BOOLIFY(rgCmd[1].cmdf & MSOCMDF_ENABLED);
  9960. }
  9961. AddUrlToUrlHistoryStg(szUrl,
  9962. pwszTitle,
  9963. _psb,
  9964. fWriteHistory,
  9965. fSelectHistory ? _pocthf : NULL,
  9966. get_punkSFHistory(), NULL);
  9967. //
  9968. // Satona had the redirect code ifdef'd out, but for
  9969. // netscape compatibility, we need to update the history
  9970. // for the redirected URL as well. - zekel - 22-JUL-97
  9971. //
  9972. // If this page is a redirect, update intsite for destination too
  9973. INTERNET_CACHE_ENTRY_INFO *pCacheEntry = NULL;
  9974. #ifndef UNIX
  9975. WCHAR chBuf[MAX_CACHE_ENTRY_INFO_SIZE];
  9976. // Find entry in cache using redirect map
  9977. pCacheEntry = (INTERNET_CACHE_ENTRY_INFO *)chBuf;
  9978. #else
  9979. union
  9980. {
  9981. double _alignOn8;
  9982. WCHAR _chBuf[MAX_CACHE_ENTRY_INFO_SIZE];
  9983. } chBuf;
  9984. // Find entry in cache using redirect map
  9985. pCacheEntry = (INTERNET_CACHE_ENTRY_INFO *)&chBuf;
  9986. #endif /* !UNIX */
  9987. DWORD dwSize = SIZEOF(chBuf);
  9988. BOOL fSuccess = GetUrlCacheEntryInfoEx(szUrl, pCacheEntry, &dwSize, NULL, 0, NULL, 0);
  9989. if (fSuccess)
  9990. {
  9991. // If we have a different url than we started with, update it too
  9992. if (StrCmp(szUrl, pCacheEntry->lpszSourceUrlName))
  9993. {
  9994. AddUrlToUrlHistoryStg(pCacheEntry->lpszSourceUrlName,
  9995. pwszTitle,
  9996. _psb,
  9997. fWriteHistory,
  9998. fSelectHistory ? _pocthf : NULL,
  9999. get_punkSFHistory(), NULL);
  10000. }
  10001. }
  10002. }
  10003. }
  10004. }
  10005. //
  10006. // CDocObjectHost::_SetUpTransitionCapability()
  10007. //
  10008. // Returns TRUE if all the following hold true:
  10009. // - object has readystate property
  10010. // - readystate property is currently < interactive
  10011. // - Object supports IPropertyNotifySink
  10012. // Then this object supports delayed switching when it
  10013. // it tells us that it is ready...
  10014. //
  10015. // This is how we switch pages only when the new page is ready to be
  10016. // switched to. Also, by doing this we can also make the switch smooth
  10017. // by applying graphical transitions.
  10018. //
  10019. BOOL CDocObjectHost::_SetUpTransitionCapability(BOOL fWindowOpen /* = FALSE */)
  10020. {
  10021. // By default DocObject doesn't have gray-flash communication
  10022. BOOL fSupportsReadystate = FALSE;
  10023. long lReadyState = 0; // Init to avoid a bogus C4701 warning
  10024. // Sanity Check
  10025. if (!_pole)
  10026. return(fSupportsReadystate);
  10027. // Check for proper readystate support
  10028. BOOL fReadyStateOK = FALSE;
  10029. IDispatch * p_idispatch;
  10030. if (SUCCEEDED(_pole->QueryInterface( IID_IDispatch, (void **) &p_idispatch )))
  10031. {
  10032. VARIANTARG va;
  10033. EXCEPINFO exInfo;
  10034. if (SUCCEEDED(p_idispatch->Invoke( DISPID_READYSTATE, IID_NULL, LOCALE_USER_DEFAULT, DISPATCH_PROPERTYGET, (DISPPARAMS *)&g_dispparamsNoArgs, &va, &exInfo, NULL)))
  10035. {
  10036. if ((va.vt == VT_I4) && (va.lVal < READYSTATE_COMPLETE))
  10037. {
  10038. lReadyState = fWindowOpen ? READYSTATE_COMPLETE : va.lVal;
  10039. fReadyStateOK = TRUE;
  10040. }
  10041. }
  10042. p_idispatch->Release();
  10043. }
  10044. if (fReadyStateOK)
  10045. {
  10046. // Check and Set-Up IPropertyNotifySink
  10047. if (SUCCEEDED(ConnectToConnectionPoint(SAFECAST(this, IPropertyNotifySink*), IID_IPropertyNotifySink, TRUE, _pole, &_dwPropNotifyCookie, NULL)))
  10048. {
  10049. fSupportsReadystate = TRUE;
  10050. _OnReadyState(lReadyState);
  10051. }
  10052. }
  10053. // If no ReadyState, we simulate it
  10054. if (!fSupportsReadystate)
  10055. {
  10056. if (fWindowOpen)
  10057. {
  10058. // Connect the property notify sink or we
  10059. // will never activate the pending view.
  10060. //
  10061. ConnectToConnectionPoint(SAFECAST(this, IPropertyNotifySink*),
  10062. IID_IPropertyNotifySink,
  10063. TRUE,
  10064. _pole,
  10065. &_dwPropNotifyCookie,
  10066. NULL);
  10067. }
  10068. _OnReadyState(READYSTATE_COMPLETE, !fWindowOpen);
  10069. }
  10070. return(fSupportsReadystate);
  10071. }
  10072. // This removes any property notify sink we set up
  10073. //
  10074. BOOL CDocObjectHost::_RemoveTransitionCapability()
  10075. {
  10076. BOOL fRet = FALSE;
  10077. if (_dwPropNotifyCookie)
  10078. {
  10079. ConnectToConnectionPoint(NULL, IID_IPropertyNotifySink, FALSE, _pole, &_dwPropNotifyCookie, NULL);
  10080. fRet = TRUE;
  10081. }
  10082. return(fRet);
  10083. }
  10084. HRESULT _GetRequestFlagFromPIB(IBinding *pib, DWORD *pdwOptions)
  10085. {
  10086. HRESULT hres = E_FAIL;
  10087. *pdwOptions = 0;
  10088. if (pib)
  10089. {
  10090. IWinInetInfo* pwinet;
  10091. hres = pib->QueryInterface(IID_IWinInetInfo, (void **)&pwinet);
  10092. if (SUCCEEDED(hres)) {
  10093. DWORD cbSize = SIZEOF(*pdwOptions);
  10094. hres = pwinet->QueryOption(INTERNET_OPTION_REQUEST_FLAGS,
  10095. (LPVOID)pdwOptions, &cbSize);
  10096. TraceMsg(TF_SHDNAVIGATE, "DOH::BSC::_HFNS() pwinet->QueryOptions hres=%x dwOptions=%x", hres, *pdwOptions);
  10097. pwinet->Release();
  10098. }
  10099. }
  10100. return hres;
  10101. }
  10102. void CDocObjectHost::_Navigate()
  10103. {
  10104. NAVMSG3(TEXT("_Navigate calling SHDVID_ACTIVATEMENOW"), 0, NULL);
  10105. if (_pmsoctBrowser)
  10106. {
  10107. VARIANT varSynch;
  10108. V_VT(&varSynch) = VT_BOOL;
  10109. V_BOOL(&varSynch) = _fDocCanNavigate ? VARIANT_TRUE : VARIANT_FALSE;
  10110. _pmsoctBrowser->Exec(&CGID_ShellDocView,
  10111. SHDVID_ACTIVATEMENOW,
  10112. NULL,
  10113. &varSynch,
  10114. NULL);
  10115. }
  10116. }
  10117. #ifndef UNIX
  10118. void CDocObjectHost::_NavigateFolder(BSTR bstrUrl)
  10119. {
  10120. // This code accesses one of IE's default behaviors which
  10121. // allows for navigation to a web folder.
  10122. // ------------------------------------------------------
  10123. Iwfolders * pWF = NULL;
  10124. IElementBehaviorFactory * pebf = NULL;
  10125. IElementBehavior * pPeer = NULL;
  10126. HWND hwndOwner = NULL;
  10127. IServiceProvider * psp = NULL;
  10128. IUnknown * punkwb = NULL;
  10129. // Make the peer factory
  10130. if ( !_psb || (FAILED(_psb->GetWindow (&hwndOwner))) ||
  10131. (FAILED(CoCreateInstance(CLSID_PeerFactory, NULL, CLSCTX_INPROC,
  10132. IID_IElementBehaviorFactory, (void **)&pebf))) ||
  10133. (FAILED(pebf->FindBehavior(L"httpFolder", NULL, NULL, &pPeer))) ||
  10134. (FAILED(pPeer->QueryInterface(IID_Iwfolders, (void **)&pWF))) ||
  10135. (FAILED(QueryService(SID_STopLevelBrowser, IID_IServiceProvider, (void **)&psp))) ||
  10136. (FAILED(psp->QueryService(SID_SContainerDispatch, IID_IUnknown, (void **)&punkwb))) )
  10137. {
  10138. WCHAR wszMessage[MAX_PATH];
  10139. WCHAR wszTitle[MAX_PATH];
  10140. MLLoadShellLangString(IDS_ERRORINTERNAL, wszMessage, ARRAYSIZE(wszMessage));
  10141. MLLoadShellLangString(IDS_NAME, wszTitle, ARRAYSIZE(wszTitle));
  10142. ULONG_PTR uCookie = 0;
  10143. SHActivateContext(&uCookie);
  10144. MessageBox(hwndOwner, wszMessage, wszTitle, MB_OK | MB_ICONERROR);
  10145. if (uCookie)
  10146. {
  10147. SHDeactivateContext(uCookie);
  10148. }
  10149. goto done;
  10150. }
  10151. // Sundown: coercion to unsigned long is valid for HWNDs
  10152. pWF->navigateNoSite(bstrUrl, NULL, PtrToUlong(hwndOwner), punkwb);
  10153. done:
  10154. if (pebf)
  10155. pebf->Release();
  10156. if (pPeer)
  10157. pPeer->Release();
  10158. if (pWF)
  10159. pWF->Release();
  10160. if (punkwb)
  10161. punkwb->Release();
  10162. if (psp)
  10163. psp->Release();
  10164. }
  10165. #endif //UNIX
  10166. void CDocObjectHost::_CancelPendingNavigation(BOOL fAsyncDownload,
  10167. BOOL fSyncReally, /* = FALSE */
  10168. BOOL fDontShowNavCancelPage, /* = FALSE */
  10169. BOOL fForceClose /* = FALSE */)
  10170. {
  10171. ASSERT(_phf);
  10172. // TODO: We need to clean up the call to this method and eliminate need for fSyncReally
  10173. //
  10174. // Passing NULL for the 4th argument (instead of passing in a
  10175. // variant like we do in the case when fAsyncDownload is TRUE) looks plain wrong!
  10176. // See how this command+argument is interpreted in CBaseBrowser2::Exec.
  10177. // It is too close to RTM (of IE5.5) now to fix this. The net result is that
  10178. // when this function is called with fAsyncDownload=FALSE, we end up posting
  10179. // ASYNCOP_CANCELPENDINGNAVIGATION, which is just what the caller does not want.
  10180. // To workaround this, I have introduced the argument fSyncReally.
  10181. // the hlframe no longer knows if the clear was a cancel or a start of navigation
  10182. // because we don't call anything tosignal a successfull navigation
  10183. if (_pmsoctBrowser)
  10184. {
  10185. TraceMsg(DM_TRACE, "DOH::_CancelPendingNavigation calling _pmsc->Exec");
  10186. if (_pwb && fDontShowNavCancelPage)
  10187. {
  10188. _pwb->SetFlags(BSF_DONTSHOWNAVCANCELPAGE, BSF_DONTSHOWNAVCANCELPAGE);
  10189. }
  10190. if (fForceClose && _fWindowOpen) // Force the browser to close
  10191. {
  10192. HideBrowser(); // Makes the browser appear to go away faster.
  10193. _pmsoctBrowser->Exec(&CGID_Explorer, SBCMDID_CANCELANDCLOSE, 0, NULL, NULL);
  10194. }
  10195. else if (fAsyncDownload)
  10196. {
  10197. VARIANT var = {0};
  10198. var.vt = VT_I4;
  10199. ASSERT(var.lVal == FALSE); // asynd download is done.
  10200. _pmsoctBrowser->Exec(&CGID_Explorer, SBCMDID_CANCELNAVIGATION, 0, &var, NULL);
  10201. }
  10202. else if (fSyncReally)
  10203. {
  10204. VARIANT var = { 0 };
  10205. var.vt = VT_I4;
  10206. var.lVal = TRUE;
  10207. _pmsoctBrowser->Exec(&CGID_Explorer, SBCMDID_CANCELNAVIGATION, 0, &var, NULL);
  10208. }
  10209. else
  10210. {
  10211. // This actually causes an async cancel
  10212. //
  10213. _pmsoctBrowser->Exec(&CGID_Explorer, SBCMDID_CANCELNAVIGATION, 0, NULL, NULL);
  10214. }
  10215. }
  10216. // Release our navigation state.
  10217. // Doing a "fSyncReally" may cause us to lose our _phf member value. Check it again.
  10218. //
  10219. if (_phf)
  10220. {
  10221. _phf->Navigate(0, NULL, NULL, (IHlink*)-1);
  10222. }
  10223. }
  10224. void CDocObjectHost::_ResetStatusBar()
  10225. {
  10226. _SetStatusText(TEXT(""));
  10227. if (_psb)
  10228. _psb->SendControlMsg(FCW_STATUS, SB_SETICON, STATUS_PANE_NAVIGATION,
  10229. (LPARAM)g_ahiconState[IDI_STATE_NORMAL-IDI_STATE_FIRST], NULL);
  10230. return;
  10231. }
  10232. void CDocObjectHost::_DoAsyncNavigation(LPCTSTR pszURL)
  10233. {
  10234. if (_pmsoctBrowser) {
  10235. VARIANT vararg = {0};
  10236. vararg.vt = VT_BSTR;
  10237. vararg.bstrVal = SysAllocStringT(pszURL);
  10238. if (vararg.bstrVal)
  10239. {
  10240. TraceMsg(DM_TRACE, "DOH::_DoAsyncNavigation calling _pmsc->Exec");
  10241. _pmsoctBrowser->Exec(&CGID_Explorer, SBCMDID_ASYNCNAVIGATION, 0, &vararg, NULL);
  10242. VariantClear(&vararg);
  10243. }
  10244. }
  10245. }
  10246. // note: szError is never used, so don't waste time setting it
  10247. UINT SHIEErrorMsgBox(IShellBrowser* psb,
  10248. HWND hwndOwner, HRESULT hrError, LPCWSTR szError, LPCTSTR pszURLparam,
  10249. UINT idResource, UINT wFlags)
  10250. {
  10251. UINT uRet = IDCANCEL;
  10252. TCHAR szMsg[MAX_PATH];
  10253. LPCTSTR pszURL = TEXT("");
  10254. HWND hwndParent = hwndOwner;
  10255. IShellBrowser *psbParent = NULL;
  10256. // if a URL was specified, use it; otherwise use empty string
  10257. if (pszURLparam)
  10258. pszURL = pszURLparam;
  10259. //
  10260. // NOTES: This table of error code will be mapped to (IDS_ERRMSG_FIRST +
  10261. // offset) and we MLLoadString it.
  10262. //
  10263. const static c_ahres[] = {
  10264. HRESULT_FROM_WIN32(ERROR_INTERNET_INVALID_URL),
  10265. HRESULT_FROM_WIN32(ERROR_INTERNET_NAME_NOT_RESOLVED),
  10266. INET_E_UNKNOWN_PROTOCOL,
  10267. INET_E_REDIRECT_FAILED,
  10268. INET_E_DATA_NOT_AVAILABLE,
  10269. };
  10270. for (int i=0; i<ARRAYSIZE(c_ahres); i++) {
  10271. if (c_ahres[i]==hrError) {
  10272. MLLoadString(IDS_ERRMSG_FIRST+i, szMsg, ARRAYSIZE(szMsg));
  10273. break;
  10274. }
  10275. }
  10276. if (i >= ARRAYSIZE(c_ahres))
  10277. {
  10278. // Default message if FormatMessage doesn't recognize dwLastError
  10279. MLLoadString(IDS_UNDEFINEDERR, szMsg, ARRAYSIZE(szMsg));
  10280. if (hrError >= HRESULT_FROM_WIN32(INTERNET_ERROR_BASE)
  10281. && hrError <= HRESULT_FROM_WIN32(INTERNET_ERROR_LAST))
  10282. {
  10283. HMODULE hmod = GetModuleHandle(TEXT("WININET"));
  10284. ASSERT(hmod);
  10285. FormatMessage(FORMAT_MESSAGE_FROM_HMODULE, (LPCVOID)hmod, HRESULT_CODE(hrError), 0L,
  10286. szMsg, ARRAYSIZE(szMsg), NULL);
  10287. } else {
  10288. // See if one of the system components has an error message
  10289. // for this error. If not, szMsg will retain our default
  10290. // message to handle this.
  10291. FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, NULL, hrError, 0L,
  10292. szMsg, ARRAYSIZE(szMsg), NULL);
  10293. }
  10294. }
  10295. psbParent = psb;
  10296. if (psbParent)
  10297. {
  10298. psbParent->AddRef();
  10299. }
  10300. // Here we make an heroic effort to find a visible window to run the dialog against
  10301. // If we can't, then we bail, to avoid weird UI effect (particularly when the frametop
  10302. // browser is in kiosk mode
  10303. if (!IsWindowVisible(hwndParent))
  10304. {
  10305. if (NULL == psb || FAILED(psb->GetWindow(&hwndParent)) || !IsWindowVisible(hwndParent))
  10306. {
  10307. hwndParent = NULL;
  10308. ATOMICRELEASE(psbParent);
  10309. }
  10310. if (NULL == hwndParent && psb)
  10311. {
  10312. IUnknown_QueryService(psb, SID_STopFrameBrowser, IID_IShellBrowser, (void **)&psbParent);
  10313. if (NULL == psbParent || FAILED(psbParent->GetWindow(&hwndParent)) || !IsWindowVisible(hwndParent))
  10314. {
  10315. hwndParent = NULL;
  10316. }
  10317. }
  10318. }
  10319. if (hwndParent)
  10320. {
  10321. if (psbParent) {
  10322. psbParent->EnableModelessSB(FALSE);
  10323. }
  10324. uRet = MLShellMessageBox(hwndParent,
  10325. MAKEINTRESOURCE(idResource),
  10326. MAKEINTRESOURCE(IDS_TITLE),
  10327. wFlags, pszURL,szMsg);
  10328. if (psbParent) {
  10329. psbParent->EnableModelessSB(TRUE);
  10330. }
  10331. }
  10332. if (psbParent)
  10333. {
  10334. UINT cRef = psbParent->Release();
  10335. AssertMsg(cRef>0, TEXT("IE_ErrorMsgBox psb->Release returned 0."));
  10336. }
  10337. return uRet;
  10338. }
  10339. //
  10340. // See if the URL is of a type that we should
  10341. // ShellExecute()
  10342. //
  10343. HRESULT IsProtocolRegistered(LPCTSTR pcszProtocol);
  10344. BOOL ShouldShellExecURL(LPTSTR pszURL)
  10345. {
  10346. BOOL fRet = FALSE;
  10347. PARSEDURL pu = {sizeof(pu)};
  10348. HRESULT hr = ParseURL(pszURL, &pu);
  10349. if (SUCCEEDED(hr) && pu.nScheme != URL_SCHEME_SHELL)
  10350. {
  10351. TCHAR sz[MAX_PATH];
  10352. hr = StringCchCopyN(sz, ARRAYSIZE(sz), pu.pszProtocol, pu.cchProtocol);
  10353. if (SUCCEEDED(hr))
  10354. {
  10355. hr = IsProtocolRegistered(sz);
  10356. if (SUCCEEDED(hr))
  10357. {
  10358. //
  10359. // HACKHACK - telnet.exe will fault on buffer overrun
  10360. // if the url is > 230. we special case here.
  10361. //
  10362. if (lstrlen(pszURL) <= 230 ||
  10363. (StrCmpI(sz, TEXT("telnet")) &&
  10364. StrCmpI(sz, TEXT("rlogin")) &&
  10365. StrCmpI(sz, TEXT("tn3270"))
  10366. )
  10367. )
  10368. {
  10369. fRet = TRUE;
  10370. }
  10371. }
  10372. }
  10373. }
  10374. return fRet;
  10375. }
  10376. //========================================================================
  10377. // class CShdAdviseSink
  10378. //========================================================================
  10379. class CShdAdviseSink : public IAdviseSink
  10380. {
  10381. public:
  10382. // *** IUnknown methods ***
  10383. virtual STDMETHODIMP QueryInterface(REFIID riid, void ** ppvObj);
  10384. virtual STDMETHODIMP_(ULONG) AddRef(void) ;
  10385. virtual STDMETHODIMP_(ULONG) Release(void);
  10386. // *** IAdviseSink methods ***
  10387. virtual void __stdcall OnDataChange(
  10388. FORMATETC *pFormatetc,
  10389. STGMEDIUM *pStgmed);
  10390. virtual void __stdcall OnViewChange(
  10391. DWORD dwAspect,
  10392. LONG lindex);
  10393. virtual void __stdcall OnRename(
  10394. IMoniker *pmk);
  10395. virtual void __stdcall OnSave( void);
  10396. virtual void __stdcall OnClose( void);
  10397. CShdAdviseSink(IBrowserService* pwb, IOleObject* pole);
  10398. ~CShdAdviseSink();
  10399. protected:
  10400. UINT _cRef;
  10401. IOleObject* _pole;
  10402. DWORD _dwConnection;
  10403. };
  10404. //
  10405. // We'd better maintain the list of those CShdAdviseSink
  10406. // per-thread so that we don't leak all those oleobjects when
  10407. // the thread is terminated before those objects are closed.
  10408. //
  10409. void CShdAdviseSink_Advise(IBrowserService* pwb, IOleObject* pole)
  10410. {
  10411. IAdviseSink* padv = new CShdAdviseSink(pwb, pole);
  10412. // If pole->Advise succeeds, it will addreff to IAdviseSink.
  10413. if (padv != NULL)
  10414. {
  10415. padv->Release();
  10416. }
  10417. }
  10418. CShdAdviseSink::CShdAdviseSink(IBrowserService* pwb, IOleObject* pole)
  10419. : _cRef(1)
  10420. {
  10421. ASSERT(pole);
  10422. TraceMsg(DM_ADVISE, "CShdAdviseSink(%x) being constructed", this);
  10423. HRESULT hres = pole->Advise(this, &_dwConnection);
  10424. if (SUCCEEDED(hres)) {
  10425. _pole = pole;
  10426. pole->AddRef();
  10427. TraceMsg(DM_ADVISE, "CShdAdviseSink(%x) called pole->Advise. new _cRef=%d (%x)", this, _cRef, _dwConnection);
  10428. }
  10429. }
  10430. CShdAdviseSink::~CShdAdviseSink()
  10431. {
  10432. TraceMsg(DM_ADVISE, "CShdAdviseSink(%x) being destroyed", this);
  10433. ATOMICRELEASE(_pole);
  10434. }
  10435. ULONG CShdAdviseSink::AddRef()
  10436. {
  10437. _cRef++;
  10438. TraceMsg(TF_SHDREF, "CShdAdviseSink(%x)::AddRef called, new _cRef=%d", this, _cRef);
  10439. return _cRef;
  10440. }
  10441. ULONG CShdAdviseSink::Release()
  10442. {
  10443. _cRef--;
  10444. TraceMsg(TF_SHDREF, "CShdAdviseSink(%x)::Release called, new _cRef=%d", this, _cRef);
  10445. if (_cRef > 0)
  10446. return _cRef;
  10447. delete this;
  10448. return 0;
  10449. }
  10450. HRESULT CShdAdviseSink::QueryInterface(REFIID riid, void ** ppvObj)
  10451. {
  10452. if (IsEqualIID(riid, IID_IAdviseSink) ||
  10453. IsEqualIID(riid, IID_IUnknown))
  10454. {
  10455. *ppvObj = (IAdviseSink*)this;
  10456. }
  10457. else
  10458. {
  10459. *ppvObj = NULL;
  10460. return E_NOINTERFACE;
  10461. }
  10462. AddRef();
  10463. return NOERROR;
  10464. }
  10465. void CShdAdviseSink::OnDataChange(
  10466. FORMATETC *pFormatetc,
  10467. STGMEDIUM *pStgmed)
  10468. {
  10469. }
  10470. void CShdAdviseSink::OnViewChange(
  10471. DWORD dwAspect,
  10472. LONG lindex)
  10473. {
  10474. }
  10475. void CShdAdviseSink::OnRename(
  10476. IMoniker *pmk)
  10477. {
  10478. }
  10479. void CShdAdviseSink::OnSave( void)
  10480. {
  10481. }
  10482. void CShdAdviseSink::OnClose( void)
  10483. {
  10484. TraceMsg(DM_ADVISE, "CShdAdviseSink(%x)::OnClose called. Calling Unadvise. _cRef=%d", this, _cRef);
  10485. HRESULT hres;
  10486. AddRef();
  10487. ASSERT(_pole);
  10488. if (_pole) // paranoia
  10489. {
  10490. hres = _pole->Unadvise(_dwConnection);
  10491. ATOMICRELEASE(_pole);
  10492. TraceMsg(DM_ADVISE, "CShdAdviseSink(%x)::OnClose. Called Unadvise(%x). new _cRef=%d", this, hres, _cRef);
  10493. }
  10494. Release();
  10495. }
  10496. /// adding property sheet pages
  10497. HRESULT CDocObjectHost::AddPages(LPFNADDPROPSHEETPAGE lpfnAddPage, LPARAM lParam)
  10498. {
  10499. HRESULT hres = S_OK;
  10500. IShellPropSheetExt *pspse;
  10501. /*
  10502. * Create a property sheet page for required page, including imported File
  10503. * Types property sheet.
  10504. */
  10505. // add stuff that the docobj itself has.
  10506. if (_pole)
  10507. {
  10508. if (SUCCEEDED(_pole->QueryInterface(IID_IShellPropSheetExt, (void **)&pspse)))
  10509. {
  10510. hres = pspse->AddPages(lpfnAddPage, lParam);
  10511. pspse->Release();
  10512. }
  10513. else
  10514. {
  10515. // Some docobjects don't know about IShellPropSheetExt (ie, Visual Basic),
  10516. // so do it ourselves.
  10517. if (NULL == _hinstInetCpl)
  10518. _hinstInetCpl = LoadLibrary(TEXT("inetcpl.cpl"));
  10519. if (_hinstInetCpl)
  10520. {
  10521. PFNADDINTERNETPROPERTYSHEETSEX pfnAddSheet = (PFNADDINTERNETPROPERTYSHEETSEX)GetProcAddress(_hinstInetCpl, STR_ADDINTERNETPROPSHEETSEX);
  10522. if (pfnAddSheet)
  10523. {
  10524. IEPROPPAGEINFO iepi = {0};
  10525. // we just want the security page.
  10526. iepi.cbSize = sizeof(iepi);
  10527. iepi.dwFlags = (DWORD)-1; // all pages
  10528. hres = pfnAddSheet(lpfnAddPage, lParam, 0, 0, &iepi);
  10529. }
  10530. // Don't FreeLibrary here, otherwise PropertyPage will GP-fault!
  10531. }
  10532. }
  10533. }
  10534. return hres;
  10535. }
  10536. //==========================================================================
  10537. // IDocHostUIHandler implementation
  10538. //==========================================================================
  10539. HRESULT CDocObjectHost::TranslateAccelerator(LPMSG lpMsg, const GUID *pguidCmdGroup, DWORD nCmdID)
  10540. {
  10541. if (_pWebOCUIHandler)
  10542. return _pWebOCUIHandler->TranslateAccelerator(lpMsg, pguidCmdGroup, nCmdID);
  10543. return _dhUIHandler.TranslateAccelerator(lpMsg, pguidCmdGroup, nCmdID);
  10544. }
  10545. HRESULT CDocObjectHost::GetDropTarget(IDropTarget *pDropTarget, IDropTarget **ppDropTarget)
  10546. {
  10547. // REVIEW: Does this apply anymore?
  10548. TraceMsg(DM_DOCHOSTUIHANDLER, "CDOH::GetDropTarget called");
  10549. HRESULT hres;
  10550. if (_pWebOCUIHandler)
  10551. {
  10552. hres = _pWebOCUIHandler->GetDropTarget(pDropTarget, ppDropTarget);
  10553. if (SUCCEEDED(hres))
  10554. return hres;
  10555. }
  10556. if (pDropTarget)
  10557. {
  10558. hres = S_OK;
  10559. IDropTarget *pdtFrame;
  10560. IDropTarget *pdt3;
  10561. IDropTarget *pdtBlocking;
  10562. QueryService(SID_STopFrameBrowser, IID_IDropTarget, (void **)&pdtFrame);
  10563. // hack: this is because we need to look all the way through to top parents for a containing drop target
  10564. // what we really need is a per dataobject drop target
  10565. //
  10566. // this is not required to be obtained
  10567. QueryService(SID_ITopViewHost, IID_IDropTarget, (void **)&pdt3);
  10568. if (IsSameObject(pdt3, pdtFrame)) {
  10569. ATOMICRELEASE(pdt3);
  10570. }
  10571. // allow constrained browser bands like Search to prevent drop
  10572. QueryService(SID_SDropBlocker, IID_IUnknown, (void **)&pdtBlocking);
  10573. if (pdtBlocking)
  10574. {
  10575. ATOMICRELEASE(pdt3);
  10576. pDropTarget = NULL;
  10577. }
  10578. if (pdtFrame)
  10579. {
  10580. *ppDropTarget = DropTargetWrap_CreateInstance(pDropTarget, pdtFrame, _hwnd, pdt3);
  10581. if (!*ppDropTarget)
  10582. hres = E_OUTOFMEMORY;
  10583. TraceMsg(DM_DOCHOSTUIHANDLER, "CDOH::GetDropTarget returning S_OK");
  10584. ASSERT(hres == S_OK);
  10585. pdtFrame->Release();
  10586. }
  10587. else
  10588. {
  10589. ASSERT(0);
  10590. hres = E_UNEXPECTED;
  10591. }
  10592. ATOMICRELEASE(pdtBlocking);
  10593. ATOMICRELEASE(pdt3);
  10594. }
  10595. else
  10596. {
  10597. hres = E_INVALIDARG;
  10598. }
  10599. return hres;
  10600. }
  10601. HRESULT CDocObjectHost::ShowUI(
  10602. DWORD dwID, IOleInPlaceActiveObject *pActiveObject,
  10603. IOleCommandTarget *pCommandTarget, IOleInPlaceFrame *pFrame,
  10604. IOleInPlaceUIWindow *pDoc)
  10605. {
  10606. if (_pWebOCUIHandler)
  10607. return _pWebOCUIHandler->ShowUI(dwID, pActiveObject, pCommandTarget, pFrame, pDoc);
  10608. if (_dwAppHack & BROWSERFLAG_MSHTML) // Who else will call on this interface?
  10609. {
  10610. if (_pmsoctBrowser)
  10611. {
  10612. TraceMsg(DM_PREMERGEDMENU, "DOH::ShowUI called this=%x pcmd=%x",
  10613. this,pCommandTarget);
  10614. VARIANT var = { 0 };
  10615. HRESULT hresT=_pmsoctBrowser->Exec(&CGID_Explorer, SBCMDID_SETMERGEDWEBMENU, 0, NULL, &var);
  10616. if (SUCCEEDED(hresT))
  10617. {
  10618. if (_pcmdMergedMenu)
  10619. {
  10620. // Tell Trident to stop calling us twice
  10621. TraceMsg(DM_WARNING, "DOH::ShowUI called twice! "
  10622. "this=%x pcmdCur=%x pcmdNew=%x",
  10623. this, _pcmdMergedMenu, pCommandTarget);
  10624. _pcmdMergedMenu->Release();
  10625. }
  10626. _pcmdMergedMenu = pCommandTarget;
  10627. _pcmdMergedMenu->AddRef();
  10628. ASSERT(var.vt == VT_INT_PTR);
  10629. _hmenuCur = (HMENU)var.byref;
  10630. DEBUG_CODE( _DumpMenus(TEXT("after ShowUI"), TRUE); )
  10631. return S_OK;
  10632. }
  10633. }
  10634. }
  10635. return S_FALSE;
  10636. }
  10637. HRESULT CDocObjectHost::HideUI(void)
  10638. {
  10639. if (_pWebOCUIHandler)
  10640. return _pWebOCUIHandler->HideUI();
  10641. if (_pcmdMergedMenu) {
  10642. _pcmdMergedMenu->Release();
  10643. _pcmdMergedMenu = NULL;
  10644. }
  10645. return S_FALSE;
  10646. }
  10647. HRESULT CDocObjectHost::GetHostInfo(DOCHOSTUIINFO *pInfo)
  10648. {
  10649. IServiceProvider * psp = NULL;
  10650. IWebBrowser2 * pwb = NULL;
  10651. VARIANT_BOOL b = VARIANT_FALSE;
  10652. DWORD dwFlagsWebOC = 0;
  10653. HRESULT hr;
  10654. if (_pWebOCUIHandler
  10655. && SUCCEEDED(_pWebOCUIHandler->GetHostInfo(pInfo))
  10656. )
  10657. {
  10658. dwFlagsWebOC = pInfo->dwFlags;
  10659. }
  10660. _dhUIHandler.GetHostInfo(pInfo);
  10661. // Merge flags
  10662. //
  10663. pInfo->dwFlags |= dwFlagsWebOC;
  10664. // Add the local machine flag, if we're in iexplore.exe or explorer.exe.
  10665. if (IsInternetExplorerApp())
  10666. pInfo->dwFlags |= DOCHOSTUIFLAG_LOCAL_MACHINE_ACCESS_CHECK;
  10667. // Get the top level browser
  10668. //
  10669. hr = QueryService(SID_STopLevelBrowser, IID_PPV_ARG(IServiceProvider, &psp));
  10670. if (hr)
  10671. goto Cleanup;
  10672. // Get the IWebBrowser2 object/interface
  10673. //
  10674. hr = psp->QueryService(SID_SContainerDispatch, IID_IWebBrowser2, (void **)&pwb);
  10675. if (hr)
  10676. goto Cleanup;
  10677. // Tell the browser what our dochost flags are
  10678. IEFrameAuto *pIEFrameAuto;
  10679. if (SUCCEEDED(pwb->QueryInterface(IID_PPV_ARG(IEFrameAuto, &pIEFrameAuto))))
  10680. {
  10681. pIEFrameAuto->SetDocHostFlags(pInfo->dwFlags);
  10682. pIEFrameAuto->Release();
  10683. }
  10684. // Is the browser in Theater Mode?
  10685. //
  10686. hr = pwb->get_TheaterMode(&b);
  10687. if (hr)
  10688. goto Cleanup;
  10689. // If so, turn on flat scrollbars.
  10690. //
  10691. if (b == VARIANT_TRUE)
  10692. pInfo->dwFlags |= DOCHOSTUIFLAG_FLAT_SCROLLBAR;
  10693. Cleanup:
  10694. ATOMICRELEASE(psp);
  10695. ATOMICRELEASE(pwb);
  10696. return S_OK;
  10697. }
  10698. HRESULT CDocObjectHost::ShowContextMenu(DWORD dwID, POINT *ppt, IUnknown *pcmdtReserved, IDispatch *pdispReserved)
  10699. {
  10700. HRESULT hr;
  10701. OLECMD rgcmd = { IDM_BROWSEMODE, 0 };
  10702. // If we're in the WebOC and it has a IDocHostUIHandler, use it.
  10703. //
  10704. if (_pWebOCUIHandler)
  10705. {
  10706. hr = _pWebOCUIHandler->ShowContextMenu(dwID, ppt, pcmdtReserved, pdispReserved);
  10707. if (hr == S_OK)
  10708. goto Cleanup;
  10709. }
  10710. // Find out if the DocObject is in Edit mode
  10711. // Don't need apphack here as only Trident responds to CGID_MSHTML
  10712. //
  10713. hr = IUnknown_QueryStatus(pcmdtReserved, &CGID_MSHTML, 1, &rgcmd, NULL);
  10714. if ( hr == S_OK
  10715. && !(rgcmd.cmdf & OLECMDF_LATCHED)) // if not LATCHED means we're in edit mode.
  10716. {
  10717. hr = S_FALSE;
  10718. }
  10719. else
  10720. {
  10721. hr = _dhUIHandler.ShowContextMenu(dwID, ppt, pcmdtReserved, pdispReserved);
  10722. }
  10723. Cleanup:
  10724. return hr;
  10725. }
  10726. HRESULT CDocObjectHost::UpdateUI(void)
  10727. {
  10728. if (_pWebOCUIHandler)
  10729. return _pWebOCUIHandler->UpdateUI();
  10730. return _dhUIHandler.UpdateUI();
  10731. }
  10732. HRESULT CDocObjectHost::EnableModeless(BOOL fEnable)
  10733. {
  10734. if (_pWebOCUIHandler)
  10735. return _pWebOCUIHandler->EnableModeless(fEnable);
  10736. return _dhUIHandler.EnableModeless(fEnable);
  10737. }
  10738. HRESULT CDocObjectHost::OnDocWindowActivate(BOOL fActivate)
  10739. {
  10740. if (_pWebOCUIHandler)
  10741. return _pWebOCUIHandler->OnDocWindowActivate(fActivate);
  10742. return _dhUIHandler.OnDocWindowActivate(fActivate);
  10743. }
  10744. HRESULT CDocObjectHost::OnFrameWindowActivate(BOOL fActivate)
  10745. {
  10746. if (_pWebOCUIHandler)
  10747. return _pWebOCUIHandler->OnFrameWindowActivate(fActivate);
  10748. return _dhUIHandler.OnFrameWindowActivate(fActivate);
  10749. }
  10750. HRESULT CDocObjectHost::ResizeBorder( LPCRECT prcBorder, IOleInPlaceUIWindow *pUIWindow, BOOL fRameWindow)
  10751. {
  10752. if (_pWebOCUIHandler)
  10753. return _pWebOCUIHandler->ResizeBorder(prcBorder, pUIWindow, fRameWindow);
  10754. return _dhUIHandler.ResizeBorder(prcBorder, pUIWindow, fRameWindow);
  10755. }
  10756. HRESULT CDocObjectHost::GetOptionKeyPath(BSTR *pbstrKey, DWORD dw)
  10757. {
  10758. if (_pWebOCUIHandler)
  10759. return _pWebOCUIHandler->GetOptionKeyPath(pbstrKey, dw);
  10760. return _dhUIHandler.GetOptionKeyPath(pbstrKey, dw);
  10761. }
  10762. HRESULT CDocObjectHost::GetExternal(IDispatch **ppDisp)
  10763. {
  10764. if (_pWebOCUIHandler)
  10765. return _pWebOCUIHandler->GetExternal(ppDisp);
  10766. return _dhUIHandler.GetExternal(ppDisp);
  10767. }
  10768. HRESULT CDocObjectHost::TranslateUrl(DWORD dwTranslate, OLECHAR *pchURLIn, OLECHAR **ppchURLOut)
  10769. {
  10770. if (_pWebOCUIHandler)
  10771. return _pWebOCUIHandler->TranslateUrl(dwTranslate, pchURLIn, ppchURLOut);
  10772. return _dhUIHandler.TranslateUrl(dwTranslate, pchURLIn, ppchURLOut);
  10773. }
  10774. HRESULT CDocObjectHost::FilterDataObject(IDataObject *pDO, IDataObject **ppDORet)
  10775. {
  10776. if (_pWebOCUIHandler)
  10777. return _pWebOCUIHandler->FilterDataObject(pDO, ppDORet);
  10778. return _dhUIHandler.FilterDataObject(pDO, ppDORet);
  10779. }
  10780. HRESULT CDocObjectHost::GetOverrideKeyPath(LPOLESTR *pchKey, DWORD dw)
  10781. {
  10782. if (_pWebOCUIHandler2)
  10783. return _pWebOCUIHandler2->GetOverrideKeyPath(pchKey, dw);
  10784. return _dhUIHandler.GetOverrideKeyPath(pchKey, dw);
  10785. }
  10786. HRESULT CDocObjectHost::ShowMessage(HWND hwnd, LPOLESTR lpstrText, LPOLESTR lpstrCaption,
  10787. DWORD dwType, LPOLESTR lpstrHelpFile, DWORD dwHelpContext, LRESULT __RPC_FAR *plResult)
  10788. {
  10789. if (_pWebOCShowUI)
  10790. {
  10791. return _pWebOCShowUI->ShowMessage(hwnd, lpstrText, lpstrCaption, dwType,
  10792. lpstrHelpFile, dwHelpContext, plResult);
  10793. }
  10794. return E_FAIL;
  10795. }
  10796. HRESULT CDocObjectHost::ShowHelp(HWND hwnd, LPOLESTR pszHelpFile, UINT uCommand, DWORD dwData,
  10797. POINT ptMouse, IDispatch __RPC_FAR *pDispatchObjectHit)
  10798. {
  10799. if (_pWebOCShowUI)
  10800. {
  10801. return _pWebOCShowUI->ShowHelp(hwnd, pszHelpFile, uCommand, dwData, ptMouse,
  10802. pDispatchObjectHit);
  10803. }
  10804. return E_FAIL;
  10805. }
  10806. void
  10807. CDocObjectHost::HideBrowser() const
  10808. {
  10809. if (_psp && _fWindowOpen && !(_dwAppHack & BROWSERFLAG_DONTAUTOCLOSE))
  10810. {
  10811. IWebBrowser2 * pWebBrowser;
  10812. HRESULT hres = _psp->QueryService(SID_SWebBrowserApp,
  10813. IID_PPV_ARG(IWebBrowser2, &pWebBrowser));
  10814. if (SUCCEEDED(hres))
  10815. {
  10816. pWebBrowser->put_Visible(VARIANT_FALSE);
  10817. pWebBrowser->Release();
  10818. }
  10819. }
  10820. }
  10821. //
  10822. // support for script error caching and status bar notification
  10823. //
  10824. void
  10825. CDocObjectHost::_ScriptErr_Dlg(BOOL fOverridePerErrorMode)
  10826. {
  10827. // we can get reentered through the message pump ShowHTMLDialog runs
  10828. // therefore we might already have a dialog open when a second dialog
  10829. // is requested
  10830. if (_fScriptErrDlgOpen)
  10831. {
  10832. // a dialog is already open lower in the callstack
  10833. // request an up-to-date dialog be shown
  10834. // we have to do this because otherwise we might
  10835. // be in per-error-mode and miss some errors which
  10836. // arrived while the dialog lower in the callstack
  10837. // was open. note that we only do this if we're set
  10838. // to show notifications for every error.
  10839. _fShowScriptErrDlgAgain = SHRegGetBoolUSValue(szRegKey_SMIEM,
  10840. szRegVal_ErrDlgPerErr,
  10841. FALSE,
  10842. TRUE);
  10843. }
  10844. else
  10845. {
  10846. _fScriptErrDlgOpen = TRUE;
  10847. // keep showing dialogs as long as someone farther up the
  10848. // call stack keeps requesting them
  10849. do
  10850. {
  10851. BOOL fShowDlg;
  10852. _fShowScriptErrDlgAgain = FALSE;
  10853. // if the user double clicked on the status bar, then we
  10854. // show the dialog regardless of per-error-mode settings
  10855. if (fOverridePerErrorMode)
  10856. {
  10857. fShowDlg = TRUE;
  10858. // because of other script errors hitting the
  10859. // _fScriptErrDlgOpen code above, we can arrive
  10860. // here multiple times. The first time we show a
  10861. // dialog can be because the user requested it,
  10862. // but all subsequent times must be because we're
  10863. // in "show every error" mode.
  10864. fOverridePerErrorMode = FALSE;
  10865. }
  10866. else
  10867. {
  10868. fShowDlg = SHRegGetBoolUSValue(szRegKey_SMIEM,
  10869. szRegVal_ErrDlgPerErr,
  10870. FALSE,
  10871. TRUE);
  10872. }
  10873. if (fShowDlg)
  10874. {
  10875. HRESULT hr;
  10876. TCHAR szResURL[MAX_URL_STRING];
  10877. hr = MLBuildResURLWrap(TEXT("shdoclc.dll"),
  10878. HINST_THISDLL,
  10879. ML_CROSSCODEPAGE,
  10880. TEXT("ieerror.dlg"),
  10881. szResURL,
  10882. ARRAYSIZE(szResURL),
  10883. TEXT("shdocvw.dll"));
  10884. if (SUCCEEDED(hr))
  10885. {
  10886. IMoniker * pmk;
  10887. HWND hwnd;
  10888. hr = CreateURLMoniker(NULL, szResURL, &pmk);
  10889. if (SUCCEEDED(hr))
  10890. {
  10891. VARIANT varErrorCache;
  10892. V_VT(&varErrorCache) = VT_DISPATCH;
  10893. V_DISPATCH(&varErrorCache) = _pScriptErrList;
  10894. GetWindow(&hwnd);
  10895. ShowHTMLDialog(hwnd, pmk, &varErrorCache, L"help:no", NULL);
  10896. ATOMICRELEASE(pmk);
  10897. }
  10898. }
  10899. }
  10900. } while (_fShowScriptErrDlgAgain);
  10901. _fScriptErrDlgOpen = FALSE;
  10902. }
  10903. }
  10904. HRESULT
  10905. CDocObjectHost::_ScriptErr_CacheInfo(VARIANTARG *pvarIn)
  10906. {
  10907. IHTMLDocument2 * pOmDoc;
  10908. IHTMLWindow2 * pOmWindow;
  10909. IHTMLEventObj * pEventObj;
  10910. HRESULT hr;
  10911. TCHAR * apchNames[] =
  10912. { TEXT("errorLine"),
  10913. TEXT("errorCharacter"),
  10914. TEXT("errorCode"),
  10915. TEXT("errorMessage"),
  10916. TEXT("errorUrl")
  10917. };
  10918. DISPID aDispid[ARRAYSIZE(apchNames)];
  10919. VARIANT varOut[ARRAYSIZE(apchNames)];
  10920. int i;
  10921. pOmDoc = NULL;
  10922. pOmWindow = NULL;
  10923. pEventObj = NULL;
  10924. // load the script error object
  10925. hr = V_UNKNOWN(pvarIn)->QueryInterface(IID_IHTMLDocument2, (void **) &pOmDoc);
  10926. if (FAILED(hr))
  10927. {
  10928. return hr;
  10929. }
  10930. hr = pOmDoc->get_parentWindow(&pOmWindow);
  10931. ATOMICRELEASE(pOmDoc);
  10932. if (FAILED(hr))
  10933. {
  10934. return hr;
  10935. }
  10936. hr = pOmWindow->get_event(&pEventObj);
  10937. ATOMICRELEASE(pOmWindow);
  10938. if (FAILED(hr))
  10939. {
  10940. return hr;
  10941. }
  10942. //
  10943. // copy the interesting data out of the event object
  10944. //
  10945. for (i = 0; i < ARRAYSIZE(apchNames); i++)
  10946. {
  10947. DISPPARAMS params;
  10948. // get the property's dispid
  10949. hr = pEventObj->GetIDsOfNames(IID_NULL, &apchNames[i], 1, LOCALE_SYSTEM_DEFAULT, &aDispid[i]);
  10950. if (hr != S_OK)
  10951. {
  10952. ATOMICRELEASE(pEventObj);
  10953. return hr;
  10954. }
  10955. params.cArgs = 0;
  10956. params.cNamedArgs = 0;
  10957. hr = pEventObj->Invoke(aDispid[i], IID_NULL, LOCALE_SYSTEM_DEFAULT, DISPATCH_PROPERTYGET, &params, &varOut[i], NULL, NULL);
  10958. if (hr != S_OK)
  10959. {
  10960. ATOMICRELEASE(pEventObj);
  10961. return hr;
  10962. }
  10963. }
  10964. ATOMICRELEASE(pEventObj);
  10965. ASSERT(V_VT(&varOut[0]) == VT_I4);
  10966. ASSERT(V_VT(&varOut[1]) == VT_I4);
  10967. ASSERT(V_VT(&varOut[2]) == VT_I4);
  10968. ASSERT(V_VT(&varOut[3]) == VT_BSTR);
  10969. ASSERT(V_VT(&varOut[4]) == VT_BSTR);
  10970. ASSERT(ARRAYSIZE(apchNames) == 5);
  10971. hr = _pScriptErrList->AddNewErrorInfo(V_I4(&varOut[0]), // line
  10972. V_I4(&varOut[1]), // char
  10973. V_I4(&varOut[2]), // code
  10974. V_BSTR(&varOut[3]), // message
  10975. V_BSTR(&varOut[4])); // url
  10976. return hr;
  10977. }
  10978. //
  10979. // CScriptErrorList manages an array of _CScriptErrInfo objects
  10980. // the script error handler dialogs access this information
  10981. // when requested by the user
  10982. //
  10983. CScriptErrorList::CScriptErrorList() :
  10984. CImpIDispatch(LIBID_SHDocVw, 1, 1, IID_IScriptErrorList)
  10985. {
  10986. ASSERT(_lDispIndex == 0);
  10987. _ulRefCount = 1;
  10988. _hdpa = DPA_Create(4);
  10989. }
  10990. CScriptErrorList::~CScriptErrorList()
  10991. {
  10992. if (_hdpa != NULL)
  10993. {
  10994. ClearErrorList();
  10995. DPA_Destroy(_hdpa);
  10996. _hdpa = NULL;
  10997. }
  10998. }
  10999. HRESULT
  11000. CScriptErrorList::AddNewErrorInfo(LONG lLine,
  11001. LONG lChar,
  11002. LONG lCode,
  11003. BSTR strMsg,
  11004. BSTR strUrl)
  11005. {
  11006. HRESULT hr;
  11007. _CScriptErrInfo * pNewData;
  11008. if (strMsg == NULL || strUrl == NULL)
  11009. {
  11010. return E_INVALIDARG;
  11011. }
  11012. pNewData = new _CScriptErrInfo;
  11013. if (pNewData != NULL)
  11014. {
  11015. hr = pNewData->Init(lLine, lChar, lCode, strMsg, strUrl);
  11016. if (SUCCEEDED(hr))
  11017. {
  11018. if (_hdpa != NULL)
  11019. {
  11020. DPA_AppendPtr(_hdpa, (LPVOID)pNewData);
  11021. _lDispIndex = DPA_GetPtrCount(_hdpa)-1;
  11022. }
  11023. else
  11024. {
  11025. delete pNewData;
  11026. hr = E_FAIL;
  11027. }
  11028. }
  11029. else
  11030. {
  11031. delete pNewData;
  11032. }
  11033. }
  11034. else
  11035. {
  11036. hr = E_OUTOFMEMORY;
  11037. }
  11038. return hr;
  11039. }
  11040. void
  11041. CScriptErrorList::ClearErrorList()
  11042. {
  11043. if (_hdpa != NULL)
  11044. {
  11045. int iDel;
  11046. int cPtr;
  11047. cPtr = DPA_GetPtrCount(_hdpa);
  11048. // delete from end to beginning to avoid unnecessary packing
  11049. for (iDel = cPtr-1; iDel >= 0; iDel--)
  11050. {
  11051. delete ((_CScriptErrInfo *)DPA_GetPtr(_hdpa, iDel));
  11052. DPA_DeletePtr(_hdpa, iDel);
  11053. }
  11054. _lDispIndex = 0;
  11055. }
  11056. }
  11057. STDMETHODIMP
  11058. CScriptErrorList::QueryInterface(REFIID iid, void ** ppObj)
  11059. {
  11060. ASSERT(ppObj != NULL);
  11061. if (IsEqualIID(iid, IID_IUnknown) ||
  11062. IsEqualIID(iid, IID_IDispatch) ||
  11063. IsEqualIID(iid, IID_IScriptErrorList))
  11064. {
  11065. *ppObj = (IScriptErrorList *)this;
  11066. }
  11067. else
  11068. {
  11069. *ppObj = NULL;
  11070. return E_NOINTERFACE;
  11071. }
  11072. AddRef();
  11073. return S_OK;
  11074. }
  11075. STDMETHODIMP_(ULONG)
  11076. CScriptErrorList::AddRef()
  11077. {
  11078. _ulRefCount++;
  11079. return _ulRefCount;
  11080. }
  11081. STDMETHODIMP_(ULONG)
  11082. CScriptErrorList::Release()
  11083. {
  11084. _ulRefCount--;
  11085. if (_ulRefCount > 0)
  11086. {
  11087. return _ulRefCount;
  11088. }
  11089. delete this;
  11090. return 0;
  11091. }
  11092. STDMETHODIMP
  11093. CScriptErrorList::advanceError()
  11094. {
  11095. HRESULT hr;
  11096. hr = E_FAIL;
  11097. if (_hdpa != NULL)
  11098. {
  11099. int cPtr;
  11100. cPtr = DPA_GetPtrCount(_hdpa);
  11101. if (_lDispIndex < cPtr-1)
  11102. {
  11103. _lDispIndex++;
  11104. hr = S_OK;
  11105. }
  11106. }
  11107. return hr;
  11108. }
  11109. STDMETHODIMP
  11110. CScriptErrorList::retreatError()
  11111. {
  11112. if (_lDispIndex < 1)
  11113. {
  11114. return E_FAIL;
  11115. }
  11116. _lDispIndex--;
  11117. return S_OK;
  11118. }
  11119. STDMETHODIMP
  11120. CScriptErrorList::canAdvanceError(BOOL * pfCanAdvance)
  11121. {
  11122. HRESULT hr;
  11123. ASSERT(pfCanAdvance != NULL);
  11124. hr = E_FAIL;
  11125. if (_hdpa != NULL)
  11126. {
  11127. int cPtr;
  11128. cPtr = DPA_GetPtrCount(_hdpa);
  11129. *pfCanAdvance = _lDispIndex < cPtr-1;
  11130. hr = S_OK;
  11131. }
  11132. return hr;
  11133. }
  11134. STDMETHODIMP
  11135. CScriptErrorList::canRetreatError(BOOL * pfCanRetreat)
  11136. {
  11137. ASSERT(pfCanRetreat != NULL);
  11138. *pfCanRetreat = _lDispIndex > 0;
  11139. return S_OK;
  11140. }
  11141. STDMETHODIMP
  11142. CScriptErrorList::getErrorLine(LONG * plLine)
  11143. {
  11144. HRESULT hr;
  11145. ASSERT(plLine != NULL);
  11146. ASSERT(_lDispIndex >= 0);
  11147. hr = E_FAIL;
  11148. if (_hdpa != NULL)
  11149. {
  11150. int cPtr;
  11151. cPtr = DPA_GetPtrCount(_hdpa);
  11152. ASSERT(_lDispIndex < cPtr || _lDispIndex == 0);
  11153. if (cPtr > 0)
  11154. {
  11155. _CScriptErrInfo * pInfo;
  11156. pInfo = (_CScriptErrInfo *)DPA_GetPtr(_hdpa, _lDispIndex);
  11157. *plLine = pInfo->_lLine;
  11158. hr = S_OK;
  11159. }
  11160. }
  11161. return hr;
  11162. }
  11163. STDMETHODIMP
  11164. CScriptErrorList::getErrorChar(LONG * plChar)
  11165. {
  11166. HRESULT hr;
  11167. ASSERT(plChar != NULL);
  11168. ASSERT(_lDispIndex >= 0);
  11169. hr = E_FAIL;
  11170. if (_hdpa != NULL)
  11171. {
  11172. int cPtr;
  11173. cPtr = DPA_GetPtrCount(_hdpa);
  11174. ASSERT(_lDispIndex < cPtr || _lDispIndex == 0);
  11175. if (cPtr > 0)
  11176. {
  11177. _CScriptErrInfo * pInfo;
  11178. pInfo = (_CScriptErrInfo *)DPA_GetPtr(_hdpa, _lDispIndex);
  11179. *plChar = pInfo->_lChar;
  11180. hr = S_OK;
  11181. }
  11182. }
  11183. return hr;
  11184. }
  11185. STDMETHODIMP
  11186. CScriptErrorList::getErrorCode(LONG * plCode)
  11187. {
  11188. HRESULT hr;
  11189. ASSERT(plCode != NULL);
  11190. ASSERT(_lDispIndex >= 0);
  11191. hr = E_FAIL;
  11192. if (_hdpa != NULL)
  11193. {
  11194. int cPtr;
  11195. cPtr = DPA_GetPtrCount(_hdpa);
  11196. ASSERT(_lDispIndex < cPtr || _lDispIndex == 0);
  11197. if (cPtr > 0)
  11198. {
  11199. _CScriptErrInfo * pInfo;
  11200. pInfo = (_CScriptErrInfo *)DPA_GetPtr(_hdpa, _lDispIndex);
  11201. *plCode = pInfo->_lCode;
  11202. hr = S_OK;
  11203. }
  11204. }
  11205. return hr;
  11206. }
  11207. STDMETHODIMP
  11208. CScriptErrorList::getErrorMsg(BSTR * pstrMsg)
  11209. {
  11210. HRESULT hr;
  11211. ASSERT(pstrMsg != NULL);
  11212. ASSERT(_lDispIndex >= 0);
  11213. hr = E_FAIL;
  11214. if (_hdpa != NULL)
  11215. {
  11216. int cPtr;
  11217. cPtr = DPA_GetPtrCount(_hdpa);
  11218. ASSERT(_lDispIndex < cPtr || _lDispIndex == 0);
  11219. if (cPtr > 0)
  11220. {
  11221. _CScriptErrInfo * pInfo;
  11222. pInfo = (_CScriptErrInfo *)DPA_GetPtr(_hdpa, _lDispIndex);
  11223. *pstrMsg = SysAllocString(pInfo->_strMsg);
  11224. if (*pstrMsg != NULL)
  11225. {
  11226. hr = S_OK;
  11227. }
  11228. else
  11229. {
  11230. hr = E_OUTOFMEMORY;
  11231. }
  11232. }
  11233. }
  11234. return hr;
  11235. }
  11236. STDMETHODIMP
  11237. CScriptErrorList::getErrorUrl(BSTR * pstrUrl)
  11238. {
  11239. HRESULT hr;
  11240. ASSERT(pstrUrl != NULL);
  11241. ASSERT(_lDispIndex >= 0);
  11242. hr = E_FAIL;
  11243. if (_hdpa != NULL)
  11244. {
  11245. int cPtr;
  11246. cPtr = DPA_GetPtrCount(_hdpa);
  11247. ASSERT(_lDispIndex < cPtr || _lDispIndex == 0);
  11248. if (cPtr > 0)
  11249. {
  11250. _CScriptErrInfo * pInfo;
  11251. pInfo = (_CScriptErrInfo *)DPA_GetPtr(_hdpa, _lDispIndex);
  11252. *pstrUrl = SysAllocString(pInfo->_strUrl);
  11253. if (*pstrUrl != NULL)
  11254. {
  11255. hr = S_OK;
  11256. }
  11257. else
  11258. {
  11259. hr = E_OUTOFMEMORY;
  11260. }
  11261. }
  11262. }
  11263. return hr;
  11264. }
  11265. STDMETHODIMP
  11266. CScriptErrorList::getAlwaysShowLockState(BOOL * pfAlwaysShowLocked)
  11267. {
  11268. *pfAlwaysShowLocked = IsInetcplRestricted(TEXT("Advanced"));
  11269. return S_OK;
  11270. }
  11271. STDMETHODIMP
  11272. CScriptErrorList::getDetailsPaneOpen(BOOL * pfDetailsPaneOpen)
  11273. {
  11274. *pfDetailsPaneOpen =
  11275. SHRegGetBoolUSValue(szRegKey_SMIEM,
  11276. szRegVal_ErrDlgDetailsOpen,
  11277. FALSE,
  11278. FALSE);
  11279. return S_OK;
  11280. }
  11281. STDMETHODIMP
  11282. CScriptErrorList::setDetailsPaneOpen(BOOL fDetailsPaneOpen)
  11283. {
  11284. TCHAR szYes[] = TEXT("yes");
  11285. TCHAR szNo[] = TEXT("no");
  11286. LPTSTR pszVal;
  11287. int cbSize;
  11288. if (fDetailsPaneOpen)
  11289. {
  11290. pszVal = szYes;
  11291. cbSize = sizeof(szYes);
  11292. }
  11293. else
  11294. {
  11295. pszVal = szNo;
  11296. cbSize = sizeof(szNo);
  11297. }
  11298. SHRegSetUSValue(szRegKey_SMIEM,
  11299. szRegVal_ErrDlgDetailsOpen,
  11300. REG_SZ,
  11301. pszVal,
  11302. cbSize,
  11303. SHREGSET_HKCU | SHREGSET_FORCE_HKCU);
  11304. // even if it failed, we can't do anything about it...
  11305. return S_OK;
  11306. }
  11307. STDMETHODIMP
  11308. CScriptErrorList::getPerErrorDisplay(BOOL * pfPerErrorDisplay)
  11309. {
  11310. *pfPerErrorDisplay =
  11311. SHRegGetBoolUSValue(szRegKey_SMIEM,
  11312. szRegVal_ErrDlgPerErr,
  11313. FALSE,
  11314. FALSE);
  11315. return S_OK;
  11316. }
  11317. STDMETHODIMP
  11318. CScriptErrorList::setPerErrorDisplay(BOOL fPerErrorDisplay)
  11319. {
  11320. TCHAR szYes[] = TEXT("yes");
  11321. TCHAR szNo[] = TEXT("no");
  11322. LPTSTR pszVal;
  11323. int cbSize;
  11324. if (fPerErrorDisplay)
  11325. {
  11326. pszVal = szYes;
  11327. cbSize = sizeof(szYes);
  11328. }
  11329. else
  11330. {
  11331. pszVal = szNo;
  11332. cbSize = sizeof(szNo);
  11333. }
  11334. SHRegSetUSValue(szRegKey_SMIEM,
  11335. szRegVal_ErrDlgPerErr,
  11336. REG_SZ,
  11337. pszVal,
  11338. cbSize,
  11339. SHREGSET_HKCU | SHREGSET_FORCE_HKCU);
  11340. // even if it failed, we can't do anything about it...
  11341. return S_OK;
  11342. }
  11343. HRESULT
  11344. CScriptErrorList::_CScriptErrInfo::Init(LONG lLine,
  11345. LONG lChar,
  11346. LONG lCode,
  11347. BSTR strMsg,
  11348. BSTR strUrl)
  11349. {
  11350. ASSERT(_strMsg == NULL);
  11351. ASSERT(_strUrl == NULL);
  11352. _strMsg = SysAllocString(strMsg);
  11353. if (_strMsg == NULL)
  11354. {
  11355. return E_OUTOFMEMORY;
  11356. }
  11357. _strUrl = SysAllocString(strUrl);
  11358. if (_strUrl == NULL)
  11359. {
  11360. SysFreeString(_strMsg);
  11361. return E_OUTOFMEMORY;
  11362. }
  11363. _lLine = lLine;
  11364. _lChar = lChar;
  11365. _lCode = lCode;
  11366. return S_OK;
  11367. }
  11368. CScriptErrorList::_CScriptErrInfo::~_CScriptErrInfo()
  11369. {
  11370. if (_strMsg != NULL)
  11371. {
  11372. SysFreeString(_strMsg);
  11373. }
  11374. if (_strUrl != NULL)
  11375. {
  11376. SysFreeString(_strUrl);
  11377. }
  11378. }