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.

925 lines
24 KiB

  1. //+----------------------------------------------------------------------------
  2. //
  3. // File:
  4. // ole2int.h
  5. //
  6. // Contents:
  7. // This is the internal compound document header file that all
  8. // implementations in the linking and embedding code include.
  9. //
  10. // Classes:
  11. //
  12. // Functions:
  13. //
  14. // History:
  15. // 20-Jan-95 t-ScottH add CThreadCheck::Dump method (_DEBUG only)
  16. // 09-Jan-95 t-scotth changed macro VDATETHREAD to accept a
  17. // pointer
  18. // 19-Apr-94 alexgo renamed global clipboard formats to
  19. // Cairo conventions
  20. // 24-Jan-94 alexgo first pass converting to Cairo style
  21. // memory allocation
  22. // 01/13/93 - alexgo - temporarily disabled _DEBUG for Chicago
  23. // 12/30/93 - ChrisWe - define _DEBUG #if DBG==1 so that asserts
  24. // are included; got rid of some previously #ifdef NEVER
  25. // code; added proper file prolog
  26. // 12/27/93 - ErikGav - changed lstr* to wcs* on Win32
  27. // 12/17/93 - ChrisWe - added first pass at GlobalAlloc debugging
  28. // macros
  29. // 12/08/93 - ChrisWe - made error assert message strings constant;
  30. // formatting changes
  31. // 12/07/93 - ChrisWe - removed obsolete names for memory arenas;
  32. // did some minor formatting; removed obsolete DBCS stuff
  33. //
  34. //-----------------------------------------------------------------------------
  35. /*
  36. * This is the internal ole2 header, which means it contains those
  37. * interfaces which might eventually be exposed to the outside
  38. * and which will be exposed to our implementations. We don't want
  39. * to expose these now, so I have put them in a separate file.
  40. */
  41. #ifndef _LE2INT_H_
  42. #define _LE2INT_H_
  43. // For TLS on Nt, we use a reserved DWORD in the TEB directly. We need to
  44. // include these files in order to get the macro NtCurrentTeb. These must
  45. // be included before windows.h
  46. extern "C"
  47. {
  48. #include <nt.h> // NT_PRODUCT_TYPE
  49. #include <ntdef.h> // NT_PRODUCT_TYPE
  50. #include <ntrtl.h> // NT_PRODUCT_TYPE
  51. #include <nturtl.h> // NT_PRODUCT_TYPE
  52. #include <windef.h> // NT_PRODUCT_TYPE
  53. #include <winbase.h> // NT_PRODUCT_TYPE
  54. }
  55. // ------------------------------------
  56. // system includes
  57. #include <string.h>
  58. #include <stdlib.h>
  59. #include <stddef.h>
  60. #ifdef WIN32
  61. # include <wchar.h>
  62. #else
  63. # include <ctype.h>
  64. #endif
  65. // we need to turn on the validation code in the ole library for
  66. // Cairo/Daytona/Chicago debug builds, which was keyed off _DEBUG
  67. // in the win16 code. It appears we need this before any other files
  68. // are included so that debug only declarations in ole2.h/compobj.h
  69. // get processed.
  70. #if DBG==1
  71. # ifndef _DEBUG
  72. # define _DEBUG
  73. # endif
  74. #endif
  75. #ifndef _MAC
  76. # include <windows.h>
  77. # include <malloc.h>
  78. # include <shellapi.h>
  79. #else
  80. //#include <mac.h>
  81. #endif // _MAC
  82. //
  83. // Debug support
  84. //
  85. # include <debnot.h>
  86. DECLARE_DEBUG(LE)
  87. DECLARE_DEBUG(Ref)
  88. DECLARE_DEBUG(DD)
  89. #if DBG==1
  90. #define LEDebugOut(x) LEInlineDebugOut x
  91. #define RefDebugOut(x) RefInlineDebugOut x
  92. #define DDDebugOut(x) DDInlineDebugOut x
  93. #else
  94. #define LEDebugOut(x) NULL
  95. #define RefDebugOut(x) NULL
  96. #define DDDebugOut(x) NULL
  97. #endif // DBG
  98. #include <tls.h>
  99. //+-------------------------------------------------------------------------
  100. //
  101. // Function: LEERROR (macro)
  102. //
  103. // Synopsis: prints out an error message if [cond] is TRUE, along with
  104. // the file and line information
  105. //
  106. // Effects:
  107. //
  108. // Arguments: [cond] -- condition to test against
  109. // [szError] -- string to print out
  110. //
  111. // Requires:
  112. //
  113. // Returns:
  114. //
  115. // Signals:
  116. //
  117. // Modifies:
  118. //
  119. // Algorithm:
  120. //
  121. // History: dd-mmm-yy Author Comment
  122. // 18-Apr-94 alexgo author
  123. //
  124. // Notes: Only present in DEBUG builds
  125. //
  126. //--------------------------------------------------------------------------
  127. #if DBG==1
  128. #define LEERROR( cond, szError ) if( cond ) {\
  129. LEDebugOut((DEB_ERROR, "ERROR!: %s (%s %d)\n", szError, __FILE__, \
  130. __LINE__)); }
  131. #else
  132. #define LEERROR( cond, szError )
  133. #endif //!DBG
  134. //+-------------------------------------------------------------------------
  135. //
  136. // Function: LEWARN (macro)
  137. //
  138. // Synopsis: prints out a warning message if [cond] is TRUE, along with
  139. // the file and line information
  140. //
  141. // Effects:
  142. //
  143. // Arguments: [cond] -- condition to test against
  144. // [szWarn] -- string to print out
  145. //
  146. // Requires:
  147. //
  148. // Returns:
  149. //
  150. // Signals:
  151. //
  152. // Modifies:
  153. //
  154. // Algorithm:
  155. //
  156. // History: dd-mmm-yy Author Comment
  157. // 18-Apr-94 alexgo author
  158. //
  159. // Notes: Only present in DEBUG builds
  160. //
  161. //--------------------------------------------------------------------------
  162. #if DBG==1
  163. #define LEWARN( cond, szWarn ) if( cond ) {\
  164. LEDebugOut((DEB_WARN, "WARNING!: %s (%s %d)\n", szWarn, __FILE__, \
  165. __LINE__)); }
  166. #else
  167. #define LEWARN( cond, szWarn )
  168. #endif //!DBG
  169. //+-------------------------------------------------------------------------
  170. //
  171. // Function: LEVERIFY (macro)
  172. //
  173. // Synopsis: prints out a warning message if [cond] is FALSE, along with
  174. // the file and line information. In non-debug builds, the
  175. // condition IS still evaluated/executed.
  176. //
  177. // Effects:
  178. //
  179. // Arguments: [cond] -- condition to test for (intended to be true)
  180. //
  181. // Requires:
  182. //
  183. // Returns:
  184. //
  185. // Signals:
  186. //
  187. // Modifies:
  188. //
  189. // Algorithm:
  190. //
  191. // History: dd-mmm-yy Author Comment
  192. // 30-Aug-94 davepl author
  193. //
  194. // Notes: Warns only in DEBUG builds, executes in all builds
  195. //
  196. //--------------------------------------------------------------------------
  197. #if DBG==1
  198. #define LEVERIFY( cond ) ( (cond) ? \
  199. (void) NULL : \
  200. LEDebugOut((DEB_WARN, "VERIFY FAILED: %s (%s %d)\n", #cond, __FILE__, __LINE__)) \
  201. )
  202. #else
  203. #define LEVERIFY( cond ) (void) (cond)
  204. #endif //!DBG
  205. #ifdef WIN32
  206. # define __loadds // Not used
  207. # define UnlockData(ds) // Not used
  208. # define _fmalloc malloc
  209. # define _frealloc realloc
  210. # define _ffree free
  211. #endif // WIN32
  212. #ifdef WIN32
  213. # define _xmemset memset
  214. # define _xmemcpy memcpy
  215. # define _xmemcmp memcmp
  216. # define _xmemmove memmove
  217. #else
  218. # define _xmemset _fmemset
  219. # define _xmemcpy _fmemcpy
  220. # define _xmemcmp _fmemcmp
  221. # define _xmemmove _fmemmove
  222. #endif // WIN32
  223. #ifdef WIN32
  224. # define EXPORT
  225. #else
  226. # define EXPORT __export
  227. #endif
  228. // ------------------------------------
  229. // public includes
  230. #include <ole2.h>
  231. #include <ole2sp.h>
  232. #include <ole2com.h>
  233. // ------------------------------------
  234. // internal includes
  235. #include <utils.h>
  236. #include <olecoll.h>
  237. #include <valid.h>
  238. #include <map_kv.h>
  239. #include <privguid.h>
  240. #include <memapi.hxx>
  241. /* Exported CLSIDs.. */
  242. // REVIEW, why not just change these to be correct?
  243. #define CLSID_StaticMetafile CLSID_Picture_Metafile
  244. #define CLSID_StaticDib CLSID_Picture_Dib
  245. #ifdef _MAC
  246. #define BITMAP_TO_DIB(foretc)
  247. #else
  248. #define BITMAP_TO_DIB(foretc) \
  249. if (foretc.cfFormat == CF_BITMAP) {\
  250. foretc.cfFormat = CF_DIB;\
  251. foretc.tymed = TYMED_HGLOBAL;\
  252. }
  253. #endif // _MAC
  254. // NOTE!!!
  255. //
  256. // If a member is added to the aspect, tymed, or advf enumerations,
  257. // these values MUST be updated accordingly!!
  258. #define MAX_VALID_ASPECT DVASPECT_DOCPRINT
  259. #define MAX_VALID_TYMED TYMED_ENHMF
  260. #define MAX_VALID_ADVF ADVF_DATAONSTOP
  261. // This creates a mask of the valid ADVF bits:
  262. #define MASK_VALID_ADVF ((MAX_VALID_ADVF << 1) - 1)
  263. // #include "pres.h"
  264. #define VERIFY_ASPECT_SINGLE(dwAsp) {\
  265. if (!(dwAsp && !(dwAsp & (dwAsp-1)) && (dwAsp <= MAX_VALID_ASPECT))) {\
  266. LEDebugOut((DEB_WARN, "More than 1 aspect is specified"));\
  267. return ResultFromScode(DV_E_DVASPECT);\
  268. }\
  269. }
  270. #define VERIFY_TYMED_SINGLE(tymed) {\
  271. if (!(tymed && !(tymed & (tymed-1)) && (tymed <= MAX_VALID_TYMED))) \
  272. return ResultFromScode(DV_E_TYMED); \
  273. }
  274. // Legal formats for clipformat (and thus, cache nodes)
  275. // CF_METAFILEPICT && TYMED_MFPICT
  276. // CF_BITMAP && TYMED_GDI
  277. // CF_DIB && TYMED_HGLOBAL
  278. // CF_other && TYMED_HGLOBAL
  279. #define VERIFY_TYMED_VALID_FOR_CLIPFORMAT(pfetc) {\
  280. if ((pfetc->cfFormat==CF_METAFILEPICT && !(pfetc->tymed & TYMED_MFPICT))\
  281. || (pfetc->cfFormat==CF_ENHMETAFILE && !(pfetc->tymed & TYMED_ENHMF))\
  282. || (pfetc->cfFormat==CF_BITMAP && !(pfetc->tymed & TYMED_GDI))\
  283. || (pfetc->cfFormat==CF_DIB && !(pfetc->tymed & TYMED_HGLOBAL))\
  284. || (pfetc->cfFormat!=CF_METAFILEPICT && \
  285. pfetc->cfFormat!=CF_BITMAP && \
  286. pfetc->cfFormat!=CF_DIB && \
  287. pfetc->cfFormat!=CF_ENHMETAFILE && \
  288. !(pfetc->tymed & TYMED_HGLOBAL)))\
  289. return ResultFromScode(DV_E_TYMED); \
  290. }
  291. #define VERIFY_TYMED_SINGLE_VALID_FOR_CLIPFORMAT(pfetc) \
  292. { \
  293. if (pfetc->cfFormat==CF_METAFILEPICT && pfetc->tymed != TYMED_MFPICT) \
  294. return ResultFromScode(DV_E_TYMED); \
  295. \
  296. if (pfetc->cfFormat==CF_ENHMETAFILE && pfetc->tymed != TYMED_ENHMF) \
  297. return ResultFromScode(DV_E_TYMED); \
  298. \
  299. if (pfetc->cfFormat==CF_BITMAP && pfetc->tymed != TYMED_GDI) \
  300. return ResultFromScode(DV_E_TYMED); \
  301. \
  302. if (pfetc->cfFormat==CF_DIB && pfetc->tymed != TYMED_HGLOBAL) \
  303. return ResultFromScode(DV_E_TYMED); \
  304. \
  305. if (pfetc->cfFormat != CF_METAFILEPICT) \
  306. if (pfetc->cfFormat != CF_BITMAP) \
  307. if (pfetc->cfFormat != CF_DIB) \
  308. if (pfetc->cfFormat != CF_ENHMETAFILE) \
  309. if (pfetc->tymed != TYMED_HGLOBAL) \
  310. return ResultFromScode(DV_E_TYMED); \
  311. }
  312. // This was the original code...
  313. /*
  314. #define VERIFY_TYMED_SINGLE_VALID_FOR_CLIPFORMAT(pfetc) {\
  315. if ((pfetc->cfFormat==CF_METAFILEPICT && pfetc->tymed!=TYMED_MFPICT)\
  316. || ( (pfetc->cfFormat==CF_BITMAP || \
  317. pfetc->cfFormat == CF_DIB ) \
  318. && pfetc->tymed!=TYMED_GDI)\
  319. || (pfetc->cfFormat!=CF_METAFILEPICT && \
  320. pfetc->cfFormat!=CF_BITMAP && \
  321. pfetc->cfFormat!=CF_DIB && \
  322. pfetc->tymed!=TYMED_HGLOBAL)) \
  323. return ResultFromScode(DV_E_TYMED); \
  324. }
  325. */
  326. //+----------------------------------------------------------------------------
  327. //
  328. // Function:
  329. // CreateObjectDescriptor, static
  330. //
  331. // Synopsis:
  332. // Creates and initializes an OBJECTDESCRIPTOR from the given
  333. // parameters
  334. //
  335. // Arguments:
  336. // [clsid] -- the class ID of the object being transferred
  337. // [dwAspect] -- the display aspect drawn by the source of the
  338. // transfer
  339. // [psizel] -- pointer to the size of the object
  340. // [ppointl] -- pointer to the mouse offset in the object that
  341. // initiated a drag-drop transfer
  342. // [dwStatus] -- the OLEMISC status flags for the object
  343. // being transferred
  344. // [lpszFullUserTypeName] -- the full user type name of the
  345. // object being transferred
  346. // [lpszSrcOfCopy] -- a human readable name for the object
  347. // being transferred
  348. //
  349. // Returns:
  350. // If successful, A handle to the new OBJECTDESCRIPTOR; otherwise
  351. // NULL.
  352. //
  353. // Notes:
  354. // REVIEW, this seems generally useful for anyone using the
  355. // clipboard, or drag-drop; perhaps it should be exported.
  356. //
  357. // History:
  358. // 12/07/93 - ChrisWe - file inspection and cleanup
  359. //
  360. //-----------------------------------------------------------------------------
  361. INTERNAL_(HGLOBAL) CreateObjectDescriptor(CLSID clsid, DWORD dwAspect,
  362. const SIZEL FAR *psizel, const POINTL FAR *ppointl,
  363. DWORD dwStatus, LPOLESTR lpszFullUserTypeName,
  364. LPOLESTR lpszSrcOfCopy);
  365. INTERNAL_(HRESULT) CheckTymedCFCombination(LPFORMATETC pfetc);
  366. /*
  367. #define VERIFY_ASPECT_SINGLE(dwAsp) {\
  368. if (!(dwAsp && !(dwAsp & (dwAsp-1)) && (dwAsp <= MAX_VALID_ASPECT))) {\
  369. AssertSz(FALSE, "More than 1 aspect is specified");\
  370. return ResultFromScode(DV_E_DVASPECT);\
  371. }\
  372. }
  373. */
  374. //+----------------------------------------------------------------------------
  375. //
  376. // Function:
  377. // VerifyAspectSingle (Internal Inline)
  378. //
  379. // Synopsis:
  380. // Verifies that exactly one bit is set in the aspect, and that
  381. // it is one of the known aspect bits.
  382. //
  383. // Returns:
  384. // S_OK For a valid aspect
  385. // DV_E_ASPECT For an invalid aspect
  386. //
  387. // Notes:
  388. // The (0 == (dwAsp & (dwAsp - 1))) test is an efficient means
  389. // for testing that exactly at most bit is set in dwAsp, once it
  390. // is known that dwAsp is nonzero.
  391. //
  392. // History:
  393. // 01/07/94 DavePl Created
  394. //
  395. //-----------------------------------------------------------------------------
  396. inline HRESULT VerifyAspectSingle(DWORD dwAsp)
  397. {
  398. // Ensure at least one bit is set
  399. if (dwAsp)
  400. {
  401. // Ensure at most one bit is set
  402. if (0 == (dwAsp & (dwAsp-1)))
  403. {
  404. // Ensure that one bit is valid
  405. if (MAX_VALID_ASPECT >= dwAsp)
  406. {
  407. return S_OK;
  408. }
  409. }
  410. }
  411. LEDebugOut((DEB_WARN,"WARNING: Invalid Aspect DWORD -> %0X\n", dwAsp));
  412. return DV_E_DVASPECT;
  413. }
  414. /*
  415. #define VERIFY_TYMED_SINGLE(tymed) {\
  416. if (!(tymed && !(tymed & (tymed-1)) && (tymed <= MAX_VALID_TYMED))) \
  417. return ResultFromScode(DV_E_TYMED); \
  418. }
  419. */
  420. //+----------------------------------------------------------------------------
  421. //
  422. // Function:
  423. // VerifyTymedSingle (Internal Inline)
  424. //
  425. // Synopsis:
  426. // Verifies that exactly one bit is set in the tymed, and that
  427. // it is one of the known tymed bits.
  428. //
  429. // Returns:
  430. // S_OK For a valid aspect
  431. // DV_E_ASPECT For an invalid aspect
  432. //
  433. // Notes:
  434. // The (0 == (dwAsp & (dwAsp - 1))) test is an efficient means
  435. // for testing that exactly at most bit is set in dwTymed, once it
  436. // is known that dwTymed is nonzero.
  437. //
  438. // History:
  439. // 01/07/94 DavePl Created
  440. //
  441. //-----------------------------------------------------------------------------
  442. inline HRESULT VerifyTymedSingle(DWORD dwTymed)
  443. {
  444. // Ensure that at least one bit is set
  445. if (dwTymed)
  446. {
  447. // Ensure that at most one bit is set
  448. if (0 == (dwTymed & (dwTymed - 1)))
  449. {
  450. // Ensure that the one set bit is a valid one
  451. if (MAX_VALID_TYMED >= dwTymed)
  452. {
  453. return S_OK;
  454. }
  455. }
  456. }
  457. LEDebugOut((DEB_WARN,"WARNING: Invalid Tymed DWORD -> %0X\n", dwTymed));
  458. return DV_E_TYMED;
  459. }
  460. //+-------------------------------------------------------------------------
  461. //
  462. // Class: CSafeRefCount
  463. //
  464. // Purpose: A class that implements reference counting rules for objects.
  465. // It keeps track of reference count and zombie state.
  466. // It helps object manage their liveness properly.
  467. //
  468. // History: dd-mmm-yy Author Comment
  469. // 16-Jan-97 Gopalk Simplified and Rewritten to handle
  470. // aggregation
  471. //
  472. //--------------------------------------------------------------------------
  473. class CSafeRefCount : public CPrivAlloc
  474. {
  475. public:
  476. // Constructor
  477. CSafeRefCount(IUnknown *pUnkOuter) {
  478. m_cRefs = 0;
  479. m_fInDelete = FALSE;
  480. m_pUnkOuter = pUnkOuter;
  481. #if DBG==1
  482. m_cNestCount = 0;
  483. #endif
  484. }
  485. // Destructor. It has to be virtual so that delete this will
  486. // despatched to the right object
  487. virtual ~CSafeRefCount() {
  488. Win4Assert(!m_cRefs && !m_cNestCount && m_fInDelete);
  489. }
  490. // Reference count methods
  491. ULONG SafeAddRef() {
  492. return InterlockedIncrement((LONG *)& m_cRefs);
  493. }
  494. ULONG SafeRelease();
  495. // Nest count methods
  496. void IncrementNestCount() {
  497. #if DBG==1
  498. InterlockedIncrement((LONG *) &m_cNestCount);
  499. #endif
  500. if(m_pUnkOuter)
  501. m_pUnkOuter->AddRef();
  502. else
  503. SafeAddRef();
  504. return;
  505. }
  506. void DecrementNestCount() {
  507. #if DBG==1
  508. InterlockedDecrement((LONG *) &m_cNestCount);
  509. Win4Assert((LONG) m_cNestCount >= 0);
  510. #endif
  511. if(m_pUnkOuter)
  512. m_pUnkOuter->Release();
  513. else
  514. SafeRelease();
  515. return;
  516. }
  517. // State methods
  518. BOOL IsZombie() {
  519. return m_fInDelete;
  520. }
  521. // Other useful methods
  522. IUnknown *GetPUnkOuter() {
  523. return m_pUnkOuter;
  524. }
  525. ULONG GetRefCount(void) {
  526. return m_cRefs;
  527. }
  528. #if DBG==1
  529. ULONG GetNestCount(void) {
  530. return m_cNestCount;
  531. }
  532. #endif
  533. private:
  534. ULONG m_cRefs;
  535. BOOL m_fInDelete;
  536. IUnknown *m_pUnkOuter;
  537. #if DBG==1
  538. ULONG m_cNestCount;
  539. #endif
  540. };
  541. //+-------------------------------------------------------------------------
  542. //
  543. // Class: CRefExportCount
  544. //
  545. // Purpose: A class that implements reference counting rules for server
  546. // objects that export their nested objects on behalf of their
  547. // clients like DEFHANDLER abd CACHE. It keeps track of
  548. // reference count, export count, zombie state, etc.
  549. // It helps object manage their shutdown logic properly.
  550. //
  551. // History: dd-mmm-yy Author Comment
  552. // 16-Jan-97 Gopalk Creation
  553. //
  554. //--------------------------------------------------------------------------
  555. class CRefExportCount : public CPrivAlloc
  556. {
  557. public:
  558. // Constructor
  559. CRefExportCount(IUnknown *pUnkOuter) {
  560. m_cRefs = 0;
  561. m_cExportCount = 0;
  562. m_IsZombie = FALSE;
  563. m_Status = ALIVE;
  564. m_pUnkOuter = pUnkOuter;
  565. #if DBG==1
  566. m_cNestCount = 0;
  567. #endif
  568. }
  569. // Destructor. It has to be virtual so that delete this will
  570. // despatched to the right object
  571. virtual ~CRefExportCount() {
  572. Win4Assert(!m_cRefs && !m_cNestCount && !m_cExportCount &&
  573. m_IsZombie && m_Status==DEAD);
  574. }
  575. // Reference count methods
  576. ULONG SafeAddRef() {
  577. return InterlockedIncrement((LONG *)& m_cRefs);
  578. }
  579. ULONG SafeRelease();
  580. // Nest count methods
  581. void IncrementNestCount() {
  582. #if DBG==1
  583. InterlockedIncrement((LONG *) &m_cNestCount);
  584. #endif
  585. if(m_pUnkOuter)
  586. m_pUnkOuter->AddRef();
  587. else
  588. SafeAddRef();
  589. return;
  590. }
  591. void DecrementNestCount() {
  592. #if DBG==1
  593. InterlockedDecrement((LONG *) &m_cNestCount);
  594. Win4Assert((LONG) m_cNestCount >= 0);
  595. #endif
  596. if(m_pUnkOuter)
  597. m_pUnkOuter->Release();
  598. else
  599. SafeRelease();
  600. return;
  601. }
  602. // Methods used by exported nested objects
  603. ULONG IncrementExportCount() {
  604. return InterlockedIncrement((LONG *) &m_cExportCount);
  605. }
  606. ULONG DecrementExportCount();
  607. // State methods
  608. BOOL IsZombie() {
  609. return m_IsZombie;
  610. }
  611. BOOL IsExported() {
  612. return m_cExportCount>0;
  613. }
  614. // Other useful methods
  615. IUnknown *GetPUnkOuter() {
  616. return m_pUnkOuter;
  617. }
  618. ULONG GetRefCount(void) {
  619. return m_cRefs;
  620. }
  621. ULONG GetExportCount(void) {
  622. return m_cExportCount;
  623. }
  624. #if DBG==1
  625. ULONG GetNestCount(void) {
  626. return m_cNestCount;
  627. }
  628. #endif
  629. private:
  630. // Cleanup function which is invoked when the object transistions
  631. // into zombie state. It is virtual so that the correct cleanup
  632. // function is invoked
  633. virtual void CleanupFn(void) {
  634. return;
  635. }
  636. // Tokens used
  637. enum tagTokens {
  638. ALIVE = 0,
  639. KILL = 1,
  640. DEAD = 2
  641. };
  642. // Member variables
  643. ULONG m_cRefs;
  644. ULONG m_cExportCount;
  645. ULONG m_IsZombie;
  646. ULONG m_Status;
  647. IUnknown *m_pUnkOuter;
  648. #if DBG==1
  649. ULONG m_cNestCount;
  650. #endif
  651. };
  652. //+-------------------------------------------------------------------------
  653. //
  654. // Class: CStabilize
  655. //
  656. // Purpose: An instance of this class should be allocated on the
  657. // stack of every object method that makes an outgoing call.
  658. //
  659. // History: dd-mmm-yy Author Comment
  660. // 16-Jan-97 Gopalk Simplified and Rewritten to handle
  661. // aggregation
  662. //
  663. //--------------------------------------------------------------------------
  664. class CStabilize
  665. {
  666. public:
  667. // Constructor
  668. CStabilize(CSafeRefCount *pSafeRefCount) {
  669. m_pSafeRefCount = pSafeRefCount;
  670. pSafeRefCount->IncrementNestCount();
  671. }
  672. // Destructor
  673. ~CStabilize() {
  674. m_pSafeRefCount->DecrementNestCount();
  675. }
  676. private:
  677. CSafeRefCount *m_pSafeRefCount;
  678. };
  679. //+-------------------------------------------------------------------------
  680. //
  681. // Class: CRefStabilize
  682. //
  683. // Purpose: An instance of this class should be allocated on the
  684. // stack of every object method that makes an outgoing call.
  685. //
  686. // History: dd-mmm-yy Author Comment
  687. // 16-Jan-97 Gopalk Simplified and Rewritten to handle
  688. // aggregation
  689. //
  690. //--------------------------------------------------------------------------
  691. class CRefStabilize
  692. {
  693. public:
  694. // Constructor
  695. CRefStabilize(CRefExportCount *pRefExportCount) {
  696. m_pRefExportCount = pRefExportCount;
  697. pRefExportCount->IncrementNestCount();
  698. }
  699. // Destructor
  700. ~CRefStabilize() {
  701. m_pRefExportCount->DecrementNestCount();
  702. }
  703. private:
  704. CRefExportCount *m_pRefExportCount;
  705. };
  706. //+-------------------------------------------------------------------------
  707. //
  708. // Class: CThreadCheck
  709. //
  710. // Purpose: ensures that an object is called on the correct thread
  711. //
  712. // Interface:
  713. //
  714. // History: dd-mmm-yy Author Comment
  715. // 30-Jan-95 t-ScottH add Dump method to CThreadCheck class
  716. // (_DEBUG only)
  717. // 21-Nov-94 alexgo author
  718. //
  719. // Notes: To use this class, an object should simply publicly
  720. // inherit CThreadCheck. The VDATETHREAD macro can then be
  721. // used to check the thread id at each entry point.
  722. //
  723. //--------------------------------------------------------------------------
  724. class CThreadCheck
  725. {
  726. public:
  727. inline CThreadCheck();
  728. BOOL VerifyThreadId(); // in utils.cpp
  729. #ifdef _DEBUG
  730. HRESULT Dump(char **ppszDumpOA, ULONG ulFlag, int nIndentLevel); // utils.cpp
  731. #endif //_DEBUG
  732. private:
  733. DWORD m_tid;
  734. };
  735. //+-------------------------------------------------------------------------
  736. //
  737. // Member: CThreadCheck::CThreadCheck
  738. //
  739. // Synopsis: stores the current thread id
  740. //
  741. // Effects:
  742. //
  743. // Arguments:
  744. //
  745. // Requires:
  746. //
  747. // Returns: void
  748. //
  749. // Signals:
  750. //
  751. // Modifies:
  752. //
  753. // Derivation:
  754. //
  755. // Algorithm:
  756. //
  757. // History: dd-mmm-yy Author Comment
  758. // 21-Nov-94 alexgo author
  759. //
  760. // Notes:
  761. //
  762. //--------------------------------------------------------------------------
  763. inline CThreadCheck::CThreadCheck( void )
  764. {
  765. m_tid = GetCurrentThreadId();
  766. LEWARN(!m_tid, "GetCurrentThreadId failed!!");
  767. }
  768. //+-------------------------------------------------------------------------
  769. //
  770. // Function: VDATETHREAD (macro)
  771. //
  772. // Synopsis: makes sure the correct thread is called
  773. //
  774. // Effects:
  775. //
  776. // Arguments:
  777. //
  778. // Requires: the calling class must inherit from CThreadCheck
  779. //
  780. // Returns: RPC_E_WRONG_THREAD if called on the wrong thread
  781. //
  782. // Signals:
  783. //
  784. // Modifies:
  785. //
  786. // Algorithm:
  787. //
  788. // History: dd-mmm-yy Author Comment
  789. // 09-Jan-95 t-ScottH give VDATETHREAD an argument
  790. // 21-Nov-94 alexgo author
  791. //
  792. // Notes: THIS MACRO FUNCTIONS IN RETAIL BUILDS TOO!!!
  793. //
  794. //--------------------------------------------------------------------------
  795. #define VDATETHREAD(pObject) if( !( pObject->VerifyThreadId() ) ) { return RPC_E_WRONG_THREAD; }
  796. // utility macros.
  797. #define LONG_ABS(x) ((x) < 0 ? -(x) : (x))
  798. #endif // _LE2INT_H_
  799.