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.

3010 lines
80 KiB

  1. #include "precomp.h"
  2. #define __MARS_INLINE_FAST_IS_EQUAL_GUID
  3. #define LIGHTWEIGHT_AUTOPERSIST
  4. #define BLOCK_PANEL_RENAVIGATES
  5. #include "mcinc.h"
  6. #include <evilguid.h>
  7. #include "marswin.h"
  8. #include "pandef.h"
  9. #include "panel.h"
  10. #include "place.h"
  11. #include "htiface.h"
  12. #include "mimeinfo.h"
  13. #include <exdispid.h>
  14. #include "dllload.h"
  15. #include <perhist.h>
  16. #include <mshtmcid.h>
  17. #include <strsafe.h>
  18. #include <msiehost.h>
  19. // We include this cpp file because the stuff
  20. // in pandef needs to be included in another project
  21. // namely, parser\comptree
  22. #include "pandef.cpp"
  23. // CLSID strings passed to ATL to create control
  24. static WCHAR wszCLSID_HTMLDocument[] = L"{25336920-03F9-11CF-8FD0-00AA00686F13}";
  25. static WCHAR wszCLSID_WebBrowser[] = L"{8856F961-340A-11D0-A96B-00C04FD705A2}";
  26. static WCHAR wszCLSID_HTADocument[] = L"{3050f5c8-98b5-11cf-bb82-00aa00bdce0b}";
  27. const GUID CLSID_HTADoc = { 0x3050f5c8, 0x98b5, 0x11cf, { 0xbb, 0x82, 0x00, 0xaa, 0x00, 0xbd, 0xce, 0x0b } };
  28. // CLASS_CMarsPanel = {EE0462C2-5CD3-11d3-97FA-00C04F45D0B3}
  29. const GUID CLASS_CMarsPanel = { 0xee0462c2, 0x5cd3, 0x11d3, { 0x97, 0xfa, 0x0, 0xc0, 0x4f, 0x45, 0xd0, 0xb3 } };
  30. CMarsPanel::CMarsPanel(CPanelCollection *pParent, CMarsWindow *pMarsWindow) :
  31. m_MarsExternal(this, pMarsWindow),
  32. m_BrowserEvents(this)
  33. {
  34. m_spPanelCollection = pParent;
  35. m_spMarsDocument = m_spPanelCollection->Document();
  36. m_lReadyState = READYSTATE_COMPLETE;
  37. }
  38. CMarsPanel::~CMarsPanel()
  39. {
  40. }
  41. HRESULT CMarsPanel::Passivate()
  42. {
  43. return CMarsComObject::Passivate();
  44. }
  45. HRESULT CMarsPanel::DoPassivate()
  46. {
  47. m_spMarsDocument->MarsWindow()->NotifyHost(MARSHOST_ON_PANEL_PASSIVATE, SAFECAST(this, IMarsPanel *), 0);
  48. m_spPanelCollection->SetActivePanel(this, FALSE);
  49. // First we unload the document so that script can do work in its "onunload"
  50. // handler, before we become passive
  51. if(IsWebBrowser())
  52. {
  53. CComPtr<IUnknown> spUnk;
  54. if (SUCCEEDED(m_Content.QueryControl(IID_IUnknown, (void **)&spUnk)))
  55. {
  56. m_BrowserEvents.Connect(spUnk, FALSE);
  57. }
  58. }
  59. else if(IsCustomControl())
  60. {
  61. }
  62. else
  63. {
  64. DisconnectCompletionAdviser();
  65. }
  66. m_Content.DestroyWindow();
  67. ////////////////////////////////////////
  68. m_spMarsDocument->MarsWindow()->ReleaseOwnedObjects(SAFECAST(this, IDispatch *));
  69. m_BrowserEvents.Passivate();
  70. m_MarsExternal.Passivate();
  71. m_spBrowserService.Release();
  72. m_spPanelCollection.Release();
  73. m_spMarsDocument.Release();
  74. return S_OK;
  75. }
  76. // IUnknown
  77. IMPLEMENT_ADDREF_RELEASE(CMarsPanel);
  78. STDMETHODIMP CMarsPanel::QueryInterface(REFIID iid, void ** ppvObject)
  79. {
  80. ATLASSERT(ppvObject);
  81. if ((iid == IID_IUnknown) ||
  82. (iid == IID_IDispatch) ||
  83. (iid == IID_IMarsPanel))
  84. {
  85. *ppvObject = SAFECAST(this, IMarsPanel *);
  86. }
  87. else if (iid == IID_IHlinkFrame)
  88. {
  89. *ppvObject = SAFECAST(this, IHlinkFrame *);
  90. }
  91. else if (iid == IID_IServiceProvider)
  92. {
  93. *ppvObject = SAFECAST(this, IServiceProvider *);
  94. }
  95. else if (iid == IID_IInternetSecurityManager)
  96. {
  97. *ppvObject = SAFECAST(this, IInternetSecurityManager *);
  98. }
  99. else if ((iid == IID_IOleInPlaceSite) || (iid == IID_IOleWindow))
  100. {
  101. *ppvObject = SAFECAST(this, IOleInPlaceSite *);
  102. }
  103. else if (iid == IID_IOleControlSite)
  104. {
  105. *ppvObject = SAFECAST(this, IOleControlSite *);
  106. }
  107. else if (iid == IID_IPropertyNotifySink)
  108. {
  109. *ppvObject = SAFECAST(this, IPropertyNotifySink *);
  110. }
  111. else if (iid == IID_IProfferService)
  112. {
  113. *ppvObject = SAFECAST(this, IProfferService *);
  114. }
  115. else if (iid == IID_IOleInPlaceUIWindow)
  116. {
  117. *ppvObject = SAFECAST(this, IOleInPlaceUIWindow *);
  118. }
  119. else if (iid == CLASS_CMarsPanel)
  120. {
  121. *ppvObject = SAFECAST(this, CMarsPanel *);
  122. }
  123. else
  124. {
  125. *ppvObject = NULL;
  126. return E_NOINTERFACE;
  127. }
  128. AddRef();
  129. return S_OK;
  130. }
  131. HRESULT CMarsPanel::DoEnableModeless(BOOL fEnable)
  132. {
  133. CComPtr<IOleInPlaceActiveObject> spOleInPlaceActiveObject;
  134. HRESULT hr = m_Content.QueryControl(&spOleInPlaceActiveObject);
  135. if (SUCCEEDED(hr))
  136. {
  137. spOleInPlaceActiveObject->EnableModeless(fEnable);
  138. }
  139. return hr;
  140. }
  141. //==================================================================
  142. // Automation Object Model
  143. //==================================================================
  144. //------------------------------------------------------------------------------
  145. // IMarsPanel::get_name
  146. //
  147. HRESULT CMarsPanel::get_name( BSTR *pbstrName )
  148. {
  149. HRESULT hr = E_INVALIDARG;
  150. if(API_IsValidWritePtr( pbstrName ))
  151. {
  152. *pbstrName = SysAllocString( GetName() );
  153. hr = (NULL != *pbstrName) ? S_OK : E_OUTOFMEMORY;
  154. }
  155. return hr;
  156. }
  157. //------------------------------------------------------------------------------
  158. // IMarsPanel::get_content
  159. //
  160. HRESULT CMarsPanel::get_content( IDispatch* *ppVal )
  161. {
  162. HRESULT hr = E_INVALIDARG;
  163. if(API_IsValidWritePtr( ppVal ))
  164. {
  165. *ppVal = NULL;
  166. if(VerifyNotPassive( &hr ))
  167. {
  168. CreateControl();
  169. hr = m_Content.QueryControl( ppVal );
  170. }
  171. }
  172. return hr;
  173. }
  174. //------------------------------------------------------------------------------
  175. // IMarsPanel::get_visible
  176. //
  177. HRESULT CMarsPanel::get_visible( VARIANT_BOOL *pbVisible )
  178. {
  179. HRESULT hr = E_INVALIDARG;
  180. if(API_IsValidWritePtr( pbVisible ))
  181. {
  182. if(VerifyNotPassive( &hr ))
  183. {
  184. *pbVisible = VARIANT_BOOLIFY( m_fVisible );
  185. hr = S_OK;
  186. }
  187. else
  188. {
  189. *pbVisible = VARIANT_FALSE;
  190. }
  191. }
  192. return hr;
  193. }
  194. //------------------------------------------------------------------------------
  195. // IMarsPanel::put_visible
  196. //
  197. HRESULT CMarsPanel::put_visible( VARIANT_BOOL bVisible )
  198. {
  199. ATLASSERT(IsValidVariantBoolVal( bVisible ));
  200. HRESULT hr = S_OK;
  201. if(VerifyNotPassive( &hr ))
  202. {
  203. if(!!m_fVisible != !!bVisible)
  204. {
  205. m_fVisible = (bVisible != VARIANT_FALSE);
  206. if(!m_fVisible)
  207. {
  208. m_spPanelCollection->SetActivePanel( this, FALSE );
  209. }
  210. // If the theme has changed while the panel was invisible,
  211. // now is a good time to automatically update it
  212. if(m_fVisible && IsContentInvalid())
  213. {
  214. refresh();
  215. }
  216. OnLayoutChange();
  217. }
  218. else
  219. {
  220. hr = S_FALSE;
  221. }
  222. }
  223. return hr;
  224. }
  225. //------------------------------------------------------------------------------
  226. // IMarsPanel::get_startUrl
  227. //
  228. HRESULT CMarsPanel::get_startUrl( BSTR *pVal )
  229. {
  230. HRESULT hr = E_INVALIDARG;
  231. if(API_IsValidWritePtr( pVal ))
  232. {
  233. *pVal = m_bstrStartUrl.Copy();
  234. hr = S_OK;
  235. }
  236. return hr;
  237. }
  238. //------------------------------------------------------------------------------
  239. // IMarsPanel::put_startUrl
  240. //
  241. HRESULT CMarsPanel::put_startUrl( BSTR newVal )
  242. {
  243. HRESULT hr = S_OK;
  244. m_bstrStartUrl = newVal;
  245. return hr;
  246. }
  247. //------------------------------------------------------------------------------
  248. // IMarsPanel::get_height
  249. //
  250. HRESULT CMarsPanel::get_height( long *plHeight )
  251. {
  252. HRESULT hr = E_INVALIDARG;
  253. if(API_IsValidWritePtr( plHeight ))
  254. {
  255. if(VerifyNotPassive( &hr ))
  256. {
  257. hr = S_OK;
  258. if(m_Content.IsWindowVisible())
  259. {
  260. // Use actual position
  261. RECT rc;
  262. m_Content.GetWindowRect( &rc );
  263. *plHeight = rc.bottom - rc.top;
  264. }
  265. else
  266. {
  267. // Panel's hidden. Return requested position.
  268. *plHeight = m_lHeight;
  269. }
  270. }
  271. else
  272. {
  273. *plHeight = 0;
  274. }
  275. }
  276. return hr;
  277. }
  278. //------------------------------------------------------------------------------
  279. // IMarsPanel::put_height
  280. //
  281. HRESULT CMarsPanel::put_height( long lHeight )
  282. {
  283. ATLASSERT(lHeight >= 0);
  284. HRESULT hr = S_OK;
  285. if(VerifyNotPassive( &hr ))
  286. {
  287. if(lHeight >= 0)
  288. {
  289. if(m_lMinHeight >= 0 && lHeight < m_lMinHeight) lHeight = m_lMinHeight;
  290. if(m_lMaxHeight >= 0 && lHeight > m_lMaxHeight) lHeight = m_lMaxHeight;
  291. if(m_lHeight != lHeight)
  292. {
  293. m_lHeight = lHeight;
  294. OnLayoutChange();
  295. }
  296. }
  297. else
  298. {
  299. hr = S_FALSE;
  300. }
  301. }
  302. return hr;
  303. }
  304. //------------------------------------------------------------------------------
  305. // IMarsPanel::get_width
  306. //
  307. HRESULT CMarsPanel::get_width( long *plWidth )
  308. {
  309. HRESULT hr = E_INVALIDARG;
  310. if(API_IsValidWritePtr( plWidth ))
  311. {
  312. if(VerifyNotPassive( &hr ))
  313. {
  314. if(m_Content.IsWindowVisible())
  315. {
  316. // Use actual position
  317. RECT rc;
  318. m_Content.GetWindowRect( &rc );
  319. *plWidth = rc.right - rc.left;
  320. }
  321. else
  322. {
  323. // Panel's hidden. Return requested position.
  324. *plWidth = m_lWidth;
  325. }
  326. hr = S_OK;
  327. }
  328. else
  329. {
  330. *plWidth = 0;
  331. }
  332. }
  333. return hr;
  334. }
  335. //------------------------------------------------------------------------------
  336. // IMarsPanel::put_width
  337. //
  338. HRESULT CMarsPanel::put_width( long lWidth )
  339. {
  340. ATLASSERT(lWidth >= 0);
  341. HRESULT hr = S_OK;
  342. if(VerifyNotPassive( &hr ))
  343. {
  344. if(lWidth >= 0)
  345. {
  346. if(m_lMinWidth >= 0 && lWidth < m_lMinWidth) lWidth = m_lMinWidth;
  347. if(m_lMaxWidth >= 0 && lWidth > m_lMaxWidth) lWidth = m_lMaxWidth;
  348. if(m_lWidth != lWidth)
  349. {
  350. m_lWidth = lWidth;
  351. OnLayoutChange();
  352. }
  353. }
  354. else
  355. {
  356. hr = S_FALSE;
  357. }
  358. }
  359. return hr;
  360. }
  361. //------------------------------------------------------------------------------
  362. // IMarsPanel::get_x
  363. //
  364. HRESULT CMarsPanel::get_x( long *plX )
  365. {
  366. HRESULT hr = E_INVALIDARG;
  367. if(API_IsValidWritePtr( plX ))
  368. {
  369. if(VerifyNotPassive( &hr ))
  370. {
  371. hr = S_OK;
  372. if(m_Content.IsWindowVisible())
  373. {
  374. // Use actual position
  375. RECT rc;
  376. GetMyClientRectInParentCoords( &rc );
  377. *plX = rc.left;
  378. }
  379. else
  380. {
  381. // Panel's hidden. Return requested position.
  382. *plX = m_lX;
  383. }
  384. }
  385. else
  386. {
  387. *plX = 0;
  388. }
  389. }
  390. return hr;
  391. }
  392. //------------------------------------------------------------------------------
  393. // IMarsPanel::put_x
  394. //
  395. HRESULT CMarsPanel::put_x( long lX )
  396. {
  397. HRESULT hr = S_OK;
  398. if(VerifyNotPassive( &hr ))
  399. {
  400. if(m_lX != lX)
  401. {
  402. m_lX = lX;
  403. if(IsPopup())
  404. {
  405. OnLayoutChange();
  406. }
  407. }
  408. }
  409. return hr;
  410. }
  411. //------------------------------------------------------------------------------
  412. // IMarsPanel::get_y
  413. //
  414. HRESULT CMarsPanel::get_y( long *plY )
  415. {
  416. HRESULT hr = E_INVALIDARG;
  417. if(API_IsValidWritePtr( plY ))
  418. {
  419. if(VerifyNotPassive( &hr ))
  420. {
  421. hr = S_OK;
  422. if(m_Content.IsWindowVisible())
  423. {
  424. // Use actual position
  425. RECT rc;
  426. GetMyClientRectInParentCoords( &rc );
  427. *plY = rc.top;
  428. }
  429. else
  430. {
  431. *plY = m_lY;
  432. }
  433. }
  434. else
  435. {
  436. *plY = 0;
  437. }
  438. }
  439. return hr;
  440. }
  441. //------------------------------------------------------------------------------
  442. // IMarsPanel::put_y
  443. //
  444. HRESULT CMarsPanel::put_y( long lY )
  445. {
  446. HRESULT hr = S_OK;
  447. if(VerifyNotPassive( &hr ))
  448. {
  449. if(m_lY != lY)
  450. {
  451. m_lY = lY;
  452. if(IsPopup())
  453. {
  454. OnLayoutChange();
  455. }
  456. }
  457. }
  458. return hr;
  459. }
  460. //------------------------------------------------------------------------------
  461. // IMarsPanel::get_position
  462. //
  463. HRESULT CMarsPanel::get_position( VARIANT *pvarPosition )
  464. {
  465. HRESULT hr = E_INVALIDARG;
  466. if(API_IsValidWritePtr( pvarPosition ))
  467. {
  468. if(VerifyNotPassive( &hr ))
  469. {
  470. VariantClear( pvarPosition );
  471. hr = S_FALSE;
  472. if(m_Position <= c_iPositionMapSize)
  473. {
  474. pvarPosition->bstrVal = SysAllocString( s_PositionMap[m_Position].pwszName );
  475. if(pvarPosition->bstrVal)
  476. {
  477. pvarPosition->vt = VT_BSTR;
  478. hr = S_OK;
  479. }
  480. }
  481. }
  482. }
  483. return hr;
  484. }
  485. //------------------------------------------------------------------------------
  486. // IMarsPanel::put_position
  487. //
  488. HRESULT CMarsPanel::put_position( VARIANT varPosition )
  489. {
  490. HRESULT hr = E_INVALIDARG;
  491. if(API_IsValidVariantBstr( varPosition ))
  492. {
  493. if(VerifyNotPassive( &hr ))
  494. {
  495. hr = SCRIPT_ERROR;
  496. PANEL_POSITION position;
  497. if(SUCCEEDED(StringToPanelPosition( varPosition.bstrVal, &position )))
  498. {
  499. hr = S_OK;
  500. if(m_Position != position)
  501. {
  502. m_Position = s_PositionMap[position].Position;
  503. if(m_Position == PANEL_POPUP)
  504. {
  505. m_Content.SetWindowPos( HWND_TOP, 0, 0, 0, 0, SWP_NOACTIVATE|SWP_NOMOVE|SWP_NOSIZE );
  506. }
  507. OnLayoutChange();
  508. }
  509. }
  510. }
  511. }
  512. return hr;
  513. }
  514. //------------------------------------------------------------------------------
  515. // IMarsPanel::get_autoSize
  516. //
  517. HRESULT CMarsPanel::get_autoSize( VARIANT_BOOL *pbAutoSize )
  518. {
  519. HRESULT hr = E_INVALIDARG;
  520. if(API_IsValidWritePtr( pbAutoSize ))
  521. {
  522. *pbAutoSize = VARIANT_BOOLIFY(IsAutoSizing());
  523. if(VerifyNotPassive( &hr ))
  524. {
  525. hr = S_OK;
  526. }
  527. }
  528. return hr;
  529. }
  530. //------------------------------------------------------------------------------
  531. // IMarsPanel::put_autoSize
  532. //
  533. HRESULT CMarsPanel::put_autoSize( VARIANT_BOOL bAutoSize )
  534. {
  535. HRESULT hr = S_OK;
  536. ATLASSERT(IsValidVariantBoolVal( bAutoSize ));
  537. if(VerifyNotPassive( &hr ))
  538. {
  539. if(bAutoSize)
  540. {
  541. if(!IsAutoSizing())
  542. {
  543. m_dwFlags |= PANEL_FLAG_AUTOSIZE;
  544. OnLayoutChange();
  545. }
  546. }
  547. else
  548. {
  549. if(IsAutoSizing())
  550. {
  551. m_dwFlags &= ~PANEL_FLAG_AUTOSIZE;
  552. OnLayoutChange();
  553. }
  554. }
  555. }
  556. return hr;
  557. }
  558. //------------------------------------------------------------------------------
  559. // IMarsPanel::get_contentInvalid
  560. //
  561. HRESULT CMarsPanel::get_contentInvalid( VARIANT_BOOL *pbInvalid )
  562. {
  563. HRESULT hr = E_INVALIDARG;
  564. if(API_IsValidWritePtr( pbInvalid ))
  565. {
  566. *pbInvalid = VARIANT_BOOLIFY(m_fContentInvalid);
  567. hr = S_OK;
  568. }
  569. return hr;
  570. }
  571. //------------------------------------------------------------------------------
  572. // IMarsPanel::put_contentInvalid
  573. //
  574. HRESULT CMarsPanel::put_contentInvalid( VARIANT_BOOL bInvalid )
  575. {
  576. ATLASSERT(IsValidVariantBoolVal( bInvalid ));
  577. ATLASSERT(!IsPassive());
  578. m_fContentInvalid = BOOLIFY( bInvalid );
  579. return S_OK;
  580. }
  581. //------------------------------------------------------------------------------
  582. // IMarsPanel::get_layoutIndex
  583. //
  584. HRESULT CMarsPanel::get_layoutIndex( long *plIndex )
  585. {
  586. HRESULT hr = E_INVALIDARG;
  587. if(API_IsValidWritePtr( plIndex ))
  588. {
  589. if(VerifyNotPassive( &hr ))
  590. {
  591. hr = m_spPanelCollection->FindPanelIndex( this, plIndex );
  592. }
  593. }
  594. return hr;
  595. }
  596. //------------------------------------------------------------------------------
  597. // IMarsPanel::moveto
  598. //
  599. HRESULT CMarsPanel::moveto( VARIANT vlX, VARIANT vlY, VARIANT vlWidth, VARIANT vlHeight )
  600. {
  601. HRESULT hr = S_OK;
  602. ATLASSERT(vlX.vt == VT_NULL || vlX.vt == VT_I4);
  603. ATLASSERT(vlY.vt == VT_NULL || vlY.vt == VT_I4);
  604. ATLASSERT(vlWidth.vt == VT_NULL || vlWidth.vt == VT_I4);
  605. ATLASSERT(vlHeight.vt == VT_NULL || vlHeight.vt == VT_I4);
  606. if(VerifyNotPassive( &hr ))
  607. {
  608. long lX = VariantToI4( vlX );
  609. long lY = VariantToI4( vlY );
  610. long lWidth = VariantToI4( vlWidth );
  611. long lHeight = VariantToI4( vlHeight );
  612. if(( lX != m_lX ) ||
  613. ( lY != m_lY ) ||
  614. (lWidth >= 0 && lWidth != m_lWidth ) ||
  615. (lHeight >= 0 && lHeight != m_lHeight) )
  616. {
  617. m_lX = lX;
  618. m_lY = lY;
  619. if(lWidth >= 0) m_lWidth = lWidth;
  620. if(lHeight >= 0) m_lHeight = lHeight;
  621. OnLayoutChange();
  622. }
  623. }
  624. return hr;
  625. }
  626. //------------------------------------------------------------------------------
  627. // IMarsPanel::restrictWidth
  628. //
  629. HRESULT CMarsPanel::restrictWidth( VARIANT vlMin, VARIANT vlMax, VARIANT vbstrMarker )
  630. {
  631. HRESULT hr = S_OK;
  632. ATLASSERT(vlMin.vt == VT_EMPTY || vlMin.vt == VT_NULL || vlMin.vt == VT_BSTR || vlMin.vt == VT_I4);
  633. ATLASSERT(vlMax.vt == VT_EMPTY || vlMax.vt == VT_NULL || vlMax.vt == VT_BSTR || vlMin.vt == VT_I4);
  634. ATLASSERT((vbstrMarker.vt==VT_NULL) || (vbstrMarker.vt == VT_EMPTY));
  635. if(VerifyNotPassive( &hr ))
  636. {
  637. m_lMaxWidth = m_lMinWidth = -1;
  638. if(vlMin.vt != VT_NULL &&
  639. vlMin.vt != VT_EMPTY )
  640. {
  641. CComVariant vlMin2; vlMin2.ChangeType( VT_I4, &vlMin );
  642. m_lMinWidth = VariantToI4( vlMin2 );
  643. }
  644. if(vlMax.vt != VT_NULL &&
  645. vlMax.vt != VT_EMPTY )
  646. {
  647. CComVariant vlMax2; vlMax2.ChangeType( VT_I4, &vlMax );
  648. m_lMaxWidth = VariantToI4( vlMax2 );
  649. }
  650. if(m_lMaxWidth >= 0 && m_lMaxWidth < m_lMinWidth)
  651. {
  652. m_lMaxWidth = m_lMinWidth;
  653. }
  654. OnLayoutChange();
  655. }
  656. return hr;
  657. }
  658. //------------------------------------------------------------------------------
  659. // IMarsPanel::restrictHeight
  660. //
  661. HRESULT CMarsPanel::restrictHeight( VARIANT vlMin, VARIANT vlMax, VARIANT vbstrMarker )
  662. {
  663. HRESULT hr = S_OK;
  664. ATLASSERT(vlMin.vt == VT_EMPTY || vlMin.vt == VT_NULL || vlMin.vt == VT_BSTR || vlMin.vt == VT_I4);
  665. ATLASSERT(vlMax.vt == VT_EMPTY || vlMax.vt == VT_NULL || vlMax.vt == VT_BSTR || vlMin.vt == VT_I4);
  666. ATLASSERT((vbstrMarker.vt==VT_NULL) || (vbstrMarker.vt == VT_EMPTY));
  667. if(VerifyNotPassive( &hr ))
  668. {
  669. m_lMaxHeight = m_lMinHeight = -1;
  670. if(vlMin.vt != VT_NULL &&
  671. vlMin.vt != VT_EMPTY )
  672. {
  673. CComVariant vlMin2; vlMin2.ChangeType( VT_I4, &vlMin );
  674. m_lMinHeight = VariantToI4( vlMin2 );
  675. }
  676. if(vlMax.vt != VT_NULL &&
  677. vlMax.vt != VT_EMPTY )
  678. {
  679. CComVariant vlMax2; vlMax2.ChangeType( VT_I4, &vlMax );
  680. m_lMaxHeight = VariantToI4( vlMax2 );
  681. }
  682. if(m_lMaxHeight >= 0 && m_lMaxHeight < m_lMinHeight) m_lMaxHeight = m_lMinHeight;
  683. OnLayoutChange();
  684. }
  685. return hr;
  686. }
  687. //------------------------------------------------------------------------------
  688. // IMarsPanel::canResize
  689. //
  690. HRESULT CMarsPanel::canResize( long lDX, long lDY, VARIANT_BOOL *pVal )
  691. {
  692. long lWidthOld = m_lWidth;
  693. long lHeightOld = m_lHeight;
  694. RECT rcClient;
  695. m_lWidth += lDX;
  696. m_lHeight += lDY;
  697. (void)m_spMarsDocument->Window()->GetClientRect( &rcClient );
  698. if(m_spMarsDocument->MarsWindow()->CanLayout( rcClient ))
  699. {
  700. if(pVal) *pVal = VARIANT_TRUE;
  701. }
  702. else
  703. {
  704. if(pVal) *pVal = VARIANT_FALSE;
  705. }
  706. m_lWidth = lWidthOld;
  707. m_lHeight = lHeightOld;
  708. return S_OK;
  709. }
  710. //------------------------------------------------------------------------------
  711. // IMarsPanel::activate
  712. //
  713. HRESULT CMarsPanel::activate()
  714. {
  715. m_Content.SendMessage(WM_SETFOCUS, 0, 0);
  716. return S_OK;
  717. }
  718. //------------------------------------------------------------------------------
  719. // IMarsPanel::insertBefore
  720. //
  721. HRESULT CMarsPanel::insertBefore(VARIANT varInsertBefore)
  722. {
  723. ATLASSERT(varInsertBefore.vt == VT_I4 || // index to insert before
  724. varInsertBefore.vt == VT_BSTR || // panel name to insert before
  725. varInsertBefore.vt == VT_DISPATCH); // panel object to insert before
  726. HRESULT hr = E_INVALIDARG;
  727. if (API_IsValidVariant(varInsertBefore))
  728. {
  729. if (VerifyNotPassive(&hr))
  730. {
  731. hr = E_FAIL;
  732. long lIndex = -668;
  733. switch(varInsertBefore.vt)
  734. {
  735. case VT_I4:
  736. lIndex = varInsertBefore.lVal;
  737. hr = S_OK;
  738. break;
  739. case VT_DISPATCH:
  740. {
  741. CComClassPtr<CMarsPanel> spPanel;
  742. varInsertBefore.pdispVal->QueryInterface(CLASS_CMarsPanel, (void **)&spPanel);
  743. if (spPanel)
  744. {
  745. hr = m_spPanelCollection->FindPanelIndex(spPanel, &lIndex);
  746. }
  747. break;
  748. }
  749. case VT_BSTR:
  750. hr = m_spPanelCollection->FindPanelIndex(
  751. m_spPanelCollection->FindPanel(varInsertBefore.bstrVal),
  752. &lIndex);
  753. break;
  754. default:
  755. ATLASSERT(0);
  756. }
  757. if (SUCCEEDED(hr))
  758. {
  759. // Successfully got an index to insert before
  760. ATLASSERT(lIndex != -668);
  761. // Get our current index
  762. long lCurrentIndex;
  763. if (SUCCEEDED(m_spPanelCollection->FindPanelIndex(this, &lCurrentIndex)))
  764. {
  765. ATLASSERT(lCurrentIndex != -1);
  766. if (lIndex != lCurrentIndex)
  767. {
  768. m_spPanelCollection->InsertPanelFromTo(lCurrentIndex, lIndex);
  769. OnLayoutChange();
  770. }
  771. }
  772. else
  773. {
  774. ATLASSERT(!"FindPanelIndex failed!");
  775. }
  776. }
  777. }
  778. }
  779. return hr;
  780. }
  781. //------------------------------------------------------------------------------
  782. // IMarsPanel::execMshtml
  783. //
  784. // execMshtml allows script to send a command directly to Trident. This is different from
  785. // IWebBrowser2::ExecWB because ExecWB passes a NULL command group, which prevents Trident
  786. // from responding to commands like IDM_FIND. Usually, we could accomplish this by calling
  787. // the OM method execCommand, but Trident doesn't respond to execCommand("Find")
  788. //
  789. HRESULT CMarsPanel::execMshtml(DWORD nCmdID, DWORD nCmdExecOpt,
  790. VARIANTARG *pvaIn, VARIANTARG *pvaOut)
  791. {
  792. HRESULT hr = E_INVALIDARG;
  793. if (VerifyNotPassive(&hr))
  794. {
  795. CComPtr<IOleCommandTarget> spCmdTarget;
  796. hr = m_Content.QueryControl(IID_IOleCommandTarget, (void **) &spCmdTarget);
  797. if (SUCCEEDED(hr))
  798. {
  799. hr = spCmdTarget->Exec(&CGID_MSHTML, nCmdID, nCmdExecOpt, pvaIn, pvaOut);
  800. }
  801. hr = S_OK;
  802. }
  803. return hr;
  804. }
  805. //------------------------------------------------------------------------------
  806. // IMarsPanel::get_isCurrentlyVisible
  807. //
  808. HRESULT CMarsPanel::get_isCurrentlyVisible(VARIANT_BOOL *pbIsVisible)
  809. {
  810. HRESULT hr = E_INVALIDARG;
  811. if (API_IsValidWritePtr(pbIsVisible))
  812. {
  813. if (VerifyNotPassive(&hr))
  814. {
  815. *pbIsVisible = VARIANT_BOOLIFY(m_Content.IsWindowVisible());
  816. hr = S_OK;
  817. }
  818. }
  819. return hr;
  820. }
  821. //------------------------------------------------------------------------------
  822. // IServiceProvider::QueryService
  823. //
  824. // First, we try to handle guidService, then we go to IProfferServiceImpl,
  825. // then we go to the parent window.
  826. //
  827. HRESULT CMarsPanel::QueryService(REFGUID guidService, REFIID riid, void **ppv)
  828. {
  829. HRESULT hr = E_FAIL;
  830. *ppv = NULL;
  831. if (!IsPassive())
  832. {
  833. if (guidService == IID_IInternetProtocol)
  834. {
  835. // Yeah, we don't support this service. Stop asking us for it!
  836. }
  837. else if ((guidService == SID_SHlinkFrame) ||
  838. (guidService == SID_SProfferService) ||
  839. (guidService == SID_SMarsPanel))
  840. {
  841. hr = QueryInterface(riid, ppv);
  842. }
  843. else if (guidService == SID_SInternetSecurityManager)
  844. {
  845. if (IsTrusted())
  846. {
  847. hr = QueryInterface(riid, ppv);
  848. }
  849. }
  850. if (FAILED(hr))
  851. {
  852. hr = IProfferServiceImpl::QueryService(guidService, riid, ppv);
  853. }
  854. }
  855. if (FAILED(hr))
  856. {
  857. hr = m_spMarsDocument->MarsWindow()->QueryService(guidService, riid, ppv);
  858. }
  859. return hr;
  860. }
  861. //------------------------------------------------------------------------------
  862. // IHlinkFrame::Navigate
  863. //
  864. HRESULT CMarsPanel::Navigate(DWORD grfHLNF, LPBC pbc,
  865. IBindStatusCallback *pibsc, IHlink *pihlNavigate)
  866. {
  867. // BUGBUG: Call ReleasedOwnedObjects for this panel
  868. HRESULT hr = E_FAIL;
  869. CComPtr<IMoniker> spMk;
  870. if (VerifyNotPassive())
  871. {
  872. pihlNavigate->GetMonikerReference(grfHLNF, &spMk, NULL);
  873. if (spMk)
  874. {
  875. hr = NavigateMk(spMk);
  876. }
  877. }
  878. return hr;
  879. }
  880. //------------------------------------------------------------------------------
  881. HRESULT CMarsPanel::Create( MarsAppDef_Panel* pLayout)
  882. {
  883. ATLASSERT(!IsPassive());
  884. m_bstrName = pLayout->szName;
  885. m_Position = pLayout->Position;
  886. m_lWidth = pLayout->lWidth;
  887. m_lHeight = pLayout->lHeight;
  888. m_lX = pLayout->lX;
  889. m_lY = pLayout->lY;
  890. m_dwFlags = pLayout->dwFlags;
  891. m_lMinWidth = pLayout->lWidthMin;
  892. m_lMinHeight = pLayout->lHeightMin;
  893. m_lMaxWidth = pLayout->lWidthMax;
  894. m_lMaxHeight = pLayout->lHeightMax;
  895. m_fVisible = BOOLIFY(m_dwFlags & PANEL_FLAG_VISIBLE);
  896. m_dwCookie = 0;
  897. if(!IsAutoSizing())
  898. {
  899. switch(m_Position)
  900. {
  901. case PANEL_BOTTOM:
  902. case PANEL_TOP:
  903. if(m_lMinHeight < 0 && m_lMaxHeight < 0)
  904. {
  905. m_lMinHeight = m_lHeight;
  906. m_lMaxHeight = m_lHeight;
  907. }
  908. break;
  909. case PANEL_LEFT:
  910. case PANEL_RIGHT:
  911. if(m_lMinWidth < 0 && m_lMaxWidth < 0)
  912. {
  913. m_lMinWidth = m_lWidth;
  914. m_lMaxWidth = m_lWidth;
  915. }
  916. break;
  917. }
  918. }
  919. {
  920. DWORD dwStyle = WS_CHILD | WS_CLIPSIBLINGS;
  921. RECT rcCreate = { 0, 0, 0, 0 };
  922. m_Content.Create( m_spMarsDocument->Window()->m_hWnd, &rcCreate, _T(""), dwStyle, 0 );
  923. }
  924. {
  925. CComPtr<IObjectWithSite> spObj;
  926. m_Content.QueryHost(IID_IObjectWithSite, (void **)&spObj);
  927. if (spObj)
  928. {
  929. spObj->SetSite(SAFECAST(this, IMarsPanel *)); // To connect our QueryService
  930. }
  931. }
  932. m_spMarsDocument->MarsWindow()->NotifyHost(MARSHOST_ON_PANEL_INIT, SAFECAST(this, IMarsPanel *), 0);
  933. if(pLayout->szUrl[0])
  934. {
  935. m_bstrStartUrl = pLayout->szUrl;
  936. }
  937. if(!(m_dwFlags & PANEL_FLAG_ONDEMAND))
  938. {
  939. CreateControl();
  940. }
  941. if(m_dwFlags & PANEL_FLAG_VISIBLE)
  942. {
  943. OnLayoutChange();
  944. }
  945. return S_OK;
  946. }
  947. //------------------------------------------------------------------------------
  948. DELAY_LOAD_NAME_HRESULT(g_hinstBorg, mshtml, BorgDllGetClassObject, DllGetClassObject,
  949. (REFCLSID rclsid, REFIID riid, LPVOID* ppv),
  950. (rclsid, riid, ppv));
  951. HRESULT CMarsPanel::CreateControlObject()
  952. {
  953. ATLASSERT(!m_fControlCreated);
  954. CComPtr<IAxWinHostWindow> spHost;
  955. HRESULT hr = m_Content.QueryHost(&spHost);
  956. if (SUCCEEDED(hr))
  957. {
  958. if(IsWebBrowser())
  959. {
  960. hr = spHost->CreateControl(wszCLSID_WebBrowser, m_Content, 0);
  961. }
  962. else if(IsCustomControl())
  963. {
  964. hr = spHost->CreateControl(m_bstrStartUrl, m_Content, 0);
  965. }
  966. else
  967. {
  968. if (IsTrusted())
  969. {
  970. CComPtr<IClassFactory> spCf;
  971. hr = BorgDllGetClassObject(CLSID_HTADoc, IID_IClassFactory, (void **)&spCf);
  972. if (SUCCEEDED(hr))
  973. {
  974. CComPtr<IUnknown> spUnk;
  975. hr = spCf->CreateInstance(NULL, IID_IUnknown, (void **)&spUnk);
  976. if (SUCCEEDED(hr))
  977. {
  978. hr = spHost->AttachControl(spUnk, m_Content);
  979. }
  980. }
  981. }
  982. else
  983. {
  984. hr = spHost->CreateControl(wszCLSID_HTMLDocument, m_Content, 0);
  985. }
  986. }
  987. }
  988. return hr;
  989. }
  990. //------------------------------------------------------------------------------
  991. // Internal function called when panel is first made visible
  992. HRESULT CMarsPanel::CreateControl()
  993. {
  994. HRESULT hr = S_FALSE;
  995. if(!m_fControlCreated)
  996. {
  997. // Create WebBrowser or Trident and navigate to default url
  998. if (SUCCEEDED(CreateControlObject()))
  999. {
  1000. m_fControlCreated = TRUE;
  1001. if(IsWebBrowser())
  1002. {
  1003. CComPtr<IUnknown> spUnk;
  1004. if (SUCCEEDED(m_Content.QueryControl(IID_IUnknown, (void **)&spUnk)))
  1005. {
  1006. m_BrowserEvents.Connect(spUnk, TRUE);
  1007. // get the browserservice that we will intercept to update the travel log
  1008. // only if this is a WebBrowser and not a Popup
  1009. if (!m_spBrowserService)
  1010. {
  1011. HRESULT hrQS = IUnknown_QueryService(spUnk, SID_STopFrameBrowser,
  1012. IID_IBrowserService,
  1013. (void **)&m_spBrowserService);
  1014. if (FAILED(hrQS))
  1015. {
  1016. ATLASSERT(!m_spBrowserService);
  1017. }
  1018. }
  1019. CComPtr<IOleCommandTarget> spCommandTarget;
  1020. if (SUCCEEDED(IUnknown_QueryService(spUnk, SID_STopFrameBrowser, IID_IOleCommandTarget, (void **)&spCommandTarget)))
  1021. {
  1022. VARIANT var;
  1023. var.vt = VT_BOOL;
  1024. var.boolVal = TRUE;
  1025. spCommandTarget->Exec(&CGID_InternetExplorer,
  1026. IECMDID_SET_INVOKE_DEFAULT_BROWSER_ON_NEW_WINDOW,
  1027. 0,
  1028. &var,
  1029. NULL);
  1030. }
  1031. }
  1032. }
  1033. else if(IsCustomControl())
  1034. {
  1035. }
  1036. else
  1037. {
  1038. ConnectCompletionAdviser();
  1039. }
  1040. if(IsTrusted())
  1041. {
  1042. m_Content.SetExternalDispatch(&m_MarsExternal);
  1043. }
  1044. if (m_bstrStartUrl)
  1045. {
  1046. ATLASSERT(m_bstrStartUrl[0]);
  1047. NavigateURL(m_bstrStartUrl, FALSE);
  1048. m_bstrStartUrl.Empty();
  1049. }
  1050. m_spMarsDocument->MarsWindow()->NotifyHost(MARSHOST_ON_PANEL_CONTROL_CREATE, SAFECAST(this, IMarsPanel *), 0);
  1051. hr = S_OK;
  1052. }
  1053. else
  1054. {
  1055. hr = E_FAIL;
  1056. }
  1057. }
  1058. return hr;
  1059. }
  1060. //------------------------------------------------------------------------------
  1061. // This returns void because it calls a script method that might return
  1062. // S_FALSE with no URL, so we should force callers to check the BSTR
  1063. //
  1064. // rbstrUrl = document.location.href
  1065. //
  1066. void CMarsPanel::GetUrl(CComBSTR& rbstrUrl)
  1067. {
  1068. CComPtr<IHTMLDocument2> spDoc2;
  1069. GetDoc2FromAxWindow(&m_Content, &spDoc2);
  1070. if (spDoc2)
  1071. {
  1072. CComPtr<IHTMLLocation> spLoc;
  1073. spDoc2->get_location(&spLoc);
  1074. if (spLoc)
  1075. {
  1076. spLoc->get_href(&rbstrUrl);
  1077. }
  1078. }
  1079. }
  1080. //------------------------------------------------------------------------------
  1081. HRESULT CMarsPanel::NavigateMk(IMoniker *pmk)
  1082. {
  1083. HRESULT hr = E_FAIL;
  1084. if (VerifyNotPassive())
  1085. {
  1086. CComPtr<IPersistMoniker> spPersistMk;
  1087. if (SUCCEEDED(m_Content.QueryControl(IID_IPersistMoniker, (void **)&spPersistMk)))
  1088. {
  1089. m_spMarsDocument->MarsWindow()->ReleaseOwnedObjects((IDispatch *)this);
  1090. hr = spPersistMk->Load(FALSE, pmk, NULL, 0);
  1091. }
  1092. else
  1093. {
  1094. // NavigateMk: QueryControl failed -- the most likely reason for this is that
  1095. // you don't have CLSID_HTADocument registered -- upgrade your IE bits
  1096. ATLASSERT(FALSE);
  1097. // Don't just hang the UI
  1098. m_lReadyState = READYSTATE_COMPLETE;
  1099. }
  1100. }
  1101. return hr;
  1102. }
  1103. //------------------------------------------------------------------------------
  1104. HRESULT CMarsPanel::NavigateURL(LPCWSTR lpszURL, BOOL fForceLoad)
  1105. {
  1106. HRESULT hr = E_FAIL;
  1107. if (VerifyNotPassive())
  1108. {
  1109. CreateControl();
  1110. BOOL fIgnoreNavigate = FALSE;
  1111. #ifdef BLOCK_PANEL_RENAVIGATES
  1112. if (!fForceLoad && IsTrusted() && !IsContentInvalid())
  1113. {
  1114. CComBSTR sbstrCurrentUrl;
  1115. GetUrl(sbstrCurrentUrl);
  1116. if (sbstrCurrentUrl && (0 == StrCmpIW(sbstrCurrentUrl, lpszURL)))
  1117. {
  1118. fIgnoreNavigate = TRUE;
  1119. hr = S_FALSE;
  1120. }
  1121. }
  1122. #endif
  1123. if(!fIgnoreNavigate)
  1124. {
  1125. if(IsWebBrowser())
  1126. {
  1127. CComPtr<IWebBrowser2> spWebBrowser2;
  1128. if (SUCCEEDED(m_Content.QueryControl(IID_IWebBrowser2, (void **)&spWebBrowser2)))
  1129. {
  1130. CComVariant varEmpty;
  1131. CComVariant varURL(lpszURL);
  1132. m_spMarsDocument->MarsWindow()->ReleaseOwnedObjects((IDispatch *)this);
  1133. hr = spWebBrowser2->Navigate2(&varURL, &varEmpty, &varEmpty, &varEmpty, &varEmpty);
  1134. }
  1135. }
  1136. else if(IsCustomControl())
  1137. {
  1138. }
  1139. else
  1140. {
  1141. CComPtr<IMoniker> spMkUrl;
  1142. if (SUCCEEDED(CreateURLMoniker(NULL, lpszURL, &spMkUrl)) && spMkUrl)
  1143. {
  1144. hr = NavigateMk(spMkUrl);
  1145. }
  1146. }
  1147. }
  1148. if (SUCCEEDED(hr))
  1149. {
  1150. m_fContentInvalid = FALSE;
  1151. }
  1152. }
  1153. return hr;
  1154. }
  1155. //------------------------------------------------------------------------------
  1156. // IMarsPanel::navigate
  1157. //
  1158. HRESULT CMarsPanel::navigate(VARIANT varTarget, VARIANT varForceLoad)
  1159. {
  1160. HRESULT hr = S_FALSE;
  1161. if (API_IsValidVariant(varTarget) && VerifyNotPassive(&hr))
  1162. {
  1163. CComBSTR strPath;
  1164. if (SUCCEEDED(MarsVariantToPath(varTarget, strPath)))
  1165. {
  1166. if (!PathIsURLW(strPath) && PathIsURLFileW(strPath))
  1167. {
  1168. // handle navigate to .url shortcut
  1169. CComPtr<IDispatch> spDisp;
  1170. CreateControl();
  1171. if (SUCCEEDED(m_Content.QueryControl(&spDisp)))
  1172. {
  1173. if (SUCCEEDED(MarsNavigateShortcut(spDisp, strPath)))
  1174. {
  1175. m_spMarsDocument->MarsWindow()->ReleaseOwnedObjects((IDispatch *)this);
  1176. hr = S_OK;
  1177. }
  1178. }
  1179. }
  1180. else
  1181. {
  1182. // handle navigate to URL
  1183. BOOL fForceLoad;
  1184. if (varForceLoad.vt == VT_BOOL)
  1185. {
  1186. // the optional param was specified
  1187. fForceLoad = varForceLoad.boolVal;
  1188. }
  1189. else
  1190. {
  1191. fForceLoad = FALSE;
  1192. }
  1193. if (SUCCEEDED(NavigateURL(strPath, fForceLoad)))
  1194. {
  1195. hr = S_OK;
  1196. }
  1197. }
  1198. }
  1199. }
  1200. return hr;
  1201. }
  1202. //------------------------------------------------------------------------------
  1203. // IMarsPanel::refresh
  1204. //
  1205. HRESULT CMarsPanel::refresh(void)
  1206. {
  1207. m_fInRefresh = TRUE;
  1208. execMshtml(IDM_REFRESH, OLECMDEXECOPT_DODEFAULT, NULL, NULL);
  1209. m_fInRefresh = FALSE;
  1210. m_fContentInvalid = FALSE;
  1211. return S_OK;
  1212. }
  1213. //------------------------------------------------------------------------------
  1214. void CMarsPanel::OnLayoutChange()
  1215. {
  1216. ATLASSERT(!IsPassive());
  1217. if (!m_fVisible && !m_Content.IsWindowVisible())
  1218. {
  1219. // We're not even visible. Nothing to do.
  1220. return;
  1221. }
  1222. // Create content if it's not already created
  1223. CreateControl();
  1224. // Redraw entire Mars window
  1225. m_spPanelCollection->Layout();
  1226. }
  1227. //------------------------------------------------------------------------------
  1228. void CMarsPanel::MakeVisible(VARIANT_BOOL bVisible, VARIANT_BOOL bForce)
  1229. {
  1230. ATLASSERT(!IsPassive());
  1231. BOOL fVisible = m_Content.IsWindowVisible();
  1232. if (bForce || (!!fVisible != !!bVisible))
  1233. {
  1234. m_Content.ShowWindow((bVisible) ? SW_SHOW : SW_HIDE);
  1235. }
  1236. }
  1237. //------------------------------------------------------------------------------
  1238. void CMarsPanel::OnWindowPosChanging(WINDOWPOS *pWindowPos)
  1239. {
  1240. if (!IsPassive() && !m_spPanelCollection->IsLayoutLocked())
  1241. {
  1242. if (pWindowPos->x < 0)
  1243. {
  1244. pWindowPos->x = 0;
  1245. }
  1246. if (pWindowPos->y < 0)
  1247. {
  1248. pWindowPos->y = 0;
  1249. }
  1250. }
  1251. }
  1252. //------------------------------------------------------------------------------
  1253. inline void DimChange(long& lMember, int iVal, BOOL& bChanged)
  1254. {
  1255. if (lMember != iVal)
  1256. {
  1257. lMember = iVal;
  1258. bChanged = TRUE;
  1259. }
  1260. }
  1261. //------------------------------------------------------------------------------
  1262. void CMarsPanel::OnWindowPosChanged(WINDOWPOS *pWindowPos)
  1263. {
  1264. if(!IsPassive() && !m_spPanelCollection->IsLayoutLocked())
  1265. {
  1266. BOOL bChanged = FALSE;
  1267. switch(m_Position)
  1268. {
  1269. case PANEL_POPUP:
  1270. if(!(pWindowPos->flags & SWP_NOMOVE)) DimChange(m_lX , pWindowPos->x , bChanged);
  1271. if(!(pWindowPos->flags & SWP_NOMOVE)) DimChange(m_lY , pWindowPos->y , bChanged);
  1272. if(!(pWindowPos->flags & SWP_NOSIZE)) DimChange(m_lWidth , pWindowPos->cx, bChanged);
  1273. if(!(pWindowPos->flags & SWP_NOSIZE)) DimChange(m_lHeight, pWindowPos->cy, bChanged);
  1274. break;
  1275. case PANEL_BOTTOM:
  1276. case PANEL_TOP:
  1277. if(!(pWindowPos->flags & SWP_NOSIZE)) DimChange(m_lHeight, pWindowPos->cy, bChanged);
  1278. break;
  1279. case PANEL_LEFT:
  1280. case PANEL_RIGHT:
  1281. if(!(pWindowPos->flags & SWP_NOSIZE)) DimChange(m_lWidth, pWindowPos->cx, bChanged);
  1282. break;
  1283. }
  1284. if(bChanged)
  1285. {
  1286. OnLayoutChange();
  1287. }
  1288. }
  1289. }
  1290. //------------------------------------------------------------------------------
  1291. void CMarsPanel::GetMinMaxInfo( POINT& ptMin, POINT& ptMax )
  1292. {
  1293. long lWidth = m_lWidth;
  1294. long lHeight = m_lHeight;
  1295. long lMinWidth;
  1296. long lMinHeight;
  1297. long lMaxWidth;
  1298. long lMaxHeight;
  1299. if(!IsAutoSizing())
  1300. {
  1301. lMinWidth = m_lMinWidth;
  1302. lMinHeight = m_lMinHeight;
  1303. lMaxWidth = m_lMaxWidth;
  1304. lMaxHeight = m_lMaxHeight;
  1305. }
  1306. else
  1307. {
  1308. ComputeDimensionsOfContent( &lMinWidth, &lMinHeight );
  1309. if(m_lMinWidth != -1 && lMinWidth < m_lMinWidth ) lMinWidth = m_lMinWidth;
  1310. if(m_lMinHeight != -1 && lMinHeight < m_lMinHeight) lMinHeight = m_lMinHeight;
  1311. lMaxWidth = m_lMaxWidth;
  1312. lMaxHeight = m_lMaxHeight;
  1313. if(lMinWidth > lWidth ) lWidth = lMinWidth;
  1314. if(lMinHeight > lHeight) lHeight = lMinHeight;
  1315. }
  1316. switch(m_Position)
  1317. {
  1318. case PANEL_BOTTOM:
  1319. case PANEL_TOP :
  1320. if(lMinHeight < 0) lMinHeight = lHeight;
  1321. if(lMaxHeight < 0) lMaxHeight = lHeight;
  1322. break;
  1323. case PANEL_LEFT :
  1324. case PANEL_RIGHT:
  1325. if(lMinWidth < 0) lMinWidth = lWidth;
  1326. if(lMaxWidth < 0) lMaxWidth = lWidth;
  1327. break;
  1328. }
  1329. ptMin.x = lMinWidth;
  1330. ptMin.y = lMinHeight;
  1331. ptMax.x = lMaxWidth;
  1332. ptMax.y = lMaxHeight;
  1333. }
  1334. bool CMarsPanel::CanLayout( RECT& rcClient, POINT& ptDiff )
  1335. {
  1336. ptDiff.x = 0;
  1337. ptDiff.y = 0;
  1338. if(IsVisible())
  1339. {
  1340. RECT rcClient2;
  1341. POINT ptMin;
  1342. POINT ptMax;
  1343. long lWidth;
  1344. long lHeight;
  1345. GetRect ( &rcClient, &rcClient2 );
  1346. GetMinMaxInfo( ptMin , ptMax );
  1347. lWidth = rcClient2.right - rcClient2.left;
  1348. lHeight = rcClient2.bottom - rcClient2.top;
  1349. if(ptMin.x >= 0 && lWidth < ptMin.x) ptDiff.x -= (lWidth - ptMin.x);
  1350. if(ptMax.x >= 0 && lWidth > ptMax.x) ptDiff.x -= (lWidth - ptMax.x);
  1351. if(ptMin.y >= 0 && lHeight < ptMin.y) ptDiff.y -= (lHeight - ptMin.y);
  1352. if(ptMax.y >= 0 && lHeight > ptMax.y) ptDiff.y -= (lHeight - ptMax.y);
  1353. }
  1354. return ptDiff.x == 0 && ptDiff.y == 0;
  1355. }
  1356. //------------------------------------------------------------------------------
  1357. // S_FALSE : We used up all remaining client area
  1358. // E_INVALIDARG : *prcClient was empty, so we are hidden
  1359. HRESULT CMarsPanel::Layout( RECT *prcClient )
  1360. {
  1361. ATLASSERT(prcClient);
  1362. ATLASSERT(!IsPassive());
  1363. RECT rcMyClient;
  1364. HRESULT hr = S_OK;
  1365. if (m_fVisible && !IsRectEmpty(prcClient))
  1366. {
  1367. hr = GetRect(prcClient, &rcMyClient);
  1368. // Optimize out the case that the rect is the same as we already have. This
  1369. // is pretty common, and Windows doesn't optimize it out.
  1370. RECT rcCurrent;
  1371. GetMyClientRectInParentCoords(&rcCurrent);
  1372. if(memcmp( &rcCurrent, &rcMyClient, sizeof(RECT) ))
  1373. {
  1374. m_Content.MoveWindow( &rcMyClient, TRUE );
  1375. }
  1376. if (IsPopup())
  1377. {
  1378. // Bring popup windows to top
  1379. m_Content.SetWindowPos(HWND_TOP, 0, 0, 0, 0, SWP_NOACTIVATE|SWP_NOMOVE|SWP_NOSIZE);
  1380. }
  1381. MakeVisible(VARIANT_TRUE, VARIANT_FALSE);
  1382. }
  1383. else
  1384. {
  1385. if (m_fVisible)
  1386. {
  1387. // We wanted to be visible but had no remaining client area
  1388. hr = E_INVALIDARG;
  1389. }
  1390. MakeVisible(VARIANT_FALSE, VARIANT_FALSE);
  1391. }
  1392. return hr;
  1393. }
  1394. //------------------------------------------------------------------------------
  1395. // IPropertyNotifySink::OnChanged
  1396. //
  1397. STDMETHODIMP CMarsPanel::OnChanged(DISPID dispID)
  1398. {
  1399. if (DISPID_READYSTATE == dispID)
  1400. {
  1401. VARIANT vResult = {0};
  1402. EXCEPINFO excepInfo;
  1403. UINT uArgErr;
  1404. DISPPARAMS dp = {NULL, NULL, 0, 0};
  1405. CComPtr<IHTMLDocument2> spDocument;
  1406. if (SUCCEEDED(m_Content.QueryControl(IID_IHTMLDocument2, (void **)&spDocument))
  1407. && SUCCEEDED(spDocument->Invoke(DISPID_READYSTATE, IID_NULL, LOCALE_SYSTEM_DEFAULT,
  1408. DISPATCH_PROPERTYGET, &dp, &vResult, &excepInfo,
  1409. &uArgErr)))
  1410. {
  1411. m_lReadyState = (READYSTATE)V_I4(&vResult);
  1412. switch (m_lReadyState)
  1413. {
  1414. case READYSTATE_UNINITIALIZED: //= 0,
  1415. break;
  1416. case READYSTATE_LOADING: //= 1,
  1417. break;
  1418. case READYSTATE_LOADED: //= 2,
  1419. break;
  1420. case READYSTATE_INTERACTIVE: //= 3,
  1421. break;
  1422. case READYSTATE_COMPLETE: //= 4
  1423. if (IsAutoSizing())
  1424. {
  1425. OnLayoutChange();
  1426. }
  1427. m_spMarsDocument->GetPlaces()->OnPanelReady();
  1428. break;
  1429. }
  1430. }
  1431. }
  1432. return NOERROR;
  1433. }
  1434. //------------------------------------------------------------------------------
  1435. void CMarsPanel::ConnectCompletionAdviser()
  1436. {
  1437. if (!m_dwCookie)
  1438. {
  1439. CComPtr<IConnectionPointContainer> spICPC;
  1440. if (SUCCEEDED(m_Content.QueryControl(IID_IConnectionPointContainer, (void **)&spICPC)))
  1441. {
  1442. CComPtr<IConnectionPoint> spCP;
  1443. if (spICPC && SUCCEEDED(spICPC->FindConnectionPoint(IID_IPropertyNotifySink, &spCP)))
  1444. {
  1445. spCP->Advise((LPUNKNOWN)(IPropertyNotifySink*)this, &m_dwCookie);
  1446. ATLASSERT(m_dwCookie);
  1447. }
  1448. }
  1449. }
  1450. }
  1451. //------------------------------------------------------------------------------
  1452. void CMarsPanel::DisconnectCompletionAdviser()
  1453. {
  1454. if (m_dwCookie)
  1455. {
  1456. CComPtr<IConnectionPointContainer> spICPC;
  1457. if (SUCCEEDED(m_Content.QueryControl(IID_IConnectionPointContainer, (void **)&spICPC)))
  1458. {
  1459. CComPtr<IConnectionPoint> spCP;
  1460. if (spICPC && SUCCEEDED(spICPC->FindConnectionPoint(IID_IPropertyNotifySink, &spCP)))
  1461. {
  1462. spCP->Unadvise(m_dwCookie);
  1463. m_dwCookie = 0;
  1464. }
  1465. }
  1466. }
  1467. }
  1468. //------------------------------------------------------------------------------
  1469. // Given some content, we're going to compute its dimensions and use those.
  1470. //
  1471. void CMarsPanel::ComputeDimensionsOfContent(long *plWidth, long *plHeight)
  1472. {
  1473. ATLASSERT(plWidth && plHeight);
  1474. ATLASSERT(!IsPassive());
  1475. *plWidth = -1;
  1476. *plHeight = -1;
  1477. if(!IsWebBrowser() && IsAutoSizing())
  1478. {
  1479. CComPtr<IHTMLDocument2> spDocument;
  1480. if(SUCCEEDED(m_Content.QueryControl(IID_IHTMLDocument2, (void **)&spDocument)))
  1481. {
  1482. CComPtr<IHTMLElement> spBody;
  1483. if(spDocument)
  1484. {
  1485. spDocument->get_body( &spBody );
  1486. }
  1487. BOOL fScrollBar = FALSE;
  1488. BOOL fHeight = (m_Position == PANEL_BOTTOM) ||
  1489. (m_Position == PANEL_TOP ) ||
  1490. (m_Position == PANEL_POPUP );
  1491. BOOL fWidth = (m_Position == PANEL_LEFT ) ||
  1492. (m_Position == PANEL_RIGHT) ||
  1493. (m_Position == PANEL_POPUP);
  1494. CComQIPtr<IHTMLElement2> spBody2(spBody);
  1495. if(spBody2 && fHeight)
  1496. {
  1497. LONG lScrollHeight = 0; spBody2->get_scrollHeight( &lScrollHeight );
  1498. if(m_lMaxHeight >= 0 && lScrollHeight > m_lMaxHeight)
  1499. {
  1500. *plHeight = m_lMaxHeight;
  1501. fScrollBar = TRUE;
  1502. }
  1503. else
  1504. {
  1505. *plHeight = lScrollHeight;
  1506. }
  1507. }
  1508. if(spBody2 && fWidth)
  1509. {
  1510. LONG lScrollWidth = 0; spBody2->get_scrollWidth( &lScrollWidth );
  1511. if(m_lMaxWidth >= 0 && lScrollWidth > m_lMaxWidth)
  1512. {
  1513. *plWidth = m_lMaxWidth;
  1514. fScrollBar = TRUE;
  1515. }
  1516. else
  1517. {
  1518. *plWidth = lScrollWidth;
  1519. }
  1520. }
  1521. CComQIPtr<IHTMLBodyElement> spBody3(spBody);
  1522. if(spBody3)
  1523. {
  1524. spBody3->put_scroll( CComBSTR( fScrollBar ? L"yes" : L"no" ) );
  1525. }
  1526. }
  1527. }
  1528. }
  1529. //------------------------------------------------------------------------------
  1530. // Given the remaining client rect that we are allowed to use, calculate our
  1531. // own position in client coordinates, and return the remaining empty client
  1532. // rectangle
  1533. //
  1534. // S_OK : Remaining client area
  1535. // S_FALSE : No client area remaining
  1536. HRESULT CMarsPanel::GetRect(RECT *prcClient, RECT *prcMyClient)
  1537. {
  1538. ATLASSERT(!IsPassive());
  1539. HRESULT hr = S_OK;
  1540. if (!m_fVisible)
  1541. {
  1542. memset(prcMyClient, 0, sizeof(*prcMyClient));
  1543. return S_OK;
  1544. }
  1545. *prcMyClient = *prcClient;
  1546. long lWidth = m_lWidth;
  1547. long lHeight = m_lHeight;
  1548. if (IsAutoSizing())
  1549. {
  1550. long lMinWidth;
  1551. long lMinHeight;
  1552. ComputeDimensionsOfContent(&lMinWidth, &lMinHeight);
  1553. if(lMinWidth > lWidth ) lWidth = lMinWidth;
  1554. if(lMinHeight > lHeight) lHeight = lMinHeight;
  1555. }
  1556. if(m_lMinWidth >= 0 && lWidth < m_lMinWidth ) lWidth = m_lMinWidth;
  1557. if(m_lMinHeight >= 0 && lHeight < m_lMinHeight) lHeight = m_lMinHeight;
  1558. switch (m_Position)
  1559. {
  1560. case PANEL_POPUP:
  1561. // Special case: we exist on top of the other panels.
  1562. if (m_lX < 0)
  1563. {
  1564. prcMyClient->right = prcClient->right + 1 + m_lX;
  1565. prcMyClient->left = prcMyClient->right - lWidth;
  1566. }
  1567. else
  1568. {
  1569. prcMyClient->left = prcClient->left + m_lX;
  1570. prcMyClient->right = prcMyClient->left + lWidth;
  1571. }
  1572. if (m_lY < 0)
  1573. {
  1574. prcMyClient->bottom = prcClient->bottom + 1 + m_lY;
  1575. prcMyClient->top = prcMyClient->bottom - lHeight;
  1576. }
  1577. else
  1578. {
  1579. prcMyClient->top = prcClient->top + m_lY;
  1580. prcMyClient->bottom = prcMyClient->top + lHeight;
  1581. }
  1582. break;
  1583. case PANEL_LEFT:
  1584. prcClient->left = prcMyClient->right = prcClient->left + lWidth;
  1585. if (prcClient->left > prcClient->right)
  1586. {
  1587. prcClient->left = prcMyClient->right = prcClient->right;
  1588. hr = S_FALSE;
  1589. }
  1590. break;
  1591. case PANEL_RIGHT:
  1592. prcClient->right = prcMyClient->left = prcClient->right - lWidth;
  1593. if (prcClient->right < prcClient->left)
  1594. {
  1595. prcClient->right = prcMyClient->left = prcClient->left;
  1596. hr = S_FALSE;
  1597. }
  1598. break;
  1599. case PANEL_TOP:
  1600. prcClient->top = prcMyClient->bottom = prcClient->top + lHeight;
  1601. if (prcClient->top > prcClient->bottom)
  1602. {
  1603. prcClient->top = prcMyClient->bottom = prcClient->bottom;
  1604. hr = S_FALSE;
  1605. }
  1606. break;
  1607. case PANEL_BOTTOM:
  1608. prcClient->bottom = prcMyClient->top = prcClient->bottom - lHeight;
  1609. if (prcClient->bottom < prcClient->top)
  1610. {
  1611. prcClient->bottom = prcMyClient->top = prcClient->top;
  1612. hr = S_FALSE;
  1613. }
  1614. break;
  1615. case PANEL_WINDOW:
  1616. hr = S_FALSE;
  1617. break;
  1618. default:
  1619. ATLASSERT(FALSE); // Invalid panel position.
  1620. break;
  1621. }
  1622. return hr;
  1623. }
  1624. // =========================================================
  1625. // CBrowserEvents
  1626. // =========================================================
  1627. CMarsPanel::CBrowserEvents::CBrowserEvents(CMarsPanel *pParent) :
  1628. CMarsPanelSubObject(pParent)
  1629. {
  1630. ATLASSERT(m_dwCookie == 0);
  1631. ATLASSERT(m_dwCookie2 == 0);
  1632. }
  1633. IMPLEMENT_ADDREF_RELEASE(CMarsPanel::CBrowserEvents);
  1634. //------------------------------------------------------------------------------
  1635. void CMarsPanel::CBrowserEvents::Connect(IUnknown *punk, BOOL bConnect)
  1636. {
  1637. CComPtr<IConnectionPointContainer> spCpc;
  1638. if (SUCCEEDED(punk->QueryInterface(IID_IConnectionPointContainer, (void **)&spCpc)))
  1639. {
  1640. CComPtr<IConnectionPoint> spCp;
  1641. if (SUCCEEDED(spCpc->FindConnectionPoint(DIID_DWebBrowserEvents, &spCp)))
  1642. {
  1643. if (bConnect)
  1644. {
  1645. spCp->Advise(this, &m_dwCookie);
  1646. }
  1647. else if (m_dwCookie)
  1648. {
  1649. spCp->Unadvise(m_dwCookie);
  1650. m_dwCookie = 0;
  1651. }
  1652. }
  1653. spCp.Release();
  1654. if (SUCCEEDED(spCpc->FindConnectionPoint(DIID_DWebBrowserEvents2, &spCp)))
  1655. {
  1656. if (bConnect)
  1657. {
  1658. spCp->Advise(this, &m_dwCookie2);
  1659. }
  1660. else if (m_dwCookie2)
  1661. {
  1662. spCp->Unadvise(m_dwCookie2);
  1663. m_dwCookie2 = 0;
  1664. }
  1665. }
  1666. }
  1667. }
  1668. //------------------------------------------------------------------------------
  1669. // IUnknown::QueryInterface
  1670. //
  1671. HRESULT CMarsPanel::CBrowserEvents::QueryInterface(REFIID iid, void **ppvObject)
  1672. {
  1673. HRESULT hr;
  1674. if ((iid == IID_IUnknown) ||
  1675. (iid == IID_IDispatch))
  1676. {
  1677. AddRef();
  1678. *ppvObject = SAFECAST(this, IDispatch *);
  1679. hr = S_OK;
  1680. }
  1681. else
  1682. {
  1683. *ppvObject = NULL;
  1684. hr = E_NOINTERFACE;
  1685. }
  1686. return hr;
  1687. }
  1688. //------------------------------------------------------------------------------
  1689. // IDispatch::Invoke
  1690. //
  1691. HRESULT CMarsPanel::CBrowserEvents::Invoke(DISPID dispidMember, REFIID riid,
  1692. LCID lcid, WORD wFlags, DISPPARAMS* pdispparams, VARIANT* pvarResult,
  1693. EXCEPINFO* pexcepinfo, UINT* puArgErr)
  1694. {
  1695. HRESULT hr = S_OK;
  1696. if (VerifyNotPassive(&hr))
  1697. {
  1698. switch (dispidMember)
  1699. {
  1700. case DISPID_BEFORENAVIGATE:
  1701. case DISPID_FRAMEBEFORENAVIGATE:
  1702. case DISPID_BEFORENAVIGATE2:
  1703. {
  1704. VARIANT *pVarCancel = &pdispparams->rgvarg[0];
  1705. if (pVarCancel->vt == (VT_BOOL | VT_BYREF))
  1706. {
  1707. if (VARIANT_TRUE == *pVarCancel->pboolVal)
  1708. {
  1709. CComPtr<IHTMLDocument2> spDoc2;
  1710. GetDoc2FromAxWindow(&Parent()->m_Content, &spDoc2);
  1711. if (spDoc2)
  1712. {
  1713. VARIANT vResult = {0};
  1714. EXCEPINFO excepInfo;
  1715. UINT uArgErr;
  1716. DISPPARAMS dp = {NULL, NULL, 0, 0};
  1717. if (SUCCEEDED(spDoc2->Invoke(DISPID_READYSTATE, IID_NULL, LOCALE_SYSTEM_DEFAULT,
  1718. DISPATCH_PROPERTYGET, &dp, &vResult, &excepInfo, &uArgErr)))
  1719. {
  1720. Parent()->m_lReadyState = (READYSTATE)V_I4(&vResult);
  1721. }
  1722. }
  1723. }
  1724. else
  1725. {
  1726. Parent()->m_lReadyState = READYSTATE_LOADING;
  1727. }
  1728. if (READYSTATE_COMPLETE == Parent()->m_lReadyState)
  1729. {
  1730. Parent()->m_spMarsDocument->GetPlaces()->OnPanelReady();
  1731. }
  1732. }
  1733. break;
  1734. }
  1735. case DISPID_DOCUMENTCOMPLETE:
  1736. {
  1737. Parent()->m_lReadyState = READYSTATE_COMPLETE;
  1738. Parent()->m_spMarsDocument->GetPlaces()->OnPanelReady();
  1739. break;
  1740. }
  1741. } // switch(dispidMember)
  1742. }
  1743. return hr;
  1744. }
  1745. //------------------------------------------------------------------------------
  1746. STDMETHODIMP CMarsPanel::TranslateAccelerator(MSG *pMsg, DWORD grfModifiers)
  1747. {
  1748. HRESULT hr;
  1749. ATLASSERT(!m_fTabCycle);
  1750. if (IsVK_TABCycler(pMsg))
  1751. {
  1752. m_fTabCycle = TRUE;
  1753. hr = S_OK;
  1754. }
  1755. else
  1756. {
  1757. hr = S_FALSE;
  1758. }
  1759. return hr;
  1760. }
  1761. //------------------------------------------------------------------------------
  1762. STDMETHODIMP CMarsPanel::OnUIActivate()
  1763. {
  1764. ATLASSERT(!IsPassive());
  1765. m_spPanelCollection->SetActivePanel(this, TRUE);
  1766. return S_OK;
  1767. }
  1768. //------------------------------------------------------------------------------
  1769. HRESULT CMarsPanel::UIDeactivate()
  1770. {
  1771. HRESULT hr;
  1772. CComPtr<IOleInPlaceObject> spOleInPlaceObject;
  1773. if (SUCCEEDED(m_Content.QueryControl(&spOleInPlaceObject)))
  1774. {
  1775. hr = spOleInPlaceObject->UIDeactivate();
  1776. }
  1777. else
  1778. {
  1779. // What the heck else can we do?
  1780. hr = S_FALSE;
  1781. }
  1782. return hr;
  1783. }
  1784. //------------------------------------------------------------------------------
  1785. // Forwards the message to the hosted control.
  1786. void CMarsPanel::ForwardMessage(UINT uMsg, WPARAM wParam, LPARAM lParam)
  1787. {
  1788. HWND hwnd;
  1789. CComPtr<IOleWindow> spOleWindow;
  1790. // Note that we send the message directly to the window rather than use
  1791. // WM_FORWARDMSG which calls TranslateAccelerator
  1792. if (SUCCEEDED(m_Content.QueryControl(&spOleWindow)) &&
  1793. SUCCEEDED(spOleWindow->GetWindow(&hwnd)))
  1794. {
  1795. SendMessage(hwnd, uMsg, wParam, lParam);
  1796. }
  1797. }
  1798. //------------------------------------------------------------------------------
  1799. HRESULT CMarsPanel::TranslateAccelerator(MSG *pMsg)
  1800. {
  1801. ATLASSERT(!IsPassive());
  1802. HRESULT hr = S_FALSE;
  1803. BOOL fGlobal = IsGlobalKeyMessage( pMsg );
  1804. if((S_OK == SHIsChildOrSelf(m_Content.m_hWnd, pMsg->hwnd)) || fGlobal)
  1805. {
  1806. if(m_spActiveObject && (this == m_spPanelCollection->ActivePanel()))
  1807. {
  1808. hr = m_spActiveObject->TranslateAccelerator(pMsg);
  1809. }
  1810. else
  1811. {
  1812. CComPtr<IOleInPlaceActiveObject> obj;
  1813. if(SUCCEEDED(m_Content.QueryControl( IID_IOleInPlaceActiveObject, (void **)&obj )))
  1814. {
  1815. hr = obj->TranslateAccelerator(pMsg);
  1816. }
  1817. //
  1818. // If it's a WebBrowser, forward the accelerator directly to the Document object, otherwise accesskeys won't be resolved.
  1819. //
  1820. if(hr == S_FALSE && fGlobal)
  1821. {
  1822. CComPtr<IWebBrowser2> obj2;
  1823. if(SUCCEEDED(m_Content.QueryControl( IID_IWebBrowser2, (void **)&obj2 )))
  1824. {
  1825. CComPtr<IDispatch> disp;
  1826. if(SUCCEEDED(obj2->get_Document( &disp )) && disp)
  1827. {
  1828. CComPtr<IOleInPlaceActiveObject> obj3;
  1829. if(SUCCEEDED(disp.QueryInterface( &obj3 )))
  1830. {
  1831. hr = obj3->TranslateAccelerator(pMsg);
  1832. }
  1833. }
  1834. }
  1835. }
  1836. }
  1837. }
  1838. return hr;
  1839. }
  1840. //----------------------------------------------------------------------------
  1841. // Returns the Screen coordinates of this panel
  1842. //----------------------------------------------------------------------------
  1843. void CMarsPanel::GetMyClientRectInParentCoords(RECT *prc)
  1844. {
  1845. ATLASSERT(!IsPassive());
  1846. POINT ptParent = {0, 0}, ptMe = {0, 0}, ptOffset;
  1847. m_Content.ClientToScreen(&ptMe);
  1848. m_spMarsDocument->Window()->ClientToScreen(&ptParent);
  1849. ptOffset.x = ptMe.x - ptParent.x;
  1850. ptOffset.y = ptMe.y - ptParent.y;
  1851. m_Content.GetClientRect(prc);
  1852. OffsetRect(prc, ptOffset.x, ptOffset.y);
  1853. }
  1854. // IInternetSecurityManager
  1855. // This interface is used to override default security settings for our panels.
  1856. // These panels are trusted.
  1857. //------------------------------------------------------------------------------
  1858. // IInternetSecurityManager::SetSecuritySite
  1859. //
  1860. HRESULT CMarsPanel::SetSecuritySite(IInternetSecurityMgrSite *pSite)
  1861. {
  1862. return E_NOTIMPL;
  1863. }
  1864. //------------------------------------------------------------------------------
  1865. // IInternetSecurityManager::GetSecuritySite
  1866. //
  1867. HRESULT CMarsPanel::GetSecuritySite(IInternetSecurityMgrSite **ppSite)
  1868. {
  1869. return E_NOTIMPL;
  1870. }
  1871. //------------------------------------------------------------------------------
  1872. // IInternetSecurityManager::MapUrlToZone
  1873. //
  1874. HRESULT CMarsPanel::MapUrlToZone(LPCWSTR pwszUrl, DWORD *pdwZone, DWORD dwFlags)
  1875. {
  1876. return INET_E_DEFAULT_ACTION;
  1877. }
  1878. //------------------------------------------------------------------------------
  1879. // IInternetSecurityManager::GetSecurityId
  1880. //
  1881. HRESULT CMarsPanel::GetSecurityId(LPCWSTR pwszUrl, BYTE *pbSecurityId, DWORD *pcbSecurityId, DWORD_PTR dwReserved)
  1882. {
  1883. return INET_E_DEFAULT_ACTION;
  1884. }
  1885. //------------------------------------------------------------------------------
  1886. // IInternetSecurityManager::ProcessUrlAction
  1887. //
  1888. // Be as permissive as we can
  1889. //
  1890. HRESULT CMarsPanel::ProcessUrlAction(LPCWSTR pwszUrl, DWORD dwAction,
  1891. BYTE __RPC_FAR *pPolicy, DWORD cbPolicy, BYTE *pContext,
  1892. DWORD cbContext, DWORD dwFlags, DWORD dwReserved)
  1893. {
  1894. ATLASSERT(IsTrusted());
  1895. if (cbPolicy >= sizeof(DWORD))
  1896. {
  1897. *((DWORD *)pPolicy) = URLPOLICY_ALLOW;
  1898. }
  1899. return S_OK;
  1900. }
  1901. //------------------------------------------------------------------------------
  1902. // IInternetSecurityManager::QueryCustomPolicy
  1903. //
  1904. // Be as permissive as we can
  1905. //
  1906. HRESULT CMarsPanel::QueryCustomPolicy(LPCWSTR pwszUrl, REFGUID guidKey, BYTE **ppPolicy,
  1907. DWORD *pcbPolicy, BYTE *pContext, DWORD cbContext, DWORD dwReserved)
  1908. {
  1909. ATLASSERT(IsTrusted());
  1910. ATLASSERT(ppPolicy && !*ppPolicy);
  1911. ATLASSERT(pcbPolicy);
  1912. if (ppPolicy && pcbPolicy)
  1913. {
  1914. *ppPolicy = (BYTE *)CoTaskMemAlloc(sizeof(DWORD));
  1915. if (*ppPolicy)
  1916. {
  1917. *pcbPolicy = sizeof(DWORD);
  1918. *(DWORD *)*ppPolicy = URLPOLICY_ALLOW;
  1919. return S_OK;
  1920. }
  1921. }
  1922. return INET_E_DEFAULT_ACTION;
  1923. }
  1924. //------------------------------------------------------------------------------
  1925. // IInternetSecurityManager::SetZoneMapping
  1926. //
  1927. HRESULT CMarsPanel::SetZoneMapping(DWORD dwZone, LPCWSTR lpszPattern, DWORD dwFlags)
  1928. {
  1929. return INET_E_DEFAULT_ACTION;
  1930. }
  1931. //------------------------------------------------------------------------------
  1932. // IInternetSecurityManager::GetZoneMappings
  1933. //
  1934. HRESULT CMarsPanel::GetZoneMappings(DWORD dwZone, IEnumString **ppenumString, DWORD dwFlags)
  1935. {
  1936. return INET_E_DEFAULT_ACTION;
  1937. }
  1938. //------------------------------------------------------------------------------
  1939. // OnDocHostUIExec
  1940. //
  1941. // When we get an Exec from Trident on CGID_DocHostCommandHandler, we can return S_OK
  1942. // to indicate that we handled the command and Trident should take no further action
  1943. // We'll delegate the processing to script by firing events
  1944. //
  1945. // TODO: once Mars accelerators are implemented, we should just block Trident from
  1946. // taking action, and not fire any events.
  1947. //
  1948. HRESULT CMarsPanel::OnDocHostUIExec(const GUID *pguidCmdGroup, DWORD nCmdID, DWORD nCmdexecopt,
  1949. VARIANTARG *pvarargIn, VARIANTARG *pvarargOut)
  1950. {
  1951. // HACK: Shdocvw/Trident sometimes tests specifically for a value like
  1952. // OLECMDERR_E_NOTSUPPORTED and will not perform an essential action
  1953. // if we return something more generic like E_FAIL.
  1954. HRESULT hr = OLECMDERR_E_NOTSUPPORTED;
  1955. if(!IsPassive() && pguidCmdGroup && (*pguidCmdGroup == CGID_DocHostCommandHandler))
  1956. {
  1957. switch (nCmdID)
  1958. {
  1959. case OLECMDID_SHOWFIND:
  1960. hr = S_OK;
  1961. break;
  1962. case IDM_NEW_TOPLEVELWINDOW:
  1963. // Shdocvw gives us this command when Ctrl+N or the localized equivalent
  1964. // is translated. We return S_OK to stop it from opening an IE window.
  1965. hr = S_OK;
  1966. break;
  1967. case IDM_REFRESH:
  1968. case IDM_REFRESH_TOP:
  1969. case IDM_REFRESH_TOP_FULL:
  1970. case IDM_REFRESH_THIS:
  1971. case IDM_REFRESH_THIS_FULL:
  1972. if(!m_fInRefresh)
  1973. {
  1974. hr = S_OK;
  1975. }
  1976. break;
  1977. case OLECMDID_SHOWSCRIPTERROR:
  1978. if(SUCCEEDED(m_spMarsDocument->MarsWindow()->NotifyHost( MARSHOST_ON_SCRIPT_ERROR, V_VT(pvarargIn) == VT_UNKNOWN ? V_UNKNOWN(pvarargIn) : NULL, 0 )))
  1979. {
  1980. V_VT (pvarargOut) = VT_BOOL;
  1981. V_BOOL(pvarargOut) = VARIANT_FALSE;
  1982. hr = S_OK;
  1983. }
  1984. break;
  1985. }
  1986. }
  1987. return hr;
  1988. }
  1989. //
  1990. // CPanelCollection implementation
  1991. //
  1992. //------------------------------------------------------------------------------
  1993. CPanelCollection::CPanelCollection(CMarsDocument *pMarsDocument)
  1994. {
  1995. m_spMarsDocument = pMarsDocument;
  1996. }
  1997. //------------------------------------------------------------------------------
  1998. CPanelCollection::~CPanelCollection()
  1999. {
  2000. ATLASSERT(GetSize() == 0);
  2001. FreePanels();
  2002. }
  2003. //------------------------------------------------------------------------------
  2004. void CPanelCollection::FreePanels()
  2005. {
  2006. for (int i=0; i<GetSize(); i++)
  2007. {
  2008. (*this)[i].PassivateAndRelease();
  2009. }
  2010. RemoveAll();
  2011. }
  2012. //------------------------------------------------------------------------------
  2013. HRESULT CPanelCollection::DoPassivate()
  2014. {
  2015. FreePanels();
  2016. m_spMarsDocument.Release();
  2017. return S_OK;
  2018. }
  2019. IMPLEMENT_ADDREF_RELEASE(CPanelCollection);
  2020. //------------------------------------------------------------------------------
  2021. // IUnknown::QueryInterface
  2022. //
  2023. STDMETHODIMP CPanelCollection::QueryInterface(REFIID iid, void **ppvObject)
  2024. {
  2025. HRESULT hr;
  2026. if (API_IsValidWritePtr(ppvObject))
  2027. {
  2028. if ((iid == IID_IUnknown) ||
  2029. (iid == IID_IDispatch) ||
  2030. (iid == IID_IMarsPanelCollection))
  2031. {
  2032. AddRef();
  2033. *ppvObject = SAFECAST(this, IMarsPanelCollection *);
  2034. hr = S_OK;
  2035. }
  2036. else
  2037. {
  2038. *ppvObject = NULL;
  2039. hr = E_NOINTERFACE;
  2040. }
  2041. }
  2042. else
  2043. {
  2044. hr = E_INVALIDARG;
  2045. }
  2046. return hr;
  2047. }
  2048. //------------------------------------------------------------------------------
  2049. HRESULT CPanelCollection::DoEnableModeless(BOOL fEnable)
  2050. {
  2051. for (int i=0; i<GetSize(); i++)
  2052. {
  2053. (*this)[i]->DoEnableModeless(fEnable);
  2054. }
  2055. return S_OK;
  2056. }
  2057. //////////////////////////////
  2058. // IMarsPanelCollection
  2059. //------------------------------------------------------------------------------
  2060. // IMarsPanelCollection::get_panel
  2061. //
  2062. // TODO: (PaulNash, 9/19/99) This method is outdated.
  2063. // Remove once content is switched over.
  2064. //
  2065. STDMETHODIMP CPanelCollection::get_panel(LPWSTR pwszName, IMarsPanel **ppPanel)
  2066. {
  2067. CComVariant var(pwszName);
  2068. return get_item(var, ppPanel);
  2069. }
  2070. //------------------------------------------------------------------------------
  2071. // IMarsPanelCollection::addPanel
  2072. //
  2073. STDMETHODIMP CPanelCollection::addPanel(
  2074. BSTR bstrName,
  2075. VARIANT varType,
  2076. BSTR bstrStartUrl,
  2077. VARIANT varCreate,
  2078. long lFlags,
  2079. IMarsPanel **ppPanel)
  2080. {
  2081. HRESULT hr = E_INVALIDARG;
  2082. if (API_IsValidString(bstrName) &&
  2083. (VT_NULL == varType.vt || API_IsValidVariantBstr(varType)) &&
  2084. (NULL == bstrStartUrl || API_IsValidString(bstrStartUrl)) &&
  2085. (VT_NULL == varCreate.vt || API_IsValidVariantBstr(varCreate)) &&
  2086. API_IsValidFlag(lFlags, PANEL_FLAG_ALL) &&
  2087. API_IsValidWritePtr(ppPanel) )
  2088. {
  2089. *ppPanel = NULL;
  2090. if (VerifyNotPassive(&hr))
  2091. {
  2092. MarsAppDef_Panel Layout;
  2093. BSTR bstrType = VariantToBSTR( varType );
  2094. BSTR bstrCreate = VariantToBSTR( varCreate );
  2095. DWORD dwFlags = DEFAULT_PANEL_FLAGS | (DWORD)lFlags;
  2096. StringToPanelFlags( bstrType , dwFlags );
  2097. StringToPanelFlags( bstrCreate, dwFlags );
  2098. StringCchCopyW ( Layout.szName, ARRAYSIZE(Layout.szName), bstrName );
  2099. ExpandEnvironmentStringsW( bstrStartUrl , Layout.szUrl, ARRAYSIZE(Layout.szUrl ) );
  2100. Layout.dwFlags = dwFlags;
  2101. AddPanel(&Layout, NULL);
  2102. hr = get_item( CComVariant( bstrName ), ppPanel );
  2103. }
  2104. }
  2105. return hr;
  2106. }
  2107. //------------------------------------------------------------------------------
  2108. // IMarsPanelCollection::removePanel
  2109. //
  2110. STDMETHODIMP CPanelCollection::removePanel(LPWSTR pwszName)
  2111. {
  2112. HRESULT hr = E_INVALIDARG;
  2113. if(API_IsValidString(pwszName))
  2114. {
  2115. if(VerifyNotPassive(&hr))
  2116. {
  2117. hr = S_FALSE;
  2118. for(int i=0; i<GetSize(); i++)
  2119. {
  2120. if(!StrCmpI(pwszName, (*this)[i]->GetName()))
  2121. {
  2122. BOOL fVisible = (*this)[i]->IsVisible();
  2123. (*this)[i].PassivateAndRelease();
  2124. RemoveAt(i);
  2125. if(fVisible)
  2126. {
  2127. Layout();
  2128. }
  2129. hr = S_OK;
  2130. break;
  2131. }
  2132. }
  2133. }
  2134. }
  2135. return hr;
  2136. }
  2137. //------------------------------------------------------------------------------
  2138. // IMarsPanelCollection::lockLayout
  2139. //
  2140. STDMETHODIMP CPanelCollection::lockLayout()
  2141. {
  2142. HRESULT hr = S_OK;
  2143. if (VerifyNotPassive(&hr))
  2144. {
  2145. m_iLockLayout++;
  2146. }
  2147. return hr;
  2148. }
  2149. //------------------------------------------------------------------------------
  2150. // IMarsPanelCollection::unlockLayout
  2151. //
  2152. STDMETHODIMP CPanelCollection::unlockLayout()
  2153. {
  2154. HRESULT hr = S_OK;
  2155. if (VerifyNotPassive(&hr))
  2156. {
  2157. if (IsLayoutLocked())
  2158. {
  2159. if (0 == --m_iLockLayout)
  2160. {
  2161. // TODO: clear lock timeout
  2162. if (m_fPendingLayout)
  2163. {
  2164. m_fPendingLayout = FALSE;
  2165. Layout();
  2166. }
  2167. }
  2168. }
  2169. }
  2170. return hr;
  2171. }
  2172. //------------------------------------------------------------------------------
  2173. void CPanelCollection::Layout()
  2174. {
  2175. if(!IsPassive())
  2176. {
  2177. if(!IsLayoutLocked())
  2178. {
  2179. RECT rcClient;
  2180. lockLayout();
  2181. m_spMarsDocument->Window()->GetClientRect( &rcClient );
  2182. if(m_spMarsDocument->MarsWindow()->CanLayout( rcClient ) == false)
  2183. {
  2184. m_spMarsDocument->MarsWindow()->FixLayout( rcClient );
  2185. }
  2186. m_fPendingLayout = FALSE;
  2187. for (int i=0; i<GetSize(); i++)
  2188. {
  2189. if (S_OK != (*this)[i]->Layout( &rcClient ))
  2190. {
  2191. // We're out of client area; won't be able to show all panels.
  2192. // Keep calling Layout for remaining panels so they can hide themselves.
  2193. }
  2194. }
  2195. ATLASSERT(!m_fPendingLayout);
  2196. unlockLayout();
  2197. }
  2198. else
  2199. {
  2200. // We'll do the layout once we get unlocked
  2201. m_fPendingLayout = TRUE;
  2202. }
  2203. }
  2204. }
  2205. //------------------------------------------------------------------------------
  2206. void CPanelCollection::SetActivePanel(CMarsPanel *pPanel, BOOL bActive)
  2207. {
  2208. if (bActive)
  2209. {
  2210. if (m_spActivePanel != pPanel)
  2211. {
  2212. if (m_spActivePanel)
  2213. {
  2214. m_spActivePanel->UIDeactivate();
  2215. m_spActivePanel.Release();
  2216. }
  2217. m_spActivePanel = pPanel;
  2218. }
  2219. }
  2220. else
  2221. {
  2222. // A panel is telling us it doesn't want to be the active
  2223. // panel anymore.
  2224. if (pPanel == m_spActivePanel)
  2225. {
  2226. m_spActivePanel->UIDeactivate();
  2227. m_spActivePanel.Release();
  2228. }
  2229. }
  2230. }
  2231. //------------------------------------------------------------------------------
  2232. // IMarsPanelCollection::get_activePanel
  2233. //
  2234. STDMETHODIMP CPanelCollection::get_activePanel(IMarsPanel **ppPanel)
  2235. {
  2236. HRESULT hr = E_INVALIDARG;
  2237. if (API_IsValidWritePtr(ppPanel))
  2238. {
  2239. *ppPanel = NULL;
  2240. if (VerifyNotPassive(&hr))
  2241. {
  2242. hr = S_OK;
  2243. *ppPanel = ActivePanel();
  2244. if (*ppPanel)
  2245. {
  2246. (*ppPanel)->AddRef();
  2247. }
  2248. }
  2249. }
  2250. return hr;
  2251. }
  2252. //------------------------------------------------------------------------------
  2253. HRESULT CPanelCollection::AddPanel( MarsAppDef_Panel* pLayout, /*optional*/ IMarsPanel **ppPanel)
  2254. {
  2255. ATLASSERT(pLayout);
  2256. ATLASSERT(!IsPassive());
  2257. HRESULT hr = E_FAIL;
  2258. if (ppPanel)
  2259. {
  2260. *ppPanel = NULL;
  2261. }
  2262. // If it's a duplicate panel name, just fail.
  2263. if (!FindPanel(pLayout->szName))
  2264. {
  2265. CComClassPtr<CMarsPanel> spPanel;
  2266. spPanel.Attach(new CMarsPanel(this, m_spMarsDocument->MarsWindow()));
  2267. if (spPanel)
  2268. {
  2269. if (Add(spPanel))
  2270. {
  2271. spPanel->Create(pLayout);
  2272. if (ppPanel)
  2273. {
  2274. hr = spPanel->QueryInterface(IID_IMarsPanel, (void **)ppPanel);
  2275. }
  2276. hr = S_OK;
  2277. }
  2278. else
  2279. {
  2280. hr = E_OUTOFMEMORY;
  2281. }
  2282. }
  2283. else
  2284. {
  2285. hr = E_OUTOFMEMORY;
  2286. }
  2287. }
  2288. return hr;
  2289. }
  2290. //------------------------------------------------------------------------------
  2291. CMarsPanel *CPanelCollection::FindPanel(LPCWSTR pwszName)
  2292. {
  2293. ATLASSERT(!IsPassive());
  2294. CMarsPanel *pPanel = NULL;
  2295. int iLen = GetSize();
  2296. for (int i = 0; i < iLen; ++i)
  2297. {
  2298. if (!StrCmpIW(pwszName, (*this)[i]->GetName()))
  2299. {
  2300. pPanel = (*this)[i];
  2301. break;
  2302. }
  2303. }
  2304. return pPanel;
  2305. }
  2306. //------------------------------------------------------------------------------
  2307. HRESULT CPanelCollection::FindPanelIndex(CMarsPanel *pPanel, long *plIndex)
  2308. {
  2309. ATLASSERT(plIndex);
  2310. ATLASSERT(!IsPassive());
  2311. HRESULT hr = E_FAIL;
  2312. *plIndex = -1;
  2313. if (pPanel)
  2314. {
  2315. long lSize = GetSize();
  2316. for (long i = 0; i < lSize; ++i)
  2317. {
  2318. if (pPanel == (*this)[i])
  2319. {
  2320. *plIndex = i;
  2321. hr = S_OK;
  2322. break;
  2323. }
  2324. }
  2325. }
  2326. return hr;
  2327. }
  2328. //------------------------------------------------------------------------------
  2329. HRESULT CPanelCollection::InsertPanelFromTo(long lOldIndex, long lNewIndex)
  2330. {
  2331. ATLASSERT((lOldIndex >= 0) && (lOldIndex < GetSize()));
  2332. ATLASSERT(!IsPassive());
  2333. HRESULT hr = S_FALSE;
  2334. if (lNewIndex < 0)
  2335. {
  2336. lNewIndex = 0;
  2337. }
  2338. if (lNewIndex > GetSize() - 1)
  2339. {
  2340. lNewIndex = GetSize() - 1;
  2341. }
  2342. // If this is something that is done very often, we should optimize this better
  2343. // and probably not use an array
  2344. if (lOldIndex != lNewIndex)
  2345. {
  2346. CComClassPtr<CMarsPanel> spPanel = (*this)[lOldIndex];
  2347. RemoveAt(lOldIndex);
  2348. InsertAt(lNewIndex, spPanel);
  2349. hr = S_OK;
  2350. }
  2351. return hr;
  2352. }
  2353. //------------------------------------------------------------------------------
  2354. // Sets the dirty bit on all panels after a theme switch
  2355. //
  2356. void CPanelCollection::InvalidatePanels()
  2357. {
  2358. for (int i=0; i < GetSize(); i++)
  2359. {
  2360. (*this)[i]->put_contentInvalid(VARIANT_TRUE);
  2361. }
  2362. }
  2363. //------------------------------------------------------------------------------
  2364. // Called after the theme switch event has fired, to refresh any panels
  2365. // that are visible but still haven't been updated with the new theme
  2366. //
  2367. void CPanelCollection::RefreshInvalidVisiblePanels()
  2368. {
  2369. for (int i=0; i < GetSize(); i++)
  2370. {
  2371. CMarsPanel *pPanel = (*this)[i];
  2372. if (pPanel->IsVisible() && pPanel->IsContentInvalid())
  2373. {
  2374. pPanel->refresh();
  2375. }
  2376. }
  2377. }
  2378. //------------------------------------------------------------------------------
  2379. // IMarsPanelCollection::get_length
  2380. //
  2381. // standard collection method (gets instantaneous length of coll)
  2382. //
  2383. STDMETHODIMP CPanelCollection::get_length(LONG *plNumPanels)
  2384. {
  2385. HRESULT hr = E_INVALIDARG;
  2386. if (API_IsValidWritePtr(plNumPanels))
  2387. {
  2388. (*plNumPanels) = GetSize();
  2389. hr = S_OK;
  2390. }
  2391. return hr;
  2392. }
  2393. //------------------------------------------------------------------------------
  2394. // IMarsPanelCollection::get_item
  2395. //
  2396. // standard collection method (gets an theme given index or name)
  2397. //
  2398. STDMETHODIMP CPanelCollection::get_item(/*[in]*/ VARIANT varIndexOrName,
  2399. /*[out, retval]*/ IMarsPanel **ppPanel)
  2400. {
  2401. ATLASSERT(VT_BSTR == varIndexOrName.vt || VT_I4 == varIndexOrName.vt);
  2402. HRESULT hr = E_INVALIDARG;
  2403. //
  2404. // We can't use the API_IsValid varieties because they rip, and we actually don't want that.
  2405. // It's only valid to RIP on IsValidFailure if only a single type is allowed, but here we
  2406. // allow two types in the Variant, so we would only want to RIP if both are false (already
  2407. // handled by above RIP).
  2408. //
  2409. if ((IsValidVariantI4(varIndexOrName) || IsValidVariantBstr(varIndexOrName)) &&
  2410. API_IsValidWritePtr(ppPanel))
  2411. {
  2412. *ppPanel= NULL;
  2413. if (VerifyNotPassive(&hr))
  2414. {
  2415. CMarsPanel *pPanel = NULL;
  2416. if (VT_BSTR == varIndexOrName.vt)
  2417. {
  2418. pPanel = FindPanel(V_BSTR(&varIndexOrName));
  2419. if (pPanel)
  2420. {
  2421. hr = pPanel->QueryInterface(IID_IMarsPanel, (void **)ppPanel);
  2422. }
  2423. else
  2424. {
  2425. hr = S_FALSE;
  2426. }
  2427. }
  2428. else if (VT_I4 == varIndexOrName.vt)
  2429. {
  2430. long idxPanel = V_I4(&varIndexOrName);
  2431. if (idxPanel >= 0 && idxPanel < GetSize())
  2432. {
  2433. pPanel = (*this)[idxPanel];
  2434. if (pPanel)
  2435. {
  2436. hr = pPanel->QueryInterface(IID_IMarsPanel, (void **)ppPanel);
  2437. }
  2438. else
  2439. {
  2440. hr = S_FALSE;
  2441. }
  2442. }
  2443. }
  2444. else
  2445. {
  2446. // We only accept VT_BSTR and VT_I4 and we should have already
  2447. // detected any other invalid params higher up in the function.
  2448. ATLASSERT(false);
  2449. }
  2450. }
  2451. }
  2452. return hr;
  2453. } // get_item
  2454. //------------------------------------------------------------------------------
  2455. // IMarsPanelCollection::get__newEnum
  2456. // standard collection method (gets a new IEnumVARIANT)
  2457. //
  2458. STDMETHODIMP CPanelCollection::get__newEnum(/*[out, retval]*/ IUnknown **ppEnumPanels)
  2459. {
  2460. HRESULT hr = E_INVALIDARG;
  2461. if (API_IsValidWritePtr(ppEnumPanels))
  2462. {
  2463. *ppEnumPanels = NULL;
  2464. if (VerifyNotPassive(&hr))
  2465. {
  2466. // This helper takes a CMarsSimpleArray and does all
  2467. // the work of creating a CComEnum for us. Neat!
  2468. hr = CMarsComEnumVariant< CMarsPanel >::CreateFromMarsSimpleArray(*this, ppEnumPanels);
  2469. }
  2470. }
  2471. return hr;
  2472. } // get__newEnum