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

1628 lines
46 KiB

  1. //---------------------------------------------------------------------------
  2. //
  3. // Copyright (c) Microsoft Corporation
  4. //
  5. // File: olecontrol.cpp
  6. //
  7. // History:
  8. // 7-31-96 by dli
  9. //------------------------------------------------------------------------
  10. #include "priv.h"
  11. class COleControlHost;
  12. //---------------------------------------------------------------------------
  13. // Event sink
  14. class CEventSink : public IDispatch
  15. //---------------------------------------------------------------------------
  16. {
  17. public:
  18. CEventSink( BOOL bAutoDelete = FALSE ) ;
  19. // Connect/disconnect
  20. BOOL Connect( HWND hwndOwner, HWND hwndSite, LPUNKNOWN punkOC ) ;
  21. BOOL Disconnect() ;
  22. // IUnknown methods
  23. STDMETHOD (QueryInterface)( REFIID riid, void** ppvObj ) ;
  24. STDMETHOD_(ULONG, AddRef)() ;
  25. STDMETHOD_(ULONG, Release)() ;
  26. // IDispatch methods
  27. STDMETHOD (GetTypeInfoCount)( UINT *pctinfo )
  28. { return E_NOTIMPL ; }
  29. STDMETHOD (GetTypeInfo)( UINT iTInfo, LCID lcid, ITypeInfo **ppTInfo )
  30. { return E_NOTIMPL ; }
  31. STDMETHOD (GetIDsOfNames)( REFIID riid, LPOLESTR *rgszNames, UINT cNames,
  32. LCID lcid, DISPID *rgDispId )
  33. { return E_NOTIMPL ; }
  34. STDMETHOD (Invoke)(
  35. IN DISPID dispIdMember,
  36. IN REFIID riid,
  37. IN LCID lcid,
  38. IN WORD wFlags,
  39. IN OUT DISPPARAMS *pDispParams,
  40. OUT VARIANT *pVarResult,
  41. OUT EXCEPINFO *pExcepInfo,
  42. OUT UINT *puArgErr) ;
  43. private:
  44. static HRESULT _GetDefaultEventIID( LPUNKNOWN punkOC, IID* piid ) ;
  45. BOOL _Connect( HWND hwndOwner, HWND hwndSite, LPUNKNOWN punkOC, REFIID iid ) ;
  46. BOOL _IsConnected( REFIID iid ) ;
  47. ULONG _dwCookie ; // connection cookie
  48. IID _iid ; // connection interface
  49. IID _iidDefault ; // OC's default event dispatch interface
  50. LPUNKNOWN _punkOC ; // OC's unknown
  51. LONG _cRef ; // ref count
  52. HWND _hwndSite, //
  53. _hwndOwner ;
  54. BOOL _bAutoDelete ;
  55. } ;
  56. class CProxyUIHandler :
  57. public IDocHostUIHandler2
  58. {
  59. public:
  60. // *** IUnknown methods ***
  61. STDMETHODIMP QueryInterface(REFIID riid, LPVOID * ppvObj);
  62. STDMETHODIMP_(ULONG) AddRef(void);
  63. STDMETHODIMP_(ULONG) Release(void);
  64. // *** IDocHostUIHandler methods ***
  65. virtual STDMETHODIMP ShowContextMenu(DWORD dwID, POINT *ppt, IUnknown *pcmdtReserved, IDispatch *pdispReserved);
  66. virtual STDMETHODIMP GetHostInfo(DOCHOSTUIINFO *pInfo);
  67. virtual STDMETHODIMP ShowUI(DWORD dwID, IOleInPlaceActiveObject *pActiveObject, IOleCommandTarget *pCommandTarget, IOleInPlaceFrame *pFrame, IOleInPlaceUIWindow *pDoc);
  68. virtual STDMETHODIMP HideUI();
  69. virtual STDMETHODIMP UpdateUI();
  70. virtual STDMETHODIMP EnableModeless(BOOL fActivate);
  71. virtual STDMETHODIMP OnDocWindowActivate(BOOL fActivate);
  72. virtual STDMETHODIMP OnFrameWindowActivate(BOOL fActivate);
  73. virtual STDMETHODIMP ResizeBorder(LPCRECT prcBorder, IOleInPlaceUIWindow *pUIWindow, BOOL fRameWindow);
  74. virtual STDMETHODIMP TranslateAccelerator(LPMSG lpMsg, const GUID *pguidCmdGroup, DWORD nCmdID);
  75. virtual STDMETHODIMP GetOptionKeyPath(LPOLESTR *pchKey, DWORD dw);
  76. virtual STDMETHODIMP GetDropTarget(IDropTarget *pDropTarget, IDropTarget **ppDropTarget);
  77. virtual STDMETHODIMP GetExternal(IDispatch **ppDispatch);
  78. virtual STDMETHODIMP TranslateUrl(DWORD dwTranslate, OLECHAR *pchURLIn, OLECHAR **ppchURLOut);
  79. virtual STDMETHODIMP FilterDataObject( IDataObject *pDO, IDataObject **ppDORet);
  80. // *** IDocHostUIHandler2 methods ***
  81. virtual STDMETHODIMP GetOverrideKeyPath( LPOLESTR *pchKey, DWORD dw);
  82. };
  83. //---------------------------------------------------------------------------
  84. // Ole control container object
  85. class COleControlHost :
  86. public IOleClientSite,
  87. public IAdviseSink,
  88. public IOleInPlaceSite,
  89. public IOleInPlaceFrame,
  90. public IServiceProvider,
  91. public IOleCommandTarget,
  92. public IDispatch // For ambient properties
  93. {
  94. friend CProxyUIHandler;
  95. protected:
  96. static LRESULT CALLBACK OCHostWndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
  97. HRESULT _Draw(HDC hdc);
  98. HRESULT _PersistInit();
  99. HRESULT _Init();
  100. HRESULT _Activate();
  101. HRESULT _Deactivate();
  102. HRESULT _DoVerb(long iVerb, LPMSG lpMsg);
  103. HRESULT _Exit();
  104. HRESULT _InitOCStruct(LPOCHINITSTRUCT lpocs);
  105. LRESULT _OnPaint();
  106. LRESULT _OnSize(HWND hwnd, LPARAM lParam);
  107. LRESULT _OnCreate(HWND hwnd, LPCREATESTRUCT);
  108. LRESULT _OnDestroy();
  109. LRESULT _OnQueryInterface(WPARAM wParam, LPARAM lParam);
  110. LRESULT _SetOwner(IUnknown * punkOwner);
  111. LRESULT _ConnectEvents( LPUNKNOWN punkOC, BOOL bConnect ) ;
  112. LRESULT _SetServiceProvider(IServiceProvider* pSP);
  113. LRESULT _SendNotify(UINT code, LPNMHDR pnmhdr);
  114. // IUnknown
  115. UINT _cRef;
  116. DWORD _dwAspect;
  117. DWORD _dwMiscStatus; // OLE misc status
  118. DWORD _dwConnection; // Token for Advisory connections
  119. BOOL _bInPlaceActive; // Flag indicating if the OC is in place active
  120. HWND _hwnd;
  121. HWND _hwndParent;
  122. CLSID _clsidOC;
  123. IUnknown *_punkOC;
  124. IViewObject *_pIViewObject;
  125. IOleObject *_pIOleObject;
  126. IOleInPlaceObject *_pIOleIPObject;
  127. IUnknown *_punkOwner;
  128. CEventSink _eventSink ;
  129. CProxyUIHandler _xuih;
  130. IDocHostUIHandler *_pIDocHostUIParent;
  131. IDocHostUIHandler2 *_pIDocHostUIParent2;
  132. IDispatch *_pdispSiteDelegate;
  133. public:
  134. COleControlHost(HWND hwnd);
  135. static void _RegisterClass();
  136. // *** IUnknown methods ***
  137. STDMETHODIMP QueryInterface(REFIID riid, LPVOID * ppvObj);
  138. STDMETHODIMP_(ULONG) AddRef(void);
  139. STDMETHODIMP_(ULONG) Release(void);
  140. // IServiceProvider
  141. STDMETHODIMP QueryService(REFGUID guidService, REFIID riid, LPVOID* ppvObj);
  142. // *** IOleClientSite methods ***
  143. STDMETHOD (SaveObject)();
  144. STDMETHOD (GetMoniker)(DWORD, DWORD, LPMONIKER *);
  145. STDMETHOD (GetContainer)(LPOLECONTAINER *);
  146. STDMETHOD (ShowObject)();
  147. STDMETHOD (OnShowWindow)(BOOL);
  148. STDMETHOD (RequestNewObjectLayout)();
  149. // *** IAdviseSink methods ***
  150. STDMETHOD_(void,OnDataChange)(FORMATETC *, STGMEDIUM *);
  151. STDMETHOD_(void,OnViewChange)(DWORD, LONG);
  152. STDMETHOD_(void,OnRename)(LPMONIKER);
  153. STDMETHOD_(void,OnSave)();
  154. STDMETHOD_(void,OnClose)();
  155. // *** IOleWindow Methods ***
  156. STDMETHOD (GetWindow) (HWND * phwnd);
  157. STDMETHOD (ContextSensitiveHelp) (BOOL fEnterMode);
  158. // *** IOleInPlaceSite Methods ***
  159. STDMETHOD (CanInPlaceActivate) (void);
  160. STDMETHOD (OnInPlaceActivate) (void);
  161. STDMETHOD (OnUIActivate) (void);
  162. STDMETHOD (GetWindowContext) (IOleInPlaceFrame ** ppFrame, IOleInPlaceUIWindow ** ppDoc, LPRECT lprcPosRect, LPRECT lprcClipRect, LPOLEINPLACEFRAMEINFO lpFrameInfo);
  163. STDMETHOD (Scroll) (SIZE scrollExtent);
  164. STDMETHOD (OnUIDeactivate) (BOOL fUndoable);
  165. STDMETHOD (OnInPlaceDeactivate) (void);
  166. STDMETHOD (DiscardUndoState) (void);
  167. STDMETHOD (DeactivateAndUndo) (void);
  168. STDMETHOD (OnPosRectChange) (LPCRECT lprcPosRect);
  169. // IOleInPlaceUIWindow methods.
  170. STDMETHOD (GetBorder)(LPRECT lprectBorder);
  171. STDMETHOD (RequestBorderSpace)(LPCBORDERWIDTHS lpborderwidths);
  172. STDMETHOD (SetBorderSpace)(LPCBORDERWIDTHS lpborderwidths);
  173. STDMETHOD (SetActiveObject)(IOleInPlaceActiveObject * pActiveObject,
  174. LPCOLESTR lpszObjName);
  175. // IOleInPlaceFrame methods
  176. STDMETHOD (InsertMenus)(HMENU hmenuShared, LPOLEMENUGROUPWIDTHS lpMenuWidths);
  177. STDMETHOD (SetMenu)(HMENU hmenuShared, HOLEMENU holemenu, HWND hwndActiveObject);
  178. STDMETHOD (RemoveMenus)(HMENU hmenuShared);
  179. STDMETHOD (SetStatusText)(LPCOLESTR pszStatusText);
  180. STDMETHOD (EnableModeless)(BOOL fEnable);
  181. STDMETHOD (TranslateAccelerator)(LPMSG lpmsg, WORD wID);
  182. // IOleCommandTarget
  183. virtual STDMETHODIMP QueryStatus(const GUID *pguid, ULONG cCmds, MSOCMD rgCmds[], MSOCMDTEXT *pcmdtext);
  184. virtual STDMETHODIMP Exec(const GUID *pguid, DWORD nCmdID, DWORD nCmdexecopt, VARIANTARG *pvarargIn, VARIANTARG *pvarargOut);
  185. // IDispatch (for ambient properties)
  186. STDMETHODIMP GetTypeInfoCount(UINT* pctinfo);
  187. STDMETHODIMP GetTypeInfo(UINT iTInfo, LCID lcid, ITypeInfo** ppTInfo);
  188. STDMETHODIMP GetIDsOfNames(REFIID riid, LPOLESTR *rgszNames, UINT cNames,
  189. LCID lcid, DISPID *rgDispId);
  190. STDMETHODIMP Invoke(DISPID dispIdMember, REFIID riid,
  191. LCID lcid, WORD wFlags, DISPPARAMS *pDispParams, VARIANT *pvarResult,
  192. EXCEPINFO *pExcepInfo, UINT *puArgErr);
  193. };
  194. HRESULT COleControlHost::GetTypeInfoCount(UINT* pctinfo)
  195. {
  196. if (_pdispSiteDelegate)
  197. {
  198. return _pdispSiteDelegate->GetTypeInfoCount(pctinfo);
  199. }
  200. return E_NOTIMPL;
  201. }
  202. HRESULT COleControlHost::GetTypeInfo(UINT iTInfo, LCID lcid, ITypeInfo** ppTInfo)
  203. {
  204. if (_pdispSiteDelegate)
  205. {
  206. return _pdispSiteDelegate->GetTypeInfo(iTInfo, lcid, ppTInfo);
  207. }
  208. return E_NOTIMPL;
  209. }
  210. HRESULT COleControlHost::GetIDsOfNames(REFIID riid, LPOLESTR *rgszNames, UINT cNames,
  211. LCID lcid, DISPID *rgDispId)
  212. {
  213. if (_pdispSiteDelegate)
  214. {
  215. return _pdispSiteDelegate->GetIDsOfNames(riid, rgszNames, cNames, lcid, rgDispId);
  216. }
  217. return E_NOTIMPL;
  218. }
  219. HRESULT COleControlHost::Invoke(DISPID dispIdMember, REFIID riid,
  220. LCID lcid, WORD wFlags, DISPPARAMS *pDispParams, VARIANT *pvarResult,
  221. EXCEPINFO *pExcepInfo, UINT *puArgErr)
  222. {
  223. if (_pdispSiteDelegate)
  224. {
  225. return _pdispSiteDelegate->Invoke(dispIdMember, riid, lcid, wFlags, pDispParams, pvarResult, pExcepInfo, puArgErr);
  226. }
  227. return DISP_E_MEMBERNOTFOUND;
  228. }
  229. HRESULT COleControlHost::_Draw(HDC hdc)
  230. {
  231. HRESULT hr = E_FAIL;
  232. if (_hwnd && _punkOC && !_bInPlaceActive)
  233. {
  234. RECT rc;
  235. GetClientRect(_hwnd, &rc);
  236. hr = OleDraw(_punkOC, _dwAspect, hdc, &rc);
  237. }
  238. return(hr);
  239. }
  240. HRESULT COleControlHost::_PersistInit()
  241. {
  242. IPersistStreamInit * pIPersistStreamInit;
  243. if (_SendNotify(OCN_PERSISTINIT, NULL) == OCNPERSISTINIT_HANDLED)
  244. return S_FALSE;
  245. HRESULT hr = _punkOC->QueryInterface(IID_IPersistStreamInit, (void **)&pIPersistStreamInit);
  246. if (SUCCEEDED(hr))
  247. {
  248. hr = pIPersistStreamInit->InitNew();
  249. pIPersistStreamInit->Release();
  250. }
  251. else
  252. {
  253. IPersistStorage * pIPersistStorage;
  254. hr = _punkOC->QueryInterface(IID_IPersistStorage, (void **)&pIPersistStorage);
  255. if (SUCCEEDED(hr))
  256. {
  257. // Create a zero sized ILockBytes.
  258. ILockBytes *pILockBytes;
  259. hr = CreateILockBytesOnHGlobal(NULL, TRUE, &pILockBytes);
  260. if (SUCCEEDED(hr)) {
  261. // Use the ILockBytes to create a storage.
  262. IStorage *pIStorage;
  263. hr = StgCreateDocfileOnILockBytes(pILockBytes,
  264. STGM_CREATE |
  265. STGM_READWRITE |
  266. STGM_SHARE_EXCLUSIVE,
  267. 0, &pIStorage);
  268. if (SUCCEEDED(hr)) {
  269. // Call InitNew to initialize the object.
  270. hr = pIPersistStorage->InitNew(pIStorage);
  271. // Clean up
  272. pIStorage->Release();
  273. } // IStorage
  274. pILockBytes->Release();
  275. } // ILockBytes
  276. pIPersistStorage->Release();
  277. }
  278. }
  279. return hr;
  280. }
  281. HRESULT COleControlHost::_Init()
  282. {
  283. HRESULT hr = E_FAIL;
  284. OCNCOCREATEMSG ocm = {0};
  285. ocm.clsidOC = _clsidOC;
  286. ocm.ppunk = &_punkOC;
  287. if(_SendNotify(OCN_COCREATEINSTANCE, &ocm.nmhdr) != OCNCOCREATE_HANDLED)
  288. {
  289. hr = CoCreateInstance(_clsidOC, NULL, CLSCTX_INPROC_SERVER | CLSCTX_LOCAL_SERVER,
  290. IID_IUnknown, (LPVOID *)&_punkOC);
  291. if (FAILED(hr))
  292. {
  293. TraceMsg(TF_OCCONTROL, "_Init: Unable to CoCreateInstance this Class ID -- hr = %lX -- hr = %lX", _clsidOC, hr);
  294. return hr;
  295. }
  296. }
  297. ASSERT(_punkOC != NULL);
  298. if (_punkOC == NULL)
  299. return E_FAIL;
  300. hr = _punkOC->QueryInterface(IID_IOleObject, (void **)&_pIOleObject);
  301. if (FAILED(hr))
  302. {
  303. TraceMsg(TF_OCCONTROL, "_Init: Unable to QueryInterface IOleObject -- hr = %s", hr);
  304. return hr;
  305. }
  306. hr = _pIOleObject->GetMiscStatus(_dwAspect, &_dwMiscStatus);
  307. // Set the inplace active flag here
  308. // If this fails, we will assume that we can setclientsite later
  309. if (_dwMiscStatus & OLEMISC_SETCLIENTSITEFIRST)
  310. {
  311. hr = _pIOleObject->SetClientSite(this);
  312. _PersistInit();
  313. }
  314. else
  315. {
  316. _PersistInit();
  317. hr = _pIOleObject->SetClientSite(this);
  318. }
  319. if (FAILED(hr))
  320. {
  321. TraceMsg(TF_OCCONTROL, "_Init: Unable to set client site -- hr = %lX", hr);
  322. return hr;
  323. }
  324. if (SUCCEEDED(_punkOC->QueryInterface(IID_IViewObject, (void **)&_pIViewObject)))
  325. {
  326. _pIViewObject->SetAdvise(_dwAspect, 0, this);
  327. }
  328. //FEATURE: this is not really useful because we do not handle the cases, yet
  329. _pIOleObject->Advise(this, &_dwConnection);
  330. _pIOleObject->SetHostNames(TEXTW("OC Host Window"), TEXTW("OC Host Window"));
  331. return S_OK;
  332. }
  333. //
  334. HRESULT COleControlHost::_Activate()
  335. {
  336. HRESULT hr = E_FAIL;
  337. RECT rcClient;
  338. ASSERT(_hwnd);
  339. _SendNotify(OCN_ACTIVATE, NULL);
  340. if (!GetClientRect(_hwnd, &rcClient))
  341. SetRectEmpty(&rcClient);
  342. hr = _pIOleObject->DoVerb(OLEIVERB_INPLACEACTIVATE, NULL, this, 0, _hwnd, &rcClient);
  343. if (SUCCEEDED(hr))
  344. _bInPlaceActive = TRUE;
  345. // Calling second DoVerb with OLEIVERB_SHOW because:
  346. // 1. If the above DoVerb fails, this is a back up activation call
  347. // 2. If the above DoVerb succeeds, this is also necessary because
  348. // Some embeddings needs to be explicitly told to show themselves.
  349. if (!(_dwMiscStatus & OLEMISC_INVISIBLEATRUNTIME))
  350. hr = _pIOleObject->DoVerb(OLEIVERB_SHOW, NULL, this, 0, _hwnd, &rcClient);
  351. if (FAILED(hr))
  352. TraceMsg(TF_OCCONTROL, "_Activate: %d Unable to DoVerb! Error = %lX", _bInPlaceActive, hr);
  353. return hr;
  354. }
  355. HRESULT COleControlHost::_Deactivate()
  356. {
  357. _SendNotify(OCN_DEACTIVATE, NULL);
  358. if (_pIOleIPObject)
  359. {
  360. _pIOleIPObject->InPlaceDeactivate();
  361. // Should be set to NULL by the above function call
  362. ASSERT(_pIOleIPObject == NULL);
  363. return S_OK;
  364. }
  365. return S_FALSE;
  366. }
  367. HRESULT COleControlHost::_DoVerb(long iVerb, LPMSG lpMsg)
  368. {
  369. HRESULT hr = E_FAIL;
  370. RECT rcClient;
  371. ASSERT(_hwnd && IsWindow(_hwnd));
  372. if (!GetClientRect(_hwnd, &rcClient))
  373. SetRectEmpty(&rcClient);
  374. hr = _pIOleObject->DoVerb(iVerb, lpMsg, this, 0, _hwnd, &rcClient);
  375. if (SUCCEEDED(hr))
  376. _bInPlaceActive = TRUE;
  377. #if 0 // we'll count on DocHost::DoVerb to do this if needed (or our caller?)
  378. // note that DocHost does this always (no OLEMISC_* check)
  379. if (iVerb == OLEIVERB_INPLACEACTIVATE) {
  380. // Calling second DoVerb with OLEIVERB_SHOW because:
  381. // 1. If the above DoVerb fails, this is a back up activation call
  382. // 2. If the above DoVerb succeeds, this is also necessary because
  383. // Some embeddings needs to be explicitly told to show themselves.
  384. if (!(_dwMiscStatus & OLEMISC_INVISIBLEATRUNTIME))
  385. hr = _pIOleObject->DoVerb(OLEIVERB_SHOW, lpMsg, this, 0, _hwnd, &rcClient);
  386. }
  387. #endif
  388. if (FAILED(hr))
  389. TraceMsg(TF_OCCONTROL, "_Activate: %d Unable to DoVerb! Error = %lX", _bInPlaceActive, hr);
  390. return hr;
  391. }
  392. // Clean up and Release all of interface pointers used in this object
  393. HRESULT COleControlHost::_Exit()
  394. {
  395. _SendNotify(OCN_EXIT, NULL);
  396. if (_pIViewObject)
  397. {
  398. _pIViewObject->SetAdvise(_dwAspect, 0, NULL);
  399. _pIViewObject->Release();
  400. _pIViewObject = NULL;
  401. }
  402. if (_pIOleObject)
  403. {
  404. if (_dwConnection)
  405. {
  406. _pIOleObject->Unadvise(_dwConnection);
  407. _dwConnection = 0;
  408. }
  409. _pIOleObject->Close(OLECLOSE_NOSAVE);
  410. _pIOleObject->SetClientSite(NULL);
  411. _pIOleObject->Release();
  412. _pIOleObject = NULL;
  413. }
  414. if (_punkOC)
  415. {
  416. ULONG ulRef;
  417. ulRef = _punkOC->Release();
  418. _punkOC = NULL;
  419. if (ulRef != 0)
  420. TraceMsg(TF_OCCONTROL, "OCHOST _Exit: After last release ref = %d > 0", ulRef);
  421. }
  422. ATOMICRELEASE(_pIDocHostUIParent);
  423. ATOMICRELEASE(_pIDocHostUIParent2);
  424. if (_punkOwner) {
  425. _punkOwner->Release();
  426. _punkOwner = NULL;
  427. }
  428. if (_pdispSiteDelegate) {
  429. _pdispSiteDelegate->Release();
  430. _pdispSiteDelegate = NULL;
  431. }
  432. return S_OK;
  433. }
  434. COleControlHost::COleControlHost(HWND hwnd)
  435. : _cRef(1), _dwAspect(DVASPECT_CONTENT), _hwnd(hwnd)
  436. {
  437. // These variables should be initialized to zeros automatically
  438. ASSERT(_dwMiscStatus == 0);
  439. ASSERT(_dwConnection == 0);
  440. ASSERT(_bInPlaceActive == FALSE);
  441. ASSERT(_pIDocHostUIParent == NULL);
  442. ASSERT(_pIDocHostUIParent2 == NULL);
  443. ASSERT(_clsidOC == CLSID_NULL);
  444. ASSERT(_punkOC == NULL);
  445. ASSERT(_pIViewObject == NULL);
  446. ASSERT(_pIOleIPObject == NULL);
  447. ASSERT(_pdispSiteDelegate == NULL);
  448. ASSERT(_hwnd);
  449. }
  450. #ifdef DEBUG
  451. #define _AddRef(psz) { ++_cRef; TraceMsg(TF_OCCONTROL, "CDocObjectHost(%x)::QI(%s) is AddRefing _cRef=%lX", this, psz, _cRef); }
  452. #else
  453. #define _AddRef(psz) ++_cRef
  454. #endif
  455. // *** IUnknown Methods ***
  456. HRESULT COleControlHost::QueryInterface(REFIID riid, LPVOID * ppvObj)
  457. {
  458. // ppvObj must not be NULL
  459. ASSERT(ppvObj != NULL);
  460. if (ppvObj == NULL)
  461. return E_INVALIDARG;
  462. *ppvObj = NULL;
  463. if ((IsEqualIID(riid, IID_IUnknown)) ||
  464. (IsEqualIID(riid, IID_IOleWindow)) ||
  465. (IsEqualIID(riid, IID_IOleInPlaceUIWindow)) ||
  466. (IsEqualIID(riid, IID_IOleInPlaceFrame)))
  467. {
  468. *ppvObj = SAFECAST(this, IOleInPlaceFrame *);
  469. TraceMsg(TF_OCCONTROL, "QI IOleInPlaceFrame succeeded");
  470. }
  471. else if (IsEqualIID(riid, IID_IServiceProvider))
  472. {
  473. *ppvObj = SAFECAST(this, IServiceProvider *);
  474. TraceMsg(TF_OCCONTROL, "QI IServiceProvider succeeded");
  475. }
  476. else if (IsEqualIID(riid, IID_IOleClientSite))
  477. {
  478. *ppvObj = SAFECAST(this, IOleClientSite *);
  479. TraceMsg(TF_OCCONTROL, "QI IOleClientSite succeeded");
  480. }
  481. else if (IsEqualIID(riid, IID_IAdviseSink))
  482. {
  483. *ppvObj = SAFECAST(this, IAdviseSink *);
  484. TraceMsg(TF_OCCONTROL, "QI IAdviseSink succeeded");
  485. }
  486. else if (IsEqualIID(riid, IID_IOleInPlaceSite))
  487. {
  488. *ppvObj = SAFECAST(this, IOleInPlaceSite *);
  489. TraceMsg(TF_OCCONTROL, "QI IOleInPlaceSite succeeded");
  490. }
  491. else if (IsEqualIID(riid, IID_IOleCommandTarget))
  492. {
  493. *ppvObj = SAFECAST(this, IOleCommandTarget *);
  494. TraceMsg(TF_OCCONTROL, "QI IOleCommandTarget succeeded");
  495. }
  496. else if (NULL != _pIDocHostUIParent &&
  497. IsEqualIID(riid, IID_IDocHostUIHandler))
  498. {
  499. // only implement this if the host implements it
  500. *ppvObj = SAFECAST(&_xuih, IDocHostUIHandler *);
  501. TraceMsg(TF_OCCONTROL, "QI IDocHostUIHandler succeeded");
  502. }
  503. else if (NULL != _pIDocHostUIParent2 &&
  504. IsEqualIID(riid, IID_IDocHostUIHandler2))
  505. {
  506. // only implement this if the host implements it
  507. *ppvObj = SAFECAST(&_xuih, IDocHostUIHandler2 *);
  508. TraceMsg(TF_OCCONTROL, "QI IDocHostUIHandler2 succeeded");
  509. }
  510. else if (IsEqualIID(riid, IID_IDispatch))
  511. {
  512. *ppvObj = SAFECAST(this, IDispatch *);
  513. TraceMsg(TF_OCCONTROL, "QI IDispatch succeeded");
  514. }
  515. else
  516. return E_NOINTERFACE; // Otherwise, don't delegate to HTMLObj!!
  517. _AddRef(TEXT("IOleInPlaceSite"));
  518. return S_OK;
  519. }
  520. ULONG COleControlHost::AddRef()
  521. {
  522. _cRef++;
  523. TraceMsg(TF_OCCONTROL, "COleControlHost(%x)::AddRef called, new _cRef=%lX", this, _cRef);
  524. return _cRef;
  525. }
  526. ULONG COleControlHost::Release()
  527. {
  528. _cRef--;
  529. TraceMsg(TF_OCCONTROL, "COleControlHost(%x)::Release called, new _cRef=%lX", this, _cRef);
  530. if (_cRef > 0)
  531. return _cRef;
  532. delete this;
  533. return 0;
  534. }
  535. // ServiceProvider interfaces
  536. HRESULT COleControlHost::QueryService(REFGUID guidService,
  537. REFIID riid, void **ppvObj)
  538. {
  539. HRESULT hres = E_FAIL;
  540. *ppvObj = NULL;
  541. if (_punkOwner) {
  542. IServiceProvider *psp;
  543. _punkOwner->QueryInterface(IID_IServiceProvider, (LPVOID*)&psp);
  544. if (psp) {
  545. hres = psp->QueryService(guidService, riid, ppvObj);
  546. psp->Release();
  547. }
  548. }
  549. return hres;
  550. }
  551. // ************************ IOleClientSite methods ******************
  552. HRESULT COleControlHost::SaveObject()
  553. {
  554. //FEATURE: default set to E_NOTIMPL may not be correct
  555. HRESULT hr = E_NOTIMPL;
  556. IStorage * pIs;
  557. if (SUCCEEDED(_punkOC->QueryInterface(IID_IStorage, (void **)&pIs)))
  558. {
  559. IPersistStorage *pIps;
  560. if (SUCCEEDED(_punkOC->QueryInterface(IID_IPersistStorage, (void **)&pIps)))
  561. {
  562. OleSave(pIps, pIs, TRUE);
  563. pIps->SaveCompleted(NULL);
  564. pIps->Release();
  565. hr = S_OK;
  566. }
  567. pIs->Release();
  568. }
  569. return hr;
  570. }
  571. HRESULT COleControlHost::GetMoniker(DWORD dwAssign, DWORD dwWhichMoniker, LPMONIKER * ppMk)
  572. {
  573. return E_NOTIMPL;
  574. }
  575. HRESULT COleControlHost::GetContainer(LPOLECONTAINER * ppContainer)
  576. {
  577. *ppContainer = NULL;
  578. return E_NOINTERFACE;
  579. }
  580. HRESULT COleControlHost::ShowObject()
  581. {
  582. // RECTL rcl;
  583. // POINT pt1, pt2;
  584. return S_OK;
  585. }
  586. HRESULT COleControlHost::OnShowWindow(BOOL fShow)
  587. {
  588. return S_OK;
  589. }
  590. HRESULT COleControlHost::RequestNewObjectLayout()
  591. {
  592. return E_NOTIMPL;
  593. }
  594. // ************************ IAdviseSink methods *********************
  595. void COleControlHost::OnDataChange(FORMATETC * pFmt, STGMEDIUM * pStgMed)
  596. {
  597. // NOTES: This is optional
  598. return;
  599. }
  600. void COleControlHost::OnViewChange(DWORD dwAspect, LONG lIndex)
  601. {
  602. // FEATURE: need to let the container know the colors might have changed
  603. // but don't want to deal with the paletts now
  604. // Draw only if not inplace active and this is the right aspect. Inplace
  605. // active objects have their own window and are responsible for painting
  606. // themselves.
  607. // WARNING: _bInPlaceActive is not determined, yet.
  608. // This funtion is called as a result of calling doverb, however,
  609. // _bInPlaceActive will only be determined as DoVerb returns
  610. // works fine for now, but could be trouble later.
  611. if ((_hwnd) && (!_bInPlaceActive) && (dwAspect == _dwAspect))
  612. {
  613. HDC hdc = GetDC(_hwnd);
  614. if (hdc)
  615. {
  616. _Draw(hdc);
  617. ReleaseDC(_hwnd, hdc);
  618. }
  619. }
  620. }
  621. void COleControlHost::OnRename(LPMONIKER pMoniker)
  622. {
  623. return;
  624. }
  625. void COleControlHost::OnSave()
  626. {
  627. // NOTES: This is optional
  628. return;
  629. }
  630. void COleControlHost::OnClose()
  631. {
  632. // FEATURE: need to let the container know the colors might have changed
  633. return;
  634. }
  635. // ************************ IOleWindow Methods **********************
  636. HRESULT COleControlHost::GetWindow(HWND * lphwnd)
  637. {
  638. *lphwnd = _hwnd;
  639. return S_OK;
  640. }
  641. HRESULT COleControlHost::ContextSensitiveHelp(BOOL fEnterMode)
  642. {
  643. // NOTES: This is optional
  644. return E_NOTIMPL;
  645. }
  646. // *********************** IOleInPlaceSite Methods *****************
  647. HRESULT COleControlHost::CanInPlaceActivate(void)
  648. {
  649. return S_OK;
  650. }
  651. HRESULT COleControlHost::OnInPlaceActivate(void)
  652. {
  653. if (!_pIOleIPObject)
  654. return (_punkOC->QueryInterface(IID_IOleInPlaceObject, (void **)&_pIOleIPObject));
  655. else
  656. return S_OK;
  657. }
  658. HRESULT COleControlHost::OnUIActivate(void)
  659. {
  660. LRESULT lres;
  661. OCNONUIACTIVATEMSG oam = {0};
  662. oam.punk = _punkOC;
  663. lres = _SendNotify(OCN_ONUIACTIVATE, &oam.nmhdr);
  664. return S_OK;
  665. }
  666. HRESULT COleControlHost::GetWindowContext (IOleInPlaceFrame ** ppFrame, IOleInPlaceUIWindow ** ppIIPUIWin,
  667. LPRECT lprcPosRect, LPRECT lprcClipRect, LPOLEINPLACEFRAMEINFO lpFrameInfo)
  668. {
  669. *ppFrame = this;
  670. _AddRef("GetWindowContext");
  671. // This is set to NULL because the document window is the same as the frame
  672. // window
  673. *ppIIPUIWin = NULL;
  674. ASSERT(_hwnd);
  675. if (!GetClientRect(_hwnd, lprcPosRect))
  676. SetRectEmpty(lprcPosRect);
  677. // Set the clip rectangle to be the same as the position rectangle
  678. CopyRect(lprcClipRect, lprcPosRect);
  679. lpFrameInfo->cb = sizeof(OLEINPLACEFRAMEINFO);
  680. #ifdef MDI
  681. lpFrameInfo->fMDIApp = TRUE;
  682. #else
  683. lpFrameInfo->fMDIApp = FALSE;
  684. #endif
  685. lpFrameInfo->hwndFrame = _hwnd;
  686. lpFrameInfo->haccel = 0;
  687. lpFrameInfo->cAccelEntries = 0;
  688. return S_OK;
  689. }
  690. HRESULT COleControlHost::Scroll(SIZE scrollExtent)
  691. {
  692. // Should implement later
  693. return E_NOTIMPL;
  694. }
  695. HRESULT COleControlHost::OnUIDeactivate(BOOL fUndoable)
  696. {
  697. return E_NOTIMPL;
  698. }
  699. HRESULT COleControlHost::OnInPlaceDeactivate(void)
  700. {
  701. if (_pIOleIPObject)
  702. {
  703. _pIOleIPObject->Release();
  704. _pIOleIPObject = NULL;
  705. }
  706. return S_OK;
  707. }
  708. HRESULT COleControlHost::DiscardUndoState(void)
  709. {
  710. // Should implement later
  711. return E_NOTIMPL;
  712. }
  713. HRESULT COleControlHost::DeactivateAndUndo(void)
  714. {
  715. // Should implement later
  716. return E_NOTIMPL;
  717. }
  718. HRESULT COleControlHost::OnPosRectChange(LPCRECT lprcPosRect)
  719. {
  720. // We do not allow the children to change the size themselves
  721. OCNONPOSRECTCHANGEMSG opcm = {0};
  722. opcm.prcPosRect = lprcPosRect;
  723. _SendNotify(OCN_ONPOSRECTCHANGE, &opcm.nmhdr);
  724. return S_OK;
  725. }
  726. // ************************ IOleInPlaceUIWindow methods *************
  727. HRESULT COleControlHost::GetBorder(LPRECT lprectBorder)
  728. {
  729. return E_NOTIMPL;
  730. }
  731. HRESULT COleControlHost::RequestBorderSpace(LPCBORDERWIDTHS lpborderwidths)
  732. {
  733. return E_NOTIMPL;
  734. }
  735. HRESULT COleControlHost::SetBorderSpace(LPCBORDERWIDTHS lpborderwidths)
  736. {
  737. return E_NOTIMPL;
  738. }
  739. HRESULT COleControlHost::SetActiveObject(IOleInPlaceActiveObject * pActiveObject,
  740. LPCOLESTR lpszObjName)
  741. {
  742. return E_NOTIMPL;
  743. }
  744. // *********************** IOleInPlaceFrame Methods *****************
  745. HRESULT COleControlHost::InsertMenus(HMENU hmenuShared, LPOLEMENUGROUPWIDTHS lpMenuWidths)
  746. {
  747. // Should implement later
  748. return E_NOTIMPL;
  749. }
  750. HRESULT COleControlHost::SetMenu(HMENU hmenuShared, HOLEMENU holemenu, HWND hwndActiveObject)
  751. {
  752. // Should implement later
  753. return E_NOTIMPL;
  754. }
  755. HRESULT COleControlHost::RemoveMenus(HMENU hmenuShared)
  756. {
  757. // Should implement later
  758. return E_NOTIMPL;
  759. }
  760. HRESULT COleControlHost::SetStatusText(LPCOLESTR pszStatusText)
  761. {
  762. OCNONSETSTATUSTEXTMSG osst = {0};
  763. osst.pwszStatusText = pszStatusText;
  764. _SendNotify(OCN_ONSETSTATUSTEXT, &osst.nmhdr);
  765. return S_OK;
  766. }
  767. HRESULT COleControlHost::EnableModeless(BOOL fEnable)
  768. {
  769. // Should implement later
  770. return E_NOTIMPL;
  771. }
  772. HRESULT COleControlHost::TranslateAccelerator(LPMSG lpmsg, WORD wID)
  773. {
  774. // Should implement later
  775. return E_NOTIMPL;
  776. }
  777. // ************************ IOleCommandTarget Methods *************
  778. HRESULT COleControlHost::QueryStatus(const GUID *pguid, ULONG cCmds, MSOCMD rgCmds[], MSOCMDTEXT *pcmdtext)
  779. {
  780. return IUnknown_QueryStatus(_punkOwner, pguid, cCmds, rgCmds, pcmdtext);
  781. }
  782. HRESULT COleControlHost::Exec(const GUID *pguid, DWORD nCmdID, DWORD nCmdexecopt, VARIANTARG *pvarargIn, VARIANTARG *pvarargOut)
  783. {
  784. return IUnknown_Exec(_punkOwner, pguid, nCmdID, nCmdexecopt, pvarargIn, pvarargOut);
  785. }
  786. HRESULT COleControlHost::_InitOCStruct(LPOCHINITSTRUCT lpocs)
  787. {
  788. HRESULT hres = E_FAIL;
  789. if (_punkOC)
  790. return S_FALSE;
  791. if (lpocs)
  792. {
  793. if (lpocs->cbSize != SIZEOF(OCHINITSTRUCT))
  794. return hres;
  795. if (lpocs->clsidOC == CLSID_NULL)
  796. return hres;
  797. _clsidOC = lpocs->clsidOC;
  798. _SetOwner(lpocs->punkOwner);
  799. }
  800. else
  801. return hres;
  802. hres = _Init();
  803. if (SUCCEEDED(hres))
  804. hres = _Activate();
  805. return hres;
  806. }
  807. LRESULT COleControlHost::_OnPaint()
  808. {
  809. ASSERT(_hwnd);
  810. PAINTSTRUCT ps;
  811. HDC hdc = BeginPaint(_hwnd, &ps);
  812. _Draw(hdc);
  813. EndPaint(_hwnd, &ps);
  814. return 0;
  815. }
  816. LRESULT COleControlHost::_OnSize(HWND hwnd, LPARAM lParam)
  817. {
  818. if (_pIOleIPObject)
  819. {
  820. RECT rcPos, rcClip ;
  821. SetRect( &rcPos, 0, 0, LOWORD(lParam), HIWORD(lParam) ) ;
  822. rcClip = rcPos ;
  823. _pIOleIPObject->SetObjectRects(&rcPos, &rcClip);
  824. }
  825. return 0;
  826. }
  827. LRESULT COleControlHost::_OnCreate(HWND hwnd, LPCREATESTRUCT lpcs)
  828. {
  829. TCHAR szClsid[50];
  830. _hwndParent = GetParent(hwnd);
  831. SetWindowLongPtr(hwnd, 0, (LONG_PTR)this);
  832. LPOCHINITSTRUCT lpois = (LPOCHINITSTRUCT)lpcs->lpCreateParams;
  833. HRESULT hres = S_OK;
  834. if (lpois)
  835. hres = _InitOCStruct(lpois);
  836. else if (GetWindowText(hwnd, szClsid, ARRAYSIZE(szClsid)))
  837. {
  838. OCHINITSTRUCT ois;
  839. ois.cbSize = SIZEOF(OCHINITSTRUCT);
  840. if (FAILED(SHCLSIDFromString(szClsid, &ois.clsidOC)))
  841. ois.clsidOC = CLSID_NULL;
  842. ois.punkOwner = NULL;
  843. hres = _InitOCStruct(&ois);
  844. }
  845. if (FAILED(hres))
  846. return -1;
  847. return 0;
  848. }
  849. LRESULT COleControlHost::_OnDestroy()
  850. {
  851. ASSERT(_hwnd);
  852. SetWindowLongPtr(_hwnd, 0, 0);
  853. _ConnectEvents( _punkOC, FALSE ) ;
  854. _Deactivate();
  855. _Exit();
  856. Release();
  857. return 0;
  858. }
  859. LRESULT COleControlHost::_OnQueryInterface(WPARAM wParam, LPARAM lParam)
  860. {
  861. if (lParam)
  862. {
  863. QIMSG * qiMsg = (QIMSG *)lParam;
  864. return _punkOC->QueryInterface(*qiMsg->qiid, qiMsg->ppvObject);
  865. }
  866. return -1;
  867. }
  868. LRESULT COleControlHost::_SetOwner(IUnknown * punkNewOwner)
  869. {
  870. if (_punkOwner)
  871. _punkOwner->Release();
  872. _punkOwner = punkNewOwner;
  873. if (_punkOwner)
  874. _punkOwner->AddRef();
  875. ATOMICRELEASE(_pIDocHostUIParent);
  876. ATOMICRELEASE(_pIDocHostUIParent2);
  877. // Query if owner supports IDocHostUIHandler, if so then
  878. // we turn on our delegating wrapper
  879. if (punkNewOwner)
  880. {
  881. punkNewOwner->QueryInterface(IID_IDocHostUIHandler, (LPVOID *)&_pIDocHostUIParent);
  882. punkNewOwner->QueryInterface(IID_IDocHostUIHandler2, (LPVOID *)&_pIDocHostUIParent2);
  883. }
  884. return 0;
  885. }
  886. LRESULT COleControlHost::_ConnectEvents( LPUNKNOWN punkOC, BOOL bConnect )
  887. {
  888. if( bConnect )
  889. {
  890. ASSERT( punkOC ) ;
  891. return _eventSink.Connect( _hwndParent, _hwnd, punkOC ) ;
  892. }
  893. return _eventSink.Disconnect() ;
  894. }
  895. LRESULT COleControlHost::_SetServiceProvider(IServiceProvider* pSP)
  896. {
  897. // Free any existing delegates
  898. if (_pdispSiteDelegate)
  899. {
  900. _pdispSiteDelegate->Release();
  901. }
  902. // For now, we just delegate IDispatch (Ambient properties) calls
  903. HRESULT hr = pSP->QueryService(SID_OleControlSite, IID_PPV_ARG(IDispatch, &_pdispSiteDelegate));
  904. if (FAILED(hr))
  905. {
  906. _pdispSiteDelegate = NULL;
  907. }
  908. return 0;
  909. }
  910. LRESULT COleControlHost::_SendNotify(UINT code, LPNMHDR pnmhdr)
  911. {
  912. NMHDR nmhdr;
  913. ASSERT(_hwnd);
  914. if (!_hwndParent)
  915. return 0;
  916. if (!pnmhdr)
  917. pnmhdr = &nmhdr;
  918. pnmhdr->hwndFrom = _hwnd;
  919. pnmhdr->idFrom = GetDlgCtrlID( _hwnd ) ;
  920. pnmhdr->code = code;
  921. return SendMessage(_hwndParent, WM_NOTIFY, 0, (LPARAM)pnmhdr);
  922. }
  923. LRESULT CALLBACK COleControlHost::OCHostWndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
  924. {
  925. COleControlHost *pcoch = (COleControlHost *)GetWindowPtr(hwnd, 0);
  926. if (!pcoch && (uMsg != WM_CREATE))
  927. return DefWindowProcWrap(hwnd, uMsg, wParam, lParam);
  928. switch(uMsg)
  929. {
  930. case WM_CREATE:
  931. pcoch = new COleControlHost(hwnd);
  932. if (pcoch)
  933. return pcoch->_OnCreate(hwnd, (LPCREATESTRUCT)lParam);
  934. return -1;
  935. case WM_ERASEBKGND:
  936. if (pcoch->_punkOC && pcoch->_bInPlaceActive)
  937. {
  938. // Now tell windows we don't need no stinkin'
  939. // erased background because our view object
  940. // is in-place active and he/she will be
  941. // taking over from here.
  942. return TRUE;
  943. }
  944. break;
  945. case WM_PAINT:
  946. return pcoch->_OnPaint();
  947. case WM_SIZE:
  948. return pcoch->_OnSize(hwnd, lParam);
  949. case WM_DESTROY:
  950. return pcoch->_OnDestroy();
  951. case OCM_QUERYINTERFACE:
  952. return pcoch->_OnQueryInterface(wParam, lParam);
  953. case OCM_INITIALIZE:
  954. return pcoch->_InitOCStruct((LPOCHINITSTRUCT)lParam);
  955. case OCM_SETOWNER:
  956. return pcoch->_SetOwner((IUnknown*)lParam);
  957. case OCM_DOVERB:
  958. return pcoch->_DoVerb((long)wParam, (LPMSG)lParam);
  959. case OCM_ENABLEEVENTS:
  960. return pcoch->_ConnectEvents( pcoch->_punkOC, (BOOL)wParam ) ;
  961. case OCM_SETSERVICEPROVIDER:
  962. return pcoch->_SetServiceProvider((IServiceProvider*) lParam);
  963. case WM_PALETTECHANGED:
  964. if (pcoch->_pIOleIPObject) {
  965. HWND hwnd;
  966. if (SUCCEEDED(pcoch->_pIOleIPObject->GetWindow(&hwnd))) {
  967. SendMessage(hwnd, WM_PALETTECHANGED, wParam, lParam);
  968. }
  969. }
  970. break;
  971. case WM_SETFOCUS:
  972. // OC doesn't respond to OLEIVERB_UIACTIVATE ?
  973. if( pcoch->_dwMiscStatus & OLEMISC_NOUIACTIVATE )
  974. {
  975. // so explicitly assign focus
  976. HWND hwndObj ;
  977. if( pcoch->_pIOleIPObject &&
  978. SUCCEEDED( pcoch->_pIOleIPObject->GetWindow( &hwndObj ) ) )
  979. SetFocus( hwndObj ) ;
  980. }
  981. else
  982. pcoch->_DoVerb( OLEIVERB_UIACTIVATE, NULL ) ;
  983. break ;
  984. default:
  985. return DefWindowProcWrap(hwnd, uMsg, wParam, lParam);
  986. }
  987. return 0;
  988. }
  989. void COleControlHost::_RegisterClass()
  990. {
  991. WNDCLASS wc = {0};
  992. wc.style = CS_GLOBALCLASS;
  993. wc.lpfnWndProc = OCHostWndProc;
  994. //wc.cbClsExtra = 0;
  995. wc.cbWndExtra = SIZEOF(LPVOID);
  996. wc.hInstance = HINST_THISDLL;
  997. //wc.hIcon = NULL;
  998. wc.hCursor = LoadCursor (NULL, IDC_ARROW);
  999. wc.hbrBackground = (HBRUSH) (COLOR_BACKGROUND + 1);
  1000. //wc.lpszMenuName = NULL;
  1001. wc.lpszClassName = OCHOST_CLASS;
  1002. SHRegisterClass(&wc);
  1003. }
  1004. HRESULT CProxyUIHandler::QueryInterface(REFIID riid, LPVOID * ppvObj)
  1005. {
  1006. COleControlHost *poch = IToClass(COleControlHost, _xuih, this);
  1007. return poch->QueryInterface(riid, ppvObj);
  1008. };
  1009. ULONG CProxyUIHandler::AddRef(void)
  1010. {
  1011. COleControlHost *poch = IToClass(COleControlHost, _xuih, this);
  1012. return poch->AddRef();
  1013. };
  1014. ULONG CProxyUIHandler::Release(void)
  1015. {
  1016. COleControlHost *poch = IToClass(COleControlHost, _xuih, this);
  1017. return poch->Release();
  1018. };
  1019. HRESULT CProxyUIHandler::ShowContextMenu(DWORD dwID, POINT *ppt, IUnknown *pcmdtReserved, IDispatch *pdispReserved)
  1020. {
  1021. COleControlHost *poch = IToClass(COleControlHost, _xuih, this);
  1022. return poch->_pIDocHostUIParent ? poch->_pIDocHostUIParent->ShowContextMenu(dwID, ppt, pcmdtReserved, pdispReserved) : E_NOTIMPL;
  1023. }
  1024. HRESULT CProxyUIHandler::GetHostInfo(DOCHOSTUIINFO *pInfo)
  1025. {
  1026. COleControlHost *poch = IToClass(COleControlHost, _xuih, this);
  1027. return poch->_pIDocHostUIParent ? poch->_pIDocHostUIParent->GetHostInfo(pInfo) : E_NOTIMPL;
  1028. }
  1029. HRESULT CProxyUIHandler::ShowUI(DWORD dwID, IOleInPlaceActiveObject *pActiveObject, IOleCommandTarget *pCommandTarget, IOleInPlaceFrame *pFrame, IOleInPlaceUIWindow *pDoc)
  1030. {
  1031. COleControlHost *poch = IToClass(COleControlHost, _xuih, this);
  1032. return poch->_pIDocHostUIParent ? poch->_pIDocHostUIParent->ShowUI(dwID, pActiveObject, pCommandTarget, pFrame, pDoc): E_NOTIMPL;
  1033. }
  1034. HRESULT CProxyUIHandler::HideUI()
  1035. {
  1036. COleControlHost *poch = IToClass(COleControlHost, _xuih, this);
  1037. return poch->_pIDocHostUIParent ? poch->_pIDocHostUIParent->HideUI(): E_NOTIMPL;
  1038. }
  1039. HRESULT CProxyUIHandler::UpdateUI()
  1040. {
  1041. COleControlHost *poch = IToClass(COleControlHost, _xuih, this);
  1042. return poch->_pIDocHostUIParent ? poch->_pIDocHostUIParent->UpdateUI(): E_NOTIMPL;
  1043. }
  1044. HRESULT CProxyUIHandler::EnableModeless(BOOL fActivate)
  1045. {
  1046. COleControlHost *poch = IToClass(COleControlHost, _xuih, this);
  1047. return poch->_pIDocHostUIParent ? poch->_pIDocHostUIParent->EnableModeless(fActivate): E_NOTIMPL;
  1048. }
  1049. HRESULT CProxyUIHandler::OnDocWindowActivate(BOOL fActivate)
  1050. {
  1051. COleControlHost *poch = IToClass(COleControlHost, _xuih, this);
  1052. return poch->_pIDocHostUIParent ? poch->_pIDocHostUIParent->OnDocWindowActivate(fActivate): E_NOTIMPL;
  1053. }
  1054. HRESULT CProxyUIHandler::OnFrameWindowActivate(BOOL fActivate)
  1055. {
  1056. COleControlHost *poch = IToClass(COleControlHost, _xuih, this);
  1057. return poch->_pIDocHostUIParent ? poch->_pIDocHostUIParent->OnFrameWindowActivate(fActivate): E_NOTIMPL;
  1058. }
  1059. HRESULT CProxyUIHandler::ResizeBorder(LPCRECT prcBorder, IOleInPlaceUIWindow *pUIWindow, BOOL fRameWindow)
  1060. {
  1061. COleControlHost *poch = IToClass(COleControlHost, _xuih, this);
  1062. return poch->_pIDocHostUIParent ? poch->_pIDocHostUIParent->ResizeBorder(prcBorder, pUIWindow, fRameWindow): E_NOTIMPL;
  1063. }
  1064. HRESULT CProxyUIHandler::TranslateAccelerator(LPMSG lpMsg, const GUID *pguidCmdGroup, DWORD nCmdID)
  1065. {
  1066. COleControlHost *poch = IToClass(COleControlHost, _xuih, this);
  1067. return poch->_pIDocHostUIParent ? poch->_pIDocHostUIParent->TranslateAccelerator(lpMsg, pguidCmdGroup, nCmdID): E_NOTIMPL;
  1068. }
  1069. HRESULT CProxyUIHandler::GetOptionKeyPath(LPOLESTR *pchKey, DWORD dw)
  1070. {
  1071. COleControlHost *poch = IToClass(COleControlHost, _xuih, this);
  1072. return poch->_pIDocHostUIParent ? poch->_pIDocHostUIParent->GetOptionKeyPath(pchKey, dw): E_NOTIMPL;
  1073. }
  1074. HRESULT CProxyUIHandler::GetDropTarget(IDropTarget *pDropTarget, IDropTarget **ppDropTarget)
  1075. {
  1076. COleControlHost *poch = IToClass(COleControlHost, _xuih, this);
  1077. return poch->_pIDocHostUIParent ? poch->_pIDocHostUIParent->GetDropTarget(pDropTarget, ppDropTarget) : E_NOTIMPL;
  1078. }
  1079. HRESULT CProxyUIHandler::GetExternal(IDispatch **ppDispatch)
  1080. {
  1081. COleControlHost *poch = IToClass(COleControlHost, _xuih, this);
  1082. return poch->_pIDocHostUIParent ? poch->_pIDocHostUIParent->GetExternal(ppDispatch) : E_NOTIMPL;
  1083. }
  1084. HRESULT CProxyUIHandler::TranslateUrl(DWORD dwTranslate, OLECHAR *pchURLIn, OLECHAR **ppchURLOut)
  1085. {
  1086. COleControlHost *poch = IToClass(COleControlHost, _xuih, this);
  1087. return poch->_pIDocHostUIParent ? poch->_pIDocHostUIParent->TranslateUrl(dwTranslate, pchURLIn, ppchURLOut) : E_NOTIMPL;
  1088. }
  1089. HRESULT CProxyUIHandler::FilterDataObject( IDataObject *pDO, IDataObject **ppDORet)
  1090. {
  1091. COleControlHost *poch = IToClass(COleControlHost, _xuih, this);
  1092. return poch->_pIDocHostUIParent ? poch->_pIDocHostUIParent->FilterDataObject(pDO, ppDORet) : E_NOTIMPL;
  1093. }
  1094. HRESULT CProxyUIHandler::GetOverrideKeyPath( LPOLESTR *pchKey, DWORD dw)
  1095. {
  1096. COleControlHost *poch = IToClass(COleControlHost, _xuih, this);
  1097. return poch->_pIDocHostUIParent2 ? poch->_pIDocHostUIParent2->GetOverrideKeyPath(pchKey, dw) : E_NOTIMPL;
  1098. }
  1099. STDAPI_(BOOL) DllRegisterWindowClasses(const SHDRC * pshdrc)
  1100. {
  1101. if (pshdrc && pshdrc->cbSize == SIZEOF(SHDRC) && !(pshdrc->dwFlags & ~SHDRCF_ALL))
  1102. {
  1103. if (pshdrc->dwFlags & SHDRCF_OCHOST)
  1104. {
  1105. COleControlHost::_RegisterClass();
  1106. return TRUE;
  1107. }
  1108. }
  1109. return FALSE;
  1110. }
  1111. //---------------------------------------------------------------------------
  1112. // CEventSink constructor
  1113. CEventSink::CEventSink( BOOL bAutoDelete )
  1114. : _hwndSite(NULL),
  1115. _hwndOwner(NULL),
  1116. _punkOC(NULL),
  1117. _dwCookie(0),
  1118. _cRef(1),
  1119. _bAutoDelete( bAutoDelete )
  1120. {
  1121. _iid = _iidDefault = IID_NULL ;
  1122. }
  1123. // CEventSink IUnknown impl
  1124. STDMETHODIMP CEventSink::QueryInterface( REFIID riid, void** ppvObj )
  1125. {
  1126. *ppvObj = NULL ;
  1127. if( IsEqualGUID( riid, IID_IUnknown ) ||
  1128. IsEqualGUID( riid, IID_IDispatch )||
  1129. IsEqualGUID( riid, _iidDefault ) )
  1130. {
  1131. *ppvObj = this ;
  1132. return S_OK ;
  1133. }
  1134. return E_NOINTERFACE ;
  1135. }
  1136. STDMETHODIMP_(ULONG) CEventSink::AddRef()
  1137. {
  1138. return InterlockedIncrement( &_cRef ) ;
  1139. }
  1140. STDMETHODIMP_(ULONG) CEventSink::Release()
  1141. {
  1142. if( InterlockedDecrement( &_cRef ) <= 0 )
  1143. {
  1144. if( _bAutoDelete )
  1145. delete this ;
  1146. return 0 ;
  1147. }
  1148. return _cRef ;
  1149. }
  1150. // Connects the sink to the OC's default event dispatch interface.
  1151. BOOL CEventSink::Connect( HWND hwndOwner, HWND hwndSite, LPUNKNOWN punkOC )
  1152. {
  1153. ASSERT( punkOC ) ;
  1154. IID iidDefault = IID_NULL ;
  1155. if( SUCCEEDED( _GetDefaultEventIID( punkOC, &iidDefault ) ) )
  1156. {
  1157. _iidDefault = iidDefault ;
  1158. return _Connect( hwndOwner, hwndSite, punkOC, iidDefault ) ;
  1159. }
  1160. return FALSE ;
  1161. }
  1162. // Establishes advise connection on the specified interface
  1163. BOOL CEventSink::_Connect( HWND hwndOwner, HWND hwndSite, LPUNKNOWN punkOC, REFIID iid )
  1164. {
  1165. LPCONNECTIONPOINTCONTAINER pcpc;
  1166. ASSERT(punkOC != NULL) ;
  1167. HRESULT hr = CONNECT_E_CANNOTCONNECT ;
  1168. if( _IsConnected( iid ) )
  1169. return TRUE ;
  1170. if( _dwCookie )
  1171. Disconnect() ;
  1172. if( punkOC &&
  1173. SUCCEEDED( punkOC->QueryInterface(IID_IConnectionPointContainer, (LPVOID*)&pcpc )))
  1174. {
  1175. LPCONNECTIONPOINT pcp = NULL;
  1176. DWORD dwCookie = 0;
  1177. ASSERT(pcpc != NULL);
  1178. if( SUCCEEDED(pcpc->FindConnectionPoint( iid, &pcp )))
  1179. {
  1180. ASSERT(pcp != NULL);
  1181. hr = pcp->Advise( this, &dwCookie ) ;
  1182. if( SUCCEEDED( hr ) )
  1183. {
  1184. _iid = iid ;
  1185. _dwCookie = dwCookie ;
  1186. _hwndOwner = hwndOwner ;
  1187. _hwndSite = hwndSite ;
  1188. _punkOC = punkOC ;
  1189. _punkOC->AddRef() ;
  1190. }
  1191. pcp->Release();
  1192. }
  1193. pcpc->Release();
  1194. }
  1195. return SUCCEEDED( hr ) ;
  1196. }
  1197. // Retrieves default event dispatch interface from the OC.
  1198. HRESULT CEventSink::_GetDefaultEventIID( LPUNKNOWN punkOC, IID* piid )
  1199. {
  1200. HRESULT hr ;
  1201. ASSERT( punkOC ) ;
  1202. ASSERT( piid ) ;
  1203. IProvideClassInfo *pci ;
  1204. IProvideClassInfo2 *pci2 ;
  1205. *piid = IID_NULL ;
  1206. #define IMPLTYPE_MASK \
  1207. (IMPLTYPEFLAG_FDEFAULT|IMPLTYPEFLAG_FSOURCE|IMPLTYPEFLAG_FRESTRICTED)
  1208. #define IMPLTYPE_DEFAULTSOURCE \
  1209. (IMPLTYPEFLAG_FDEFAULT|IMPLTYPEFLAG_FSOURCE)
  1210. // Retrieve default outbound dispatch IID using OC's IProvideClassInfo2
  1211. if( SUCCEEDED( (hr = punkOC->QueryInterface( IID_IProvideClassInfo2, (void**)&pci2 )) ) )
  1212. {
  1213. hr = pci2->GetGUID( GUIDKIND_DEFAULT_SOURCE_DISP_IID, piid ) ;
  1214. pci2->Release() ;
  1215. }
  1216. else // no IProvideClassInfo2; try IProvideClassInfo:
  1217. if( SUCCEEDED( (hr = punkOC->QueryInterface( IID_IProvideClassInfo, (void**)&pci )) ) )
  1218. {
  1219. ITypeInfo* pClassInfo = NULL;
  1220. if( SUCCEEDED( (hr = pci->GetClassInfo( &pClassInfo )) ) )
  1221. {
  1222. LPTYPEATTR pClassAttr;
  1223. ASSERT( pClassInfo );
  1224. if( SUCCEEDED( (hr = pClassInfo->GetTypeAttr( &pClassAttr )) ) )
  1225. {
  1226. ASSERT( pClassAttr ) ;
  1227. ASSERT( pClassAttr->typekind == TKIND_COCLASS ) ;
  1228. // Enumerate implemented interfaces looking for default source IID.
  1229. HREFTYPE hRefType;
  1230. int nFlags;
  1231. for( UINT i = 0; i < pClassAttr->cImplTypes; i++ )
  1232. {
  1233. if( SUCCEEDED( (hr = pClassInfo->GetImplTypeFlags( i, &nFlags )) ) &&
  1234. ((nFlags & IMPLTYPE_MASK) == IMPLTYPE_DEFAULTSOURCE) )
  1235. {
  1236. // Got the interface, now retrieve its IID:
  1237. ITypeInfo* pEventInfo = NULL ;
  1238. if( SUCCEEDED( (hr = pClassInfo->GetRefTypeOfImplType( i, &hRefType )) ) &&
  1239. SUCCEEDED( (hr = pClassInfo->GetRefTypeInfo( hRefType, &pEventInfo )) ) )
  1240. {
  1241. LPTYPEATTR pEventAttr;
  1242. ASSERT( pEventInfo ) ;
  1243. if( SUCCEEDED( (hr = pEventInfo->GetTypeAttr( &pEventAttr )) ) )
  1244. {
  1245. *piid = pEventAttr->guid ;
  1246. pEventInfo->ReleaseTypeAttr(pEventAttr);
  1247. }
  1248. pEventInfo->Release();
  1249. }
  1250. break;
  1251. }
  1252. }
  1253. pClassInfo->ReleaseTypeAttr(pClassAttr);
  1254. }
  1255. pClassInfo->Release();
  1256. }
  1257. pci->Release() ;
  1258. }
  1259. if( SUCCEEDED( hr ) && IsEqualIID( *piid, IID_NULL ) )
  1260. hr = E_FAIL ;
  1261. return hr ;
  1262. }
  1263. // reports whether the sink is connected to the indicated sink
  1264. BOOL CEventSink::_IsConnected( REFIID iid )
  1265. {
  1266. return _dwCookie != 0L &&
  1267. IsEqualIID( iid, _iid ) ;
  1268. }
  1269. // disconnects the sink
  1270. BOOL CEventSink::Disconnect()
  1271. {
  1272. LPCONNECTIONPOINTCONTAINER pcpc;
  1273. if( _dwCookie != 0 &&
  1274. _punkOC &&
  1275. SUCCEEDED( _punkOC->QueryInterface(IID_IConnectionPointContainer, (LPVOID*)&pcpc)))
  1276. {
  1277. LPCONNECTIONPOINT pcp = NULL;
  1278. ASSERT(pcpc != NULL);
  1279. if (SUCCEEDED(pcpc->FindConnectionPoint(_iid, &pcp)))
  1280. {
  1281. ASSERT(pcp != NULL);
  1282. pcp->Unadvise(_dwCookie);
  1283. pcp->Release();
  1284. _iid = IID_NULL ;
  1285. _dwCookie = 0L ;
  1286. _hwndOwner = NULL ;
  1287. _hwndSite = NULL ;
  1288. _punkOC->Release() ;
  1289. _punkOC = NULL ;
  1290. }
  1291. pcpc->Release();
  1292. return TRUE ;
  1293. }
  1294. return FALSE ;
  1295. }
  1296. // CEventSink IDispatch interface
  1297. STDMETHODIMP CEventSink::Invoke(
  1298. IN DISPID dispIdMember,
  1299. IN REFIID riid,
  1300. IN LCID lcid,
  1301. IN WORD wFlags,
  1302. IN OUT DISPPARAMS *pDispParams,
  1303. OUT VARIANT *pVarResult,
  1304. OUT EXCEPINFO *pExcepInfo,
  1305. OUT UINT *puArgErr)
  1306. {
  1307. // Copy method args to notification block
  1308. NMOCEVENT event ;
  1309. ZeroMemory( &event, sizeof(event) ) ;
  1310. event.hdr.hwndFrom = _hwndSite;
  1311. event.hdr.idFrom = GetDlgCtrlID( _hwndSite ) ;
  1312. event.hdr.code = OCN_OCEVENT ;
  1313. event.dispID = dispIdMember ;
  1314. event.iid = riid ;
  1315. event.lcid = lcid ;
  1316. event.wFlags = wFlags ;
  1317. event.pDispParams = pDispParams ;
  1318. event.pVarResult = pVarResult ;
  1319. event.pExepInfo = pExcepInfo ;
  1320. event.puArgErr = puArgErr ;
  1321. // Notify parent of event
  1322. ::SendMessage( _hwndOwner, WM_NOTIFY, event.hdr.idFrom, (LPARAM)&event ) ;
  1323. // Cleanup args
  1324. if (pVarResult != NULL)
  1325. VariantClear( pVarResult ) ;
  1326. return S_OK ;
  1327. }