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.

1620 lines
46 KiB

  1. // Copyright (C) 1996-1997 Microsoft Corporation. All rights reserved.
  2. #include "header.h"
  3. #include "CtlHelp.H"
  4. #include "StdEnum.H"
  5. #include "internet.h"
  6. #include "hhctrl.h"
  7. #include <stddef.h>
  8. #include <stdarg.h>
  9. #ifndef _DEBUG
  10. #undef THIS_FILE
  11. static const char THIS_FILE[] = __FILE__;
  12. #endif
  13. // this is used in our window proc so that we can find out who was last created
  14. static COleControl *s_pLastControlCreated;
  15. //=--------------------------------------------------------------------------=
  16. // COleControl::COleControl
  17. //=--------------------------------------------------------------------------=
  18. // constructor
  19. //
  20. // Parameters:
  21. // IUnknown * - [in] controlling Unknown
  22. // int - [in] type of primary dispatch interface OBJECT_TYPE_*
  23. // void * - [in] pointer to entire object
  24. //
  25. // Notes:
  26. //
  27. COleControl::COleControl
  28. (
  29. IUnknown *pUnkOuter,
  30. int iPrimaryDispatch,
  31. void *pMainInterface
  32. )
  33. : CAutomationObject(pUnkOuter, iPrimaryDispatch, pMainInterface),
  34. m_cpEvents(SINK_TYPE_EVENT),
  35. m_cpPropNotify(SINK_TYPE_PROPNOTIFY)
  36. {
  37. // initialize all our variables -- we decided against using a memory-zeroing
  38. // memory allocator, so we sort of have to do this work now ...
  39. //
  40. m_nFreezeEvents = 0;
  41. m_pClientSite = NULL;
  42. m_pControlSite = NULL;
  43. m_pInPlaceSite = NULL;
  44. m_pInPlaceFrame = NULL;
  45. m_pInPlaceUIWindow = NULL;
  46. m_pInPlaceSiteWndless = NULL;
  47. // certain hosts don't like 0,0 as your initial size, so we're going to set
  48. // our initial size to 100,50 [so it's at least sort of visible on the screen]
  49. m_Size.cx = 100;
  50. m_Size.cy = 50;
  51. SetRectEmpty(&m_rcLocation);
  52. m_hwnd = NULL;
  53. m_hwndParent = NULL;
  54. m_nFreezeEvents = 0;
  55. // m_pSimpleFrameSite = NULL;
  56. m_pOleAdviseHolder = NULL;
  57. m_pViewAdviseSink = NULL;
  58. m_pDispAmbient = NULL;
  59. m_fDirty = FALSE;
  60. m_fModeFlagValid = FALSE;
  61. m_fInPlaceActive = FALSE;
  62. m_fInPlaceVisible = FALSE;
  63. m_fUIActive = FALSE;
  64. m_fSaveSucceeded = FALSE;
  65. m_fViewAdvisePrimeFirst = FALSE;
  66. m_fViewAdviseOnlyOnce = FALSE;
  67. m_fRunMode = FALSE;
  68. }
  69. //=--------------------------------------------------------------------------=
  70. // COleControl::~COleControl
  71. //=--------------------------------------------------------------------------=
  72. // "We are all of us resigned to death; it's life we aren't resigned to."
  73. // - Graham Greene (1904-91)
  74. //
  75. // Notes:
  76. //
  77. COleControl::~COleControl()
  78. {
  79. // if we've still got a window, go and kill it now.
  80. //
  81. if (m_hwnd) {
  82. // so our window proc doesn't crash.
  83. //
  84. SetWindowLong(m_hwnd, GWLP_USERDATA, 0xFFFFFFFF);
  85. DestroyWindow(m_hwnd);
  86. }
  87. // clean up all the pointers we're holding around.
  88. QUICK_RELEASE(m_pClientSite);
  89. QUICK_RELEASE(m_pControlSite);
  90. QUICK_RELEASE(m_pInPlaceSite);
  91. QUICK_RELEASE(m_pInPlaceFrame);
  92. QUICK_RELEASE(m_pInPlaceUIWindow);
  93. // QUICK_RELEASE(m_pSimpleFrameSite);
  94. QUICK_RELEASE(m_pOleAdviseHolder);
  95. QUICK_RELEASE(m_pViewAdviseSink);
  96. QUICK_RELEASE(m_pDispAmbient);
  97. QUICK_RELEASE(m_pInPlaceSiteWndless);
  98. }
  99. //=--------------------------------------------------------------------------=
  100. // COleControl::InternalQueryInterface
  101. //=--------------------------------------------------------------------------=
  102. // derived-controls should delegate back to this when they decide to support
  103. // additional interfaces
  104. //
  105. // Parameters:
  106. // REFIID - [in] interface they want
  107. // void ** - [out] where they want to put the resulting object ptr.
  108. //
  109. // Output:
  110. // HRESULT - S_OK, E_NOINTERFACE
  111. //
  112. // Notes:
  113. // - NOTE: this function is speed critical!!!!
  114. // Using the typedef'd enum lets use see what the value of riid.Data1 is
  115. typedef enum {
  116. tgIUnknown = 0x00000000,
  117. tgIClassFactory = 0x00000001,
  118. tgIMalloc = 0x00000002,
  119. tgIMarshal = 0x00000003,
  120. tgIPSFactory = 0x00000009,
  121. tgILockBytes = 0x0000000a,
  122. tgIStorage = 0x0000000b,
  123. tgIStream = 0x0000000c,
  124. tgIEnumSTATSTG = 0x0000000d,
  125. tgIBindCtx = 0x0000000e,
  126. tgIMoniker = 0x0000000f,
  127. tgIRunningObjectTable = 0x00000010,
  128. tgIInternalMoniker = 0x00000011,
  129. tgIRootStorage = 0x00000012,
  130. tgIMessageFilter = 0x00000016,
  131. tgIStdMarshalInfo = 0x00000018,
  132. tgIExternalConnection = 0x00000019,
  133. tgIWeakRef = 0x0000001a,
  134. tgIEnumUnknown = 0x00000100,
  135. tgIEnumString = 0x00000101,
  136. tgIEnumMoniker = 0x00000102,
  137. tgIEnumFORMATETC = 0x00000103,
  138. tgIEnumOLEVERB = 0x00000104,
  139. tgIEnumSTATDATA = 0x00000105,
  140. tgIEnumGeneric = 0x00000106,
  141. tgIEnumHolder = 0x00000107,
  142. tgIEnumCallback = 0x00000108,
  143. tgIPersistStream = 0x00000109,
  144. tgIPersistStorage = 0x0000010a,
  145. tgIPersistFile = 0x0000010b,
  146. tgIPersist = 0x0000010c,
  147. tgIViewObject = 0x0000010d,
  148. tgIDataObject = 0x0000010e,
  149. tgIAdviseSink = 0x0000010f,
  150. tgIDataAdviseHolder = 0x00000110,
  151. tgIOleAdviseHolder = 0x00000111,
  152. tgIOleObject = 0x00000112,
  153. tgIOleInPlaceObject = 0x00000113,
  154. tgIOleWindow = 0x00000114,
  155. tgIOleInPlaceUIWindow = 0x00000115,
  156. tgIOleInPlaceFrame = 0x00000116,
  157. tgIOleInPlaceActiveObject = 0x00000117,
  158. tgIOleClientSite = 0x00000118,
  159. tgIOleInPlaceSite = 0x00000119,
  160. tgIParseDisplayName = 0x0000011a,
  161. tgIOleContainer = 0x0000011b,
  162. tgIOleItemContainer = 0x0000011c,
  163. tgIOleLink = 0x0000011d,
  164. tgIOleCache = 0x0000011e,
  165. tgIOleManager = 0x0000011f,
  166. tgIOlePresObj = 0x00000120,
  167. tgIDropSource = 0x00000121,
  168. tgIDropTarget = 0x00000122,
  169. tgIAdviseSink2 = 0x00000125,
  170. tgIRunnableObject = 0x00000126,
  171. tgIViewObject2 = 0x00000127,
  172. tgIOleCache2 = 0x00000128,
  173. tgIOleCacheControl = 0x00000129,
  174. tgIDispatch = 0x00020400,
  175. tgITypeInfo = 0x00020401,
  176. tgITypeLib = 0x00020402,
  177. tgITypeComp = 0x00020403,
  178. tgIEnumVARIANT = 0x00020404,
  179. tgICreateTypeInfo = 0x00020405,
  180. tgICreateTypeLib = 0x00020406,
  181. tgIPropertyPage2 = 0x01e44665,
  182. tgIOleInPlaceObjectWindowless = 0x1c2056cc,
  183. tgIErrorInfo = 0x1cf2b120,
  184. tgICreateErrorInfo = 0x22f03340,
  185. tgIPerPropertyBrowsing = 0x376bd3aa,
  186. tgIPersistPropertyBag = 0x37D84F60,
  187. tgIAdviseSinkEx = 0x3af24290,
  188. tgIViewObjectEx = 0x3af24292,
  189. tgICategorizeProperties = 0x4d07fc10,
  190. tgIPointerInactive = 0x55980ba0,
  191. tgIFormExpert = 0x5aac7f70,
  192. tgIOleInPlaceComponent = 0x5efc7970,
  193. tgIGangConnectWithDefault = 0x6d5140c0,
  194. tgIServiceProvider = 0x6d5140c1,
  195. tgISelectionContainer = 0x6d5140c6,
  196. tgIRequireClasses = 0x6d5140d0,
  197. tgIProvideDynamicClassInfo = 0x6d5140d1,
  198. tgIDataFrameExpert = 0x73687490,
  199. tgISimpleFrameSite = 0x742b0e01,
  200. tgIPicture = 0x7bf80980,
  201. tgIPictureDisp = 0x7bf80981,
  202. tgIPersistStreamInit = 0x7fd52380,
  203. tgIOleUndoAction = 0x894ad3b0,
  204. tgIOleInPlaceSiteWindowless = 0x922eada0,
  205. tgIDataFrame = 0x97F254E0,
  206. tgIControl_95 = 0x9a4bbfb5,
  207. tgIPropertyNotifySink = 0x9bfbbc02,
  208. tgIOleInPlaceSiteEx = 0x9c2cad80,
  209. tgIOleCompoundUndoAction = 0xa1faf330,
  210. tgIControl = 0xa7fddba0,
  211. tgIProvideClassInfo = 0xb196b283,
  212. tgIConnectionPointContainer = 0xb196b284,
  213. tgIEnumConnectionPoints = 0xb196b285,
  214. tgIConnectionPoint = 0xb196b286,
  215. tgIEnumConnections = 0xb196b287,
  216. tgIOleControl = 0xb196b288,
  217. tgIOleControlSite = 0xb196b289,
  218. tgISpecifyPropertyPages = 0xb196b28b,
  219. tgIPropertyPageSite = 0xb196b28c,
  220. tgIPropertyPage = 0xb196b28d,
  221. tgIClassFactory2 = 0xb196b28f,
  222. tgIEnumOleUndoActions = 0xb3e7c340,
  223. tgIMsoDocument = 0xb722bcc5,
  224. tgIMsoView = 0xb722bcc6,
  225. tgIMsoCommandTarget = 0xb722bccb,
  226. tgIOlePropertyFrame = 0xb83bb801,
  227. tgIPropertyPageInPlace = 0xb83bb802,
  228. tgIPropertyPage3 = 0xb83bb803,
  229. tgIPropertyPageSite2 = 0xb83bb804,
  230. tgIFont = 0xbef6e002,
  231. tgIFontDisp = 0xbef6e003,
  232. tgIQuickActivate = 0xcf51ed10,
  233. tgIOleUndoActionManager = 0xd001f200,
  234. tgIPSFactoryBuffer = 0xd5f569d0,
  235. tgIOleStandardTool = 0xd97877c4,
  236. tgISupportErrorInfo = 0xdf0b3d60,
  237. tgICDataDoc = 0xF413E4C0,
  238. } DATA1_GUIDS;
  239. HRESULT COleControl::InternalQueryInterface(REFIID riid, void **ppvObjOut)
  240. {
  241. #ifdef _DEBUG
  242. DATA1_GUIDS gd = (DATA1_GUIDS) riid.Data1;
  243. #endif
  244. switch (riid.Data1) {
  245. // private interface for prop page support
  246. case Data1_IControlPrv:
  247. if (DO_GUIDS_MATCH(riid, IID_IControlPrv)) {
  248. *ppvObjOut = (void *)this;
  249. ExternalAddRef();
  250. return S_OK;
  251. }
  252. goto NoInterface;
  253. case Data1_IOleControl:
  254. if (DO_GUIDS_MATCH(riid, IID_IOleControl))
  255. *ppvObjOut = (void *) (IOleControl*) this;
  256. break;
  257. case Data1_IPointerInactive:
  258. if (DO_GUIDS_MATCH(riid, IID_IPointerInactive))
  259. *ppvObjOut = (void *) (IPointerInactive*) this;
  260. break;
  261. case Data1_IQuickActivate:
  262. if (DO_GUIDS_MATCH(riid, IID_IQuickActivate))
  263. *ppvObjOut = (void *) (IQuickActivate*) this;
  264. break;
  265. case Data1_IOleObject:
  266. if (DO_GUIDS_MATCH(riid, IID_IOleObject))
  267. *ppvObjOut = (void *) (IOleObject*) this;
  268. break;
  269. QI_INHERITS((IPersistStorage *)this, IPersist);
  270. QI_INHERITS(this, IPersistStreamInit);
  271. QI_INHERITS(this, IOleInPlaceObject);
  272. QI_INHERITS(this, IOleInPlaceObjectWindowless);
  273. QI_INHERITS((IOleInPlaceActiveObject *)this, IOleWindow);
  274. QI_INHERITS(this, IOleInPlaceActiveObject);
  275. QI_INHERITS(this, IViewObject);
  276. QI_INHERITS(this, IViewObject2);
  277. QI_INHERITS(this, IViewObjectEx);
  278. QI_INHERITS(this, IConnectionPointContainer);
  279. // QI_INHERITS(this, ISpecifyPropertyPages);
  280. QI_INHERITS(this, IPersistStorage);
  281. QI_INHERITS(this, IPersistPropertyBag);
  282. QI_INHERITS(this, IProvideClassInfo);
  283. default:
  284. goto NoInterface;
  285. }
  286. // we like the interface, so addref and return
  287. ((IUnknown *)(*ppvObjOut))->AddRef();
  288. return S_OK;
  289. NoInterface:
  290. // delegate to super-class for automation interfaces, etc ...
  291. return CAutomationObject::InternalQueryInterface(riid, ppvObjOut);
  292. }
  293. //=--------------------------------------------------------------------------=
  294. // COleControl::FindConnectionPoint [IConnectionPointContainer]
  295. //=--------------------------------------------------------------------------=
  296. // given an IID, find a connection point sink for it.
  297. //
  298. // Parameters:
  299. // REFIID - [in] interfaces they want
  300. // IConnectionPoint ** - [out] where the cp should go
  301. //
  302. // Output:
  303. // HRESULT
  304. STDMETHODIMP COleControl::FindConnectionPoint(REFIID riid, IConnectionPoint **ppConnectionPoint)
  305. {
  306. CHECK_POINTER(ppConnectionPoint);
  307. // we support the event interface, and IDispatch for it, and we also
  308. // support IPropertyNotifySink.
  309. //
  310. if (DO_GUIDS_MATCH(riid, EVENTIIDOFCONTROL(m_ObjectType)) || DO_GUIDS_MATCH(riid, IID_IDispatch))
  311. *ppConnectionPoint = &m_cpEvents;
  312. else if (DO_GUIDS_MATCH(riid, IID_IPropertyNotifySink))
  313. *ppConnectionPoint = &m_cpPropNotify;
  314. else
  315. return E_NOINTERFACE;
  316. // generic post-processing.
  317. //
  318. (*ppConnectionPoint)->AddRef();
  319. return S_OK;
  320. }
  321. //=--------------------------------------------------------------------------=
  322. // COleControl::EnumConnectionPoints [IConnectionPointContainer]
  323. //=--------------------------------------------------------------------------=
  324. // creates an enumerator for connection points.
  325. //
  326. // Parameters:
  327. // IEnumConnectionPoints ** - [out]
  328. //
  329. // Output:
  330. // HRESULT
  331. STDMETHODIMP COleControl::EnumConnectionPoints(IEnumConnectionPoints **ppEnumConnectionPoints)
  332. {
  333. IConnectionPoint **rgConnectionPoints;
  334. CHECK_POINTER(ppEnumConnectionPoints);
  335. // Alloc an array of connection points [since our standard enum
  336. // assumes this and free's it later ]
  337. rgConnectionPoints = (IConnectionPoint **) lcCalloc(sizeof(IConnectionPoint *) * 2);
  338. RETURN_ON_NULLALLOC(rgConnectionPoints);
  339. // we support the event interface for this dude as well as IPropertyNotifySink
  340. //
  341. rgConnectionPoints[0] = &m_cpEvents;
  342. rgConnectionPoints[1] = &m_cpPropNotify;
  343. *ppEnumConnectionPoints = (IEnumConnectionPoints *)(IEnumGeneric *) new CStandardEnum(IID_IEnumConnectionPoints,
  344. 2, sizeof(IConnectionPoint *), (void *)rgConnectionPoints,
  345. CopyAndAddRefObject);
  346. if (!*ppEnumConnectionPoints) {
  347. lcFree(rgConnectionPoints);
  348. return E_OUTOFMEMORY;
  349. }
  350. return S_OK;
  351. }
  352. //=--------------------------------------------------------------------------=
  353. // COleControl::CConnectionPoint::m_pOleControl
  354. //=--------------------------------------------------------------------------=
  355. // returns a pointer to the control in which we are nested.
  356. //
  357. // Output:
  358. // COleControl *
  359. //
  360. // Notes:
  361. //
  362. inline COleControl *COleControl::CConnectionPoint::m_pOleControl
  363. (
  364. void
  365. )
  366. {
  367. return (COleControl *)((BYTE *)this - ((m_bType == SINK_TYPE_EVENT)
  368. ? offsetof(COleControl, m_cpEvents)
  369. : offsetof(COleControl, m_cpPropNotify)));
  370. }
  371. //=--------------------------------------------------------------------------=
  372. // COleControl::CConnectionPoint::QueryInterface
  373. //=--------------------------------------------------------------------------=
  374. // standard qi
  375. //
  376. // Parameters:
  377. // REFIID - [in] interface they want
  378. // void ** - [out] where they want to put the resulting object ptr.
  379. //
  380. // Output:
  381. // HRESULT - S_OK, E_NOINTERFACE
  382. STDMETHODIMP COleControl::CConnectionPoint::QueryInterface
  383. (
  384. REFIID riid,
  385. void **ppvObjOut
  386. )
  387. {
  388. if (DO_GUIDS_MATCH(riid, IID_IConnectionPoint) || DO_GUIDS_MATCH(riid, IID_IUnknown)) {
  389. *ppvObjOut = (IConnectionPoint *)this;
  390. AddRef();
  391. return S_OK;
  392. }
  393. return E_NOINTERFACE;
  394. }
  395. ULONG COleControl::CConnectionPoint::AddRef(void)
  396. {
  397. return m_pOleControl()->ExternalAddRef();
  398. }
  399. ULONG COleControl::CConnectionPoint::Release(void)
  400. {
  401. return m_pOleControl()->ExternalRelease();
  402. }
  403. //=--------------------------------------------------------------------------=
  404. // COleControl::CConnectionPoint::GetConnectionInterface
  405. //=--------------------------------------------------------------------------=
  406. // returns the interface we support connections on.
  407. //
  408. // Parameters:
  409. // IID * - [out] interface we support.
  410. //
  411. // Output:
  412. // HRESULT
  413. STDMETHODIMP COleControl::CConnectionPoint::GetConnectionInterface(IID *piid)
  414. {
  415. if (m_bType == SINK_TYPE_EVENT)
  416. *piid = EVENTIIDOFCONTROL(m_pOleControl()->m_ObjectType);
  417. else
  418. *piid = IID_IPropertyNotifySink;
  419. return S_OK;
  420. }
  421. //=--------------------------------------------------------------------------=
  422. // COleControl::CConnectionPoint::GetConnectionPointContainer
  423. //=--------------------------------------------------------------------------=
  424. // returns the connection point container
  425. //
  426. // Parameters:
  427. // IConnectionPointContainer **ppCPC
  428. //
  429. // Output:
  430. // HRESULT
  431. STDMETHODIMP COleControl::CConnectionPoint::GetConnectionPointContainer(IConnectionPointContainer **ppCPC)
  432. {
  433. return m_pOleControl()->ExternalQueryInterface(IID_IConnectionPointContainer, (void **)ppCPC);
  434. }
  435. //=--------------------------------------------------------------------------=
  436. // COleControl::CConnectiontPoint::Advise
  437. //=--------------------------------------------------------------------------=
  438. // someboyd wants to be advised when something happens.
  439. //
  440. // Parameters:
  441. // IUnknown * - [in] guy who wants to be advised.
  442. // DWORD * - [out] cookie
  443. //
  444. // Output:
  445. // HRESULT
  446. STDMETHODIMP COleControl::CConnectionPoint::Advise(IUnknown *pUnk, DWORD *pdwCookie)
  447. {
  448. HRESULT hr;
  449. void *pv;
  450. CHECK_POINTER(pdwCookie);
  451. // first, make sure everybody's got what they thinks they got
  452. if (m_bType == SINK_TYPE_EVENT) {
  453. /*
  454. * CONSIDER: 12.95 -- this theoretically is broken -- if they do
  455. * a find connection point on IDispatch, and they just happened to
  456. * also support the Event IID, we'd advise on that. this is not
  457. * awesome, but will prove entirely acceptable short term.
  458. */
  459. hr = pUnk->QueryInterface(EVENTIIDOFCONTROL(m_pOleControl()->m_ObjectType), &pv);
  460. if (FAILED(hr))
  461. hr = pUnk->QueryInterface(IID_IDispatch, &pv);
  462. }
  463. else
  464. hr = pUnk->QueryInterface(IID_IPropertyNotifySink, &pv);
  465. RETURN_ON_FAILURE(hr);
  466. // finally, add the sink. It's now been cast to the correct type and has
  467. // been AddRef'd.
  468. return AddSink(pv, pdwCookie);
  469. }
  470. #ifdef _WIN64
  471. IUnknown* COleControl::CConnectionPoint::CookieToSink( DWORD dwCookie )
  472. {
  473. for ( short i=0; i<m_cSinks; i++ )
  474. {
  475. if ( m_rgSinks64[i].dwCookie == dwCookie )
  476. return m_rgSinks64[i].pUnk;
  477. }
  478. return NULL;
  479. }
  480. DWORD COleControl::CConnectionPoint::NextCookie()
  481. {
  482. DWORD dw = m_dwNextCookie;
  483. if ( dw==0 )
  484. {
  485. // Try to find an available cookie
  486. // There must be an available cookie, since m_cSinks is a short, cookie is DWORD
  487. dw = 1;
  488. while ( CookieToSink(dw) != NULL ) // dw is used
  489. dw++;
  490. }
  491. else
  492. m_dwNextCookie++;
  493. return dw;
  494. }
  495. #endif
  496. //=--------------------------------------------------------------------------=
  497. // COleControl::CConnectionPoint::AddSink
  498. //=--------------------------------------------------------------------------=
  499. // in some cases, we'll already have done the QI, and won't need to do the
  500. // work that is done in the Advise routine above. thus, these people can
  501. // just call this instead. [this stems really from IQuickActivate]
  502. //
  503. // Parameters:
  504. // void * - [in] the sink to add. it's already been addref'd
  505. // DWORD * - [out] cookie
  506. //
  507. // Output:
  508. // HRESULT
  509. HRESULT COleControl::CConnectionPoint::AddSink(void *pv, DWORD *pdwCookie)
  510. {
  511. #ifdef _WIN64
  512. CONNECTDATA* rgUnkNew;
  513. if ( m_cSinks == 0 )
  514. {
  515. ASSERT_COMMENT(!m_rgSinks64, "this should be null when there are no sinks");
  516. m_rgSinks64 = (CONNECTDATA*)lcCalloc(8 * sizeof(CONNECTDATA));
  517. RETURN_ON_NULLALLOC(m_rgSinks64);
  518. }
  519. else if (!(m_cSinks & 0x7)) {
  520. rgUnkNew = (CONNECTDATA*)lcReAlloc(m_rgSinks64, (m_cSinks + 8) * sizeof(CONNECTDATA));
  521. RETURN_ON_NULLALLOC(rgUnkNew);
  522. m_rgSinks64 = rgUnkNew;
  523. }
  524. m_rgSinks64[m_cSinks].pUnk = (IUnknown *)pv;
  525. *pdwCookie = m_rgSinks64[m_cSinks].dwCookie = NextCookie();
  526. m_cSinks++;
  527. return S_OK;
  528. #else
  529. IUnknown **rgUnkNew;
  530. int i = 0;
  531. // we optimize the case where there is only one sink to not allocate
  532. // any storage. turns out very rarely is there more than one.
  533. //
  534. switch (m_cSinks) {
  535. case 0:
  536. ASSERT_COMMENT(!m_rgSinks, "this should be null when there are no sinks");
  537. m_rgSinks = (IUnknown **)pv;
  538. break;
  539. case 1:
  540. // go ahead and do the initial allocation. we'll get 8 at a time
  541. rgUnkNew = (IUnknown **)lcCalloc(8 * sizeof(IUnknown *));
  542. RETURN_ON_NULLALLOC(rgUnkNew);
  543. rgUnkNew[0] = (IUnknown *)m_rgSinks;
  544. rgUnkNew[1] = (IUnknown *)pv;
  545. m_rgSinks = rgUnkNew;
  546. break;
  547. default:
  548. // if we're out of sinks, then we have to increase the size
  549. // of the array
  550. if (!(m_cSinks & 0x7)) {
  551. rgUnkNew = (IUnknown **) lcReAlloc(m_rgSinks, (m_cSinks + 8) * sizeof(IUnknown *));
  552. RETURN_ON_NULLALLOC(rgUnkNew);
  553. m_rgSinks = rgUnkNew;
  554. } else
  555. rgUnkNew = m_rgSinks;
  556. rgUnkNew[m_cSinks] = (IUnknown *)pv;
  557. break;
  558. }
  559. *pdwCookie = (DWORD)pv;
  560. m_cSinks++;
  561. return S_OK;
  562. #endif
  563. }
  564. //=--------------------------------------------------------------------------=
  565. // COleControl::CConnectionPoint::Unadvise
  566. //=--------------------------------------------------------------------------=
  567. // they don't want to be told any more.
  568. //
  569. // Parameters:
  570. // DWORD - [in] the cookie we gave 'em.
  571. //
  572. // Output:
  573. // HRESULT
  574. STDMETHODIMP COleControl::CConnectionPoint::Unadvise(DWORD dwCookie)
  575. {
  576. IUnknown *pUnk;
  577. int x;
  578. if (!dwCookie)
  579. return S_OK;
  580. // see how many sinks we've currently got, and deal with things based
  581. // on that.
  582. #ifdef _WIN64
  583. pUnk = CookieToSink(dwCookie);
  584. if (pUnk == NULL)
  585. return CONNECT_E_NOCONNECTION;
  586. switch (m_cSinks) {
  587. case 1:
  588. lcFree(m_rgSinks64);
  589. m_rgSinks64 = NULL;
  590. m_dwNextCookie = 1;
  591. break;
  592. default:
  593. // there are more than one sinks. just clean up the hole we've
  594. // got in our array now.
  595. //
  596. for (x = 0; x < m_cSinks; x++)
  597. {
  598. if ((DWORD)m_rgSinks64[x].dwCookie == dwCookie)
  599. break;
  600. }
  601. if (x == m_cSinks)
  602. return CONNECT_E_NOCONNECTION;
  603. else // (x < m_cSinks - 1)
  604. memcpy(&(m_rgSinks64[x]), &(m_rgSinks64[x + 1]), (m_cSinks -1 - x) * sizeof(CONNECTDATA));
  605. break;
  606. }
  607. // we're happy
  608. //
  609. m_cSinks--;
  610. pUnk->Release();
  611. return S_OK;
  612. #else
  613. switch (m_cSinks) {
  614. case 1:
  615. // it's the only sink. make sure the ptrs are the same, and
  616. // then free things up
  617. if ((DWORD)m_rgSinks != dwCookie)
  618. return CONNECT_E_NOCONNECTION;
  619. m_rgSinks = NULL;
  620. break;
  621. case 2:
  622. // there are two sinks. go back down to one sink scenario
  623. //
  624. if ((DWORD)m_rgSinks[0] != dwCookie && (DWORD)m_rgSinks[1] != dwCookie)
  625. return CONNECT_E_NOCONNECTION;
  626. pUnk = ((DWORD)m_rgSinks[0] == dwCookie)
  627. ? m_rgSinks[1]
  628. : ((DWORD)m_rgSinks[1] == dwCookie) ? m_rgSinks[0] : NULL;
  629. if (!pUnk) return CONNECT_E_NOCONNECTION;
  630. lcFree(m_rgSinks);
  631. m_rgSinks = (IUnknown **)pUnk;
  632. break;
  633. default:
  634. // there are more than two sinks. just clean up the hole we've
  635. // got in our array now.
  636. //
  637. for (x = 0; x < m_cSinks; x++) {
  638. if ((DWORD)m_rgSinks[x] == dwCookie)
  639. break;
  640. }
  641. if (x == m_cSinks) return CONNECT_E_NOCONNECTION;
  642. if (x < m_cSinks - 1)
  643. memcpy(&(m_rgSinks[x]), &(m_rgSinks[x + 1]), (m_cSinks -1 - x) * sizeof(IUnknown *));
  644. else
  645. m_rgSinks[x] = NULL;
  646. break;
  647. }
  648. // we're happy
  649. //
  650. m_cSinks--;
  651. ((IUnknown *)dwCookie)->Release();
  652. return S_OK;
  653. #endif
  654. }
  655. //=--------------------------------------------------------------------------=
  656. // COleControl::CConnectionPoint::EnumConnections
  657. //=--------------------------------------------------------------------------=
  658. // enumerates all current connections
  659. //
  660. // Paramters:
  661. // IEnumConnections ** - [out] new enumerator object
  662. //
  663. // Output:
  664. // HRESULT
  665. //
  666. // NOtes:
  667. //
  668. STDMETHODIMP COleControl::CConnectionPoint::EnumConnections
  669. (
  670. IEnumConnections **ppEnumOut
  671. )
  672. {
  673. CONNECTDATA *rgConnectData = NULL;
  674. int i;
  675. if (m_cSinks) {
  676. // allocate some memory big enough to hold all of the sinks.
  677. rgConnectData = (CONNECTDATA *)lcCalloc(m_cSinks * sizeof(CONNECTDATA));
  678. RETURN_ON_NULLALLOC(rgConnectData);
  679. #ifdef _WIN64
  680. for (i = 0; i < m_cSinks; i++) {
  681. rgConnectData[i].pUnk = m_rgSinks64[i].pUnk;
  682. rgConnectData[i].dwCookie = m_rgSinks64[i].dwCookie;
  683. }
  684. #else
  685. // fill in the array
  686. //
  687. if (m_cSinks == 1) {
  688. rgConnectData[0].pUnk = (IUnknown *)m_rgSinks;
  689. rgConnectData[0].dwCookie = (DWORD)m_rgSinks;
  690. } else {
  691. // loop through all available sinks.
  692. //
  693. for (i = 0; i < m_cSinks; i++) {
  694. rgConnectData[i].pUnk = m_rgSinks[i];
  695. rgConnectData[i].dwCookie = (DWORD)m_rgSinks[i];
  696. }
  697. }
  698. #endif
  699. }
  700. // create yon enumerator object.
  701. //
  702. *ppEnumOut = (IEnumConnections *)(IEnumGeneric *)new CStandardEnum(IID_IEnumConnections,
  703. m_cSinks, sizeof(CONNECTDATA), rgConnectData, CopyAndAddRefObject);
  704. if (!*ppEnumOut) {
  705. lcFree(rgConnectData);
  706. return E_OUTOFMEMORY;
  707. }
  708. return S_OK;
  709. }
  710. //=--------------------------------------------------------------------------=
  711. // COleControl::CConnectionPoint::~CConnectionPoint
  712. //=--------------------------------------------------------------------------=
  713. // cleans up
  714. //
  715. // Notes:
  716. //
  717. COleControl::CConnectionPoint::~CConnectionPoint ()
  718. {
  719. int x;
  720. #ifdef _WIN64
  721. if (!m_cSinks)
  722. return;
  723. else {
  724. for (x = 0; x < m_cSinks; x++)
  725. QUICK_RELEASE(m_rgSinks64[x].pUnk);
  726. lcFree(m_rgSinks64);
  727. }
  728. #else
  729. // clean up some memory stuff
  730. //
  731. if (!m_cSinks)
  732. return;
  733. else if (m_cSinks == 1)
  734. ((IUnknown *)m_rgSinks)->Release();
  735. else {
  736. for (x = 0; x < m_cSinks; x++)
  737. QUICK_RELEASE(m_rgSinks[x]);
  738. lcFree(m_rgSinks);
  739. }
  740. #endif
  741. }
  742. //=--------------------------------------------------------------------------=
  743. // COleControl::CConnectionPiont::DoInvoke
  744. //=--------------------------------------------------------------------------=
  745. // fires an event to all listening on our event interface.
  746. //
  747. // Parameters:
  748. // DISPID - [in] event to fire.
  749. // DISPPARAMS - [in]
  750. void COleControl::CConnectionPoint::DoInvoke(DISPID dispid, DISPPARAMS *pdispparams)
  751. {
  752. int iConnection;
  753. // if we don't have any sinks, then there's nothing to do. we intentionally
  754. // ignore errors here.
  755. #ifdef _WIN64
  756. if (m_cSinks == 0)
  757. return;
  758. else
  759. for (iConnection = 0; iConnection < m_cSinks; iConnection++)
  760. ((IDispatch *)m_rgSinks64[iConnection].pUnk)->Invoke(dispid, IID_NULL, 0, DISPATCH_METHOD, pdispparams, NULL, NULL, NULL);
  761. #else
  762. if (m_cSinks == 0)
  763. return;
  764. else if (m_cSinks == 1)
  765. ((IDispatch *)m_rgSinks)->Invoke(dispid, IID_NULL, 0, DISPATCH_METHOD, pdispparams, NULL, NULL, NULL);
  766. else
  767. for (iConnection = 0; iConnection < m_cSinks; iConnection++)
  768. ((IDispatch *)m_rgSinks[iConnection])->Invoke(dispid, IID_NULL, 0, DISPATCH_METHOD, pdispparams, NULL, NULL, NULL);
  769. #endif
  770. }
  771. //=--------------------------------------------------------------------------=
  772. // COleControl::CConnectionPoint::DoOnChanged
  773. //=--------------------------------------------------------------------------=
  774. // fires the OnChanged event for IPropertyNotifySink listeners.
  775. //
  776. // Parameters:
  777. // DISPID - [in] dude that changed.
  778. //
  779. // Output:
  780. // none
  781. void COleControl::CConnectionPoint::DoOnChanged(DISPID dispid)
  782. {
  783. ASSERT_COMMENT(FALSE, "DoOnChanged called, restore the code");
  784. #if 0
  785. int iConnection;
  786. // if we don't have any sinks, then there's nothing to do.
  787. if (m_cSinks == 0)
  788. return;
  789. else if (m_cSinks == 1)
  790. ((IPropertyNotifySink *)m_rgSinks)->OnChanged(dispid);
  791. else
  792. for (iConnection = 0; iConnection < m_cSinks; iConnection++)
  793. ((IPropertyNotifySink *)m_rgSinks[iConnection])->OnChanged(dispid);
  794. #endif
  795. }
  796. //=--------------------------------------------------------------------------=
  797. // COleControl::CConnectionPoint::DoOnRequestEdit
  798. //=--------------------------------------------------------------------------=
  799. // fires the OnRequestEdit for IPropertyNotifySinkListeners
  800. //
  801. // Parameters:
  802. // DISPID - [in] dispid user wants to change.
  803. //
  804. // Output:
  805. // BOOL - false means you cant
  806. BOOL COleControl::CConnectionPoint::DoOnRequestEdit(DISPID dispid)
  807. {
  808. HRESULT hr;
  809. int iConnection;
  810. #ifdef _WIN64
  811. if (m_cSinks == 0)
  812. hr = S_OK;
  813. else {
  814. for (iConnection = 0; iConnection < m_cSinks; iConnection++) {
  815. hr = ((IPropertyNotifySink *)m_rgSinks64[iConnection].pUnk)->OnRequestEdit(dispid);
  816. if (hr != S_OK) break;
  817. }
  818. }
  819. #else
  820. // if we don't have any sinks, then there's nothing to do.
  821. if (m_cSinks == 0)
  822. hr = S_OK;
  823. else if (m_cSinks == 1)
  824. hr =((IPropertyNotifySink *)m_rgSinks)->OnRequestEdit(dispid);
  825. else {
  826. for (iConnection = 0; iConnection < m_cSinks; iConnection++) {
  827. hr = ((IPropertyNotifySink *)m_rgSinks[iConnection])->OnRequestEdit(dispid);
  828. if (hr != S_OK) break;
  829. }
  830. }
  831. #endif
  832. return (hr == S_OK) ? TRUE : FALSE;
  833. }
  834. //=--------------------------------------------------------------------------=
  835. // COleControl::CreateInPlaceWindow
  836. //=--------------------------------------------------------------------------=
  837. // creates the window with which we will be working.
  838. // yay.
  839. //
  840. // Parameters:
  841. // int - [in] left
  842. // int - [in] top
  843. // BOOL - [in] can we skip redrawing?
  844. //
  845. // Output:
  846. // HWND
  847. //
  848. // Notes:
  849. // - DANGER! DANGER! this function is protected so that anybody can call it
  850. // from their control. however, people should be extremely careful of when
  851. // and why they do this. preferably, this function would only need to be
  852. // called by an end-control writer in design mode to take care of some
  853. // hosting/painting issues. otherwise, the framework should be left to
  854. // call it when it wants.
  855. HWND COleControl::CreateInPlaceWindow(int x, int y, BOOL fNoRedraw)
  856. {
  857. BOOL fVisible;
  858. DWORD dwWindowStyle, dwExWindowStyle;
  859. char szWindowTitle[128];
  860. // if we've already got a window, do nothing.
  861. if (m_hwnd)
  862. return m_hwnd;
  863. // get the user to register the class if it's not already
  864. // been done. we have to critical section this since more than one thread
  865. // can be trying to create this control
  866. if (!CTLWNDCLASSREGISTERED(m_ObjectType)) {
  867. // EnterCriticalSection(&g_CriticalSection);
  868. if (!RegisterClassData()) {
  869. // LeaveCriticalSection(&g_CriticalSection);
  870. return NULL;
  871. }
  872. else
  873. CTLWNDCLASSREGISTERED(m_ObjectType) = TRUE;
  874. // LeaveCriticalSection(&g_CriticalSection);
  875. }
  876. dwWindowStyle = dwExWindowStyle = 0;
  877. szWindowTitle[0] = '\0';
  878. if (!BeforeCreateWindow(&dwWindowStyle, &dwExWindowStyle, szWindowTitle))
  879. return NULL;
  880. dwWindowStyle |= (WS_CHILD | WS_CLIPSIBLINGS);
  881. // create window visible if parent hidden (common case)
  882. // otherwise, create hidden, then shown. this is a little subtle, but
  883. // it makes sense eventually.
  884. ASSERT(m_hwndParent); // why would this ever occur? [rw]
  885. if (!m_hwndParent)
  886. m_hwndParent = GetParkingWindow();
  887. fVisible = IsWindowVisible(m_hwndParent);
  888. if (!fVisible)
  889. dwWindowStyle |= WS_VISIBLE;
  890. // we have to mutex the entire create window process since we need to use
  891. // the s_pLastControlCreated to pass in the object pointer. nothing too
  892. // serious
  893. // EnterCriticalSection(&g_CriticalSection);
  894. s_pLastControlCreated = this;
  895. m_fCreatingWindow = TRUE;
  896. // finally, go create the window, parenting it as appropriate.
  897. m_hwnd = CreateWindowEx(dwExWindowStyle,
  898. WNDCLASSNAMEOFCONTROL(m_ObjectType),
  899. szWindowTitle,
  900. dwWindowStyle,
  901. x, y,
  902. m_Size.cx, m_Size.cy,
  903. m_hwndParent,
  904. NULL, _Module.GetModuleInstance(), NULL);
  905. // clean up some variables, and leave the critical section
  906. m_fCreatingWindow = FALSE;
  907. s_pLastControlCreated = NULL;
  908. // LeaveCriticalSection(&g_CriticalSection);
  909. if (IsValidWindow(m_hwnd)) {
  910. // let the derived-control do something if they so desire
  911. if (!AfterCreateWindow()) {
  912. BeforeDestroyWindow();
  913. SetWindowLong(m_hwnd, GWLP_USERDATA, 0xFFFFFFFF);
  914. DestroyWindow(m_hwnd);
  915. m_hwnd = NULL;
  916. return m_hwnd;
  917. }
  918. // if we didn't create the window visible, show it now.
  919. if (fVisible)
  920. SetWindowPos(m_hwnd,
  921. // m_hwndParent,
  922. NULL, // RAID #30314
  923. 0, 0, 0, 0,
  924. SWP_NOSIZE | SWP_NOMOVE | SWP_NOZORDER | SWP_SHOWWINDOW | (fNoRedraw) ? SWP_NOREDRAW : 0);
  925. }
  926. // finally, tell the host of this
  927. if (m_pClientSite)
  928. m_pClientSite->ShowObject();
  929. return m_hwnd;
  930. }
  931. //=--------------------------------------------------------------------------=
  932. // COleControl::SetInPlaceParent [helper]
  933. //=--------------------------------------------------------------------------=
  934. // sets up the parent window for our control.
  935. //
  936. // Parameters:
  937. // HWND - [in] new parent window
  938. void COleControl::SetInPlaceParent(HWND hwndParent)
  939. {
  940. ASSERT_COMMENT(!m_pInPlaceSiteWndless, "This routine should only get called for windowed OLE controls");
  941. if (m_hwndParent == hwndParent)
  942. return;
  943. m_hwndParent = hwndParent;
  944. if (m_hwnd)
  945. SetParent(m_hwnd, hwndParent);
  946. }
  947. //=--------------------------------------------------------------------------=
  948. // COleControl::ControlWindowProc
  949. //=--------------------------------------------------------------------------=
  950. // default window proc for an OLE Control. controls will have their own
  951. // window proc called from this one, after some processing is done.
  952. //
  953. // Parameters:
  954. // - see win32sdk docs.
  955. //
  956. // Notes:
  957. //
  958. LRESULT CALLBACK COleControl::ControlWindowProc(HWND hwnd, UINT msg,
  959. WPARAM wParam, LPARAM lParam)
  960. {
  961. COleControl *pCtl = ControlFromHwnd(hwnd);
  962. LRESULT lResult;
  963. // if the value isn't a positive value, then it's in some special
  964. // state [creation or destruction] this is safe because under win32,
  965. // the upper 2GB of an address space aren't available.
  966. if (!pCtl) {
  967. pCtl = s_pLastControlCreated;
  968. SetWindowLongPtr(hwnd, GWLP_USERDATA, (LONG_PTR) pCtl);
  969. pCtl->m_hwnd = hwnd;
  970. }
  971. // 17-Sep-1997 [ralphw] Changed to 0xFFFFFFFF to avoid 32-bit dependencies
  972. else if ((DWORD_PTR) pCtl == (DWORD_PTR) 0xFFFFFFFF) {
  973. return DefWindowProc(hwnd, msg, wParam, lParam);
  974. }
  975. // message preprocessing
  976. #if 0
  977. if (pCtl->m_pSimpleFrameSite) {
  978. hr = pCtl->m_pSimpleFrameSite->PreMessageFilter(hwnd, msg, wParam, lParam, &lResult, &dwCookie);
  979. if (hr == S_FALSE)
  980. return lResult;
  981. }
  982. #endif
  983. // for certain messages, do not call the user window proc. instead,
  984. // we have something else we'd like to do.
  985. switch (msg) {
  986. case WM_MOUSEACTIVATE:
  987. {
  988. pCtl->InPlaceActivate(OLEIVERB_UIACTIVATE);
  989. break;
  990. }
  991. case WM_PAINT:
  992. {
  993. // call the user's OnDraw routine.
  994. PAINTSTRUCT ps;
  995. RECT rc;
  996. HDC hdc;
  997. // if we're given an HDC, then use it
  998. // REVIEW: 17-Sep-1997 [ralphw] who's handing us a dc in wParam?
  999. if (!wParam)
  1000. hdc = BeginPaint(hwnd, &ps);
  1001. else
  1002. hdc = (HDC)wParam;
  1003. GetClientRect(hwnd, &rc);
  1004. pCtl->OnDraw(DVASPECT_CONTENT, hdc, (RECTL *)&rc, NULL, NULL, TRUE);
  1005. if (!wParam)
  1006. EndPaint(hwnd, &ps);
  1007. }
  1008. break;
  1009. default:
  1010. // call the derived-control's window proc
  1011. lResult = pCtl->WindowProc(msg, wParam, lParam);
  1012. break;
  1013. }
  1014. // message postprocessing
  1015. switch (msg) {
  1016. case WM_NCDESTROY:
  1017. // after this point, the window doesn't exist any more
  1018. pCtl->m_hwnd = NULL;
  1019. break;
  1020. // REVIEW: 14-Oct-1997 [ralphw] This message never arrives
  1021. case WM_SETFOCUS:
  1022. case WM_KILLFOCUS:
  1023. // give the control site focus notification
  1024. if (pCtl->m_fInPlaceActive && pCtl->m_pControlSite) {
  1025. DBWIN("Focus change");
  1026. pCtl->m_pControlSite->OnFocus(msg == WM_SETFOCUS);
  1027. }
  1028. break;
  1029. case WM_SIZE:
  1030. // a change in size is a change in view
  1031. if (!pCtl->m_fCreatingWindow)
  1032. pCtl->ViewChanged();
  1033. break;
  1034. }
  1035. // lastly, simple frame postmessage processing
  1036. #if 0
  1037. if (pCtl->m_pSimpleFrameSite)
  1038. pCtl->m_pSimpleFrameSite->PostMessageFilter(hwnd, msg, wParam, lParam, &lResult, dwCookie);
  1039. #endif
  1040. return lResult;
  1041. }
  1042. //=--------------------------------------------------------------------------=
  1043. // COleControl::SetFocus
  1044. //=--------------------------------------------------------------------------=
  1045. // we have to override this routine to get UI Activation correct.
  1046. //
  1047. // Parameters:
  1048. // BOOL - [in] true means take, false release
  1049. //
  1050. // Output:
  1051. // BOOL
  1052. //
  1053. // Notes:
  1054. // - CONSIDER: this is pretty messy, and it's still not entirely clear
  1055. // what the ole control/focus story is.
  1056. // REVIEW: 14-Oct-1997 [ralphw] Doesn't look like it is ever called
  1057. BOOL COleControl::SetFocus(BOOL fGrab)
  1058. {
  1059. DBWIN("COleControl::SetFocus");
  1060. HRESULT hr;
  1061. HWND hwnd;
  1062. // first thing to do is check out UI Activation state, and then set
  1063. // focus [either with windows api, or via the host for windowless
  1064. // controls]
  1065. if (m_pInPlaceSiteWndless) {
  1066. if (!m_fUIActive && fGrab)
  1067. if (FAILED(InPlaceActivate(OLEIVERB_UIACTIVATE))) return FALSE;
  1068. hr = m_pInPlaceSiteWndless->SetFocus(fGrab);
  1069. return (hr == S_OK) ? TRUE : FALSE;
  1070. }
  1071. else {
  1072. // we've got a window.
  1073. if (m_fInPlaceActive) {
  1074. hwnd = (fGrab) ? m_hwnd : m_hwndParent;
  1075. if (!m_fUIActive && fGrab)
  1076. return SUCCEEDED(InPlaceActivate(OLEIVERB_UIACTIVATE));
  1077. else
  1078. return (::SetFocus(hwnd) == hwnd);
  1079. } else
  1080. return FALSE;
  1081. }
  1082. // dead code
  1083. }
  1084. #if 0
  1085. //=--------------------------------------------------------------------------=
  1086. // COleControl::ReflectWindowProc
  1087. //=--------------------------------------------------------------------------=
  1088. // reflects window messages on to the child window.
  1089. //
  1090. // Parameters and Output:
  1091. // - see win32 sdk docs
  1092. // REVIEW: 14-Oct-1997 [ralphw] Doesn't seem to ever be called
  1093. LRESULT CALLBACK COleControl::ReflectWindowProc(HWND hwnd, UINT msg,
  1094. WPARAM wParam, LPARAM lParam)
  1095. {
  1096. COleControl *pCtl;
  1097. switch (msg) {
  1098. case WM_COMMAND:
  1099. case WM_NOTIFY:
  1100. case WM_CTLCOLORBTN:
  1101. case WM_CTLCOLORDLG:
  1102. case WM_CTLCOLOREDIT:
  1103. case WM_CTLCOLORLISTBOX:
  1104. case WM_CTLCOLORMSGBOX:
  1105. case WM_CTLCOLORSCROLLBAR:
  1106. case WM_CTLCOLORSTATIC:
  1107. case WM_DRAWITEM:
  1108. case WM_MEASUREITEM:
  1109. case WM_DELETEITEM:
  1110. case WM_VKEYTOITEM:
  1111. case WM_CHARTOITEM:
  1112. case WM_COMPAREITEM:
  1113. case WM_HSCROLL:
  1114. case WM_VSCROLL:
  1115. case WM_PARENTNOTIFY:
  1116. case WM_SETFOCUS:
  1117. case WM_SIZE:
  1118. pCtl = (COleControl *) GetWindowLong(hwnd, GWLP_USERDATA);
  1119. if (pCtl)
  1120. return SendMessage(pCtl->m_hwnd, msg, wParam, lParam);
  1121. break;
  1122. }
  1123. return DefWindowProc(hwnd, msg, wParam, lParam);
  1124. }
  1125. #endif
  1126. //=--------------------------------------------------------------------------=
  1127. // COleControl::GetAmbientProperty [callable]
  1128. //=--------------------------------------------------------------------------=
  1129. // returns the value of an ambient property
  1130. //
  1131. // Parameters:
  1132. // DISPID - [in] property to get
  1133. // VARTYPE - [in] type of desired data
  1134. // void * - [out] where to put the data
  1135. //
  1136. // Output:
  1137. // BOOL - FALSE means didn't work.
  1138. BOOL COleControl::GetAmbientProperty(DISPID dispid, VARTYPE vt, void *pData)
  1139. {
  1140. DISPPARAMS dispparams;
  1141. VARIANT v, v2;
  1142. HRESULT hr;
  1143. v.vt = VT_EMPTY;
  1144. v.lVal = 0;
  1145. v2.vt = VT_EMPTY;
  1146. v2.lVal = 0;
  1147. // get a pointer to the source of ambient properties.
  1148. //
  1149. if (!m_pDispAmbient) {
  1150. if (m_pClientSite)
  1151. m_pClientSite->QueryInterface(IID_IDispatch, (void **)&m_pDispAmbient);
  1152. if (!m_pDispAmbient)
  1153. return FALSE;
  1154. }
  1155. // now go and get the property into a variant.
  1156. memset(&dispparams, 0, sizeof(DISPPARAMS));
  1157. hr = m_pDispAmbient->Invoke(dispid, IID_NULL, 0, DISPATCH_PROPERTYGET, &dispparams,
  1158. &v, NULL, NULL);
  1159. if (FAILED(hr))
  1160. return FALSE;
  1161. // we've got the variant, so now go an coerce it to the type that the user
  1162. // wants. if the types are the same, then this will copy the stuff to
  1163. // do appropriate ref counting ...
  1164. //
  1165. hr = VariantChangeType(&v2, &v, 0, vt);
  1166. if (FAILED(hr)) {
  1167. VariantClear(&v);
  1168. return FALSE;
  1169. }
  1170. // copy the data to where the user wants it
  1171. CopyMemory(pData, &(v2.lVal), g_rgcbDataTypeSize[vt]);
  1172. VariantClear(&v);
  1173. return TRUE;
  1174. }
  1175. //=--------------------------------------------------------------------------=
  1176. // COleControl::GetAmbientFont [callable]
  1177. //=--------------------------------------------------------------------------=
  1178. // gets the current font for the user.
  1179. //
  1180. // Parameters:
  1181. // IFont ** - [out] where to put the font.
  1182. //
  1183. // Output:
  1184. // BOOL - FALSE means couldn't get it.
  1185. BOOL COleControl::GetAmbientFont(IFont **ppFont)
  1186. {
  1187. IDispatch *pFontDisp;
  1188. // we don't have to do much here except get the ambient property and QI
  1189. // it for the user.
  1190. *ppFont = NULL;
  1191. if (!GetAmbientProperty(DISPID_AMBIENT_FONT, VT_DISPATCH, &pFontDisp))
  1192. return FALSE;
  1193. pFontDisp->QueryInterface(IID_IFont, (void **)ppFont);
  1194. pFontDisp->Release();
  1195. return (*ppFont) ? TRUE : FALSE;
  1196. }
  1197. //=--------------------------------------------------------------------------=
  1198. // COleControl::DesignMode
  1199. //=--------------------------------------------------------------------------=
  1200. // returns TRUE if we're in Design mode.
  1201. //
  1202. // Output:
  1203. // BOOL - true is design mode, false is run mode
  1204. //
  1205. // Notes:
  1206. //
  1207. BOOL COleControl::DesignMode(void)
  1208. {
  1209. // BUGBUG: if we never call this, then remove it
  1210. VARIANT_BOOL f;
  1211. // if we don't already know our run mode, go and get it. we'll assume
  1212. // it's true unless told otherwise [or if the operation fails ...]
  1213. if (!m_fModeFlagValid) {
  1214. f = TRUE;
  1215. m_fModeFlagValid = TRUE;
  1216. GetAmbientProperty(DISPID_AMBIENT_USERMODE, VT_BOOL, &f);
  1217. m_fRunMode = f;
  1218. }
  1219. return !m_fRunMode;
  1220. }
  1221. //=--------------------------------------------------------------------------=
  1222. // COleControl::FireEvent
  1223. //=--------------------------------------------------------------------------=
  1224. // fires an event. handles arbitrary number of arguments.
  1225. //
  1226. // Parameters:
  1227. // EVENTINFO * - [in] struct that describes the event.
  1228. // ... - arguments to the event
  1229. //
  1230. // Output:
  1231. // none
  1232. //
  1233. // Notes:
  1234. // - use stdarg's va_* macros.
  1235. void __cdecl COleControl::FireEvent(EVENTINFO *pEventInfo, ...)
  1236. {
  1237. va_list valist;
  1238. DISPPARAMS dispparams;
  1239. VARIANT rgvParameters[MAX_ARGS];
  1240. VARIANT *pv;
  1241. VARTYPE vt;
  1242. int iParameter;
  1243. int cbSize;
  1244. ASSERT_COMMENT(pEventInfo->cParameters <= MAX_ARGS, "Doesn't support more than MAX_ARGS params.");
  1245. va_start(valist, pEventInfo);
  1246. // copy the Parameters into the rgvParameters array. make sure we reverse
  1247. // them for automation
  1248. //
  1249. pv = &(rgvParameters[pEventInfo->cParameters - 1]);
  1250. for (iParameter = 0; iParameter < pEventInfo->cParameters; iParameter++) {
  1251. vt = pEventInfo->rgTypes[iParameter];
  1252. // if it's a by value variant, then just copy the whole thing
  1253. if (vt == VT_VARIANT)
  1254. *pv = va_arg(valist, VARIANT);
  1255. else {
  1256. // copy the vt and the data value.
  1257. pv->vt = vt;
  1258. if (vt & VT_BYREF)
  1259. cbSize = sizeof(void *);
  1260. else
  1261. cbSize = g_rgcbDataTypeSize[vt];
  1262. // small optimization -- we can copy 2/4 bytes over quite
  1263. // quickly.
  1264. if (cbSize == sizeof(short))
  1265. V_I2(pv) = va_arg(valist, short);
  1266. else if (cbSize == 4)
  1267. V_I4(pv) = va_arg(valist, long);
  1268. else {
  1269. // copy over 8 bytes
  1270. ASSERT_COMMENT(cbSize == 8, "don't recognize the type!!");
  1271. V_CY(pv) = va_arg(valist, CURRENCY);
  1272. }
  1273. }
  1274. pv--;
  1275. }
  1276. // fire the event
  1277. dispparams.rgvarg = rgvParameters;
  1278. dispparams.cArgs = pEventInfo->cParameters;
  1279. dispparams.rgdispidNamedArgs = NULL;
  1280. dispparams.cNamedArgs = 0;
  1281. m_cpEvents.DoInvoke(pEventInfo->dispid, &dispparams);
  1282. va_end(valist);
  1283. }
  1284. #if 0
  1285. //=--------------------------------------------------------------------------=
  1286. // COleControl::AfterCreateWindow [overridable]
  1287. //=--------------------------------------------------------------------------=
  1288. //
  1289. // Output:
  1290. // BOOL - false means fatal error, can't continue
  1291. BOOL COleControl::AfterCreateWindow(void)
  1292. {
  1293. return TRUE;
  1294. }
  1295. #endif
  1296. //=--------------------------------------------------------------------------=
  1297. // COleControl::InvalidateControl [callable]
  1298. //=--------------------------------------------------------------------------=
  1299. void COleControl::InvalidateControl(LPCRECT lpRect)
  1300. {
  1301. if (m_fInPlaceActive)
  1302. InvalidateRect(m_hwnd, lpRect, TRUE);
  1303. else
  1304. ViewChanged();
  1305. }
  1306. //=--------------------------------------------------------------------------=
  1307. // COleControl::SetControlSize [callable]
  1308. //=--------------------------------------------------------------------------=
  1309. // sets the control size. they'll give us the size in pixels. we've got to
  1310. // convert them back to HIMETRIC before passing them on!
  1311. //
  1312. // Parameters:
  1313. // SIZEL * - [in] new size
  1314. //
  1315. // Output:
  1316. // BOOL
  1317. //
  1318. // Notes:
  1319. //
  1320. BOOL COleControl::SetControlSize(SIZEL *pSize)
  1321. {
  1322. HRESULT hr;
  1323. SIZEL slHiMetric;
  1324. PixelToHiMetric(pSize, &slHiMetric);
  1325. hr = SetExtent(DVASPECT_CONTENT, &slHiMetric);
  1326. return (FAILED(hr)) ? FALSE : TRUE;
  1327. }
  1328. //=--------------------------------------------------------------------------=
  1329. // COleControl::RecreateControlWindow [callable]
  1330. //=--------------------------------------------------------------------------=
  1331. // called by a [subclassed, typically] control to recreate it's control
  1332. // window.
  1333. //
  1334. // Parameters:
  1335. // none
  1336. //
  1337. // Output:
  1338. // HRESULT
  1339. //
  1340. // Notes:
  1341. // - NOTE: USE ME EXTREMELY SPARINGLY! THIS IS AN EXTREMELY EXPENSIVE
  1342. // OPERATION!
  1343. //
  1344. #if 0
  1345. HRESULT COleControl::RecreateControlWindow(void)
  1346. {
  1347. HRESULT hr;
  1348. HWND hwndPrev;
  1349. DBWIN("RecreateControlWindow called -- it probably shouldn't be.");
  1350. // we need to correctly preserve the control's position within the
  1351. // z-order here.
  1352. if (m_hwnd)
  1353. hwndPrev = ::GetWindow(m_hwnd, GW_HWNDPREV);
  1354. // if we're in place active, then we have to deactivate, and reactivate
  1355. // ourselves with the new window ...
  1356. if (m_fInPlaceActive) {
  1357. hr = InPlaceDeactivate();
  1358. RETURN_ON_FAILURE(hr);
  1359. hr = InPlaceActivate((m_fUIActive) ? OLEIVERB_UIACTIVATE : OLEIVERB_INPLACEACTIVATE);
  1360. RETURN_ON_FAILURE(hr);
  1361. } else if (m_hwnd) {
  1362. DestroyWindow(m_hwnd);
  1363. m_hwnd = NULL;
  1364. CreateInPlaceWindow(0, 0, FALSE);
  1365. }
  1366. // restore z-order position
  1367. if (m_hwnd)
  1368. SetWindowPos(m_hwnd, hwndPrev, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE);
  1369. return m_hwnd ? S_OK : E_FAIL;
  1370. }
  1371. #endif