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.

1090 lines
52 KiB

  1. /*++
  2. Copyright (c) Microsoft Corporation
  3. Module Name:
  4. sxsctxact.c
  5. Abstract:
  6. Side-by-side activation support for Windows/NT
  7. Implementation of context activation/deactivation
  8. Author:
  9. Michael Grier (MGrier) 2/2/2000
  10. Revision History:
  11. --*/
  12. #if defined(__cplusplus)
  13. extern "C" {
  14. #endif
  15. #pragma warning(disable:4214) // bit field types other than int
  16. #pragma warning(disable:4201) // nameless struct/union
  17. #pragma warning(disable:4115) // named type definition in parentheses
  18. #pragma warning(disable:4127) // condition expression is constant
  19. #include <ntos.h>
  20. #include <ntrtl.h>
  21. #include <nturtl.h>
  22. #include <sxstypes.h>
  23. #include "sxsp.h"
  24. #if NT_SXS_PERF_COUNTERS_ENABLED
  25. #if defined(_X86_)
  26. __inline
  27. ULONGLONG
  28. RtlpGetCycleCount(void)
  29. {
  30. __asm {
  31. RDTSC
  32. }
  33. }
  34. #else
  35. __inline
  36. ULONGLONG
  37. RtlpGetCycleCount(void)
  38. {
  39. return 0;
  40. }
  41. #endif // defined(_X86_)
  42. #endif // NT_SXS_PERF_COUNTERS_ENABLED
  43. // DWORD just so that in the debugger we don't have to guess the size...
  44. ULONG RtlpCaptureActivationContextActivationStacks =
  45. #if DBG
  46. TRUE
  47. #else
  48. FALSE
  49. #endif
  50. ;
  51. //
  52. // APPCOMPAT: Setting this flag to TRUE indicates that we no longer allow
  53. // skipping over "unactivated" (ie: multiple activation) context frames.
  54. // The default action should be FALSE, which will let multiply-activated
  55. // contexts slide by.
  56. //
  57. // WARNING: This allows app authors to be a little sleazy about their activate
  58. // and deactivate pairs.
  59. //
  60. #if DBG
  61. BOOLEAN RtlpNotAllowingMultipleActivation = FALSE;
  62. #else
  63. #define RtlpNotAllowingMultipleActivation FALSE
  64. #endif
  65. NTSTATUS
  66. RtlpAllocateActivationContextStackFrame(
  67. IN ULONG Flags,
  68. PTEB Teb,
  69. OUT PRTL_HEAP_ALLOCATED_ACTIVATION_CONTEXT_STACK_FRAME *FrameOut
  70. )
  71. {
  72. NTSTATUS Status = STATUS_INTERNAL_ERROR;
  73. LIST_ENTRY *ple;
  74. PRTL_HEAP_ALLOCATED_ACTIVATION_CONTEXT_STACK_FRAME Frame = NULL;
  75. ULONG i;
  76. EXCEPTION_RECORD ExceptionRecord;
  77. if (FrameOut != NULL)
  78. *FrameOut = NULL;
  79. ASSERT((Flags == 0) && (FrameOut != NULL) && (Teb != NULL));
  80. if ((Flags != 0) || (FrameOut == NULL) || (Teb == NULL)) {
  81. Status = STATUS_INVALID_PARAMETER;
  82. goto Exit;
  83. }
  84. for (ple = Teb->ActivationContextStack.FrameListCache.Flink; ple != &Teb->ActivationContextStack.FrameListCache; ple = ple->Flink) {
  85. PACTIVATION_CONTEXT_STACK_FRAMELIST FrameList = CONTAINING_RECORD(ple, ACTIVATION_CONTEXT_STACK_FRAMELIST, Links);
  86. // Someone trashed our framelist!
  87. ASSERT(FrameList->Magic == ACTIVATION_CONTEXT_STACK_FRAMELIST_MAGIC);
  88. if (FrameList->Magic != ACTIVATION_CONTEXT_STACK_FRAMELIST_MAGIC) {
  89. ExceptionRecord.ExceptionRecord = NULL;
  90. ExceptionRecord.NumberParameters = 4;
  91. ExceptionRecord.ExceptionInformation[0] = SXS_CORRUPTION_CODE_FRAMELIST;
  92. ExceptionRecord.ExceptionInformation[1] = SXS_CORRUPTION_CODE_FRAMELIST_SUBCODE_BAD_MAGIC;
  93. ExceptionRecord.ExceptionInformation[2] = (ULONG_PTR) &Teb->ActivationContextStack.FrameListCache;
  94. ExceptionRecord.ExceptionInformation[3] = (ULONG_PTR) FrameList;
  95. ExceptionRecord.ExceptionCode = STATUS_SXS_CORRUPTION;
  96. ExceptionRecord.ExceptionFlags = EXCEPTION_NONCONTINUABLE;
  97. RtlRaiseException(&ExceptionRecord);
  98. }
  99. if (FrameList->FramesInUse != RTL_NUMBER_OF(FrameList->Frames)) {
  100. for (i=0; i<RTL_NUMBER_OF(FrameList->Frames); i++) {
  101. if (FrameList->Frames[i].Frame.Flags & RTL_ACTIVATION_CONTEXT_STACK_FRAME_FLAG_ON_FREE_LIST) {
  102. ASSERT(FrameList->FramesInUse != NUMBER_OF(FrameList->Frames));
  103. FrameList->FramesInUse++;
  104. FrameList->NotFramesInUse = ~FrameList->FramesInUse;
  105. Frame = &FrameList->Frames[i];
  106. break;
  107. }
  108. }
  109. }
  110. if (Frame != NULL)
  111. break;
  112. }
  113. if (Frame == NULL) {
  114. // No space left; allocate a new framelist...
  115. PACTIVATION_CONTEXT_STACK_FRAMELIST FrameList = (PACTIVATION_CONTEXT_STACK_FRAMELIST)RtlAllocateHeap(RtlProcessHeap(), 0, sizeof(ACTIVATION_CONTEXT_STACK_FRAMELIST));
  116. if (FrameList == NULL) {
  117. Status = STATUS_NO_MEMORY;
  118. goto Exit;
  119. }
  120. FrameList->Magic = ACTIVATION_CONTEXT_STACK_FRAMELIST_MAGIC;
  121. FrameList->Flags = 0;
  122. for (i=0; i<RTL_NUMBER_OF(FrameList->Frames); i++) {
  123. FrameList->Frames[i].Frame.Previous = NULL;
  124. FrameList->Frames[i].Frame.ActivationContext = NULL;
  125. FrameList->Frames[i].Frame.Flags = RTL_ACTIVATION_CONTEXT_STACK_FRAME_FLAG_ON_FREE_LIST | RTL_ACTIVATION_CONTEXT_STACK_FRAME_FLAG_HEAP_ALLOCATED;
  126. FrameList->Frames[i].Cookie = 0;
  127. }
  128. Frame = &FrameList->Frames[0];
  129. FrameList->FramesInUse = 1;
  130. FrameList->NotFramesInUse = ~FrameList->FramesInUse;
  131. InsertHeadList(&Teb->ActivationContextStack.FrameListCache, &FrameList->Links);
  132. }
  133. ASSERT((Frame != NULL) && (Frame->Frame.Flags & RTL_ACTIVATION_CONTEXT_STACK_FRAME_FLAG_ON_FREE_LIST));
  134. Frame->Frame.Flags = RTL_ACTIVATION_CONTEXT_STACK_FRAME_FLAG_HEAP_ALLOCATED;
  135. *FrameOut = Frame;
  136. Status = STATUS_SUCCESS;
  137. Exit:
  138. return Status;
  139. }
  140. VOID
  141. RtlpFreeActivationContextStackFrame(
  142. PRTL_HEAP_ALLOCATED_ACTIVATION_CONTEXT_STACK_FRAME Frame
  143. )
  144. {
  145. LIST_ENTRY *ple = NULL;
  146. EXCEPTION_RECORD ExceptionRecord;
  147. PTEB Teb = NtCurrentTeb();
  148. ASSERT(Frame != NULL);
  149. if (Frame != NULL) {
  150. // If this assert fires, someone's trying to free an already freed frame. Or someone's set the
  151. // "I'm on the free list" flag in the frame data.
  152. ASSERT(!(Frame->Frame.Flags & RTL_ACTIVATION_CONTEXT_STACK_FRAME_FLAG_ON_FREE_LIST));
  153. if (!(Frame->Frame.Flags & RTL_ACTIVATION_CONTEXT_STACK_FRAME_FLAG_ON_FREE_LIST)) {
  154. for (ple = Teb->ActivationContextStack.FrameListCache.Flink; ple != &Teb->ActivationContextStack.FrameListCache; ple = ple->Flink) {
  155. PACTIVATION_CONTEXT_STACK_FRAMELIST FrameList = CONTAINING_RECORD(ple, ACTIVATION_CONTEXT_STACK_FRAMELIST, Links);
  156. ASSERT(FrameList->Magic == ACTIVATION_CONTEXT_STACK_FRAMELIST_MAGIC);
  157. if (FrameList->Magic != ACTIVATION_CONTEXT_STACK_FRAMELIST_MAGIC) {
  158. ExceptionRecord.ExceptionRecord = NULL;
  159. ExceptionRecord.NumberParameters = 4;
  160. ExceptionRecord.ExceptionInformation[0] = SXS_CORRUPTION_CODE_FRAMELIST;
  161. ExceptionRecord.ExceptionInformation[1] = SXS_CORRUPTION_CODE_FRAMELIST_SUBCODE_BAD_MAGIC;
  162. ExceptionRecord.ExceptionInformation[2] = (ULONG_PTR) &Teb->ActivationContextStack.FrameListCache;
  163. ExceptionRecord.ExceptionInformation[3] = (ULONG_PTR) FrameList;
  164. ExceptionRecord.ExceptionCode = STATUS_SXS_CORRUPTION;
  165. ExceptionRecord.ExceptionFlags = EXCEPTION_NONCONTINUABLE;
  166. RtlRaiseException(&ExceptionRecord);
  167. }
  168. ASSERT(FrameList->NotFramesInUse == (ULONG) (~FrameList->FramesInUse));
  169. if (FrameList->NotFramesInUse != (ULONG) (~FrameList->FramesInUse)) {
  170. ExceptionRecord.ExceptionRecord = NULL;
  171. ExceptionRecord.NumberParameters = 4;
  172. ExceptionRecord.ExceptionInformation[0] = SXS_CORRUPTION_CODE_FRAMELIST;
  173. ExceptionRecord.ExceptionInformation[1] = SXS_CORRUPTION_CODE_FRAMELIST_SUBCODE_BAD_INUSECOUNT;
  174. ExceptionRecord.ExceptionInformation[2] = (ULONG_PTR) &Teb->ActivationContextStack.FrameListCache;
  175. ExceptionRecord.ExceptionInformation[3] = (ULONG_PTR) FrameList;
  176. ExceptionRecord.ExceptionCode = STATUS_SXS_CORRUPTION;
  177. ExceptionRecord.ExceptionFlags = EXCEPTION_NONCONTINUABLE;
  178. RtlRaiseException(&ExceptionRecord);
  179. }
  180. if ((Frame >= &FrameList->Frames[0]) &&
  181. (Frame < &FrameList->Frames[RTL_NUMBER_OF(FrameList->Frames)])) {
  182. // It's in this frame list; look for it!
  183. ULONG i = (ULONG)(Frame - FrameList->Frames);
  184. // If this assert fires, it means that the frame pointer passed in should have been a frame
  185. // in this framelist, but it actually didn't point to any of the array entries exactly.
  186. // Probably someone munged the pointer.
  187. ASSERT(Frame == &FrameList->Frames[i]);
  188. if ((Frame == &FrameList->Frames[i]) && (FrameList->FramesInUse > 0)) {
  189. FrameList->FramesInUse--;
  190. FrameList->NotFramesInUse = ~FrameList->FramesInUse;
  191. Frame->Frame.Flags = RTL_ACTIVATION_CONTEXT_STACK_FRAME_FLAG_ON_FREE_LIST;
  192. // These are allocated in reverse order - the youngest
  193. // frames are at the head of the list, rather than the tail,
  194. // to speed up activation/deactivation. So, we have to walk from the
  195. // current framelist toward the front of the list, freeing entries
  196. // as necessary.
  197. if (FrameList->FramesInUse == 0) {
  198. // Keep an extra framelist allocated to avoid heap allocation thrashing. Be good and check
  199. // that the framelists don't have entries in use.
  200. LIST_ENTRY *ple2 = ple->Blink;
  201. while (ple2 != &Teb->ActivationContextStack.FrameListCache) {
  202. PACTIVATION_CONTEXT_STACK_FRAMELIST FrameList2 = CONTAINING_RECORD(ple2, ACTIVATION_CONTEXT_STACK_FRAMELIST, Links);
  203. LIST_ENTRY *ple2_Blink = ple2->Blink;
  204. ASSERT(FrameList->Magic == ACTIVATION_CONTEXT_STACK_FRAMELIST_MAGIC);
  205. ASSERT(FrameList->NotFramesInUse == (ULONG) (~FrameList->FramesInUse));
  206. // This assert is saying that the in-use count for a framelist after the current one is not
  207. // zero. This shouldn't be able to happen; there should be at most 1 framelist after the
  208. // current one and it should have no entries in use. Probably this indicates heap
  209. // corruption.
  210. ASSERT(FrameList2->FramesInUse == 0);
  211. if (FrameList2->FramesInUse == 0) {
  212. RemoveEntryList(ple2);
  213. RtlFreeHeap(RtlProcessHeap(), 0, FrameList2);
  214. }
  215. ple2 = ple2_Blink;
  216. }
  217. }
  218. }
  219. // No sense continuing the search on the list; we've found the one.
  220. break;
  221. }
  222. }
  223. // If we ran off the end of the list, it must have been a bogus frame pointer.
  224. ASSERT(ple != &Teb->ActivationContextStack.FrameListCache);
  225. }
  226. }
  227. }
  228. #if !defined(INVALID_HANDLE_VALUE)
  229. #define INVALID_HANDLE_VALUE ((HANDLE)(LONG_PTR)-1)
  230. #endif // !defined(INVALID_HANDLE_VALUE)
  231. //
  232. // Define magic cookie values returned by RtlActivateActivationContext*() that
  233. // represent a failure to activate the requested context. The notable thing
  234. // is that on deactivation via the cookie, we need to know whether to leave
  235. // querying disabled or whether to enable it, thus the two magic values.
  236. //
  237. // The top nibble of the cookie denotes its type: normal, default-pushed or failed
  238. #define ACTIVATION_CONTEXT_ACTIVATION_COOKIE_TYPE_NORMAL (1)
  239. #define ACTIVATION_CONTEXT_ACTIVATION_COOKIE_TYPE_DUPLICATE_ACTIVATION (2)
  240. #define ULONG_PTR_IZE(_x) ((ULONG_PTR) (_x))
  241. #define ULONG_PTR_IZE_SHIFT_AND_MASK(_x, _shift, _mask) ((ULONG_PTR) ((ULONG_PTR_IZE((_x)) & (_mask)) << (_shift)))
  242. //
  243. // We only use the lower 12 bits of the thread id, but that should be unique enough;
  244. // this is really for debugging aids; if your tests pass such that you're
  245. // erroneously passing activation context cookies between threads that happen to
  246. // match up in their lower 12 bits of their thread id, you're pretty darned
  247. // lucky.
  248. //
  249. #define CHAR_BITS 8
  250. #define BIT_LENGTH(x) (sizeof(x) * CHAR_BITS)
  251. #define ACTIVATION_CONTEXT_ACTIVATION_COOKIE_TYPE_BIT_LENGTH (4)
  252. #define ACTIVATION_CONTEXT_ACTIVATION_COOKIE_TYPE_BIT_OFFSET (BIT_LENGTH(PVOID) - ACTIVATION_CONTEXT_ACTIVATION_COOKIE_TYPE_BIT_LENGTH)
  253. #define ACTIVATION_CONTEXT_ACTIVATION_COOKIE_TYPE_BIT_MASK ((1 << ACTIVATION_CONTEXT_ACTIVATION_COOKIE_TYPE_BIT_LENGTH) - 1)
  254. #define ACTIVATION_CONTEXT_ACTIVATION_COOKIE_TID_BIT_LENGTH ((BIT_LENGTH(PVOID) / 2) - ACTIVATION_CONTEXT_ACTIVATION_COOKIE_TYPE_BIT_LENGTH)
  255. #define ACTIVATION_CONTEXT_ACTIVATION_COOKIE_TID_BIT_OFFSET (ACTIVATION_CONTEXT_ACTIVATION_COOKIE_TYPE_BIT_OFFSET - ACTIVATION_CONTEXT_ACTIVATION_COOKIE_TID_BIT_LENGTH)
  256. #define ACTIVATION_CONTEXT_ACTIVATION_COOKIE_TID_BIT_MASK ((1 << ACTIVATION_CONTEXT_ACTIVATION_COOKIE_TID_BIT_LENGTH) - 1)
  257. #define ACTIVATION_CONTEXT_ACTIVATION_COOKIE_CODE_BIT_LENGTH (BIT_LENGTH(PVOID) - (ACTIVATION_CONTEXT_ACTIVATION_COOKIE_TYPE_BIT_LENGTH + ACTIVATION_CONTEXT_ACTIVATION_COOKIE_TID_BIT_LENGTH))
  258. #define ACTIVATION_CONTEXT_ACTIVATION_COOKIE_CODE_BIT_OFFSET (0)
  259. #define ACTIVATION_CONTEXT_ACTIVATION_COOKIE_CODE_BIT_MASK ((1 << ACTIVATION_CONTEXT_ACTIVATION_COOKIE_CODE_BIT_LENGTH) - 1)
  260. // Never try to use more than 32 bits for the TID field.
  261. C_ASSERT(ACTIVATION_CONTEXT_ACTIVATION_COOKIE_TID_BIT_LENGTH <= BIT_LENGTH(ULONG));
  262. #define MAKE_ACTIVATION_CONTEXT_ACTIVATION_COOKIE(_type, _teb, _code) \
  263. ((ULONG_PTR) ( \
  264. ULONG_PTR_IZE_SHIFT_AND_MASK((_type), ACTIVATION_CONTEXT_ACTIVATION_COOKIE_TYPE_BIT_OFFSET, ACTIVATION_CONTEXT_ACTIVATION_COOKIE_TYPE_BIT_MASK) | \
  265. ULONG_PTR_IZE_SHIFT_AND_MASK((HandleToUlong((_teb)->ClientId.UniqueThread)), ACTIVATION_CONTEXT_ACTIVATION_COOKIE_TID_BIT_OFFSET, ACTIVATION_CONTEXT_ACTIVATION_COOKIE_TID_BIT_MASK) | \
  266. ULONG_PTR_IZE_SHIFT_AND_MASK((_code), ACTIVATION_CONTEXT_ACTIVATION_COOKIE_CODE_BIT_OFFSET, ACTIVATION_CONTEXT_ACTIVATION_COOKIE_CODE_BIT_MASK)))
  267. #define EXTRACT_ACTIVATION_CONTEXT_ACTIVATION_COOKIE_FIELD(_x, _fieldname) (ULONG_PTR_IZE((ULONG_PTR_IZE((_x)) >> ACTIVATION_CONTEXT_ACTIVATION_COOKIE_ ## _fieldname ## _BIT_OFFSET)) & ACTIVATION_CONTEXT_ACTIVATION_COOKIE_ ## _fieldname ## _BIT_MASK)
  268. #define EXTRACT_ACTIVATION_CONTEXT_ACTIVATION_COOKIE_TYPE(_x) EXTRACT_ACTIVATION_CONTEXT_ACTIVATION_COOKIE_FIELD((_x), TYPE)
  269. #define EXTRACT_ACTIVATION_CONTEXT_ACTIVATION_COOKIE_TID(_x) EXTRACT_ACTIVATION_CONTEXT_ACTIVATION_COOKIE_FIELD((_x), TID)
  270. #define EXTRACT_ACTIVATION_CONTEXT_ACTIVATION_COOKIE_CODE(_x) EXTRACT_ACTIVATION_CONTEXT_ACTIVATION_COOKIE_FIELD((_x), CODE)
  271. #define ACTIVATION_CONTEXT_TRUNCATED_TID_(_teb) (HandleToUlong((_teb)->ClientId.UniqueThread) & ACTIVATION_CONTEXT_ACTIVATION_COOKIE_TID_BIT_MASK)
  272. #define ACTIVATION_CONTEXT_TRUNCATED_TID() ACTIVATION_CONTEXT_TRUNCATED_TID_(NtCurrentTeb())
  273. PACTIVATION_CONTEXT
  274. RtlpMapSpecialValuesToBuiltInActivationContexts(
  275. PACTIVATION_CONTEXT ActivationContext
  276. )
  277. {
  278. if (ActivationContext == ACTCTX_EMPTY) {
  279. ActivationContext = const_cast<PACTIVATION_CONTEXT>(&RtlpTheEmptyActivationContext);
  280. }
  281. return ActivationContext;
  282. }
  283. // Disable FPO optimization so that captured call stacks are more complete
  284. #if defined(_X86_)
  285. #pragma optimize( "y", off ) // disable FPO for consistent stack traces
  286. #endif
  287. NTSTATUS
  288. NTAPI
  289. RtlActivateActivationContext(
  290. ULONG Flags,
  291. PACTIVATION_CONTEXT ActivationContext,
  292. ULONG_PTR *CookieOut
  293. )
  294. {
  295. NTSTATUS Status = STATUS_INTERNAL_ERROR;
  296. ASSERT(Flags == 0);
  297. ASSERT(CookieOut != NULL);
  298. if (CookieOut != NULL)
  299. *CookieOut = INVALID_ACTIVATION_CONTEXT_ACTIVATION_COOKIE;
  300. if ((Flags != 0) || (CookieOut == NULL)) {
  301. Status = STATUS_INVALID_PARAMETER;
  302. goto Exit;
  303. }
  304. if (!NT_SUCCESS(Status = RtlActivateActivationContextEx(
  305. 0,
  306. NtCurrentTeb(),
  307. ActivationContext,
  308. CookieOut)))
  309. goto Exit;
  310. Status = STATUS_SUCCESS;
  311. Exit:
  312. return Status;
  313. }
  314. NTSTATUS
  315. NTAPI
  316. RtlActivateActivationContextEx(
  317. ULONG Flags,
  318. PTEB Teb,
  319. PACTIVATION_CONTEXT ActivationContext,
  320. ULONG_PTR *Cookie
  321. )
  322. {
  323. #if NT_SXS_PERF_COUNTERS_ENABLED
  324. ULONGLONG InitialCycleCount = RtlpGetCycleCount();
  325. #endif
  326. NTSTATUS Status = STATUS_SUCCESS;
  327. ULONG_PTR NewCookie = INVALID_ACTIVATION_CONTEXT_ACTIVATION_COOKIE;
  328. PRTL_HEAP_ALLOCATED_ACTIVATION_CONTEXT_STACK_FRAME Frame;
  329. ULONG CapturedFrameCount, CapturedFrameHash;
  330. ASSERT(Cookie != NULL);
  331. if (Cookie != NULL)
  332. *Cookie = INVALID_ACTIVATION_CONTEXT_ACTIVATION_COOKIE;
  333. ASSERT((Flags & ~(RTL_ACTIVATE_ACTIVATION_CONTEXT_EX_FLAG_RELEASE_ON_STACK_DEALLOCATION)) == 0);
  334. ASSERT(Teb != NULL);
  335. ASSERT(ActivationContext != INVALID_HANDLE_VALUE);
  336. ActivationContext = RtlpMapSpecialValuesToBuiltInActivationContexts(ActivationContext);
  337. if (((Flags & ~(RTL_ACTIVATE_ACTIVATION_CONTEXT_EX_FLAG_RELEASE_ON_STACK_DEALLOCATION)) != 0) ||
  338. (Teb == NULL) ||
  339. (ActivationContext == INVALID_HANDLE_VALUE) ||
  340. (Cookie == NULL)) {
  341. Status = STATUS_INVALID_PARAMETER;
  342. goto Exit;
  343. }
  344. Status = RtlpAllocateActivationContextStackFrame(0, Teb, &Frame);
  345. if (!NT_SUCCESS(Status))
  346. goto Exit;
  347. Frame->Frame.Flags = RTL_ACTIVATION_CONTEXT_STACK_FRAME_FLAG_HEAP_ALLOCATED | RTL_ACTIVATION_CONTEXT_STACK_FRAME_FLAG_ACTIVATED;
  348. if (Flags & RTL_ACTIVATE_ACTIVATION_CONTEXT_EX_FLAG_RELEASE_ON_STACK_DEALLOCATION) {
  349. Frame->Frame.Flags |= RTL_ACTIVATION_CONTEXT_STACK_FRAME_FLAG_NO_DEACTIVATE |
  350. RTL_ACTIVATION_CONTEXT_STACK_FRAME_FLAG_RELEASE_ON_DEACTIVATION;
  351. RtlAddRefActivationContext(ActivationContext);
  352. }
  353. if (RtlpCaptureActivationContextActivationStacks)
  354. CapturedFrameCount = RtlCaptureStackBackTrace(2, NUMBER_OF(Frame->ActivationStackBackTrace), Frame->ActivationStackBackTrace, &CapturedFrameHash);
  355. else
  356. CapturedFrameCount = 0;
  357. while (CapturedFrameCount < NUMBER_OF(Frame->ActivationStackBackTrace))
  358. Frame->ActivationStackBackTrace[CapturedFrameCount++] = NULL;
  359. Frame->Frame.Previous = Teb->ActivationContextStack.ActiveFrame;
  360. Frame->Frame.ActivationContext = ActivationContext;
  361. NewCookie = MAKE_ACTIVATION_CONTEXT_ACTIVATION_COOKIE(ACTIVATION_CONTEXT_ACTIVATION_COOKIE_TYPE_NORMAL, Teb, Teb->ActivationContextStack.NextCookieSequenceNumber);
  362. Teb->ActivationContextStack.NextCookieSequenceNumber++;
  363. Frame->Cookie = NewCookie;
  364. *Cookie = NewCookie;
  365. Teb->ActivationContextStack.ActiveFrame = &Frame->Frame;
  366. Status = STATUS_SUCCESS;
  367. Exit:
  368. #if NT_SXS_PERF_COUNTERS_ENABLED
  369. Teb->ActivationContextCounters.ActivationCycles += RtlpGetCycleCount() - InitialCycleCount;
  370. Teb->ActivationContextCounters.Activations++;
  371. #endif // NT_SXS_PERF_COUNTERS_ENABLED
  372. return Status;
  373. }
  374. #if defined(_X86_)
  375. #pragma optimize("", on)
  376. #endif
  377. VOID
  378. NTAPI
  379. RtlDeactivateActivationContext(
  380. ULONG Flags,
  381. ULONG_PTR Cookie
  382. )
  383. {
  384. #if NT_SXS_PERF_COUNTERS_ENABLED
  385. ULONGLONG InitialCycleCount = RtlpGetCycleCount();
  386. #endif // NT_SXS_PERF_COUNTERS_ENABLED
  387. PTEB Teb = NtCurrentTeb();
  388. PRTL_ACTIVATION_CONTEXT_STACK_FRAME Frame;
  389. PRTL_ACTIVATION_CONTEXT_STACK_FRAME UnwindEndFrame = NULL;
  390. PRTL_HEAP_ALLOCATED_ACTIVATION_CONTEXT_STACK_FRAME HeapFrame = NULL;
  391. if ((Flags & ~(RTL_DEACTIVATE_ACTIVATION_CONTEXT_FLAG_FORCE_EARLY_DEACTIVATION)) != 0) {
  392. DbgPrintEx(DPFLTR_SXS_ID, DPFLTR_ERROR_LEVEL, "SXS: %s() called with invalid flags 0x%08lx\n", __FUNCTION__, Flags);
  393. RtlRaiseStatus(STATUS_INVALID_PARAMETER);
  394. }
  395. // Fast exit
  396. if (Cookie == INVALID_ACTIVATION_CONTEXT_ACTIVATION_COOKIE)
  397. return;
  398. if (EXTRACT_ACTIVATION_CONTEXT_ACTIVATION_COOKIE_TYPE(Cookie) != ACTIVATION_CONTEXT_ACTIVATION_COOKIE_TYPE_NORMAL) {
  399. DbgPrintEx(DPFLTR_SXS_ID, DPFLTR_ERROR_LEVEL, "SXS: %s() called with invalid cookie type 0x%08I64x\n", __FUNCTION__, Cookie);
  400. RtlRaiseStatus(STATUS_INVALID_PARAMETER);
  401. }
  402. if (EXTRACT_ACTIVATION_CONTEXT_ACTIVATION_COOKIE_TID(Cookie) != ACTIVATION_CONTEXT_TRUNCATED_TID()) {
  403. DbgPrintEx(DPFLTR_SXS_ID, DPFLTR_ERROR_LEVEL, "SXS: %s() called with invalid cookie tid 0x%08I64x - should be %08lx\n", __FUNCTION__, Cookie, ACTIVATION_CONTEXT_TRUNCATED_TID());
  404. RtlRaiseStatus(STATUS_INVALID_PARAMETER);
  405. }
  406. Frame = Teb->ActivationContextStack.ActiveFrame;
  407. // Do the "downcast", but don't use HeapFrame unless the RTL_ACTIVATION_CONTEXT_STACK_FRAME_FLAG_HEAP_ALLOCATED
  408. // flag is set...
  409. if (Frame != NULL) {
  410. HeapFrame = (Frame->Flags & RTL_ACTIVATION_CONTEXT_STACK_FRAME_FLAG_HEAP_ALLOCATED) ? CONTAINING_RECORD(Frame, RTL_HEAP_ALLOCATED_ACTIVATION_CONTEXT_STACK_FRAME, Frame) : NULL;
  411. }
  412. RTL_SOFT_ASSERT((Frame != NULL) && (Frame->Flags & RTL_ACTIVATION_CONTEXT_STACK_FRAME_FLAG_HEAP_ALLOCATED) && (HeapFrame->Cookie == Cookie));
  413. if (Frame != NULL)
  414. {
  415. if (((Frame->Flags & RTL_ACTIVATION_CONTEXT_STACK_FRAME_FLAG_HEAP_ALLOCATED) == 0) ||
  416. (HeapFrame->Cookie != Cookie))
  417. {
  418. ULONG InterveningFrameCount = 0;
  419. // The cookie wasn't current. Let's see if we can figure out what frame it was for...
  420. PRTL_ACTIVATION_CONTEXT_STACK_FRAME CandidateFrame = Frame->Previous;
  421. PRTL_HEAP_ALLOCATED_ACTIVATION_CONTEXT_STACK_FRAME CandidateHeapFrame =
  422. (CandidateFrame != NULL) ?
  423. (CandidateFrame->Flags & RTL_ACTIVATION_CONTEXT_STACK_FRAME_FLAG_HEAP_ALLOCATED) ?
  424. CONTAINING_RECORD(CandidateFrame, RTL_HEAP_ALLOCATED_ACTIVATION_CONTEXT_STACK_FRAME, Frame) :
  425. NULL :
  426. NULL;
  427. while ((CandidateFrame != NULL) &&
  428. ((CandidateHeapFrame == NULL) ||
  429. (CandidateHeapFrame->Cookie != Cookie))) {
  430. InterveningFrameCount++;
  431. CandidateFrame = CandidateFrame->Previous;
  432. CandidateHeapFrame =
  433. (CandidateFrame != NULL) ?
  434. (CandidateFrame->Flags & RTL_ACTIVATION_CONTEXT_STACK_FRAME_FLAG_HEAP_ALLOCATED) ?
  435. CONTAINING_RECORD(CandidateFrame, RTL_HEAP_ALLOCATED_ACTIVATION_CONTEXT_STACK_FRAME, Frame) :
  436. NULL :
  437. NULL;
  438. }
  439. RTL_SOFT_ASSERT(CandidateFrame != NULL);
  440. if (CandidateFrame == NULL) {
  441. RtlRaiseStatus(STATUS_SXS_INVALID_DEACTIVATION);
  442. } else {
  443. // Otherwise someone left some dirt around.
  444. EXCEPTION_RECORD ExceptionRecord;
  445. ExceptionRecord.ExceptionRecord = NULL;
  446. ExceptionRecord.NumberParameters = 3;
  447. ExceptionRecord.ExceptionInformation[0] = InterveningFrameCount;
  448. ExceptionRecord.ExceptionInformation[1] = (ULONG_PTR) CandidateFrame;
  449. ExceptionRecord.ExceptionInformation[2] = (ULONG_PTR) Teb->ActivationContextStack.ActiveFrame;
  450. ExceptionRecord.ExceptionCode = STATUS_SXS_EARLY_DEACTIVATION;
  451. ExceptionRecord.ExceptionFlags = 0; // this exception *is* continuable since we can actually put the activation stack into a reasonable state
  452. RtlRaiseException(&ExceptionRecord);
  453. // If they continue the exception, just do the unwinds.
  454. UnwindEndFrame = CandidateFrame->Previous;
  455. }
  456. } else {
  457. UnwindEndFrame = Frame->Previous;
  458. }
  459. do {
  460. PRTL_ACTIVATION_CONTEXT_STACK_FRAME Previous = Frame->Previous;
  461. // This is a weird one. A no-deactivate frame is typically only used to propogate
  462. // active activation context state to a newly created thread. As such, it'll always
  463. // be the topmost frame... thus how did we come to decide to deactivate it?
  464. ASSERTMSG(
  465. "Unwinding through a no-deactivate frame",
  466. !(Frame->Flags & RTL_ACTIVATION_CONTEXT_STACK_FRAME_FLAG_NO_DEACTIVATE));
  467. if (Frame->Flags & RTL_ACTIVATION_CONTEXT_STACK_FRAME_FLAG_RELEASE_ON_DEACTIVATION) {
  468. RtlReleaseActivationContext(Frame->ActivationContext);
  469. }
  470. if (Frame->Flags & RTL_ACTIVATION_CONTEXT_STACK_FRAME_FLAG_HEAP_ALLOCATED) {
  471. RtlpFreeActivationContextStackFrame(CONTAINING_RECORD(Frame, RTL_HEAP_ALLOCATED_ACTIVATION_CONTEXT_STACK_FRAME, Frame));
  472. }
  473. Frame = Previous;
  474. } while (Frame != UnwindEndFrame);
  475. Teb->ActivationContextStack.ActiveFrame = UnwindEndFrame;
  476. }
  477. #if NT_SXS_PERF_COUNTERS_ENABLED
  478. Teb->ActivationContextCounters.DeactivationCycles += RtlpGetCycleCount() - InitialCycleCount;
  479. Teb->ActivationContextCounters.Deactivations++;
  480. #endif
  481. }
  482. VOID
  483. FASTCALL
  484. RtlActivateActivationContextUnsafeFast(
  485. PRTL_CALLER_ALLOCATED_ACTIVATION_CONTEXT_STACK_FRAME Frame,
  486. PACTIVATION_CONTEXT ActivationContext
  487. )
  488. {
  489. const PRTL_ACTIVATION_CONTEXT_STACK_FRAME ActiveFrame = (PRTL_ACTIVATION_CONTEXT_STACK_FRAME) NtCurrentTeb()->ActivationContextStack.ActiveFrame;
  490. EXCEPTION_RECORD ExceptionRecord;
  491. ASSERT(Frame->Format == RTL_CALLER_ALLOCATED_ACTIVATION_CONTEXT_STACK_FRAME_FORMAT_WHISTLER);
  492. ASSERT(Frame->Size >= sizeof(RTL_CALLER_ALLOCATED_ACTIVATION_CONTEXT_STACK_FRAME_BASIC));
  493. if (Frame->Size >= sizeof(RTL_CALLER_ALLOCATED_ACTIVATION_CONTEXT_STACK_FRAME_EXTENDED))
  494. {
  495. Frame->Extra1 = (PVOID) (~((ULONG_PTR) ActiveFrame));
  496. Frame->Extra2 = (PVOID) (~((ULONG_PTR) ActivationContext));
  497. Frame->Extra3 = _ReturnAddress();
  498. }
  499. if (ActiveFrame != NULL) {
  500. ASSERT(
  501. (ActiveFrame->Flags &
  502. (RTL_ACTIVATION_CONTEXT_STACK_FRAME_FLAG_ACTIVATED |
  503. RTL_ACTIVATION_CONTEXT_STACK_FRAME_FLAG_DEACTIVATED |
  504. RTL_ACTIVATION_CONTEXT_STACK_FRAME_FLAG_NOT_REALLY_ACTIVATED)) == RTL_ACTIVATION_CONTEXT_STACK_FRAME_FLAG_ACTIVATED);
  505. if (
  506. ((ActiveFrame->Flags &
  507. (RTL_ACTIVATION_CONTEXT_STACK_FRAME_FLAG_ACTIVATED |
  508. RTL_ACTIVATION_CONTEXT_STACK_FRAME_FLAG_DEACTIVATED |
  509. RTL_ACTIVATION_CONTEXT_STACK_FRAME_FLAG_NOT_REALLY_ACTIVATED)) != RTL_ACTIVATION_CONTEXT_STACK_FRAME_FLAG_ACTIVATED)) {
  510. ExceptionRecord.ExceptionRecord = NULL;
  511. ExceptionRecord.NumberParameters = 4;
  512. ExceptionRecord.ExceptionInformation[0] = (ULONG_PTR) &NtCurrentTeb()->ActivationContextStack;
  513. ExceptionRecord.ExceptionInformation[1] = (ULONG_PTR) ActiveFrame;
  514. ExceptionRecord.ExceptionInformation[2] = (ULONG_PTR) ActiveFrame;
  515. ExceptionRecord.ExceptionInformation[3] = ActiveFrame->Flags;
  516. ExceptionRecord.ExceptionCode = STATUS_SXS_CORRUPT_ACTIVATION_STACK;
  517. ExceptionRecord.ExceptionFlags = EXCEPTION_NONCONTINUABLE;
  518. RtlRaiseException(&ExceptionRecord);
  519. return; // shouldn't be able to happen with EXCEPTION_NONCONTINUABLE set
  520. }
  521. if ((ActiveFrame->Flags & RTL_ACTIVATION_CONTEXT_STACK_FRAME_FLAG_HEAP_ALLOCATED) == 0) {
  522. PRTL_CALLER_ALLOCATED_ACTIVATION_CONTEXT_STACK_FRAME ActiveFastFrame = CONTAINING_RECORD(ActiveFrame, RTL_CALLER_ALLOCATED_ACTIVATION_CONTEXT_STACK_FRAME, Frame);
  523. ASSERT(ActiveFastFrame->Format == RTL_CALLER_ALLOCATED_ACTIVATION_CONTEXT_STACK_FRAME_FORMAT_WHISTLER);
  524. ASSERT(ActiveFastFrame->Size >= sizeof(RTL_CALLER_ALLOCATED_ACTIVATION_CONTEXT_STACK_FRAME_BASIC));
  525. if (ActiveFastFrame->Size >= sizeof(RTL_CALLER_ALLOCATED_ACTIVATION_CONTEXT_STACK_FRAME_EXTENDED)) {
  526. ASSERT(ActiveFastFrame->Extra1 == (PVOID) (~((ULONG_PTR) ActiveFrame->Previous)));
  527. ASSERT(ActiveFastFrame->Extra2 == (PVOID) (~((ULONG_PTR) ActiveFrame->ActivationContext)));
  528. }
  529. }
  530. }
  531. Frame->Frame.Previous = NtCurrentTeb()->ActivationContextStack.ActiveFrame;
  532. Frame->Frame.ActivationContext = ActivationContext;
  533. Frame->Frame.Flags = RTL_ACTIVATION_CONTEXT_STACK_FRAME_FLAG_ACTIVATED;
  534. if ((((ActiveFrame == NULL) && (ActivationContext == NULL)) ||
  535. ((ActiveFrame != NULL) && (ActiveFrame->ActivationContext == ActivationContext))) &&
  536. !RtlpNotAllowingMultipleActivation)
  537. {
  538. Frame->Frame.Flags |= RTL_ACTIVATION_CONTEXT_STACK_FRAME_FLAG_NOT_REALLY_ACTIVATED;
  539. }
  540. else
  541. {
  542. NtCurrentTeb()->ActivationContextStack.ActiveFrame = &Frame->Frame;
  543. }
  544. }
  545. VOID
  546. FASTCALL
  547. RtlDeactivateActivationContextUnsafeFast(
  548. PRTL_CALLER_ALLOCATED_ACTIVATION_CONTEXT_STACK_FRAME Frame
  549. )
  550. {
  551. EXCEPTION_RECORD ExceptionRecord;
  552. const PRTL_ACTIVATION_CONTEXT_STACK_FRAME ActiveFrame = NtCurrentTeb()->ActivationContextStack.ActiveFrame;
  553. ASSERT(Frame->Format == RTL_CALLER_ALLOCATED_ACTIVATION_CONTEXT_STACK_FRAME_FORMAT_WHISTLER);
  554. ASSERT(Frame->Size >= sizeof(RTL_CALLER_ALLOCATED_ACTIVATION_CONTEXT_STACK_FRAME_BASIC));
  555. ASSERT((Frame->Frame.Flags & RTL_ACTIVATION_CONTEXT_STACK_FRAME_FLAG_DEACTIVATED) == 0);
  556. if (Frame->Frame.Flags & RTL_ACTIVATION_CONTEXT_STACK_FRAME_FLAG_DEACTIVATED)
  557. {
  558. ExceptionRecord.ExceptionRecord = NULL;
  559. ExceptionRecord.NumberParameters = 3;
  560. ExceptionRecord.ExceptionInformation[0] = 0;
  561. ExceptionRecord.ExceptionInformation[1] = (ULONG_PTR) &Frame->Frame;
  562. ExceptionRecord.ExceptionInformation[2] = (ULONG_PTR) NtCurrentTeb()->ActivationContextStack.ActiveFrame;
  563. ExceptionRecord.ExceptionCode = STATUS_SXS_MULTIPLE_DEACTIVATION;
  564. ExceptionRecord.ExceptionFlags = 0;
  565. RtlRaiseException(&ExceptionRecord);
  566. return; // in case someone is cute and continues the exception
  567. }
  568. ASSERT(Frame->Frame.Flags & RTL_ACTIVATION_CONTEXT_STACK_FRAME_FLAG_ACTIVATED);
  569. if ((Frame->Frame.Flags & RTL_ACTIVATION_CONTEXT_STACK_FRAME_FLAG_ACTIVATED) == 0)
  570. {
  571. ExceptionRecord.ExceptionRecord = NULL;
  572. ExceptionRecord.NumberParameters = 3;
  573. ExceptionRecord.ExceptionInformation[0] = 0;
  574. ExceptionRecord.ExceptionInformation[1] = (ULONG_PTR) &Frame->Frame;
  575. ExceptionRecord.ExceptionInformation[2] = (ULONG_PTR) NtCurrentTeb()->ActivationContextStack.ActiveFrame;
  576. ExceptionRecord.ExceptionCode = STATUS_SXS_INVALID_DEACTIVATION;
  577. ExceptionRecord.ExceptionFlags = EXCEPTION_NONCONTINUABLE; // this exception is NOT continuable
  578. RtlRaiseException(&ExceptionRecord);
  579. return; // in case someone is cute and continues the exception
  580. }
  581. ASSERT(
  582. (Frame->Frame.Flags &
  583. (RTL_ACTIVATION_CONTEXT_STACK_FRAME_FLAG_ACTIVATED |
  584. RTL_ACTIVATION_CONTEXT_STACK_FRAME_FLAG_DEACTIVATED)) == RTL_ACTIVATION_CONTEXT_STACK_FRAME_FLAG_ACTIVATED);
  585. if (
  586. ((Frame->Frame.Flags &
  587. (RTL_ACTIVATION_CONTEXT_STACK_FRAME_FLAG_ACTIVATED |
  588. RTL_ACTIVATION_CONTEXT_STACK_FRAME_FLAG_DEACTIVATED)) != RTL_ACTIVATION_CONTEXT_STACK_FRAME_FLAG_ACTIVATED)) {
  589. ExceptionRecord.ExceptionRecord = NULL;
  590. ExceptionRecord.NumberParameters = 4;
  591. ExceptionRecord.ExceptionInformation[0] = (ULONG_PTR) &NtCurrentTeb()->ActivationContextStack;
  592. ExceptionRecord.ExceptionInformation[1] = (ULONG_PTR) ActiveFrame;
  593. ExceptionRecord.ExceptionInformation[2] = (ULONG_PTR) &Frame->Frame;
  594. ExceptionRecord.ExceptionInformation[3] = Frame->Frame.Flags;
  595. ExceptionRecord.ExceptionCode = STATUS_SXS_CORRUPT_ACTIVATION_STACK;
  596. ExceptionRecord.ExceptionFlags = EXCEPTION_NONCONTINUABLE;
  597. RtlRaiseException(&ExceptionRecord);
  598. return; // shouldn't be able to happen with EXCEPTION_NONCONTINUABLE set
  599. }
  600. if (Frame->Size >= sizeof(RTL_CALLER_ALLOCATED_ACTIVATION_CONTEXT_STACK_FRAME_EXTENDED))
  601. {
  602. ASSERT(Frame->Extra1 == (PVOID) (~((ULONG_PTR) Frame->Frame.Previous)));
  603. ASSERT(Frame->Extra2 == (PVOID) (~((ULONG_PTR) Frame->Frame.ActivationContext)));
  604. if ((Frame->Extra1 != (PVOID) (~((ULONG_PTR) Frame->Frame.Previous))) ||
  605. (Frame->Extra2 != (PVOID) (~((ULONG_PTR) Frame->Frame.ActivationContext)))) {
  606. ExceptionRecord.ExceptionRecord = NULL;
  607. ExceptionRecord.NumberParameters = 4;
  608. ExceptionRecord.ExceptionInformation[0] = (ULONG_PTR) &NtCurrentTeb()->ActivationContextStack;
  609. ExceptionRecord.ExceptionInformation[1] = (ULONG_PTR) ActiveFrame;
  610. ExceptionRecord.ExceptionInformation[2] = (ULONG_PTR) &Frame->Frame;
  611. ExceptionRecord.ExceptionInformation[3] = Frame->Frame.Flags;
  612. ExceptionRecord.ExceptionCode = STATUS_SXS_CORRUPT_ACTIVATION_STACK;
  613. ExceptionRecord.ExceptionFlags = EXCEPTION_NONCONTINUABLE;
  614. RtlRaiseException(&ExceptionRecord);
  615. return; // shouldn't be able to happen with EXCEPTION_NONCONTINUABLE set
  616. }
  617. }
  618. if (ActiveFrame != NULL) {
  619. ASSERT(
  620. (ActiveFrame->Flags &
  621. (RTL_ACTIVATION_CONTEXT_STACK_FRAME_FLAG_ACTIVATED |
  622. RTL_ACTIVATION_CONTEXT_STACK_FRAME_FLAG_DEACTIVATED |
  623. RTL_ACTIVATION_CONTEXT_STACK_FRAME_FLAG_NOT_REALLY_ACTIVATED)) == RTL_ACTIVATION_CONTEXT_STACK_FRAME_FLAG_ACTIVATED);
  624. if (
  625. ((ActiveFrame->Flags &
  626. (RTL_ACTIVATION_CONTEXT_STACK_FRAME_FLAG_ACTIVATED |
  627. RTL_ACTIVATION_CONTEXT_STACK_FRAME_FLAG_DEACTIVATED |
  628. RTL_ACTIVATION_CONTEXT_STACK_FRAME_FLAG_NOT_REALLY_ACTIVATED)) != RTL_ACTIVATION_CONTEXT_STACK_FRAME_FLAG_ACTIVATED)) {
  629. ExceptionRecord.ExceptionRecord = NULL;
  630. ExceptionRecord.NumberParameters = 4;
  631. ExceptionRecord.ExceptionInformation[0] = (ULONG_PTR) &NtCurrentTeb()->ActivationContextStack;
  632. ExceptionRecord.ExceptionInformation[1] = (ULONG_PTR) ActiveFrame;
  633. ExceptionRecord.ExceptionInformation[2] = (ULONG_PTR) ActiveFrame;
  634. ExceptionRecord.ExceptionInformation[3] = ActiveFrame->Flags;
  635. ExceptionRecord.ExceptionCode = STATUS_SXS_CORRUPT_ACTIVATION_STACK;
  636. ExceptionRecord.ExceptionFlags = EXCEPTION_NONCONTINUABLE;
  637. RtlRaiseException(&ExceptionRecord);
  638. return; // shouldn't be able to happen with EXCEPTION_NONCONTINUABLE set
  639. }
  640. if ((ActiveFrame->Flags & RTL_ACTIVATION_CONTEXT_STACK_FRAME_FLAG_HEAP_ALLOCATED) == 0) {
  641. PRTL_CALLER_ALLOCATED_ACTIVATION_CONTEXT_STACK_FRAME ActiveFastFrame = CONTAINING_RECORD(ActiveFrame, RTL_CALLER_ALLOCATED_ACTIVATION_CONTEXT_STACK_FRAME, Frame);
  642. ASSERT(ActiveFastFrame->Format == RTL_CALLER_ALLOCATED_ACTIVATION_CONTEXT_STACK_FRAME_FORMAT_WHISTLER);
  643. ASSERT(ActiveFastFrame->Size >= sizeof(RTL_CALLER_ALLOCATED_ACTIVATION_CONTEXT_STACK_FRAME_BASIC));
  644. if (ActiveFastFrame->Size >= sizeof(RTL_CALLER_ALLOCATED_ACTIVATION_CONTEXT_STACK_FRAME_EXTENDED)) {
  645. ASSERT(ActiveFastFrame->Extra1 == (PVOID) (~((ULONG_PTR) ActiveFrame->Previous)));
  646. ASSERT(ActiveFastFrame->Extra2 == (PVOID) (~((ULONG_PTR) ActiveFrame->ActivationContext)));
  647. if ((ActiveFastFrame->Extra1 != (PVOID) (~((ULONG_PTR) ActiveFrame->Previous))) ||
  648. (ActiveFastFrame->Extra2 != (PVOID) (~((ULONG_PTR) ActiveFrame->ActivationContext)))) {
  649. ExceptionRecord.ExceptionRecord = NULL;
  650. ExceptionRecord.NumberParameters = 4;
  651. ExceptionRecord.ExceptionInformation[0] = (ULONG_PTR) &NtCurrentTeb()->ActivationContextStack;
  652. ExceptionRecord.ExceptionInformation[1] = (ULONG_PTR) ActiveFrame;
  653. ExceptionRecord.ExceptionInformation[2] = (ULONG_PTR) ActiveFrame;
  654. ExceptionRecord.ExceptionInformation[3] = ActiveFrame->Flags;
  655. ExceptionRecord.ExceptionCode = STATUS_SXS_CORRUPT_ACTIVATION_STACK;
  656. ExceptionRecord.ExceptionFlags = EXCEPTION_NONCONTINUABLE;
  657. RtlRaiseException(&ExceptionRecord);
  658. return; // shouldn't be able to happen with EXCEPTION_NONCONTINUABLE set
  659. }
  660. }
  661. }
  662. }
  663. //
  664. // Was this "not really activated" above (AppCompat problem) from above?
  665. //
  666. if (Frame->Frame.Flags & RTL_ACTIVATION_CONTEXT_STACK_FRAME_FLAG_NOT_REALLY_ACTIVATED)
  667. {
  668. // Nothing special to do
  669. }
  670. else
  671. {
  672. // Make sure that the deactivation matches. If it does not (the exceptional
  673. // condition) we'll throw an exception to make people deal with their
  674. // coding errors.
  675. if (NtCurrentTeb()->ActivationContextStack.ActiveFrame != &Frame->Frame)
  676. {
  677. ULONG InterveningFrameCount = 0;
  678. // What's the deal? Look to see if we're further up the stack.
  679. // Actually, what we'll do is see if we can find our parent up the stack.
  680. // This will also handle the double-deactivation case and let us continue
  681. // nicely.
  682. PRTL_ACTIVATION_CONTEXT_STACK_FRAME SearchFrame = NtCurrentTeb()->ActivationContextStack.ActiveFrame;
  683. const PRTL_ACTIVATION_CONTEXT_STACK_FRAME Previous = Frame->Frame.Previous;
  684. DbgPrintEx(
  685. DPFLTR_SXS_ID,
  686. DPFLTR_TRACE_LEVEL,
  687. "SXS: %s() Active frame is not the frame being deactivated %p != %p\n",
  688. __FUNCTION__,
  689. NtCurrentTeb()->ActivationContextStack.ActiveFrame,
  690. &Frame->Frame);
  691. while ((SearchFrame != NULL) && (SearchFrame != Previous)) {
  692. // Validate the stack frame while we're here...
  693. ASSERT(
  694. (SearchFrame->Flags &
  695. (RTL_ACTIVATION_CONTEXT_STACK_FRAME_FLAG_ACTIVATED |
  696. RTL_ACTIVATION_CONTEXT_STACK_FRAME_FLAG_DEACTIVATED |
  697. RTL_ACTIVATION_CONTEXT_STACK_FRAME_FLAG_NOT_REALLY_ACTIVATED)) == RTL_ACTIVATION_CONTEXT_STACK_FRAME_FLAG_ACTIVATED);
  698. if (
  699. ((SearchFrame->Flags &
  700. (RTL_ACTIVATION_CONTEXT_STACK_FRAME_FLAG_ACTIVATED |
  701. RTL_ACTIVATION_CONTEXT_STACK_FRAME_FLAG_DEACTIVATED |
  702. RTL_ACTIVATION_CONTEXT_STACK_FRAME_FLAG_NOT_REALLY_ACTIVATED)) != RTL_ACTIVATION_CONTEXT_STACK_FRAME_FLAG_ACTIVATED)) {
  703. ExceptionRecord.ExceptionRecord = NULL;
  704. ExceptionRecord.NumberParameters = 4;
  705. ExceptionRecord.ExceptionInformation[0] = (ULONG_PTR) &NtCurrentTeb()->ActivationContextStack;
  706. ExceptionRecord.ExceptionInformation[1] = (ULONG_PTR) SearchFrame;
  707. ExceptionRecord.ExceptionInformation[2] = (ULONG_PTR) &Frame->Frame;
  708. ExceptionRecord.ExceptionInformation[3] = SearchFrame->Flags;
  709. ExceptionRecord.ExceptionCode = STATUS_SXS_CORRUPT_ACTIVATION_STACK;
  710. ExceptionRecord.ExceptionFlags = EXCEPTION_NONCONTINUABLE;
  711. RtlRaiseException(&ExceptionRecord);
  712. return; // shouldn't be able to happen with EXCEPTION_NONCONTINUABLE set
  713. }
  714. if ((SearchFrame->Flags & RTL_ACTIVATION_CONTEXT_STACK_FRAME_FLAG_HEAP_ALLOCATED) == 0) {
  715. PRTL_CALLER_ALLOCATED_ACTIVATION_CONTEXT_STACK_FRAME FastSearchFrame =
  716. CONTAINING_RECORD(SearchFrame, RTL_CALLER_ALLOCATED_ACTIVATION_CONTEXT_STACK_FRAME, Frame);
  717. ASSERT(FastSearchFrame->Extra1 == (PVOID) (~((ULONG_PTR) SearchFrame->Previous)));
  718. ASSERT(FastSearchFrame->Extra2 == (PVOID) (~((ULONG_PTR) SearchFrame->ActivationContext)));
  719. if ((FastSearchFrame->Extra1 != (PVOID) (~((ULONG_PTR) SearchFrame->Previous))) ||
  720. (FastSearchFrame->Extra2 != (PVOID) (~((ULONG_PTR) SearchFrame->ActivationContext)))) {
  721. ExceptionRecord.ExceptionRecord = NULL;
  722. ExceptionRecord.NumberParameters = 4;
  723. ExceptionRecord.ExceptionInformation[0] = (ULONG_PTR) &NtCurrentTeb()->ActivationContextStack;
  724. ExceptionRecord.ExceptionInformation[1] = (ULONG_PTR) SearchFrame;
  725. ExceptionRecord.ExceptionInformation[2] = (ULONG_PTR) &Frame->Frame;
  726. ExceptionRecord.ExceptionInformation[3] = SearchFrame->Flags;
  727. ExceptionRecord.ExceptionCode = STATUS_SXS_CORRUPT_ACTIVATION_STACK;
  728. ExceptionRecord.ExceptionFlags = EXCEPTION_NONCONTINUABLE;
  729. RtlRaiseException(&ExceptionRecord);
  730. return; // shouldn't be able to happen with EXCEPTION_NONCONTINUABLE set
  731. }
  732. }
  733. InterveningFrameCount++;
  734. SearchFrame = SearchFrame->Previous;
  735. }
  736. ExceptionRecord.ExceptionRecord = NULL;
  737. ExceptionRecord.NumberParameters = 3;
  738. ExceptionRecord.ExceptionInformation[0] = InterveningFrameCount;
  739. ExceptionRecord.ExceptionInformation[1] = (ULONG_PTR) &Frame->Frame;
  740. ExceptionRecord.ExceptionInformation[2] = (ULONG_PTR) NtCurrentTeb()->ActivationContextStack.ActiveFrame;
  741. if (SearchFrame != NULL) {
  742. // We're there. That's actually good; it just probably means that a function that our caller called
  743. // activated an activation context and forgot to deactivate. Throw the exception and if it's continued,
  744. // we're good to go.
  745. if (InterveningFrameCount == 0) {
  746. // Wow, the frame-to-deactivate's previous is the active one. It must be that the caller
  747. // already deactivated and is now deactivating again.
  748. ExceptionRecord.ExceptionCode = STATUS_SXS_MULTIPLE_DEACTIVATION;
  749. } else {
  750. // Otherwise someone left some dirt around.
  751. ExceptionRecord.ExceptionCode = STATUS_SXS_EARLY_DEACTIVATION;
  752. }
  753. ExceptionRecord.ExceptionFlags = 0; // this exception *is* continuable since we can actually put the activation stack into a reasonable state
  754. } else {
  755. // It wasn't there. It's almost certainly the wrong thing to try to set this
  756. ExceptionRecord.ExceptionCode = STATUS_SXS_INVALID_DEACTIVATION;
  757. ExceptionRecord.ExceptionFlags = EXCEPTION_NONCONTINUABLE; // this exception is NOT continuable
  758. }
  759. RtlRaiseException(&ExceptionRecord);
  760. }
  761. NtCurrentTeb()->ActivationContextStack.ActiveFrame = Frame->Frame.Previous;
  762. }
  763. Frame->Frame.Flags |= RTL_ACTIVATION_CONTEXT_STACK_FRAME_FLAG_DEACTIVATED;
  764. if (Frame->Size >= sizeof(RTL_CALLER_ALLOCATED_ACTIVATION_CONTEXT_STACK_FRAME_EXTENDED))
  765. Frame->Extra4 = _ReturnAddress();
  766. }
  767. NTSTATUS
  768. NTAPI
  769. RtlGetActiveActivationContext(
  770. PACTIVATION_CONTEXT *ActivationContext
  771. )
  772. {
  773. PRTL_ACTIVATION_CONTEXT_STACK_FRAME Frame;
  774. EXCEPTION_RECORD ExceptionRecord;
  775. if (ActivationContext != NULL) {
  776. *ActivationContext = NULL;
  777. }
  778. else {
  779. return STATUS_INVALID_PARAMETER;
  780. }
  781. Frame = (PRTL_ACTIVATION_CONTEXT_STACK_FRAME) NtCurrentTeb()->ActivationContextStack.ActiveFrame;
  782. if (Frame != NULL) {
  783. ASSERT(
  784. (Frame->Flags & (RTL_ACTIVATION_CONTEXT_STACK_FRAME_FLAG_ACTIVATED | RTL_ACTIVATION_CONTEXT_STACK_FRAME_FLAG_DEACTIVATED | RTL_ACTIVATION_CONTEXT_STACK_FRAME_FLAG_NOT_REALLY_ACTIVATED)) ==
  785. RTL_ACTIVATION_CONTEXT_STACK_FRAME_FLAG_ACTIVATED);
  786. if ((Frame->Flags & (RTL_ACTIVATION_CONTEXT_STACK_FRAME_FLAG_ACTIVATED |
  787. RTL_ACTIVATION_CONTEXT_STACK_FRAME_FLAG_DEACTIVATED |
  788. RTL_ACTIVATION_CONTEXT_STACK_FRAME_FLAG_NOT_REALLY_ACTIVATED)) !=
  789. RTL_ACTIVATION_CONTEXT_STACK_FRAME_FLAG_ACTIVATED) {
  790. ExceptionRecord.ExceptionRecord = NULL;
  791. ExceptionRecord.NumberParameters = 4;
  792. ExceptionRecord.ExceptionInformation[0] = (ULONG_PTR) &NtCurrentTeb()->ActivationContextStack;
  793. ExceptionRecord.ExceptionInformation[1] = (ULONG_PTR) Frame;
  794. ExceptionRecord.ExceptionInformation[2] = (ULONG_PTR) Frame;
  795. ExceptionRecord.ExceptionInformation[3] = Frame->Flags;
  796. ExceptionRecord.ExceptionCode = STATUS_SXS_CORRUPT_ACTIVATION_STACK;
  797. ExceptionRecord.ExceptionFlags = EXCEPTION_NONCONTINUABLE;
  798. RtlRaiseException(&ExceptionRecord);
  799. return STATUS_INTERNAL_ERROR; // shouldn't be able to happen with EXCEPTION_NONCONTINUABLE set
  800. }
  801. if ((Frame->Flags & RTL_ACTIVATION_CONTEXT_STACK_FRAME_FLAG_HEAP_ALLOCATED) == 0) {
  802. PRTL_CALLER_ALLOCATED_ACTIVATION_CONTEXT_STACK_FRAME FastFrame = CONTAINING_RECORD(Frame, RTL_CALLER_ALLOCATED_ACTIVATION_CONTEXT_STACK_FRAME, Frame);
  803. ASSERT(FastFrame->Format == RTL_CALLER_ALLOCATED_ACTIVATION_CONTEXT_STACK_FRAME_FORMAT_WHISTLER);
  804. ASSERT(FastFrame->Size >= sizeof(RTL_CALLER_ALLOCATED_ACTIVATION_CONTEXT_STACK_FRAME_BASIC));
  805. if (FastFrame->Size >= sizeof(RTL_CALLER_ALLOCATED_ACTIVATION_CONTEXT_STACK_FRAME_EXTENDED)) {
  806. ASSERT(FastFrame->Extra1 == (PVOID) (~((ULONG_PTR) Frame->Previous)));
  807. ASSERT(FastFrame->Extra2 == (PVOID) (~((ULONG_PTR) Frame->ActivationContext)));
  808. if ((FastFrame->Extra1 != (PVOID) (~((ULONG_PTR) Frame->Previous))) ||
  809. (FastFrame->Extra2 != (PVOID) (~((ULONG_PTR) Frame->ActivationContext)))) {
  810. ExceptionRecord.ExceptionRecord = NULL;
  811. ExceptionRecord.NumberParameters = 4;
  812. ExceptionRecord.ExceptionInformation[0] = (ULONG_PTR) &NtCurrentTeb()->ActivationContextStack;
  813. ExceptionRecord.ExceptionInformation[1] = (ULONG_PTR) Frame;
  814. ExceptionRecord.ExceptionInformation[2] = (ULONG_PTR) Frame;
  815. ExceptionRecord.ExceptionInformation[3] = Frame->Flags;
  816. ExceptionRecord.ExceptionCode = STATUS_SXS_CORRUPT_ACTIVATION_STACK;
  817. ExceptionRecord.ExceptionFlags = EXCEPTION_NONCONTINUABLE;
  818. RtlRaiseException(&ExceptionRecord);
  819. return STATUS_INTERNAL_ERROR; // shouldn't be able to happen with EXCEPTION_NONCONTINUABLE set
  820. }
  821. }
  822. }
  823. RtlAddRefActivationContext(Frame->ActivationContext);
  824. *ActivationContext = Frame->ActivationContext;
  825. }
  826. return STATUS_SUCCESS;
  827. }
  828. VOID
  829. NTAPI
  830. RtlFreeThreadActivationContextStack(
  831. VOID
  832. )
  833. {
  834. PTEB Teb = NtCurrentTeb();
  835. PRTL_ACTIVATION_CONTEXT_STACK_FRAME Frame = Teb->ActivationContextStack.ActiveFrame;
  836. #if RTL_CATCH_PEOPLE_TWIDDLING_FRAMELISTS_OR_HEAP_CORRUPTION
  837. EXCEPTION_RECORD ExceptionRecord;
  838. #endif
  839. LIST_ENTRY *ple = NULL;
  840. while (Frame != NULL) {
  841. PRTL_ACTIVATION_CONTEXT_STACK_FRAME Previous = Frame->Previous;
  842. // Release any lingering frames. The notable case when this happens is when a thread that
  843. // has a non-default activation context active creates another thread which inherits the
  844. // first thread's activation context, adding a reference to the activation context. When
  845. // the new thread eventually dies, that initial frame is still active.
  846. if (Frame->Flags & RTL_ACTIVATION_CONTEXT_STACK_FRAME_FLAG_RELEASE_ON_DEACTIVATION) {
  847. RtlReleaseActivationContext(Frame->ActivationContext);
  848. }
  849. if (Frame->Flags & RTL_ACTIVATION_CONTEXT_STACK_FRAME_FLAG_HEAP_ALLOCATED) {
  850. RtlpFreeActivationContextStackFrame(CONTAINING_RECORD(Frame, RTL_HEAP_ALLOCATED_ACTIVATION_CONTEXT_STACK_FRAME, Frame));
  851. }
  852. Frame = Previous;
  853. }
  854. Teb->ActivationContextStack.ActiveFrame = NULL;
  855. // Spin through the frame list cache and free any items left over. There should be
  856. // only one, but who knows if the gc algorithm above will changes sometime.
  857. ple = Teb->ActivationContextStack.FrameListCache.Flink;
  858. while (ple != &Teb->ActivationContextStack.FrameListCache) {
  859. LIST_ENTRY *pleNext = ple->Flink;
  860. PACTIVATION_CONTEXT_STACK_FRAMELIST FrameList = CONTAINING_RECORD(ple, ACTIVATION_CONTEXT_STACK_FRAMELIST, Links);
  861. #if RTL_CATCH_PEOPLE_TWIDDLING_FRAMELISTS_OR_HEAP_CORRUPTION
  862. // If these fire, then something bad happened to the frame list cache; the list
  863. // got its magic twiddled, there were frames left active in the list, or
  864. // the frames in use count wasn't properly updated
  865. ASSERT(FrameList->Magic == ACTIVATION_CONTEXT_STACK_FRAMELIST_MAGIC);
  866. ASSERT(FrameList->FramesInUse == 0);
  867. ASSERT(FrameList->NotFramesInUse == (ULONG)~FrameList->FramesInUse);
  868. if (FrameList->Magic != ACTIVATION_CONTEXT_STACK_FRAMELIST_MAGIC) {
  869. ExceptionRecord.ExceptionRecord = NULL;
  870. ExceptionRecord.NumberParameters = 4;
  871. ExceptionRecord.ExceptionInformation[0] = SXS_CORRUPTION_CODE_FRAMELIST;
  872. ExceptionRecord.ExceptionInformation[1] = SXS_CORRUPTION_CODE_FRAMELIST_SUBCODE_BAD_MAGIC;
  873. ExceptionRecord.ExceptionInformation[2] = (ULONG_PTR) &Teb->ActivationContextStack.FrameListCache;
  874. ExceptionRecord.ExceptionInformation[3] = (ULONG_PTR) FrameList;
  875. ExceptionRecord.ExceptionCode = STATUS_SXS_CORRUPTION;
  876. ExceptionRecord.ExceptionFlags = EXCEPTION_NONCONTINUABLE;
  877. RtlRaiseException(&ExceptionRecord);
  878. }
  879. else if ((FrameList->FramesInUse > 0) || ((ULONG)~FrameList->FramesInUse != FrameList->NotFramesInUse)) {
  880. ExceptionRecord.ExceptionRecord = NULL;
  881. ExceptionRecord.NumberParameters = 4;
  882. ExceptionRecord.ExceptionInformation[0] = SXS_CORRUPTION_CODE_FRAMELIST;
  883. ExceptionRecord.ExceptionInformation[1] = SXS_CORRUPTION_CODE_FRAMELIST_SUBCODE_BAD_INUSECOUNT;
  884. ExceptionRecord.ExceptionInformation[2] = (ULONG_PTR) &Teb->ActivationContextStack.FrameListCache;
  885. ExceptionRecord.ExceptionInformation[3] = (ULONG_PTR) FrameList;
  886. ExceptionRecord.ExceptionCode = STATUS_SXS_CORRUPTION;
  887. ExceptionRecord.ExceptionFlags = EXCEPTION_NONCONTINUABLE;
  888. RtlRaiseException(&ExceptionRecord);
  889. }
  890. #endif
  891. RemoveEntryList(ple);
  892. ple = pleNext;
  893. RtlFreeHeap(RtlProcessHeap(), 0, FrameList);
  894. }
  895. ASSERT(IsListEmpty(&Teb->ActivationContextStack.FrameListCache));}
  896. BOOLEAN
  897. NTAPI
  898. RtlIsActivationContextActive(
  899. PACTIVATION_CONTEXT ActivationContext
  900. )
  901. {
  902. PTEB Teb = NtCurrentTeb();
  903. PRTL_ACTIVATION_CONTEXT_STACK_FRAME Frame = Teb->ActivationContextStack.ActiveFrame;
  904. while (Frame != NULL) {
  905. if (Frame->ActivationContext == ActivationContext) {
  906. return TRUE;
  907. }
  908. Frame = Frame->Previous;
  909. }
  910. return FALSE;
  911. }
  912. #if defined(__cplusplus)
  913. } /* extern "C" */
  914. #endif