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

5091 lines
118 KiB

  1. // Copyright (c)1997-1999 Microsoft Corporation, All Rights Reserved
  2. // Notes on m_bfModeSwitched and m_bfReloadAttempted.
  3. // IE5 bug 52818 was punted; pages containing IFrames don't refresh when changing
  4. // browse/edit modes, because the stream is seen as dirty (because the IFrame
  5. // considers itself dirty.) In response, we set m_bfModeSwitched when changing mode,
  6. // m_bfReloadAttempted when and ATTEMPT is made to reload the page, and check for BOTH
  7. // in OnReadyStateChanged. If the mode was changed but the page wasn't reloaded,
  8. // we have to reload it manually.
  9. #include "stdafx.h"
  10. #include "DHTMLEd.h"
  11. #include "DHTMLEdit.h"
  12. #include "site.h"
  13. #include "proxyframe.h"
  14. #include <TRIEDIID.h>
  15. #include <mshtmdid.h>
  16. #include "dispexa.h"
  17. #include <wchar.h>
  18. #include <string.h>
  19. // HTML to initialize Trident with if the host didn't supply any
  20. // The <P>&nbsp;</P> works around a nasty Trident bug.
  21. // Change: now there is one with paragraphs, one with DIVs.
  22. //
  23. static WCHAR* g_initialHTMLwithP = \
  24. L"<HTML>\r\n\
  25. <HEAD>\r\n\
  26. <META NAME=\"GENERATOR\" Content=\"Microsoft DHTML Editing Control\">\r\n\
  27. <TITLE></TITLE>\r\n\
  28. </HEAD>\r\n\
  29. <BODY>\r\n\
  30. <P>&nbsp;</P>\r\n\
  31. </BODY>\r\n\
  32. </HTML>\r\n";
  33. static WCHAR* g_initialHTMLwithDIV = \
  34. L"<HTML>\r\n\
  35. <HEAD>\r\n\
  36. <META NAME=\"GENERATOR\" Content=\"Microsoft DHTML Editing Control\">\r\n\
  37. <TITLE></TITLE>\r\n\
  38. </HEAD>\r\n\
  39. <BODY>\r\n\
  40. <DIV>&nbsp;</DIV>\r\n\
  41. </BODY>\r\n\
  42. </HTML>\r\n";
  43. // Text, numbers and constants used to construct a unique-per-process protocol ID
  44. //
  45. static WCHAR* g_wszProtocolPrefix = L"DHTMLEd";
  46. static int s_iProtocolSuffix = 0;
  47. #define MAX_PROTOCOL_SUFFIX 999999
  48. // Name of the Title property which we get from the IHtmlDocument2 interface.
  49. static WCHAR* g_wszHTMLTitlePropName = L"title";
  50. // Maps private DHTMLEdit command IDs to Triedit command IDs.
  51. // The third field is true if the command includes an out parameter.
  52. //
  53. static CommandMap cmdMap[] =
  54. {
  55. {DECMD_BOLD, IDM_TRIED_BOLD, FALSE},
  56. {DECMD_COPY, IDM_TRIED_COPY, FALSE},
  57. {DECMD_CUT, IDM_TRIED_CUT, FALSE},
  58. {DECMD_DELETE, IDM_TRIED_DELETE, FALSE},
  59. {DECMD_DELETECELLS, IDM_TRIED_DELETECELLS, FALSE},
  60. {DECMD_DELETECOLS, IDM_TRIED_DELETECOLS, FALSE},
  61. {DECMD_DELETEROWS, IDM_TRIED_DELETEROWS, FALSE},
  62. {DECMD_FINDTEXT, IDM_TRIED_FIND, FALSE},
  63. {DECMD_FONT, IDM_TRIED_FONT, FALSE},
  64. {DECMD_GETBACKCOLOR, IDM_TRIED_BACKCOLOR, TRUE},
  65. {DECMD_GETBLOCKFMT, IDM_TRIED_BLOCKFMT, TRUE},
  66. {DECMD_GETBLOCKFMTNAMES, IDM_TRIED_GETBLOCKFMTS, TRUE},
  67. {DECMD_GETFONTNAME, IDM_TRIED_FONTNAME, TRUE},
  68. {DECMD_GETFONTSIZE, IDM_TRIED_FONTSIZE, TRUE},
  69. {DECMD_GETFORECOLOR, IDM_TRIED_FORECOLOR, TRUE},
  70. {DECMD_HYPERLINK, IDM_TRIED_HYPERLINK, FALSE},
  71. {DECMD_IMAGE, IDM_TRIED_IMAGE, FALSE},
  72. {DECMD_INDENT, IDM_TRIED_INDENT, FALSE},
  73. {DECMD_INSERTCELL, IDM_TRIED_INSERTCELL, FALSE},
  74. {DECMD_INSERTCOL, IDM_TRIED_INSERTCOL, FALSE},
  75. {DECMD_INSERTROW, IDM_TRIED_INSERTROW, FALSE},
  76. {DECMD_INSERTTABLE, IDM_TRIED_INSERTTABLE, FALSE},
  77. {DECMD_ITALIC, IDM_TRIED_ITALIC, FALSE},
  78. {DECMD_JUSTIFYLEFT, IDM_TRIED_JUSTIFYLEFT, FALSE},
  79. {DECMD_JUSTIFYRIGHT, IDM_TRIED_JUSTIFYRIGHT, FALSE},
  80. {DECMD_JUSTIFYCENTER, IDM_TRIED_JUSTIFYCENTER, FALSE},
  81. {DECMD_LOCK_ELEMENT, IDM_TRIED_LOCK_ELEMENT, FALSE},
  82. {DECMD_MAKE_ABSOLUTE, IDM_TRIED_MAKE_ABSOLUTE, FALSE},
  83. {DECMD_MERGECELLS, IDM_TRIED_MERGECELLS, FALSE},
  84. {DECMD_ORDERLIST, IDM_TRIED_ORDERLIST, FALSE},
  85. {DECMD_OUTDENT, IDM_TRIED_OUTDENT, FALSE},
  86. {DECMD_PASTE, IDM_TRIED_PASTE, FALSE},
  87. {DECMD_REDO, IDM_TRIED_REDO, FALSE},
  88. {DECMD_REMOVEFORMAT, IDM_TRIED_REMOVEFORMAT, FALSE},
  89. {DECMD_SELECTALL, IDM_TRIED_SELECTALL, FALSE},
  90. {DECMD_SEND_BACKWARD, IDM_TRIED_SEND_BACKWARD, FALSE},
  91. {DECMD_BRING_FORWARD, IDM_TRIED_SEND_FORWARD, FALSE},
  92. {DECMD_SEND_BELOW_TEXT, IDM_TRIED_SEND_BEHIND_1D, FALSE},
  93. {DECMD_BRING_ABOVE_TEXT, IDM_TRIED_SEND_FRONT_1D, FALSE},
  94. {DECMD_SEND_TO_BACK, IDM_TRIED_SEND_TO_BACK, FALSE},
  95. {DECMD_BRING_TO_FRONT, IDM_TRIED_SEND_TO_FRONT, FALSE},
  96. {DECMD_SETBACKCOLOR, IDM_TRIED_BACKCOLOR, FALSE},
  97. {DECMD_SETBLOCKFMT, IDM_TRIED_BLOCKFMT, FALSE},
  98. {DECMD_SETFONTNAME, IDM_TRIED_FONTNAME, FALSE},
  99. {DECMD_SETFONTSIZE, IDM_TRIED_FONTSIZE, FALSE},
  100. {DECMD_SETFORECOLOR, IDM_TRIED_FORECOLOR, FALSE},
  101. {DECMD_SPLITCELL, IDM_TRIED_SPLITCELL, FALSE},
  102. {DECMD_UNDERLINE, IDM_TRIED_UNDERLINE, FALSE},
  103. {DECMD_UNDO, IDM_TRIED_UNDO, FALSE},
  104. {DECMD_UNLINK, IDM_TRIED_UNLINK, FALSE},
  105. {DECMD_UNORDERLIST, IDM_TRIED_UNORDERLIST, FALSE},
  106. {DECMD_PROPERTIES, IDM_TRIED_DOVERB, FALSE}
  107. };
  108. CProxyFrame::CProxyFrame(CDHTMLSafe* pCtl)
  109. {
  110. SAFEARRAYBOUND rgsabound[1] = {0};
  111. _ASSERTE(pCtl);
  112. m_cRef = 1;
  113. m_pUnkTriEdit = NULL;
  114. m_hWndObj = NULL;
  115. m_pIOleIPActiveObject = NULL;
  116. m_pSite = NULL;
  117. m_pCtl = pCtl;
  118. m_fCreated = FALSE;
  119. m_fActivated = FALSE;
  120. m_state = ESTATE_NOTCREATED;
  121. m_readyState = READYSTATE_UNINITIALIZED;
  122. m_dwFilterFlags = m_dwFilterOutFlags = filterAll;
  123. m_fActivateApplets = FALSE;
  124. m_fActivateControls = FALSE;
  125. m_fActivateDTCs = TRUE;
  126. m_fShowAllTags = FALSE;
  127. m_fShowBorders = FALSE;
  128. m_fDialogEditing = TRUE;
  129. m_fDisplay3D = TRUE;
  130. m_fScrollbars = TRUE;
  131. m_fDisplayFlatScrollbars = FALSE;
  132. m_fContextMenu = TRUE;
  133. m_fPreserveSource = TRUE;
  134. m_fAbsoluteDropMode = FALSE;
  135. m_fSnapToGrid = FALSE;
  136. m_ulSnapToGridX = 50;
  137. m_ulSnapToGridY = 50;
  138. rgsabound[0].lLbound = 0;
  139. rgsabound[0].cElements = 0;
  140. m_pMenuStrings = NULL;
  141. m_pMenuStates = NULL;
  142. m_vbBrowseMode = VARIANT_FALSE;
  143. m_vbUseDivOnCr = VARIANT_FALSE;
  144. m_bfIsLoading = FALSE;
  145. m_bfBaseURLFromBASETag = FALSE;
  146. m_bfPreserveDirtyFlagAcrossBrowseMode = FALSE;
  147. m_bstrInitialDoc.Empty ();
  148. m_bstrCurDocPath.Empty ();
  149. wcscpy ( m_wszProtocol, g_wszProtocolPrefix );
  150. WCHAR wszSuffix[8];
  151. _itow ( s_iProtocolSuffix++, wszSuffix, 10 );
  152. if ( MAX_PROTOCOL_SUFFIX <= s_iProtocolSuffix )
  153. {
  154. s_iProtocolSuffix = 0; // Roll over.
  155. }
  156. wcscat ( m_wszProtocol, wszSuffix );
  157. wcscpy ( m_wszProtocolPrefix, m_wszProtocol );
  158. wcscat ( m_wszProtocolPrefix, L":" );
  159. m_pProtInfo = NULL;
  160. m_bfIsURL = FALSE;
  161. m_bstrBaseURL = L"";
  162. m_hwndRestoreFocus = NULL;
  163. #ifdef LATE_BIND_URLMON_WININET
  164. m_hUlrMon = NULL;
  165. m_hWinINet = NULL;
  166. m_pfnCoInternetCombineUrl = NULL;
  167. m_pfnCoInternetParseUrl = NULL;
  168. m_pfnCreateURLMoniker = NULL;
  169. m_pfnCoInternetGetSession = NULL;
  170. m_pfnURLOpenBlockingStream = NULL;
  171. m_pfnDeleteUrlCacheEntry = NULL;
  172. m_pfnInternetCreateUrl = NULL;
  173. m_pfnInternetCrackUrl = NULL;
  174. #endif // LATE_BIND_URLMON_WININET
  175. m_bfModeSwitched = FALSE;
  176. m_bfReloadAttempted = FALSE;
  177. m_bfSFSRedirect = FALSE;
  178. }
  179. CProxyFrame::~CProxyFrame()
  180. {
  181. _ASSERTE(FALSE == m_fCreated);
  182. _ASSERTE(FALSE == m_fActivated);
  183. _ASSERTE( m_cRef == 0 );
  184. if (m_pMenuStrings)
  185. {
  186. SafeArrayDestroy(m_pMenuStrings);
  187. m_pMenuStrings = NULL;
  188. }
  189. if (m_pMenuStates)
  190. {
  191. SafeArrayDestroy(m_pMenuStates);
  192. m_pMenuStates = NULL;
  193. }
  194. // This should never happen: SetActiveObject should take care of it.
  195. _ASSERTE ( NULL == m_pIOleIPActiveObject );
  196. if (m_pIOleIPActiveObject)
  197. {
  198. m_pIOleIPActiveObject->Release();
  199. m_pIOleIPActiveObject = NULL;
  200. }
  201. UnRegisterPluggableProtocol ();
  202. #ifdef LATE_BIND_URLMON_WININET
  203. DynUnloadLibraries ();
  204. #endif // LATE_BIND_URLMON_WININET
  205. }
  206. // Create the TriEdit object and host it.
  207. // Clean up and return an error if there was any problem.
  208. //
  209. HRESULT
  210. CProxyFrame::Init(IUnknown* pUnk, IUnknown** ppUnkTriEdit)
  211. {
  212. HRESULT hr = S_OK;
  213. #ifdef LATE_BIND_URLMON_WININET
  214. if ( ! DynLoadLibraries () )
  215. {
  216. return E_FAIL;
  217. }
  218. #endif // LATE_BIND_URLMON_WININET
  219. hr = RegisterPluggableProtocol ();
  220. if ( FAILED ( hr ) )
  221. {
  222. return hr;
  223. }
  224. _ASSERTE(NULL == m_pSite);
  225. _ASSERTE(GetState() == ESTATE_NOTCREATED);
  226. InitializeDocString ();
  227. if (m_pSite)
  228. return E_UNEXPECTED;
  229. if (GetState() != ESTATE_NOTCREATED)
  230. return E_UNEXPECTED;
  231. // Create and initialize the site for TriEdit
  232. m_pSite = new CSite(this);
  233. if (NULL == m_pSite)
  234. {
  235. return E_OUTOFMEMORY;
  236. }
  237. m_pSite->AddRef(); // So we can free with Release
  238. // Ask the site to create TriEdit
  239. if (SUCCEEDED(hr = m_pSite->HrCreate(pUnk, &m_pUnkTriEdit)))
  240. {
  241. ChangeState(ESTATE_CREATED);
  242. m_fCreated = TRUE;
  243. if (ppUnkTriEdit)
  244. {
  245. m_pUnkTriEdit->AddRef();
  246. *ppUnkTriEdit = m_pUnkTriEdit;
  247. }
  248. }
  249. else
  250. {
  251. m_pSite->Release();
  252. m_pSite = NULL;
  253. }
  254. return hr;
  255. }
  256. // Destroy the site and the TriEdit object.
  257. //
  258. HRESULT
  259. CProxyFrame::Close()
  260. {
  261. HRESULT hr = S_OK;
  262. _ASSERTE(m_pUnkTriEdit);
  263. _ASSERTE(m_pSite);
  264. _ASSERTE(GetState() != ESTATE_NOTCREATED);
  265. m_bstrCurDocPath.Empty ();
  266. // triedit must be created
  267. // any state from created to activated is ok
  268. if (GetState() == ESTATE_NOTCREATED)
  269. return E_UNEXPECTED;
  270. if (m_fActivated)
  271. {
  272. hr = HrExecCommand(&CGID_MSHTML, IDM_STOP, MSOCMDEXECOPT_DONTPROMPTUSER, NULL, NULL);
  273. _ASSERTE(SUCCEEDED(hr));
  274. }
  275. ChangeState(ESTATE_NOTCREATED);
  276. m_fCreated = FALSE;
  277. m_fActivated = FALSE;
  278. if (m_pSite != NULL)
  279. {
  280. CSite* pSite = m_pSite; // prevents reentry;
  281. m_pSite = NULL;
  282. pSite->Close(FALSE);
  283. ReleaseInterface(pSite)
  284. pSite = NULL;
  285. }
  286. if (m_pUnkTriEdit != NULL)
  287. {
  288. LPUNKNOWN pUnkTriEdit = m_pUnkTriEdit;
  289. m_pUnkTriEdit = NULL;
  290. ReleaseInterface(pUnkTriEdit);
  291. pUnkTriEdit = NULL;
  292. }
  293. m_hwndRestoreFocus = NULL;
  294. return S_OK;
  295. }
  296. // Determine which string constant to use and return a pointer to it.
  297. //
  298. WCHAR* CProxyFrame::GetInitialHTML ()
  299. {
  300. if ( m_vbUseDivOnCr )
  301. {
  302. return g_initialHTMLwithDIV;
  303. }
  304. else
  305. {
  306. return g_initialHTMLwithP;
  307. }
  308. }
  309. // Perform these steps before loading TriEdit's contents
  310. //
  311. HRESULT
  312. CProxyFrame::PreActivate()
  313. {
  314. HRESULT hr = S_OK;
  315. _ASSERTE(m_pSite);
  316. _ASSERTE(m_pCtl);
  317. _ASSERTE(ESTATE_CREATED == GetState());
  318. if (GetState() != ESTATE_CREATED)
  319. return E_UNEXPECTED;
  320. if (FAILED(hr = m_pSite->HrObjectInitialize()))
  321. {
  322. _ASSERTE(SUCCEEDED(hr));
  323. goto error;
  324. }
  325. m_fActivated = TRUE;
  326. ChangeState(ESTATE_PREACTIVATING);
  327. if (FAILED(hr = HrSetRuntimeProperties()))
  328. {
  329. _ASSERTE(SUCCEEDED(hr));
  330. goto error;
  331. }
  332. ChangeState(ESTATE_ACTIVATING);
  333. error:
  334. return hr;
  335. }
  336. void
  337. CProxyFrame::UIDeactivate()
  338. {
  339. // This was m_pSite->GetIPObject()->UIDeactivate(),
  340. // but the QA teams VB app using this version of the control crashed
  341. // with a NULL pointer dereference.
  342. if ( NULL != m_pSite )
  343. {
  344. LPOLEINPLACEOBJECT pipObj = m_pSite->GetIPObject();
  345. if ( NULL != pipObj )
  346. {
  347. pipObj->UIDeactivate();
  348. }
  349. }
  350. }
  351. // Perform these steps after loading TriEdits contents to go UI active.
  352. //
  353. HRESULT
  354. CProxyFrame::Activate()
  355. {
  356. HRESULT hr = S_OK;
  357. _ASSERTE(m_pSite);
  358. _ASSERTE(m_pCtl);
  359. _ASSERTE(m_pCtl->m_hWndCD);
  360. _ASSERTE(GetState() == ESTATE_ACTIVATING);
  361. if (GetState() != ESTATE_ACTIVATING)
  362. return E_UNEXPECTED;
  363. // UI-activate the control
  364. if ( ! m_pCtl->m_bUIActive )
  365. {
  366. // Used to be UIActivate, until MohanB fixed OnSetFocus and activation/deactivation linkage.
  367. m_pCtl->DoVerbInPlaceActivate ( NULL, NULL );
  368. }
  369. // activate Trident with "Show"
  370. m_pSite->InitialActivate(OLEIVERB_SHOW, m_pCtl->m_hWndCD);
  371. ChangeState(ESTATE_ACTIVATED);
  372. // This may have been deferred, because the site's command target did not yet exist...
  373. SetBrowseMode ( m_vbBrowseMode );
  374. return hr;
  375. }
  376. // Load and activate the control with a minimal, empty page.
  377. //
  378. HRESULT
  379. CProxyFrame::LoadInitialDoc()
  380. {
  381. HRESULT hr = S_OK;
  382. _ASSERTE(GetState() == ESTATE_CREATED);
  383. if (GetState() != ESTATE_CREATED)
  384. return E_UNEXPECTED;
  385. if (FAILED(hr = PreActivate()))
  386. goto error;
  387. if (FAILED(hr = LoadBSTRDeferred ( m_bstrInitialDoc )))
  388. {
  389. _ASSERTE(SUCCEEDED(hr));
  390. goto error;
  391. }
  392. if (FAILED(hr = Activate()))
  393. goto error;
  394. error:
  395. return hr;
  396. }
  397. // Before getting or setting a property or calling a method on the docobject,
  398. // assure that it's been properly activated.
  399. //
  400. void CProxyFrame::AssureActivated ()
  401. {
  402. if ( ! m_fActivated )
  403. {
  404. if ( m_pCtl->IsUserMode() )
  405. {
  406. if ( !m_pCtl->m_bInPlaceActive )
  407. {
  408. m_pCtl->DoVerbInPlaceActivate ( NULL, NULL );
  409. }
  410. LoadInitialDoc ();
  411. }
  412. }
  413. }
  414. // Loading MSHTML shifts the focus to its document window.
  415. // This is not desirable in a control. Experimentation has demonstrated
  416. // that the focus shifts between various QIs from MSHTML (probably in response
  417. // to posted messages.) There is no routine in DHTMLEdit which enters with the
  418. // focus outside the control and exits with the focus within the control.
  419. // Therefore, a member variable is used to preserve the appropriate focus
  420. // across calls to OnReadyStateChanged, which are called in response to events
  421. // fired by the control. m_hwndRestoreFocus is used to preserve the appropriate
  422. // window to receive the focus. Note that NULL may be appropriate, but is not honored.
  423. // If no window had focus, the document will gain focus.
  424. //
  425. void
  426. CProxyFrame::OnReadyStateChanged(READYSTATE readyState)
  427. {
  428. _ASSERTE(m_pCtl);
  429. m_readyState = readyState;
  430. switch (m_readyState)
  431. {
  432. case READYSTATE_UNINITIALIZED:
  433. {
  434. m_hwndRestoreFocus = NULL;
  435. }
  436. break;
  437. case READYSTATE_LOADING:
  438. {
  439. m_hwndRestoreFocus = ::GetFocus ();
  440. }
  441. break;
  442. case READYSTATE_LOADED:
  443. {
  444. }
  445. break;
  446. case READYSTATE_INTERACTIVE:
  447. {
  448. if ( NULL != m_hwndRestoreFocus )
  449. {
  450. _ASSERTE ( ::IsWindow ( m_hwndRestoreFocus ) );
  451. if ( ::IsWindow ( m_hwndRestoreFocus ) )
  452. {
  453. ::SetFocus ( m_hwndRestoreFocus );
  454. }
  455. }
  456. // See if we failed to get a refresh on a mode change. This happens if
  457. // there are IFrames on the page, perhaps in other cases as well.
  458. if ( m_bfModeSwitched && !m_bfReloadAttempted )
  459. {
  460. HRESULT hr = S_OK;
  461. CComPtr<IMoniker> srpMoniker;
  462. CComPtr<IBindCtx> srpBindCtx;
  463. CComQIPtr<IPersistMoniker, &IID_IPersistMoniker> srpPM (m_pUnkTriEdit);
  464. _ASSERTE ( srpPM );
  465. if ( srpPM )
  466. {
  467. CComBSTR bstrProtocol = m_wszProtocolPrefix;
  468. #ifdef LATE_BIND_URLMON_WININET
  469. _ASSERTE ( m_pfnCreateURLMoniker );
  470. hr = (*m_pfnCreateURLMoniker)( NULL, bstrProtocol, &srpMoniker );
  471. #else
  472. hr = CreateURLMoniker ( NULL, bstrProtocol, &srpMoniker );
  473. #endif // LATE_BIND_URLMON_WININET
  474. _ASSERTE ( SUCCEEDED( hr ) );
  475. if ( SUCCEEDED ( hr ) )
  476. {
  477. hr = ::CreateBindCtx(NULL, &srpBindCtx);
  478. _ASSERTE ( SUCCEEDED( hr ) );
  479. if ( SUCCEEDED ( hr ) )
  480. {
  481. hr = srpPM->Load(FALSE, srpMoniker, srpBindCtx, STGM_READ);
  482. }
  483. }
  484. }
  485. }
  486. m_bfModeSwitched = FALSE;
  487. m_bfReloadAttempted = FALSE;
  488. }
  489. break;
  490. case READYSTATE_COMPLETE:
  491. {
  492. HRESULT hr = S_OK;
  493. m_hwndRestoreFocus = NULL;
  494. if ( ! m_vbBrowseMode )
  495. {
  496. hr = HrSetDocLoadedProperties();
  497. _ASSERTE(SUCCEEDED(hr));
  498. }
  499. _ASSERTE ( m_pCtl->m_hWnd );
  500. _ASSERTE ( ::IsWindow ( m_pCtl->m_hWnd ) );
  501. if ( m_bfPreserveDirtyFlagAcrossBrowseMode && !m_vbBrowseMode )
  502. {
  503. m_bfPreserveDirtyFlagAcrossBrowseMode = FALSE;
  504. SetDirtyFlag ( TRUE );
  505. }
  506. // Post a user message to fire the DocumentComplete event.
  507. // Otherwise, calling things like LoadURL from DocumentComplete behaves strangely.
  508. ::PostMessage ( m_pCtl->m_hWnd, DOCUMENT_COMPETE_MESSAGE, DOCUMENT_COMPETE_SIGNATURE, 0L );
  509. HrSetRuntimeProperties ();
  510. //m_bfIsLoading = FALSE; // This has been moved the the DOCUMENT_COMPETE_MESSAGE handler.
  511. SetBaseURLFromBaseHref (); // Must be called after clearing m_bfIsLoading
  512. }
  513. break;
  514. }
  515. }
  516. /*
  517. * IUnknown implementation
  518. */
  519. /*
  520. * CProxyFrame::QueryInterface
  521. * CProxyFrame::AddRef
  522. * CProxyFrame::Release
  523. */
  524. STDMETHODIMP CProxyFrame::QueryInterface( REFIID riid, void **ppv )
  525. {
  526. /*
  527. * We provide IOleInPlaceFrame and IOleCommandTarget
  528. * interfaces here for the ActiveX Document hosting
  529. */
  530. *ppv = NULL;
  531. if ( IID_IUnknown == riid || IID_IOleInPlaceUIWindow == riid
  532. || IID_IOleWindow == riid || IID_IOleInPlaceFrame == riid )
  533. {
  534. *ppv = static_cast<IOleInPlaceFrame *>(this);
  535. }
  536. else if ( IID_IOleCommandTarget == riid )
  537. {
  538. *ppv = static_cast<IOleCommandTarget *>(this);
  539. }
  540. else if ( IID_IBindStatusCallback == riid )
  541. {
  542. *ppv = static_cast<IBindStatusCallback *>(this);
  543. }
  544. else if ( IID_IAuthenticate == riid )
  545. {
  546. *ppv = static_cast<IAuthenticate *>(this);
  547. }
  548. else if ( IID_IServiceProvider == riid )
  549. {
  550. // Ask the control for a security manager IF in edit mode:
  551. if ( ! m_vbBrowseMode )
  552. {
  553. return m_pCtl->GetUnknown()->QueryInterface ( riid, ppv );
  554. }
  555. }
  556. if ( NULL != *ppv )
  557. {
  558. ((LPUNKNOWN)*ppv)->AddRef();
  559. return S_OK;
  560. }
  561. return E_NOINTERFACE;
  562. }
  563. STDMETHODIMP_(ULONG) CProxyFrame::AddRef( void )
  564. {
  565. return ++m_cRef;
  566. }
  567. STDMETHODIMP_(ULONG) CProxyFrame::Release( void )
  568. {
  569. //Nothing special happening here-- life if user-controlled.
  570. // Debug check to see we don't fall below 0
  571. _ASSERTE( m_cRef != 0 );
  572. ULONG ulRefCount = --m_cRef;
  573. if ( 0 == ulRefCount )
  574. {
  575. delete this; // Do not refer to any member variables after this.
  576. }
  577. return ulRefCount;
  578. }
  579. /*
  580. * IOleInPlaceFrame implementation
  581. */
  582. /*
  583. * CProxyFrame::GetWindow
  584. *
  585. * Purpose:
  586. * Retrieves the handle of the window associated with the object
  587. * on which this interface is implemented.
  588. *
  589. * Parameters:
  590. * phWnd HWND * in which to store the window handle.
  591. *
  592. * Return Value:
  593. * HRESULT S_OK if successful, E_FAIL if there is no
  594. * window.
  595. */
  596. STDMETHODIMP CProxyFrame::GetWindow( HWND* phWnd )
  597. {
  598. if ( m_pCtl != NULL )
  599. {
  600. *phWnd = m_pCtl->m_hWnd;
  601. }
  602. return S_OK;
  603. }
  604. /*
  605. * CProxyFrame::ContextSensitiveHelp
  606. *
  607. * Purpose:
  608. * Instructs the object on which this interface is implemented to
  609. * enter or leave a context-sensitive help mode.
  610. *
  611. * Parameters:
  612. * fEnterMode BOOL TRUE to enter the mode, FALSE otherwise.
  613. *
  614. * Return Value:
  615. * HRESULT S_OK
  616. */
  617. STDMETHODIMP CProxyFrame::ContextSensitiveHelp( BOOL /*fEnterMode*/ )
  618. {
  619. return S_OK;
  620. }
  621. /*
  622. * CProxyFrame::GetBorder
  623. *
  624. * Purpose:
  625. * Returns the rectangle in which the container is willing to
  626. * negotiate about an object's adornments.
  627. *
  628. * Parameters:
  629. * prcBorder LPRECT in which to store the rectangle.
  630. *
  631. * Return Value:
  632. * HRESULT S_OK if all is well, INPLACE_E_NOTOOLSPACE
  633. * if there is no negotiable space.
  634. */
  635. STDMETHODIMP CProxyFrame::GetBorder( LPRECT prcBorder )
  636. {
  637. if ( NULL == prcBorder )
  638. {
  639. return E_INVALIDARG;
  640. }
  641. //We return all the client area space
  642. m_pCtl->GetClientRect( prcBorder );
  643. return S_OK;
  644. }
  645. /*
  646. * CProxyFrame::RequestBorderSpace
  647. *
  648. * Purpose:
  649. * Asks the container if it can surrender the amount of space
  650. * in pBW that the object would like for it's adornments. The
  651. * container does nothing but validate the spaces on this call.
  652. *
  653. * Parameters:
  654. * pBW LPCBORDERWIDTHS containing the requested space.
  655. * The values are the amount of space requested
  656. * from each side of the relevant window.
  657. *
  658. * Return Value:
  659. * HRESULT S_OK if we can give up space,
  660. * INPLACE_E_NOTOOLSPACE otherwise.
  661. */
  662. STDMETHODIMP CProxyFrame::RequestBorderSpace( LPCBORDERWIDTHS /*pBW*/ )
  663. {
  664. // We have no border space restrictions
  665. return S_OK;
  666. }
  667. /*
  668. * CProxyFrame::SetBorderSpace
  669. *
  670. * Purpose:
  671. * Called when the object now officially requests that the
  672. * container surrender border space it previously allowed
  673. * in RequestBorderSpace. The container should resize windows
  674. * appropriately to surrender this space.
  675. *
  676. * Parameters:
  677. * pBW LPCBORDERWIDTHS containing the amount of space
  678. * from each side of the relevant window that the
  679. * object is now reserving.
  680. *
  681. * Return Value:
  682. * HRESULT S_OK
  683. */
  684. STDMETHODIMP CProxyFrame::SetBorderSpace( LPCBORDERWIDTHS /*pBW*/ )
  685. {
  686. // We turn off the MSHTML.DLL UI so we ignore all of this.
  687. return S_OK;
  688. }
  689. /*
  690. * CProxyFrame::SetActiveObject
  691. *
  692. * Purpose:
  693. * Provides the container with the object's IOleInPlaceActiveObject
  694. * pointer
  695. *
  696. * Parameters:
  697. * pIIPActiveObj LPOLEINPLACEACTIVEOBJECT of interest.
  698. * pszObj LPCOLESTR naming the object. Not used.
  699. *
  700. * Return Value:
  701. * HRESULT S_OK
  702. */
  703. STDMETHODIMP CProxyFrame::SetActiveObject( LPOLEINPLACEACTIVEOBJECT pIIPActiveObj,
  704. LPCOLESTR /*pszObj*/)
  705. {
  706. // If we already have an active Object then release it.
  707. if ( NULL != m_pIOleIPActiveObject )
  708. {
  709. m_pIOleIPActiveObject->Release();
  710. }
  711. //NULLs m_pIOleIPActiveObject if pIIPActiveObj is NULL
  712. m_pIOleIPActiveObject = pIIPActiveObj;
  713. if ( NULL != m_pIOleIPActiveObject )
  714. {
  715. m_pIOleIPActiveObject->AddRef();
  716. m_pIOleIPActiveObject->GetWindow( &m_hWndObj );
  717. }
  718. return S_OK;
  719. }
  720. /*
  721. * CProxyFrame::InsertMenus
  722. *
  723. * Purpose:
  724. * Instructs the container to place its in-place menu items where
  725. * necessary in the given menu and to fill in elements 0, 2, and 4
  726. * of the OLEMENUGROUPWIDTHS array to indicate how many top-level
  727. * items are in each group.
  728. *
  729. * Parameters:
  730. * hMenu HMENU in which to add popups.
  731. * pMGW LPOLEMENUGROUPWIDTHS in which to store the
  732. * width of each container menu group.
  733. *
  734. * Return Value:
  735. * HRESULT E_NOTIMPL
  736. */
  737. STDMETHODIMP CProxyFrame::InsertMenus( HMENU /*hMenu*/, LPOLEMENUGROUPWIDTHS /*pMGW*/ )
  738. {
  739. // We've turned off the MSHTML.DLL Menus so we don't expect any merging to go on!
  740. return E_NOTIMPL;
  741. }
  742. /*
  743. * CProxyFrame::SetMenu
  744. *
  745. * Purpose:
  746. * Instructs the container to replace whatever menu it's currently
  747. * using with the given menu and to call OleSetMenuDescritor so OLE
  748. * knows to whom to dispatch messages.
  749. *
  750. * Parameters:
  751. * hMenu HMENU to show.
  752. * hOLEMenu HOLEMENU to the menu descriptor.
  753. * hWndObj HWND of the active object to which messages are
  754. * dispatched.
  755. *
  756. * Return Value:
  757. * HRESULT NOERROR
  758. */
  759. STDMETHODIMP CProxyFrame::SetMenu( HMENU /*hMenu*/, HOLEMENU /*hOLEMenu*/, HWND /*hWndObj*/ )
  760. {
  761. // We've turned off the MSHTML.DLL Menus so we don't expect any merging to go on!
  762. return E_NOTIMPL;
  763. }
  764. /*
  765. * CProxyFrame::RemoveMenus
  766. *
  767. * Purpose:
  768. * Asks the container to remove any menus it put into hMenu in
  769. * InsertMenus.
  770. *
  771. * Parameters:
  772. * hMenu HMENU from which to remove the container's
  773. * items.
  774. *
  775. * Return Value:
  776. * HRESULT NOERROR
  777. */
  778. STDMETHODIMP CProxyFrame::RemoveMenus( HMENU /*hMenu*/ )
  779. {
  780. // We've turned off the MSHTML.DLL Menus so we don't expect any merging to go on!
  781. return E_NOTIMPL;
  782. }
  783. /*
  784. * CProxyFrame::SetStatusText
  785. *
  786. * Purpose:
  787. * Asks the container to place some text in a status line, if one
  788. * exists. If the container does not have a status line it
  789. * should return E_FAIL here in which case the object could
  790. * display its own.
  791. *
  792. * Parameters:
  793. * pszText LPCOLESTR to display.
  794. *
  795. * Return Value:
  796. * HRESULT S_OK if successful, S_TRUNCATED if not all
  797. * of the text could be displayed, or E_FAIL if
  798. * the container has no status line.
  799. */
  800. STDMETHODIMP CProxyFrame::SetStatusText( LPCOLESTR /*pszText*/ )
  801. {
  802. return S_OK;
  803. }
  804. /*
  805. * CProxyFrame::EnableModeless
  806. *
  807. * Purpose:
  808. * Instructs the container to show or hide any modeless popup
  809. * windows that it may be using.
  810. *
  811. * Parameters:
  812. * fEnable BOOL indicating to enable/show the windows
  813. * (TRUE) or to hide them (FALSE).
  814. *
  815. * Return Value:
  816. * HRESULT S_OK
  817. */
  818. STDMETHODIMP CProxyFrame::EnableModeless( BOOL /*fEnable*/ )
  819. {
  820. return S_OK;
  821. }
  822. /*
  823. * CProxyFrame::TranslateAccelerator
  824. *
  825. * Purpose:
  826. * When dealing with an in-place object from an EXE server, this
  827. * is called to give the container a chance to process accelerators
  828. * after the server has looked at the message.
  829. *
  830. * Parameters:
  831. * pMSG LPMSG for the container to examine.
  832. * wID WORD the identifier in the container's
  833. * accelerator table (from IOleInPlaceSite
  834. * ::GetWindowContext) for this message (OLE does
  835. * some translation before calling).
  836. *
  837. * Return Value:
  838. * HRESULT NOERROR if the keystroke was used,
  839. * S_FALSE otherwise.
  840. */
  841. STDMETHODIMP CProxyFrame::TranslateAccelerator( LPMSG /*pMSG*/, WORD /*wID*/ )
  842. {
  843. return S_FALSE;
  844. }
  845. /*
  846. * IOleCommandTarget::QueryStatus
  847. */
  848. STDMETHODIMP CProxyFrame::QueryStatus( const GUID* pguidCmdGroup, ULONG cCmds,
  849. OLECMD* prgCmds, OLECMDTEXT* pCmdText )
  850. {
  851. if ( pguidCmdGroup != NULL )
  852. {
  853. // It's a nonstandard group!!
  854. return OLECMDERR_E_UNKNOWNGROUP;
  855. }
  856. MSOCMD* pCmd;
  857. INT c;
  858. HRESULT hr = S_OK;
  859. // By default command text is NOT SUPPORTED.
  860. if ( pCmdText && ( pCmdText->cmdtextf != OLECMDTEXTF_NONE ) )
  861. {
  862. pCmdText->cwActual = 0;
  863. }
  864. // Loop through each command in the array, setting the status of each.
  865. for ( pCmd = prgCmds, c = cCmds; --c >= 0; pCmd++ )
  866. {
  867. // By default command status is NOT SUPPORTED.
  868. pCmd->cmdf = 0;
  869. switch ( pCmd->cmdID )
  870. {
  871. case OLECMDID_UPDATECOMMANDS:
  872. pCmd->cmdf = OLECMDF_SUPPORTED;
  873. break;
  874. case OLECMDID_NEW:
  875. case OLECMDID_OPEN:
  876. case OLECMDID_SAVE:
  877. pCmd->cmdf = (MSOCMDF_SUPPORTED | MSOCMDF_ENABLED);
  878. break;
  879. }
  880. }
  881. return (hr);
  882. }
  883. /*
  884. * IOleCommandTarget::Exec
  885. */
  886. STDMETHODIMP CProxyFrame::Exec( const GUID* pguidCmdGroup, DWORD nCmdID,
  887. DWORD /*nCmdexecopt*/, VARIANTARG* /*pvaIn*/, VARIANTARG* /*pvaOut*/ )
  888. {
  889. HRESULT hr = S_OK;
  890. if ( pguidCmdGroup == NULL )
  891. {
  892. switch (nCmdID)
  893. {
  894. case OLECMDID_UPDATECOMMANDS:
  895. {
  896. // Fires event to container.
  897. m_pCtl->Fire_DisplayChanged();
  898. hr = S_OK;
  899. }
  900. break;
  901. default:
  902. hr = OLECMDERR_E_NOTSUPPORTED;
  903. break;
  904. }
  905. }
  906. else
  907. {
  908. hr = OLECMDERR_E_UNKNOWNGROUP;
  909. }
  910. return (hr);
  911. }
  912. // Connector from control to site.
  913. //
  914. void
  915. CProxyFrame::UpdateObjectRects()
  916. {
  917. _ASSERTE ( m_pSite );
  918. if ( NULL != m_pSite )
  919. {
  920. m_pSite->UpdateObjectRects();
  921. }
  922. }
  923. // Called from the control's TranslateAccelerator.
  924. // Try our own (VID-like) acclerators first, and if not handled pass them along to TriEdit.
  925. //
  926. HRESULT
  927. CProxyFrame::HrTranslateAccelerator(LPMSG lpmsg)
  928. {
  929. HRESULT hr = S_OK;
  930. if (NULL != m_pIOleIPActiveObject)
  931. {
  932. _ASSERTE(lpmsg);
  933. hr = HrHandleAccelerator(lpmsg);
  934. if (hr != S_OK)
  935. {
  936. _ASSERTE(SUCCEEDED(hr));
  937. hr = m_pIOleIPActiveObject->TranslateAccelerator(lpmsg);
  938. }
  939. }
  940. return hr;
  941. }
  942. // A lot of time was lost here in scenarios like clicking on/tabbing to a control
  943. // embedded in a VB OCX, tabbing to a control on a page, etc.
  944. // Exercise great caution and perform a lot of testing if this is changed.
  945. //
  946. LRESULT
  947. CProxyFrame::OnSetFocus(UINT /*nMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& bHandled)
  948. {
  949. if ( ! m_pCtl->m_bUIActive )
  950. {
  951. m_pCtl->DoVerbUIActivate ( NULL, NULL );
  952. }
  953. // Give the focus to the ActiveX Document window
  954. if ( m_hWndObj != NULL )
  955. {
  956. ::SetFocus( m_hWndObj );
  957. bHandled = TRUE;
  958. }
  959. // activate Trident with "Show"
  960. m_pSite->Activate(OLEIVERB_SHOW);
  961. return 0;
  962. }
  963. // Sets the Trident window's parent correctly when created and destroyed.
  964. //
  965. void
  966. CProxyFrame::SetParent ( HWND hwndParent )
  967. {
  968. // This may be called before the control has been drawn.
  969. if ( NULL != m_hWndObj )
  970. {
  971. if( hwndParent )
  972. {
  973. HWND hwndOldParent = ::SetParent ( m_hWndObj, hwndParent );
  974. if ( NULL == hwndOldParent )
  975. {
  976. DWORD dwErr = 0;
  977. dwErr = GetLastError ();
  978. }
  979. _ASSERTE ( m_pSite );
  980. m_pSite->SetWindow ( hwndParent );
  981. }
  982. }
  983. }
  984. // Handles WM_SHOWWINDOW messages directed to the control.
  985. //
  986. void
  987. CProxyFrame::Show ( WPARAM nCmdShow )
  988. {
  989. // This may be called before the control has been drawn.
  990. // Hide or show the hosted Trident
  991. if ( NULL != m_hWndObj )
  992. {
  993. ::ShowWindow ( m_hWndObj, (int)nCmdShow );
  994. }
  995. }
  996. ///////////////////////////////////////////////////////////////////////////////////////////
  997. //
  998. // ExecCommand mechanism
  999. //
  1000. ///////////////////////////////////////////////////////////////////////////////////////////
  1001. // Convert a command ID into a TriEdit command ID.
  1002. // Some commands used to represent other command groups as well, thus the ppguidCmdGroup parameter.
  1003. // While this does little now, it may be useful again in the future.
  1004. //
  1005. HRESULT
  1006. CProxyFrame::HrMapCommand(DHTMLEDITCMDID typeLibCmdID,
  1007. ULONG* cmdID, const GUID** ppguidCmdGroup, BOOL* pbOutParam)
  1008. {
  1009. _ASSERTE(cmdID);
  1010. _ASSERTE(ppguidCmdGroup);
  1011. _ASSERTE(pbOutParam);
  1012. *cmdID = 0;
  1013. *ppguidCmdGroup = NULL;
  1014. *pbOutParam = FALSE;
  1015. for (UINT i=0; i < sizeof(cmdMap)/sizeof(CommandMap); ++i)
  1016. {
  1017. if (typeLibCmdID == cmdMap[i].typeLibCmdID)
  1018. {
  1019. *cmdID = cmdMap[i].cmdID;
  1020. *ppguidCmdGroup = &GUID_TriEditCommandGroup;
  1021. *pbOutParam = cmdMap[i].bOutParam;
  1022. return S_OK;
  1023. }
  1024. }
  1025. return OLECMDERR_E_NOTSUPPORTED ;
  1026. }
  1027. // Helper routine for calling Exec.
  1028. //
  1029. HRESULT
  1030. CProxyFrame::HrExecCommand(const GUID* pguidCmdGroup, ULONG ucmdID,
  1031. OLECMDEXECOPT cmdexecopt, VARIANT* pVarIn, VARIANT* pVarOut)
  1032. {
  1033. HRESULT hr = E_FAIL;
  1034. LPOLECOMMANDTARGET pCommandTarget = NULL;
  1035. // note that it is valid for pguidCmdGroup to be NULL
  1036. _ASSERTE(m_pSite);
  1037. if (NULL == m_pSite)
  1038. return E_UNEXPECTED;
  1039. pCommandTarget = m_pSite->GetCommandTarget();
  1040. _ASSERTE(pCommandTarget);
  1041. if (pCommandTarget != NULL)
  1042. {
  1043. hr = pCommandTarget->Exec(pguidCmdGroup, ucmdID, cmdexecopt, pVarIn, pVarOut);
  1044. }
  1045. return hr;
  1046. }
  1047. // Main command dispatcher; called from the control's ExecCommand method.
  1048. // Handle our unique commands here, pass the rest onto HrExecGenericCommands.
  1049. //
  1050. HRESULT
  1051. CProxyFrame::HrMapExecCommand(DHTMLEDITCMDID deCommand, OLECMDEXECOPT cmdexecopt,
  1052. VARIANT* pVarInput, VARIANT* pVarOutput)
  1053. {
  1054. HRESULT hr = S_OK;
  1055. LPOLECOMMANDTARGET pCmdTgt = NULL;
  1056. ULONG ulMappedCommand = 0;
  1057. const GUID* pguidCmdGroup = NULL;
  1058. BOOL bOutParam = FALSE;
  1059. if (FALSE == m_fActivated)
  1060. return E_UNEXPECTED;
  1061. _ASSERTE(m_pSite);
  1062. if (NULL == m_pSite)
  1063. return E_UNEXPECTED;
  1064. pCmdTgt = m_pSite->GetCommandTarget();
  1065. _ASSERTE(pCmdTgt);
  1066. if (NULL == pCmdTgt)
  1067. return E_UNEXPECTED;
  1068. // Its valid for pVarInput to be NULL
  1069. if (FAILED(hr = HrMapCommand(deCommand, &ulMappedCommand, &pguidCmdGroup, &bOutParam)))
  1070. return hr;
  1071. AssureActivated();
  1072. switch ( deCommand )
  1073. {
  1074. case DECMD_GETBLOCKFMTNAMES:
  1075. hr = HrExecGetBlockFmtNames(pVarInput);
  1076. break;
  1077. case DECMD_INSERTTABLE:
  1078. hr = HrExecInsertTable(pVarInput);
  1079. break;
  1080. case DECMD_GETFORECOLOR:
  1081. case DECMD_GETBACKCOLOR:
  1082. hr = HrExecGetColor(deCommand, ulMappedCommand, pVarOutput);
  1083. break;
  1084. case DECMD_SETFONTSIZE:
  1085. hr = HrExecSetFontSize(pVarInput);
  1086. break;
  1087. case DECMD_GETBLOCKFMT:
  1088. // Trident inconsistancy: GetBlockFmt fails if outparam isn't a BSTR. GetFontName is OK with VT_EMPTY
  1089. VariantChangeType ( pVarOutput, pVarOutput, 0, VT_BSTR );
  1090. // Fall through; do not break!
  1091. case DECMD_GETFONTNAME:
  1092. case DECMD_GETFONTSIZE:
  1093. hr = HrExecGenericCommands(pguidCmdGroup, ulMappedCommand, cmdexecopt, pVarOutput, TRUE );
  1094. break;
  1095. // Because our QueryStatus on DECMD_PROPERTIES returns TRUE for anything with IOleObject, executing the properties
  1096. // verb can return an unexpected error. Therefore, we ALWAYS return S_OK from this command to avoid causing VB and
  1097. // script to terminate.
  1098. case DECMD_PROPERTIES:
  1099. {
  1100. CComVariant varParam;
  1101. varParam.vt = VT_I4;
  1102. varParam.lVal = OLEIVERB_PROPERTIES;
  1103. hr = HrExecGenericCommands(pguidCmdGroup, ulMappedCommand, cmdexecopt, &varParam, FALSE );
  1104. hr = S_OK;
  1105. }
  1106. break;
  1107. default:
  1108. hr = HrExecGenericCommands(pguidCmdGroup, ulMappedCommand, cmdexecopt, pVarInput, bOutParam);
  1109. break;
  1110. }
  1111. if (FAILED(hr))
  1112. {
  1113. if (DISP_E_BADVARTYPE == hr || DISP_E_MEMBERNOTFOUND == hr)
  1114. {
  1115. // Map these Trident errors to something more general.
  1116. // These errors can occur if Trident expected the element
  1117. // it was trying to operate on to support certain interfaces.
  1118. // The caller was trying to perform an operation not valid
  1119. // for the current selection. Probably didn't call QueryStatus
  1120. // first.
  1121. hr = OLECMDERR_E_NOTSUPPORTED;
  1122. }
  1123. }
  1124. return hr;
  1125. }
  1126. ///////////////////////////////////////////////////////////////////////////////////////////
  1127. //
  1128. // ExecCommand handler implementations
  1129. //
  1130. ///////////////////////////////////////////////////////////////////////////////////////////
  1131. // Helper routine for calling Exec and dealing with results.
  1132. //
  1133. HRESULT
  1134. CProxyFrame::HrExecGenericCommands(const GUID* pguidCmdGroup, ULONG cmdID,
  1135. OLECMDEXECOPT cmdexecopt, LPVARIANT pVarInput, BOOL bOutParam)
  1136. {
  1137. HRESULT hr = S_OK;
  1138. LPOLECOMMANDTARGET pCmdTgt = NULL;
  1139. LPVARIANT _pVar = NULL;
  1140. VARIANT varCopy;
  1141. pCmdTgt = m_pSite->GetCommandTarget();
  1142. if (pVarInput && V_VT(pVarInput) & VT_BYREF)
  1143. {
  1144. // convert VARIANTARGs to Variant for use by Trident
  1145. // this occurs in VB if the user specified a basic type
  1146. // as an arg, i.e., String or Long, instead of Variant
  1147. VariantInit(&varCopy);
  1148. if (FAILED(hr = VariantCopyInd(&varCopy, pVarInput)))
  1149. {
  1150. _ASSERTE(SUCCEEDED(hr));
  1151. return hr;
  1152. }
  1153. _pVar = &varCopy;
  1154. }
  1155. else if (pVarInput)
  1156. _pVar = pVarInput;
  1157. if (bOutParam)
  1158. {
  1159. hr = pCmdTgt->Exec(pguidCmdGroup, cmdID, cmdexecopt, NULL, _pVar);
  1160. }
  1161. else
  1162. {
  1163. hr = pCmdTgt->Exec(pguidCmdGroup, cmdID, cmdexecopt, _pVar, NULL);
  1164. }
  1165. if (FAILED(hr))
  1166. goto cleanup;
  1167. // if a VARIANTARG was passed in for a command with output then
  1168. // fill it in with the result from the Exec
  1169. if (bOutParam && pVarInput && (V_VT(pVarInput) & VT_BYREF))
  1170. {
  1171. _ASSERTE(_pVar); // _pVar should always be non NULL here
  1172. // if there was an input arg that was byref,
  1173. // then it should have been mapped to _pVar
  1174. if (NULL == _pVar)
  1175. return E_UNEXPECTED; // the catch all error return for "we are in a weird state"
  1176. // if the type of return is different that the type the caller
  1177. // passed in then do nothing and return
  1178. if (V_VT(_pVar) != (V_VT(pVarInput) ^ VT_BYREF))
  1179. return hr;
  1180. switch(V_VT(_pVar))
  1181. {
  1182. case VT_BSTR:
  1183. _ASSERTE(V_VT(pVarInput) == (VT_BSTR|VT_BYREF));
  1184. if (V_BSTRREF(pVarInput))
  1185. hr = SysReAllocString(V_BSTRREF(pVarInput), V_BSTR(_pVar));
  1186. break;
  1187. case VT_BOOL:
  1188. _ASSERTE(V_VT(pVarInput) == (VT_BOOL|VT_BYREF));
  1189. if (V_BOOLREF(pVarInput))
  1190. *(V_BOOLREF(pVarInput)) = V_BOOL(_pVar);
  1191. break;
  1192. case VT_I4:
  1193. _ASSERTE(V_VT(pVarInput) == (VT_I4|VT_BYREF));
  1194. if (V_I4REF(pVarInput))
  1195. *(V_I4REF(pVarInput)) = V_I4(_pVar);
  1196. break;
  1197. default:
  1198. _ASSERTE(0);
  1199. break;
  1200. }
  1201. }
  1202. cleanup:
  1203. // Our documentation replaces E_FAIL with DE_E_UNEXPECTED: different values.
  1204. if ( E_FAIL == hr )
  1205. {
  1206. hr = DE_E_UNEXPECTED;
  1207. }
  1208. return hr;
  1209. }
  1210. // Handler for command DECMD_GETBLOCKFMTNAMES.
  1211. // There are plenty of possible types of arrays to be handled.
  1212. //
  1213. HRESULT
  1214. CProxyFrame::HrExecGetBlockFmtNames(LPVARIANT pVarInput)
  1215. {
  1216. HRESULT hr = S_OK;
  1217. LPOLECOMMANDTARGET pCmdTgt = NULL;
  1218. VARIANT varArray;
  1219. LPUNKNOWN pUnk = NULL;
  1220. CComPtr<IDEGetBlockFmtNamesParam> piNamesParam;
  1221. pCmdTgt = m_pSite->GetCommandTarget();
  1222. if (NULL == pVarInput)
  1223. return E_INVALIDARG;
  1224. if (V_VT(pVarInput) == (VT_BYREF|VT_DISPATCH))
  1225. {
  1226. if (V_DISPATCHREF(pVarInput))
  1227. pUnk = *(V_DISPATCHREF(pVarInput));
  1228. else
  1229. return E_INVALIDARG;
  1230. }
  1231. else if (V_VT(pVarInput) == VT_DISPATCH)
  1232. {
  1233. if (V_DISPATCH(pVarInput))
  1234. pUnk = V_DISPATCH(pVarInput);
  1235. else
  1236. return E_INVALIDARG;
  1237. }
  1238. else if (V_VT(pVarInput) == (VT_BYREF|VT_UNKNOWN))
  1239. {
  1240. if (V_UNKNOWNREF(pVarInput))
  1241. pUnk = *(V_UNKNOWNREF(pVarInput));
  1242. else
  1243. return E_INVALIDARG;
  1244. }
  1245. else if (V_VT(pVarInput) == VT_UNKNOWN)
  1246. {
  1247. if (V_UNKNOWN(pVarInput))
  1248. pUnk = V_UNKNOWN(pVarInput);
  1249. else
  1250. return E_INVALIDARG;
  1251. }
  1252. else
  1253. return E_INVALIDARG;
  1254. // This can happen in VB if an object that has not
  1255. // been set with CreateObject has been passed in
  1256. if (NULL == pUnk)
  1257. return E_INVALIDARG;
  1258. // Try to get the names object before
  1259. // performing the command
  1260. if (FAILED(hr = pUnk->QueryInterface(IID_IDEGetBlockFmtNamesParam, (LPVOID*) &piNamesParam)))
  1261. return E_INVALIDARG;
  1262. _ASSERTE((!piNamesParam) == FALSE);
  1263. // Trident wants the vt to be specifically VT_ARRAY with
  1264. // no type qualifer -- if you give one it fails even though
  1265. // an array of BSTRs is returned
  1266. VariantInit(&varArray);
  1267. V_VT(&varArray) = VT_ARRAY;
  1268. hr = pCmdTgt->Exec(&GUID_TriEditCommandGroup, IDM_TRIED_GETBLOCKFMTS,
  1269. MSOCMDEXECOPT_DONTPROMPTUSER, NULL, &varArray);
  1270. if (FAILED(hr))
  1271. goto cleanup;
  1272. piNamesParam->put_Names(&varArray);
  1273. cleanup:
  1274. return hr;
  1275. }
  1276. // Handler for command DECMD_INSERTTABLE.
  1277. //
  1278. HRESULT
  1279. CProxyFrame::HrExecInsertTable(LPVARIANT pVarInput)
  1280. {
  1281. HRESULT hr = S_OK;
  1282. LPOLECOMMANDTARGET pCmdTgt = NULL;
  1283. VARIANT varTableArray;
  1284. LPUNKNOWN pUnk = NULL;
  1285. CComPtr<IDEInsertTableParam> piTableParam;
  1286. pCmdTgt = m_pSite->GetCommandTarget();
  1287. VariantInit(&varTableArray);
  1288. if (NULL == pVarInput)
  1289. return E_INVALIDARG;
  1290. if (V_VT(pVarInput) == (VT_BYREF|VT_DISPATCH))
  1291. {
  1292. if (V_DISPATCHREF(pVarInput))
  1293. pUnk = *(V_DISPATCHREF(pVarInput));
  1294. else
  1295. return E_INVALIDARG;
  1296. }
  1297. else if (V_VT(pVarInput) == VT_DISPATCH)
  1298. {
  1299. if (V_DISPATCH(pVarInput))
  1300. pUnk = V_DISPATCH(pVarInput);
  1301. else
  1302. return E_INVALIDARG;
  1303. }
  1304. else if (V_VT(pVarInput) == (VT_BYREF|VT_UNKNOWN))
  1305. {
  1306. if (V_UNKNOWNREF(pVarInput))
  1307. pUnk = *(V_UNKNOWNREF(pVarInput));
  1308. else
  1309. return E_INVALIDARG;
  1310. }
  1311. else if (V_VT(pVarInput) == VT_UNKNOWN)
  1312. {
  1313. if (V_UNKNOWN(pVarInput))
  1314. pUnk = V_UNKNOWN(pVarInput);
  1315. else
  1316. return E_INVALIDARG;
  1317. }
  1318. else
  1319. return E_INVALIDARG;
  1320. // This can happen in VB if an object that has not
  1321. // been set with CreateObject has been passed in
  1322. if (NULL == pUnk)
  1323. return E_INVALIDARG;
  1324. if (FAILED(hr = pUnk->QueryInterface(IID_IDEInsertTableParam, (LPVOID*) &piTableParam)))
  1325. return E_INVALIDARG;
  1326. _ASSERTE((!piTableParam) == FALSE);
  1327. if (FAILED(hr = HrGetTableSafeArray(piTableParam, &varTableArray)))
  1328. {
  1329. _ASSERTE(SUCCEEDED(hr));
  1330. return hr;
  1331. }
  1332. hr = pCmdTgt->Exec(&GUID_TriEditCommandGroup, IDM_TRIED_INSERTTABLE,
  1333. MSOCMDEXECOPT_DONTPROMPTUSER, &varTableArray, NULL);
  1334. return hr;
  1335. }
  1336. // Hanlder for commands DECMD_GETFORECOLOR and DECMD_GETBACKCOLOR.
  1337. // Reply with a string in the format #RRGGBB or an empty string.
  1338. //
  1339. HRESULT
  1340. CProxyFrame::HrExecGetColor(DHTMLEDITCMDID deCommand, ULONG ulMappedCommand, LPVARIANT pVarOutput)
  1341. {
  1342. USES_CONVERSION;
  1343. HRESULT hr = S_OK;
  1344. LPOLECOMMANDTARGET pCmdTgt = NULL;
  1345. VARIANT varColorOut;
  1346. TCHAR buf[32];
  1347. WCHAR* oleStr = NULL;
  1348. pCmdTgt = m_pSite->GetCommandTarget();
  1349. if (NULL == pVarOutput)
  1350. return E_INVALIDARG;
  1351. // validate the command
  1352. if (DECMD_GETFORECOLOR != deCommand && DECMD_GETBACKCOLOR != deCommand)
  1353. return E_INVALIDARG;
  1354. // validate the args
  1355. if (V_VT(pVarOutput) == (VT_BYREF|VT_BSTR))
  1356. {
  1357. if (NULL == V_BSTRREF(pVarOutput))
  1358. return E_INVALIDARG;
  1359. }
  1360. else if (V_VT(pVarOutput) == VT_BSTR)
  1361. {
  1362. if (NULL == V_BSTR(pVarOutput))
  1363. return E_INVALIDARG;
  1364. }
  1365. else if (V_VT(pVarOutput) != (VT_EMPTY) && V_VT(pVarOutput) != (VT_NULL))
  1366. return E_INVALIDARG;
  1367. VariantInit(&varColorOut);
  1368. V_VT(&varColorOut) = VT_I4;
  1369. hr = pCmdTgt->Exec(&GUID_TriEditCommandGroup, ulMappedCommand,
  1370. MSOCMDEXECOPT_DONTPROMPTUSER, NULL, &varColorOut);
  1371. // Trident will return VT_NULL if color selection
  1372. // was mixed or no text is selected, we return empty
  1373. // string ("") in that case.
  1374. buf[0] = 0;
  1375. if (VT_I4 == V_VT(&varColorOut))
  1376. {
  1377. ULONG ulColor = 0;
  1378. ULONG r=0;
  1379. ULONG g=0;
  1380. ULONG b=0;
  1381. ulColor = V_I4(&varColorOut);
  1382. r = 0x000000ff & ulColor;
  1383. g = (0x0000ff00 & ulColor) >> 8;
  1384. b = (0x00ff0000 & ulColor) >> 16;
  1385. wsprintf(buf, TEXT("#%02X%02X%02X"), r, g, b);
  1386. }
  1387. oleStr = T2OLE(buf);
  1388. if (V_VT(pVarOutput) == (VT_BSTR|VT_BYREF))
  1389. hr = SysReAllocString(V_BSTRREF(pVarOutput), oleStr);
  1390. else if (V_VT(pVarOutput) == (VT_BSTR))
  1391. hr = SysReAllocString(&(V_BSTR(pVarOutput)), oleStr);
  1392. else if (V_VT(pVarOutput) == (VT_EMPTY) || V_VT(pVarOutput) == (VT_NULL))
  1393. {
  1394. V_VT(pVarOutput) = VT_BSTR;
  1395. V_BSTR(pVarOutput) = SysAllocString(oleStr);
  1396. }
  1397. return hr;
  1398. }
  1399. // Handler for command DECMD_SETFONTSIZE.
  1400. //
  1401. HRESULT
  1402. CProxyFrame::HrExecSetFontSize(LPVARIANT pVarInput)
  1403. {
  1404. HRESULT hr = S_OK;
  1405. LPOLECOMMANDTARGET pCmdTgt = NULL;
  1406. VARIANT varSizeIn;
  1407. pCmdTgt = m_pSite->GetCommandTarget();
  1408. if (NULL == pVarInput)
  1409. return E_INVALIDARG;
  1410. VariantInit(&varSizeIn);
  1411. if (FAILED(hr = VariantChangeType(&varSizeIn, pVarInput, 0, VT_I4)))
  1412. return E_INVALIDARG;
  1413. if (varSizeIn.lVal < 0 || varSizeIn.lVal > 7)
  1414. return E_INVALIDARG;
  1415. if (0 == varSizeIn.lVal)
  1416. varSizeIn.lVal = varSizeIn.lVal + 1;
  1417. hr = pCmdTgt->Exec(&GUID_TriEditCommandGroup, IDM_TRIED_FONTSIZE,
  1418. MSOCMDEXECOPT_DONTPROMPTUSER, &varSizeIn, NULL);
  1419. return hr;
  1420. }
  1421. ///////////////////////////////////////////////////////////////////////////////////////////
  1422. //
  1423. // QueryStatus mechanism
  1424. //
  1425. ///////////////////////////////////////////////////////////////////////////////////////////
  1426. // Map the control specific command ID to a TriEdit command ID and call QueryStatus.
  1427. //
  1428. HRESULT
  1429. CProxyFrame::HrMapQueryStatus( DHTMLEDITCMDID ucmdID, DHTMLEDITCMDF* cmdf)
  1430. {
  1431. LPOLECOMMANDTARGET pCommandTarget = NULL;
  1432. _ASSERTE(cmdf);
  1433. HRESULT hr = E_FAIL;
  1434. if (FALSE == m_fActivated)
  1435. return E_UNEXPECTED;
  1436. if (NULL == cmdf)
  1437. return E_INVALIDARG;
  1438. *cmdf = (DHTMLEDITCMDF) 0;
  1439. _ASSERTE(m_pSite);
  1440. if (NULL == m_pSite)
  1441. return E_UNEXPECTED;
  1442. pCommandTarget = m_pSite->GetCommandTarget();
  1443. _ASSERTE(pCommandTarget);
  1444. if ( pCommandTarget != NULL )
  1445. {
  1446. AssureActivated ();
  1447. ULONG cmdID = 0;
  1448. const GUID* pguidCmdGroup = NULL;
  1449. BOOL bOutParam = FALSE;
  1450. if (SUCCEEDED(hr = HrMapCommand(ucmdID, &cmdID, &pguidCmdGroup, &bOutParam)))
  1451. {
  1452. MSOCMD msocmd;
  1453. msocmd.cmdID = cmdID;
  1454. msocmd.cmdf = 0;
  1455. hr = pCommandTarget->QueryStatus(pguidCmdGroup, 1, &msocmd, NULL);
  1456. *cmdf = (DHTMLEDITCMDF) msocmd.cmdf;
  1457. }
  1458. }
  1459. return hr;
  1460. }
  1461. // General routine for determining the status of a command.
  1462. // Should resolve to not supported, disabled, enabled, latched or ninched.
  1463. //
  1464. HRESULT
  1465. CProxyFrame::HrQueryStatus(const GUID* pguidCmdGroup, ULONG ucmdID, OLECMDF* cmdf)
  1466. {
  1467. HRESULT hr = E_FAIL;
  1468. _ASSERTE(cmdf);
  1469. // Note that it is valid for pguidCmdGroup to be NULL
  1470. if (NULL == cmdf)
  1471. return E_INVALIDARG;
  1472. *cmdf = (OLECMDF) 0;
  1473. _ASSERTE(m_pSite);
  1474. if ( m_pSite != NULL ) // m_pSite should always be set
  1475. {
  1476. LPOLECOMMANDTARGET pCommandTarget = m_pSite->GetCommandTarget();
  1477. if ( pCommandTarget != NULL )
  1478. {
  1479. MSOCMD msocmd;
  1480. msocmd.cmdID = ucmdID;
  1481. msocmd.cmdf = 0;
  1482. hr = pCommandTarget->QueryStatus(pguidCmdGroup, 1, &msocmd, NULL);
  1483. *cmdf = (OLECMDF) msocmd.cmdf;
  1484. }
  1485. }
  1486. return hr;
  1487. }
  1488. // A tragic FAT16 compatibility problem: file names in the specific form:
  1489. // [a-zA-z]\:[^\\].+ cause various, severe problems. NTFS "forgives".
  1490. // We must detect these, both in file names and file:// URL and return an error.
  1491. //
  1492. BOOL
  1493. CProxyFrame::IsMissingBackSlash ( BSTR path, BOOL bfIsURL )
  1494. {
  1495. BOOL bfMissing = FALSE;
  1496. if ( bfIsURL )
  1497. {
  1498. WCHAR wszFileProtocol[] = L"file://";
  1499. int cchProtocol = wcslen ( wszFileProtocol );
  1500. if ( 0 == _wcsnicmp ( path, wszFileProtocol, cchProtocol ) )
  1501. {
  1502. if ( OLECHAR(':') == path[cchProtocol+1] )
  1503. {
  1504. if ( OLECHAR('\\') != path[cchProtocol+2] )
  1505. {
  1506. bfMissing = TRUE;
  1507. }
  1508. }
  1509. }
  1510. }
  1511. else
  1512. {
  1513. // Path name. chec for drive letter, colon, non-backslash.
  1514. if ( OLECHAR(':') == path[1] )
  1515. {
  1516. if ( OLECHAR('\\') != path[2] )
  1517. {
  1518. bfMissing = TRUE;
  1519. }
  1520. }
  1521. }
  1522. return bfMissing;
  1523. }
  1524. ///////////////////////////////////////////////////////////////////////////////////////////
  1525. //
  1526. // Control methods and properties
  1527. //
  1528. ///////////////////////////////////////////////////////////////////////////////////////////
  1529. // Handles NewDocument, LoadURL and LoadDocument control methods.
  1530. // The document is loaded indirectly via the pluggable protocol handler.
  1531. // If "path" is NULL, do NewDocument. TestbfURL to see if it's a URL or UNC path.
  1532. //
  1533. HRESULT
  1534. CProxyFrame::LoadDocument(BSTR path, BOOL bfIsURL )
  1535. {
  1536. USES_CONVERSION;
  1537. HRESULT hr = S_OK;
  1538. UINT pathLen = 0;
  1539. AssureActivated (); // This can set m_bstrLoadText as a side effect in unactivated controls! Be careful!
  1540. if (FALSE == m_fActivated)
  1541. return E_UNEXPECTED;
  1542. m_bstrLoadText.Empty (); // Clear the text to be added directly, or it will be used instead!
  1543. m_bstrCurDocPath = L"";
  1544. m_bstrBaseURL = L"";
  1545. if (path)
  1546. pathLen = ::SysStringLen(path);
  1547. else
  1548. pathLen = 0;
  1549. // We've resetting the contents of the control. Go back to default save mechanism.
  1550. // If we load Unicode it will be reset.
  1551. m_pSite->SetSaveAsUnicode ( FALSE );
  1552. if (path && pathLen)
  1553. {
  1554. _ASSERTE(path);
  1555. _ASSERTE(pathLen > 0);
  1556. // First, look out for a wicked error: X:FileName with no '\' is BAD on FAT16.
  1557. if ( IsMissingBackSlash ( path, bfIsURL ) )
  1558. {
  1559. hr = DE_E_PATH_NOT_FOUND;
  1560. LoadBSTRDeferred ( m_bstrInitialDoc );
  1561. goto error;
  1562. }
  1563. // Try to open the file -- stop the sequence
  1564. // if its bogus or we don't have access
  1565. if ( !bfIsURL )
  1566. {
  1567. if (FAILED(hr = m_pSite->HrTestFileOpen(path)))
  1568. {
  1569. LoadBSTRDeferred ( m_bstrInitialDoc );
  1570. goto error;
  1571. }
  1572. }
  1573. m_bfIsURL = bfIsURL;
  1574. m_bstrCurDocPath = path; // This needs to be set before loading, because base url is needed durring load.
  1575. SetBaseURLFromCurDocPath ( bfIsURL );
  1576. m_bfPreserveDirtyFlagAcrossBrowseMode = FALSE;
  1577. CComPtr<IMoniker> srpMoniker;
  1578. CComPtr<IBindCtx> srpBindCtx;
  1579. CComQIPtr<IPersistMoniker, &IID_IPersistMoniker> srpPM (m_pUnkTriEdit);
  1580. _ASSERTE ( srpPM );
  1581. if ( srpPM )
  1582. {
  1583. CComBSTR bstrProtocol = m_wszProtocolPrefix;
  1584. bstrProtocol += L"(";
  1585. bstrProtocol += path;
  1586. bstrProtocol += L")";
  1587. #ifdef LATE_BIND_URLMON_WININET
  1588. _ASSERTE ( m_pfnCreateURLMoniker );
  1589. hr = (*m_pfnCreateURLMoniker)( NULL, bstrProtocol, &srpMoniker );
  1590. #else
  1591. hr = CreateURLMoniker ( NULL, bstrProtocol, &srpMoniker );
  1592. #endif // LATE_BIND_URLMON_WININET
  1593. _ASSERTE ( SUCCEEDED( hr ) );
  1594. if ( SUCCEEDED ( hr ) )
  1595. {
  1596. hr = ::CreateBindCtx(NULL, &srpBindCtx);
  1597. _ASSERTE ( SUCCEEDED( hr ) );
  1598. if ( SUCCEEDED ( hr ) )
  1599. {
  1600. // Delete the cache entry before downloading.
  1601. // This assures that loading, posting, and reloading works.
  1602. // Bug 18544.
  1603. // NOTE: Inexact match fails! http://www.microsoft.com fails,
  1604. // because this actually loads/caches a specific default page.
  1605. if ( bfIsURL )
  1606. {
  1607. LPTSTR szURL = OLE2T ( m_bstrCurDocPath );
  1608. #ifdef LATE_BIND_URLMON_WININET
  1609. _ASSERTE ( m_pfnDeleteUrlCacheEntry );
  1610. (*m_pfnDeleteUrlCacheEntry)( szURL );
  1611. #else
  1612. DeleteUrlCacheEntry ( szURL );
  1613. #endif // LATE_BIND_URLMON_WININET
  1614. }
  1615. m_bfIsLoading = TRUE;
  1616. m_hrDeferredLoadError = S_OK; // URLs: don't let Trident get the error!
  1617. hr = srpPM->Load(FALSE, srpMoniker, srpBindCtx, STGM_READ);
  1618. if ( SUCCEEDED ( hr ) && FAILED ( m_hrDeferredLoadError ) )
  1619. {
  1620. hr = m_hrDeferredLoadError; // In case we stashed a result
  1621. }
  1622. if ( FAILED ( hr ) )
  1623. {
  1624. m_bfIsLoading = FALSE;
  1625. }
  1626. }
  1627. }
  1628. }
  1629. }
  1630. else
  1631. {
  1632. if (FAILED(hr = LoadBSTRDeferred ( m_bstrInitialDoc )))
  1633. {
  1634. _ASSERTE(SUCCEEDED(hr));
  1635. goto error;
  1636. }
  1637. }
  1638. error:
  1639. return hr;
  1640. }
  1641. // Implements FilterSourceCode control method
  1642. // Used to restore filtered content extracted directly from DOM.
  1643. //
  1644. HRESULT
  1645. CProxyFrame::FilterSourceCode ( BSTR bsSourceIn, BSTR* pbsSourceOut )
  1646. {
  1647. HRESULT hr;
  1648. CComPtr<IStream> spStreamIn;
  1649. IStream* piStreamOut;
  1650. hr = m_pSite->HrBstrToStream(bsSourceIn, &spStreamIn);
  1651. if ( SUCCEEDED ( hr ) )
  1652. {
  1653. if ( m_vbBrowseMode )
  1654. {
  1655. spStreamIn.p->AddRef ();
  1656. piStreamOut = spStreamIn;
  1657. }
  1658. else
  1659. {
  1660. hr = m_pSite->HrFilter ( FALSE, spStreamIn, &piStreamOut, m_dwFilterOutFlags | dwFilterSourceCode);
  1661. }
  1662. if ( SUCCEEDED ( hr ) )
  1663. {
  1664. hr = m_pSite->HrStreamToBstr ( piStreamOut, pbsSourceOut );
  1665. piStreamOut->Release ();
  1666. }
  1667. }
  1668. return hr;
  1669. }
  1670. // Implements the control's Print method
  1671. //
  1672. HRESULT
  1673. CProxyFrame::Print ( BOOL bfWithUI )
  1674. {
  1675. AssureActivated ();
  1676. if (FALSE == m_fActivated)
  1677. return E_UNEXPECTED;
  1678. return HrExecCommand ( &GUID_TriEditCommandGroup, IDM_TRIED_PRINT,
  1679. bfWithUI ? MSOCMDEXECOPT_PROMPTUSER : MSOCMDEXECOPT_DONTPROMPTUSER, NULL, NULL );
  1680. }
  1681. // Implements the control's Refresh method
  1682. //
  1683. HRESULT
  1684. CProxyFrame::RefreshDoc ()
  1685. {
  1686. if ( NULL != m_hWndObj )
  1687. {
  1688. if ( ::IsWindow ( m_hWndObj ) )
  1689. {
  1690. ::InvalidateRect ( m_hWndObj, NULL, TRUE );
  1691. return S_OK;
  1692. }
  1693. }
  1694. return S_FALSE;
  1695. }
  1696. // Implements the control's SaveDocument method
  1697. //
  1698. HRESULT
  1699. CProxyFrame::SaveDocument(BSTR path)
  1700. {
  1701. HRESULT hr = S_OK;
  1702. ULONG pathLen = 0;
  1703. if (FALSE == m_fActivated)
  1704. return E_UNEXPECTED;
  1705. _ASSERTE(GetState() == ESTATE_ACTIVATED);
  1706. AssureActivated ();
  1707. if (GetState() != ESTATE_ACTIVATED)
  1708. return E_UNEXPECTED;
  1709. _ASSERTE(path);
  1710. if (path)
  1711. pathLen = ::SysStringLen(path);
  1712. else
  1713. pathLen = 0;
  1714. if (0 == pathLen)
  1715. return E_INVALIDARG;
  1716. _ASSERTE(pathLen);
  1717. // First, look out for a wicked error: X:FileName with no '\' is BAD on FAT16.
  1718. if ( IsMissingBackSlash ( path, FALSE ) )
  1719. {
  1720. return DE_E_PATH_NOT_FOUND;
  1721. }
  1722. hr = m_pSite->HrSaveToFile(path, m_dwFilterOutFlags);
  1723. if ( SUCCEEDED ( hr ) )
  1724. {
  1725. m_bstrCurDocPath = path;
  1726. }
  1727. return hr;
  1728. }
  1729. // Implements the control's SetContextMenu method
  1730. // One routine handles javascript arrays, the other simple arrays.
  1731. //
  1732. HRESULT
  1733. CProxyFrame::SetContextMenu(LPVARIANT pVarMenuStrings, LPVARIANT pVarMenuStates)
  1734. {
  1735. if (V_VT(pVarMenuStrings) == VT_DISPATCH || V_VT(pVarMenuStates) == VT_DISPATCH)
  1736. return SetContextMenuDispEx(pVarMenuStrings, pVarMenuStates);
  1737. else
  1738. return SetContextMenuSA(pVarMenuStrings, pVarMenuStates);
  1739. }
  1740. // Get menu strings from SafeArray
  1741. //
  1742. HRESULT
  1743. CProxyFrame::SetContextMenuSA(LPVARIANT pVarMenuStrings, LPVARIANT pVarMenuStates)
  1744. {
  1745. HRESULT hr = S_OK;
  1746. SAFEARRAY* psaStrings = NULL;
  1747. SAFEARRAY* psaStates = NULL;
  1748. LONG lLBound, lUBound, lLBoundState, lUBoundState;
  1749. if (NULL == pVarMenuStrings || NULL == pVarMenuStates)
  1750. return E_INVALIDARG;
  1751. if ((VT_ARRAY|VT_BSTR) != V_VT(pVarMenuStrings) &&
  1752. ((VT_ARRAY|VT_BSTR)|VT_BYREF) != V_VT(pVarMenuStrings) &&
  1753. ((VT_ARRAY|VT_VARIANT)|VT_BYREF) != V_VT(pVarMenuStrings) &&
  1754. (VT_ARRAY|VT_VARIANT) != V_VT(pVarMenuStrings))
  1755. return E_INVALIDARG;
  1756. if ((VT_ARRAY|VT_I4) != V_VT(pVarMenuStates) &&
  1757. ((VT_ARRAY|VT_I4)|VT_BYREF) != V_VT(pVarMenuStates) &&
  1758. ((VT_ARRAY|VT_VARIANT)|VT_BYREF) != V_VT(pVarMenuStates) &&
  1759. (VT_ARRAY|VT_VARIANT) != V_VT(pVarMenuStates))
  1760. return E_INVALIDARG;
  1761. if ((VT_ARRAY|VT_BSTR) == V_VT(pVarMenuStrings))
  1762. {
  1763. psaStrings = V_ARRAY(pVarMenuStrings);
  1764. }
  1765. if ((VT_ARRAY|VT_VARIANT) == V_VT(pVarMenuStrings))
  1766. {
  1767. psaStrings = V_ARRAY(pVarMenuStrings);
  1768. }
  1769. else if ((VT_ARRAY|VT_BSTR|VT_BYREF) == V_VT(pVarMenuStrings))
  1770. {
  1771. if (NULL == V_ARRAYREF(pVarMenuStrings))
  1772. return E_INVALIDARG;
  1773. psaStrings = *(V_ARRAYREF(pVarMenuStrings));
  1774. }
  1775. else if ((VT_ARRAY|VT_VARIANT|VT_BYREF) == V_VT(pVarMenuStrings))
  1776. {
  1777. if (NULL == V_ARRAYREF(pVarMenuStrings))
  1778. return E_INVALIDARG;
  1779. psaStrings = *(V_ARRAYREF(pVarMenuStrings));
  1780. }
  1781. if ((VT_ARRAY|VT_I4) == V_VT(pVarMenuStates))
  1782. {
  1783. psaStates = V_ARRAY(pVarMenuStates);
  1784. }
  1785. if ((VT_ARRAY|VT_VARIANT) == V_VT(pVarMenuStates))
  1786. {
  1787. psaStates = V_ARRAY(pVarMenuStates);
  1788. }
  1789. else if ((VT_ARRAY|VT_I4|VT_BYREF) == V_VT(pVarMenuStates))
  1790. {
  1791. if (NULL == V_ARRAYREF(pVarMenuStates))
  1792. return E_INVALIDARG;
  1793. psaStates = *(V_ARRAYREF(pVarMenuStates));
  1794. }
  1795. else if ((VT_ARRAY|VT_VARIANT|VT_BYREF) == V_VT(pVarMenuStates))
  1796. {
  1797. if (NULL == V_ARRAYREF(pVarMenuStates))
  1798. return E_INVALIDARG;
  1799. psaStates = *(V_ARRAYREF(pVarMenuStates));
  1800. }
  1801. if (NULL == psaStrings || NULL == psaStates)
  1802. return E_INVALIDARG;
  1803. SafeArrayGetLBound(psaStrings, 1, &lLBound);
  1804. SafeArrayGetUBound(psaStrings, 1, &lUBound);
  1805. SafeArrayGetLBound(psaStates, 1, &lLBoundState);
  1806. SafeArrayGetUBound(psaStates, 1, &lUBoundState);
  1807. if (lLBound != lLBoundState || lUBound != lUBoundState)
  1808. return E_INVALIDARG;
  1809. if (m_pMenuStrings)
  1810. {
  1811. SafeArrayDestroy(m_pMenuStrings);
  1812. m_pMenuStrings = NULL;
  1813. }
  1814. if (m_pMenuStates)
  1815. {
  1816. SafeArrayDestroy(m_pMenuStates);
  1817. m_pMenuStates = NULL;
  1818. }
  1819. // An empty array was passed in
  1820. // The context menu has been cleared
  1821. if (lLBound ==lUBound )
  1822. goto cleanup;
  1823. if (FAILED(hr = SafeArrayCopy(psaStrings, &m_pMenuStrings)))
  1824. goto cleanup;
  1825. if (FAILED(hr = SafeArrayCopy(psaStates, &m_pMenuStates)))
  1826. goto cleanup;
  1827. cleanup:
  1828. if (FAILED(hr))
  1829. {
  1830. if (m_pMenuStrings)
  1831. {
  1832. SafeArrayDestroy(m_pMenuStrings);
  1833. m_pMenuStrings = NULL;
  1834. }
  1835. if (m_pMenuStates)
  1836. {
  1837. SafeArrayDestroy(m_pMenuStates);
  1838. m_pMenuStates = NULL;
  1839. }
  1840. }
  1841. return hr;
  1842. }
  1843. // Get menu strings from JScript array, or object that supports IDispatchEx
  1844. // For iterating through JScript arrays, we expect the elements
  1845. // to be accessable by ordinals starting at 0, i.e., a 0 based array
  1846. //
  1847. HRESULT
  1848. CProxyFrame::SetContextMenuDispEx(LPVARIANT pVarMenuStrings, LPVARIANT pVarMenuStates)
  1849. {
  1850. HRESULT hr = S_OK;
  1851. ULONG i=0;
  1852. ULONG ulStringsLen = 0;
  1853. ULONG ulStatesLen = 0;
  1854. IDispatch* pdStrings = NULL;
  1855. IDispatch* pdStates = NULL;
  1856. IDispatchEx* pdexStrings = NULL;
  1857. IDispatchEx* pdexStates = NULL;
  1858. CDispExArray dispStrings;
  1859. CDispExArray dispStates;
  1860. VARIANT varString;
  1861. VARIANT varState;
  1862. SAFEARRAYBOUND rgsabound[1] = {0};
  1863. LONG ix[1] = {0};
  1864. if (VT_DISPATCH != V_VT(pVarMenuStrings) || VT_DISPATCH != V_VT(pVarMenuStates))
  1865. return E_INVALIDARG;
  1866. VariantInit(&varString);
  1867. VariantInit(&varState);
  1868. pdStrings = V_DISPATCH(pVarMenuStrings);
  1869. pdStates = V_DISPATCH(pVarMenuStates);
  1870. _ASSERTE(pdStrings);
  1871. _ASSERTE(pdStates);
  1872. if (FAILED(hr = pdStrings->QueryInterface(IID_IDispatchEx, (LPVOID*) &pdexStrings)))
  1873. {
  1874. return E_INVALIDARG;
  1875. }
  1876. dispStrings.Attach(pdexStrings);
  1877. if (FAILED(hr = pdStates->QueryInterface(IID_IDispatchEx, (LPVOID*) &pdexStates)))
  1878. {
  1879. return E_INVALIDARG;
  1880. }
  1881. dispStates.Attach(pdexStates);
  1882. if (FAILED(dispStrings.HrGetLength(&ulStringsLen)))
  1883. goto cleanup;
  1884. if (FAILED(dispStates.HrGetLength(&ulStatesLen)))
  1885. goto cleanup;
  1886. // Make sure that arrays are equal length
  1887. if (ulStringsLen != ulStatesLen)
  1888. return E_INVALIDARG;
  1889. if (m_pMenuStrings)
  1890. {
  1891. SafeArrayDestroy(m_pMenuStrings);
  1892. m_pMenuStrings = NULL;
  1893. }
  1894. if (m_pMenuStates)
  1895. {
  1896. SafeArrayDestroy(m_pMenuStates);
  1897. m_pMenuStates = NULL;
  1898. }
  1899. // An empty array was passed in
  1900. // The context menu has been cleared
  1901. if (ulStringsLen <= 0)
  1902. goto cleanup;
  1903. rgsabound[0].lLbound = 0;
  1904. rgsabound[0].cElements = ulStringsLen;
  1905. m_pMenuStrings = SafeArrayCreate(VT_BSTR, 1, rgsabound);
  1906. _ASSERTE(m_pMenuStrings);
  1907. if (NULL == m_pMenuStrings)
  1908. {
  1909. hr = E_OUTOFMEMORY;
  1910. goto cleanup;
  1911. }
  1912. m_pMenuStates = SafeArrayCreate(VT_I4, 1, rgsabound);
  1913. _ASSERTE(m_pMenuStates);
  1914. if (NULL == m_pMenuStates)
  1915. {
  1916. hr = E_OUTOFMEMORY;
  1917. goto cleanup;
  1918. }
  1919. // For iterating through JScript arrays, we expect the elements
  1920. // to be accessable by ordinals starting at 0, i.e., a 0 based array
  1921. hr = S_OK;
  1922. for (i=0; i < ulStringsLen && hr != S_FALSE; i++)
  1923. {
  1924. if (FAILED(hr = dispStrings.HrGetElement(i, &varString)))
  1925. goto cleanup;
  1926. if (FAILED(hr = dispStates.HrGetElement(i, &varState)))
  1927. goto cleanup;
  1928. if (VT_BSTR != V_VT(&varString) || VT_I4 != V_VT(&varState))
  1929. {
  1930. hr = E_INVALIDARG;
  1931. goto cleanup;
  1932. }
  1933. ix[0] = i;
  1934. if (FAILED(hr = SafeArrayPutElement(m_pMenuStrings, ix, (LPVOID) V_BSTR(&varString))))
  1935. goto cleanup;
  1936. if (FAILED(hr = SafeArrayPutElement(m_pMenuStates, ix, (LPVOID) &(V_I4(&varState)))))
  1937. goto cleanup;
  1938. VariantClear ( &varString );
  1939. VariantClear ( &varState );
  1940. }
  1941. cleanup:
  1942. if (FAILED(hr))
  1943. {
  1944. if (m_pMenuStrings)
  1945. {
  1946. SafeArrayDestroy(m_pMenuStrings);
  1947. m_pMenuStrings = NULL;
  1948. }
  1949. if (m_pMenuStates)
  1950. {
  1951. SafeArrayDestroy(m_pMenuStates);
  1952. m_pMenuStates = NULL;
  1953. }
  1954. }
  1955. return hr;
  1956. }
  1957. // DocumentTitle property implementation; read only.
  1958. // Get the property from the HTML document.
  1959. //
  1960. HRESULT
  1961. CProxyFrame::GetDocumentTitle ( CComBSTR& bstrTitle )
  1962. {
  1963. HRESULT hr = S_OK;
  1964. DISPID dispid;
  1965. DISPPARAMS dispparamsNoArgs = {NULL, NULL, 0, 0};
  1966. CComVariant varResult;
  1967. CComPtr<IHTMLDocument2> piHtmlDoc = NULL;
  1968. hr = HrGetDoc( &piHtmlDoc );
  1969. if ( SUCCEEDED ( hr ) )
  1970. {
  1971. AssureActivated();
  1972. hr = piHtmlDoc->GetIDsOfNames ( IID_NULL, &g_wszHTMLTitlePropName, 1, LOCALE_SYSTEM_DEFAULT, &dispid );
  1973. _ASSERTE ( SUCCEEDED ( hr ) );
  1974. if ( FAILED ( hr ) )
  1975. {
  1976. return hr;
  1977. }
  1978. hr = piHtmlDoc->Invoke ( dispid, IID_NULL, LOCALE_SYSTEM_DEFAULT, DISPATCH_PROPERTYGET,
  1979. &dispparamsNoArgs, &varResult, NULL, NULL );
  1980. _ASSERTE ( SUCCEEDED ( hr ) );
  1981. if ( FAILED ( hr ) )
  1982. {
  1983. return hr;
  1984. }
  1985. hr = varResult.ChangeType ( VT_BSTR );
  1986. _ASSERTE ( SUCCEEDED ( hr ) );
  1987. if ( FAILED ( hr ) )
  1988. {
  1989. return hr;
  1990. }
  1991. bstrTitle = varResult.bstrVal;
  1992. }
  1993. return hr;
  1994. }
  1995. // Implements getting the control's BrowseMode property
  1996. //
  1997. HRESULT
  1998. CProxyFrame::GetBrowseMode ( VARIANT_BOOL *pVal )
  1999. {
  2000. *pVal = m_vbBrowseMode;
  2001. return S_OK;
  2002. }
  2003. // Implements setting the control's BrowseMode property
  2004. //
  2005. HRESULT
  2006. CProxyFrame::SetBrowseMode ( VARIANT_BOOL newVal )
  2007. {
  2008. HRESULT hr = S_FALSE; // Indicates value was set, but actual mode was not changed.
  2009. _ASSERTE ( m_pSite );
  2010. // If we're still reading the property bag, just set the value, don't change the text;
  2011. // it hasn't been loaded yet.
  2012. if ( NULL == m_pSite->GetCommandTarget() )
  2013. {
  2014. m_vbBrowseMode = newVal;
  2015. hr = S_OK;
  2016. }
  2017. else
  2018. {
  2019. if ( m_vbBrowseMode != newVal )
  2020. {
  2021. AssureActivated ();
  2022. m_bfModeSwitched = TRUE;
  2023. if ( newVal && m_pCtl->IsUserMode () ) // newVal means "switching to browse mode"
  2024. {
  2025. CComPtr<IStream> spStream = NULL;
  2026. HrGetIsDirty ( m_bfPreserveDirtyFlagAcrossBrowseMode );
  2027. hr = m_pSite->HrSaveToStreamAndFilter ( &spStream, m_dwFilterOutFlags );
  2028. if ( SUCCEEDED ( hr ) )
  2029. {
  2030. m_bstrLoadText.Empty ();
  2031. // Preserve the byte order mark, or else it will not be reloaded properly
  2032. hr = m_pSite->HrStreamToBstr ( spStream, &m_bstrLoadText, TRUE );
  2033. }
  2034. }
  2035. m_vbBrowseMode = newVal;
  2036. // Let Trident know the ambient property has changed.
  2037. CComQIPtr<IOleControl,&IID_IOleControl>spioc ( m_pSite->GetObjectUnknown() );
  2038. if ( spioc )
  2039. {
  2040. m_bfIsLoading = TRUE;
  2041. spioc->OnAmbientPropertyChange ( DISPID_AMBIENT_USERMODE );
  2042. }
  2043. }
  2044. }
  2045. return hr;
  2046. }
  2047. // Implements getting the control's UseDivOnCarriageReturn property
  2048. //
  2049. HRESULT
  2050. CProxyFrame::GetDivOnCr ( VARIANT_BOOL *pVal )
  2051. {
  2052. *pVal = m_vbUseDivOnCr;
  2053. return S_OK;
  2054. }
  2055. // Implements setting the control's UseDivOnCarriageReturn property
  2056. //
  2057. HRESULT
  2058. CProxyFrame::SetDivOnCr ( VARIANT_BOOL newVal )
  2059. {
  2060. HRESULT hr = S_OK;
  2061. CComVariant varDefBlock;
  2062. m_vbUseDivOnCr = newVal;
  2063. // Reinitialize if we haven't loaded our properties before this point.
  2064. if ( READYSTATE_UNINITIALIZED == m_readyState )
  2065. {
  2066. // InitializeDocString takes m_vbUseDivOnCr into account
  2067. InitializeDocString ();
  2068. }
  2069. return hr;
  2070. }
  2071. // Implements getting the control's read-only Busy property
  2072. //
  2073. HRESULT
  2074. CProxyFrame::GetBusy ( VARIANT_BOOL *pVal )
  2075. {
  2076. #pragma warning(disable: 4310) // cast truncates constant value
  2077. *pVal = ( m_bfIsLoading ) ? VARIANT_TRUE : VARIANT_FALSE;
  2078. #pragma warning(default: 4310) // cast truncates constant value
  2079. return S_OK;
  2080. }
  2081. // Implements setting the control's ActivateActiveXControls property
  2082. //
  2083. HRESULT
  2084. CProxyFrame::HrSetPropActivateControls(BOOL activateControls)
  2085. {
  2086. HRESULT hr = S_OK;
  2087. if (m_fActivated)
  2088. {
  2089. if (SUCCEEDED(hr = HrTridentSetPropBool(IDM_NOACTIVATENORMALOLECONTROLS, !activateControls)))
  2090. m_fActivateControls = activateControls;
  2091. }
  2092. else
  2093. m_fActivateControls = activateControls;
  2094. _ASSERTE(SUCCEEDED(hr));
  2095. return hr;
  2096. }
  2097. // Implements getting the control's ActivateActiveXControls property
  2098. //
  2099. HRESULT
  2100. CProxyFrame::HrGetPropActivateControls(BOOL& activateControls)
  2101. {
  2102. HRESULT hr = S_OK;
  2103. activateControls = m_fActivateControls;
  2104. _ASSERTE(SUCCEEDED(hr));
  2105. return hr;
  2106. }
  2107. // Implements setting the control's ActivateApplets property
  2108. //
  2109. HRESULT
  2110. CProxyFrame::HrSetPropActivateApplets(BOOL activateApplets)
  2111. {
  2112. HRESULT hr = S_OK;
  2113. if (m_fActivated)
  2114. {
  2115. if (SUCCEEDED(hr = HrTridentSetPropBool(IDM_NOACTIVATEJAVAAPPLETS, !activateApplets)))
  2116. m_fActivateApplets = activateApplets;
  2117. }
  2118. else
  2119. m_fActivateApplets = activateApplets;
  2120. _ASSERTE(SUCCEEDED(hr));
  2121. return hr;
  2122. }
  2123. // Implements getting the control's ActivateApplets property
  2124. //
  2125. HRESULT
  2126. CProxyFrame::HrGetPropActivateApplets(BOOL& activateApplets)
  2127. {
  2128. HRESULT hr = S_OK;
  2129. activateApplets = m_fActivateApplets;
  2130. _ASSERTE(SUCCEEDED(hr));
  2131. return hr;
  2132. }
  2133. // Implements setting the control's ActivateDTCs property
  2134. //
  2135. HRESULT
  2136. CProxyFrame::HrSetPropActivateDTCs(BOOL activateDTCs)
  2137. {
  2138. HRESULT hr = S_OK;
  2139. if (m_fActivated)
  2140. {
  2141. if (SUCCEEDED(hr = HrTridentSetPropBool(IDM_NOACTIVATEDESIGNTIMECONTROLS, !activateDTCs)))
  2142. m_fActivateDTCs = activateDTCs;
  2143. }
  2144. else
  2145. m_fActivateDTCs = activateDTCs;
  2146. _ASSERTE(SUCCEEDED(hr));
  2147. return hr;
  2148. }
  2149. // Implements getting the control's ActivateDTCs property
  2150. //
  2151. HRESULT
  2152. CProxyFrame::HrGetPropActivateDTCs(BOOL& activateDTCs)
  2153. {
  2154. HRESULT hr = S_OK;
  2155. activateDTCs = m_fActivateDTCs;
  2156. _ASSERTE(SUCCEEDED(hr));
  2157. return hr;
  2158. }
  2159. // Implements setting the control's ShowDetails property
  2160. //
  2161. HRESULT
  2162. CProxyFrame::HrSetPropShowAllTags(BOOL showAllTags)
  2163. {
  2164. HRESULT hr = S_OK;
  2165. if (m_fActivated)
  2166. {
  2167. if (SUCCEEDED(hr = HrTridentSetPropBool(IDM_SHOWALLTAGS, showAllTags)))
  2168. m_fShowAllTags = showAllTags;
  2169. }
  2170. else
  2171. m_fShowAllTags = showAllTags;
  2172. _ASSERTE(SUCCEEDED(hr));
  2173. return hr;
  2174. }
  2175. // Implements getting the control's ShowDetails property
  2176. //
  2177. HRESULT
  2178. CProxyFrame::HrGetPropShowAllTags(BOOL& showAllTags)
  2179. {
  2180. HRESULT hr = S_OK;
  2181. showAllTags = m_fShowAllTags;
  2182. _ASSERTE(SUCCEEDED(hr));
  2183. return hr;
  2184. }
  2185. // Implements setting the control's ShowBorders property
  2186. //
  2187. HRESULT
  2188. CProxyFrame::HrSetPropShowBorders(BOOL showBorders)
  2189. {
  2190. HRESULT hr = S_OK;
  2191. if (m_fActivated)
  2192. {
  2193. if (SUCCEEDED(hr = HrTridentSetPropBool(IDM_SHOWZEROBORDERATDESIGNTIME, showBorders)))
  2194. m_fShowBorders = showBorders;
  2195. }
  2196. else
  2197. m_fShowBorders = showBorders;
  2198. _ASSERTE(SUCCEEDED(hr));
  2199. return hr;
  2200. }
  2201. // Implements getting the control's ShowBorders property
  2202. //
  2203. HRESULT
  2204. CProxyFrame::HrGetPropShowBorders(BOOL& showBorders)
  2205. {
  2206. HRESULT hr = S_OK;
  2207. showBorders = m_fShowBorders;
  2208. _ASSERTE(SUCCEEDED(hr));
  2209. return hr;
  2210. }
  2211. // Implements setting the control's Appearance property
  2212. //
  2213. HRESULT
  2214. CProxyFrame::HrSetDisplay3D(BOOL bVal)
  2215. {
  2216. m_fDisplay3D = bVal;
  2217. return S_OK;
  2218. }
  2219. // Implements getting the control's Appearance property
  2220. //
  2221. HRESULT
  2222. CProxyFrame::HrGetDisplay3D(BOOL& bVal)
  2223. {
  2224. bVal = m_fDisplay3D;
  2225. return S_OK;
  2226. }
  2227. // Implements setting the control's Scrollbars property
  2228. //
  2229. HRESULT
  2230. CProxyFrame::HrSetScrollbars(BOOL bVal)
  2231. {
  2232. m_fScrollbars = bVal;
  2233. return S_OK;
  2234. }
  2235. // Implements getting the control's Scrollbars property
  2236. //
  2237. HRESULT
  2238. CProxyFrame::HrGetScrollbars(BOOL& bVal)
  2239. {
  2240. bVal = m_fScrollbars;
  2241. return S_OK;
  2242. }
  2243. // Implements setting the control's ScrollbarAppearance property
  2244. //
  2245. HRESULT
  2246. CProxyFrame::HrSetDisplayFlatScrollbars(BOOL bVal)
  2247. {
  2248. m_fDisplayFlatScrollbars = bVal;
  2249. return S_OK;
  2250. }
  2251. // Implements getting the control's ScrollbarAppearance property
  2252. //
  2253. HRESULT
  2254. CProxyFrame::HrGetDisplayFlatScrollbars(BOOL& bVal)
  2255. {
  2256. bVal = m_fDisplayFlatScrollbars;
  2257. return S_OK;
  2258. }
  2259. // Implements setting the control's AbsoluteDropMode property
  2260. //
  2261. HRESULT
  2262. CProxyFrame::HrSetAbsoluteDropMode(BOOL dropMode)
  2263. {
  2264. HRESULT hr = S_OK;
  2265. if (m_fActivated)
  2266. {
  2267. VARIANT var;
  2268. VariantInit(&var);
  2269. V_VT(&var) = VT_BOOL;
  2270. #pragma warning(disable: 4310) // cast truncates constant value
  2271. V_BOOL(&var) = (dropMode) ? VARIANT_TRUE : VARIANT_FALSE;
  2272. #pragma warning(default: 4310) // cast truncates constant value
  2273. if (SUCCEEDED(hr = HrExecCommand(&GUID_TriEditCommandGroup, IDM_TRIED_SET_2D_DROP_MODE,
  2274. MSOCMDEXECOPT_DONTPROMPTUSER, &var, NULL)))
  2275. m_fAbsoluteDropMode = dropMode;
  2276. }
  2277. else
  2278. m_fAbsoluteDropMode = dropMode;
  2279. _ASSERTE(SUCCEEDED(hr));
  2280. return hr;
  2281. }
  2282. // Implements getting the control's AbsoluteDropMode property
  2283. //
  2284. HRESULT
  2285. CProxyFrame::HrGetAbsoluteDropMode(BOOL& dropMode)
  2286. {
  2287. HRESULT hr = S_OK;
  2288. dropMode = m_fAbsoluteDropMode;
  2289. return hr;
  2290. }
  2291. // Implements setting the control's SnapToGrid property
  2292. //
  2293. HRESULT
  2294. CProxyFrame::HrSetSnapToGrid(BOOL snapToGrid)
  2295. {
  2296. HRESULT hr = S_OK;
  2297. if (m_fActivated)
  2298. {
  2299. VARIANT var;
  2300. POINT pt = {0};
  2301. VariantInit(&var);
  2302. if ( snapToGrid )
  2303. {
  2304. pt.y = m_ulSnapToGridY;
  2305. pt.x = m_ulSnapToGridX;
  2306. }
  2307. else
  2308. {
  2309. pt.y = 0;
  2310. pt.x = 0;
  2311. }
  2312. V_VT(&var) = VT_BYREF;
  2313. V_BYREF(&var) = &pt;
  2314. if (SUCCEEDED(hr = HrExecCommand(&GUID_TriEditCommandGroup, IDM_TRIED_SET_ALIGNMENT,
  2315. MSOCMDEXECOPT_DONTPROMPTUSER, &var, NULL)))
  2316. m_fSnapToGrid = snapToGrid;
  2317. }
  2318. else
  2319. m_fSnapToGrid = snapToGrid;
  2320. _ASSERTE(SUCCEEDED(hr));
  2321. return hr;
  2322. }
  2323. // Implements getting the control's SnapToGrid property
  2324. //
  2325. HRESULT
  2326. CProxyFrame::HrGetSnapToGrid(BOOL& snapToGrid)
  2327. {
  2328. HRESULT hr = S_OK;
  2329. snapToGrid = m_fSnapToGrid;
  2330. return hr;
  2331. }
  2332. // Implements setting the control's SnapToGridX property
  2333. //
  2334. HRESULT
  2335. CProxyFrame::HrSetSnapToGridX(LONG snapToGridX)
  2336. {
  2337. HRESULT hr = S_OK;
  2338. if ( 0 >= snapToGridX )
  2339. {
  2340. return DE_E_INVALIDARG;
  2341. }
  2342. if (m_fActivated)
  2343. {
  2344. VARIANT var;
  2345. POINT pt = {0};
  2346. VariantInit(&var);
  2347. pt.x = snapToGridX;
  2348. pt.y = m_ulSnapToGridY;
  2349. V_VT(&var) = VT_BYREF;
  2350. V_BYREF(&var) = &pt;
  2351. if (SUCCEEDED(hr = HrExecCommand(&GUID_TriEditCommandGroup, IDM_TRIED_SET_ALIGNMENT,
  2352. MSOCMDEXECOPT_DONTPROMPTUSER, &var, NULL)))
  2353. m_ulSnapToGridX = snapToGridX;
  2354. }
  2355. else
  2356. m_ulSnapToGridX = snapToGridX;
  2357. _ASSERTE(SUCCEEDED(hr));
  2358. return hr;
  2359. }
  2360. // Implements getting the control's SnapToGridX property
  2361. //
  2362. HRESULT
  2363. CProxyFrame::HrGetSnapToGridX(LONG& snapToGridX)
  2364. {
  2365. HRESULT hr = S_OK;
  2366. snapToGridX = m_ulSnapToGridX;
  2367. return hr;
  2368. }
  2369. // Implements setting the control's SnapToGridY property
  2370. //
  2371. HRESULT
  2372. CProxyFrame::HrSetSnapToGridY(LONG snapToGridY)
  2373. {
  2374. HRESULT hr = S_OK;
  2375. if ( 0 >= snapToGridY )
  2376. {
  2377. return DE_E_INVALIDARG;
  2378. }
  2379. if (m_fActivated)
  2380. {
  2381. VARIANT var;
  2382. POINT pt = {0};
  2383. VariantInit(&var);
  2384. pt.y = snapToGridY;
  2385. pt.x = m_ulSnapToGridX;
  2386. V_VT(&var) = VT_BYREF;
  2387. V_BYREF(&var) = &pt;
  2388. if (SUCCEEDED(hr = HrExecCommand(&GUID_TriEditCommandGroup, IDM_TRIED_SET_ALIGNMENT,
  2389. MSOCMDEXECOPT_DONTPROMPTUSER, &var, NULL)))
  2390. m_ulSnapToGridY = snapToGridY;
  2391. }
  2392. else
  2393. m_ulSnapToGridY = snapToGridY;
  2394. _ASSERTE(SUCCEEDED(hr));
  2395. return hr;
  2396. }
  2397. // Implements getting the control's SnapToGridY property
  2398. //
  2399. HRESULT
  2400. CProxyFrame::HrGetSnapToGridY(LONG& snapToGridY)
  2401. {
  2402. HRESULT hr = S_OK;
  2403. snapToGridY = m_ulSnapToGridY;
  2404. return hr;
  2405. }
  2406. // Implements setting the control's DocumentHTML property
  2407. //
  2408. HRESULT
  2409. CProxyFrame::HrSetDocumentHTML(BSTR bVal)
  2410. {
  2411. HRESULT hr = S_OK;
  2412. _ASSERTE(bVal);
  2413. if (NULL == bVal)
  2414. return E_INVALIDARG;
  2415. if (m_pCtl->IsUserMode ())
  2416. {
  2417. hr = DE_E_UNEXPECTED;
  2418. AssureActivated ();
  2419. if ( m_fActivated )
  2420. {
  2421. m_bstrBaseURL = L"";
  2422. m_bfPreserveDirtyFlagAcrossBrowseMode = FALSE;
  2423. if ( 0 == SysStringLen ( bVal ) )
  2424. {
  2425. CComBSTR bstrMT = GetInitialHTML ();
  2426. hr = LoadBSTRDeferred ( bstrMT );
  2427. }
  2428. else
  2429. {
  2430. hr = LoadBSTRDeferred ( bVal );
  2431. }
  2432. if ( FAILED ( hr ) )
  2433. {
  2434. goto error;
  2435. }
  2436. // We've reset the contents of the control. Go back to default save mechanism.
  2437. m_pSite->SetSaveAsUnicode ( FALSE );
  2438. }
  2439. }
  2440. error:
  2441. return hr;
  2442. }
  2443. // Implements getting the control's DocumentHTML property
  2444. //
  2445. HRESULT
  2446. CProxyFrame::HrGetDocumentHTML(BSTR* bVal)
  2447. {
  2448. HRESULT hr = S_OK;
  2449. BOOL bfWasDirty = FALSE;
  2450. _ASSERTE(bVal);
  2451. if (NULL == bVal)
  2452. return E_INVALIDARG;
  2453. if ( m_bfIsLoading )
  2454. return DE_E_UNEXPECTED; // This is invalid while document is still loading.
  2455. if ( FAILED ( hr = m_pSite->HrIsDirtyIPersistStreamInit(bfWasDirty) ) )
  2456. {
  2457. _ASSERTE ( SUCCEEDED ( hr ) );
  2458. bfWasDirty = FALSE; // what else can we do in a situation like this?
  2459. }
  2460. AssureActivated ();
  2461. if (m_fActivated)
  2462. {
  2463. _ASSERTE(m_pSite);
  2464. hr = m_pSite->HrSaveToBstr(bVal, m_dwFilterOutFlags );
  2465. // Preserve original dirty state.
  2466. if ( bfWasDirty )
  2467. {
  2468. SetDirtyFlag ( TRUE );
  2469. }
  2470. }
  2471. return hr;
  2472. }
  2473. // Implements setting the control's SourceCodePreservation property
  2474. //
  2475. HRESULT
  2476. CProxyFrame::HrSetPreserveSource(BOOL bVal)
  2477. {
  2478. m_fPreserveSource = bVal;
  2479. if (m_fPreserveSource)
  2480. m_dwFilterFlags = filterAll;
  2481. else
  2482. m_dwFilterFlags = filterDTCs | filterASP;
  2483. return S_OK;
  2484. }
  2485. // Implements getting the control's SourceCodePreservation property
  2486. //
  2487. HRESULT
  2488. CProxyFrame::HrGetPreserveSource(BOOL& bVal)
  2489. {
  2490. bVal = m_fPreserveSource;
  2491. return S_OK;
  2492. }
  2493. // Implements getting the control's read-only IsDirty property
  2494. //
  2495. HRESULT
  2496. CProxyFrame::HrGetIsDirty(BOOL& bVal)
  2497. {
  2498. HRESULT hr = S_OK;
  2499. bVal = FALSE;
  2500. AssureActivated ();
  2501. if (m_fActivated)
  2502. {
  2503. hr = m_pSite->HrIsDirtyIPersistStreamInit(bVal);
  2504. }
  2505. return hr;
  2506. }
  2507. // Implements getting the BaseURL property
  2508. //
  2509. HRESULT
  2510. CProxyFrame::GetBaseURL ( CComBSTR& bstrBaseURL )
  2511. {
  2512. AssureActivated ();
  2513. if ( NULL == m_bstrBaseURL.m_str )
  2514. {
  2515. bstrBaseURL = L"";
  2516. }
  2517. else
  2518. {
  2519. bstrBaseURL = m_bstrBaseURL;
  2520. }
  2521. return S_OK;
  2522. }
  2523. // Implements setting the BaseURL property.
  2524. // NOTE:
  2525. // The BaseURL can't be (effectively) changed if there's a <BASE HREF=XXX> tag in
  2526. // the document. Our pluggable Protocol's CombineURL is never called in this case,
  2527. // so don't misguide the user by changing the property.
  2528. //
  2529. // Pay attention to m_bfBaseURLFromBASETag before calling to set the value from
  2530. // the routine parsing the <BASE> tag!
  2531. //
  2532. HRESULT
  2533. CProxyFrame::SetBaseURL ( CComBSTR& bstrBaseURL )
  2534. {
  2535. HRESULT hr = S_OK;
  2536. _ASSERTE ( bstrBaseURL );
  2537. // Non-persisted property. Ignore if not in UserMode.
  2538. if ( m_pCtl->IsUserMode () )
  2539. {
  2540. if ( m_bfBaseURLFromBASETag )
  2541. {
  2542. return S_FALSE;
  2543. }
  2544. else
  2545. {
  2546. if ( NULL == m_bstrBaseURL.m_str )
  2547. {
  2548. m_bstrBaseURL = L"";
  2549. }
  2550. // If this test succeedes, the user has done something like x.BaseURL = x.DOM.url or
  2551. // x.BaseURL = y.DOM.url.
  2552. // Response: bstrBaseURL may be the bare protocol prefix, or a prefix with a URL attached
  2553. // for example: dhtmled0:(http://www.microsoft.com).
  2554. // Strip off the prefix and parens (if they exist) and use the interior URL.
  2555. if ( 0 == _wcsnicmp ( bstrBaseURL.m_str, g_wszProtocolPrefix, wcslen ( g_wszProtocolPrefix ) ) )
  2556. {
  2557. CComBSTR bstrNew = bstrBaseURL.m_str;
  2558. // There must be a colon; it would be possibe to have a legitimate base url beginning with g_wszProtocolPrefix
  2559. WCHAR* pwcURL = wcschr ( bstrNew, (WCHAR)':' );
  2560. if ( NULL != pwcURL )
  2561. {
  2562. // Find the first open paren:
  2563. pwcURL = wcschr ( pwcURL, (WCHAR)'(' );
  2564. if ( NULL == pwcURL )
  2565. {
  2566. bstrBaseURL = L""; // No (...)? Set the Base to empty. Input must have been bare protocol ID.
  2567. }
  2568. else
  2569. {
  2570. pwcURL++; // Step past the paren.
  2571. // Strip of dhtmledXXX:( ...to... ) and set the BaseURL to what remains.
  2572. _ASSERTE ( (WCHAR)')' == pwcURL[wcslen(pwcURL)-1] );
  2573. if ( (WCHAR)')' == pwcURL[wcslen(pwcURL)-1] )
  2574. {
  2575. pwcURL[wcslen(pwcURL)-1] = (WCHAR)'\0';
  2576. bstrBaseURL = pwcURL;
  2577. }
  2578. else
  2579. {
  2580. // Unexpected: ill formed pluggable protocol id:
  2581. // starts with dhtml[n[n]]:( but does not end with ).
  2582. // If we skipped it, we would crash. Best to use an empty base URL.
  2583. bstrBaseURL = L"";
  2584. }
  2585. }
  2586. }
  2587. }
  2588. if ( 0 != wcscmp ( m_bstrBaseURL.m_str, bstrBaseURL.m_str ) )
  2589. {
  2590. m_bstrBaseURL = bstrBaseURL;
  2591. m_bfIsLoading = TRUE;
  2592. // Can't Exec without a command target:
  2593. if ( NULL != m_pSite->GetCommandTarget() )
  2594. {
  2595. // Reload the page, revaluating relative links.
  2596. hr = HrExecCommand(&CGID_MSHTML, IDM_REFRESH, MSOCMDEXECOPT_DONTPROMPTUSER, NULL, NULL);
  2597. }
  2598. }
  2599. }
  2600. }
  2601. return hr;
  2602. }
  2603. ///////////////////////////////////////////////////////////////////////////////////////////
  2604. //
  2605. // Accelerator handler implementations
  2606. //
  2607. ///////////////////////////////////////////////////////////////////////////////////////////
  2608. // Nudge accelerator handler
  2609. // Nudge the selection in the given direction by one pixle if SnaptoGrid is off, or by
  2610. // the SnaptoGridX/Y quantity if SnapToGrid is on.
  2611. //
  2612. HRESULT
  2613. CProxyFrame::HrNudge(DENudgeDirection dir)
  2614. {
  2615. HRESULT hr = S_FALSE;
  2616. OLECMDF cmdf = (OLECMDF) 0;
  2617. VARIANT var;
  2618. LPVARIANT pVarIn = &var;
  2619. LONG lXDelta = m_fSnapToGrid ? m_ulSnapToGridX : 1;
  2620. LONG lYDelta = m_fSnapToGrid ? m_ulSnapToGridY : 1;
  2621. if (FAILED(hr = HrQueryStatus(&GUID_TriEditCommandGroup, IDM_TRIED_NUDGE_ELEMENT, &cmdf)))
  2622. {
  2623. _ASSERTE(SUCCEEDED(hr));
  2624. goto cleanup;
  2625. }
  2626. if (cmdf & OLECMDF_SUPPORTED && cmdf & OLECMDF_ENABLED)
  2627. {
  2628. LPPOINT lpPoint = new POINT;
  2629. if (NULL == lpPoint)
  2630. {
  2631. hr = E_OUTOFMEMORY;
  2632. goto cleanup;
  2633. }
  2634. _ASSERTE(lpPoint);
  2635. lpPoint->x = 0;
  2636. lpPoint->y = 0;
  2637. // Set increment to snap to absolute grid, not relative grid.
  2638. // Find the selections current position and set increment modulo that position.
  2639. // This assures the first nudge snaps to a grid corner.
  2640. if ( m_fSnapToGrid )
  2641. {
  2642. POINT ptSelPos;
  2643. if ( SUCCEEDED ( GetSelectionPos ( &ptSelPos ) ) )
  2644. {
  2645. LONG lXNorm = ptSelPos.x % lXDelta;
  2646. LONG lYNorm = ptSelPos.y % lYDelta;
  2647. lXDelta = lXNorm ? lXNorm : lXDelta;
  2648. lYDelta = lYNorm ? lYNorm : lYDelta;
  2649. }
  2650. }
  2651. switch(dir)
  2652. {
  2653. case deNudgeUp:
  2654. {
  2655. lpPoint->x = 0;
  2656. lpPoint->y = -lYDelta;
  2657. }
  2658. break;
  2659. case deNudgeDown:
  2660. {
  2661. lpPoint->x = 0;
  2662. lpPoint->y = lYDelta;
  2663. }
  2664. break;
  2665. case deNudgeLeft:
  2666. {
  2667. lpPoint->x = -lXDelta;
  2668. lpPoint->y = 0;
  2669. }
  2670. break;
  2671. case deNudgeRight:
  2672. {
  2673. lpPoint->x = lXDelta;
  2674. lpPoint->y = 0;
  2675. }
  2676. break;
  2677. default: // move right by default
  2678. {
  2679. lpPoint->x = lXDelta;
  2680. lpPoint->y = 0;
  2681. }
  2682. break;
  2683. }
  2684. VariantInit(pVarIn);
  2685. V_VT(pVarIn) = VT_BYREF;
  2686. V_BYREF(pVarIn) = lpPoint;
  2687. if (FAILED(hr = HrExecCommand(&GUID_TriEditCommandGroup, IDM_TRIED_NUDGE_ELEMENT, MSOCMDEXECOPT_DONTPROMPTUSER, pVarIn, NULL)))
  2688. {
  2689. _ASSERTE(SUCCEEDED(hr));
  2690. goto cleanup;
  2691. }
  2692. hr = S_OK;
  2693. }
  2694. else
  2695. hr = S_FALSE;
  2696. cleanup:
  2697. return hr;
  2698. }
  2699. // Accelerator handler
  2700. // Toggle the absolute positioned property of the selected object
  2701. //
  2702. HRESULT
  2703. CProxyFrame::HrToggleAbsolutePositioned()
  2704. {
  2705. HRESULT hr = S_FALSE;
  2706. OLECMDF cmdf = (OLECMDF) 0;
  2707. if (FAILED(hr = HrQueryStatus(&GUID_TriEditCommandGroup, IDM_TRIED_MAKE_ABSOLUTE, &cmdf)))
  2708. {
  2709. _ASSERTE(SUCCEEDED(hr));
  2710. goto cleanup;
  2711. }
  2712. if (cmdf & OLECMDF_SUPPORTED && cmdf & OLECMDF_ENABLED)
  2713. {
  2714. if (FAILED(hr = HrExecCommand(&GUID_TriEditCommandGroup, IDM_TRIED_MAKE_ABSOLUTE,
  2715. MSOCMDEXECOPT_DONTPROMPTUSER, NULL, NULL)))
  2716. {
  2717. _ASSERTE(SUCCEEDED(hr));
  2718. goto cleanup;
  2719. }
  2720. hr = S_OK;
  2721. }
  2722. cleanup:
  2723. return hr;
  2724. }
  2725. // Accelerator handler
  2726. // Make a link out of the current selection (with UI.)
  2727. //
  2728. HRESULT
  2729. CProxyFrame::HrHyperLink()
  2730. {
  2731. HRESULT hr = S_FALSE;
  2732. OLECMDF cmdf = (OLECMDF) 0;
  2733. if (FAILED(hr = HrQueryStatus(&GUID_TriEditCommandGroup, IDM_TRIED_HYPERLINK, &cmdf)))
  2734. {
  2735. _ASSERTE(SUCCEEDED(hr));
  2736. goto cleanup;
  2737. }
  2738. if (cmdf & OLECMDF_SUPPORTED && cmdf & OLECMDF_ENABLED)
  2739. {
  2740. if (FAILED(hr = HrExecCommand(&GUID_TriEditCommandGroup, IDM_TRIED_HYPERLINK,
  2741. MSOCMDEXECOPT_PROMPTUSER, NULL, NULL)))
  2742. {
  2743. _ASSERTE(SUCCEEDED(hr));
  2744. goto cleanup;
  2745. }
  2746. hr = S_OK;
  2747. }
  2748. cleanup:
  2749. return hr;
  2750. }
  2751. // Accelerator handler
  2752. // Increase the indent of the current selection.
  2753. //
  2754. HRESULT
  2755. CProxyFrame::HrIncreaseIndent()
  2756. {
  2757. HRESULT hr = S_FALSE;
  2758. OLECMDF cmdf = (OLECMDF) 0;
  2759. if (FAILED(hr = HrQueryStatus(&GUID_TriEditCommandGroup, IDM_TRIED_INDENT, &cmdf)))
  2760. {
  2761. _ASSERTE(SUCCEEDED(hr));
  2762. goto cleanup;
  2763. }
  2764. if (cmdf & OLECMDF_SUPPORTED && cmdf & OLECMDF_ENABLED)
  2765. {
  2766. if (FAILED(hr = HrExecCommand(&GUID_TriEditCommandGroup, IDM_TRIED_INDENT,
  2767. MSOCMDEXECOPT_DONTPROMPTUSER, NULL, NULL)))
  2768. {
  2769. _ASSERTE(SUCCEEDED(hr));
  2770. goto cleanup;
  2771. }
  2772. hr = S_OK;
  2773. }
  2774. cleanup:
  2775. return hr;
  2776. }
  2777. // Accelerator handler
  2778. // Decrease the indent of the current selection.
  2779. //
  2780. HRESULT
  2781. CProxyFrame::HrDecreaseIndent()
  2782. {
  2783. HRESULT hr = S_FALSE;
  2784. OLECMDF cmdf = (OLECMDF) 0;
  2785. if (FAILED(hr = HrQueryStatus(&GUID_TriEditCommandGroup, IDM_TRIED_OUTDENT, &cmdf)))
  2786. {
  2787. _ASSERTE(SUCCEEDED(hr));
  2788. goto cleanup;
  2789. }
  2790. if (cmdf & OLECMDF_SUPPORTED && cmdf & OLECMDF_ENABLED)
  2791. {
  2792. if (FAILED(hr = HrExecCommand(&GUID_TriEditCommandGroup, IDM_TRIED_OUTDENT,
  2793. MSOCMDEXECOPT_DONTPROMPTUSER, NULL, NULL)))
  2794. {
  2795. _ASSERTE(SUCCEEDED(hr));
  2796. goto cleanup;
  2797. }
  2798. hr = S_OK;
  2799. }
  2800. cleanup:
  2801. return hr;
  2802. }
  2803. // Check for and handle control-specific accelerators. If none is found, call TriEdit to handle it.
  2804. //
  2805. HRESULT
  2806. CProxyFrame::HrHandleAccelerator(LPMSG lpmsg)
  2807. {
  2808. HRESULT hr = S_FALSE;
  2809. BOOL fControl = (0x8000 & GetKeyState(VK_CONTROL));
  2810. BOOL fShift = (0x8000 & GetKeyState(VK_SHIFT));
  2811. BOOL fAlt = (0x8000 & GetKeyState(VK_MENU));
  2812. if (lpmsg->message == WM_KEYDOWN && lpmsg->wParam == VK_UP)
  2813. {
  2814. hr = HrNudge(deNudgeUp);
  2815. }
  2816. else if (lpmsg->message == WM_KEYDOWN && lpmsg->wParam == VK_DOWN)
  2817. {
  2818. hr = HrNudge(deNudgeDown);
  2819. }
  2820. else if (lpmsg->message == WM_KEYDOWN && lpmsg->wParam == VK_LEFT)
  2821. {
  2822. hr = HrNudge(deNudgeLeft);
  2823. }
  2824. else if (lpmsg->message == WM_KEYDOWN && lpmsg->wParam == VK_RIGHT)
  2825. {
  2826. hr = HrNudge(deNudgeRight);
  2827. }
  2828. else if (lpmsg->message == WM_KEYDOWN && lpmsg->wParam == 'K' && fControl)
  2829. {
  2830. hr = HrToggleAbsolutePositioned();
  2831. }
  2832. else if (lpmsg->message == WM_KEYDOWN && lpmsg->wParam == 'L' && fControl && !fAlt)
  2833. {
  2834. hr = HrHyperLink();
  2835. }
  2836. else if (lpmsg->message == WM_KEYDOWN && lpmsg->wParam == 'T' && !fShift && fControl)
  2837. {
  2838. hr = HrIncreaseIndent();
  2839. }
  2840. else if (lpmsg->message == WM_KEYDOWN && lpmsg->wParam == 'T' && fShift && fControl)
  2841. {
  2842. hr = HrDecreaseIndent();
  2843. }
  2844. else if (lpmsg->message == WM_KEYDOWN && lpmsg->wParam == VK_TAB && fControl)
  2845. {
  2846. // Process control-tab keys as belonging to the container; this allows the user
  2847. // to tab out of the control in non-MDI apps. MDI uses control-tab to switch
  2848. // windows, thus these apps (like VID) do not pass them to us.
  2849. IOleControlSite* piControlSite = m_pCtl->GetControlSite ();
  2850. _ASSERTE ( piControlSite );
  2851. if ( NULL != piControlSite )
  2852. {
  2853. // Eat the control key, but preserve shift to perform reverse tabbing.
  2854. // KEYMOD_SHIFT = 0x00000001, but isn't defined in any header...
  2855. DWORD dwModifiers = fShift ? 1 : 0;
  2856. hr = piControlSite->TranslateAccelerator ( lpmsg, dwModifiers );
  2857. }
  2858. }
  2859. return hr;
  2860. }
  2861. ///////////////////////////////////////////////////////////////////////////////////////////
  2862. //
  2863. // BaseURL helper routines
  2864. //
  2865. ///////////////////////////////////////////////////////////////////////////////////////////
  2866. // Override the default BaseURL if there is one or more <BASE HREF=...> tags
  2867. // in the document. If successful, set m_bfBaseURLFromBASETag to TRUE
  2868. // If multiple BASE tags exist, simply use the last one.
  2869. // Equivilent script: baseurl = document.all.tags("BASE")[<LAST>].href,
  2870. // where <LAST> is derived.
  2871. //
  2872. HRESULT
  2873. CProxyFrame::SetBaseURLFromBaseHref ()
  2874. {
  2875. HRESULT hr = S_OK;
  2876. CComBSTR bstrBase;
  2877. if ( !m_bfBaseURLFromBASETag )
  2878. {
  2879. if ( SUCCEEDED ( hr ) )
  2880. {
  2881. CComPtr<IHTMLDocument2> spHtmlDoc = NULL;
  2882. hr = HrGetDoc( &spHtmlDoc );
  2883. if ( spHtmlDoc && SUCCEEDED ( hr ) )
  2884. {
  2885. CComPtr<IHTMLElementCollection> spAll = NULL;
  2886. hr = spHtmlDoc->get_all ( &spAll );
  2887. if ( spAll && SUCCEEDED ( hr ) )
  2888. {
  2889. CComVariant varTag = L"BASE";
  2890. IDispatch* piDispTags = NULL;
  2891. hr = spAll->tags ( varTag, &piDispTags );
  2892. if ( piDispTags && SUCCEEDED ( hr ) )
  2893. {
  2894. CComQIPtr<IHTMLElementCollection, &IID_IHTMLElementCollection> spBases (piDispTags);
  2895. piDispTags->Release ();
  2896. piDispTags = NULL;
  2897. if ( spBases )
  2898. {
  2899. long cBases = 0;
  2900. hr = spBases->get_length ( &cBases );
  2901. if ( SUCCEEDED ( hr ) && ( 0 != cBases ) )
  2902. {
  2903. CComVariant varName;
  2904. varName.vt = VT_I2;
  2905. for ( varName.iVal = 0; varName.iVal < cBases; varName.iVal++ )
  2906. {
  2907. IDispatch* piDispBase = NULL;
  2908. CComVariant varValue;
  2909. hr = spBases->item ( varName, varName, &piDispBase );
  2910. if ( piDispBase && SUCCEEDED ( hr ) )
  2911. {
  2912. CComQIPtr<IHTMLElement, &IID_IHTMLElement> spElem ( piDispBase );
  2913. piDispBase->Release ();
  2914. piDispBase = NULL;
  2915. if ( spElem )
  2916. {
  2917. varValue.Clear ();
  2918. hr = spElem->getAttribute ( L"HREF", FALSE, &varValue );
  2919. if ( SUCCEEDED ( hr ) )
  2920. {
  2921. hr = varValue.ChangeType ( VT_BSTR );
  2922. if ( SUCCEEDED ( hr ) )
  2923. {
  2924. if ( 0 != SysStringLen ( varValue.bstrVal ) )
  2925. {
  2926. bstrBase = varValue.bstrVal;
  2927. }
  2928. }
  2929. }
  2930. }
  2931. }
  2932. }
  2933. if ( 0 != bstrBase.Length () )
  2934. {
  2935. hr = SetBaseURL ( bstrBase ); // This clears m_bfBaseURLIsDefault
  2936. m_bfBaseURLFromBASETag = TRUE;
  2937. }
  2938. }
  2939. }
  2940. }
  2941. }
  2942. }
  2943. }
  2944. }
  2945. return hr;
  2946. }
  2947. // Set the m_bstrBaseURL value using m_bstrCurDocPath.
  2948. // With URLs, it may be impossible to be certain about the correct BaseURL,
  2949. // so make an intellegent guess. With files, it should be deterministic.
  2950. //
  2951. HRESULT
  2952. CProxyFrame::SetBaseURLFromCurDocPath ( BOOL bfIsURL )
  2953. {
  2954. m_bfBaseURLFromBASETag = FALSE; // We're reloading: whipe this out.
  2955. if ( bfIsURL )
  2956. {
  2957. return SetBaseURLFromURL ( m_bstrCurDocPath );
  2958. }
  2959. else
  2960. {
  2961. return SetBaseURLFromFileName ( m_bstrCurDocPath );
  2962. }
  2963. }
  2964. // Given a URL_COMPONENTS with nScheme set to INTERNET_SCHEME_FILE,
  2965. // modify the path part to reflect the base path, reconstruct the URL,
  2966. // and set m_bstrBaseURL.
  2967. // Separators may be \ or /.
  2968. //
  2969. HRESULT
  2970. CProxyFrame::SetBaseUrlFromFileUrlComponents ( URL_COMPONENTS & urlc )
  2971. {
  2972. TCHAR* pszPath;
  2973. BOOL bfBackSlash = TRUE;
  2974. HRESULT hr = S_OK;
  2975. _ASSERTE ( INTERNET_SCHEME_FILE == urlc.nScheme );
  2976. _ASSERTE ( urlc.dwUrlPathLength );
  2977. if ( urlc.dwUrlPathLength <= 0)
  2978. {
  2979. return E_UNEXPECTED;
  2980. }
  2981. pszPath = new TCHAR [urlc.dwUrlPathLength + 3]; // Extra room for \0, dot, and /.
  2982. if ( NULL != pszPath )
  2983. {
  2984. TCHAR c = 0;
  2985. int iPos = 0;
  2986. // Scan backwards and modify in copy (never in BSTR, please) for beginning, '/' or '\'
  2987. memcpy ( pszPath, urlc.lpszUrlPath, ( urlc.dwUrlPathLength + 1 ) * sizeof(TCHAR) );
  2988. for ( iPos = urlc.dwUrlPathLength - 1; iPos >= 0; iPos-- )
  2989. {
  2990. c = pszPath[iPos];
  2991. pszPath[iPos] = '\0'; // Delete first, ask questions later. '\' must go.
  2992. if ( '\\' == c )
  2993. {
  2994. break;
  2995. }
  2996. if ( '/' == c )
  2997. {
  2998. bfBackSlash = FALSE;
  2999. break;
  3000. }
  3001. }
  3002. // Space was reserved for an additional two characters, if needed.
  3003. // If empty, add a dot.
  3004. if ( 0 == _tcslen ( pszPath ) )
  3005. {
  3006. _tcscat ( pszPath, TEXT(".") );
  3007. }
  3008. // Add a / or \.
  3009. if ( bfBackSlash )
  3010. {
  3011. _tcscat ( pszPath, TEXT("\\") );
  3012. }
  3013. else
  3014. {
  3015. _tcscat ( pszPath, TEXT("/") );
  3016. }
  3017. urlc.lpszUrlPath = pszPath;
  3018. urlc.dwUrlPathLength = _tcslen ( pszPath );
  3019. DWORD dwLen = 0;
  3020. #ifdef LATE_BIND_URLMON_WININET
  3021. _ASSERTE ( m_pfnInternetCreateUrl );
  3022. (*m_pfnInternetCreateUrl)( &urlc, 0, NULL, &dwLen ); // Get the size required.
  3023. #else
  3024. InternetCreateUrl ( &urlc, 0, NULL, &dwLen ); // Get the size required.
  3025. #endif // LATE_BIND_URLMON_WININET
  3026. _ASSERTE ( 0 != dwLen );
  3027. TCHAR* pszURL = new TCHAR [ dwLen + 1 ];
  3028. _ASSERTE ( pszURL );
  3029. if ( NULL != pszURL )
  3030. {
  3031. // Incredibly, on Win98, the URL is terminated with a single byte \0.
  3032. // Intializing this buffer to zero assures full termination of the string.
  3033. dwLen += 1;
  3034. memset ( pszURL, 0, sizeof(TCHAR) * dwLen );
  3035. #ifdef LATE_BIND_URLMON_WININET
  3036. if ( (*m_pfnInternetCreateUrl)( &urlc, 0, pszURL, &dwLen ) )
  3037. #else
  3038. if ( InternetCreateUrl ( &urlc, 0, pszURL, &dwLen ) )
  3039. #endif // LATE_BIND_URLMON_WININET
  3040. {
  3041. m_bstrBaseURL = pszURL;
  3042. }
  3043. else
  3044. {
  3045. hr = HRESULT_FROM_WIN32 ( GetLastError () );
  3046. }
  3047. delete [] pszURL;
  3048. }
  3049. delete [] pszPath;
  3050. }
  3051. else
  3052. {
  3053. return E_FAIL;
  3054. }
  3055. return hr;
  3056. }
  3057. // The most complicated scenario for "guessing" at the base URL.
  3058. // URLs like http://www.x.com/stuff could be either a file or a directory;
  3059. // a default page might actually be loaded. We guess based on whether or
  3060. // not the last item in the path contains a period. If so, we eliminate it.
  3061. // We make sure the path ends with a '/'.
  3062. //
  3063. HRESULT
  3064. CProxyFrame::SetBaseUrlFromUrlComponents ( URL_COMPONENTS & urlc )
  3065. {
  3066. _ASSERTE ( INTERNET_SCHEME_FILE != urlc.nScheme );
  3067. BOOL bfPeriodIncluded = FALSE;
  3068. HRESULT hr = S_OK;
  3069. if ( 0 == urlc.dwSchemeLength )
  3070. {
  3071. m_bstrBaseURL = L"";
  3072. return S_FALSE;
  3073. }
  3074. // Scan backwards over path for beginning, '/'
  3075. TCHAR c = 0;
  3076. int iPos = 0;
  3077. for ( iPos = urlc.dwUrlPathLength - 1; iPos >= 0; iPos-- )
  3078. {
  3079. c = urlc.lpszUrlPath[iPos];
  3080. if ( '/' == c )
  3081. {
  3082. break;
  3083. }
  3084. if ( '.' == c )
  3085. {
  3086. bfPeriodIncluded = TRUE;
  3087. }
  3088. }
  3089. if ( bfPeriodIncluded )
  3090. {
  3091. if ( 0 > iPos ) iPos = 0;
  3092. urlc.lpszUrlPath[iPos] = '\0'; // Truncate at the '/', or beginning
  3093. urlc.dwUrlPathLength = _tcslen ( urlc.lpszUrlPath );
  3094. }
  3095. // Recreate the URL:
  3096. DWORD dwLen = 0;
  3097. #ifdef LATE_BIND_URLMON_WININET
  3098. _ASSERTE ( m_pfnInternetCreateUrl );
  3099. (*m_pfnInternetCreateUrl)( &urlc, 0, NULL, &dwLen ); // Get the size required.
  3100. #else
  3101. InternetCreateUrl ( &urlc, 0, NULL, &dwLen ); // Get the size required.
  3102. #endif // LATE_BIND_URLMON_WININET
  3103. _ASSERTE ( 0 != dwLen );
  3104. TCHAR* pszURL = new TCHAR [ dwLen + 1 ];
  3105. _ASSERTE ( pszURL );
  3106. if ( NULL != pszURL )
  3107. {
  3108. dwLen += 1;
  3109. memset ( pszURL, 0, sizeof(TCHAR) * dwLen );
  3110. #ifdef LATE_BIND_URLMON_WININET
  3111. if ( (*m_pfnInternetCreateUrl)( &urlc, 0, pszURL, &dwLen ) )
  3112. #else
  3113. if ( InternetCreateUrl ( &urlc, 0, pszURL, &dwLen ) )
  3114. #endif
  3115. {
  3116. m_bstrBaseURL = pszURL;
  3117. // Append a '/' if needed.
  3118. WCHAR wc = m_bstrBaseURL.m_str[m_bstrBaseURL.Length () - 1];
  3119. if ( ( WCHAR('/') != wc ) && ( NULL != urlc.lpszHostName ) ) // hostname: special case for user pluggable protocols
  3120. {
  3121. m_bstrBaseURL += L"/";
  3122. }
  3123. }
  3124. else
  3125. {
  3126. hr = HRESULT_FROM_WIN32 ( GetLastError () );
  3127. }
  3128. delete [] pszURL;
  3129. }
  3130. return hr;
  3131. }
  3132. // Crack the URL, determine if it's a file scheme or other, and call the appropriate handler.
  3133. //
  3134. HRESULT
  3135. CProxyFrame::SetBaseURLFromURL ( const CComBSTR& bstrURL )
  3136. {
  3137. USES_CONVERSION;
  3138. HRESULT hr = S_OK;
  3139. URL_COMPONENTS urlc;
  3140. TCHAR *ptszScheme = NULL;
  3141. TCHAR *ptszHostName = NULL;
  3142. TCHAR *ptszUrlPath = NULL;
  3143. BOOL fSuccess = FALSE;
  3144. TCHAR* tszURL = NULL;
  3145. _ASSERTE ( 0 != bstrURL.Length () );
  3146. tszURL = OLE2T ( bstrURL );
  3147. _ASSERTE ( tszURL );
  3148. if ( NULL == tszURL )
  3149. {
  3150. return E_OUTOFMEMORY;
  3151. }
  3152. memset ( &urlc, 0, sizeof ( urlc ) );
  3153. urlc.dwStructSize = sizeof ( urlc );
  3154. urlc.dwSchemeLength = 1;
  3155. urlc.dwHostNameLength = 1;
  3156. urlc.dwUrlPathLength = 1;
  3157. #ifdef LATE_BIND_URLMON_WININET
  3158. _ASSERTE ( m_pfnInternetCrackUrl );
  3159. fSuccess = (*m_pfnInternetCrackUrl)( tszURL, 0, 0, &urlc );
  3160. #else
  3161. fSuccess = InternetCrackUrl ( tszURL, 0, 0, &urlc );
  3162. #endif // LATE_BIND_URLMON_WININET
  3163. if ( !fSuccess )
  3164. {
  3165. return E_FAIL;
  3166. }
  3167. if ( 0 != urlc.dwSchemeLength )
  3168. {
  3169. urlc.dwSchemeLength++;
  3170. ptszScheme = new TCHAR[urlc.dwSchemeLength];
  3171. urlc.lpszScheme = ptszScheme;
  3172. if ( NULL == ptszScheme )
  3173. goto ONERROR;
  3174. }
  3175. if ( 0 != urlc.dwHostNameLength )
  3176. {
  3177. urlc.dwHostNameLength++;
  3178. ptszHostName = new TCHAR[urlc.dwHostNameLength];
  3179. urlc.lpszHostName = ptszHostName;
  3180. if ( NULL == ptszHostName )
  3181. goto ONERROR;
  3182. }
  3183. if ( 0 != urlc.dwUrlPathLength )
  3184. {
  3185. urlc.dwUrlPathLength++;
  3186. ptszUrlPath = new TCHAR[urlc.dwUrlPathLength];
  3187. urlc.lpszUrlPath = ptszUrlPath;
  3188. if ( NULL == ptszUrlPath )
  3189. goto ONERROR;
  3190. }
  3191. #ifdef LATE_BIND_URLMON_WININET
  3192. fSuccess = (*m_pfnInternetCrackUrl)( tszURL, 0, 0, &urlc );
  3193. #else
  3194. fSuccess = InternetCrackUrl ( tszURL, 0, 0, &urlc );
  3195. #endif
  3196. if ( fSuccess )
  3197. {
  3198. if ( INTERNET_SCHEME_FILE == urlc.nScheme )
  3199. {
  3200. hr = SetBaseUrlFromFileUrlComponents ( urlc );
  3201. }
  3202. else
  3203. {
  3204. hr = SetBaseUrlFromUrlComponents ( urlc );
  3205. }
  3206. }
  3207. ONERROR:
  3208. if ( ptszScheme )
  3209. delete [] ptszScheme;
  3210. if ( ptszHostName )
  3211. delete [] ptszHostName;
  3212. if ( ptszUrlPath )
  3213. delete [] ptszUrlPath;
  3214. return hr;
  3215. }
  3216. // Given a UNC file name, set the m_bstrBaseURL member variable.
  3217. // if bstrFName is empty, set m_bstrBaseURL to empty.
  3218. // Else, scan backward to the first "\" or the beginning of the string.
  3219. // Truncate the string at this point. If the resultant string is empty,
  3220. // add ".". Then, add "\".
  3221. //
  3222. HRESULT
  3223. CProxyFrame::SetBaseURLFromFileName ( const CComBSTR& bstrFName )
  3224. {
  3225. if ( 0 == bstrFName.Length () )
  3226. {
  3227. m_bstrBaseURL = L"";
  3228. }
  3229. else
  3230. {
  3231. WCHAR* pwzstr = new WCHAR[bstrFName.Length () + 1];
  3232. _ASSERTE ( pwzstr );
  3233. if ( NULL != pwzstr )
  3234. {
  3235. WCHAR wc = 0;
  3236. int iPos = 0;
  3237. // Scan backwards and modify in copy (never in BSTR, please) for beginning or '\'
  3238. memcpy ( pwzstr, bstrFName.m_str, sizeof(WCHAR) * (bstrFName.Length () + 1) );
  3239. for ( iPos = wcslen ( pwzstr ) - 1; iPos >= 0; iPos-- )
  3240. {
  3241. wc = pwzstr[iPos];
  3242. pwzstr[iPos] = WCHAR('\0'); // Delete first, ask questions later. '\' must go.
  3243. if ( WCHAR('\\') == wc )
  3244. {
  3245. break;
  3246. }
  3247. }
  3248. m_bstrBaseURL = pwzstr;
  3249. delete [] pwzstr;
  3250. // If empty, add a '.'
  3251. if ( 0 == m_bstrBaseURL.Length () )
  3252. {
  3253. m_bstrBaseURL += L".";
  3254. }
  3255. m_bstrBaseURL += L"\\";
  3256. }
  3257. else
  3258. {
  3259. return E_FAIL;
  3260. }
  3261. }
  3262. return S_OK;
  3263. }
  3264. ///////////////////////////////////////////////////////////////////////////////////////////
  3265. //
  3266. // Security oriented routines
  3267. //
  3268. ///////////////////////////////////////////////////////////////////////////////////////////
  3269. // This is a critical security issue:
  3270. // The pluggable protocol's ParseURL is called with PARSE_SECURITY_URL in the SFS control.
  3271. // If the BaseURL is empty, and if we're hosted in Trident, we should return the
  3272. // URL of the hosting page.
  3273. // If there is no Trident host, say we're hosted in VB, return the bootdrive + : + /.
  3274. // Bootdrive is not always C.
  3275. //
  3276. HRESULT
  3277. CProxyFrame::GetSecurityURL (CComBSTR& bstrSecurityURL )
  3278. {
  3279. HRESULT hr = S_OK;
  3280. IOleClientSite *piClientSiteUnreffed = NULL;
  3281. bstrSecurityURL = L"";
  3282. piClientSiteUnreffed = m_pCtl->m_spClientSite;
  3283. if ( NULL != piClientSiteUnreffed )
  3284. {
  3285. CComPtr<IOleContainer> spContainer = NULL;
  3286. hr = piClientSiteUnreffed->GetContainer ( &spContainer );
  3287. if ( SUCCEEDED ( hr ) && spContainer )
  3288. {
  3289. CComQIPtr<IHTMLDocument2, &IID_IHTMLDocument2> spHostDoc ( spContainer );
  3290. if ( spHostDoc )
  3291. {
  3292. CComPtr<IHTMLLocation> spHostLoc = NULL;
  3293. spHostDoc->get_location ( &spHostLoc );
  3294. if ( spHostLoc )
  3295. {
  3296. BSTR bsOut;
  3297. hr = spHostLoc->get_href ( &bsOut );
  3298. if ( SUCCEEDED ( hr ) )
  3299. {
  3300. bstrSecurityURL.Empty ();
  3301. bstrSecurityURL.Attach ( bsOut );
  3302. }
  3303. }
  3304. }
  3305. else
  3306. {
  3307. // If we are not hosted in Trident, use local machine access:
  3308. TCHAR tszDrive[4];
  3309. GetModuleFileName ( _Module.m_hInst, tszDrive, 3 ); // Get X:\.
  3310. _ASSERTE ( TCHAR(':') == tszDrive[1] );
  3311. _ASSERTE ( TCHAR('\\') == tszDrive[2] );
  3312. bstrSecurityURL = tszDrive;
  3313. hr = S_OK;
  3314. }
  3315. }
  3316. }
  3317. return hr;
  3318. }
  3319. ///////////////////////////////////////////////////////////////////////////////////////////
  3320. //
  3321. // Pluggable protocol oriented routines
  3322. //
  3323. ///////////////////////////////////////////////////////////////////////////////////////////
  3324. // Register our pluggable protocol handler so dhtmledN[N...] is loaded by our code.
  3325. //
  3326. HRESULT
  3327. CProxyFrame::RegisterPluggableProtocol()
  3328. {
  3329. HRESULT hr;
  3330. // Get InternetSession
  3331. CComPtr<IInternetSession> srpSession;
  3332. #ifdef LATE_BIND_URLMON_WININET
  3333. _ASSERTE ( m_pfnCoInternetGetSession );
  3334. hr = (*m_pfnCoInternetGetSession)(0, &srpSession, 0);
  3335. #else
  3336. hr = CoInternetGetSession (0, &srpSession, 0);
  3337. #endif // LATE_BIND_URLMON_WININET
  3338. if ( FAILED ( hr ) )
  3339. {
  3340. return hr;
  3341. }
  3342. if(m_pProtInfo == NULL)
  3343. {
  3344. hr = CComObject<CDHTMLEdProtocolInfo>::CreateInstance(&m_pProtInfo);
  3345. if ( FAILED ( hr ) )
  3346. {
  3347. return hr;
  3348. }
  3349. // CreateInstance - doesnt AddRef
  3350. m_pProtInfo->GetUnknown()->AddRef();
  3351. }
  3352. hr = srpSession->RegisterNameSpace(
  3353. static_cast<IClassFactory*>(m_pProtInfo),
  3354. CLSID_DHTMLEdProtocol,
  3355. m_wszProtocol,
  3356. 0,
  3357. NULL,
  3358. 0);
  3359. if ( FAILED ( hr ) )
  3360. {
  3361. return hr;
  3362. }
  3363. CComQIPtr <IProtocolInfoConnector, &IID_IProtocolInfoConnector> piPic ( m_pProtInfo );
  3364. _ASSERTE ( piPic );
  3365. piPic->SetProxyFrame ( (SIZE_T*)this );
  3366. ATLTRACE( _T("CProxyFrame::Registered ProtocolInfo\n"));
  3367. return NOERROR;
  3368. }
  3369. // Unregister the pluggable protocol handler installed in RegisterPluggableProtocol
  3370. //
  3371. HRESULT
  3372. CProxyFrame::UnRegisterPluggableProtocol()
  3373. {
  3374. if(m_pProtInfo == NULL)
  3375. return E_UNEXPECTED;
  3376. // Get InternetSession
  3377. HRESULT hr;
  3378. CComPtr<IInternetSession> srpSession;
  3379. #ifdef LATE_BIND_URLMON_WININET
  3380. _ASSERTE ( m_pfnCoInternetGetSession );
  3381. hr = (*m_pfnCoInternetGetSession)(0, &srpSession, 0);
  3382. #else
  3383. hr = CoInternetGetSession (0, &srpSession, 0);
  3384. #endif // LATE_BIND_URLMON_WININET
  3385. if(SUCCEEDED(hr))
  3386. {
  3387. // UnRegister Protocol
  3388. srpSession->UnregisterNameSpace(
  3389. static_cast<IClassFactory*>(m_pProtInfo),
  3390. m_wszProtocol);
  3391. }
  3392. m_pProtInfo->GetUnknown()->Release();
  3393. m_pProtInfo = NULL;
  3394. ATLTRACE(_T("CProxyFrame::UnRegistered ProtocolInfo\n"));
  3395. return NOERROR;
  3396. }
  3397. // Workhorse routine that actually performs the loading of the control, including filtering.
  3398. // ParseAndBind calls this to retrieve the data to be displayed in the control.
  3399. //
  3400. HRESULT
  3401. CProxyFrame::GetFilteredStream ( IStream** ppStream )
  3402. {
  3403. USES_CONVERSION;
  3404. HRESULT hr = S_OK;
  3405. LPTSTR pFileName = NULL;
  3406. CComPtr<IStream> piStream;
  3407. BOOL bfLoadingFromBSTR = ( 0 != m_bstrLoadText.Length () );
  3408. *ppStream = NULL;
  3409. m_bfReloadAttempted = TRUE;
  3410. if ( !bfLoadingFromBSTR )
  3411. {
  3412. _ASSERTE(m_bstrCurDocPath);
  3413. pFileName = OLE2T(m_bstrCurDocPath);
  3414. _ASSERTE(pFileName);
  3415. if (NULL == pFileName)
  3416. return E_OUTOFMEMORY;
  3417. }
  3418. if ( bfLoadingFromBSTR )
  3419. {
  3420. hr = m_pSite->HrBstrToStream(m_bstrLoadText, &piStream);
  3421. }
  3422. else if ( m_bfIsURL )
  3423. {
  3424. hr = m_pSite->HrURLToStream(pFileName, &piStream);
  3425. }
  3426. else
  3427. {
  3428. hr = m_pSite->HrFileToStream(pFileName, &piStream);
  3429. }
  3430. if (FAILED( hr ))
  3431. {
  3432. m_bstrCurDocPath.Empty ();
  3433. m_bstrBaseURL.Empty ();
  3434. // Get TriEdit into a reasonable state by loading an empty document
  3435. // If we reinstanced successfully, this should never fail
  3436. // Also, this will make ignoring the above assert benign
  3437. if (FAILED(m_pSite->HrBstrToStream(m_bstrInitialDoc, ppStream)))
  3438. {
  3439. _ASSERTE(SUCCEEDED(hr));
  3440. }
  3441. }
  3442. else
  3443. {
  3444. if ( m_vbBrowseMode )
  3445. {
  3446. piStream.p->AddRef ();
  3447. *ppStream = piStream;
  3448. }
  3449. else
  3450. {
  3451. hr = m_pSite->HrFilter(TRUE, piStream, ppStream, m_dwFilterFlags);
  3452. }
  3453. if (FAILED(hr))
  3454. {
  3455. m_pSite->HrBstrToStream(m_bstrInitialDoc, ppStream);
  3456. }
  3457. else
  3458. {
  3459. m_dwFilterOutFlags = m_dwFilterFlags;
  3460. }
  3461. }
  3462. // Store the result to return from the (indirectly) called routine,
  3463. // but don't return an error to ParseAndBind!
  3464. if ( FAILED(hr) && ( ! bfLoadingFromBSTR ) )
  3465. {
  3466. m_hrDeferredLoadError = hr; // Stash this away, we'll pic it up in LoadDocument
  3467. hr = S_OK;
  3468. }
  3469. return hr;
  3470. }
  3471. ///////////////////////////////////////////////////////////////////////////////////////////
  3472. //
  3473. // Document event handling routines
  3474. //
  3475. ///////////////////////////////////////////////////////////////////////////////////////////
  3476. HRESULT
  3477. CProxyFrame::OnTriEditEvent ( const GUID& iidEventInterface, DISPID dispid )
  3478. {
  3479. HRESULT hr = S_OK;
  3480. if ( DIID_HTMLDocumentEvents == iidEventInterface )
  3481. {
  3482. switch ( dispid )
  3483. {
  3484. case DISPID_HTMLDOCUMENTEVENTS_ONKEYPRESS:
  3485. case DISPID_HTMLDOCUMENTEVENTS_ONMOUSEDOWN:
  3486. if ( DISPID_HTMLDOCUMENTEVENTS_ONMOUSEDOWN == dispid )
  3487. {
  3488. m_pCtl->Fire_onmousedown();
  3489. }
  3490. else if ( DISPID_HTMLDOCUMENTEVENTS_ONKEYPRESS == dispid )
  3491. {
  3492. m_pCtl->Fire_onkeypress();
  3493. }
  3494. // Make the control UIActive if it was clicked in. Since the DocObject swallows the clicks,
  3495. // the control isn't activated automatically.
  3496. // Not needed in browse mode.
  3497. if ( !m_pCtl->m_bUIActive && ! m_vbBrowseMode )
  3498. {
  3499. m_pCtl->DoVerbUIActivate ( NULL, NULL );
  3500. if ( m_hWndObj != NULL )
  3501. {
  3502. ::SetFocus( m_hWndObj );
  3503. }
  3504. }
  3505. break;
  3506. case DISPID_HTMLDOCUMENTEVENTS_ONMOUSEMOVE:
  3507. m_pCtl->Fire_onmousemove();
  3508. break;
  3509. case DISPID_HTMLDOCUMENTEVENTS_ONMOUSEUP:
  3510. m_pCtl->Fire_onmouseup();
  3511. // onclick is not delivered in edit mode. First one lost in broswe mode.
  3512. m_pCtl->Fire_onclick();
  3513. break;
  3514. case DISPID_HTMLDOCUMENTEVENTS_ONMOUSEOUT:
  3515. m_pCtl->Fire_onmouseout();
  3516. break;
  3517. case DISPID_HTMLDOCUMENTEVENTS_ONMOUSEOVER:
  3518. m_pCtl->Fire_onmouseover();
  3519. break;
  3520. case DISPID_HTMLDOCUMENTEVENTS_ONCLICK:
  3521. // We do not fire the onclick event in response.
  3522. // It is only delivered in browse mode, and in addition,
  3523. // the first onclick is lost. We fire on onmouseup.
  3524. //m_pCtl->Fire_onclick();
  3525. // The addition of the DesignMode property, in addition to <BASE TARGET="_top">
  3526. // makes links exploitable for cross-zone access in the SFS control.
  3527. // We must disable clicks (user and script) in the SFS control to prevent this.
  3528. if ( m_pCtl->IsSafeForScripting ())
  3529. {
  3530. CComPtr<IHTMLDocument2> spHtmlDoc;
  3531. hr = HrGetDoc ( &spHtmlDoc );
  3532. if ( SUCCEEDED ( hr ) && spHtmlDoc )
  3533. {
  3534. CComPtr<IHTMLWindow2> spWindow;
  3535. hr = spHtmlDoc->get_parentWindow ( &spWindow );
  3536. if ( SUCCEEDED ( hr ) && spWindow )
  3537. {
  3538. CComPtr<IHTMLEventObj> spEvt;
  3539. hr = spWindow->get_event ( &spEvt );
  3540. if ( SUCCEEDED ( hr ) && spEvt )
  3541. {
  3542. CComVariant varFalse(VARIANT_FALSE);
  3543. spEvt->put_cancelBubble ( VARIANT_TRUE );
  3544. spEvt->put_returnValue ( varFalse );
  3545. }
  3546. }
  3547. }
  3548. }
  3549. break;
  3550. case DISPID_HTMLDOCUMENTEVENTS_ONDBLCLICK:
  3551. m_pCtl->Fire_ondblclick();
  3552. break;
  3553. case DISPID_HTMLDOCUMENTEVENTS_ONKEYDOWN:
  3554. m_pCtl->Fire_onkeydown();
  3555. break;
  3556. case DISPID_HTMLDOCUMENTEVENTS_ONKEYUP:
  3557. m_pCtl->Fire_onkeyup();
  3558. break;
  3559. case DISPID_HTMLDOCUMENTEVENTS_ONREADYSTATECHANGE:
  3560. m_pCtl->Fire_onreadystatechange();
  3561. break;
  3562. default:
  3563. _ASSERTE ( TRUE );
  3564. break;
  3565. }
  3566. }
  3567. else if ( DIID_HTMLWindowEvents == iidEventInterface )
  3568. {
  3569. // I expected to get these, but I'm not...
  3570. switch ( dispid )
  3571. {
  3572. case DISPID_HTMLWINDOWEVENTS_ONLOAD:
  3573. case DISPID_HTMLWINDOWEVENTS_ONUNLOAD:
  3574. case DISPID_HTMLWINDOWEVENTS_ONHELP:
  3575. case DISPID_HTMLWINDOWEVENTS_ONFOCUS:
  3576. case DISPID_HTMLWINDOWEVENTS_ONBLUR:
  3577. case DISPID_HTMLWINDOWEVENTS_ONERROR:
  3578. case DISPID_HTMLWINDOWEVENTS_ONRESIZE:
  3579. case DISPID_HTMLWINDOWEVENTS_ONSCROLL:
  3580. case DISPID_HTMLWINDOWEVENTS_ONBEFOREUNLOAD:
  3581. hr = S_OK;
  3582. break;
  3583. default:
  3584. _ASSERTE ( TRUE );
  3585. break;
  3586. }
  3587. }
  3588. return hr;
  3589. }
  3590. ///////////////////////////////////////////////////////////////////////////////////////////
  3591. //
  3592. // Dynamic loading routines, used in 4.0 versions
  3593. //
  3594. ///////////////////////////////////////////////////////////////////////////////////////////
  3595. #ifdef LATE_BIND_URLMON_WININET
  3596. // Load Urlmon and Wininet and get the proc addresses of every routine we use.
  3597. // We must be able to register the control, even if these libraries are not installed.
  3598. // NOTE:
  3599. // This routine loads ANSI versions. Needs addaptation for UNICODE.
  3600. //
  3601. BOOL CProxyFrame::DynLoadLibraries ()
  3602. {
  3603. m_hUlrMon = LoadLibrary ( TEXT("URLMON.DLL") );
  3604. m_hWinINet = LoadLibrary ( TEXT("WININET.DLL") );
  3605. if ( ( NULL == m_hUlrMon ) || ( NULL == m_hWinINet ) )
  3606. {
  3607. DynUnloadLibraries ();
  3608. return FALSE;
  3609. }
  3610. m_pfnCoInternetCombineUrl = (PFNCoInternetCombineUrl)GetProcAddress (
  3611. m_hUlrMon, "CoInternetCombineUrl" );
  3612. _ASSERTE ( m_pfnCoInternetCombineUrl );
  3613. m_pfnCoInternetParseUrl = (PFNCoInternetParseUrl)GetProcAddress (
  3614. m_hUlrMon, "CoInternetParseUrl" );
  3615. _ASSERTE ( m_pfnCoInternetParseUrl );
  3616. m_pfnCreateURLMoniker = (PFNCreateURLMoniker)GetProcAddress (
  3617. m_hUlrMon, "CreateURLMoniker" );
  3618. _ASSERTE ( m_pfnCreateURLMoniker );
  3619. m_pfnCoInternetGetSession = (PFNCoInternetGetSession)GetProcAddress (
  3620. m_hUlrMon, "CoInternetGetSession" );
  3621. _ASSERTE ( m_pfnCoInternetGetSession );
  3622. m_pfnURLOpenBlockingStream = (PFNURLOpenBlockingStream)GetProcAddress (
  3623. m_hUlrMon, "URLOpenBlockingStreamA" );
  3624. _ASSERTE ( m_pfnURLOpenBlockingStream );
  3625. m_pfnDeleteUrlCacheEntry = (PFNDeleteUrlCacheEntry)GetProcAddress (
  3626. m_hWinINet, "DeleteUrlCacheEntry" );
  3627. _ASSERTE ( m_pfnDeleteUrlCacheEntry );
  3628. m_pfnInternetCreateUrl = (PFNInternetCreateUrl)GetProcAddress (
  3629. m_hWinINet, "InternetCreateUrlA" );
  3630. _ASSERTE ( m_pfnInternetCreateUrl );
  3631. m_pfnInternetCrackUrl = (PFNInternetCrackURL)GetProcAddress (
  3632. m_hWinINet, "InternetCrackUrlA" );
  3633. _ASSERTE ( m_pfnInternetCrackUrl );
  3634. return ( m_pfnCoInternetCombineUrl && m_pfnCoInternetParseUrl && m_pfnCreateURLMoniker &&
  3635. m_pfnCoInternetGetSession && m_pfnURLOpenBlockingStream && m_pfnDeleteUrlCacheEntry &&
  3636. m_pfnInternetCreateUrl && m_pfnInternetCrackUrl );
  3637. }
  3638. // Release the libraries loaded by DynLoadLibraries
  3639. //
  3640. void CProxyFrame::DynUnloadLibraries ()
  3641. {
  3642. if ( NULL != m_hUlrMon )
  3643. {
  3644. FreeLibrary ( m_hUlrMon );
  3645. m_hUlrMon = NULL;
  3646. }
  3647. if ( NULL != m_hWinINet )
  3648. {
  3649. FreeLibrary ( m_hWinINet );
  3650. m_hWinINet = NULL;
  3651. }
  3652. m_pfnCoInternetCombineUrl = NULL;
  3653. m_pfnCoInternetParseUrl = NULL;
  3654. m_pfnCreateURLMoniker = NULL;
  3655. m_pfnCoInternetGetSession = NULL;
  3656. m_pfnURLOpenBlockingStream = NULL;
  3657. m_pfnDeleteUrlCacheEntry = NULL;
  3658. m_pfnInternetCreateUrl = NULL;
  3659. m_pfnInternetCrackUrl = NULL;
  3660. }
  3661. #endif // LATE_BIND_URLMON_WININET
  3662. ///////////////////////////////////////////////////////////////////////////////////////////
  3663. //
  3664. // Utility routines
  3665. //
  3666. ///////////////////////////////////////////////////////////////////////////////////////////
  3667. // Return the IHTMLDocument2 pointer from the hosted doc.
  3668. //
  3669. HRESULT
  3670. CProxyFrame::HrGetDoc(IHTMLDocument2 **ppDoc)
  3671. {
  3672. HRESULT hr = E_FAIL;
  3673. IUnknown* lpUnk = m_pSite->GetObjectUnknown();
  3674. if (FALSE == m_fActivated)
  3675. return DE_E_UNEXPECTED;
  3676. _ASSERTE(ppDoc);
  3677. if (NULL == ppDoc)
  3678. return DE_E_INVALIDARG;
  3679. _ASSERTE(lpUnk);
  3680. if ( m_bfIsLoading )
  3681. return DE_E_UNEXPECTED; // This is invalid while document is still loading.
  3682. if (lpUnk != NULL)
  3683. {
  3684. // Request the "document" object from the MSHTML
  3685. *ppDoc = NULL;
  3686. hr = lpUnk->QueryInterface(IID_IHTMLDocument2, (void **)ppDoc);
  3687. }
  3688. _ASSERTE(SUCCEEDED(hr)); // this should always succeed
  3689. return hr;
  3690. }
  3691. // Helper routine to set any Boolean Trident property
  3692. //
  3693. HRESULT
  3694. CProxyFrame::HrTridentSetPropBool(ULONG cmd, BOOL bVal)
  3695. {
  3696. HRESULT hr = S_OK;
  3697. VARIANT varIn;
  3698. VariantInit(&varIn);
  3699. V_VT(&varIn) = VT_BOOL;
  3700. #pragma warning(disable: 4310) // cast truncates constant value
  3701. bVal ? V_BOOL(&varIn) = VARIANT_TRUE : V_BOOL(&varIn) = VARIANT_FALSE;
  3702. #pragma warning(default: 4310) // cast truncates constant value
  3703. hr = HrExecCommand(&CGID_MSHTML, cmd, MSOCMDEXECOPT_DONTPROMPTUSER, &varIn, NULL);
  3704. // this should always succeed since all props
  3705. // should be set in correct phases of Trident creation
  3706. _ASSERTE(SUCCEEDED(hr));
  3707. return hr;
  3708. }
  3709. // Helper routine to get any Boolean Trident property
  3710. //
  3711. HRESULT
  3712. CProxyFrame::HrTridentGetPropBool(ULONG cmd, BOOL& bVal)
  3713. {
  3714. HRESULT hr = S_OK;
  3715. OLECMDF cmdf = (OLECMDF) 0;
  3716. if (SUCCEEDED(HrQueryStatus(&CGID_MSHTML, cmd, &cmdf)))
  3717. {
  3718. bVal = (cmdf & OLECMDF_ENABLED) == OLECMDF_ENABLED ? TRUE : FALSE;
  3719. }
  3720. // this should always succeed since all props
  3721. // should be set in correct phases of Trident creation
  3722. _ASSERTE(SUCCEEDED(hr));
  3723. return hr;
  3724. }
  3725. // Store the BSTR so LoadFilteredStream can access it, and load a URL with our protocol
  3726. // to kick off the load/resolve/display through the pluggable protocol handler.
  3727. //
  3728. // Clear the BaseURL, and mark the control "Loading..."
  3729. //
  3730. HRESULT
  3731. CProxyFrame::LoadBSTRDeferred ( BSTR bVal )
  3732. {
  3733. HRESULT hr = E_FAIL;
  3734. _ASSERTE ( m_pUnkTriEdit );
  3735. m_bstrLoadText = bVal;
  3736. CComPtr<IMoniker> srpMoniker;
  3737. CComPtr<IBindCtx> srpBindCtx;
  3738. CComQIPtr<IPersistMoniker, &IID_IPersistMoniker> srpPM (m_pUnkTriEdit);
  3739. _ASSERTE ( srpPM );
  3740. if ( srpPM )
  3741. {
  3742. #ifdef LATE_BIND_URLMON_WININET
  3743. _ASSERTE ( m_pfnCreateURLMoniker );
  3744. hr = (*m_pfnCreateURLMoniker)( NULL, m_wszProtocolPrefix, &srpMoniker );
  3745. #else
  3746. hr = CreateURLMoniker ( NULL, m_wszProtocolPrefix, &srpMoniker );
  3747. #endif // LATE_BIND_URLMON_WININET
  3748. _ASSERTE ( SUCCEEDED( hr ) );
  3749. if ( SUCCEEDED ( hr ) )
  3750. {
  3751. hr = ::CreateBindCtx(NULL, &srpBindCtx);
  3752. _ASSERTE ( SUCCEEDED( hr ) );
  3753. if ( SUCCEEDED ( hr ) )
  3754. {
  3755. m_bfIsLoading = TRUE;
  3756. m_bfBaseURLFromBASETag = FALSE;
  3757. hr = srpPM->Load(FALSE, srpMoniker, srpBindCtx, STGM_READ);
  3758. _ASSERTE ( SUCCEEDED( hr ) );
  3759. }
  3760. }
  3761. }
  3762. return hr;
  3763. }
  3764. // Set the document stream's dirty flag
  3765. //
  3766. HRESULT
  3767. CProxyFrame::SetDirtyFlag ( BOOL bfMakeDirty )
  3768. {
  3769. CComVariant varDirty;
  3770. varDirty = bfMakeDirty ? true : false;
  3771. return HrExecCommand(&CGID_MSHTML, IDM_SETDIRTY, MSOCMDEXECOPT_DONTPROMPTUSER, &varDirty, NULL);
  3772. }
  3773. // properties that can be set only after TriEdit is in running state
  3774. HRESULT
  3775. CProxyFrame::HrSetRuntimeProperties()
  3776. {
  3777. HRESULT hr = S_OK;
  3778. if (FAILED(hr = HrSetPropActivateControls(m_fActivateControls)))
  3779. {
  3780. _ASSERTE(SUCCEEDED(hr));
  3781. goto error;
  3782. }
  3783. if (FAILED(hr = HrSetPropActivateApplets(m_fActivateApplets)))
  3784. {
  3785. _ASSERTE(SUCCEEDED(hr));
  3786. goto error;
  3787. }
  3788. if (FAILED(hr = HrSetPropActivateDTCs(m_fActivateDTCs)))
  3789. {
  3790. _ASSERTE(SUCCEEDED(hr));
  3791. goto error;
  3792. }
  3793. // toggle properties
  3794. if (FAILED(hr = HrSetPropShowAllTags(m_fShowAllTags)))
  3795. {
  3796. _ASSERTE(SUCCEEDED(hr));
  3797. goto error;
  3798. }
  3799. if (FAILED(hr = HrSetPropShowBorders(m_fShowBorders)))
  3800. {
  3801. _ASSERTE(SUCCEEDED(hr));
  3802. goto error;
  3803. }
  3804. error:
  3805. return hr;
  3806. }
  3807. HRESULT
  3808. CProxyFrame::HrGetCurrentDocumentPath(BSTR* bVal)
  3809. {
  3810. HRESULT hr = S_OK;
  3811. _ASSERTE(bVal);
  3812. if (NULL == bVal)
  3813. return E_INVALIDARG;
  3814. *bVal = m_bstrCurDocPath.Copy ();
  3815. return hr;
  3816. }
  3817. // properties that can only be set after UIActivation
  3818. HRESULT
  3819. CProxyFrame::HrSetDocLoadedProperties()
  3820. {
  3821. HRESULT hr = S_OK;
  3822. BOOL bGoodUndoBehavior = TRUE;
  3823. bGoodUndoBehavior = TRUE;
  3824. if (FAILED(HrTridentGetPropBool(IDM_GOOD_UNDO_BEHAVIOR, bGoodUndoBehavior)))
  3825. {
  3826. _ASSERTE(SUCCEEDED(hr));
  3827. goto error;
  3828. }
  3829. if (FAILED(hr = HrSetAbsoluteDropMode(m_fAbsoluteDropMode)))
  3830. {
  3831. _ASSERTE(SUCCEEDED(hr));
  3832. goto error;
  3833. }
  3834. if (FAILED(hr = HrSetSnapToGridX(m_ulSnapToGridX)))
  3835. {
  3836. _ASSERTE(SUCCEEDED(hr));
  3837. goto error;
  3838. }
  3839. if (FAILED(hr = HrSetSnapToGridY(m_ulSnapToGridY)))
  3840. {
  3841. _ASSERTE(SUCCEEDED(hr));
  3842. goto error;
  3843. }
  3844. if (FAILED(hr = HrSetSnapToGrid(m_fSnapToGrid)))
  3845. {
  3846. _ASSERTE(SUCCEEDED(hr));
  3847. goto error;
  3848. }
  3849. error:
  3850. return hr;
  3851. }
  3852. // HrExecInsertTable helper. Extract the safearrys
  3853. //
  3854. HRESULT
  3855. CProxyFrame::HrGetTableSafeArray(IDEInsertTableParam* pTable, LPVARIANT pVarIn)
  3856. {
  3857. HRESULT hr = S_OK;
  3858. UINT i = 0;
  3859. SAFEARRAY FAR* psa = NULL;
  3860. SAFEARRAYBOUND rgsabound[1] = {0};
  3861. LONG ix[1] = {0};
  3862. VARIANT varElem;
  3863. LONG nNumRows = 0;
  3864. LONG nNumCols = 0;
  3865. BSTR bstrTableAttrs = NULL;
  3866. BSTR bstrCellAttrs = NULL;
  3867. BSTR bstrCaption = NULL;
  3868. _ASSERTE(pTable);
  3869. if (FAILED(hr = pTable->get_NumRows(&nNumRows)))
  3870. {
  3871. _ASSERTE(SUCCEEDED(hr));
  3872. return hr;
  3873. }
  3874. if (FAILED(hr = pTable->get_NumCols(&nNumCols)))
  3875. {
  3876. _ASSERTE(SUCCEEDED(hr));
  3877. return hr;
  3878. }
  3879. if (FAILED(hr = pTable->get_TableAttrs(&bstrTableAttrs)))
  3880. {
  3881. _ASSERTE(SUCCEEDED(hr));
  3882. return hr;
  3883. }
  3884. _ASSERTE(bstrTableAttrs);
  3885. if (FAILED(hr = pTable->get_CellAttrs(&bstrCellAttrs)))
  3886. {
  3887. _ASSERTE(SUCCEEDED(hr));
  3888. return hr;
  3889. }
  3890. _ASSERTE(bstrCellAttrs);
  3891. if (FAILED(hr = pTable->get_Caption(&bstrCaption)))
  3892. {
  3893. _ASSERTE(SUCCEEDED(hr));
  3894. return hr;
  3895. }
  3896. _ASSERTE(bstrCaption);
  3897. rgsabound[0].lLbound = 0;
  3898. rgsabound[0].cElements = 5;
  3899. psa = SafeArrayCreate(VT_VARIANT, 1, rgsabound);
  3900. _ASSERTE(psa);
  3901. if(NULL == psa)
  3902. return E_OUTOFMEMORY;
  3903. VariantInit(pVarIn);
  3904. V_VT(pVarIn) = VT_ARRAY;
  3905. V_ARRAY(pVarIn) = psa;
  3906. i=0;
  3907. // elmement 1: number of rows
  3908. ix[0] = i;
  3909. VariantInit(&varElem);
  3910. V_VT(&varElem) = VT_I4;
  3911. V_I4(&varElem) = nNumRows;
  3912. hr = SafeArrayPutElement(psa, ix, &varElem);
  3913. VariantClear(&varElem);
  3914. ++i;
  3915. // elmement 2: number of columns
  3916. ix[0] = i;
  3917. VariantInit(&varElem);
  3918. V_VT(&varElem) = VT_I4;
  3919. V_I4(&varElem) = nNumCols;
  3920. hr = SafeArrayPutElement(psa, ix, &varElem);
  3921. VariantClear(&varElem);
  3922. ++i;
  3923. // elmement 3: table tag attributes
  3924. ix[0] = i;
  3925. VariantInit(&varElem);
  3926. V_VT(&varElem) = VT_BSTR;
  3927. V_BSTR(&varElem) = bstrTableAttrs;
  3928. hr = SafeArrayPutElement(psa, ix, &varElem);
  3929. VariantClear(&varElem);
  3930. ++i;
  3931. // elmement 4: cell attributes
  3932. ix[0] = i;
  3933. VariantInit(&varElem);
  3934. V_VT(&varElem) = VT_BSTR;
  3935. V_BSTR(&varElem) = bstrCellAttrs;
  3936. hr = SafeArrayPutElement(psa, ix, &varElem);
  3937. VariantClear(&varElem);
  3938. ++i;
  3939. // elmement 5: table caption
  3940. // VK bug 15857: don't include caption if it's empty.
  3941. if ( 0 != SysStringLen ( bstrCaption ) )
  3942. {
  3943. ix[0] = i;
  3944. VariantInit(&varElem);
  3945. V_VT(&varElem) = VT_BSTR;
  3946. V_BSTR(&varElem) = bstrCaption;
  3947. hr = SafeArrayPutElement(psa, ix, &varElem);
  3948. VariantClear(&varElem);
  3949. ++i;
  3950. }
  3951. return hr;
  3952. }
  3953. // Determine which object is selected, and return its position
  3954. //
  3955. HRESULT
  3956. CProxyFrame::GetSelectionPos ( LPPOINT lpWhere )
  3957. {
  3958. HRESULT hr = E_FAIL;
  3959. CComPtr<IHTMLDocument2> spHtmlDoc = NULL;
  3960. CComPtr<IHTMLSelectionObject> spSelectionObj = NULL;
  3961. CComPtr<IDispatch> spRangeDisp = NULL;
  3962. CComPtr<IHTMLElement> spElement = NULL;
  3963. lpWhere->x = 0;
  3964. lpWhere->y = 0;
  3965. hr = HrGetDoc ( &spHtmlDoc );
  3966. if ( SUCCEEDED ( hr ) )
  3967. {
  3968. hr = spHtmlDoc->get_selection ( &spSelectionObj );
  3969. if ( SUCCEEDED ( hr ) )
  3970. {
  3971. hr = spSelectionObj->createRange ( &spRangeDisp );
  3972. if (SUCCEEDED ( hr ) )
  3973. {
  3974. CComQIPtr<IHTMLTxtRange, &IID_IHTMLTxtRange> spTextRange ( spRangeDisp );
  3975. if ( spTextRange )
  3976. {
  3977. hr = spTextRange->parentElement(&spElement);
  3978. }
  3979. else
  3980. {
  3981. CComQIPtr<IHTMLControlRange, &IID_IHTMLControlRange> spControlRange ( spRangeDisp );
  3982. if ( spControlRange )
  3983. {
  3984. hr = spControlRange->commonParentElement(&spElement);
  3985. }
  3986. }
  3987. if ( spElement )
  3988. {
  3989. CComPtr<IHTMLStyle> spStyle = NULL;
  3990. hr = spElement->get_style ( &spStyle );
  3991. if ( spStyle )
  3992. {
  3993. spStyle->get_pixelTop ( &( lpWhere->y ) );
  3994. spStyle->get_pixelLeft ( &( lpWhere->x ) );
  3995. }
  3996. }
  3997. }
  3998. }
  3999. }
  4000. return hr;
  4001. }
  4002. // If the current document is loaded from a URL, return the empty string.
  4003. // If it's loaded from a file, strip the path part off and return just the file name.
  4004. // Return S_FALSE for a URL or no file name. S_OK if a file name is supplied.
  4005. //
  4006. HRESULT
  4007. CProxyFrame::GetCurDocNameWOPath ( CComBSTR& bstrDocName )
  4008. {
  4009. bstrDocName = L"";
  4010. if ( m_bfIsURL )
  4011. {
  4012. return S_FALSE;
  4013. }
  4014. if ( 0 == m_bstrCurDocPath.Length () )
  4015. {
  4016. return S_FALSE;
  4017. }
  4018. bstrDocName = m_bstrCurDocPath;
  4019. // Truncate at first backslash:
  4020. _wcsrev ( bstrDocName );
  4021. wcstok ( bstrDocName, OLESTR( "\\" ) );
  4022. _wcsrev ( bstrDocName );
  4023. return S_OK;
  4024. }
  4025. // Used by ShowContextMenu to properly offset the position of the click
  4026. //
  4027. HRESULT
  4028. CProxyFrame::GetScrollPos ( LPPOINT lpPos )
  4029. {
  4030. HRESULT hr = E_FAIL;
  4031. CComPtr<IHTMLDocument2> spHtmlDoc = NULL;
  4032. CComPtr<IHTMLElement> spBodyElem = NULL;
  4033. _ASSERTE ( lpPos );
  4034. hr = HrGetDoc ( &spHtmlDoc );
  4035. // It's possible that the user clicked while the doc was still loading.
  4036. // If so, just return 0, 0.
  4037. if ( DE_E_UNEXPECTED == hr )
  4038. {
  4039. lpPos->x = lpPos->y = 0;
  4040. return S_FALSE;
  4041. }
  4042. _ASSERTE ( spHtmlDoc );
  4043. if ( SUCCEEDED ( hr ) )
  4044. {
  4045. hr = spHtmlDoc->get_body ( &spBodyElem );
  4046. _ASSERTE ( spBodyElem );
  4047. if ( SUCCEEDED ( hr ) )
  4048. {
  4049. CComQIPtr<IHTMLTextContainer, &IID_IHTMLTextContainer> spHtmlTextCont ( spBodyElem );
  4050. if ( spHtmlTextCont )
  4051. {
  4052. LONG lxPos = 0;
  4053. LONG lyPos = 0;
  4054. hr = spHtmlTextCont->get_scrollLeft ( &lxPos );
  4055. _ASSERTE ( SUCCEEDED ( hr ) );
  4056. if ( SUCCEEDED ( hr ) )
  4057. {
  4058. hr = spHtmlTextCont->get_scrollTop ( &lyPos );
  4059. _ASSERTE ( SUCCEEDED ( hr ) );
  4060. if ( SUCCEEDED ( hr ) )
  4061. {
  4062. lpPos->x = lxPos;
  4063. lpPos->y = lyPos;
  4064. }
  4065. }
  4066. }
  4067. else
  4068. {
  4069. hr = E_NOINTERFACE;
  4070. _ASSERTE ( SUCCEEDED ( hr ) );
  4071. }
  4072. }
  4073. }
  4074. return hr;
  4075. }
  4076. HRESULT
  4077. CProxyFrame::GetContainer ( LPOLECONTAINER* ppContainer )
  4078. {
  4079. _ASSERTE ( m_pCtl );
  4080. _ASSERTE ( m_pCtl->m_spClientSite );
  4081. if ( m_pCtl->m_spClientSite )
  4082. {
  4083. return m_pCtl->m_spClientSite->GetContainer ( ppContainer );
  4084. }
  4085. return E_NOTIMPL;
  4086. }
  4087. // For the Safe for Scripting control, make sure the URL specified comes from
  4088. // the same host as the SecurityURL, the URL of the hosting container..
  4089. // Note that this makes the SFS control virtually useless in VB, which returns
  4090. // the Boot Drive Root Folder as the Security URL.
  4091. //
  4092. HRESULT CProxyFrame::CheckCrossZoneSecurity ( BSTR urlToLoad )
  4093. {
  4094. HRESULT hr = S_OK;
  4095. CComPtr<IInternetSecurityManager> srpSec;
  4096. CComBSTR bstrSecURL;
  4097. hr = GetSecurityURL ( bstrSecURL );
  4098. _ASSERTE ( SUCCEEDED ( hr ) );
  4099. if ( SUCCEEDED ( hr ) )
  4100. {
  4101. #ifdef LATE_BIND_URLMON_WININET
  4102. hr = (m_pfnCoInternetCreateSecurityManager)( NULL, &srpSec, 0 );
  4103. #else
  4104. hr = CoInternetCreateSecurityManager( NULL, &srpSec, 0 );
  4105. #endif // LATE_BIND_URLMON_WININET
  4106. if ( SUCCEEDED ( hr ) && srpSec )
  4107. {
  4108. BYTE* pbSidToLoad = NULL;
  4109. BYTE* pbDSidSecURL = NULL;
  4110. DWORD dwSizeToLoad = INTERNET_MAX_URL_LENGTH;
  4111. DWORD dwSizeSecURL = INTERNET_MAX_URL_LENGTH;
  4112. pbSidToLoad = new BYTE [INTERNET_MAX_URL_LENGTH];
  4113. pbDSidSecURL = new BYTE [INTERNET_MAX_URL_LENGTH];
  4114. hr = srpSec->GetSecurityId ( urlToLoad, pbSidToLoad, &dwSizeToLoad, 0 );
  4115. _ASSERTE ( SUCCEEDED ( hr ) );
  4116. if ( SUCCEEDED ( hr ) )
  4117. {
  4118. hr = srpSec->GetSecurityId ( bstrSecURL, pbDSidSecURL, &dwSizeSecURL, 0 );
  4119. _ASSERTE ( SUCCEEDED ( hr ) );
  4120. if ( SUCCEEDED ( hr ) )
  4121. {
  4122. hr = DE_E_ACCESS_DENIED;
  4123. if ( ( dwSizeToLoad == dwSizeSecURL ) &&
  4124. ( 0 == memcmp ( pbSidToLoad, pbDSidSecURL, dwSizeToLoad ) ) )
  4125. {
  4126. hr = S_OK;
  4127. }
  4128. }
  4129. }
  4130. delete [] pbSidToLoad;
  4131. delete [] pbDSidSecURL;
  4132. }
  4133. else
  4134. {
  4135. // BUG 597887: If CoInternetCreateSecurityManager returns NULL and success, return error:
  4136. if ( !srpSec )
  4137. {
  4138. hr = E_UNEXPECTED;
  4139. }
  4140. }
  4141. }
  4142. return hr;
  4143. }
  4144. // A specialization of CheckCrossZoneSecurity which works on the current selection.
  4145. // Bug 547802 indicated a regression in execCommand, so we will assure safety ourselves.
  4146. //
  4147. HRESULT CProxyFrame::CheckCrossZoneSecurityOfSelection ()
  4148. {
  4149. HRESULT hr = S_OK;
  4150. CComPtr<IHTMLDocument2> spDOM;
  4151. CComPtr<IServiceProvider> srpSP;
  4152. CComPtr<IHTMLEditServices> srpEditor;
  4153. CComPtr<ISelectionServices> srpSelSvc;
  4154. CComPtr<IMarkupContainer> sprMarkupCont;
  4155. CComPtr<IHTMLDocument2> spSelDoc;
  4156. CComPtr<IHTMLLocation> spHostLoc;
  4157. CComBSTR bstrHref;
  4158. hr = HrGetDoc( &spDOM );
  4159. if ( FAILED(hr) ) goto ONERROR;
  4160. hr = spDOM->QueryInterface(IID_IServiceProvider, (LPVOID *)&srpSP);
  4161. if ( FAILED(hr) ) goto ONERROR;
  4162. hr = srpSP->QueryService(SID_SHTMLEditServices, IID_IHTMLEditServices, (void **)&srpEditor);
  4163. if ( FAILED(hr) ) goto ONERROR;
  4164. hr = srpEditor->GetSelectionServices(NULL, &srpSelSvc);
  4165. if ( FAILED(hr) ) goto ONERROR;
  4166. if ( !srpSelSvc ) goto ONERROR;
  4167. hr = srpSelSvc->GetMarkupContainer(&sprMarkupCont);
  4168. if ( FAILED(hr) ) goto ONERROR;
  4169. if ( !sprMarkupCont ) goto ONERROR;
  4170. hr = sprMarkupCont->QueryInterface(&spSelDoc);
  4171. if ( FAILED(hr) ) goto ONERROR;
  4172. hr = spSelDoc->get_location ( &spHostLoc );
  4173. if ( FAILED(hr) ) goto ONERROR;
  4174. if ( !spHostLoc ) goto ONERROR;
  4175. hr = spHostLoc->get_href ( &bstrHref );
  4176. if ( FAILED(hr) ) goto ONERROR;
  4177. if ( !bstrHref ) goto ONERROR;
  4178. hr = CheckCrossZoneSecurity ( bstrHref );
  4179. return hr;
  4180. ONERROR:
  4181. return DE_E_ACCESS_DENIED;
  4182. }
  4183. HRESULT CProxyFrame::OnProgress(ULONG, ULONG, ULONG ulStatusCode, LPCWSTR)
  4184. {
  4185. if ( BINDSTATUS_REDIRECTING == ulStatusCode )
  4186. {
  4187. // If we're the SFS control, cancel on Redirect. Otherwise, ignore it.
  4188. if ( m_pCtl->IsSafeForScripting ())
  4189. {
  4190. m_bfSFSRedirect = TRUE;
  4191. }
  4192. }
  4193. return E_NOTIMPL;
  4194. }