container.cpp
Upload User: xhy777
Upload Date: 2007-02-14
Package Size: 24088k
Code Size: 18k
Category:

Windows Kernel

Development Platform:

Visual C++

  1. //////////////////////////////////////////////////////////////////////////
  2. //
  3. //  container.cpp
  4. //
  5. //      This file contains the complete implementation of an ActiveX
  6. //      control container. This purpose of this container is to test
  7. //      a single control being hosted.
  8. //
  9. //  (C) Copyright 1997 by Microsoft Corporation. All rights reserved.
  10. //
  11. //////////////////////////////////////////////////////////////////////////
  12. #include <windows.h>
  13. #include <shlwapi.h>
  14. #include "container.h"
  15. /**
  16.  *  This method is the constructor for the CContainer object. 
  17.  */
  18. CContainer::CContainer()
  19. {
  20.     m_cRefs     = 1;
  21.     m_hwnd      = NULL;
  22.     m_punk      = NULL;
  23.     memset(&m_rect, 0, sizeof(m_rect));
  24. }
  25. /** 
  26.  *  This method is the destructor for the CContainer object.
  27.  */
  28. CContainer::~CContainer()
  29. {
  30.     if (m_punk)
  31.     {
  32.         m_punk->Release();
  33.         m_punk=NULL;
  34.     }
  35. }
  36. /**
  37.  *  This method is called when the caller wants an interface pointer.
  38.  *
  39.  *  @param      riid        The interface being requested.
  40.  *  @param      ppvObject   The resultant object pointer.
  41.  *
  42.  *  @return     HRESULT     S_OK, E_POINTER, E_NOINTERFACE
  43.  */
  44. STDMETHODIMP CContainer::QueryInterface(REFIID riid, PVOID *ppvObject)
  45. {
  46.     if (!ppvObject)
  47.         return E_POINTER;
  48.     if (IsEqualIID(riid, IID_IOleClientSite))
  49.         *ppvObject = (IOleClientSite *)this;
  50.     else if (IsEqualIID(riid, IID_IOleInPlaceSite))
  51.         *ppvObject = (IOleInPlaceSite *)this;
  52.     else if (IsEqualIID(riid, IID_IOleInPlaceFrame))
  53.         *ppvObject = (IOleInPlaceFrame *)this;
  54.     else if (IsEqualIID(riid, IID_IOleInPlaceUIWindow))
  55.         *ppvObject = (IOleInPlaceUIWindow *)this;
  56.     else if (IsEqualIID(riid, IID_IOleControlSite))
  57.         *ppvObject = (IOleControlSite *)this;
  58.     else if (IsEqualIID(riid, IID_IDocHostUIHandler))
  59.         *ppvObject = (IDocHostUIHandler *)this;
  60.     else if (IsEqualIID(riid, IID_IOleWindow))
  61.         *ppvObject = this;
  62.     else if (IsEqualIID(riid, IID_IDispatch))
  63.         *ppvObject = (IDispatch *)this;
  64.     else if (IsEqualIID(riid, IID_IUnknown))
  65.         *ppvObject = this;
  66.     else
  67.     {
  68.         *ppvObject = NULL;
  69.         return E_NOINTERFACE;
  70.     }
  71.     AddRef();
  72.     return S_OK;
  73. }
  74. /**
  75.  *  This method increments the current object count.
  76.  *
  77.  *  @return     ULONG       The new reference count.
  78.  */
  79. ULONG CContainer::AddRef(void)
  80. {
  81.     return ++m_cRefs;
  82. }
  83. /**
  84.  *  This method decrements the object count and deletes if necessary.
  85.  *
  86.  *  @return     ULONG       Remaining ref count.
  87.  */
  88. ULONG CContainer::Release(void)
  89. {
  90.     if (--m_cRefs)
  91.         return m_cRefs;
  92.     delete this;
  93.     return 0;
  94. }
  95. // ***********************************************************************
  96. //  IOleClientSite
  97. // ***********************************************************************
  98. HRESULT CContainer::SaveObject()
  99. {
  100.     return E_NOTIMPL;
  101. }
  102. HRESULT CContainer::GetMoniker(DWORD dwAssign, DWORD dwWhichMoniker, LPMONIKER * ppMk)
  103. {
  104.     return E_NOTIMPL;
  105. }
  106. HRESULT CContainer::GetContainer(LPOLECONTAINER * ppContainer)
  107. {
  108.     return E_NOINTERFACE;
  109. }
  110. HRESULT CContainer::ShowObject()
  111. {
  112.     return S_OK;
  113. }
  114. HRESULT CContainer::OnShowWindow(BOOL fShow)
  115. {
  116.     return S_OK;
  117. }
  118. HRESULT CContainer::RequestNewObjectLayout()
  119. {
  120.     return E_NOTIMPL;
  121. }
  122. // ***********************************************************************
  123. //  IOleWindow
  124. // ***********************************************************************
  125. HRESULT CContainer::GetWindow(HWND * lphwnd)
  126. {
  127.     if (!IsWindow(m_hwnd))
  128.     {
  129.         *lphwnd = NULL;
  130.         return S_FALSE;
  131.     }
  132.     *lphwnd = m_hwnd;
  133.     return S_OK;
  134. }
  135. HRESULT CContainer::ContextSensitiveHelp(BOOL fEnterMode)
  136. {
  137.     return E_NOTIMPL;
  138. }
  139. // ***********************************************************************
  140. //  IOleInPlaceSite
  141. // ***********************************************************************
  142. HRESULT CContainer::CanInPlaceActivate(void)
  143. {
  144.     return S_OK;
  145. }
  146. HRESULT CContainer::OnInPlaceActivate(void)
  147. {
  148.     return S_OK;
  149. }
  150. HRESULT CContainer::OnUIActivate(void)
  151. {
  152.     return S_OK;
  153. }
  154. HRESULT CContainer::GetWindowContext (IOleInPlaceFrame ** ppFrame, IOleInPlaceUIWindow ** ppIIPUIWin,
  155.                                   LPRECT lprcPosRect, LPRECT lprcClipRect, LPOLEINPLACEFRAMEINFO lpFrameInfo)
  156. {
  157.     *ppFrame = (IOleInPlaceFrame *)this;
  158.     *ppIIPUIWin = NULL;
  159.     RECT rect;
  160.     GetClientRect(m_hwnd, &rect);
  161.     lprcPosRect->left       = 0;
  162.     lprcPosRect->top        = 0;
  163.     lprcPosRect->right      = rect.right;
  164.     lprcPosRect->bottom     = rect.bottom;
  165.     CopyRect(lprcClipRect, lprcPosRect);
  166.     lpFrameInfo->cb             = sizeof(OLEINPLACEFRAMEINFO);
  167.     lpFrameInfo->fMDIApp        = FALSE;
  168.     lpFrameInfo->hwndFrame      = m_hwnd;
  169.     lpFrameInfo->haccel         = 0;
  170.     lpFrameInfo->cAccelEntries  = 0;
  171.     (*ppFrame)->AddRef();
  172.     return S_OK;
  173. }
  174. HRESULT CContainer::Scroll(SIZE scrollExtent)
  175. {
  176.     return E_NOTIMPL;
  177. }
  178. HRESULT CContainer::OnUIDeactivate(BOOL fUndoable)
  179. {
  180.     return E_NOTIMPL;
  181. }
  182. HRESULT CContainer::OnInPlaceDeactivate(void)
  183. {
  184.     return S_OK;
  185. }
  186. HRESULT CContainer::DiscardUndoState(void)
  187. {
  188.     return E_NOTIMPL;
  189. }
  190. HRESULT CContainer::DeactivateAndUndo(void)
  191. {
  192.     return E_NOTIMPL;
  193. }
  194. HRESULT CContainer::OnPosRectChange(LPCRECT lprcPosRect)
  195. {
  196.     return S_OK;
  197. }
  198. // ***********************************************************************
  199. //  IOleInPlaceUIWindow
  200. // ***********************************************************************
  201. HRESULT CContainer::GetBorder(LPRECT lprectBorder)
  202. {
  203.     return E_NOTIMPL;
  204. }
  205. HRESULT CContainer::RequestBorderSpace(LPCBORDERWIDTHS lpborderwidths)
  206. {
  207.     return E_NOTIMPL;
  208. }
  209. HRESULT CContainer::SetBorderSpace(LPCBORDERWIDTHS lpborderwidths)
  210. {
  211.     return E_NOTIMPL;
  212. }
  213. HRESULT CContainer::SetActiveObject(IOleInPlaceActiveObject * pActiveObject, LPCOLESTR lpszObjName)
  214. {
  215.     return E_NOTIMPL;
  216. }
  217. // ***********************************************************************
  218. //  IOleInPlaceFrame
  219. // ***********************************************************************
  220. HRESULT CContainer::InsertMenus(HMENU hmenuShared, LPOLEMENUGROUPWIDTHS lpMenuWidths)
  221. {
  222.     return E_NOTIMPL;
  223. }
  224. HRESULT CContainer::SetMenu(HMENU hmenuShared, HOLEMENU holemenu, HWND hwndActiveObject)
  225. {
  226.     return E_NOTIMPL;
  227. }
  228. HRESULT CContainer::RemoveMenus(HMENU hmenuShared)
  229. {
  230.     return E_NOTIMPL;
  231. }
  232. HRESULT CContainer::SetStatusText(LPCOLESTR pszStatusText)
  233. {
  234.     return S_OK;
  235. }
  236. HRESULT CContainer::EnableModeless(BOOL fEnable)
  237. {
  238.     return E_NOTIMPL;
  239. }
  240. HRESULT CContainer::TranslateAccelerator(LPMSG lpmsg, WORD wID)
  241. {
  242.     // BUGBUG: cache this pointer since this is called ALOT
  243.     IOleInPlaceActiveObject * pioipao;
  244.     if ( m_punk && SUCCEEDED(m_punk->QueryInterface(IID_IOleInPlaceActiveObject, (LPVOID *)&pioipao)))
  245.     {
  246.         HRESULT hr;
  247.         hr = pioipao->TranslateAccelerator( lpmsg );
  248.         pioipao->Release();
  249.         return hr;
  250.     }
  251.     return S_OK;
  252. }
  253. // ***********************************************************************
  254. //  IOleControlSite
  255. // ***********************************************************************
  256. HRESULT CContainer::OnControlInfoChanged()
  257. {
  258.     return E_NOTIMPL;
  259. }
  260. HRESULT CContainer::LockInPlaceActive(BOOL fLock)
  261. {
  262.     return E_NOTIMPL;
  263. }
  264. HRESULT CContainer::GetExtendedControl(IDispatch **ppDisp)
  265. {
  266.     if (ppDisp == NULL)
  267.         return E_INVALIDARG;
  268.     *ppDisp = (IDispatch *)this;
  269.     (*ppDisp)->AddRef();
  270.     return S_OK;
  271. }
  272. HRESULT CContainer::TransformCoords(POINTL *pptlHimetric, POINTF *pptfContainer, DWORD dwFlags)
  273. {
  274.     return E_NOTIMPL;
  275. }
  276. HRESULT CContainer::TranslateAccelerator(LPMSG pMsg, DWORD grfModifiers)
  277. {
  278.     // The control will call this method on the container if the control
  279.     // does not want to accelerate the given message.  This is called
  280.     // after the control processes it's accelerators.
  281.     return S_FALSE;
  282. }
  283. HRESULT CContainer::OnFocus(BOOL fGotFocus)
  284. {
  285.     return E_NOTIMPL;
  286. }
  287. HRESULT CContainer::ShowPropertyFrame(void)
  288. {
  289.     return E_NOTIMPL;
  290. }
  291. // ***********************************************************************
  292. //  IDispatch
  293. // ***********************************************************************
  294. HRESULT CContainer::GetIDsOfNames(REFIID riid, OLECHAR FAR* FAR* rgszNames, unsigned int cNames, LCID lcid, DISPID FAR* rgdispid)
  295. {
  296.     if ( 0 == StrCmpW( *rgszNames, L"Exit" ) )
  297.     {
  298.         *rgdispid = 1;
  299.         return S_OK;
  300.     }
  301.     else
  302.     {
  303.         *rgdispid = DISPID_UNKNOWN;
  304.         return DISP_E_UNKNOWNNAME;
  305.     }
  306. }
  307. HRESULT CContainer::GetTypeInfo(unsigned int itinfo, LCID lcid, ITypeInfo FAR* FAR* pptinfo)
  308. {
  309.     return E_NOTIMPL;
  310. }
  311. HRESULT CContainer::GetTypeInfoCount(unsigned int FAR * pctinfo)
  312. {
  313.     return E_NOTIMPL;
  314. }
  315. HRESULT CContainer::Invoke(DISPID dispid, REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS FAR *pdispparams, VARIANT FAR *pvarResult, EXCEPINFO FAR * pexecinfo, unsigned int FAR *puArgErr)
  316. {
  317.     if ( 1 == dispid )
  318.     {
  319.         // Exit the process by destroying our window
  320.         // DestroyWindow(m_hwnd);
  321.         // BUGBUG: Due to a bug in jscript (build 1983 and later) we AV when we destory the container window before
  322.         // allowing the contained object time to shut down.  It's totally timing related.  By delaying the actual
  323.         // DestroyWindow call we avoid the bug.  This is NOT a solution to the bug, its a work around.  It would be
  324.         // much simpler if we could just go ahead and destroy our window.  If the browser folks get this bug fixed
  325.         // we should switch back to using the Destroy Window call above and get rid of OnExit and OnRelease in the
  326.         // CWebApp class.
  327.         SendMessage(m_hwnd,WM_USER+0,0,0);              // release everything
  328.         PostMessage(m_hwnd,WM_USER+1,0,0);              // then post a message to destroy ourselves
  329.         return S_OK;
  330.     }
  331.     else
  332.     {
  333.         return DISP_E_MEMBERNOTFOUND;
  334.     }
  335. }
  336. // ***********************************************************************
  337. //  IDocHostUIHandler
  338. // ***********************************************************************
  339. HRESULT CContainer::GetHostInfo(DOCHOSTUIINFO* pInfo)
  340. {
  341.     pInfo->dwFlags = DOCHOSTUIFLAG_DIALOG|DOCHOSTUIFLAG_DISABLE_HELP_MENU|DOCHOSTUIFLAG_NO3DBORDER;
  342.     pInfo->dwDoubleClick = DOCHOSTUIDBLCLK_DEFAULT;
  343.     return S_OK;
  344. }
  345. HRESULT CContainer::ShowUI(DWORD, IOleInPlaceActiveObject *, IOleCommandTarget *, IOleInPlaceFrame *, IOleInPlaceUIWindow *)
  346. {
  347.     // S_OK means we have shown our own UI so mshtml should not show any menus or toolbars
  348.     return S_OK;
  349. }
  350. HRESULT CContainer::HideUI(void)
  351. {
  352.     // S_OK means we have hidden the UI elements (menus, toolbars, etc).
  353.     // Since we don't have any of these they are already hidden.
  354.     return S_OK;
  355. }
  356. HRESULT CContainer::UpdateUI(void)
  357. {
  358.     return S_OK;
  359. }
  360. //HRESULT CContainer::EnableModeless(BOOL)
  361. //{
  362. //    return E_NOTIMPL;
  363. //}
  364. HRESULT CContainer::OnDocWindowActivate(BOOL)
  365. {
  366.     return E_NOTIMPL;
  367. }
  368. HRESULT CContainer::OnFrameWindowActivate(BOOL)
  369. {
  370.     return E_NOTIMPL;
  371. }
  372. HRESULT CContainer::ResizeBorder(LPCRECT, IOleInPlaceUIWindow*, BOOL)
  373. {
  374.     return E_NOTIMPL;
  375. }
  376. HRESULT CContainer::ShowContextMenu(DWORD, POINT*, IUnknown*, IDispatch*)
  377. {
  378.     // S_OK means don't show context menu
  379.     return S_OK;
  380. }
  381. HRESULT CContainer::TranslateAccelerator(LPMSG, const GUID __RPC_FAR *, DWORD)
  382. {
  383.     // S_FALSE means let mshtml do the default translation
  384.     return S_FALSE;
  385. }
  386. HRESULT CContainer::GetOptionKeyPath(BSTR*, DWORD)
  387. {
  388.     return E_NOTIMPL;
  389. }
  390. STDMETHODIMP CContainer::GetDropTarget(IDropTarget *, IDropTarget **)
  391. {
  392.     return E_NOTIMPL;
  393. }
  394. STDMETHODIMP CContainer::GetExternal(IDispatch **ppDispatch)
  395. {
  396.     // return the IDispatch we have for extending the object Model
  397.     IDispatch* pDisp = (IDispatch*)this;
  398.     pDisp->AddRef();
  399.     *ppDispatch = pDisp;
  400.     return S_OK;
  401. }
  402.         
  403. STDMETHODIMP CContainer::TranslateUrl(DWORD, OLECHAR *, OLECHAR **)
  404. {
  405.     return E_NOTIMPL;
  406. }
  407.         
  408. STDMETHODIMP CContainer::FilterDataObject( IDataObject *, IDataObject **)
  409. {
  410.     return E_NOTIMPL;
  411. }
  412. // ***********************************************************************
  413. //  Public (non-interface) Methods
  414. // ***********************************************************************
  415. /**
  416.  *  This method will add an ActiveX control to the container. Note, for
  417.  *  now, this container can only have one control.
  418.  *
  419.  *  @param  bstrClsid   The CLSID or PROGID of the control.
  420.  *
  421.  *  @return             No return value.
  422.  */
  423. void CContainer::add(BSTR bstrClsid)
  424. {
  425.     CLSID   clsid;          // CLSID of the control object
  426.     HRESULT hr;             // return code
  427.     CLSIDFromString(bstrClsid, &clsid);
  428.     CoCreateInstance(clsid, 
  429.                      NULL, 
  430.                      CLSCTX_INPROC_SERVER | CLSCTX_LOCAL_SERVER, 
  431.                      IID_IUnknown,
  432.                      (PVOID *)&m_punk);
  433.     if (!m_punk)
  434.         return;
  435.     IOleObject *pioo;
  436.     hr = m_punk->QueryInterface(IID_IOleObject, (PVOID *)&pioo);
  437.     if (FAILED(hr))
  438.         return;
  439.     pioo->SetClientSite(this);
  440.     pioo->Release();
  441.     IPersistStreamInit  *ppsi;
  442.     hr = m_punk->QueryInterface(IID_IPersistStreamInit, (PVOID *)&ppsi);
  443.     if (SUCCEEDED(hr))
  444.     {
  445.         ppsi->InitNew();
  446.         ppsi->Release();
  447.     }
  448. }
  449. /**
  450.  *  This method will remove the control from the container.
  451.  *
  452.  *  @return             No return value.
  453.  */
  454. void CContainer::remove()
  455. {
  456.     if (!m_punk)
  457.         return;
  458.     HRESULT             hr;
  459.     IOleObject          *pioo;
  460.     IOleInPlaceObject   *pipo;
  461.     hr = m_punk->QueryInterface(IID_IOleObject, (PVOID *)&pioo);
  462.     if (SUCCEEDED(hr))
  463.     {
  464.         pioo->Close(OLECLOSE_NOSAVE);
  465.         pioo->SetClientSite(NULL);
  466.         pioo->Release();
  467.     }
  468.     hr = m_punk->QueryInterface(IID_IOleInPlaceObject, (PVOID *)&pipo);
  469.     if (SUCCEEDED(hr))
  470.     {
  471.         pipo->UIDeactivate();
  472.         pipo->InPlaceDeactivate();
  473.         pipo->Release();
  474.     }
  475.     m_punk->Release();
  476.     m_punk = NULL;
  477. }
  478. /**
  479.  *  This method sets the parent window. This is used by the container
  480.  *  so the control can parent itself.
  481.  *
  482.  *  @param  hwndParent  The parent window handle.
  483.  *
  484.  *  @return             No return value.
  485.  */
  486. void CContainer::setParent(HWND hwndParent)
  487. {
  488.     m_hwnd = hwndParent;
  489. }
  490. /**
  491.  *  This method will set the location of the control.
  492.  *  
  493.  *  @param      x       The top left.
  494.  *  @param      y       The top right.
  495.  *  @param      width   The width of the control.
  496.  *  @param      height  The height of the control.
  497.  */
  498. void CContainer::setLocation(int x, int y, int width, int height)
  499. {
  500.     m_rect.left     = x;
  501.     m_rect.top      = y;
  502.     m_rect.right    = width;
  503.     m_rect.bottom   = height;
  504.     if (!m_punk)
  505.         return;
  506.     HRESULT             hr;
  507.     IOleInPlaceObject   *pipo;
  508.     hr = m_punk->QueryInterface(IID_IOleInPlaceObject, (PVOID *)&pipo);
  509.     if (FAILED(hr))
  510.         return;
  511.     pipo->SetObjectRects(&m_rect, &m_rect);
  512.     pipo->Release();
  513. }
  514. /**
  515.  *  Sets the visible state of the control.
  516.  *
  517.  *  @param  fVisible    TRUE=visible, FALSE=hidden
  518.  *  @return             No return value.
  519.  */
  520. void CContainer::setVisible(BOOL fVisible)
  521. {
  522.     if (!m_punk)
  523.         return;
  524.     HRESULT     hr;
  525.     IOleObject  *pioo;
  526.     hr = m_punk->QueryInterface(IID_IOleObject, (PVOID *)&pioo);
  527.     if (FAILED(hr))
  528.         return;
  529.     
  530.     if (fVisible)
  531.     {
  532.         pioo->DoVerb(OLEIVERB_INPLACEACTIVATE, NULL, this, 0, m_hwnd, &m_rect);
  533.         pioo->DoVerb(OLEIVERB_SHOW, NULL, this, 0, m_hwnd, &m_rect);
  534.     }
  535.     else
  536.         pioo->DoVerb(OLEIVERB_HIDE, NULL, this, 0, m_hwnd, NULL);
  537.     pioo->Release();
  538. }
  539. /**
  540.  *  This sets the focus to the control (a.k.a. UIActivate)
  541.  *
  542.  *  @param  fFocus      TRUE=set, FALSE=remove
  543.  *
  544.  *  @return             No return value.
  545.  */
  546. void CContainer::setFocus(BOOL fFocus)
  547. {
  548.     if (!m_punk)
  549.         return;
  550.     HRESULT     hr;
  551.     IOleObject  *pioo;
  552.     if (fFocus)
  553.     {
  554.         hr = m_punk->QueryInterface(IID_IOleObject, (PVOID *)&pioo);
  555.         if (SUCCEEDED(hr))
  556.         {
  557.             pioo->DoVerb(OLEIVERB_UIACTIVATE, NULL, this, 0, m_hwnd, &m_rect);
  558.             pioo->Release();
  559.         }
  560.     }
  561. }
  562. /**
  563.  *  This method gives the control the opportunity to translate and use
  564.  *  key strokes.
  565.  *
  566.  *  @param      msg     Key message.
  567.  *
  568.  *  @return             No return value.
  569.  */
  570. void CContainer::translateKey(MSG msg)
  571. {
  572.     if (!m_punk)
  573.         return;
  574.     HRESULT                 hr;
  575.     IOleInPlaceActiveObject *pao;
  576.     hr = m_punk->QueryInterface(IID_IOleInPlaceActiveObject, (PVOID *)&pao);
  577.     if (FAILED(hr))
  578.         return;
  579.     pao->TranslateAccelerator(&msg);
  580.     pao->Release();
  581. }
  582. /**
  583.  *  Returns the IDispatch pointer of the contained control. Note, the
  584.  *  caller is responsible for calling IDispatch::Release().
  585.  *
  586.  *  @return             Controls dispatch interface.
  587.  */
  588. IDispatch * CContainer::getDispatch()
  589. {
  590.     if (!m_punk)
  591.         return NULL;
  592.     HRESULT     hr;
  593.     IDispatch   *pdisp;
  594.     hr = m_punk->QueryInterface(IID_IDispatch, (PVOID *)&pdisp);
  595.     return pdisp;
  596. }
  597. /**
  598.  *  Returns the IUnknown interface pointer for the containd control. Note,
  599.  *  the caller is responsible for calling IUnknown::Release().
  600.  *
  601.  *  @return             Controls unknown interface.
  602.  */
  603. IUnknown * CContainer::getUnknown()
  604. {
  605.     if (!m_punk)
  606.         return NULL;
  607.     m_punk->AddRef();
  608.     return m_punk;
  609. }