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.

1695 lines
48 KiB

  1. //=--------------------------------------------------------------------------=
  2. // CtlMisc.Cpp
  3. //=--------------------------------------------------------------------------=
  4. // Copyright 1995-1996 Microsoft Corporation. All Rights Reserved.
  5. //
  6. // THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
  7. // ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
  8. // THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
  9. // PARTICULAR PURPOSE.
  10. //=--------------------------------------------------------------------------=
  11. //
  12. // things that aren't elsewhere, such as property pages, and connection
  13. // points.
  14. #include "IPServer.H"
  15. #include "CtrlObj.H"
  16. #include "CtlHelp.H"
  17. #include "Globals.H"
  18. #include "StdEnum.H"
  19. #include "Util.H"
  20. #include <stdarg.h>
  21. // for ASSERT and FAIL
  22. //
  23. SZTHISFILE
  24. // this is used in our window proc so that we can find out who was last created
  25. //
  26. static COleControl *s_pLastControlCreated;
  27. //=--------------------------------------------------------------------------=
  28. // COleControl::COleControl
  29. //=--------------------------------------------------------------------------=
  30. // constructor
  31. //
  32. // Parameters:
  33. // IUnknown * - [in] controlling Unknown
  34. // int - [in] type of primary dispatch interface OBJECT_TYPE_*
  35. // void * - [in] pointer to entire object
  36. // BOOL - [in] whether to enable IDispatchEx functionality
  37. // to allow dynamic adding of properties
  38. // Notes:
  39. //
  40. COleControl::COleControl
  41. (
  42. IUnknown *pUnkOuter,
  43. int iPrimaryDispatch,
  44. void *pMainInterface,
  45. BOOL fExpandoEnabled
  46. )
  47. : CAutomationObject(pUnkOuter, iPrimaryDispatch, pMainInterface, fExpandoEnabled),
  48. m_cpEvents(SINK_TYPE_EVENT),
  49. m_cpPropNotify(SINK_TYPE_PROPNOTIFY)
  50. {
  51. // initialize all our variables -- we decided against using a memory-zeroing
  52. // memory allocator, so we sort of have to do this work now ...
  53. //
  54. m_nFreezeEvents = 0;
  55. m_pClientSite = NULL;
  56. m_pControlSite = NULL;
  57. m_pInPlaceSite = NULL;
  58. m_pInPlaceFrame = NULL;
  59. m_pInPlaceUIWindow = NULL;
  60. m_pInPlaceSiteWndless = NULL;
  61. // certain hosts don't like 0,0 as your initial size, so we're going to set
  62. // our initial size to 100,50 [so it's at least sort of visible on the screen]
  63. //
  64. m_Size.cx = 0;
  65. m_Size.cy = 0;
  66. memset(&m_rcLocation, 0, sizeof(m_rcLocation));
  67. m_hRgn = NULL;
  68. m_hwnd = NULL;
  69. m_hwndParent = NULL;
  70. m_hwndReflect = NULL;
  71. m_fHostReflects = TRUE;
  72. m_fCheckedReflecting = FALSE;
  73. m_nFreezeEvents = 0;
  74. m_pSimpleFrameSite = NULL;
  75. m_pOleAdviseHolder = NULL;
  76. m_pViewAdviseSink = NULL;
  77. m_pDispAmbient = NULL;
  78. m_fDirty = FALSE;
  79. m_fModeFlagValid = FALSE;
  80. m_fInPlaceActive = FALSE;
  81. m_fInPlaceVisible = FALSE;
  82. m_fUIActive = FALSE;
  83. m_fSaveSucceeded = FALSE;
  84. m_fViewAdvisePrimeFirst = FALSE;
  85. m_fViewAdviseOnlyOnce = FALSE;
  86. m_fRunMode = FALSE;
  87. }
  88. //=--------------------------------------------------------------------------=
  89. // COleControl::~COleControl
  90. //=--------------------------------------------------------------------------=
  91. // "We are all of us resigned to death; it's life we aren't resigned to."
  92. // - Graham Greene (1904-91)
  93. //
  94. // Notes:
  95. //
  96. COleControl::~COleControl()
  97. {
  98. // if we've still got a window, go and kill it now.
  99. //
  100. if (m_hwnd) {
  101. // so our window proc doesn't crash.
  102. //
  103. SetWindowLongPtr(m_hwnd, GWLP_USERDATA, (LONG_PTR)0xFFFFFFFF);
  104. DestroyWindow(m_hwnd);
  105. }
  106. if (m_hwndReflect) {
  107. SetWindowLongPtr(m_hwndReflect, GWLP_USERDATA, 0);
  108. DestroyWindow(m_hwndReflect);
  109. }
  110. if (m_hRgn != NULL)
  111. {
  112. DeleteObject(m_hRgn);
  113. m_hRgn = NULL;
  114. }
  115. // clean up all the pointers we're holding around.
  116. //
  117. QUICK_RELEASE(m_pClientSite);
  118. QUICK_RELEASE(m_pControlSite);
  119. QUICK_RELEASE(m_pInPlaceSite);
  120. QUICK_RELEASE(m_pInPlaceFrame);
  121. QUICK_RELEASE(m_pInPlaceUIWindow);
  122. QUICK_RELEASE(m_pSimpleFrameSite);
  123. QUICK_RELEASE(m_pOleAdviseHolder);
  124. QUICK_RELEASE(m_pViewAdviseSink);
  125. QUICK_RELEASE(m_pDispAmbient);
  126. QUICK_RELEASE(m_pInPlaceSiteWndless);
  127. }
  128. #ifndef DEBUG
  129. #pragma optimize("t", on)
  130. #endif // DEBUG
  131. //=--------------------------------------------------------------------------=
  132. // COleControl::InternalQueryInterface
  133. //=--------------------------------------------------------------------------=
  134. // derived-controls should delegate back to this when they decide to support
  135. // additional interfaces
  136. //
  137. // Parameters:
  138. // REFIID - [in] interface they want
  139. // void ** - [out] where they want to put the resulting object ptr.
  140. //
  141. // Output:
  142. // HRESULT - S_OK, E_NOINTERFACE
  143. //
  144. // Notes:
  145. // - NOTE: this function is speed critical!!!!
  146. //
  147. HRESULT COleControl::InternalQueryInterface
  148. (
  149. REFIID riid,
  150. void **ppvObjOut
  151. )
  152. {
  153. switch (riid.Data1) {
  154. // private interface for prop page support
  155. case Data1_IControlPrv:
  156. if(DO_GUIDS_MATCH(riid, IID_IControlPrv)) {
  157. *ppvObjOut = (void *)this;
  158. ExternalAddRef();
  159. return S_OK;
  160. }
  161. goto NoInterface;
  162. QI_INHERITS(this, IOleControl);
  163. QI_INHERITS(this, IPointerInactive);
  164. QI_INHERITS(this, IQuickActivate);
  165. QI_INHERITS(this, IOleObject);
  166. QI_INHERITS((IPersistStorage *)this, IPersist);
  167. QI_INHERITS(this, IPersistStreamInit);
  168. QI_INHERITS(this, IOleInPlaceObject);
  169. QI_INHERITS(this, IOleInPlaceObjectWindowless);
  170. QI_INHERITS((IOleInPlaceActiveObject *)this, IOleWindow);
  171. QI_INHERITS(this, IOleInPlaceActiveObject);
  172. QI_INHERITS(this, IViewObject);
  173. QI_INHERITS(this, IViewObject2);
  174. QI_INHERITS(this, IViewObjectEx);
  175. QI_INHERITS(this, IConnectionPointContainer);
  176. QI_INHERITS(this, ISpecifyPropertyPages);
  177. QI_INHERITS(this, IPersistStorage);
  178. QI_INHERITS(this, IPersistPropertyBag);
  179. QI_INHERITS(this, IProvideClassInfo);
  180. default:
  181. goto NoInterface;
  182. }
  183. // we like the interface, so addref and return
  184. //
  185. ((IUnknown *)(*ppvObjOut))->AddRef();
  186. return S_OK;
  187. NoInterface:
  188. // delegate to super-class for automation interfaces, etc ...
  189. //
  190. return CAutomationObject::InternalQueryInterface(riid, ppvObjOut);
  191. }
  192. #ifndef DEBUG
  193. #pragma optimize("s", on)
  194. #endif // DEBUG
  195. //=--------------------------------------------------------------------------=
  196. // COleControl::FindConnectionPoint [IConnectionPointContainer]
  197. //=--------------------------------------------------------------------------=
  198. // given an IID, find a connection point sink for it.
  199. //
  200. // Parameters:
  201. // REFIID - [in] interfaces they want
  202. // IConnectionPoint ** - [out] where the cp should go
  203. //
  204. // Output:
  205. // HRESULT
  206. //
  207. // Notes:
  208. //
  209. STDMETHODIMP COleControl::FindConnectionPoint
  210. (
  211. REFIID riid,
  212. IConnectionPoint **ppConnectionPoint
  213. )
  214. {
  215. CHECK_POINTER(ppConnectionPoint);
  216. // we support the event interface, and IDispatch for it, and we also
  217. // support IPropertyNotifySink.
  218. //
  219. if (DO_GUIDS_MATCH(riid, EVENTIIDOFCONTROL(m_ObjectType)) || DO_GUIDS_MATCH(riid, IID_IDispatch))
  220. *ppConnectionPoint = &m_cpEvents;
  221. else if (DO_GUIDS_MATCH(riid, IID_IPropertyNotifySink))
  222. *ppConnectionPoint = &m_cpPropNotify;
  223. else
  224. return E_NOINTERFACE;
  225. // generic post-processing.
  226. //
  227. (*ppConnectionPoint)->AddRef();
  228. return S_OK;
  229. }
  230. //=--------------------------------------------------------------------------=
  231. // COleControl::EnumConnectionPoints [IConnectionPointContainer]
  232. //=--------------------------------------------------------------------------=
  233. // creates an enumerator for connection points.
  234. //
  235. // Parameters:
  236. // IEnumConnectionPoints ** - [out]
  237. //
  238. // Output:
  239. // HRESULT
  240. //
  241. // Notes:
  242. //
  243. STDMETHODIMP COleControl::EnumConnectionPoints
  244. (
  245. IEnumConnectionPoints **ppEnumConnectionPoints
  246. )
  247. {
  248. IConnectionPoint **rgConnectionPoints;
  249. CHECK_POINTER(ppEnumConnectionPoints);
  250. // HeapAlloc an array of connection points [since our standard enum
  251. // assumes this and HeapFree's it later ]
  252. //
  253. rgConnectionPoints = (IConnectionPoint **)HeapAlloc(g_hHeap, 0, sizeof(IConnectionPoint *) * 2);
  254. RETURN_ON_NULLALLOC(rgConnectionPoints);
  255. // we support the event interface for this dude as well as IPropertyNotifySink
  256. //
  257. rgConnectionPoints[0] = &m_cpEvents;
  258. rgConnectionPoints[1] = &m_cpPropNotify;
  259. *ppEnumConnectionPoints = (IEnumConnectionPoints *)(IEnumGeneric *) new CStandardEnum(IID_IEnumConnectionPoints,
  260. 2, sizeof(IConnectionPoint *), (void *)rgConnectionPoints,
  261. CopyAndAddRefObject);
  262. if (!*ppEnumConnectionPoints) {
  263. HeapFree(g_hHeap, 0, rgConnectionPoints);
  264. return E_OUTOFMEMORY;
  265. }
  266. return S_OK;
  267. }
  268. //=--------------------------------------------------------------------------=
  269. // COleControl::GetPages [ISpecifyPropertyPages]
  270. //=--------------------------------------------------------------------------=
  271. // returns a counted array with the guids for our property pages.
  272. //
  273. // parameters:
  274. // CAUUID * - [out] where to put the counted array.
  275. //
  276. // Output:
  277. // HRESULT
  278. //
  279. // NOtes:
  280. //
  281. STDMETHODIMP COleControl::GetPages
  282. (
  283. CAUUID *pPages
  284. )
  285. {
  286. const GUID **pElems;
  287. void *pv;
  288. WORD x;
  289. // if there are no property pages, this is actually pretty easy.
  290. //
  291. if (!CPROPPAGESOFCONTROL(m_ObjectType)) {
  292. pPages->cElems = 0;
  293. pPages->pElems = NULL;
  294. return S_OK;
  295. }
  296. // fill out the Counted array, using IMalloc'd memory.
  297. //
  298. pPages->cElems = CPROPPAGESOFCONTROL(m_ObjectType);
  299. pv = CoTaskMemAlloc(sizeof(GUID) * (pPages->cElems));
  300. RETURN_ON_NULLALLOC(pv);
  301. pPages->pElems = (GUID *)pv;
  302. // loop through our array of pages and get 'em.
  303. //
  304. pElems = PPROPPAGESOFCONTROL(m_ObjectType);
  305. for (x = 0; x < pPages->cElems; x++)
  306. pPages->pElems[x] = *(pElems[x]);
  307. return S_OK;
  308. }
  309. //=--------------------------------------------------------------------------=
  310. // COleControl::CConnectionPoint::m_pOleControl
  311. //=--------------------------------------------------------------------------=
  312. // returns a pointer to the control in which we are nested.
  313. //
  314. // Output:
  315. // COleControl *
  316. //
  317. // Notes:
  318. //
  319. inline COleControl *COleControl::CConnectionPoint::m_pOleControl
  320. (
  321. void
  322. )
  323. {
  324. return (COleControl *)((BYTE *)this - ((m_bType == SINK_TYPE_EVENT)
  325. ? offsetof(COleControl, m_cpEvents)
  326. : offsetof(COleControl, m_cpPropNotify)));
  327. }
  328. //=--------------------------------------------------------------------------=
  329. // COleControl::CConnectionPoint::QueryInterface
  330. //=--------------------------------------------------------------------------=
  331. // standard qi
  332. //
  333. // Parameters:
  334. // REFIID - [in] interface they want
  335. // void ** - [out] where they want to put the resulting object ptr.
  336. //
  337. // Output:
  338. // HRESULT - S_OK, E_NOINTERFACE
  339. //
  340. // Notes:
  341. //
  342. STDMETHODIMP COleControl::CConnectionPoint::QueryInterface
  343. (
  344. REFIID riid,
  345. void **ppvObjOut
  346. )
  347. {
  348. if (DO_GUIDS_MATCH(riid, IID_IConnectionPoint) || DO_GUIDS_MATCH(riid, IID_IUnknown)) {
  349. *ppvObjOut = (IConnectionPoint *)this;
  350. AddRef();
  351. return S_OK;
  352. }
  353. return E_NOINTERFACE;
  354. }
  355. //=--------------------------------------------------------------------------=
  356. // COleControl::CConnectionPoint::AddRef
  357. //=--------------------------------------------------------------------------=
  358. //
  359. // Output:
  360. // ULONG - the new reference count
  361. //
  362. // Notes:
  363. //
  364. ULONG COleControl::CConnectionPoint::AddRef
  365. (
  366. void
  367. )
  368. {
  369. return m_pOleControl()->ExternalAddRef();
  370. }
  371. //=--------------------------------------------------------------------------=
  372. // COleControl::CConnectionPoint::Release
  373. //=--------------------------------------------------------------------------=
  374. //
  375. // Output:
  376. // ULONG - remaining refs
  377. //
  378. // Notes:
  379. //
  380. ULONG COleControl::CConnectionPoint::Release
  381. (
  382. void
  383. )
  384. {
  385. return m_pOleControl()->ExternalRelease();
  386. }
  387. //=--------------------------------------------------------------------------=
  388. // COleControl::CConnectionPoint::GetConnectionInterface
  389. //=--------------------------------------------------------------------------=
  390. // returns the interface we support connections on.
  391. //
  392. // Parameters:
  393. // IID * - [out] interface we support.
  394. //
  395. // Output:
  396. // HRESULT
  397. //
  398. // Notes:
  399. //
  400. STDMETHODIMP COleControl::CConnectionPoint::GetConnectionInterface
  401. (
  402. IID *piid
  403. )
  404. {
  405. if (m_bType == SINK_TYPE_EVENT)
  406. *piid = EVENTIIDOFCONTROL(m_pOleControl()->m_ObjectType);
  407. else
  408. *piid = IID_IPropertyNotifySink;
  409. return S_OK;
  410. }
  411. //=--------------------------------------------------------------------------=
  412. // COleControl::CConnectionPoint::GetConnectionPointContainer
  413. //=--------------------------------------------------------------------------=
  414. // returns the connection point container
  415. //
  416. // Parameters:
  417. // IConnectionPointContainer **ppCPC
  418. //
  419. // Output:
  420. // HRESULT
  421. //
  422. // Notes:
  423. //
  424. STDMETHODIMP COleControl::CConnectionPoint::GetConnectionPointContainer
  425. (
  426. IConnectionPointContainer **ppCPC
  427. )
  428. {
  429. return m_pOleControl()->ExternalQueryInterface(IID_IConnectionPointContainer, (void **)ppCPC);
  430. }
  431. //=--------------------------------------------------------------------------=
  432. // COleControl::CConnectiontPoint::Advise
  433. //=--------------------------------------------------------------------------=
  434. // someboyd wants to be advised when something happens.
  435. //
  436. // Parameters:
  437. // IUnknown * - [in] guy who wants to be advised.
  438. // DWORD * - [out] cookie
  439. //
  440. // Output:
  441. // HRESULT
  442. //
  443. // Notes:
  444. //
  445. STDMETHODIMP COleControl::CConnectionPoint::Advise
  446. (
  447. IUnknown *pUnk,
  448. DWORD *pdwCookie
  449. )
  450. {
  451. HRESULT hr;
  452. void *pv;
  453. CHECK_POINTER(pdwCookie);
  454. // first, make sure everybody's got what they thinks they got
  455. //
  456. if (m_bType == SINK_TYPE_EVENT) {
  457. // CONSIDER: 12.95 -- this theoretically is broken -- if they do a find
  458. // connection point on IDispatch, and they just happened to also support
  459. // the Event IID, we'd advise on that. this is not awesome, but will
  460. // prove entirely acceptable short term.
  461. //
  462. hr = pUnk->QueryInterface(EVENTIIDOFCONTROL(m_pOleControl()->m_ObjectType), &pv);
  463. if (FAILED(hr))
  464. hr = pUnk->QueryInterface(IID_IDispatch, &pv);
  465. }
  466. else
  467. hr = pUnk->QueryInterface(IID_IPropertyNotifySink, &pv);
  468. RETURN_ON_FAILURE(hr);
  469. // finally, add the sink. it's now been cast to the correct type and has
  470. // been AddRef'd.
  471. //
  472. return AddSink(pv, pdwCookie);
  473. }
  474. //=--------------------------------------------------------------------------=
  475. // COleControl::CConnectionPoint::AddSink
  476. //=--------------------------------------------------------------------------=
  477. // in some cases, we'll already have done the QI, and won't need to do the
  478. // work that is done in the Advise routine above. thus, these people can
  479. // just call this instead. [this stems really from IQuickActivate]
  480. //
  481. // Parameters:
  482. // void * - [in] the sink to add. it's already been addref'd
  483. // DWORD * - [out] cookie
  484. //
  485. // Output:
  486. // HRESULT
  487. //
  488. // Notes:
  489. //
  490. HRESULT COleControl::CConnectionPoint::AddSink
  491. (
  492. void *pv,
  493. DWORD *pdwCookie
  494. )
  495. {
  496. IUnknown **rgUnkNew;
  497. int i;
  498. // we optimize the case where there is only one sink to not allocate
  499. // any storage. turns out very rarely is there more than one.
  500. //
  501. if (!m_cSinks) {
  502. m_SingleSink = (IUnknown *) pv;
  503. *pdwCookie = (DWORD) 1;
  504. m_cSinks = 1;
  505. return S_OK;
  506. }
  507. // Allocated the array yet?
  508. if (!m_rgSinks) {
  509. rgUnkNew = (IUnknown **)HeapAlloc(g_hHeap, HEAP_ZERO_MEMORY, 8 * sizeof(IUnknown *));
  510. RETURN_ON_NULLALLOC(rgUnkNew);
  511. m_cAllocatedSinks = 8;
  512. m_rgSinks = rgUnkNew;
  513. m_rgSinks[0] = m_SingleSink;
  514. m_rgSinks[1] = (IUnknown *)pv;
  515. m_SingleSink = NULL;
  516. m_cSinks = 2;
  517. *pdwCookie = 2;
  518. return S_OK;
  519. }
  520. // Find an empty slot.
  521. for (i = 0; i < m_cAllocatedSinks; i++) {
  522. if (!m_rgSinks[i]) {
  523. m_rgSinks[i] = (IUnknown *)pv;
  524. i++;
  525. *pdwCookie = i;
  526. m_cSinks++;
  527. return S_OK;
  528. }
  529. }
  530. // Didn't find one, grow the array.
  531. rgUnkNew = (IUnknown **)HeapReAlloc(g_hHeap, HEAP_ZERO_MEMORY, m_rgSinks, (m_cAllocatedSinks + 8) * sizeof(IUnknown *));
  532. RETURN_ON_NULLALLOC(rgUnkNew);
  533. m_rgSinks = rgUnkNew;
  534. m_rgSinks[m_cAllocatedSinks] = (IUnknown *)pv;
  535. i = m_cAllocatedSinks+1;
  536. m_cAllocatedSinks += 8;
  537. *pdwCookie = i;
  538. m_cSinks++;
  539. return S_OK;
  540. }
  541. //=--------------------------------------------------------------------------=
  542. // COleControl::CConnectionPoint::Unadvise
  543. //=--------------------------------------------------------------------------=
  544. // they don't want to be told any more.
  545. //
  546. // Parameters:
  547. // DWORD - [in] the cookie we gave 'em.
  548. //
  549. // Output:
  550. // HRESULT
  551. //
  552. // Notes:
  553. //
  554. STDMETHODIMP COleControl::CConnectionPoint::Unadvise
  555. (
  556. DWORD dwCookie
  557. )
  558. {
  559. IUnknown *pUnk;
  560. if (!dwCookie)
  561. return S_OK;
  562. if (dwCookie == (DWORD) 1) {
  563. // If more than one Sinks added, m_SingleSink pointer has been shifted
  564. // to m_rgSinks[0].
  565. pUnk = (m_rgSinks) ? m_rgSinks[0] : m_SingleSink;
  566. m_SingleSink = NULL;
  567. if (m_rgSinks) {
  568. m_rgSinks[0] = NULL;
  569. }
  570. } else {
  571. if (dwCookie <= (DWORD)m_cAllocatedSinks) {
  572. if (m_rgSinks) {
  573. pUnk = m_rgSinks[dwCookie-1];
  574. m_rgSinks[dwCookie-1] = NULL;
  575. } else {
  576. return CONNECT_E_NOCONNECTION;
  577. }
  578. } else {
  579. return CONNECT_E_NOCONNECTION;
  580. }
  581. }
  582. m_cSinks--;
  583. if (!m_cSinks && m_rgSinks) {
  584. HeapFree(g_hHeap, 0, m_rgSinks);
  585. m_cAllocatedSinks = 0;
  586. m_rgSinks = NULL;
  587. }
  588. if (pUnk) {
  589. pUnk->Release();
  590. return S_OK;
  591. } else {
  592. return CONNECT_E_NOCONNECTION;
  593. }
  594. }
  595. //=--------------------------------------------------------------------------=
  596. // COleControl::CConnectionPoint::EnumConnections
  597. //=--------------------------------------------------------------------------=
  598. // enumerates all current connections
  599. //
  600. // Paramters:
  601. // IEnumConnections ** - [out] new enumerator object
  602. //
  603. // Output:
  604. // HRESULT
  605. //
  606. // NOtes:
  607. //
  608. STDMETHODIMP COleControl::CConnectionPoint::EnumConnections
  609. (
  610. IEnumConnections **ppEnumOut
  611. )
  612. {
  613. CONNECTDATA *rgConnectData = NULL;
  614. unsigned int i;
  615. if (m_cSinks) {
  616. // allocate some memory big enough to hold all of the sinks.
  617. //
  618. rgConnectData = (CONNECTDATA *)HeapAlloc(g_hHeap, 0, m_cSinks * sizeof(CONNECTDATA));
  619. RETURN_ON_NULLALLOC(rgConnectData);
  620. if ((m_cSinks == 1) && !m_rgSinks) {
  621. rgConnectData[0].pUnk = m_SingleSink;
  622. rgConnectData[0].dwCookie = (DWORD)1;
  623. } else {
  624. for (unsigned int x = 0, i=0; x < m_cAllocatedSinks; x++) {
  625. if (m_rgSinks[x]) {
  626. rgConnectData[i].pUnk = m_rgSinks[x];
  627. rgConnectData[i].dwCookie = x+1;
  628. i++;
  629. }
  630. }
  631. }
  632. }
  633. // create yon enumerator object.
  634. //
  635. *ppEnumOut = (IEnumConnections *)(IEnumGeneric *)new CStandardEnum(IID_IEnumConnections,
  636. m_cSinks, sizeof(CONNECTDATA), rgConnectData, CopyAndAddRefObject);
  637. if (!*ppEnumOut) {
  638. HeapFree(g_hHeap, 0, rgConnectData);
  639. return E_OUTOFMEMORY;
  640. }
  641. return S_OK;
  642. }
  643. //=--------------------------------------------------------------------------=
  644. // COleControl::CConnectionPoint::~CConnectionPoint
  645. //=--------------------------------------------------------------------------=
  646. // cleans up
  647. //
  648. // Notes:
  649. //
  650. COleControl::CConnectionPoint::~CConnectionPoint ()
  651. {
  652. int x;
  653. // clean up some memory stuff
  654. //
  655. if (!m_cSinks)
  656. return;
  657. else if (m_SingleSink)
  658. ((IUnknown *)m_SingleSink)->Release();
  659. else {
  660. for (x = 0; x < m_cAllocatedSinks; x++) {
  661. if (m_rgSinks[x]) {
  662. QUICK_RELEASE(m_rgSinks[x]);
  663. }
  664. }
  665. HeapFree(g_hHeap, 0, m_rgSinks);
  666. }
  667. }
  668. //=--------------------------------------------------------------------------=
  669. // COleControl::CConnectionPiont::DoInvoke
  670. //=--------------------------------------------------------------------------=
  671. // fires an event to all listening on our event interface.
  672. //
  673. // Parameters:
  674. // DISPID - [in] event to fire.
  675. // DISPPARAMS - [in]
  676. //
  677. // Notes:
  678. //
  679. void COleControl::CConnectionPoint::DoInvoke
  680. (
  681. DISPID dispid,
  682. DISPPARAMS *pdispparams
  683. )
  684. {
  685. int iConnection;
  686. // if we don't have any sinks, then there's nothing to do. we intentionally
  687. // ignore errors here.
  688. //
  689. if (m_cSinks == 0)
  690. return;
  691. else if (m_SingleSink) {
  692. ((IDispatch *)m_SingleSink)->Invoke(dispid, IID_NULL, 0, DISPATCH_METHOD, pdispparams, NULL, NULL, NULL);
  693. } else {
  694. for (iConnection = 0; iConnection < m_cAllocatedSinks; iConnection++) {
  695. if (m_rgSinks[iConnection]) {
  696. ((IDispatch *)m_rgSinks[iConnection])->Invoke(dispid, IID_NULL, 0, DISPATCH_METHOD, pdispparams, NULL, NULL, NULL);
  697. }
  698. }
  699. }
  700. }
  701. //=--------------------------------------------------------------------------=
  702. // COleControl::CConnectionPoint::DoOnChanged
  703. //=--------------------------------------------------------------------------=
  704. // fires the OnChanged event for IPropertyNotifySink listeners.
  705. //
  706. // Parameters:
  707. // DISPID - [in] dude that changed.
  708. //
  709. // Output:
  710. // none
  711. //
  712. // Notes:
  713. //
  714. void COleControl::CConnectionPoint::DoOnChanged
  715. (
  716. DISPID dispid
  717. )
  718. {
  719. int iConnection;
  720. // if we don't have any sinks, then there's nothing to do.
  721. //
  722. if (m_cSinks == 0)
  723. return;
  724. else if (m_SingleSink) {
  725. ((IPropertyNotifySink *)m_SingleSink)->OnChanged(dispid);
  726. } else {
  727. for (iConnection = 0; iConnection < m_cAllocatedSinks; iConnection++) {
  728. if (m_rgSinks[iConnection]) {
  729. ((IPropertyNotifySink *)m_rgSinks[iConnection])->OnChanged(dispid);
  730. }
  731. }
  732. }
  733. }
  734. //=--------------------------------------------------------------------------=
  735. // COleControl::CConnectionPoint::DoOnRequestEdit
  736. //=--------------------------------------------------------------------------=
  737. // fires the OnRequestEdit for IPropertyNotifySinkListeners
  738. //
  739. // Parameters:
  740. // DISPID - [in] dispid user wants to change.
  741. //
  742. // Output:
  743. // BOOL - false means you cant
  744. //
  745. // Notes:
  746. //
  747. BOOL COleControl::CConnectionPoint::DoOnRequestEdit
  748. (
  749. DISPID dispid
  750. )
  751. {
  752. HRESULT hr;
  753. int iConnection;
  754. // if we don't have any sinks, then there's nothing to do.
  755. //
  756. if (m_cSinks == 0)
  757. hr = S_OK;
  758. else if (m_SingleSink) {
  759. hr =((IPropertyNotifySink *)m_SingleSink)->OnRequestEdit(dispid);
  760. } else {
  761. for (iConnection = 0; iConnection < m_cAllocatedSinks; iConnection++) {
  762. if (m_rgSinks[iConnection]) {
  763. hr = ((IPropertyNotifySink *)m_rgSinks[iConnection])->OnRequestEdit(dispid);
  764. if (hr != S_OK)
  765. break;
  766. }
  767. }
  768. }
  769. return (hr == S_OK) ? TRUE : FALSE;
  770. }
  771. //=--------------------------------------------------------------------------=
  772. // COleControl::CreateInPlaceWindow
  773. //=--------------------------------------------------------------------------=
  774. // creates the window with which we will be working.
  775. // yay.
  776. //
  777. // Parameters:
  778. // int - [in] left
  779. // int - [in] top
  780. // BOOL - [in] can we skip redrawing?
  781. //
  782. // Output:
  783. // HWND
  784. //
  785. // Notes:
  786. // - DANGER! DANGER! this function is protected so that anybody can call it
  787. // from their control. however, people should be extremely careful of when
  788. // and why they do this. preferably, this function would only need to be
  789. // called by an end-control writer in design mode to take care of some
  790. // hosting/painting issues. otherwise, the framework should be left to
  791. // call it when it wants.
  792. //
  793. HWND COleControl::CreateInPlaceWindow
  794. (
  795. int x,
  796. int y,
  797. BOOL fNoRedraw
  798. )
  799. {
  800. BOOL fVisible;
  801. HRESULT hr;
  802. DWORD dwWindowStyle, dwExWindowStyle;
  803. char szWindowTitle[128];
  804. // if we've already got a window, do nothing.
  805. //
  806. if (m_hwnd)
  807. return m_hwnd;
  808. // get the user to register the class if it's not already
  809. // been done. we have to critical section this since more than one thread
  810. // can be trying to create this control
  811. //
  812. EnterCriticalSection(&g_CriticalSection);
  813. if (!CTLWNDCLASSREGISTERED(m_ObjectType)) {
  814. if (!RegisterClassData()) {
  815. LeaveCriticalSection(&g_CriticalSection);
  816. return NULL;
  817. } else
  818. CTLWNDCLASSREGISTERED(m_ObjectType) = TRUE;
  819. }
  820. LeaveCriticalSection(&g_CriticalSection);
  821. // let the user set up things like the window title, the
  822. // style, and anything else they feel interested in fiddling
  823. // with.
  824. //
  825. dwWindowStyle = dwExWindowStyle = 0;
  826. szWindowTitle[0] = '\0';
  827. if (!BeforeCreateWindow(&dwWindowStyle, &dwExWindowStyle, szWindowTitle))
  828. return NULL;
  829. dwWindowStyle |= (WS_CHILD | WS_CLIPSIBLINGS);
  830. // create window visible if parent hidden (common case)
  831. // otherwise, create hidden, then shown. this is a little subtle, but
  832. // it makes sense eventually.
  833. //
  834. if (!m_hwndParent)
  835. m_hwndParent = GetParkingWindow();
  836. fVisible = IsWindowVisible(m_hwndParent);
  837. // if a control is subclassed, and we're in
  838. // a host that doesn't support Message Reflecting, we have to create
  839. // the user window in another window which will do all the reflecting.
  840. // VERY blech. [don't however, bother in design mode]
  841. //
  842. if (SUBCLASSWNDPROCOFCONTROL(m_ObjectType) && (m_hwndParent != GetParkingWindow())) {
  843. // determine if the host supports message reflecting.
  844. //
  845. if (!m_fCheckedReflecting) {
  846. VARIANT_BOOL f;
  847. hr = GetAmbientProperty(DISPID_AMBIENT_MESSAGEREFLECT, VT_BOOL, &f);
  848. if (FAILED(hr) || !f)
  849. m_fHostReflects = FALSE;
  850. m_fCheckedReflecting = TRUE;
  851. }
  852. // if the host doesn't support reflecting, then we have to create
  853. // an extra window around the control window, and then parent it
  854. // off that.
  855. //
  856. if (!m_fHostReflects) {
  857. ASSERT(m_hwndReflect == NULL, "Where'd this come from?");
  858. m_hwndReflect = CreateReflectWindow(!fVisible, m_hwndParent, x, y, &m_Size);
  859. if (!m_hwndReflect)
  860. return NULL;
  861. SetWindowLongPtr(m_hwndReflect, GWLP_USERDATA, (LONG_PTR)this);
  862. dwWindowStyle |= WS_VISIBLE;
  863. }
  864. } else {
  865. if (!fVisible)
  866. dwWindowStyle |= WS_VISIBLE;
  867. }
  868. // we have to mutex the entire create window process since we need to use
  869. // the s_pLastControlCreated to pass in the object pointer. nothing too
  870. // serious
  871. //
  872. EnterCriticalSection(&g_CriticalSection);
  873. s_pLastControlCreated = this;
  874. m_fCreatingWindow = TRUE;
  875. // finally, go create the window, parenting it as appropriate.
  876. //
  877. m_hwnd = CreateWindowEx(dwExWindowStyle,
  878. WNDCLASSNAMEOFCONTROL(m_ObjectType),
  879. szWindowTitle,
  880. dwWindowStyle,
  881. (m_hwndReflect) ? 0 : x,
  882. (m_hwndReflect) ? 0 : y,
  883. m_Size.cx, m_Size.cy,
  884. (m_hwndReflect) ? m_hwndReflect : m_hwndParent,
  885. NULL, g_hInstance, NULL);
  886. // clean up some variables, and leave the critical section
  887. //
  888. m_fCreatingWindow = FALSE;
  889. s_pLastControlCreated = NULL;
  890. LeaveCriticalSection(&g_CriticalSection);
  891. if (m_hwnd) {
  892. // let the derived-control do something if they so desire
  893. //
  894. if (!AfterCreateWindow()) {
  895. BeforeDestroyWindow();
  896. SetWindowLongPtr(m_hwnd, GWLP_USERDATA, (LONG_PTR)0xFFFFFFFF);
  897. DestroyWindow(m_hwnd);
  898. m_hwnd = NULL;
  899. return m_hwnd;
  900. }
  901. // if we didn't create the window visible, show it now.
  902. //
  903. if (fVisible)
  904. {
  905. if (GetParent(m_hwnd) != m_hwndParent)
  906. // SetWindowPos fails if parent hwnd is passed in so keep
  907. // this behaviour in those cases without ripping.
  908. SetWindowPos(m_hwnd, m_hwndParent, 0, 0, 0, 0,
  909. SWP_NOSIZE | SWP_NOMOVE | SWP_NOZORDER | SWP_SHOWWINDOW | (fNoRedraw) ? SWP_NOREDRAW : 0);
  910. }
  911. }
  912. // finally, tell the host of this
  913. //
  914. if (m_pClientSite)
  915. m_pClientSite->ShowObject();
  916. return m_hwnd;
  917. }
  918. //=--------------------------------------------------------------------------=
  919. // COleControl::SetInPlaceParent [helper]
  920. //=--------------------------------------------------------------------------=
  921. // sets up the parent window for our control.
  922. //
  923. // Parameters:
  924. // HWND - [in] new parent window
  925. //
  926. // Notes:
  927. //
  928. void COleControl::SetInPlaceParent
  929. (
  930. HWND hwndParent
  931. )
  932. {
  933. ASSERT(!m_pInPlaceSiteWndless, "This routine should only get called for windowed OLE controls");
  934. if (m_hwndParent == hwndParent)
  935. return;
  936. m_hwndParent = hwndParent;
  937. if (m_hwnd)
  938. SetParent(GetOuterWindow(), hwndParent);
  939. }
  940. //=--------------------------------------------------------------------------=
  941. // COleControl::ControlWindowProc
  942. //=--------------------------------------------------------------------------=
  943. // default window proc for an OLE Control. controls will have their own
  944. // window proc called from this one, after some processing is done.
  945. //
  946. // Parameters:
  947. // - see win32sdk docs.
  948. //
  949. // Notes:
  950. //
  951. LRESULT CALLBACK COleControl::ControlWindowProc
  952. (
  953. HWND hwnd,
  954. UINT msg,
  955. WPARAM wParam,
  956. LPARAM lParam
  957. )
  958. {
  959. COleControl *pCtl = ControlFromHwnd(hwnd);
  960. HRESULT hr;
  961. LRESULT lResult;
  962. DWORD dwCookie;
  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. //
  967. if (!pCtl) {
  968. pCtl = s_pLastControlCreated;
  969. SetWindowLongPtr(hwnd, GWLP_USERDATA, (LONG_PTR)pCtl);
  970. pCtl->m_hwnd = hwnd;
  971. } else if ((LONG_PTR)pCtl == (LONG_PTR)0xffffffff) {
  972. return DefWindowProc(hwnd, msg, wParam, lParam);
  973. }
  974. // message preprocessing
  975. //
  976. if (pCtl->m_pSimpleFrameSite) {
  977. hr = pCtl->m_pSimpleFrameSite->PreMessageFilter(hwnd, msg, wParam, lParam, &lResult, &dwCookie);
  978. if (hr == S_FALSE) return lResult;
  979. }
  980. // for certain messages, do not call the user window proc. instead,
  981. // we have something else we'd like to do.
  982. //
  983. switch (msg) {
  984. case WM_PAINT:
  985. {
  986. // call the user's OnDraw routine.
  987. //
  988. PAINTSTRUCT ps;
  989. RECT rc;
  990. HDC hdc;
  991. // if we're given an HDC, then use it
  992. //
  993. if (!wParam)
  994. hdc = BeginPaint(hwnd, &ps);
  995. else
  996. hdc = (HDC)wParam;
  997. GetClientRect(hwnd, &rc);
  998. pCtl->OnDraw(DVASPECT_CONTENT, hdc, (RECTL *)&rc, NULL, NULL, TRUE);
  999. if (!wParam)
  1000. EndPaint(hwnd, &ps);
  1001. }
  1002. break;
  1003. default:
  1004. // call the derived-control's window proc
  1005. //
  1006. lResult = pCtl->WindowProc(msg, wParam, lParam);
  1007. break;
  1008. }
  1009. // message postprocessing
  1010. //
  1011. switch (msg) {
  1012. case WM_NCDESTROY:
  1013. // after this point, the window doesn't exist any more
  1014. //
  1015. pCtl->m_hwnd = NULL;
  1016. break;
  1017. case WM_SETFOCUS:
  1018. // give the control site focus notification
  1019. //
  1020. if (pCtl->m_fInPlaceActive && pCtl->m_pControlSite)
  1021. pCtl->m_pControlSite->OnFocus(TRUE);
  1022. pCtl->m_fUIActive = TRUE;
  1023. break;
  1024. case WM_KILLFOCUS:
  1025. // give the control site focus notification
  1026. //
  1027. if (pCtl->m_fInPlaceActive && pCtl->m_pControlSite)
  1028. pCtl->m_pControlSite->OnFocus(FALSE);
  1029. pCtl->m_fUIActive = FALSE;
  1030. break;
  1031. case WM_SIZE:
  1032. // a change in size is a change in view
  1033. //
  1034. if (!pCtl->m_fCreatingWindow)
  1035. pCtl->ViewChanged();
  1036. break;
  1037. }
  1038. // lastly, simple frame postmessage processing
  1039. //
  1040. if (pCtl->m_pSimpleFrameSite)
  1041. pCtl->m_pSimpleFrameSite->PostMessageFilter(hwnd, msg, wParam, lParam, &lResult, dwCookie);
  1042. return lResult;
  1043. }
  1044. //=--------------------------------------------------------------------------=
  1045. // COleControl::SetFocus
  1046. //=--------------------------------------------------------------------------=
  1047. // we have to override this routine to get UI Activation correct.
  1048. //
  1049. // Parameters:
  1050. // BOOL - [in] true means take, false release
  1051. //
  1052. // Output:
  1053. // BOOL
  1054. //
  1055. // Notes:
  1056. // - CONSIDER: this is pretty messy, and it's still not entirely clear
  1057. // what the ole control/focus story is.
  1058. //
  1059. BOOL COleControl::SetFocus
  1060. (
  1061. BOOL fGrab
  1062. )
  1063. {
  1064. HRESULT hr;
  1065. HWND hwnd;
  1066. // first thing to do is check out UI Activation state, and then set
  1067. // focus [either with windows api, or via the host for windowless
  1068. // controls]
  1069. //
  1070. if (m_pInPlaceSiteWndless) {
  1071. if (!m_fUIActive && fGrab)
  1072. if (FAILED(InPlaceActivate(OLEIVERB_UIACTIVATE))) return FALSE;
  1073. hr = m_pInPlaceSiteWndless->SetFocus(fGrab);
  1074. return (hr == S_OK) ? TRUE : FALSE;
  1075. } else {
  1076. // we've got a window.
  1077. //
  1078. if (m_fInPlaceActive) {
  1079. hwnd = (fGrab) ? m_hwnd : m_hwndParent;
  1080. if (!m_fUIActive && fGrab)
  1081. return SUCCEEDED(InPlaceActivate(OLEIVERB_UIACTIVATE));
  1082. else
  1083. return SetGUIFocus(hwnd);
  1084. } else
  1085. return FALSE;
  1086. }
  1087. // dead code
  1088. }
  1089. //=--------------------------------------------------------------------------=
  1090. // COleControl::SetGUIFocus
  1091. //=--------------------------------------------------------------------------=
  1092. // does the work of setting the Windows GUI focus to the specified window
  1093. //
  1094. // Parameters:
  1095. // HWND - [in] window that should get focus
  1096. //
  1097. // Output:
  1098. // BOOL - [out] whether setting focus succeeded
  1099. //
  1100. // Notes:
  1101. // we do this because some controls host non-ole window hierarchies, like
  1102. // the Netscape plugin ocx. in such cases, the control may need to be UIActive
  1103. // to function properly in the document, but cannot take the windows focus
  1104. // away from one of its child windows. such controls may override this method
  1105. // and respond as appropriate.
  1106. //
  1107. BOOL COleControl::SetGUIFocus
  1108. (
  1109. HWND hwndSet
  1110. )
  1111. {
  1112. return (::SetFocus(hwndSet) == hwndSet);
  1113. }
  1114. //=--------------------------------------------------------------------------=
  1115. // COleControl::ReflectWindowProc
  1116. //=--------------------------------------------------------------------------=
  1117. // reflects window messages on to the child window.
  1118. //
  1119. // Parameters and Output:
  1120. // - see win32 sdk docs
  1121. //
  1122. // Notes:
  1123. //
  1124. LRESULT CALLBACK COleControl::ReflectWindowProc
  1125. (
  1126. HWND hwnd,
  1127. UINT msg,
  1128. WPARAM wParam,
  1129. LPARAM lParam
  1130. )
  1131. {
  1132. COleControl *pCtl;
  1133. switch (msg) {
  1134. case WM_COMMAND:
  1135. case WM_NOTIFY:
  1136. case WM_CTLCOLORBTN:
  1137. case WM_CTLCOLORDLG:
  1138. case WM_CTLCOLOREDIT:
  1139. case WM_CTLCOLORLISTBOX:
  1140. case WM_CTLCOLORMSGBOX:
  1141. case WM_CTLCOLORSCROLLBAR:
  1142. case WM_CTLCOLORSTATIC:
  1143. case WM_DRAWITEM:
  1144. case WM_MEASUREITEM:
  1145. case WM_DELETEITEM:
  1146. case WM_VKEYTOITEM:
  1147. case WM_CHARTOITEM:
  1148. case WM_COMPAREITEM:
  1149. case WM_HSCROLL:
  1150. case WM_VSCROLL:
  1151. case WM_PARENTNOTIFY:
  1152. case WM_SETFOCUS:
  1153. case WM_SIZE:
  1154. pCtl = (COleControl *)GetWindowLongPtr(hwnd, GWLP_USERDATA);
  1155. if (pCtl)
  1156. return SendMessage(pCtl->m_hwnd, OCM__BASE + msg, wParam, lParam);
  1157. break;
  1158. }
  1159. return DefWindowProc(hwnd, msg, wParam, lParam);
  1160. }
  1161. //=--------------------------------------------------------------------------=
  1162. // COleControl::GetAmbientProperty [callable]
  1163. //=--------------------------------------------------------------------------=
  1164. // returns the value of an ambient property
  1165. //
  1166. // Parameters:
  1167. // DISPID - [in] property to get
  1168. // VARTYPE - [in] type of desired data
  1169. // void * - [out] where to put the data
  1170. //
  1171. // Output:
  1172. // BOOL - FALSE means didn't work.
  1173. //
  1174. // Notes:
  1175. //
  1176. BOOL COleControl::GetAmbientProperty
  1177. (
  1178. DISPID dispid,
  1179. VARTYPE vt,
  1180. void *pData
  1181. )
  1182. {
  1183. DISPPARAMS dispparams;
  1184. VARIANT v, v2;
  1185. HRESULT hr;
  1186. v.vt = VT_EMPTY;
  1187. v.lVal = 0;
  1188. v2.vt = VT_EMPTY;
  1189. v2.lVal = 0;
  1190. // get a pointer to the source of ambient properties.
  1191. //
  1192. if (!m_pDispAmbient) {
  1193. if (m_pClientSite)
  1194. m_pClientSite->QueryInterface(IID_IDispatch, (void **)&m_pDispAmbient);
  1195. if (!m_pDispAmbient)
  1196. return FALSE;
  1197. }
  1198. // now go and get the property into a variant.
  1199. //
  1200. memset(&dispparams, 0, sizeof(DISPPARAMS));
  1201. hr = m_pDispAmbient->Invoke(dispid, IID_NULL, 0, DISPATCH_PROPERTYGET, &dispparams,
  1202. &v, NULL, NULL);
  1203. if (FAILED(hr)) return FALSE;
  1204. // we've got the variant, so now go an coerce it to the type that the user
  1205. // wants. if the types are the same, then this will copy the stuff to
  1206. // do appropriate ref counting ...
  1207. //
  1208. hr = VariantChangeType(&v2, &v, 0, vt);
  1209. if (FAILED(hr)) {
  1210. VariantClear(&v);
  1211. return FALSE;
  1212. }
  1213. // copy the data to where the user wants it
  1214. //
  1215. CopyMemory(pData, &(v2.lVal), g_rgcbDataTypeSize[vt]);
  1216. VariantClear(&v);
  1217. return TRUE;
  1218. }
  1219. //=--------------------------------------------------------------------------=
  1220. // COleControl::GetAmbientFont [callable]
  1221. //=--------------------------------------------------------------------------=
  1222. // gets the current font for the user.
  1223. //
  1224. // Parameters:
  1225. // IFont ** - [out] where to put the font.
  1226. //
  1227. // Output:
  1228. // BOOL - FALSE means couldn't get it.
  1229. //
  1230. // Notes:
  1231. //
  1232. BOOL COleControl::GetAmbientFont
  1233. (
  1234. IFont **ppFont
  1235. )
  1236. {
  1237. IDispatch *pFontDisp;
  1238. // we don't have to do much here except get the ambient property and QI
  1239. // it for the user.
  1240. //
  1241. *ppFont = NULL;
  1242. if (!GetAmbientProperty(DISPID_AMBIENT_FONT, VT_DISPATCH, &pFontDisp))
  1243. return FALSE;
  1244. pFontDisp->QueryInterface(IID_IFont, (void **)ppFont);
  1245. pFontDisp->Release();
  1246. return (*ppFont) ? TRUE : FALSE;
  1247. }
  1248. //=--------------------------------------------------------------------------=
  1249. // COleControl::DesignMode
  1250. //=--------------------------------------------------------------------------=
  1251. // returns TRUE if we're in Design mode.
  1252. //
  1253. // Output:
  1254. // BOOL - true is design mode, false is run mode
  1255. //
  1256. // Notes:
  1257. //
  1258. BOOL COleControl::DesignMode
  1259. (
  1260. void
  1261. )
  1262. {
  1263. VARIANT_BOOL f;
  1264. // if we don't already know our run mode, go and get it. we'll assume
  1265. // it's true unless told otherwise [or if the operation fails ...]
  1266. //
  1267. if (!m_fModeFlagValid) {
  1268. f = TRUE;
  1269. m_fModeFlagValid = TRUE;
  1270. GetAmbientProperty(DISPID_AMBIENT_USERMODE, VT_BOOL, &f);
  1271. m_fRunMode = f;
  1272. }
  1273. return !m_fRunMode;
  1274. }
  1275. //=--------------------------------------------------------------------------=
  1276. // COleControl::FireEvent
  1277. //=--------------------------------------------------------------------------=
  1278. // fires an event. handles arbitrary number of arguments.
  1279. //
  1280. // Parameters:
  1281. // EVENTINFO * - [in] struct that describes the event.
  1282. // ... - arguments to the event
  1283. //
  1284. // Output:
  1285. // none
  1286. //
  1287. // Notes:
  1288. // - use stdarg's va_* macros.
  1289. //
  1290. void __cdecl COleControl::FireEvent
  1291. (
  1292. EVENTINFO *pEventInfo,
  1293. ...
  1294. )
  1295. {
  1296. va_list valist;
  1297. DISPPARAMS dispparams;
  1298. VARIANT rgvParameters[MAX_ARGS];
  1299. VARIANT *pv;
  1300. VARTYPE vt;
  1301. int iParameter;
  1302. int cbSize;
  1303. ASSERT(pEventInfo->cParameters <= MAX_ARGS, "Don't support more than MAX_ARGS params. sorry.");
  1304. va_start(valist, pEventInfo);
  1305. // copy the Parameters into the rgvParameters array. make sure we reverse
  1306. // them for automation
  1307. //
  1308. pv = &(rgvParameters[pEventInfo->cParameters - 1]);
  1309. for (iParameter = 0; iParameter < pEventInfo->cParameters; iParameter++) {
  1310. vt = pEventInfo->rgTypes[iParameter];
  1311. // if it's a by value variant, then just copy the whole
  1312. // dang thing
  1313. //
  1314. if (vt == VT_VARIANT)
  1315. *pv = va_arg(valist, VARIANT);
  1316. else {
  1317. // copy the vt and the data value.
  1318. //
  1319. pv->vt = vt;
  1320. if (vt & VT_BYREF)
  1321. cbSize = sizeof(void *);
  1322. else
  1323. cbSize = g_rgcbDataTypeSize[vt];
  1324. // small optimization -- we can copy 2/4 bytes over quite
  1325. // quickly.
  1326. //
  1327. if (cbSize == sizeof(short))
  1328. V_I2(pv) = va_arg(valist, short);
  1329. else if (cbSize == 4)
  1330. V_I4(pv) = va_arg(valist, long);
  1331. else {
  1332. // copy over 8 bytes
  1333. //
  1334. ASSERT(cbSize == 8, "don't recognize the type!!");
  1335. V_CY(pv) = va_arg(valist, CURRENCY);
  1336. }
  1337. }
  1338. pv--;
  1339. }
  1340. // fire the event
  1341. //
  1342. dispparams.rgvarg = rgvParameters;
  1343. dispparams.cArgs = pEventInfo->cParameters;
  1344. dispparams.rgdispidNamedArgs = NULL;
  1345. dispparams.cNamedArgs = 0;
  1346. m_cpEvents.DoInvoke(pEventInfo->dispid, &dispparams);
  1347. va_end(valist);
  1348. }
  1349. //=--------------------------------------------------------------------------=
  1350. // COleControl::AfterCreateWindow [overridable]
  1351. //=--------------------------------------------------------------------------=
  1352. // something the user can pay attention to
  1353. //
  1354. // Output:
  1355. // BOOL - false means fatal error, can't continue
  1356. // Notes:
  1357. //
  1358. BOOL COleControl::AfterCreateWindow
  1359. (
  1360. void
  1361. )
  1362. {
  1363. return TRUE;
  1364. }
  1365. //=--------------------------------------------------------------------------=
  1366. // COleControl::BeforeCreateWindow [overridable]
  1367. //=--------------------------------------------------------------------------=
  1368. // called just before we create a window. the user should register their
  1369. // window class here, and set up any other things, such as the title of
  1370. // the window, and/or sytle bits, etc ...
  1371. //
  1372. // Parameters:
  1373. // DWORD * - [out] dwWindowFlags
  1374. // DWORD * - [out] dwExWindowFlags
  1375. // LPSTR - [out] name of window to create
  1376. //
  1377. // Output:
  1378. // BOOL - false means fatal error, can't continue
  1379. //
  1380. // Notes:
  1381. //
  1382. BOOL COleControl::BeforeCreateWindow
  1383. (
  1384. DWORD *pdwWindowStyle,
  1385. DWORD *pdwExWindowStyle,
  1386. LPSTR pszWindowTitle
  1387. )
  1388. {
  1389. return TRUE;
  1390. }
  1391. //=--------------------------------------------------------------------------=
  1392. // COleControl::InvalidateControl [callable]
  1393. //=--------------------------------------------------------------------------=
  1394. void COleControl::InvalidateControl
  1395. (
  1396. LPCRECT lpRect
  1397. )
  1398. {
  1399. if (m_fInPlaceActive)
  1400. InvalidateRect(m_hwnd, lpRect, TRUE);
  1401. else
  1402. ViewChanged();
  1403. // CONSIDER: one might want to call pOleAdviseHolder->OnDataChanged() here
  1404. // if there was support for IDataObject
  1405. }
  1406. //=--------------------------------------------------------------------------=
  1407. // COleControl::SetControlSize [callable]
  1408. //=--------------------------------------------------------------------------=
  1409. // sets the control size. they'll give us the size in pixels. we've got to
  1410. // convert them back to HIMETRIC before passing them on!
  1411. //
  1412. // Parameters:
  1413. // SIZEL * - [in] new size
  1414. //
  1415. // Output:
  1416. // BOOL
  1417. //
  1418. // Notes:
  1419. //
  1420. BOOL COleControl::SetControlSize
  1421. (
  1422. SIZEL *pSize
  1423. )
  1424. {
  1425. HRESULT hr;
  1426. SIZEL slHiMetric;
  1427. PixelToHiMetric(pSize, &slHiMetric);
  1428. hr = SetExtent(DVASPECT_CONTENT, &slHiMetric);
  1429. return (FAILED(hr)) ? FALSE : TRUE;
  1430. }
  1431. //=--------------------------------------------------------------------------=
  1432. // COleControl::RecreateControlWindow [callable]
  1433. //=--------------------------------------------------------------------------=
  1434. // called by a [subclassed, typically] control to recreate it's control
  1435. // window.
  1436. //
  1437. // Parameters:
  1438. // none
  1439. //
  1440. // Output:
  1441. // HRESULT
  1442. //
  1443. // Notes:
  1444. // - NOTE: USE ME EXTREMELY SPARINGLY! THIS IS AN EXTREMELY EXPENSIVE
  1445. // OPERATION!
  1446. //
  1447. HRESULT COleControl::RecreateControlWindow
  1448. (
  1449. void
  1450. )
  1451. {
  1452. HRESULT hr;
  1453. HWND hwndPrev;
  1454. // we need to correctly preserve the control's position within the
  1455. // z-order here.
  1456. //
  1457. if (m_hwnd)
  1458. hwndPrev = ::GetWindow(m_hwnd, GW_HWNDPREV);
  1459. // if we're in place active, then we have to deactivate, and reactivate
  1460. // ourselves with the new window ...
  1461. //
  1462. if (m_fInPlaceActive) {
  1463. hr = InPlaceDeactivate();
  1464. RETURN_ON_FAILURE(hr);
  1465. hr = InPlaceActivate((m_fUIActive) ? OLEIVERB_UIACTIVATE : OLEIVERB_INPLACEACTIVATE);
  1466. RETURN_ON_FAILURE(hr);
  1467. } else if (m_hwnd) {
  1468. DestroyWindow(m_hwnd);
  1469. m_hwnd = NULL;
  1470. if (m_hwndReflect) {
  1471. DestroyWindow(m_hwndReflect);
  1472. m_hwndReflect = NULL;
  1473. }
  1474. CreateInPlaceWindow(0, 0, FALSE);
  1475. }
  1476. // restore z-order position
  1477. //
  1478. if (m_hwnd)
  1479. SetWindowPos(m_hwnd, hwndPrev, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE);
  1480. return m_hwnd ? S_OK : E_FAIL;
  1481. }
  1482. // from Globals.C. don't need to mutex it here since we only read it.
  1483. //
  1484. extern HINSTANCE g_hInstResources;
  1485. //=--------------------------------------------------------------------------=
  1486. // COleControl::GetResourceHandle [callable]
  1487. //=--------------------------------------------------------------------------=
  1488. // gets the HINSTANCE of the DLL where the control should get resources
  1489. // from. implemented in such a way to support satellite DLLs.
  1490. //
  1491. // Output:
  1492. // HINSTANCE
  1493. //
  1494. // Notes:
  1495. //
  1496. HINSTANCE COleControl::GetResourceHandle
  1497. (
  1498. void
  1499. )
  1500. {
  1501. if (!g_fSatelliteLocalization)
  1502. return g_hInstance;
  1503. // if we've already got it, then there's not all that much to do.
  1504. // don't need to crit sect this one right here since even if they do fall
  1505. // into the ::GetResourceHandle call, it'll properly deal with things.
  1506. //
  1507. if (g_hInstResources)
  1508. return g_hInstResources;
  1509. // we'll get the ambient localeid from the host, and pass that on to the
  1510. // automation object.
  1511. //
  1512. // crit sect this for apartment threading support.
  1513. //
  1514. EnterCriticalSection(&g_CriticalSection);
  1515. if (!g_fHaveLocale)
  1516. // if we can't get the ambient locale id, then we'll just continue
  1517. // with the globally set up value.
  1518. //
  1519. if (!GetAmbientProperty(DISPID_AMBIENT_LOCALEID, VT_I4, &g_lcidLocale))
  1520. goto Done;
  1521. g_fHaveLocale = TRUE;
  1522. Done:
  1523. LeaveCriticalSection(&g_CriticalSection);
  1524. return ::GetResourceHandle();
  1525. }