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.

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