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.

1798 lines
61 KiB

  1. /*++
  2. Copyright (c) 1989 Microsoft Corporation
  3. Module Name:
  4. sxsctxsrch.c
  5. Abstract:
  6. Side-by-side activation support for Windows/NT
  7. Implementation of context stack searching
  8. Author:
  9. Michael Grier (MGrier) 2/2/2000
  10. Revision History:
  11. --*/
  12. #pragma warning(disable:4214) // bit field types other than int
  13. #pragma warning(disable:4201) // nameless struct/union
  14. #pragma warning(disable:4115) // named type definition in parentheses
  15. #pragma warning(disable:4127) // condition expression is constant
  16. #include <nt.h>
  17. #include <ntrtl.h>
  18. #include <nturtl.h>
  19. #include <sxsp.h>
  20. #include <stdlib.h>
  21. typedef const void *PCVOID;
  22. //#undef DBG_SXS
  23. #define DBG_SXS 0
  24. //#if DBG_SXS
  25. //#undef DPFLTR_TRACE_LEVEL
  26. //#undef DPFLTR_INFO_LEVEL
  27. //#define DPFLTR_TRACE_LEVEL DPFLTR_ERROR_LEVEL
  28. //#define DPFLTR_INFO_LEVEL DPFLTR_ERROR_LEVEL
  29. //#endif
  30. #define ARRAY_FITS(_base, _count, _elemtype, _limit) ((((ULONG) (_base)) < (_limit)) && ((((ULONG) ((_base) + ((_count) * (sizeof(_elemtype)))))) <= (_limit)))
  31. #define SINGLETON_FITS(_base, _elemtype, _limit) ARRAY_FITS((_base), 1, _elemtype, (_limit))
  32. //
  33. // Comparison of unsigned numbers by subtraction does Not work!
  34. //
  35. #define RTLP_COMPARE_NUMBER(x, y) \
  36. (((x) < (y)) ? -1 : ((x) > (y)) ? +1 : 0)
  37. int
  38. __cdecl
  39. RtlpCompareActivationContextDataTOCEntryById(
  40. CONST VOID* VoidElement1,
  41. CONST VOID* VoidElement2
  42. )
  43. /*++
  44. This code must kinda sorta mimic code in sxs.dll.
  45. base\win32\fusion\dll\whistler\actctxgenctxctb.cpp
  46. CActivationContextGenerationContextContributor::Compare
  47. But we handle extended sections differently.
  48. --*/
  49. {
  50. const ACTIVATION_CONTEXT_DATA_TOC_ENTRY UNALIGNED * Element1 = (const ACTIVATION_CONTEXT_DATA_TOC_ENTRY UNALIGNED *)VoidElement1;
  51. const ACTIVATION_CONTEXT_DATA_TOC_ENTRY UNALIGNED * Element2 = (const ACTIVATION_CONTEXT_DATA_TOC_ENTRY UNALIGNED *)VoidElement2;
  52. return RTLP_COMPARE_NUMBER(Element1->Id, Element2->Id);
  53. }
  54. NTSTATUS
  55. RtlpLocateActivationContextSection(
  56. PCACTIVATION_CONTEXT_DATA ActivationContextData,
  57. const GUID *ExtensionGuid,
  58. ULONG Id,
  59. PVOID *SectionData,
  60. ULONG *SectionLength
  61. )
  62. {
  63. NTSTATUS Status = STATUS_SUCCESS;
  64. const ACTIVATION_CONTEXT_DATA_TOC_HEADER UNALIGNED * TocHeader = NULL;
  65. const ACTIVATION_CONTEXT_DATA_TOC_ENTRY UNALIGNED * TocEntries = NULL;
  66. const ACTIVATION_CONTEXT_DATA_TOC_ENTRY UNALIGNED * TocEntry = NULL;
  67. ULONG i;
  68. #if DBG_SXS
  69. DbgPrintEx(
  70. DPFLTR_SXS_ID,
  71. DPFLTR_TRACE_LEVEL,
  72. "Entered RtlpLocateActivationContextSection() Id = %u\n", Id);
  73. #endif
  74. if ((ActivationContextData->TotalSize < sizeof(ACTIVATION_CONTEXT_DATA)) ||
  75. (ActivationContextData->HeaderSize < sizeof(ACTIVATION_CONTEXT_DATA)))
  76. {
  77. DbgPrintEx(
  78. DPFLTR_SXS_ID,
  79. DPFLTR_ERROR_LEVEL,
  80. "SXS/RTL: Activation context data at %p too small; TotalSize = %lu; HeaderSize = %lu\n",
  81. ActivationContextData,
  82. ActivationContextData->TotalSize,
  83. ActivationContextData->HeaderSize);
  84. Status = STATUS_SXS_INVALID_ACTCTXDATA_FORMAT;
  85. goto Exit;
  86. }
  87. if (ExtensionGuid != NULL)
  88. {
  89. if (ActivationContextData->ExtendedTocOffset != 0)
  90. {
  91. const ACTIVATION_CONTEXT_DATA_EXTENDED_TOC_HEADER UNALIGNED * ExtHeader = NULL;
  92. const ACTIVATION_CONTEXT_DATA_EXTENDED_TOC_ENTRY UNALIGNED * ExtEntry = NULL;
  93. if (!SINGLETON_FITS(ActivationContextData->ExtendedTocOffset, ACTIVATION_CONTEXT_DATA_EXTENDED_TOC_HEADER, ActivationContextData->TotalSize))
  94. {
  95. DbgPrintEx(
  96. DPFLTR_SXS_ID,
  97. DPFLTR_ERROR_LEVEL,
  98. "SXS/RTL: Extended TOC offset (%ld) is outside bounds of activation context data (%lu bytes)\n",
  99. ActivationContextData->ExtendedTocOffset, ActivationContextData->TotalSize);
  100. Status = STATUS_SXS_INVALID_ACTCTXDATA_FORMAT;
  101. goto Exit;
  102. }
  103. ExtHeader = (PCACTIVATION_CONTEXT_DATA_EXTENDED_TOC_HEADER) (((LONG_PTR) ActivationContextData) + ActivationContextData->ExtendedTocOffset);
  104. if (!ARRAY_FITS(ExtHeader->FirstEntryOffset, ExtHeader->EntryCount, ACTIVATION_CONTEXT_DATA_EXTENDED_TOC_ENTRY, ActivationContextData->TotalSize))
  105. {
  106. DbgPrintEx(
  107. DPFLTR_SXS_ID,
  108. DPFLTR_ERROR_LEVEL,
  109. "SXS/RTL: Extended TOC entry array (starting at offset %ld; count = %lu; entry size = %u) is outside bounds of activation context data (%lu bytes)\n",
  110. ExtHeader->FirstEntryOffset,
  111. ExtHeader->EntryCount,
  112. sizeof(ACTIVATION_CONTEXT_DATA_EXTENDED_TOC_ENTRY),
  113. ActivationContextData->TotalSize);
  114. Status = STATUS_SXS_INVALID_ACTCTXDATA_FORMAT;
  115. goto Exit;
  116. }
  117. ExtEntry = (PCACTIVATION_CONTEXT_DATA_EXTENDED_TOC_ENTRY) (((LONG_PTR) ActivationContextData) + ExtHeader->FirstEntryOffset);
  118. // No fancy searching for the extension; just a dumb linear search.
  119. for (i=0; i<ExtHeader->EntryCount; i++)
  120. {
  121. if (IsEqualGUID(ExtensionGuid, &ExtEntry[i].ExtensionGuid))
  122. {
  123. if (!SINGLETON_FITS(ExtEntry[i].TocOffset, ACTIVATION_CONTEXT_DATA_TOC_HEADER, ActivationContextData->TotalSize))
  124. {
  125. DbgPrintEx(
  126. DPFLTR_SXS_ID,
  127. DPFLTR_ERROR_LEVEL,
  128. "SXS/RTL: Extended TOC section TOC %d (offset: %ld, size: %u) is outside activation context data bounds (%lu bytes)\n",
  129. i,
  130. ExtEntry[i].TocOffset,
  131. sizeof(ACTIVATION_CONTEXT_DATA_TOC_HEADER),
  132. ActivationContextData->TotalSize);
  133. Status = STATUS_SXS_INVALID_ACTCTXDATA_FORMAT;
  134. goto Exit;
  135. }
  136. TocHeader = (PCACTIVATION_CONTEXT_DATA_TOC_HEADER) (((LONG_PTR) ActivationContextData) + ExtEntry[i].TocOffset);
  137. break;
  138. }
  139. }
  140. }
  141. }
  142. else if (ActivationContextData->DefaultTocOffset != 0)
  143. {
  144. TocHeader = (PCACTIVATION_CONTEXT_DATA_TOC_HEADER) (((LONG_PTR) ActivationContextData) + ActivationContextData->DefaultTocOffset);
  145. }
  146. if ((TocHeader == NULL) || (TocHeader->EntryCount == 0))
  147. {
  148. Status = STATUS_SXS_SECTION_NOT_FOUND;
  149. goto Exit;
  150. }
  151. if (!ARRAY_FITS(TocHeader->FirstEntryOffset, TocHeader->EntryCount, ACTIVATION_CONTEXT_DATA_TOC_ENTRY, ActivationContextData->TotalSize))
  152. {
  153. DbgPrintEx(
  154. DPFLTR_SXS_ID,
  155. DPFLTR_ERROR_LEVEL,
  156. "SXS/RTL: TOC entry array (offset: %ld; count = %lu; entry size = %u) is outside bounds of activation context data (%lu bytes)\n",
  157. TocHeader->FirstEntryOffset,
  158. TocHeader->EntryCount,
  159. sizeof(ACTIVATION_CONTEXT_DATA_TOC_ENTRY),
  160. ActivationContextData->TotalSize);
  161. Status = STATUS_SXS_INVALID_ACTCTXDATA_FORMAT;
  162. goto Exit;
  163. }
  164. TocEntries = (PCACTIVATION_CONTEXT_DATA_TOC_ENTRY) (((LONG_PTR) ActivationContextData) + TocHeader->FirstEntryOffset);
  165. if (TocHeader->Flags & ACTIVATION_CONTEXT_DATA_TOC_HEADER_INORDER)
  166. {
  167. #if DBG
  168. // Paranoia while we're writing the code to encode the data structure...
  169. ULONG j;
  170. for (j=1; j<TocHeader->EntryCount; j++)
  171. ASSERT(TocEntries[j-1].Id < TocEntries[j].Id);
  172. #endif // DBG
  173. if (Id < TocEntries[0].Id)
  174. {
  175. Status = STATUS_SXS_SECTION_NOT_FOUND;
  176. goto Exit;
  177. }
  178. if (TocHeader->Flags & ACTIVATION_CONTEXT_DATA_TOC_HEADER_DENSE)
  179. {
  180. const ULONG Index = Id - TocEntries[0].Id;
  181. #if DBG
  182. ULONG jx;
  183. for (jx=1; jx<TocHeader->EntryCount; jx++)
  184. ASSERT((TocEntries[jx-1].Id + 1) == TocEntries[jx].Id);
  185. #endif // DBG
  186. if (Index >= TocHeader->EntryCount)
  187. {
  188. Status = STATUS_SXS_SECTION_NOT_FOUND;
  189. goto Exit;
  190. }
  191. // The entries are dense and in order; we can just do an array index.
  192. TocEntry = &TocEntries[Index];
  193. }
  194. else
  195. {
  196. ACTIVATION_CONTEXT_DATA_TOC_ENTRY Key;
  197. Key.Id = Id;
  198. TocEntry = (const ACTIVATION_CONTEXT_DATA_TOC_ENTRY UNALIGNED *)
  199. bsearch(
  200. &Key,
  201. TocEntries,
  202. TocHeader->EntryCount,
  203. sizeof(*TocEntries),
  204. RtlpCompareActivationContextDataTOCEntryById
  205. );
  206. }
  207. }
  208. else
  209. {
  210. // They're not in order; just do a linear search.
  211. for (i=0; i<TocHeader->EntryCount; i++)
  212. {
  213. if (TocEntries[i].Id == Id)
  214. {
  215. TocEntry = &TocEntries[i];
  216. break;
  217. }
  218. }
  219. }
  220. if ((TocEntry == NULL) || (TocEntry->Offset == 0))
  221. {
  222. Status = STATUS_SXS_SECTION_NOT_FOUND;
  223. goto Exit;
  224. }
  225. if (!SINGLETON_FITS(TocEntry->Offset, TocEntry->Length, ActivationContextData->TotalSize))
  226. {
  227. DbgPrintEx(
  228. DPFLTR_SXS_ID,
  229. DPFLTR_ERROR_LEVEL,
  230. "SXS/RTL: Section found (offset %ld; length %lu) extends past end of activation context data (%lu bytes)\n",
  231. TocEntry->Offset,
  232. TocEntry->Length,
  233. ActivationContextData->TotalSize);
  234. Status = STATUS_SXS_INVALID_ACTCTXDATA_FORMAT;
  235. goto Exit;
  236. }
  237. *SectionData = (PVOID) (((LONG_PTR) ActivationContextData) + TocEntry->Offset);
  238. *SectionLength = TocEntry->Length;
  239. Status = STATUS_SUCCESS;
  240. Exit:
  241. #if DBG_SXS
  242. DbgPrintEx(
  243. DPFLTR_SXS_ID,
  244. DPFLTR_TRACE_LEVEL,
  245. "Leaving RtlpLocateActivationContextSection() with NTSTATUS 0x%08lx\n", Status);
  246. #endif // DBG_SXS
  247. return Status;
  248. }
  249. NTSTATUS
  250. RtlpFindNextActivationContextSection(
  251. PFINDFIRSTACTIVATIONCONTEXTSECTION Context,
  252. PVOID *SectionData,
  253. ULONG *SectionLength,
  254. PACTIVATION_CONTEXT *ActivationContextOut
  255. )
  256. {
  257. NTSTATUS Status = STATUS_SUCCESS;
  258. PCACTIVATION_CONTEXT_DATA ActivationContextData = NULL;
  259. PACTIVATION_CONTEXT ActivationContextWeAreTrying = NULL;
  260. const PTEB Teb = NtCurrentTeb();
  261. const PPEB Peb = Teb->ProcessEnvironmentBlock;
  262. #if DBG_SXS
  263. DbgPrintEx(
  264. DPFLTR_SXS_ID,
  265. DPFLTR_TRACE_LEVEL,
  266. "Entered RtlpFindNextActivationContextSection()\n");
  267. #endif // DBG_SXS
  268. if (ActivationContextOut != NULL)
  269. *ActivationContextOut = NULL;
  270. for (;;)
  271. {
  272. switch (Context->Depth)
  273. {
  274. case 0:
  275. // first time through; select the activation context at the head of the stack.
  276. if (Teb->ActivationContextStack.ActiveFrame != NULL) {
  277. PRTL_ACTIVATION_CONTEXT_STACK_FRAME Frame = (PRTL_ACTIVATION_CONTEXT_STACK_FRAME) Teb->ActivationContextStack.ActiveFrame;
  278. ActivationContextWeAreTrying = Frame->ActivationContext;
  279. if ((ActivationContextWeAreTrying != NULL) &&
  280. (ActivationContextWeAreTrying != ACTCTX_PROCESS_DEFAULT)) {
  281. if (ActivationContextWeAreTrying == ACTCTX_SYSTEM_DEFAULT) {
  282. ActivationContextData = Peb->SystemDefaultActivationContextData;
  283. } else {
  284. ActivationContextData = ActivationContextWeAreTrying->ActivationContextData;
  285. }
  286. }
  287. if (ActivationContextData != NULL) {
  288. // We got what we were looking for...
  289. Context->Depth = 1;
  290. break;
  291. }
  292. // We explicitly fall through in the other case...
  293. }
  294. case 1: // try the process default
  295. ActivationContextWeAreTrying = ACTCTX_PROCESS_DEFAULT;
  296. ActivationContextData = Peb->ActivationContextData;
  297. if (ActivationContextData != NULL) {
  298. Context->Depth = 2;
  299. break;
  300. }
  301. // explicit fall through...
  302. case 2: // try system default
  303. ActivationContextWeAreTrying = ACTCTX_SYSTEM_DEFAULT;
  304. ActivationContextData = Peb->SystemDefaultActivationContextData;
  305. if (ActivationContextData != NULL) {
  306. Context->Depth = 3;
  307. break;
  308. }
  309. default:
  310. ASSERT(Context->Depth <= 3);
  311. if (Context->Depth > 3) {
  312. Status = STATUS_INTERNAL_ERROR;
  313. goto Exit;
  314. }
  315. break;
  316. }
  317. // Hmm... no data.
  318. if (ActivationContextData == NULL) {
  319. Status = STATUS_SXS_SECTION_NOT_FOUND;
  320. goto Exit;
  321. }
  322. Status = RtlpLocateActivationContextSection(
  323. ActivationContextData,
  324. Context->ExtensionGuid,
  325. Context->Id,
  326. SectionData,
  327. SectionLength);
  328. if (NT_SUCCESS(Status))
  329. break;
  330. // If we're not at the end of the search list and we get an error other
  331. // than STATUS_SXS_SECTION_NOT_FOUND, report it. If it is
  332. // STATUS_SXS_SECTION_NOT_FOUND and we're not at the end of the list,
  333. // iterate again.
  334. if ((Status != STATUS_SXS_SECTION_NOT_FOUND) ||
  335. (Context->Depth == 3))
  336. goto Exit;
  337. }
  338. Context->OutFlags =
  339. ((ActivationContextWeAreTrying == ACTCTX_SYSTEM_DEFAULT)
  340. ? FIND_ACTIVATION_CONTEXT_SECTION_OUTFLAG_FOUND_IN_SYSTEM_DEFAULT
  341. : 0)
  342. |
  343. ((ActivationContextWeAreTrying == ACTCTX_PROCESS_DEFAULT)
  344. ? FIND_ACTIVATION_CONTEXT_SECTION_OUTFLAG_FOUND_IN_PROCESS_DEFAULT
  345. : 0)
  346. ;
  347. if (ActivationContextOut != NULL)
  348. {
  349. if (ActivationContextWeAreTrying == ACTCTX_SYSTEM_DEFAULT)
  350. {
  351. // Hide this new value from old code that doesn't understand it.
  352. ActivationContextWeAreTrying = ACTCTX_PROCESS_DEFAULT;
  353. }
  354. *ActivationContextOut = ActivationContextWeAreTrying;
  355. }
  356. Status = STATUS_SUCCESS;
  357. Exit:
  358. #if DBG_SXS
  359. DbgPrintEx(
  360. DPFLTR_SXS_ID,
  361. DPFLTR_TRACE_LEVEL,
  362. "Leaving RtlpFindNextActivationContextSection() with NTSTATUS 0x%08lx\n", Status);
  363. #endif // DBG_SXS
  364. return Status;
  365. }
  366. NTSTATUS
  367. NTAPI
  368. RtlFindFirstActivationContextSection(
  369. IN PFINDFIRSTACTIVATIONCONTEXTSECTION Context,
  370. OUT PVOID *SectionData,
  371. OUT ULONG *SectionLength,
  372. OUT PACTIVATION_CONTEXT *ActivationContextFound OPTIONAL
  373. )
  374. {
  375. NTSTATUS Status = STATUS_SUCCESS;
  376. PACTIVATION_CONTEXT ActivationContextTemp = NULL;
  377. #if DBG_SXS
  378. DbgPrintEx(
  379. DPFLTR_SXS_ID,
  380. DPFLTR_TRACE_LEVEL,
  381. "Entered RtlFindFirstActivationContextSection()\n");
  382. #endif // DBG_SXS
  383. if (ActivationContextFound != NULL)
  384. *ActivationContextFound = NULL;
  385. if ((Context == NULL) ||
  386. (Context->Size < sizeof(FINDFIRSTACTIVATIONCONTEXTSECTION)) ||
  387. (Context->Flags & ~(
  388. FIND_ACTIVATION_CONTEXT_SECTION_KEY_RETURN_ACTIVATION_CONTEXT
  389. | FIND_ACTIVATION_CONTEXT_SECTION_KEY_RETURN_FLAGS)) ||
  390. (SectionData == NULL) ||
  391. (SectionLength == NULL))
  392. {
  393. Status = STATUS_INVALID_PARAMETER;
  394. goto Exit;
  395. }
  396. Context->Depth = 0;
  397. Status = RtlpFindNextActivationContextSection(Context, SectionData, SectionLength, &ActivationContextTemp);
  398. if (!NT_SUCCESS(Status))
  399. goto Exit;
  400. if (ActivationContextFound != NULL)
  401. {
  402. RtlAddRefActivationContext(ActivationContextTemp);
  403. *ActivationContextFound = ActivationContextTemp;
  404. }
  405. Status = STATUS_SUCCESS;
  406. Exit:
  407. #if DBG_SXS
  408. DbgPrintEx(
  409. DPFLTR_SXS_ID,
  410. DPFLTR_TRACE_LEVEL,
  411. "Leaving RtlFindFirstActivationContextSection() with NTSTATUS 0x%08lx\n", Status);
  412. #endif // DBG_SXS
  413. return Status;
  414. }
  415. NTSTATUS
  416. RtlpFindFirstActivationContextSection(
  417. IN PFINDFIRSTACTIVATIONCONTEXTSECTION Context,
  418. OUT PVOID *SectionData,
  419. OUT ULONG *SectionLength,
  420. OUT PACTIVATION_CONTEXT *ActivationContextFound OPTIONAL
  421. )
  422. {
  423. NTSTATUS Status = STATUS_SUCCESS;
  424. #if DBG_SXS
  425. DbgPrintEx(
  426. DPFLTR_SXS_ID,
  427. DPFLTR_TRACE_LEVEL,
  428. "Entered %s()\n", __FUNCTION__);
  429. #endif // DBG_SXS
  430. if (ActivationContextFound != NULL)
  431. *ActivationContextFound = NULL;
  432. if ((Context == NULL) ||
  433. (Context->Size < sizeof(FINDFIRSTACTIVATIONCONTEXTSECTION)) ||
  434. (Context->Flags & ~(
  435. FIND_ACTIVATION_CONTEXT_SECTION_KEY_RETURN_ACTIVATION_CONTEXT
  436. | FIND_ACTIVATION_CONTEXT_SECTION_KEY_RETURN_FLAGS)) ||
  437. (SectionData == NULL) ||
  438. (SectionLength == NULL))
  439. {
  440. Status = STATUS_INVALID_PARAMETER;
  441. goto Exit;
  442. }
  443. Context->Depth = 0;
  444. Status = RtlpFindNextActivationContextSection(Context, SectionData, SectionLength, ActivationContextFound);
  445. if (!NT_SUCCESS(Status))
  446. goto Exit;
  447. Status = STATUS_SUCCESS;
  448. Exit:
  449. #if DBG_SXS
  450. DbgPrintEx(
  451. DPFLTR_SXS_ID,
  452. DPFLTR_TRACE_LEVEL,
  453. "Leaving %s() with NTSTATUS 0x%08lx\n", __FUNCTION__, Status);
  454. #endif // DBG_SXS
  455. return Status;
  456. }
  457. NTSTATUS
  458. NTAPI
  459. RtlFindNextActivationContextSection(
  460. IN PFINDFIRSTACTIVATIONCONTEXTSECTION Context,
  461. OUT PVOID *SectionData,
  462. OUT ULONG *SectionLength,
  463. OUT PACTIVATION_CONTEXT *ActivationContextFound OPTIONAL
  464. )
  465. {
  466. NTSTATUS Status = STATUS_SUCCESS;
  467. PACTIVATION_CONTEXT ActivationContextTemp = NULL;
  468. #if DBG_SXS
  469. DbgPrintEx(
  470. DPFLTR_SXS_ID,
  471. DPFLTR_TRACE_LEVEL,
  472. "Entered RtlFindNextActivationContextSection()\n");
  473. #endif // DBG_SXS
  474. if (ActivationContextFound != NULL)
  475. *ActivationContextFound = NULL;
  476. if ((Context == NULL) ||
  477. (Context->Size < sizeof(FINDFIRSTACTIVATIONCONTEXTSECTION)) ||
  478. (Context->Flags & ~(
  479. FIND_ACTIVATION_CONTEXT_SECTION_KEY_RETURN_ACTIVATION_CONTEXT
  480. | FIND_ACTIVATION_CONTEXT_SECTION_KEY_RETURN_FLAGS)) ||
  481. (SectionData == NULL) ||
  482. (SectionLength == NULL))
  483. {
  484. Status = STATUS_INVALID_PARAMETER;
  485. goto Exit;
  486. }
  487. Status = RtlpFindNextActivationContextSection(
  488. Context,
  489. SectionData,
  490. SectionLength,
  491. &ActivationContextTemp);
  492. if (!NT_SUCCESS(Status))
  493. goto Exit;
  494. if (ActivationContextFound != NULL) {
  495. RtlAddRefActivationContext(ActivationContextTemp);
  496. *ActivationContextFound = ActivationContextTemp;
  497. }
  498. Status = STATUS_SUCCESS;
  499. Exit:
  500. #if DBG_SXS
  501. DbgPrintEx(
  502. DPFLTR_SXS_ID,
  503. DPFLTR_TRACE_LEVEL,
  504. "Leaving RtlFindNextActivationContextSection() with NTSTATUS 0x%08lx\n", Status);
  505. #endif // DBG_SXS
  506. return Status;
  507. }
  508. VOID
  509. NTAPI
  510. RtlEndFindActivationContextSection(
  511. IN PFINDFIRSTACTIVATIONCONTEXTSECTION Context
  512. )
  513. {
  514. // We don't maintain any state, so nothing to do today. Who knows what we might
  515. // do in the future however...
  516. UNREFERENCED_PARAMETER (Context);
  517. }
  518. NTSTATUS
  519. RtlpFindActivationContextSection_FillOutReturnedData(
  520. IN ULONG Flags,
  521. OUT PACTIVATION_CONTEXT_SECTION_KEYED_DATA ReturnedData,
  522. IN OUT PACTIVATION_CONTEXT ActivationContext,
  523. IN PCFINDFIRSTACTIVATIONCONTEXTSECTION Context,
  524. IN const VOID * UNALIGNED Header,
  525. IN ULONG Header_UserDataOffset,
  526. IN ULONG Header_UserDataSize,
  527. IN ULONG SectionLength
  528. )
  529. {
  530. NTSTATUS Status;
  531. PCACTIVATION_CONTEXT_DATA ActivationContextData;
  532. PCACTIVATION_CONTEXT_DATA_ASSEMBLY_ROSTER_HEADER AssemblyRosterHeader;
  533. PCACTIVATION_CONTEXT_DATA_ASSEMBLY_ROSTER_ENTRY AssemblyRosterEntryList;
  534. PCACTIVATION_CONTEXT_DATA_ASSEMBLY_INFORMATION AssemblyDataInfo;
  535. #if DBG
  536. Status = STATUS_INTERNAL_ERROR;
  537. #if !defined(INVALID_HANDLE_VALUE)
  538. #define INVALID_HANDLE_VALUE ((HANDLE)(LONG_PTR)-1)
  539. #endif
  540. ActivationContextData = (PCACTIVATION_CONTEXT_DATA)INVALID_HANDLE_VALUE;
  541. AssemblyRosterHeader = (PCACTIVATION_CONTEXT_DATA_ASSEMBLY_ROSTER_HEADER)INVALID_HANDLE_VALUE;
  542. AssemblyRosterEntryList = (PCACTIVATION_CONTEXT_DATA_ASSEMBLY_ROSTER_ENTRY)INVALID_HANDLE_VALUE;
  543. AssemblyDataInfo = (PCACTIVATION_CONTEXT_DATA_ASSEMBLY_INFORMATION)INVALID_HANDLE_VALUE;
  544. #endif
  545. if (Context == NULL) {
  546. Status = STATUS_INVALID_PARAMETER;
  547. goto Exit;
  548. }
  549. if (Header == NULL) {
  550. Status = STATUS_INVALID_PARAMETER;
  551. goto Exit;
  552. }
  553. if (ReturnedData == NULL) {
  554. Status = STATUS_SUCCESS;
  555. goto Exit;
  556. }
  557. if (Header_UserDataOffset != 0) {
  558. ReturnedData->SectionGlobalData = (PVOID) (((ULONG_PTR) Header) + Header_UserDataOffset);
  559. ReturnedData->SectionGlobalDataLength = Header_UserDataSize;
  560. }
  561. ReturnedData->SectionBase = (PVOID)Header;
  562. ReturnedData->SectionTotalLength = SectionLength;
  563. if (Flags & FIND_ACTIVATION_CONTEXT_SECTION_KEY_RETURN_ACTIVATION_CONTEXT) {
  564. ASSERT(RTL_CONTAINS_FIELD(ReturnedData, ReturnedData->Size, ActivationContext));
  565. RtlAddRefActivationContext(ActivationContext);
  566. ReturnedData->ActivationContext = ActivationContext;
  567. }
  568. if (Flags & FIND_ACTIVATION_CONTEXT_SECTION_KEY_RETURN_FLAGS) {
  569. ASSERT(RTL_CONTAINS_FIELD(ReturnedData, ReturnedData->Size, Flags));
  570. ReturnedData->Flags =
  571. ((Context->OutFlags & FIND_ACTIVATION_CONTEXT_SECTION_OUTFLAG_FOUND_IN_PROCESS_DEFAULT)
  572. ? ACTIVATION_CONTEXT_SECTION_KEYED_DATA_FLAG_FOUND_IN_PROCESS_DEFAULT
  573. : 0)
  574. |
  575. ((Context->OutFlags & FIND_ACTIVATION_CONTEXT_SECTION_OUTFLAG_FOUND_IN_SYSTEM_DEFAULT)
  576. ? ACTIVATION_CONTEXT_SECTION_KEYED_DATA_FLAG_FOUND_IN_SYSTEM_DEFAULT
  577. : 0)
  578. ;
  579. }
  580. if (Flags & FIND_ACTIVATION_CONTEXT_SECTION_KEY_RETURN_ASSEMBLY_METADATA) {
  581. typedef ACTIVATION_CONTEXT_SECTION_KEYED_DATA RETURNED_DATA;
  582. PCACTIVATION_CONTEXT_STRING_SECTION_HEADER AssemblyMetadataStringSectionHeader;
  583. PVOID AssemblyMetadataSectionBase;
  584. ULONG AssemblyMetadataSectionLength;
  585. ULONG AssemblyRosterIndex;
  586. #if DBG
  587. AssemblyRosterIndex = ~0UL;
  588. AssemblyMetadataStringSectionHeader = (PCACTIVATION_CONTEXT_STRING_SECTION_HEADER)INVALID_HANDLE_VALUE;
  589. AssemblyMetadataSectionBase = (PVOID)INVALID_HANDLE_VALUE;
  590. AssemblyMetadataSectionLength = ~0UL;
  591. #endif
  592. ASSERT(RTL_CONTAINS_FIELD(ReturnedData, ReturnedData->Size, AssemblyMetadata));
  593. Status = RtlpGetActivationContextData(
  594. 0,
  595. ActivationContext,
  596. Context, /* for its flags */
  597. &ActivationContextData
  598. );
  599. if (!NT_SUCCESS(Status))
  600. goto Exit;
  601. if (!RTL_VERIFY(ActivationContextData != NULL)) {
  602. Status = STATUS_INTERNAL_ERROR;
  603. goto Exit;
  604. }
  605. AssemblyRosterIndex = ReturnedData->AssemblyRosterIndex;
  606. ASSERT(AssemblyRosterIndex >= 1);
  607. AssemblyRosterHeader = (PCACTIVATION_CONTEXT_DATA_ASSEMBLY_ROSTER_HEADER) (((ULONG_PTR) ActivationContextData) + ActivationContextData->AssemblyRosterOffset);
  608. ASSERT(AssemblyRosterIndex < AssemblyRosterHeader->EntryCount);
  609. AssemblyRosterEntryList = (PCACTIVATION_CONTEXT_DATA_ASSEMBLY_ROSTER_ENTRY) (((ULONG_PTR) ActivationContextData) + AssemblyRosterHeader->FirstEntryOffset);
  610. AssemblyDataInfo = (PACTIVATION_CONTEXT_DATA_ASSEMBLY_INFORMATION)((ULONG_PTR)ActivationContextData + AssemblyRosterEntryList[AssemblyRosterIndex].AssemblyInformationOffset);
  611. ReturnedData->AssemblyMetadata.Information = RTL_CONST_CAST(PACTIVATION_CONTEXT_DATA_ASSEMBLY_INFORMATION)(AssemblyDataInfo);
  612. Status =
  613. RtlpLocateActivationContextSection(
  614. ActivationContextData,
  615. NULL, // ExtensionGuid
  616. ACTIVATION_CONTEXT_SECTION_ASSEMBLY_INFORMATION,
  617. &AssemblyMetadataSectionBase,
  618. &AssemblyMetadataSectionLength
  619. );
  620. if (!NT_SUCCESS(Status))
  621. goto Exit;
  622. ReturnedData->AssemblyMetadata.SectionBase = AssemblyMetadataSectionBase;
  623. ReturnedData->AssemblyMetadata.SectionLength = AssemblyMetadataSectionLength;
  624. if (AssemblyMetadataSectionBase != NULL
  625. && AssemblyMetadataSectionLength != 0) {
  626. ULONG HeaderSize;
  627. ULONG Magic;
  628. AssemblyMetadataStringSectionHeader = (PCACTIVATION_CONTEXT_STRING_SECTION_HEADER)(((ULONG_PTR)AssemblyMetadataSectionBase) + AssemblyMetadataSectionLength);
  629. if (!RTL_CONTAINS_FIELD(AssemblyMetadataStringSectionHeader, AssemblyMetadataSectionLength, Magic)) {
  630. Status = STATUS_INTERNAL_ERROR;
  631. goto Exit;
  632. }
  633. if (!RTL_CONTAINS_FIELD(AssemblyMetadataStringSectionHeader, AssemblyMetadataSectionLength, HeaderSize)) {
  634. Status = STATUS_INTERNAL_ERROR;
  635. goto Exit;
  636. }
  637. Magic = AssemblyMetadataStringSectionHeader->Magic;
  638. if (AssemblyMetadataStringSectionHeader->Magic != ACTIVATION_CONTEXT_STRING_SECTION_MAGIC) {
  639. Status = STATUS_INTERNAL_ERROR;
  640. goto Exit;
  641. }
  642. HeaderSize = AssemblyMetadataStringSectionHeader->HeaderSize;
  643. if (HeaderSize > AssemblyMetadataSectionLength) {
  644. Status = STATUS_INTERNAL_ERROR;
  645. goto Exit;
  646. }
  647. if (AssemblyMetadataSectionLength < sizeof(ACTIVATION_CONTEXT_STRING_SECTION_HEADER)) {
  648. Status = STATUS_INTERNAL_ERROR;
  649. goto Exit;
  650. }
  651. if (HeaderSize < sizeof(ACTIVATION_CONTEXT_STRING_SECTION_HEADER)) {
  652. Status = STATUS_INTERNAL_ERROR;
  653. goto Exit;
  654. }
  655. if (!RTL_CONTAINS_FIELD(AssemblyMetadataStringSectionHeader, HeaderSize, Magic)) {
  656. Status = STATUS_INTERNAL_ERROR;
  657. goto Exit;
  658. }
  659. if (!RTL_CONTAINS_FIELD(AssemblyMetadataStringSectionHeader, HeaderSize, HeaderSize)) {
  660. Status = STATUS_INTERNAL_ERROR;
  661. goto Exit;
  662. }
  663. if (!RTL_CONTAINS_FIELD(AssemblyMetadataStringSectionHeader, HeaderSize, UserDataOffset)) {
  664. Status = STATUS_INTERNAL_ERROR;
  665. goto Exit;
  666. }
  667. if (!RTL_CONTAINS_FIELD(AssemblyMetadataStringSectionHeader, HeaderSize, UserDataSize)) {
  668. Status = STATUS_INTERNAL_ERROR;
  669. goto Exit;
  670. }
  671. ReturnedData->AssemblyMetadata.SectionGlobalDataBase = (PVOID)(((ULONG_PTR)AssemblyMetadataStringSectionHeader) + AssemblyMetadataStringSectionHeader->UserDataOffset);
  672. ReturnedData->AssemblyMetadata.SectionGlobalDataLength = AssemblyMetadataStringSectionHeader->UserDataSize;
  673. }
  674. }
  675. Status = STATUS_SUCCESS;
  676. Exit:
  677. return Status;
  678. }
  679. NTSTATUS
  680. RtlpFindActivationContextSection_CheckParameters(
  681. IN ULONG Flags,
  682. IN const GUID *ExtensionGuid OPTIONAL,
  683. IN ULONG SectionId,
  684. IN PCVOID ThingToFind,
  685. OUT PACTIVATION_CONTEXT_SECTION_KEYED_DATA ReturnedData OPTIONAL
  686. )
  687. {
  688. NTSTATUS Status = STATUS_INTERNAL_ERROR;
  689. UNREFERENCED_PARAMETER(ExtensionGuid);
  690. UNREFERENCED_PARAMETER(SectionId);
  691. if ((ThingToFind == NULL) ||
  692. ((Flags & ~(
  693. FIND_ACTIVATION_CONTEXT_SECTION_KEY_RETURN_ACTIVATION_CONTEXT
  694. | FIND_ACTIVATION_CONTEXT_SECTION_KEY_RETURN_FLAGS
  695. | FIND_ACTIVATION_CONTEXT_SECTION_KEY_RETURN_ASSEMBLY_METADATA
  696. )) != 0) ||
  697. (((Flags & (
  698. FIND_ACTIVATION_CONTEXT_SECTION_KEY_RETURN_ACTIVATION_CONTEXT
  699. | FIND_ACTIVATION_CONTEXT_SECTION_KEY_RETURN_FLAGS
  700. | FIND_ACTIVATION_CONTEXT_SECTION_KEY_RETURN_ASSEMBLY_METADATA
  701. )) != 0) &&
  702. (ReturnedData == NULL)) ||
  703. ((ReturnedData != NULL) &&
  704. (ReturnedData->Size < (FIELD_OFFSET(ACTIVATION_CONTEXT_SECTION_KEYED_DATA, ActivationContext) + sizeof(ReturnedData->ActivationContext)))
  705. )) {
  706. Status = STATUS_INVALID_PARAMETER;
  707. goto Exit;
  708. }
  709. if ((Flags & FIND_ACTIVATION_CONTEXT_SECTION_KEY_RETURN_FLAGS) != 0
  710. && !RTL_CONTAINS_FIELD(ReturnedData, ReturnedData->Size, Flags)
  711. ) {
  712. Status = STATUS_INVALID_PARAMETER;
  713. DbgPrintEx(DPFLTR_SXS_ID, DPFLTR_ERROR_LEVEL, "SXS: %s() flags contains return_flags but they don't fit in size, return invalid_parameter 0x%08lx.\n", __FUNCTION__, STATUS_INVALID_PARAMETER);
  714. goto Exit;
  715. }
  716. if ((Flags & FIND_ACTIVATION_CONTEXT_SECTION_KEY_RETURN_ASSEMBLY_METADATA) != 0
  717. && !RTL_CONTAINS_FIELD(ReturnedData, ReturnedData->Size, AssemblyMetadata)
  718. ) {
  719. Status = STATUS_INVALID_PARAMETER;
  720. DbgPrintEx(DPFLTR_SXS_ID, DPFLTR_ERROR_LEVEL, "SXS: %s() flags contains return_assembly_metadata but they don't fit in size, return invalid_parameter 0x%08lx.\n", __FUNCTION__, STATUS_INVALID_PARAMETER);
  721. goto Exit;
  722. }
  723. Status = STATUS_SUCCESS;
  724. Exit:
  725. #if DBG_SXS
  726. DbgPrintEx(
  727. DPFLTR_SXS_ID,
  728. DPFLTR_TRACE_LEVEL,
  729. "Leaving RtlFindActivationContextSectionString() with NTSTATUS 0x%08lx\n", Status);
  730. #endif // DBG_SXS
  731. return Status;
  732. }
  733. NTSTATUS
  734. NTAPI
  735. RtlFindActivationContextSectionString(
  736. IN ULONG Flags,
  737. IN const GUID *ExtensionGuid OPTIONAL,
  738. IN ULONG SectionId,
  739. IN PCUNICODE_STRING StringToFind,
  740. OUT PACTIVATION_CONTEXT_SECTION_KEYED_DATA ReturnedData OPTIONAL
  741. )
  742. {
  743. NTSTATUS Status = STATUS_INTERNAL_ERROR;
  744. FINDFIRSTACTIVATIONCONTEXTSECTION Context;
  745. const ACTIVATION_CONTEXT_STRING_SECTION_HEADER UNALIGNED * Header;
  746. ULONG StringSectionLength;
  747. BOOLEAN EndSearch;
  748. ULONG HashAlgorithm;
  749. ULONG PseudoKey;
  750. PACTIVATION_CONTEXT ActivationContext;
  751. #if DBG_SXS
  752. CHAR ExtensionGuidBuffer[39];
  753. #endif
  754. const PTEB Teb = NtCurrentTeb();
  755. const PPEB Peb = Teb->ProcessEnvironmentBlock;
  756. // Super short circuit...
  757. if ((Peb->ActivationContextData == NULL) &&
  758. (Peb->SystemDefaultActivationContextData == NULL) &&
  759. (Teb->ActivationContextStack.ActiveFrame == NULL))
  760. return STATUS_SXS_SECTION_NOT_FOUND;
  761. // Move variable initialization after the short-circuiting so that we truly
  762. // do the least amount of work possible prior to the early exit.
  763. StringSectionLength = 0;
  764. EndSearch = FALSE;
  765. HashAlgorithm = HASH_STRING_ALGORITHM_INVALID;
  766. PseudoKey = 0;
  767. ActivationContext = NULL;
  768. #if DBG_SXS
  769. DbgPrintEx(
  770. DPFLTR_SXS_ID,
  771. DPFLTR_TRACE_LEVEL,
  772. "Entered RtlFindActivationContextSectionString()\n"
  773. " Flags = 0x%08lx\n"
  774. " ExtensionGuid = %s\n"
  775. " SectionId = %lu\n"
  776. " StringToFind = %wZ\n"
  777. " ReturnedData = %p\n",
  778. Flags,
  779. RtlpFormatGuidANSI(ExtensionGuid, ExtensionGuidBuffer, sizeof(ExtensionGuidBuffer)),
  780. SectionId,
  781. StringToFind,
  782. ReturnedData);
  783. #endif // DBG_SXS
  784. Status = RtlpFindActivationContextSection_CheckParameters(Flags, ExtensionGuid, SectionId, StringToFind, ReturnedData);
  785. if (!NT_SUCCESS(Status))
  786. goto Exit;
  787. Context.Size = sizeof(Context);
  788. Context.Flags = Flags;
  789. Context.OutFlags = 0;
  790. Context.ExtensionGuid = ExtensionGuid;
  791. Context.Id = SectionId;
  792. Status = RtlpFindFirstActivationContextSection(&Context, (PVOID *) &Header, &StringSectionLength, &ActivationContext);
  793. if (!NT_SUCCESS(Status))
  794. goto Exit;
  795. for (;;) {
  796. // Validate that this actually looks like a string section...
  797. if ((StringSectionLength < sizeof(ACTIVATION_CONTEXT_STRING_SECTION_HEADER)) ||
  798. (Header->Magic != ACTIVATION_CONTEXT_STRING_SECTION_MAGIC)) {
  799. DbgPrintEx(
  800. DPFLTR_SXS_ID,
  801. DPFLTR_ERROR_LEVEL,
  802. "RtlFindActivationContextSectionString() found section at %p (length %lu) which is not a string section\n",
  803. Header,
  804. StringSectionLength);
  805. Status = STATUS_SXS_INVALID_ACTCTXDATA_FORMAT;
  806. goto Exit;
  807. }
  808. Status = RtlpFindUnicodeStringInSection(
  809. Header,
  810. StringSectionLength,
  811. StringToFind,
  812. ReturnedData,
  813. &HashAlgorithm,
  814. &PseudoKey,
  815. NULL,
  816. NULL);
  817. if (NT_SUCCESS(Status))
  818. break;
  819. if (Status != STATUS_SXS_KEY_NOT_FOUND)
  820. goto Exit;
  821. Status = RtlFindNextActivationContextSection(&Context, (PVOID *) &Header, &StringSectionLength, &ActivationContext);
  822. if (!NT_SUCCESS(Status)) {
  823. // Convert from section not found to string not found so that the
  824. // caller can get an indication that at least some indirection
  825. // information was available but just not the particular key that
  826. // they're looking for.
  827. if (Status == STATUS_SXS_SECTION_NOT_FOUND)
  828. Status = STATUS_SXS_KEY_NOT_FOUND;
  829. goto Exit;
  830. }
  831. }
  832. SEND_ACTIVATION_CONTEXT_NOTIFICATION(ActivationContext, USED, NULL);
  833. if (ReturnedData != NULL) {
  834. Status =
  835. RtlpFindActivationContextSection_FillOutReturnedData(
  836. Flags,
  837. ReturnedData,
  838. ActivationContext,
  839. &Context,
  840. Header,
  841. Header->UserDataOffset,
  842. Header->UserDataSize,
  843. StringSectionLength
  844. );
  845. if (!NT_SUCCESS(Status))
  846. goto Exit;
  847. }
  848. Status = STATUS_SUCCESS;
  849. Exit:
  850. #if DBG_SXS
  851. DbgPrintEx(
  852. DPFLTR_SXS_ID,
  853. DPFLTR_TRACE_LEVEL,
  854. "Leaving RtlFindActivationContextSectionString() with NTSTATUS 0x%08lx\n", Status);
  855. #endif // DBG_SXS
  856. return Status;
  857. }
  858. int
  859. __cdecl
  860. RtlpCompareActivationContextStringSectionEntryByPseudoKey(
  861. const void *elem1,
  862. const void *elem2
  863. )
  864. /*++
  865. This code must mimic code in sxs.dll
  866. (base\win32\fusion\dll\whistler\ssgenctx.cpp CSSGenCtx::CompareStringSectionEntries)
  867. --*/
  868. {
  869. const ACTIVATION_CONTEXT_STRING_SECTION_ENTRY UNALIGNED * pEntry1 =
  870. (const ACTIVATION_CONTEXT_STRING_SECTION_ENTRY UNALIGNED *)elem1;
  871. const ACTIVATION_CONTEXT_STRING_SECTION_ENTRY UNALIGNED * pEntry2 =
  872. (const ACTIVATION_CONTEXT_STRING_SECTION_ENTRY UNALIGNED *)elem2;
  873. return RTLP_COMPARE_NUMBER(pEntry1->PseudoKey, pEntry2->PseudoKey);
  874. }
  875. NTSTATUS
  876. RtlpFindUnicodeStringInSection(
  877. const ACTIVATION_CONTEXT_STRING_SECTION_HEADER UNALIGNED * Header,
  878. SIZE_T SectionSize,
  879. PCUNICODE_STRING String,
  880. PACTIVATION_CONTEXT_SECTION_KEYED_DATA DataOut,
  881. PULONG HashAlgorithm,
  882. PULONG PseudoKey,
  883. PULONG UserDataSize,
  884. PCVOID *UserData
  885. )
  886. {
  887. NTSTATUS Status = STATUS_SUCCESS;
  888. BOOLEAN CaseInsensitiveFlag;
  889. BOOLEAN UseHashTable = TRUE;
  890. BOOLEAN UsePseudoKey = TRUE;
  891. const ACTIVATION_CONTEXT_STRING_SECTION_ENTRY UNALIGNED * Entry = NULL;
  892. if (Header->Flags & ACTIVATION_CONTEXT_STRING_SECTION_CASE_INSENSITIVE) {
  893. CaseInsensitiveFlag = TRUE;
  894. }
  895. else {
  896. CaseInsensitiveFlag = FALSE;
  897. }
  898. #if DBG_SXS
  899. DbgPrintEx(
  900. DPFLTR_SXS_ID,
  901. DPFLTR_TRACE_LEVEL,
  902. "Entered RtlpFindUnicodeStringInSection() for string %p (->Length = %u; ->Buffer = %p) \"%wZ\"\n",
  903. String,
  904. (String != NULL) ? String->Length : 0,
  905. (String != NULL) ? String->Buffer : 0,
  906. String);
  907. #endif // DBG_SXS
  908. if (UserDataSize != NULL)
  909. *UserDataSize = 0;
  910. if (UserData != NULL)
  911. *UserData = NULL;
  912. ASSERT(HashAlgorithm != NULL);
  913. ASSERT(PseudoKey != NULL);
  914. if (Header->Magic != ACTIVATION_CONTEXT_STRING_SECTION_MAGIC)
  915. {
  916. #if DBG_SXS
  917. DbgPrintEx(
  918. DPFLTR_SXS_ID,
  919. DPFLTR_TRACE_LEVEL,
  920. "RtlpFindUnicodeStringInSection: String section header has invalid .Magic value.\n");
  921. #endif
  922. Status = STATUS_SXS_INVALID_ACTCTXDATA_FORMAT;
  923. goto Exit;
  924. }
  925. // Eliminate the zero element case to make later code simpler.
  926. if (Header->ElementCount == 0)
  927. {
  928. Status = STATUS_SXS_KEY_NOT_FOUND;
  929. goto Exit;
  930. }
  931. if (Header->HashAlgorithm == HASH_STRING_ALGORITHM_INVALID)
  932. {
  933. UseHashTable = FALSE;
  934. UsePseudoKey = FALSE;
  935. }
  936. else if (*HashAlgorithm != Header->HashAlgorithm)
  937. {
  938. Status = RtlHashUnicodeString(String, CaseInsensitiveFlag, Header->HashAlgorithm, PseudoKey);
  939. if (!NT_SUCCESS(Status))
  940. {
  941. if (Status == STATUS_INVALID_PARAMETER)
  942. {
  943. ULONG TempPseudoKey = 0;
  944. // The only likely reason for invalid parameter is that the hash algorithm
  945. // wasn't understood. We'll be pedantic and see if everything else is OK...
  946. Status = RtlHashUnicodeString(String, CaseInsensitiveFlag, HASH_STRING_ALGORITHM_DEFAULT, &TempPseudoKey);
  947. if (!NT_SUCCESS(Status))
  948. {
  949. // Something's wrong, probably with the "String" parameter. Punt.
  950. goto Exit;
  951. }
  952. DbgPrintEx(
  953. DPFLTR_SXS_ID,
  954. DPFLTR_ERROR_LEVEL,
  955. "RtlpFindUnicodeStringInSection: Unsupported hash algorithm %lu found in string section.\n",
  956. Header->HashAlgorithm);
  957. // Ok, it's an algorithm ID that we don't understand. We can't use the hash
  958. // table or the pseudokey.
  959. UseHashTable = FALSE;
  960. UsePseudoKey = FALSE;
  961. }
  962. else
  963. goto Exit;
  964. }
  965. else
  966. {
  967. // Record the hash algorithm we used so that we can avoid re-hashing if we have
  968. // to search another section.
  969. *HashAlgorithm = Header->HashAlgorithm;
  970. }
  971. }
  972. // If we don't understand the format version, we have to do the manual search.
  973. if (Header->FormatVersion != ACTIVATION_CONTEXT_STRING_SECTION_FORMAT_WHISTLER)
  974. UseHashTable = FALSE;
  975. // If there's no hash table, we can't use it!
  976. if (Header->SearchStructureOffset == 0)
  977. UseHashTable = FALSE;
  978. if (UseHashTable)
  979. {
  980. ULONG i;
  981. const ACTIVATION_CONTEXT_STRING_SECTION_HASH_TABLE UNALIGNED * Table = (const ACTIVATION_CONTEXT_STRING_SECTION_HASH_TABLE UNALIGNED *)
  982. (((LONG_PTR) Header) + Header->SearchStructureOffset);
  983. ULONG Index = ((*PseudoKey) % Table->BucketTableEntryCount);
  984. const ACTIVATION_CONTEXT_STRING_SECTION_HASH_BUCKET UNALIGNED * Bucket = ((const ACTIVATION_CONTEXT_STRING_SECTION_HASH_BUCKET UNALIGNED *)
  985. (((LONG_PTR) Header) + Table->BucketTableOffset)) + Index;
  986. const LONG UNALIGNED *Chain = (const LONG UNALIGNED *) (((LONG_PTR) Header) + Bucket->ChainOffset);
  987. for (i=0; i<Bucket->ChainCount; i++)
  988. {
  989. const ACTIVATION_CONTEXT_STRING_SECTION_ENTRY UNALIGNED *TmpEntry = NULL;
  990. UNICODE_STRING TmpEntryString;
  991. if (((SIZE_T) Chain[i]) > SectionSize)
  992. {
  993. DbgPrintEx(
  994. DPFLTR_SXS_ID,
  995. DPFLTR_ERROR_LEVEL,
  996. "SXS: String hash collision chain offset at %p (= %ld) out of bounds\n", &Chain[i], Chain[i]);
  997. Status = STATUS_SXS_INVALID_ACTCTXDATA_FORMAT;
  998. goto Exit;
  999. }
  1000. TmpEntry = (const ACTIVATION_CONTEXT_STRING_SECTION_ENTRY UNALIGNED *) (((LONG_PTR) Header) + Chain[i]);
  1001. #if DBG_SXS
  1002. DbgPrintEx(
  1003. DPFLTR_SXS_ID,
  1004. DPFLTR_INFO_LEVEL,
  1005. "SXS: Searching bucket collision %d; Chain[%d] = %ld\n"
  1006. " TmpEntry = %p; ->KeyLength = %lu; ->KeyOffset = %lu\n",
  1007. i, i, Chain[i], TmpEntry, TmpEntry->KeyLength, TmpEntry->KeyOffset);
  1008. #endif DBG_SXS
  1009. if (!UsePseudoKey || (TmpEntry->PseudoKey == *PseudoKey))
  1010. {
  1011. if (((SIZE_T) TmpEntry->KeyOffset) > SectionSize)
  1012. {
  1013. DbgPrintEx(
  1014. DPFLTR_SXS_ID,
  1015. DPFLTR_ERROR_LEVEL,
  1016. "SXS: String hash table entry at %p has invalid key offset (= %ld)\n"
  1017. " Header = %p; Index = %lu; Bucket = %p; Chain = %p\n",
  1018. TmpEntry, TmpEntry->KeyOffset, Header, Index, Bucket, Chain);
  1019. Status = STATUS_SXS_INVALID_ACTCTXDATA_FORMAT;
  1020. goto Exit;
  1021. }
  1022. TmpEntryString.Length = (USHORT) TmpEntry->KeyLength;
  1023. TmpEntryString.MaximumLength = TmpEntryString.Length;
  1024. TmpEntryString.Buffer = (PWSTR) (((LONG_PTR) Header) + TmpEntry->KeyOffset);
  1025. if (RtlCompareUnicodeString((PUNICODE_STRING) String, &TmpEntryString, CaseInsensitiveFlag) == 0)
  1026. {
  1027. Entry = TmpEntry;
  1028. break;
  1029. }
  1030. }
  1031. }
  1032. }
  1033. else if (UsePseudoKey && ((Header->Flags & ACTIVATION_CONTEXT_STRING_SECTION_ENTRIES_IN_PSEUDOKEY_ORDER) != 0))
  1034. {
  1035. const ACTIVATION_CONTEXT_STRING_SECTION_ENTRY UNALIGNED * const first = (PCACTIVATION_CONTEXT_STRING_SECTION_ENTRY)
  1036. (((LONG_PTR) Header) + Header->ElementListOffset);
  1037. const ACTIVATION_CONTEXT_STRING_SECTION_ENTRY UNALIGNED * const last = first + (Header->ElementCount - 1);
  1038. ACTIVATION_CONTEXT_STRING_SECTION_ENTRY Key;
  1039. Key.PseudoKey = *PseudoKey;
  1040. Entry = (const ACTIVATION_CONTEXT_STRING_SECTION_ENTRY UNALIGNED *)
  1041. bsearch(
  1042. &Key,
  1043. first,
  1044. Header->ElementCount,
  1045. sizeof(*first),
  1046. RtlpCompareActivationContextStringSectionEntryByPseudoKey
  1047. );
  1048. if (Entry != NULL)
  1049. {
  1050. // Wow, we found the same pseudokey. We need to search all the equal
  1051. // pseudokeys, so back off to the first entry with this PK
  1052. while ((Entry != first) && (Entry->PseudoKey == *PseudoKey))
  1053. Entry--;
  1054. // We may have stopped because we found a different pseudokey, or we may
  1055. // have stopped because we hit the beginning of the list. If we found a
  1056. // different PK, move ahead one entry.
  1057. if (Entry->PseudoKey != *PseudoKey)
  1058. Entry++;
  1059. do
  1060. {
  1061. UNICODE_STRING TmpEntryString;
  1062. TmpEntryString.Length = (USHORT) Entry->KeyLength;
  1063. TmpEntryString.MaximumLength = TmpEntryString.Length;
  1064. TmpEntryString.Buffer = (PWSTR) (((LONG_PTR) Header) + Entry->KeyOffset);
  1065. if (RtlCompareUnicodeString((PUNICODE_STRING) String, &TmpEntryString, CaseInsensitiveFlag) == 0)
  1066. break;
  1067. Entry++;
  1068. } while ((Entry <= last) && (Entry->PseudoKey == *PseudoKey));
  1069. if ((Entry > last) || (Entry->PseudoKey != *PseudoKey))
  1070. Entry = NULL;
  1071. }
  1072. }
  1073. else
  1074. {
  1075. // Argh; we just have to do it the hard way.
  1076. const ACTIVATION_CONTEXT_STRING_SECTION_ENTRY UNALIGNED * TmpEntry = (PCACTIVATION_CONTEXT_STRING_SECTION_ENTRY)
  1077. (((LONG_PTR) Header) + Header->ElementListOffset);
  1078. ULONG Count;
  1079. #if DBG_SXS
  1080. DbgPrintEx(
  1081. DPFLTR_SXS_ID,
  1082. DPFLTR_INFO_LEVEL,
  1083. "RtlpFindUnicodeStringInSection: About to do linear search of %d entries.\n", Header->ElementCount);
  1084. #endif // DBG_SXS
  1085. for (Count = Header->ElementCount; Count != 0; Count--, TmpEntry++)
  1086. {
  1087. UNICODE_STRING TmpEntryString;
  1088. TmpEntryString.Length = (USHORT) TmpEntry->KeyLength;
  1089. TmpEntryString.MaximumLength = TmpEntryString.Length;
  1090. TmpEntryString.Buffer = (PWSTR) (((LONG_PTR) Header) + TmpEntry->KeyOffset);
  1091. if (!UsePseudoKey || (TmpEntry->PseudoKey == *PseudoKey))
  1092. {
  1093. if (RtlCompareUnicodeString((PUNICODE_STRING) String, &TmpEntryString, CaseInsensitiveFlag) == 0)
  1094. {
  1095. Entry = TmpEntry;
  1096. break;
  1097. }
  1098. }
  1099. }
  1100. }
  1101. if ((Entry == NULL) || (Entry->Offset == 0))
  1102. {
  1103. Status = STATUS_SXS_KEY_NOT_FOUND;
  1104. goto Exit;
  1105. }
  1106. if (DataOut != NULL) {
  1107. DataOut->DataFormatVersion = Header->DataFormatVersion;
  1108. DataOut->Data = (PVOID) (((ULONG_PTR) Header) + Entry->Offset);
  1109. DataOut->Length = Entry->Length;
  1110. if (RTL_CONTAINS_FIELD(DataOut, DataOut->Size, AssemblyRosterIndex))
  1111. DataOut->AssemblyRosterIndex = Entry->AssemblyRosterIndex;
  1112. }
  1113. if (UserDataSize != NULL)
  1114. *UserDataSize = Header->UserDataSize;
  1115. if ((UserData != NULL) && (Header->UserDataOffset != 0))
  1116. *UserData = (PCVOID) (((ULONG_PTR) Header) + Header->UserDataOffset);
  1117. Status = STATUS_SUCCESS;
  1118. Exit:
  1119. #if DBG_SXS
  1120. DbgPrintEx(
  1121. DPFLTR_SXS_ID,
  1122. DPFLTR_TRACE_LEVEL,
  1123. "Leaving RtlpFindUnicodeStringInSection() with NTSTATUS 0x%08lx\n", Status);
  1124. #endif // DBG_SXS
  1125. return Status;
  1126. }
  1127. NTSTATUS
  1128. NTAPI
  1129. RtlFindActivationContextSectionGuid(
  1130. IN ULONG Flags,
  1131. IN const GUID *ExtensionGuid OPTIONAL,
  1132. IN ULONG SectionId,
  1133. IN const GUID *GuidToFind,
  1134. OUT PACTIVATION_CONTEXT_SECTION_KEYED_DATA ReturnedData
  1135. )
  1136. {
  1137. NTSTATUS Status;
  1138. FINDFIRSTACTIVATIONCONTEXTSECTION Context;
  1139. const ACTIVATION_CONTEXT_GUID_SECTION_HEADER UNALIGNED *Header;
  1140. ULONG GuidSectionLength;
  1141. BOOLEAN EndSearch;
  1142. PACTIVATION_CONTEXT ActivationContext;
  1143. #if DBG
  1144. CHAR GuidBuffer[39];
  1145. CHAR ExtensionGuidBuffer[39];
  1146. BOOLEAN DbgPrintSxsTraceLevel;
  1147. #endif
  1148. PTEB Teb = NtCurrentTeb();
  1149. PPEB Peb = Teb->ProcessEnvironmentBlock;
  1150. // Super short circuit...
  1151. if ((Peb->ActivationContextData == NULL) &&
  1152. (Peb->SystemDefaultActivationContextData == NULL) &&
  1153. (Teb->ActivationContextStack.ActiveFrame == NULL)) {
  1154. #if DBG_SXS
  1155. DbgPrintEx(
  1156. DPFLTR_SXS_ID,
  1157. DPFLTR_TRACE_LEVEL,
  1158. __FUNCTION__"({%s}) super short circuited\n",
  1159. RtlpFormatGuidANSI(GuidToFind, GuidBuffer, sizeof(GuidBuffer));
  1160. );
  1161. #endif
  1162. return STATUS_SXS_SECTION_NOT_FOUND;
  1163. }
  1164. // Perform initialization after the above test so that we really do the minimal amount of
  1165. // work before bailing out when there's no side-by-side stuff going on in either the
  1166. // process or thread.
  1167. Status = STATUS_INTERNAL_ERROR;
  1168. GuidSectionLength = 0;
  1169. EndSearch = FALSE;
  1170. ActivationContext = NULL;
  1171. #if DBG
  1172. //
  1173. // Comparison to TRUE is odd, but such is NtQueryDebugFilterState.
  1174. //
  1175. if (NtQueryDebugFilterState(DPFLTR_SXS_ID, DPFLTR_TRACE_LEVEL) == TRUE) {
  1176. DbgPrintSxsTraceLevel = TRUE;
  1177. }
  1178. else {
  1179. DbgPrintSxsTraceLevel = FALSE;
  1180. }
  1181. if (DbgPrintSxsTraceLevel) {
  1182. DbgPrintEx(
  1183. DPFLTR_SXS_ID,
  1184. DPFLTR_TRACE_LEVEL,
  1185. "Entered RtlFindActivationContextSectionGuid()\n"
  1186. " Flags = 0x%08lx\n"
  1187. " ExtensionGuid = %s\n"
  1188. " SectionId = %lu\n"
  1189. " GuidToFind = %s\n"
  1190. " ReturnedData = %p\n",
  1191. Flags,
  1192. RtlpFormatGuidANSI(ExtensionGuid, ExtensionGuidBuffer, sizeof(ExtensionGuidBuffer)),
  1193. SectionId,
  1194. RtlpFormatGuidANSI(GuidToFind, GuidBuffer, sizeof(GuidBuffer)),
  1195. ReturnedData);
  1196. }
  1197. #endif
  1198. Status = RtlpFindActivationContextSection_CheckParameters(Flags, ExtensionGuid, SectionId, GuidToFind, ReturnedData);
  1199. if (!NT_SUCCESS(Status))
  1200. goto Exit;
  1201. Context.Size = sizeof(Context);
  1202. Context.Flags = 0;
  1203. Context.ExtensionGuid = ExtensionGuid;
  1204. Context.Id = SectionId;
  1205. Context.OutFlags = 0;
  1206. Status = RtlpFindFirstActivationContextSection(&Context, (PVOID *) &Header, &GuidSectionLength, &ActivationContext);
  1207. if (!NT_SUCCESS(Status))
  1208. goto Exit;
  1209. for (;;) {
  1210. // Validate that this actually looks like a guid section...
  1211. if ((GuidSectionLength < sizeof(ACTIVATION_CONTEXT_GUID_SECTION_HEADER)) ||
  1212. (Header->Magic != ACTIVATION_CONTEXT_GUID_SECTION_MAGIC)) {
  1213. DbgPrintEx(
  1214. DPFLTR_SXS_ID,
  1215. DPFLTR_ERROR_LEVEL,
  1216. "RtlFindActivationContextSectionGuid() found section at %p (length %lu) which is not a GUID section\n",
  1217. Header,
  1218. GuidSectionLength);
  1219. Status = STATUS_SXS_INVALID_ACTCTXDATA_FORMAT;
  1220. goto Exit;
  1221. }
  1222. Status = RtlpFindGuidInSection(
  1223. Header,
  1224. GuidToFind,
  1225. ReturnedData);
  1226. if (NT_SUCCESS(Status))
  1227. break;
  1228. // If we failed for any reason other than not finding the key in the section, bail out.
  1229. if (Status != STATUS_SXS_KEY_NOT_FOUND)
  1230. goto Exit;
  1231. Status = RtlpFindNextActivationContextSection(&Context, (PVOID *) &Header, &GuidSectionLength, &ActivationContext);
  1232. if (!NT_SUCCESS(Status)) {
  1233. // Convert from section not found to key not found so that the
  1234. // caller can get an indication that at least some indirection
  1235. // information was available but just not the particular key that
  1236. // they're looking for.
  1237. if (Status == STATUS_SXS_SECTION_NOT_FOUND)
  1238. Status = STATUS_SXS_KEY_NOT_FOUND;
  1239. goto Exit;
  1240. }
  1241. }
  1242. SEND_ACTIVATION_CONTEXT_NOTIFICATION(ActivationContext, USED, NULL);
  1243. if (ReturnedData != NULL) {
  1244. Status =
  1245. RtlpFindActivationContextSection_FillOutReturnedData(
  1246. Flags,
  1247. ReturnedData,
  1248. ActivationContext,
  1249. &Context,
  1250. Header,
  1251. Header->UserDataOffset,
  1252. Header->UserDataSize,
  1253. GuidSectionLength
  1254. );
  1255. if (!NT_SUCCESS(Status))
  1256. goto Exit;
  1257. }
  1258. Status = STATUS_SUCCESS;
  1259. Exit:
  1260. #if DBG_SXS
  1261. if (DbgPrintSxsTraceLevel) {
  1262. DbgPrintEx(
  1263. DPFLTR_SXS_ID,
  1264. DPFLTR_TRACE_LEVEL,
  1265. "Leaving "__FUNCTION__"(%s) with NTSTATUS 0x%08lx\n",
  1266. RtlpFormatGuidANSI(GuidToFind, GuidBuffer, sizeof(GuidBuffer)),
  1267. Status);
  1268. }
  1269. #endif
  1270. return Status;
  1271. }
  1272. int
  1273. __cdecl
  1274. RtlpCompareActivationContextGuidSectionEntryByGuid(
  1275. const void *elem1,
  1276. const void *elem2
  1277. )
  1278. /*++
  1279. This code must mimic code in sxs.dll
  1280. (base\win32\fusion\dll\whistler\gsgenctx.cpp CGSGenCtx::SortGuidSectionEntries)
  1281. --*/
  1282. {
  1283. const ACTIVATION_CONTEXT_GUID_SECTION_ENTRY UNALIGNED * pLeft =
  1284. (const ACTIVATION_CONTEXT_GUID_SECTION_ENTRY*)elem1;
  1285. const ACTIVATION_CONTEXT_GUID_SECTION_ENTRY UNALIGNED * pRight =
  1286. (const ACTIVATION_CONTEXT_GUID_SECTION_ENTRY*)elem2;
  1287. return memcmp( &pLeft->Guid, &pRight->Guid, sizeof(GUID) );
  1288. }
  1289. NTSTATUS
  1290. RtlpFindGuidInSection(
  1291. const ACTIVATION_CONTEXT_GUID_SECTION_HEADER UNALIGNED *Header,
  1292. const GUID *Guid,
  1293. PACTIVATION_CONTEXT_SECTION_KEYED_DATA DataOut
  1294. )
  1295. {
  1296. NTSTATUS Status = STATUS_SUCCESS;
  1297. BOOLEAN UseHashTable = TRUE;
  1298. const ACTIVATION_CONTEXT_GUID_SECTION_ENTRY UNALIGNED *Entry = NULL;
  1299. #if DBG_SXS
  1300. CHAR GuidBuffer[39];
  1301. DbgPrintEx(
  1302. DPFLTR_SXS_ID,
  1303. DPFLTR_TRACE_LEVEL,
  1304. "Entered "__FUNCTION__"({%s})\n",
  1305. RtlpFormatGuidANSI(Guid, GuidBuffer, sizeof(GuidBuffer))
  1306. );
  1307. #endif
  1308. if (Header->Magic != ACTIVATION_CONTEXT_GUID_SECTION_MAGIC)
  1309. {
  1310. #if DBG_SXS
  1311. DbgPrintEx(
  1312. DPFLTR_SXS_ID,
  1313. DPFLTR_TRACE_LEVEL,
  1314. "RtlpFindGuidInSection: Guid section header has invalid .Magic value.\n");
  1315. #endif
  1316. Status = STATUS_SXS_INVALID_ACTCTXDATA_FORMAT;
  1317. goto Exit;
  1318. }
  1319. // Eliminate the zero element case to make later code simpler.
  1320. if (Header->ElementCount == 0)
  1321. {
  1322. Status = STATUS_SXS_KEY_NOT_FOUND;
  1323. goto Exit;
  1324. }
  1325. // If we don't understand the format version, we have to do the manual search.
  1326. if (Header->FormatVersion != ACTIVATION_CONTEXT_GUID_SECTION_FORMAT_WHISTLER)
  1327. UseHashTable = FALSE;
  1328. // If there's no hash table, we can't use it!
  1329. if (Header->SearchStructureOffset == 0)
  1330. UseHashTable = FALSE;
  1331. if (UseHashTable)
  1332. {
  1333. ULONG i;
  1334. const ACTIVATION_CONTEXT_GUID_SECTION_HASH_TABLE UNALIGNED *Table = (PCACTIVATION_CONTEXT_GUID_SECTION_HASH_TABLE)
  1335. (((LONG_PTR) Header) + Header->SearchStructureOffset);
  1336. ULONG Index = ((Guid->Data1) % Table->BucketTableEntryCount);
  1337. const ACTIVATION_CONTEXT_GUID_SECTION_HASH_BUCKET UNALIGNED *Bucket = ((PCACTIVATION_CONTEXT_GUID_SECTION_HASH_BUCKET)
  1338. (((LONG_PTR) Header) + Table->BucketTableOffset)) + Index;
  1339. const ULONG UNALIGNED *Chain = (PULONG) (((LONG_PTR) Header) + Bucket->ChainOffset);
  1340. for (i=0; i<Bucket->ChainCount; i++)
  1341. {
  1342. const ACTIVATION_CONTEXT_GUID_SECTION_ENTRY UNALIGNED * TmpEntry = (PCACTIVATION_CONTEXT_GUID_SECTION_ENTRY)
  1343. (((LONG_PTR) Header) + *Chain++);
  1344. if (RtlCompareMemory(&TmpEntry->Guid, Guid, sizeof(GUID)) == sizeof(GUID))
  1345. {
  1346. Entry = TmpEntry;
  1347. break;
  1348. }
  1349. }
  1350. }
  1351. else if ((Header->Flags & ACTIVATION_CONTEXT_GUID_SECTION_ENTRIES_IN_ORDER) != 0)
  1352. {
  1353. const ACTIVATION_CONTEXT_GUID_SECTION_ENTRY UNALIGNED * const first = (PCACTIVATION_CONTEXT_GUID_SECTION_ENTRY)
  1354. (((LONG_PTR) Header) + Header->ElementListOffset);
  1355. ACTIVATION_CONTEXT_GUID_SECTION_ENTRY Key;
  1356. Key.Guid = *Guid;
  1357. Entry = (const ACTIVATION_CONTEXT_GUID_SECTION_ENTRY UNALIGNED *)
  1358. bsearch(
  1359. &Key,
  1360. first,
  1361. Header->ElementCount,
  1362. sizeof(*first),
  1363. RtlpCompareActivationContextGuidSectionEntryByGuid
  1364. );
  1365. }
  1366. else
  1367. {
  1368. // Argh; we just have to do it the hard way.
  1369. const ACTIVATION_CONTEXT_GUID_SECTION_ENTRY UNALIGNED * TmpEntry = (const ACTIVATION_CONTEXT_GUID_SECTION_ENTRY UNALIGNED *)
  1370. (((LONG_PTR) Header) + Header->ElementListOffset);
  1371. ULONG Count;
  1372. #if DBG_SXS
  1373. DbgPrintEx(
  1374. DPFLTR_SXS_ID,
  1375. DPFLTR_INFO_LEVEL,
  1376. __FUNCTION__"({%s}): About to do linear search of %d entries.\n",
  1377. RtlpFormatGuidANSI(Guid, GuidBuffer, sizeof(GuidBuffer)),
  1378. Header->ElementCount);
  1379. #endif // DBG_SXS
  1380. for (Count = Header->ElementCount; Count != 0; Count--, TmpEntry++) {
  1381. if (RtlCompareMemory(&TmpEntry->Guid, Guid, sizeof(GUID)) == sizeof(GUID)) {
  1382. Entry = TmpEntry;
  1383. break;
  1384. }
  1385. }
  1386. }
  1387. if ((Entry == NULL) || (Entry->Offset == 0)) {
  1388. Status = STATUS_SXS_KEY_NOT_FOUND;
  1389. goto Exit;
  1390. }
  1391. if (DataOut != NULL) {
  1392. DataOut->DataFormatVersion = Header->DataFormatVersion;
  1393. DataOut->Data = (PVOID) (((ULONG_PTR) Header) + Entry->Offset);
  1394. DataOut->Length = Entry->Length;
  1395. if (RTL_CONTAINS_FIELD(DataOut, DataOut->Size, AssemblyRosterIndex))
  1396. DataOut->AssemblyRosterIndex = Entry->AssemblyRosterIndex;
  1397. }
  1398. Status = STATUS_SUCCESS;
  1399. Exit:
  1400. #if DBG_SXS
  1401. DbgPrintEx(
  1402. DPFLTR_SXS_ID,
  1403. DPFLTR_TRACE_LEVEL,
  1404. "Leaving "__FUNCTION__"({%s}) with NTSTATUS 0x%08lx\n",
  1405. RtlpFormatGuidANSI(Guid, GuidBuffer, sizeof(GuidBuffer)),
  1406. Status);
  1407. #endif // DBG_SXS
  1408. return Status;
  1409. }
  1410. #define tohexdigit(_x) ((CHAR) (((_x) < 10) ? ((_x) + '0') : ((_x) + 'A' - 10)))
  1411. PSTR
  1412. RtlpFormatGuidANSI(
  1413. const GUID *Guid,
  1414. PSTR Buffer,
  1415. SIZE_T BufferLength
  1416. )
  1417. {
  1418. CHAR *pch = Buffer;
  1419. ASSERT(BufferLength > 38);
  1420. if (BufferLength <= 38)
  1421. {
  1422. return "<GUID buffer too small>";
  1423. }
  1424. if (Guid == NULL)
  1425. return "<null>";
  1426. pch = Buffer;
  1427. *pch++ = '{';
  1428. *pch++ = tohexdigit((Guid->Data1 >> 28) & 0xf);
  1429. *pch++ = tohexdigit((Guid->Data1 >> 24) & 0xf);
  1430. *pch++ = tohexdigit((Guid->Data1 >> 20) & 0xf);
  1431. *pch++ = tohexdigit((Guid->Data1 >> 16) & 0xf);
  1432. *pch++ = tohexdigit((Guid->Data1 >> 12) & 0xf);
  1433. *pch++ = tohexdigit((Guid->Data1 >> 8) & 0xf);
  1434. *pch++ = tohexdigit((Guid->Data1 >> 4) & 0xf);
  1435. *pch++ = tohexdigit((Guid->Data1 >> 0) & 0xf);
  1436. *pch++ = '-';
  1437. *pch++ = tohexdigit((Guid->Data2 >> 12) & 0xf);
  1438. *pch++ = tohexdigit((Guid->Data2 >> 8) & 0xf);
  1439. *pch++ = tohexdigit((Guid->Data2 >> 4) & 0xf);
  1440. *pch++ = tohexdigit((Guid->Data2 >> 0) & 0xf);
  1441. *pch++ = '-';
  1442. *pch++ = tohexdigit((Guid->Data3 >> 12) & 0xf);
  1443. *pch++ = tohexdigit((Guid->Data3 >> 8) & 0xf);
  1444. *pch++ = tohexdigit((Guid->Data3 >> 4) & 0xf);
  1445. *pch++ = tohexdigit((Guid->Data3 >> 0) & 0xf);
  1446. *pch++ = '-';
  1447. *pch++ = tohexdigit((Guid->Data4[0] >> 4) & 0xf);
  1448. *pch++ = tohexdigit((Guid->Data4[0] >> 0) & 0xf);
  1449. *pch++ = tohexdigit((Guid->Data4[1] >> 4) & 0xf);
  1450. *pch++ = tohexdigit((Guid->Data4[1] >> 0) & 0xf);
  1451. *pch++ = '-';
  1452. *pch++ = tohexdigit((Guid->Data4[2] >> 4) & 0xf);
  1453. *pch++ = tohexdigit((Guid->Data4[2] >> 0) & 0xf);
  1454. *pch++ = tohexdigit((Guid->Data4[3] >> 4) & 0xf);
  1455. *pch++ = tohexdigit((Guid->Data4[3] >> 0) & 0xf);
  1456. *pch++ = tohexdigit((Guid->Data4[4] >> 4) & 0xf);
  1457. *pch++ = tohexdigit((Guid->Data4[4] >> 0) & 0xf);
  1458. *pch++ = tohexdigit((Guid->Data4[5] >> 4) & 0xf);
  1459. *pch++ = tohexdigit((Guid->Data4[5] >> 0) & 0xf);
  1460. *pch++ = tohexdigit((Guid->Data4[6] >> 4) & 0xf);
  1461. *pch++ = tohexdigit((Guid->Data4[6] >> 0) & 0xf);
  1462. *pch++ = tohexdigit((Guid->Data4[7] >> 4) & 0xf);
  1463. *pch++ = tohexdigit((Guid->Data4[7] >> 0) & 0xf);
  1464. *pch++ = '}';
  1465. *pch++ = '\0';
  1466. return Buffer;
  1467. }
  1468. NTSTATUS
  1469. RtlpGetActivationContextData(
  1470. IN ULONG Flags,
  1471. IN PCACTIVATION_CONTEXT ActivationContext,
  1472. IN PCFINDFIRSTACTIVATIONCONTEXTSECTION FindContext, OPTIONAL /* This is used for its flags. */
  1473. OUT PCACTIVATION_CONTEXT_DATA* ActivationContextData
  1474. )
  1475. {
  1476. NTSTATUS Status = STATUS_INTERNAL_ERROR; // in case someone forgets to set it...
  1477. SIZE_T PebOffset;
  1478. if (ActivationContextData == NULL) {
  1479. Status = STATUS_INVALID_PARAMETER_4;
  1480. goto Exit;
  1481. }
  1482. if (Flags & ~(RTLP_GET_ACTIVATION_CONTEXT_DATA_MAP_NULL_TO_EMPTY)) {
  1483. Status = STATUS_INVALID_PARAMETER_1;
  1484. goto Exit;
  1485. }
  1486. *ActivationContextData = NULL;
  1487. PebOffset = 0;
  1488. //
  1489. // We should use RtlpMapSpecialValuesToBuiltInActivationContexts here, but
  1490. // it doesn't handle all the values and it isn't worth fixing it right now.
  1491. //
  1492. switch ((ULONG_PTR)ActivationContext)
  1493. {
  1494. case ((ULONG_PTR)NULL):
  1495. if (FindContext == NULL) {
  1496. PebOffset = FIELD_OFFSET(PEB, ActivationContextData);
  1497. } else {
  1498. switch (
  1499. FindContext->OutFlags
  1500. & ( FIND_ACTIVATION_CONTEXT_SECTION_OUTFLAG_FOUND_IN_PROCESS_DEFAULT
  1501. | FIND_ACTIVATION_CONTEXT_SECTION_OUTFLAG_FOUND_IN_SYSTEM_DEFAULT
  1502. )) {
  1503. case 0: // FALLTHROUGH
  1504. case FIND_ACTIVATION_CONTEXT_SECTION_OUTFLAG_FOUND_IN_PROCESS_DEFAULT:
  1505. PebOffset = FIELD_OFFSET(PEB, ActivationContextData);
  1506. break;
  1507. case FIND_ACTIVATION_CONTEXT_SECTION_OUTFLAG_FOUND_IN_SYSTEM_DEFAULT:
  1508. PebOffset = FIELD_OFFSET(PEB, SystemDefaultActivationContextData);
  1509. break;
  1510. case (FIND_ACTIVATION_CONTEXT_SECTION_OUTFLAG_FOUND_IN_PROCESS_DEFAULT
  1511. | FIND_ACTIVATION_CONTEXT_SECTION_OUTFLAG_FOUND_IN_SYSTEM_DEFAULT):
  1512. Status = STATUS_INVALID_PARAMETER_2;
  1513. goto Exit;
  1514. break;
  1515. }
  1516. }
  1517. break;
  1518. case ((ULONG_PTR)ACTCTX_EMPTY):
  1519. *ActivationContextData = &RtlpTheEmptyActivationContextData;
  1520. break;
  1521. case ((ULONG_PTR)ACTCTX_SYSTEM_DEFAULT):
  1522. PebOffset = FIELD_OFFSET(PEB, SystemDefaultActivationContextData);
  1523. break;
  1524. default:
  1525. *ActivationContextData = ActivationContext->ActivationContextData;
  1526. break;
  1527. }
  1528. if (PebOffset != 0)
  1529. *ActivationContextData = *(PCACTIVATION_CONTEXT_DATA*)(((ULONG_PTR)NtCurrentPeb()) + PebOffset);
  1530. //
  1531. // special transmutation of lack of actctx into the empty actctx
  1532. //
  1533. if (*ActivationContextData == NULL)
  1534. if ((Flags & RTLP_GET_ACTIVATION_CONTEXT_DATA_MAP_NULL_TO_EMPTY) != 0)
  1535. *ActivationContextData = &RtlpTheEmptyActivationContextData;
  1536. Status = STATUS_SUCCESS;
  1537. Exit:
  1538. return Status;
  1539. }