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.

1617 lines
47 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 (FAILED(hr))
  378. TraceMsg(TF_OCCONTROL, "_Activate: %d Unable to DoVerb! Error = %lX", _bInPlaceActive, hr);
  379. return hr;
  380. }
  381. // Clean up and Release all of interface pointers used in this object
  382. HRESULT COleControlHost::_Exit()
  383. {
  384. _SendNotify(OCN_EXIT, NULL);
  385. if (_pIViewObject)
  386. {
  387. _pIViewObject->SetAdvise(_dwAspect, 0, NULL);
  388. _pIViewObject->Release();
  389. _pIViewObject = NULL;
  390. }
  391. if (_pIOleObject)
  392. {
  393. if (_dwConnection)
  394. {
  395. _pIOleObject->Unadvise(_dwConnection);
  396. _dwConnection = 0;
  397. }
  398. _pIOleObject->Close(OLECLOSE_NOSAVE);
  399. _pIOleObject->SetClientSite(NULL);
  400. _pIOleObject->Release();
  401. _pIOleObject = NULL;
  402. }
  403. if (_punkOC)
  404. {
  405. ULONG ulRef;
  406. ulRef = _punkOC->Release();
  407. _punkOC = NULL;
  408. if (ulRef != 0)
  409. TraceMsg(TF_OCCONTROL, "OCHOST _Exit: After last release ref = %d > 0", ulRef);
  410. }
  411. ATOMICRELEASE(_pIDocHostUIParent);
  412. ATOMICRELEASE(_pIDocHostUIParent2);
  413. if (_punkOwner) {
  414. _punkOwner->Release();
  415. _punkOwner = NULL;
  416. }
  417. if (_pdispSiteDelegate) {
  418. _pdispSiteDelegate->Release();
  419. _pdispSiteDelegate = NULL;
  420. }
  421. return S_OK;
  422. }
  423. COleControlHost::COleControlHost(HWND hwnd)
  424. : _cRef(1), _dwAspect(DVASPECT_CONTENT), _hwnd(hwnd)
  425. {
  426. // These variables should be initialized to zeros automatically
  427. ASSERT(_dwMiscStatus == 0);
  428. ASSERT(_dwConnection == 0);
  429. ASSERT(_bInPlaceActive == FALSE);
  430. ASSERT(_pIDocHostUIParent == NULL);
  431. ASSERT(_pIDocHostUIParent2 == NULL);
  432. ASSERT(_clsidOC == CLSID_NULL);
  433. ASSERT(_punkOC == NULL);
  434. ASSERT(_pIViewObject == NULL);
  435. ASSERT(_pIOleIPObject == NULL);
  436. ASSERT(_pdispSiteDelegate == NULL);
  437. ASSERT(_hwnd);
  438. }
  439. #ifdef DEBUG
  440. #define _AddRef(psz) { ++_cRef; TraceMsg(TF_OCCONTROL, "CDocObjectHost(%x)::QI(%s) is AddRefing _cRef=%lX", this, psz, _cRef); }
  441. #else
  442. #define _AddRef(psz) ++_cRef
  443. #endif
  444. // *** IUnknown Methods ***
  445. HRESULT COleControlHost::QueryInterface(REFIID riid, LPVOID * ppvObj)
  446. {
  447. // ppvObj must not be NULL
  448. ASSERT(ppvObj != NULL);
  449. if (ppvObj == NULL)
  450. return E_INVALIDARG;
  451. *ppvObj = NULL;
  452. if ((IsEqualIID(riid, IID_IUnknown)) ||
  453. (IsEqualIID(riid, IID_IOleWindow)) ||
  454. (IsEqualIID(riid, IID_IOleInPlaceUIWindow)) ||
  455. (IsEqualIID(riid, IID_IOleInPlaceFrame)))
  456. {
  457. *ppvObj = SAFECAST(this, IOleInPlaceFrame *);
  458. TraceMsg(TF_OCCONTROL, "QI IOleInPlaceFrame succeeded");
  459. }
  460. else if (IsEqualIID(riid, IID_IServiceProvider))
  461. {
  462. *ppvObj = SAFECAST(this, IServiceProvider *);
  463. TraceMsg(TF_OCCONTROL, "QI IServiceProvider succeeded");
  464. }
  465. else if (IsEqualIID(riid, IID_IOleClientSite))
  466. {
  467. *ppvObj = SAFECAST(this, IOleClientSite *);
  468. TraceMsg(TF_OCCONTROL, "QI IOleClientSite succeeded");
  469. }
  470. else if (IsEqualIID(riid, IID_IAdviseSink))
  471. {
  472. *ppvObj = SAFECAST(this, IAdviseSink *);
  473. TraceMsg(TF_OCCONTROL, "QI IAdviseSink succeeded");
  474. }
  475. else if (IsEqualIID(riid, IID_IOleInPlaceSite))
  476. {
  477. *ppvObj = SAFECAST(this, IOleInPlaceSite *);
  478. TraceMsg(TF_OCCONTROL, "QI IOleInPlaceSite succeeded");
  479. }
  480. else if (IsEqualIID(riid, IID_IOleCommandTarget))
  481. {
  482. *ppvObj = SAFECAST(this, IOleCommandTarget *);
  483. TraceMsg(TF_OCCONTROL, "QI IOleCommandTarget succeeded");
  484. }
  485. else if (NULL != _pIDocHostUIParent &&
  486. IsEqualIID(riid, IID_IDocHostUIHandler))
  487. {
  488. // only implement this if the host implements it
  489. *ppvObj = SAFECAST(&_xuih, IDocHostUIHandler *);
  490. TraceMsg(TF_OCCONTROL, "QI IDocHostUIHandler succeeded");
  491. }
  492. else if (NULL != _pIDocHostUIParent2 &&
  493. IsEqualIID(riid, IID_IDocHostUIHandler2))
  494. {
  495. // only implement this if the host implements it
  496. *ppvObj = SAFECAST(&_xuih, IDocHostUIHandler2 *);
  497. TraceMsg(TF_OCCONTROL, "QI IDocHostUIHandler2 succeeded");
  498. }
  499. else if (IsEqualIID(riid, IID_IDispatch))
  500. {
  501. *ppvObj = SAFECAST(this, IDispatch *);
  502. TraceMsg(TF_OCCONTROL, "QI IDispatch succeeded");
  503. }
  504. else
  505. return E_NOINTERFACE; // Otherwise, don't delegate to HTMLObj!!
  506. _AddRef(TEXT("IOleInPlaceSite"));
  507. return S_OK;
  508. }
  509. ULONG COleControlHost::AddRef()
  510. {
  511. _cRef++;
  512. TraceMsg(TF_OCCONTROL, "COleControlHost(%x)::AddRef called, new _cRef=%lX", this, _cRef);
  513. return _cRef;
  514. }
  515. ULONG COleControlHost::Release()
  516. {
  517. _cRef--;
  518. TraceMsg(TF_OCCONTROL, "COleControlHost(%x)::Release called, new _cRef=%lX", this, _cRef);
  519. if (_cRef > 0)
  520. return _cRef;
  521. delete this;
  522. return 0;
  523. }
  524. // ServiceProvider interfaces
  525. HRESULT COleControlHost::QueryService(REFGUID guidService,
  526. REFIID riid, void **ppvObj)
  527. {
  528. HRESULT hres = E_FAIL;
  529. *ppvObj = NULL;
  530. if (_punkOwner) {
  531. IServiceProvider *psp;
  532. _punkOwner->QueryInterface(IID_IServiceProvider, (LPVOID*)&psp);
  533. if (psp) {
  534. hres = psp->QueryService(guidService, riid, ppvObj);
  535. psp->Release();
  536. }
  537. }
  538. return hres;
  539. }
  540. // ************************ IOleClientSite methods ******************
  541. HRESULT COleControlHost::SaveObject()
  542. {
  543. //FEATURE: default set to E_NOTIMPL may not be correct
  544. HRESULT hr = E_NOTIMPL;
  545. IStorage * pIs;
  546. if (SUCCEEDED(_punkOC->QueryInterface(IID_IStorage, (void **)&pIs)))
  547. {
  548. IPersistStorage *pIps;
  549. if (SUCCEEDED(_punkOC->QueryInterface(IID_IPersistStorage, (void **)&pIps)))
  550. {
  551. OleSave(pIps, pIs, TRUE);
  552. pIps->SaveCompleted(NULL);
  553. pIps->Release();
  554. hr = S_OK;
  555. }
  556. pIs->Release();
  557. }
  558. return hr;
  559. }
  560. HRESULT COleControlHost::GetMoniker(DWORD dwAssign, DWORD dwWhichMoniker, LPMONIKER * ppMk)
  561. {
  562. return E_NOTIMPL;
  563. }
  564. HRESULT COleControlHost::GetContainer(LPOLECONTAINER * ppContainer)
  565. {
  566. *ppContainer = NULL;
  567. return E_NOINTERFACE;
  568. }
  569. HRESULT COleControlHost::ShowObject()
  570. {
  571. // RECTL rcl;
  572. // POINT pt1, pt2;
  573. return S_OK;
  574. }
  575. HRESULT COleControlHost::OnShowWindow(BOOL fShow)
  576. {
  577. return S_OK;
  578. }
  579. HRESULT COleControlHost::RequestNewObjectLayout()
  580. {
  581. return E_NOTIMPL;
  582. }
  583. // ************************ IAdviseSink methods *********************
  584. void COleControlHost::OnDataChange(FORMATETC * pFmt, STGMEDIUM * pStgMed)
  585. {
  586. // NOTES: This is optional
  587. return;
  588. }
  589. void COleControlHost::OnViewChange(DWORD dwAspect, LONG lIndex)
  590. {
  591. // FEATURE: need to let the container know the colors might have changed
  592. // but don't want to deal with the paletts now
  593. // Draw only if not inplace active and this is the right aspect. Inplace
  594. // active objects have their own window and are responsible for painting
  595. // themselves.
  596. // WARNING: _bInPlaceActive is not determined, yet.
  597. // This funtion is called as a result of calling doverb, however,
  598. // _bInPlaceActive will only be determined as DoVerb returns
  599. // works fine for now, but could be trouble later.
  600. if ((_hwnd) && (!_bInPlaceActive) && (dwAspect == _dwAspect))
  601. {
  602. HDC hdc = GetDC(_hwnd);
  603. if (hdc)
  604. {
  605. _Draw(hdc);
  606. ReleaseDC(_hwnd, hdc);
  607. }
  608. }
  609. }
  610. void COleControlHost::OnRename(LPMONIKER pMoniker)
  611. {
  612. return;
  613. }
  614. void COleControlHost::OnSave()
  615. {
  616. // NOTES: This is optional
  617. return;
  618. }
  619. void COleControlHost::OnClose()
  620. {
  621. // FEATURE: need to let the container know the colors might have changed
  622. return;
  623. }
  624. // ************************ IOleWindow Methods **********************
  625. HRESULT COleControlHost::GetWindow(HWND * lphwnd)
  626. {
  627. *lphwnd = _hwnd;
  628. return S_OK;
  629. }
  630. HRESULT COleControlHost::ContextSensitiveHelp(BOOL fEnterMode)
  631. {
  632. // NOTES: This is optional
  633. return E_NOTIMPL;
  634. }
  635. // *********************** IOleInPlaceSite Methods *****************
  636. HRESULT COleControlHost::CanInPlaceActivate(void)
  637. {
  638. return S_OK;
  639. }
  640. HRESULT COleControlHost::OnInPlaceActivate(void)
  641. {
  642. if (!_pIOleIPObject)
  643. return (_punkOC->QueryInterface(IID_IOleInPlaceObject, (void **)&_pIOleIPObject));
  644. else
  645. return S_OK;
  646. }
  647. HRESULT COleControlHost::OnUIActivate(void)
  648. {
  649. LRESULT lres;
  650. OCNONUIACTIVATEMSG oam = {0};
  651. oam.punk = _punkOC;
  652. lres = _SendNotify(OCN_ONUIACTIVATE, &oam.nmhdr);
  653. return S_OK;
  654. }
  655. HRESULT COleControlHost::GetWindowContext (IOleInPlaceFrame ** ppFrame, IOleInPlaceUIWindow ** ppIIPUIWin,
  656. LPRECT lprcPosRect, LPRECT lprcClipRect, LPOLEINPLACEFRAMEINFO lpFrameInfo)
  657. {
  658. *ppFrame = this;
  659. _AddRef("GetWindowContext");
  660. // This is set to NULL because the document window is the same as the frame
  661. // window
  662. *ppIIPUIWin = NULL;
  663. ASSERT(_hwnd);
  664. if (!GetClientRect(_hwnd, lprcPosRect))
  665. SetRectEmpty(lprcPosRect);
  666. // Set the clip rectangle to be the same as the position rectangle
  667. CopyRect(lprcClipRect, lprcPosRect);
  668. lpFrameInfo->cb = sizeof(OLEINPLACEFRAMEINFO);
  669. #ifdef MDI
  670. lpFrameInfo->fMDIApp = TRUE;
  671. #else
  672. lpFrameInfo->fMDIApp = FALSE;
  673. #endif
  674. lpFrameInfo->hwndFrame = _hwnd;
  675. lpFrameInfo->haccel = 0;
  676. lpFrameInfo->cAccelEntries = 0;
  677. return S_OK;
  678. }
  679. HRESULT COleControlHost::Scroll(SIZE scrollExtent)
  680. {
  681. // Should implement later
  682. return E_NOTIMPL;
  683. }
  684. HRESULT COleControlHost::OnUIDeactivate(BOOL fUndoable)
  685. {
  686. return E_NOTIMPL;
  687. }
  688. HRESULT COleControlHost::OnInPlaceDeactivate(void)
  689. {
  690. if (_pIOleIPObject)
  691. {
  692. _pIOleIPObject->Release();
  693. _pIOleIPObject = NULL;
  694. }
  695. return S_OK;
  696. }
  697. HRESULT COleControlHost::DiscardUndoState(void)
  698. {
  699. // Should implement later
  700. return E_NOTIMPL;
  701. }
  702. HRESULT COleControlHost::DeactivateAndUndo(void)
  703. {
  704. // Should implement later
  705. return E_NOTIMPL;
  706. }
  707. HRESULT COleControlHost::OnPosRectChange(LPCRECT lprcPosRect)
  708. {
  709. // We do not allow the children to change the size themselves
  710. OCNONPOSRECTCHANGEMSG opcm = {0};
  711. opcm.prcPosRect = lprcPosRect;
  712. _SendNotify(OCN_ONPOSRECTCHANGE, &opcm.nmhdr);
  713. return S_OK;
  714. }
  715. // ************************ IOleInPlaceUIWindow methods *************
  716. HRESULT COleControlHost::GetBorder(LPRECT lprectBorder)
  717. {
  718. return E_NOTIMPL;
  719. }
  720. HRESULT COleControlHost::RequestBorderSpace(LPCBORDERWIDTHS lpborderwidths)
  721. {
  722. return E_NOTIMPL;
  723. }
  724. HRESULT COleControlHost::SetBorderSpace(LPCBORDERWIDTHS lpborderwidths)
  725. {
  726. return E_NOTIMPL;
  727. }
  728. HRESULT COleControlHost::SetActiveObject(IOleInPlaceActiveObject * pActiveObject,
  729. LPCOLESTR lpszObjName)
  730. {
  731. return E_NOTIMPL;
  732. }
  733. // *********************** IOleInPlaceFrame Methods *****************
  734. HRESULT COleControlHost::InsertMenus(HMENU hmenuShared, LPOLEMENUGROUPWIDTHS lpMenuWidths)
  735. {
  736. // Should implement later
  737. return E_NOTIMPL;
  738. }
  739. HRESULT COleControlHost::SetMenu(HMENU hmenuShared, HOLEMENU holemenu, HWND hwndActiveObject)
  740. {
  741. // Should implement later
  742. return E_NOTIMPL;
  743. }
  744. HRESULT COleControlHost::RemoveMenus(HMENU hmenuShared)
  745. {
  746. // Should implement later
  747. return E_NOTIMPL;
  748. }
  749. HRESULT COleControlHost::SetStatusText(LPCOLESTR pszStatusText)
  750. {
  751. OCNONSETSTATUSTEXTMSG osst = {0};
  752. osst.pwszStatusText = pszStatusText;
  753. _SendNotify(OCN_ONSETSTATUSTEXT, &osst.nmhdr);
  754. return S_OK;
  755. }
  756. HRESULT COleControlHost::EnableModeless(BOOL fEnable)
  757. {
  758. // Should implement later
  759. return E_NOTIMPL;
  760. }
  761. HRESULT COleControlHost::TranslateAccelerator(LPMSG lpmsg, WORD wID)
  762. {
  763. // Should implement later
  764. return E_NOTIMPL;
  765. }
  766. // ************************ IOleCommandTarget Methods *************
  767. HRESULT COleControlHost::QueryStatus(const GUID *pguid, ULONG cCmds, MSOCMD rgCmds[], MSOCMDTEXT *pcmdtext)
  768. {
  769. return IUnknown_QueryStatus(_punkOwner, pguid, cCmds, rgCmds, pcmdtext);
  770. }
  771. HRESULT COleControlHost::Exec(const GUID *pguid, DWORD nCmdID, DWORD nCmdexecopt, VARIANTARG *pvarargIn, VARIANTARG *pvarargOut)
  772. {
  773. return IUnknown_Exec(_punkOwner, pguid, nCmdID, nCmdexecopt, pvarargIn, pvarargOut);
  774. }
  775. HRESULT COleControlHost::_InitOCStruct(LPOCHINITSTRUCT lpocs)
  776. {
  777. HRESULT hres = E_FAIL;
  778. if (_punkOC)
  779. return S_FALSE;
  780. if (lpocs)
  781. {
  782. if (lpocs->cbSize != SIZEOF(OCHINITSTRUCT))
  783. return hres;
  784. if (lpocs->clsidOC == CLSID_NULL)
  785. return hres;
  786. _clsidOC = lpocs->clsidOC;
  787. _SetOwner(lpocs->punkOwner);
  788. }
  789. else
  790. return hres;
  791. hres = _Init();
  792. if (SUCCEEDED(hres))
  793. hres = _Activate();
  794. return hres;
  795. }
  796. LRESULT COleControlHost::_OnPaint()
  797. {
  798. ASSERT(_hwnd);
  799. PAINTSTRUCT ps;
  800. HDC hdc = BeginPaint(_hwnd, &ps);
  801. _Draw(hdc);
  802. EndPaint(_hwnd, &ps);
  803. return 0;
  804. }
  805. LRESULT COleControlHost::_OnSize(HWND hwnd, LPARAM lParam)
  806. {
  807. if (_pIOleIPObject)
  808. {
  809. RECT rcPos, rcClip ;
  810. SetRect( &rcPos, 0, 0, LOWORD(lParam), HIWORD(lParam) ) ;
  811. rcClip = rcPos ;
  812. _pIOleIPObject->SetObjectRects(&rcPos, &rcClip);
  813. }
  814. return 0;
  815. }
  816. LRESULT COleControlHost::_OnCreate(HWND hwnd, LPCREATESTRUCT lpcs)
  817. {
  818. TCHAR szClsid[50];
  819. _hwndParent = GetParent(hwnd);
  820. SetWindowLongPtr(hwnd, 0, (LONG_PTR)this);
  821. LPOCHINITSTRUCT lpois = (LPOCHINITSTRUCT)lpcs->lpCreateParams;
  822. HRESULT hres = S_OK;
  823. if (lpois)
  824. hres = _InitOCStruct(lpois);
  825. else if (GetWindowText(hwnd, szClsid, ARRAYSIZE(szClsid)))
  826. {
  827. OCHINITSTRUCT ois;
  828. ois.cbSize = SIZEOF(OCHINITSTRUCT);
  829. if (FAILED(SHCLSIDFromString(szClsid, &ois.clsidOC)))
  830. ois.clsidOC = CLSID_NULL;
  831. ois.punkOwner = NULL;
  832. hres = _InitOCStruct(&ois);
  833. }
  834. if (FAILED(hres))
  835. return -1;
  836. return 0;
  837. }
  838. LRESULT COleControlHost::_OnDestroy()
  839. {
  840. ASSERT(_hwnd);
  841. SetWindowLongPtr(_hwnd, 0, 0);
  842. _ConnectEvents( _punkOC, FALSE ) ;
  843. _Deactivate();
  844. _Exit();
  845. Release();
  846. return 0;
  847. }
  848. LRESULT COleControlHost::_OnQueryInterface(WPARAM wParam, LPARAM lParam)
  849. {
  850. if (lParam)
  851. {
  852. QIMSG * qiMsg = (QIMSG *)lParam;
  853. return _punkOC->QueryInterface(*qiMsg->qiid, qiMsg->ppvObject);
  854. }
  855. return -1;
  856. }
  857. LRESULT COleControlHost::_SetOwner(IUnknown * punkNewOwner)
  858. {
  859. if (_punkOwner)
  860. _punkOwner->Release();
  861. _punkOwner = punkNewOwner;
  862. if (_punkOwner)
  863. _punkOwner->AddRef();
  864. ATOMICRELEASE(_pIDocHostUIParent);
  865. ATOMICRELEASE(_pIDocHostUIParent2);
  866. // Query if owner supports IDocHostUIHandler, if so then
  867. // we turn on our delegating wrapper
  868. if (punkNewOwner)
  869. {
  870. punkNewOwner->QueryInterface(IID_IDocHostUIHandler, (LPVOID *)&_pIDocHostUIParent);
  871. punkNewOwner->QueryInterface(IID_IDocHostUIHandler2, (LPVOID *)&_pIDocHostUIParent2);
  872. }
  873. return 0;
  874. }
  875. LRESULT COleControlHost::_ConnectEvents( LPUNKNOWN punkOC, BOOL bConnect )
  876. {
  877. if( bConnect )
  878. {
  879. ASSERT( punkOC ) ;
  880. return _eventSink.Connect( _hwndParent, _hwnd, punkOC ) ;
  881. }
  882. return _eventSink.Disconnect() ;
  883. }
  884. LRESULT COleControlHost::_SetServiceProvider(IServiceProvider* pSP)
  885. {
  886. // Free any existing delegates
  887. if (_pdispSiteDelegate)
  888. {
  889. _pdispSiteDelegate->Release();
  890. }
  891. // For now, we just delegate IDispatch (Ambient properties) calls
  892. HRESULT hr = pSP->QueryService(SID_OleControlSite, IID_PPV_ARG(IDispatch, &_pdispSiteDelegate));
  893. if (FAILED(hr))
  894. {
  895. _pdispSiteDelegate = NULL;
  896. }
  897. return 0;
  898. }
  899. LRESULT COleControlHost::_SendNotify(UINT code, LPNMHDR pnmhdr)
  900. {
  901. NMHDR nmhdr;
  902. ASSERT(_hwnd);
  903. if (!_hwndParent)
  904. return 0;
  905. if (!pnmhdr)
  906. pnmhdr = &nmhdr;
  907. pnmhdr->hwndFrom = _hwnd;
  908. pnmhdr->idFrom = GetDlgCtrlID( _hwnd ) ;
  909. pnmhdr->code = code;
  910. return SendMessage(_hwndParent, WM_NOTIFY, 0, (LPARAM)pnmhdr);
  911. }
  912. LRESULT CALLBACK COleControlHost::OCHostWndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
  913. {
  914. COleControlHost *pcoch = (COleControlHost *)GetWindowPtr(hwnd, 0);
  915. if (!pcoch && (uMsg != WM_CREATE))
  916. return DefWindowProcWrap(hwnd, uMsg, wParam, lParam);
  917. switch(uMsg)
  918. {
  919. case WM_CREATE:
  920. pcoch = new COleControlHost(hwnd);
  921. if (pcoch)
  922. return pcoch->_OnCreate(hwnd, (LPCREATESTRUCT)lParam);
  923. return -1;
  924. case WM_ERASEBKGND:
  925. if (pcoch->_punkOC && pcoch->_bInPlaceActive)
  926. {
  927. // Now tell windows we don't need no stinkin'
  928. // erased background because our view object
  929. // is in-place active and he/she will be
  930. // taking over from here.
  931. return TRUE;
  932. }
  933. break;
  934. case WM_PAINT:
  935. return pcoch->_OnPaint();
  936. case WM_SIZE:
  937. return pcoch->_OnSize(hwnd, lParam);
  938. case WM_DESTROY:
  939. return pcoch->_OnDestroy();
  940. case OCM_QUERYINTERFACE:
  941. return pcoch->_OnQueryInterface(wParam, lParam);
  942. case OCM_INITIALIZE:
  943. return pcoch->_InitOCStruct((LPOCHINITSTRUCT)lParam);
  944. case OCM_SETOWNER:
  945. return pcoch->_SetOwner((IUnknown*)lParam);
  946. case OCM_DOVERB:
  947. return pcoch->_DoVerb((long)wParam, (LPMSG)lParam);
  948. case OCM_ENABLEEVENTS:
  949. return pcoch->_ConnectEvents( pcoch->_punkOC, (BOOL)wParam ) ;
  950. case OCM_SETSERVICEPROVIDER:
  951. return pcoch->_SetServiceProvider((IServiceProvider*) lParam);
  952. case WM_PALETTECHANGED:
  953. if (pcoch->_pIOleIPObject) {
  954. HWND hwnd;
  955. if (SUCCEEDED(pcoch->_pIOleIPObject->GetWindow(&hwnd))) {
  956. SendMessage(hwnd, WM_PALETTECHANGED, wParam, lParam);
  957. }
  958. }
  959. break;
  960. case WM_SETFOCUS:
  961. // OC doesn't respond to OLEIVERB_UIACTIVATE ?
  962. if( pcoch->_dwMiscStatus & OLEMISC_NOUIACTIVATE )
  963. {
  964. // so explicitly assign focus
  965. HWND hwndObj ;
  966. if( pcoch->_pIOleIPObject &&
  967. SUCCEEDED( pcoch->_pIOleIPObject->GetWindow( &hwndObj ) ) )
  968. SetFocus( hwndObj ) ;
  969. }
  970. else
  971. pcoch->_DoVerb( OLEIVERB_UIACTIVATE, NULL ) ;
  972. break ;
  973. default:
  974. return DefWindowProcWrap(hwnd, uMsg, wParam, lParam);
  975. }
  976. return 0;
  977. }
  978. void COleControlHost::_RegisterClass()
  979. {
  980. WNDCLASS wc = {0};
  981. wc.style = CS_GLOBALCLASS;
  982. wc.lpfnWndProc = OCHostWndProc;
  983. //wc.cbClsExtra = 0;
  984. wc.cbWndExtra = SIZEOF(LPVOID);
  985. wc.hInstance = HINST_THISDLL;
  986. //wc.hIcon = NULL;
  987. wc.hCursor = LoadCursor (NULL, IDC_ARROW);
  988. wc.hbrBackground = (HBRUSH) (COLOR_BACKGROUND + 1);
  989. //wc.lpszMenuName = NULL;
  990. wc.lpszClassName = OCHOST_CLASS;
  991. SHRegisterClass(&wc);
  992. }
  993. HRESULT CProxyUIHandler::QueryInterface(REFIID riid, LPVOID * ppvObj)
  994. {
  995. COleControlHost *poch = IToClass(COleControlHost, _xuih, this);
  996. return poch->QueryInterface(riid, ppvObj);
  997. };
  998. ULONG CProxyUIHandler::AddRef(void)
  999. {
  1000. COleControlHost *poch = IToClass(COleControlHost, _xuih, this);
  1001. return poch->AddRef();
  1002. };
  1003. ULONG CProxyUIHandler::Release(void)
  1004. {
  1005. COleControlHost *poch = IToClass(COleControlHost, _xuih, this);
  1006. return poch->Release();
  1007. };
  1008. HRESULT CProxyUIHandler::ShowContextMenu(DWORD dwID, POINT *ppt, IUnknown *pcmdtReserved, IDispatch *pdispReserved)
  1009. {
  1010. COleControlHost *poch = IToClass(COleControlHost, _xuih, this);
  1011. return poch->_pIDocHostUIParent ? poch->_pIDocHostUIParent->ShowContextMenu(dwID, ppt, pcmdtReserved, pdispReserved) : E_NOTIMPL;
  1012. }
  1013. HRESULT CProxyUIHandler::GetHostInfo(DOCHOSTUIINFO *pInfo)
  1014. {
  1015. COleControlHost *poch = IToClass(COleControlHost, _xuih, this);
  1016. return poch->_pIDocHostUIParent ? poch->_pIDocHostUIParent->GetHostInfo(pInfo) : E_NOTIMPL;
  1017. }
  1018. HRESULT CProxyUIHandler::ShowUI(DWORD dwID, IOleInPlaceActiveObject *pActiveObject, IOleCommandTarget *pCommandTarget, IOleInPlaceFrame *pFrame, IOleInPlaceUIWindow *pDoc)
  1019. {
  1020. COleControlHost *poch = IToClass(COleControlHost, _xuih, this);
  1021. return poch->_pIDocHostUIParent ? poch->_pIDocHostUIParent->ShowUI(dwID, pActiveObject, pCommandTarget, pFrame, pDoc): E_NOTIMPL;
  1022. }
  1023. HRESULT CProxyUIHandler::HideUI()
  1024. {
  1025. COleControlHost *poch = IToClass(COleControlHost, _xuih, this);
  1026. return poch->_pIDocHostUIParent ? poch->_pIDocHostUIParent->HideUI(): E_NOTIMPL;
  1027. }
  1028. HRESULT CProxyUIHandler::UpdateUI()
  1029. {
  1030. COleControlHost *poch = IToClass(COleControlHost, _xuih, this);
  1031. return poch->_pIDocHostUIParent ? poch->_pIDocHostUIParent->UpdateUI(): E_NOTIMPL;
  1032. }
  1033. HRESULT CProxyUIHandler::EnableModeless(BOOL fActivate)
  1034. {
  1035. COleControlHost *poch = IToClass(COleControlHost, _xuih, this);
  1036. return poch->_pIDocHostUIParent ? poch->_pIDocHostUIParent->EnableModeless(fActivate): E_NOTIMPL;
  1037. }
  1038. HRESULT CProxyUIHandler::OnDocWindowActivate(BOOL fActivate)
  1039. {
  1040. COleControlHost *poch = IToClass(COleControlHost, _xuih, this);
  1041. return poch->_pIDocHostUIParent ? poch->_pIDocHostUIParent->OnDocWindowActivate(fActivate): E_NOTIMPL;
  1042. }
  1043. HRESULT CProxyUIHandler::OnFrameWindowActivate(BOOL fActivate)
  1044. {
  1045. COleControlHost *poch = IToClass(COleControlHost, _xuih, this);
  1046. return poch->_pIDocHostUIParent ? poch->_pIDocHostUIParent->OnFrameWindowActivate(fActivate): E_NOTIMPL;
  1047. }
  1048. HRESULT CProxyUIHandler::ResizeBorder(LPCRECT prcBorder, IOleInPlaceUIWindow *pUIWindow, BOOL fRameWindow)
  1049. {
  1050. COleControlHost *poch = IToClass(COleControlHost, _xuih, this);
  1051. return poch->_pIDocHostUIParent ? poch->_pIDocHostUIParent->ResizeBorder(prcBorder, pUIWindow, fRameWindow): E_NOTIMPL;
  1052. }
  1053. HRESULT CProxyUIHandler::TranslateAccelerator(LPMSG lpMsg, const GUID *pguidCmdGroup, DWORD nCmdID)
  1054. {
  1055. COleControlHost *poch = IToClass(COleControlHost, _xuih, this);
  1056. return poch->_pIDocHostUIParent ? poch->_pIDocHostUIParent->TranslateAccelerator(lpMsg, pguidCmdGroup, nCmdID): E_NOTIMPL;
  1057. }
  1058. HRESULT CProxyUIHandler::GetOptionKeyPath(LPOLESTR *pchKey, DWORD dw)
  1059. {
  1060. COleControlHost *poch = IToClass(COleControlHost, _xuih, this);
  1061. return poch->_pIDocHostUIParent ? poch->_pIDocHostUIParent->GetOptionKeyPath(pchKey, dw): E_NOTIMPL;
  1062. }
  1063. HRESULT CProxyUIHandler::GetDropTarget(IDropTarget *pDropTarget, IDropTarget **ppDropTarget)
  1064. {
  1065. COleControlHost *poch = IToClass(COleControlHost, _xuih, this);
  1066. return poch->_pIDocHostUIParent ? poch->_pIDocHostUIParent->GetDropTarget(pDropTarget, ppDropTarget) : E_NOTIMPL;
  1067. }
  1068. HRESULT CProxyUIHandler::GetExternal(IDispatch **ppDispatch)
  1069. {
  1070. COleControlHost *poch = IToClass(COleControlHost, _xuih, this);
  1071. return poch->_pIDocHostUIParent ? poch->_pIDocHostUIParent->GetExternal(ppDispatch) : E_NOTIMPL;
  1072. }
  1073. HRESULT CProxyUIHandler::TranslateUrl(DWORD dwTranslate, OLECHAR *pchURLIn, OLECHAR **ppchURLOut)
  1074. {
  1075. COleControlHost *poch = IToClass(COleControlHost, _xuih, this);
  1076. return poch->_pIDocHostUIParent ? poch->_pIDocHostUIParent->TranslateUrl(dwTranslate, pchURLIn, ppchURLOut) : E_NOTIMPL;
  1077. }
  1078. HRESULT CProxyUIHandler::FilterDataObject( IDataObject *pDO, IDataObject **ppDORet)
  1079. {
  1080. COleControlHost *poch = IToClass(COleControlHost, _xuih, this);
  1081. return poch->_pIDocHostUIParent ? poch->_pIDocHostUIParent->FilterDataObject(pDO, ppDORet) : E_NOTIMPL;
  1082. }
  1083. HRESULT CProxyUIHandler::GetOverrideKeyPath( LPOLESTR *pchKey, DWORD dw)
  1084. {
  1085. COleControlHost *poch = IToClass(COleControlHost, _xuih, this);
  1086. return poch->_pIDocHostUIParent2 ? poch->_pIDocHostUIParent2->GetOverrideKeyPath(pchKey, dw) : E_NOTIMPL;
  1087. }
  1088. STDAPI_(BOOL) DllRegisterWindowClasses(const SHDRC * pshdrc)
  1089. {
  1090. if (pshdrc && pshdrc->cbSize == SIZEOF(SHDRC) && !(pshdrc->dwFlags & ~SHDRCF_ALL))
  1091. {
  1092. if (pshdrc->dwFlags & SHDRCF_OCHOST)
  1093. {
  1094. COleControlHost::_RegisterClass();
  1095. return TRUE;
  1096. }
  1097. }
  1098. return FALSE;
  1099. }
  1100. //---------------------------------------------------------------------------
  1101. // CEventSink constructor
  1102. CEventSink::CEventSink( BOOL bAutoDelete )
  1103. : _hwndSite(NULL),
  1104. _hwndOwner(NULL),
  1105. _punkOC(NULL),
  1106. _dwCookie(0),
  1107. _cRef(1),
  1108. _bAutoDelete( bAutoDelete )
  1109. {
  1110. _iid = _iidDefault = IID_NULL ;
  1111. }
  1112. // CEventSink IUnknown impl
  1113. STDMETHODIMP CEventSink::QueryInterface( REFIID riid, void** ppvObj )
  1114. {
  1115. *ppvObj = NULL ;
  1116. if( IsEqualGUID( riid, IID_IUnknown ) ||
  1117. IsEqualGUID( riid, IID_IDispatch )||
  1118. IsEqualGUID( riid, _iidDefault ) )
  1119. {
  1120. *ppvObj = this ;
  1121. return S_OK ;
  1122. }
  1123. return E_NOINTERFACE ;
  1124. }
  1125. STDMETHODIMP_(ULONG) CEventSink::AddRef()
  1126. {
  1127. return InterlockedIncrement( &_cRef ) ;
  1128. }
  1129. STDMETHODIMP_(ULONG) CEventSink::Release()
  1130. {
  1131. ASSERT( 0 != _cRef );
  1132. ULONG cRef = InterlockedDecrement( &_cRef );
  1133. if( 0 == cRef )
  1134. {
  1135. if( _bAutoDelete )
  1136. {
  1137. delete this ;
  1138. }
  1139. }
  1140. return cRef ;
  1141. }
  1142. // Connects the sink to the OC's default event dispatch interface.
  1143. BOOL CEventSink::Connect( HWND hwndOwner, HWND hwndSite, LPUNKNOWN punkOC )
  1144. {
  1145. ASSERT( punkOC ) ;
  1146. IID iidDefault = IID_NULL ;
  1147. if( SUCCEEDED( _GetDefaultEventIID( punkOC, &iidDefault ) ) )
  1148. {
  1149. _iidDefault = iidDefault ;
  1150. return _Connect( hwndOwner, hwndSite, punkOC, iidDefault ) ;
  1151. }
  1152. return FALSE ;
  1153. }
  1154. // Establishes advise connection on the specified interface
  1155. BOOL CEventSink::_Connect( HWND hwndOwner, HWND hwndSite, LPUNKNOWN punkOC, REFIID iid )
  1156. {
  1157. LPCONNECTIONPOINTCONTAINER pcpc;
  1158. ASSERT(punkOC != NULL) ;
  1159. HRESULT hr = CONNECT_E_CANNOTCONNECT ;
  1160. if( _IsConnected( iid ) )
  1161. return TRUE ;
  1162. if( _dwCookie )
  1163. Disconnect() ;
  1164. if( punkOC &&
  1165. SUCCEEDED( punkOC->QueryInterface(IID_IConnectionPointContainer, (LPVOID*)&pcpc )))
  1166. {
  1167. LPCONNECTIONPOINT pcp = NULL;
  1168. DWORD dwCookie = 0;
  1169. ASSERT(pcpc != NULL);
  1170. if( SUCCEEDED(pcpc->FindConnectionPoint( iid, &pcp )))
  1171. {
  1172. ASSERT(pcp != NULL);
  1173. hr = pcp->Advise( this, &dwCookie ) ;
  1174. if( SUCCEEDED( hr ) )
  1175. {
  1176. _iid = iid ;
  1177. _dwCookie = dwCookie ;
  1178. _hwndOwner = hwndOwner ;
  1179. _hwndSite = hwndSite ;
  1180. _punkOC = punkOC ;
  1181. _punkOC->AddRef() ;
  1182. }
  1183. pcp->Release();
  1184. }
  1185. pcpc->Release();
  1186. }
  1187. return SUCCEEDED( hr ) ;
  1188. }
  1189. // Retrieves default event dispatch interface from the OC.
  1190. HRESULT CEventSink::_GetDefaultEventIID( LPUNKNOWN punkOC, IID* piid )
  1191. {
  1192. HRESULT hr ;
  1193. ASSERT( punkOC ) ;
  1194. ASSERT( piid ) ;
  1195. IProvideClassInfo *pci ;
  1196. IProvideClassInfo2 *pci2 ;
  1197. *piid = IID_NULL ;
  1198. #define IMPLTYPE_MASK \
  1199. (IMPLTYPEFLAG_FDEFAULT|IMPLTYPEFLAG_FSOURCE|IMPLTYPEFLAG_FRESTRICTED)
  1200. #define IMPLTYPE_DEFAULTSOURCE \
  1201. (IMPLTYPEFLAG_FDEFAULT|IMPLTYPEFLAG_FSOURCE)
  1202. // Retrieve default outbound dispatch IID using OC's IProvideClassInfo2
  1203. if( SUCCEEDED( (hr = punkOC->QueryInterface( IID_IProvideClassInfo2, (void**)&pci2 )) ) )
  1204. {
  1205. hr = pci2->GetGUID( GUIDKIND_DEFAULT_SOURCE_DISP_IID, piid ) ;
  1206. pci2->Release() ;
  1207. }
  1208. else // no IProvideClassInfo2; try IProvideClassInfo:
  1209. if( SUCCEEDED( (hr = punkOC->QueryInterface( IID_IProvideClassInfo, (void**)&pci )) ) )
  1210. {
  1211. ITypeInfo* pClassInfo = NULL;
  1212. if( SUCCEEDED( (hr = pci->GetClassInfo( &pClassInfo )) ) )
  1213. {
  1214. LPTYPEATTR pClassAttr;
  1215. ASSERT( pClassInfo );
  1216. if( SUCCEEDED( (hr = pClassInfo->GetTypeAttr( &pClassAttr )) ) )
  1217. {
  1218. ASSERT( pClassAttr ) ;
  1219. ASSERT( pClassAttr->typekind == TKIND_COCLASS ) ;
  1220. // Enumerate implemented interfaces looking for default source IID.
  1221. HREFTYPE hRefType;
  1222. int nFlags;
  1223. for( UINT i = 0; i < pClassAttr->cImplTypes; i++ )
  1224. {
  1225. if( SUCCEEDED( (hr = pClassInfo->GetImplTypeFlags( i, &nFlags )) ) &&
  1226. ((nFlags & IMPLTYPE_MASK) == IMPLTYPE_DEFAULTSOURCE) )
  1227. {
  1228. // Got the interface, now retrieve its IID:
  1229. ITypeInfo* pEventInfo = NULL ;
  1230. if( SUCCEEDED( (hr = pClassInfo->GetRefTypeOfImplType( i, &hRefType )) ) &&
  1231. SUCCEEDED( (hr = pClassInfo->GetRefTypeInfo( hRefType, &pEventInfo )) ) )
  1232. {
  1233. LPTYPEATTR pEventAttr;
  1234. ASSERT( pEventInfo ) ;
  1235. if( SUCCEEDED( (hr = pEventInfo->GetTypeAttr( &pEventAttr )) ) )
  1236. {
  1237. *piid = pEventAttr->guid ;
  1238. pEventInfo->ReleaseTypeAttr(pEventAttr);
  1239. }
  1240. pEventInfo->Release();
  1241. }
  1242. break;
  1243. }
  1244. }
  1245. pClassInfo->ReleaseTypeAttr(pClassAttr);
  1246. }
  1247. pClassInfo->Release();
  1248. }
  1249. pci->Release() ;
  1250. }
  1251. if( SUCCEEDED( hr ) && IsEqualIID( *piid, IID_NULL ) )
  1252. hr = E_FAIL ;
  1253. return hr ;
  1254. }
  1255. // reports whether the sink is connected to the indicated sink
  1256. BOOL CEventSink::_IsConnected( REFIID iid )
  1257. {
  1258. return _dwCookie != 0L &&
  1259. IsEqualIID( iid, _iid ) ;
  1260. }
  1261. // disconnects the sink
  1262. BOOL CEventSink::Disconnect()
  1263. {
  1264. LPCONNECTIONPOINTCONTAINER pcpc;
  1265. if( _dwCookie != 0 &&
  1266. _punkOC &&
  1267. SUCCEEDED( _punkOC->QueryInterface(IID_IConnectionPointContainer, (LPVOID*)&pcpc)))
  1268. {
  1269. LPCONNECTIONPOINT pcp = NULL;
  1270. ASSERT(pcpc != NULL);
  1271. if (SUCCEEDED(pcpc->FindConnectionPoint(_iid, &pcp)))
  1272. {
  1273. ASSERT(pcp != NULL);
  1274. pcp->Unadvise(_dwCookie);
  1275. pcp->Release();
  1276. _iid = IID_NULL ;
  1277. _dwCookie = 0L ;
  1278. _hwndOwner = NULL ;
  1279. _hwndSite = NULL ;
  1280. _punkOC->Release() ;
  1281. _punkOC = NULL ;
  1282. }
  1283. pcpc->Release();
  1284. return TRUE ;
  1285. }
  1286. return FALSE ;
  1287. }
  1288. // CEventSink IDispatch interface
  1289. STDMETHODIMP CEventSink::Invoke(
  1290. IN DISPID dispIdMember,
  1291. IN REFIID riid,
  1292. IN LCID lcid,
  1293. IN WORD wFlags,
  1294. IN OUT DISPPARAMS *pDispParams,
  1295. OUT VARIANT *pVarResult,
  1296. OUT EXCEPINFO *pExcepInfo,
  1297. OUT UINT *puArgErr)
  1298. {
  1299. // Copy method args to notification block
  1300. NMOCEVENT event = {0};
  1301. event.hdr.hwndFrom = _hwndSite;
  1302. event.hdr.idFrom = GetDlgCtrlID( _hwndSite ) ;
  1303. event.hdr.code = OCN_OCEVENT ;
  1304. event.dispID = dispIdMember ;
  1305. event.iid = riid ;
  1306. event.lcid = lcid ;
  1307. event.wFlags = wFlags ;
  1308. event.pDispParams = pDispParams ;
  1309. event.pVarResult = pVarResult ;
  1310. event.pExepInfo = pExcepInfo ;
  1311. event.puArgErr = puArgErr ;
  1312. // Notify parent of event
  1313. ::SendMessage( _hwndOwner, WM_NOTIFY, event.hdr.idFrom, (LPARAM)&event ) ;
  1314. // Cleanup args
  1315. if (pVarResult != NULL)
  1316. VariantClear( pVarResult ) ;
  1317. return S_OK ;
  1318. }