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.

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