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.

567 lines
21 KiB

  1. //+---------------------------------------------------------------------------
  2. //
  3. // File: tls.hxx
  4. //
  5. // Purpose: manage thread local storage for OLE
  6. //
  7. // Notes: The gTlsIndex is initialized at process attach time.
  8. // The per-thread data is allocated in CoInitialize in
  9. // single-threaded apartments or on first use in
  10. // multi-threaded apartments.
  11. //
  12. // The non-inline routines are in ..\com\class\tls.cxx
  13. //
  14. // History: 16-Jun-94 BruceMa Don't decrement 0 thread count
  15. // 17-Jun-94 Bradloc Added punkState for VB94
  16. // 20-Jun-94 Rickhi Commented better
  17. // 06-Jul-94 BruceMa Support for CoGetCurrentProcess
  18. // 19-Jul-94 CraigWi Removed TLSGetEvent (used cache instead)
  19. // 21-Jul-94 AlexT Add TLSIncOleInit, TLSDecOleInit
  20. // 21-Aug-95 ShannonC Removed TLSSetMalloc, TLSGetMalloc
  21. // 06-Oct-95 Rickhi Simplified. Made into a C++ class.
  22. // 01-Feb-96 Rickhi On Nt, access TEB directly
  23. // 30-May-96 ShannonC Add punkError
  24. // 12-Sep-96 rogerg Add pDataObjClip
  25. // 26-Nov-96 Gopalk Add IsOleInitialized
  26. // 13-Jan-97 RichN Add pContextObj
  27. // 10-Feb-99 TarunA Add cAsyncSends
  28. //----------------------------------------------------------------------------
  29. #ifndef _TLS_HXX_
  30. #define _TLS_HXX_
  31. #include <rpc.h> // UUID
  32. //+---------------------------------------------------------------------------
  33. //
  34. // forward declarations (in order to avoid type casting when accessing
  35. // data members of the SOleTlsData structure).
  36. //
  37. //+---------------------------------------------------------------------------
  38. class CAptCallCtrl; // see callctrl.hxx
  39. class CSrvCallState; // see callctrl.hxx
  40. class CObjServer; // see sobjact.hxx
  41. class CSmAllocator; // see stg\h\smalloc.hxx
  42. class CMessageCall; // see call.hxx
  43. class CClientCall; // see call.hxx
  44. class CAsyncCall; // see call.hxx
  45. class CClipDataObject; // see ole232\clipbrd\clipdata.h
  46. class CSurrogatedObjectList; // see com\inc\comsrgt.hxx
  47. class CCtxCall; // see PSTable.hxx
  48. class CPolicySet; // see PSTable.hxx
  49. class CObjectContext; // see context.hxx
  50. class CComApartment; // see aprtmnt.hxx
  51. #ifdef _CHICAGO_
  52. // Chicago uses the Thread Local Storage APIs
  53. extern DWORD gTlsIndex; // global Index for TLS
  54. #endif // _CHICAGO_
  55. //+-------------------------------------------------------------------
  56. //
  57. // Struct: CallEntry
  58. //
  59. // Synopsis: Call Table Entry.
  60. //
  61. //+-------------------------------------------------------------------
  62. typedef struct tagCallEntry
  63. {
  64. void *pNext; // ptr to next entry
  65. void *pvObject; // Entry object
  66. } CallEntry;
  67. //+-------------------------------------------------------------------
  68. //
  69. // Struct: LockEntry
  70. //
  71. // Synopsis: Call Table Entry.
  72. //
  73. //+-------------------------------------------------------------------
  74. #define LOCKS_PER_ENTRY 16
  75. typedef struct tagLockEntry
  76. {
  77. tagLockEntry *pNext; // ptr to next entry
  78. WORD wReaderLevel[LOCKS_PER_ENTRY]; // reader nesting level
  79. } LockEntry;
  80. //+-------------------------------------------------------------------
  81. //
  82. // Struct: ContextStackNode
  83. //
  84. // Synopsis: Stack of contexts used with Services Without Components
  85. //
  86. //+-------------------------------------------------------------------
  87. typedef struct tagContextStackNode
  88. {
  89. tagContextStackNode* pNext;
  90. CObjectContext* pSavedContext;
  91. CObjectContext* pServerContext;
  92. CCtxCall* pClientCall;
  93. CCtxCall* pServerCall;
  94. CPolicySet* pPS;
  95. } ContextStackNode;
  96. //+-------------------------------------------------------------------
  97. //
  98. // Struct: InitializeSpyNode
  99. //
  100. // Synopsis: Node in a linked list of Initialize Spy registrations
  101. //
  102. //+-------------------------------------------------------------------
  103. typedef struct tagInitializeSpyNode
  104. {
  105. tagInitializeSpyNode *pNext;
  106. tagInitializeSpyNode *pPrev;
  107. DWORD dwRefs;
  108. DWORD dwCookie;
  109. IInitializeSpy *pInitSpy;
  110. } InitializeSpyNode;
  111. //+---------------------------------------------------------------------------
  112. //
  113. // Enum: OLETLSFLAGS
  114. //
  115. // Synopsys: bit values for dwFlags field of SOleTlsData. If you just want
  116. // to store a BOOL in TLS, use this enum and the dwFlag field.
  117. //
  118. //+---------------------------------------------------------------------------
  119. typedef enum tagOLETLSFLAGS
  120. {
  121. OLETLS_LOCALTID = 0x01, // This TID is in the current process.
  122. OLETLS_UUIDINITIALIZED = 0x02, // This Logical thread is init'd.
  123. OLETLS_INTHREADDETACH = 0x04, // This is in thread detach. Needed
  124. // due to NT's special thread detach
  125. // rules.
  126. OLETLS_CHANNELTHREADINITIALZED = 0x08,// This channel has been init'd
  127. OLETLS_WOWTHREAD = 0x10, // This thread is a 16-bit WOW thread.
  128. OLETLS_THREADUNINITIALIZING = 0x20, // This thread is in CoUninitialize.
  129. OLETLS_DISABLE_OLE1DDE = 0x40, // This thread can't use a DDE window.
  130. OLETLS_APARTMENTTHREADED = 0x80, // This is an STA apartment thread
  131. OLETLS_MULTITHREADED = 0x100, // This is an MTA apartment thread
  132. OLETLS_IMPERSONATING = 0x200, // This thread is impersonating
  133. OLETLS_DISABLE_EVENTLOGGER = 0x400, // Prevent recursion in event logger
  134. OLETLS_INNEUTRALAPT = 0x800, // This thread is in the NTA
  135. OLETLS_DISPATCHTHREAD = 0x1000, // This is a dispatch thread
  136. OLETLS_HOSTTHREAD = 0x2000, // This is a host thread
  137. OLETLS_ALLOWCOINIT = 0x4000, // This thread allows inits
  138. OLETLS_PENDINGUNINIT = 0x8000, // This thread has pending uninit
  139. OLETLS_FIRSTMTAINIT = 0x10000,// First thread to attempt an MTA init
  140. OLETLS_FIRSTNTAINIT = 0x20000,// First thread to attempt an NTA init
  141. OLETLS_APTINITIALIZING = 0x40000 // Apartment Object is initializing
  142. } OLETLSFLAGS;
  143. //+---------------------------------------------------------------------------
  144. //
  145. // Structure: SOleTlsData
  146. //
  147. // Synopsis: structure holding per thread state needed by OLE32
  148. //
  149. //+---------------------------------------------------------------------------
  150. typedef struct tagSOleTlsData
  151. {
  152. // jsimmons 5/23/2001
  153. // Alert Alert: nefarious folks (eg, URT) are looking in our TLS at
  154. // various stuff. They expect that pCurrentCtx will be at a certain
  155. // offset from the beginning of the tls struct. So don't add, delete, or
  156. // move any members within this block.
  157. /////////////////////////////////////////////////////////////////////////////////////////
  158. // ********* BEGIN "NO MUCKING AROUND" BLOCK *********
  159. /////////////////////////////////////////////////////////////////////////////////////////
  160. // Docfile multiple allocator support
  161. void *pvThreadBase; // per thread base pointer
  162. CSmAllocator *pSmAllocator; // per thread docfile allocator
  163. DWORD dwApartmentID; // Per thread "process ID"
  164. DWORD dwFlags; // see OLETLSFLAGS above
  165. LONG TlsMapIndex; // index in the global TLSMap
  166. void **ppTlsSlot; // Back pointer to the thread tls slot
  167. DWORD cComInits; // number of per-thread inits
  168. DWORD cOleInits; // number of per-thread OLE inits
  169. DWORD cCalls; // number of outstanding calls
  170. CMessageCall *pCallInfo; // channel call info
  171. CAsyncCall *pFreeAsyncCall; // ptr to available call object for this thread.
  172. CClientCall *pFreeClientCall; // ptr to available call object for this thread.
  173. CObjServer *pObjServer; // Activation Server Object for this apartment.
  174. DWORD dwTIDCaller; // TID of current calling app
  175. CObjectContext *pCurrentCtx; // Current context
  176. /////////////////////////////////////////////////////////////////////////////////////////
  177. // ********* END "NO MUCKING AROUND" BLOCK *********
  178. /////////////////////////////////////////////////////////////////////////////////////////
  179. CObjectContext *pEmptyCtx; // Empty context
  180. CObjectContext *pNativeCtx; // Native context
  181. ULONGLONG ContextId; // Uniquely identifies the current context
  182. CComApartment *pNativeApt; // Native apartment for the thread.
  183. IUnknown *pCallContext; // call context object
  184. CCtxCall *pCtxCall; // Context call object
  185. CPolicySet *pPS; // Policy set
  186. PVOID pvPendingCallsFront;// Per Apt pending async calls
  187. PVOID pvPendingCallsBack;
  188. CAptCallCtrl *pCallCtrl; // call control for RPC for this apartment
  189. CSrvCallState *pTopSCS; // top server-side callctrl state
  190. IMessageFilter *pMsgFilter; // temp storage for App MsgFilter
  191. HWND hwndSTA; // STA server window same as poxid->hServerSTA
  192. // ...needed on Win95 before oxid registration
  193. LONG cORPCNestingLevel; // call nesting level (DBG only)
  194. DWORD cDebugData; // count of bytes of debug data in call
  195. UUID LogicalThreadId; // current logical thread id
  196. HANDLE hThread; // Thread handle used for cancel
  197. HANDLE hRevert; // Token before first impersonate.
  198. IUnknown *pAsyncRelease; // Controlling unknown for async release
  199. // DDE data
  200. HWND hwndDdeServer; // Per thread Common DDE server
  201. HWND hwndDdeClient; // Per thread Common DDE client
  202. ULONG cServeDdeObjects; // non-zero if objects DDE should serve
  203. // ClassCache data
  204. LPVOID pSTALSvrsFront; // Chain of LServers registers in this thread if STA
  205. // upper layer data
  206. HWND hwndClip; // Clipboard window
  207. IDataObject *pDataObjClip; // Current Clipboard DataObject
  208. DWORD dwClipSeqNum; // Clipboard Sequence # for the above DataObject
  209. DWORD fIsClipWrapper; // Did we hand out the wrapper Clipboard DataObject?
  210. IUnknown *punkState; // Per thread "state" object
  211. // cancel data
  212. DWORD cCallCancellation; // count of CoEnableCallCancellation
  213. // async sends data
  214. DWORD cAsyncSends; // count of async sends outstanding
  215. CAsyncCall* pAsyncCallList; // async calls outstanding
  216. CSurrogatedObjectList *pSurrogateList; // Objects in the surrogate
  217. LockEntry lockEntry; // Locks currently held by the thread
  218. CallEntry CallEntry; // client-side call chain for this thread
  219. ContextStackNode* pContextStack; // Context stack node for SWC.
  220. InitializeSpyNode *pFirstSpyReg; // First registered IInitializeSpy
  221. InitializeSpyNode *pFirstFreeSpyReg; // First available spy registration
  222. DWORD dwMaxSpy; // First free IInitializeSpy cookie
  223. #ifdef WX86OLE
  224. IUnknown *punkStateWx86; // Per thread "state" object for Wx86
  225. #endif
  226. void *pDragCursors; // Per thread drag cursor table.
  227. IUnknown *punkError; // Per thread error object.
  228. ULONG cbErrorData; // Maximum size of error data.
  229. IUnknown *punkActiveXSafetyProvider;
  230. #if DBG==1
  231. LONG cTraceNestingLevel; // call nesting level for OLETRACE
  232. #endif
  233. } SOleTlsData;
  234. //+---------------------------------------------------------------------------
  235. //
  236. // class COleTls
  237. //
  238. // Synopsis: class to abstract thread-local-storage in OLE.
  239. //
  240. // Notes: To use Tls in OLE, functions should define an instance of
  241. // this class on their stack, then use the -> operator on the
  242. // instance to access fields of the SOleTls structure.
  243. //
  244. // There are two instances of the ctor. One just Assert's that
  245. // the SOleTlsData has already been allocated for this thread. Most
  246. // internal code should use this ctor, since we can assert that if
  247. // the thread made it this far into our code, tls has already been
  248. // checked.
  249. //
  250. // The other ctor will check if SOleTlsData exists, and attempt to
  251. // allocate and initialize it if it does not. This ctor will
  252. // return an HRESULT. Functions that are entry points to OLE32
  253. // should use this version.
  254. //
  255. //+---------------------------------------------------------------------------
  256. class COleTls
  257. {
  258. public:
  259. COleTls();
  260. COleTls(HRESULT &hr);
  261. COleTls(BOOL fDontAllocateIfNULL);
  262. // to get direct access to the data structure
  263. SOleTlsData * operator->(void) { return _pData; }
  264. operator SOleTlsData *() { return _pData; }
  265. // Helper functions
  266. BOOL IsNULL() { return (_pData == NULL) ? TRUE : FALSE; }
  267. private:
  268. HRESULT TLSAllocData(); // allocates an SOleTlsData structure
  269. SOleTlsData * _pData; // ptr to OLE TLS data
  270. };
  271. extern SOleTlsData *TLSLookupThreadId(DWORD dwThreadId);
  272. #ifndef _CHICAGO_
  273. //+---------------------------------------------------------------------------
  274. //
  275. // Method: COleTls::COleTls
  276. //
  277. // Synopsis: ctor for OLE Tls object.
  278. //
  279. // Notes: Most internal code should use this version of the ctor,
  280. // assuming that some outer-layer function has already verified
  281. // the existence of the tls_data.
  282. //
  283. //+---------------------------------------------------------------------------
  284. __forceinline COleTls::COleTls()
  285. {
  286. _pData = (SOleTlsData *) NtCurrentTeb()->ReservedForOle;
  287. Win4Assert(_pData && "Illegal attempt to use TLS before Initialized");
  288. }
  289. //+---------------------------------------------------------------------------
  290. //
  291. // Method: COleTls::COleTls
  292. //
  293. // Synopsis: ctor for OLE Tls object.
  294. //
  295. // Notes: Special version for CoUninitialize which will not allocate
  296. // (or assert) if the TLS is NULL. It can then be checked with
  297. // IsNULL member function.
  298. //
  299. //+---------------------------------------------------------------------------
  300. __forceinline COleTls::COleTls(BOOL fDontAllocateIfNULL)
  301. {
  302. _pData = (SOleTlsData *) NtCurrentTeb()->ReservedForOle;
  303. }
  304. //+---------------------------------------------------------------------------
  305. //
  306. // Method: COleTls::COleTls
  307. //
  308. // Synopsis: ctor for OLE Tls object.
  309. //
  310. // Notes: Peripheral OLE code that can not assume that some outer-layer
  311. // function has already verified the existence of the SOleTlsData
  312. // structure for the current thread should use this version of
  313. // the ctor.
  314. //
  315. //+---------------------------------------------------------------------------
  316. __forceinline COleTls::COleTls(HRESULT &hr)
  317. {
  318. _pData = (SOleTlsData *) NtCurrentTeb()->ReservedForOle;
  319. if (_pData)
  320. hr = S_OK;
  321. else
  322. hr = TLSAllocData();
  323. }
  324. #else // _CHICAGO_ versions
  325. //+---------------------------------------------------------------------------
  326. //
  327. // Method: COleTls::COleTls
  328. //
  329. // Synopsis: ctor for OLE Tls object.
  330. //
  331. // Notes: Most internal code should use this version of the ctor,
  332. // assuming that some outer-layer function has already verified
  333. // the existence of the tls_data.
  334. //
  335. //+---------------------------------------------------------------------------
  336. inline COleTls::COleTls()
  337. {
  338. _pData = (SOleTlsData *) TlsGetValue(gTlsIndex);
  339. Win4Assert(_pData && "Illegal attempt to use TLS before Initialized");
  340. }
  341. //+---------------------------------------------------------------------------
  342. //
  343. // Method: COleTls::COleTls
  344. //
  345. // Synopsis: ctor for OLE Tls object.
  346. //
  347. // Notes: Special version for CoUninitialize which will not allocate
  348. // (or assert) if the TLS is NULL. It can then be checked with
  349. // IsNULL member function.
  350. //
  351. //+---------------------------------------------------------------------------
  352. inline COleTls::COleTls(BOOL fDontAllocateIfNULL)
  353. {
  354. _pData = (SOleTlsData *) TlsGetValue(gTlsIndex);
  355. }
  356. //+---------------------------------------------------------------------------
  357. //
  358. // Method: COleTls::COleTls
  359. //
  360. // Synopsis: ctor for OLE Tls object.
  361. //
  362. // Notes: Peripheral OLE code that can not assume that some outer-layer
  363. // function has already verified the existence of the SOleTlsData
  364. // structure for the current thread should use this version of
  365. // the ctor.
  366. //
  367. //+---------------------------------------------------------------------------
  368. inline COleTls::COleTls(HRESULT &hr)
  369. {
  370. _pData = (SOleTlsData *) TlsGetValue(gTlsIndex);
  371. if (_pData)
  372. hr = S_OK;
  373. else
  374. hr = TLSAllocData();
  375. }
  376. #endif // _CHICAGO_
  377. //+---------------------------------------------------------------------------
  378. //
  379. // Enum: APTKIND
  380. //
  381. // Synopsis: These are the apartment models COM understands. The
  382. // GetCurrentApartmentKind functions return one of these values
  383. // identifying which apartment the currently executing thread
  384. // is in.
  385. //
  386. //-----------------------------------------------------------------------------
  387. typedef enum tagAPTKIND
  388. {
  389. APTKIND_NEUTRALTHREADED = 0x01,
  390. APTKIND_MULTITHREADED = 0x02,
  391. APTKIND_APARTMENTTHREADED = 0x04
  392. } APTKIND;
  393. //+---------------------------------------------------------------------------
  394. //
  395. // Thread IDs for the various apartment types. STA uses the currently
  396. // executing TID.
  397. //
  398. //----------------------------------------------------------------------------
  399. #define MTATID 0x0 // thread id of the MTA
  400. #define NTATID 0xFFFFFFFF // thread id of the NTA
  401. typedef DWORD HAPT;
  402. const HAPT haptNULL = 0;
  403. //+---------------------------------------------------------------------------
  404. //
  405. // Function: GetCurrentApartmentId
  406. //
  407. // Synopsis: Returns the apartment id that the current thread is executing
  408. // in. If this is the Multi-threaded apartment, it returns 0; if
  409. // it is the Neutral-threaded apartment, it returns 0xFFFFFFFF.
  410. //
  411. //+---------------------------------------------------------------------------
  412. inline DWORD GetCurrentApartmentId()
  413. {
  414. HRESULT hr;
  415. COleTls Tls(hr);
  416. //
  417. // If TLS is not initialized, this is a MTA apartment.
  418. //
  419. if (FAILED(hr))
  420. {
  421. return MTATID;
  422. }
  423. else
  424. {
  425. return (Tls->dwFlags & OLETLS_INNEUTRALAPT) ? NTATID :
  426. (Tls->dwFlags & OLETLS_APARTMENTTHREADED) ? GetCurrentThreadId() :
  427. MTATID;
  428. }
  429. }
  430. //+---------------------------------------------------------------------------
  431. //
  432. // Function: DoATClassCreate
  433. //
  434. // Synopsis: Put a given Class Factory on a new ApartmentModel thread.
  435. //
  436. //+---------------------------------------------------------------------------
  437. HRESULT DoATClassCreate(LPFNGETCLASSOBJECT pfn,
  438. REFCLSID rclsid, REFIID riid, IUnknown **ppunk);
  439. //+---------------------------------------------------------------------------
  440. //
  441. // Function: IsSTAThread
  442. //
  443. // Synopsis: returns TRUE if the current thread is for a
  444. // single-threaded apartment, FALSE otherwise
  445. //
  446. //+---------------------------------------------------------------------------
  447. inline BOOL IsSTAThread()
  448. {
  449. COleTls Tls;
  450. return (Tls->dwFlags & OLETLS_APARTMENTTHREADED) ? TRUE : FALSE;
  451. }
  452. //+---------------------------------------------------------------------------
  453. //
  454. // Function: IsMTAThread
  455. //
  456. // Synopsis: returns TRUE if the current thread is for a
  457. // multi-threaded apartment, FALSE otherwise
  458. //
  459. //+---------------------------------------------------------------------------
  460. inline BOOL IsMTAThread()
  461. {
  462. COleTls Tls;
  463. return (Tls->dwFlags & OLETLS_APARTMENTTHREADED) ? FALSE : TRUE;
  464. }
  465. //+---------------------------------------------------------------------------
  466. //
  467. // Function: IsOleInitialized
  468. //
  469. // Synopsis: returns TRUE if the current thread is for a
  470. // multi-threaded apartment, FALSE otherwise
  471. //
  472. //+---------------------------------------------------------------------------
  473. inline BOOL IsOleInitialized()
  474. {
  475. COleTls Tls(FALSE);
  476. return((!Tls.IsNULL() && Tls->cOleInits>0) ? TRUE : FALSE);
  477. }
  478. BOOL IsApartmentInitialized();
  479. IID *TLSGetLogicalThread();
  480. BOOLEAN TLSIsWOWThread();
  481. BOOLEAN TLSIsThreadDetaching();
  482. void CleanupTlsState(SOleTlsData *pTls, BOOL fSafe);
  483. inline HWND TLSGethwndSTA()
  484. {
  485. COleTls Tls;
  486. return(Tls->hwndSTA);
  487. }
  488. inline void TLSSethwndSTA(HWND hwnd)
  489. {
  490. COleTls Tls;
  491. Tls->hwndSTA = hwnd;
  492. }
  493. #endif // _TLS_HXX_