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.

1720 lines
59 KiB

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