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.

806 lines
25 KiB

  1. /*++
  2. Copyright (c) 1999-2000 Microsoft Corporation
  3. Module Name:
  4. SafeIdep.c (WinSAFER Identify Objects privates)
  5. Abstract:
  6. This module implements the WinSAFER APIs that loads the names (and
  7. high-level information) of all Authorization Levels defined within
  8. a given registry context. The list of available levels is loaded
  9. into a Rtl Generic Table that can be enumerated and accessed using
  10. conventional Rtl Generic Table techniques.
  11. Author:
  12. Jeffrey Lawson (JLawson) - Nov 1999
  13. Environment:
  14. User mode only.
  15. Exported Functions:
  16. CodeAuthzLevelObjpInitializeTable
  17. CodeAuthzLevelObjpLoadTable
  18. CodeAuthzLevelObjpEntireTableFree
  19. Revision History:
  20. Created - Nov 1999
  21. --*/
  22. #include "pch.h"
  23. #pragma hdrstop
  24. #include <winsafer.h>
  25. #include <winsaferp.h>
  26. #include "saferp.h"
  27. PVOID NTAPI
  28. SaferpGenericTableAllocate (
  29. IN PRTL_GENERIC_TABLE Table,
  30. IN CLONG ByteSize
  31. )
  32. /*++
  33. Routine Description:
  34. Internal callback for the generic table implementation.
  35. This function allocates memory for a new entry in a GENERIC_TABLE
  36. Arguments:
  37. Table - pointer to the Generic Table structure
  38. ByteSize - the size, in bytes, of the structure to allocate
  39. Return Value:
  40. Pointer to the allocated space.
  41. --*/
  42. {
  43. UNREFERENCED_PARAMETER(Table);
  44. return (PVOID) RtlAllocateHeap(RtlProcessHeap(), 0, ByteSize);
  45. }
  46. VOID NTAPI
  47. SaferpGenericTableFree (
  48. IN PRTL_GENERIC_TABLE Table,
  49. IN PVOID Buffer
  50. )
  51. /*++
  52. Routine Description:
  53. Internal callback for the generic table implementation.
  54. This function frees the space used by a GENERIC_TABLE entry.
  55. Arguments:
  56. Table - pointer to the Generic Table structure
  57. Buffer - pointer to the space to deallocate.
  58. Return Value:
  59. None.
  60. --*/
  61. {
  62. UNREFERENCED_PARAMETER(Table);
  63. ASSERT(Buffer != NULL);
  64. RtlFreeHeap(RtlProcessHeap(), 0, (LPVOID) Buffer);
  65. }
  66. RTL_GENERIC_COMPARE_RESULTS NTAPI
  67. SaferpGuidIdentsTableCompare (
  68. IN PRTL_GENERIC_TABLE Table,
  69. IN PVOID FirstStruct,
  70. IN PVOID SecondStruct
  71. )
  72. /*++
  73. Routine Description:
  74. Arguments:
  75. Return Value:
  76. --*/
  77. {
  78. PAUTHZIDENTSTABLERECORD FirstObj = (PAUTHZIDENTSTABLERECORD) FirstStruct;
  79. PAUTHZIDENTSTABLERECORD SecondObj = (PAUTHZIDENTSTABLERECORD) SecondStruct;
  80. int result;
  81. UNREFERENCED_PARAMETER(Table);
  82. // Explicitly handle null parameters as wildcards, allowing them
  83. // to match anything. We use this for quick deletion of the table.
  84. if (FirstStruct == NULL || SecondStruct == NULL)
  85. return GenericEqual;
  86. // Compare ascending by guid.
  87. result = memcmp(&FirstObj->IdentGuid,
  88. &SecondObj->IdentGuid, sizeof(GUID));
  89. if ( result < 0 )
  90. return GenericLessThan;
  91. else if ( result > 0 )
  92. return GenericGreaterThan;
  93. else
  94. return GenericEqual;
  95. }
  96. VOID NTAPI
  97. CodeAuthzGuidIdentsInitializeTable(
  98. IN OUT PRTL_GENERIC_TABLE pAuthzObjTable
  99. )
  100. /*++
  101. Routine Description:
  102. Arguments:
  103. pAuthzObjTable - pointer to the generic table structure to initialize.
  104. Return Value:
  105. Does not return a value.
  106. --*/
  107. {
  108. RtlInitializeGenericTable(
  109. pAuthzObjTable,
  110. (PRTL_GENERIC_COMPARE_ROUTINE) SaferpGuidIdentsTableCompare,
  111. (PRTL_GENERIC_ALLOCATE_ROUTINE) SaferpGenericTableAllocate,
  112. (PRTL_GENERIC_FREE_ROUTINE) SaferpGenericTableFree,
  113. NULL);
  114. }
  115. NTSTATUS NTAPI
  116. SaferpGuidIdentsLoadTable (
  117. IN OUT PRTL_GENERIC_TABLE pAuthzIdentTable,
  118. IN DWORD dwScopeId,
  119. IN HANDLE hKeyCustomBase,
  120. IN DWORD dwLevelId,
  121. IN SAFER_IDENTIFICATION_TYPES dwIdentityType
  122. )
  123. /*++
  124. Routine Description:
  125. Loads all Code Identities of a particular fragment type and which
  126. map to a specific LevelId value.
  127. Arguments:
  128. pAuthzIdentTable - specifies the table into which the new Code Identity
  129. records should be inserted.
  130. dwScopeId - can be AUTHZSCOPEID_USER, AUTHZSCOPEID_MACHINE, or
  131. AUTHSCOPEID_REGISTRY.
  132. hKeyCustomBase - used only if dwScopeId is AUTHZSCOPEID_REGISTRY.
  133. dwLevelId - specifies the LevelId for which identities should
  134. be loaded.
  135. dwIdentityType - specifies the type of identity to load.
  136. This can be SaferIdentityTypeImageName, SaferIdentityTypeImageHash,
  137. or SaferIdentityTypeUrlZone.
  138. Return Value:
  139. Returns STATUS_SUCCESS if no error occurs.
  140. --*/
  141. {
  142. DWORD dwIndex;
  143. NTSTATUS Status;
  144. HANDLE hKeyIdentityBase;
  145. //
  146. // We were given the key to the root of the policy storage,
  147. // so we need to open the subkey that contains the Identities.
  148. //
  149. {
  150. WCHAR szPathSuffix[MAX_PATH];
  151. WCHAR szDigits[20];
  152. UNICODE_STRING UnicodePathSuffix;
  153. UNICODE_STRING UnicodeDigits;
  154. UnicodePathSuffix.Buffer = szPathSuffix;
  155. UnicodePathSuffix.Length = 0;
  156. UnicodePathSuffix.MaximumLength = sizeof(szPathSuffix);
  157. UnicodeDigits.Buffer = szDigits;
  158. UnicodeDigits.Length = 0;
  159. UnicodeDigits.MaximumLength = sizeof(szDigits);
  160. Status = RtlAppendUnicodeToString(
  161. &UnicodePathSuffix,
  162. SAFER_CODEIDS_REGSUBKEY L"\\");
  163. if (!NT_SUCCESS(Status)) return Status;
  164. Status = RtlIntegerToUnicodeString(
  165. dwLevelId, 10, &UnicodeDigits);
  166. if (!NT_SUCCESS(Status)) return Status;
  167. Status = RtlAppendUnicodeStringToString(
  168. &UnicodePathSuffix, &UnicodeDigits);
  169. if (!NT_SUCCESS(Status)) return Status;
  170. switch (dwIdentityType)
  171. {
  172. case SaferIdentityTypeImageName:
  173. Status = RtlAppendUnicodeToString(
  174. &UnicodePathSuffix, L"\\" SAFER_PATHS_REGSUBKEY);
  175. break;
  176. case SaferIdentityTypeImageHash:
  177. Status = RtlAppendUnicodeToString(
  178. &UnicodePathSuffix, L"\\" SAFER_HASHMD5_REGSUBKEY);
  179. break;
  180. case SaferIdentityTypeUrlZone:
  181. Status = RtlAppendUnicodeToString(
  182. &UnicodePathSuffix, L"\\" SAFER_SOURCEURL_REGSUBKEY);
  183. break;
  184. default:
  185. Status = STATUS_INVALID_PARAMETER;
  186. break;
  187. }
  188. if (!NT_SUCCESS(Status)) return Status;
  189. ASSERT(UnicodePathSuffix.Buffer[ UnicodePathSuffix.Length /
  190. sizeof(WCHAR) ] == UNICODE_NULL);
  191. Status = CodeAuthzpOpenPolicyRootKey(
  192. dwScopeId,
  193. hKeyCustomBase,
  194. UnicodePathSuffix.Buffer,
  195. KEY_READ,
  196. FALSE,
  197. &hKeyIdentityBase);
  198. if (!NT_SUCCESS(Status))
  199. return Status;
  200. }
  201. //
  202. // Iterate through all subkeys under this branch.
  203. //
  204. for (dwIndex = 0; ; dwIndex++)
  205. {
  206. DWORD dwLength;
  207. HANDLE hKeyThisIdentity;
  208. OBJECT_ATTRIBUTES ObjectAttributes;
  209. AUTHZIDENTSTABLERECORD AuthzIdentsRec;
  210. BYTE RawQueryBuffer[sizeof(KEY_BASIC_INFORMATION) + 256];
  211. PKEY_BASIC_INFORMATION pBasicInformation =
  212. (PKEY_BASIC_INFORMATION) &RawQueryBuffer[0];
  213. PKEY_VALUE_PARTIAL_INFORMATION pPartialInformation =
  214. (PKEY_VALUE_PARTIAL_INFORMATION) &RawQueryBuffer[0];
  215. UNICODE_STRING ValueName;
  216. UNICODE_STRING UnicodeKeyname;
  217. //
  218. // Find the next Identity GUID that we will check.
  219. //
  220. Status = NtEnumerateKey(hKeyIdentityBase,
  221. dwIndex,
  222. KeyBasicInformation,
  223. pBasicInformation,
  224. sizeof(RawQueryBuffer),
  225. &dwLength);
  226. if (!NT_SUCCESS(Status)) {
  227. //
  228. // If this one key was too large to fit in our query buffer
  229. // then simply skip over it and try enumerating the next one.
  230. //
  231. if (Status == STATUS_BUFFER_OVERFLOW) {
  232. continue;
  233. } else {
  234. break;
  235. }
  236. }
  237. UnicodeKeyname.Buffer = pBasicInformation->Name;
  238. UnicodeKeyname.MaximumLength = UnicodeKeyname.Length =
  239. (USHORT) pBasicInformation->NameLength;
  240. // Note that UnicodeKeyname.Buffer is not necessarily null terminated.
  241. ASSERT(UnicodeKeyname.Length <= wcslen(UnicodeKeyname.Buffer) * sizeof(WCHAR));
  242. //
  243. // Translate the keyname (which we expect to be a GUID).
  244. //
  245. RtlZeroMemory(&AuthzIdentsRec, sizeof(AUTHZIDENTSTABLERECORD));
  246. Status = RtlGUIDFromString(&UnicodeKeyname,
  247. &AuthzIdentsRec.IdentGuid);
  248. if (!NT_SUCCESS(Status) ||
  249. IsZeroGUID(&AuthzIdentsRec.IdentGuid)) {
  250. // the keyname was apparently not numeric.
  251. continue;
  252. }
  253. AuthzIdentsRec.dwScopeId = dwScopeId;
  254. AuthzIdentsRec.dwLevelId = dwLevelId;
  255. AuthzIdentsRec.dwIdentityType = dwIdentityType;
  256. if (RtlLookupElementGenericTable(
  257. pAuthzIdentTable, (PVOID) &AuthzIdentsRec) != NULL) {
  258. // this identity GUID happens to have already been found.
  259. continue;
  260. }
  261. //
  262. // Try to open a handle to that Identity GUID.
  263. //
  264. InitializeObjectAttributes(&ObjectAttributes,
  265. &UnicodeKeyname,
  266. OBJ_CASE_INSENSITIVE,
  267. hKeyIdentityBase,
  268. NULL
  269. );
  270. Status = NtOpenKey(&hKeyThisIdentity,
  271. KEY_READ,
  272. &ObjectAttributes);
  273. if (!NT_SUCCESS(Status)) {
  274. // If we failed to open it, skip to the next one.
  275. continue;
  276. }
  277. //
  278. // Add the new record into our table.
  279. //
  280. switch (dwIdentityType) {
  281. // --------------------
  282. case SaferIdentityTypeImageName:
  283. //
  284. // Read the image path.
  285. //
  286. RtlInitUnicodeString(
  287. &ValueName, SAFER_IDS_ITEMDATA_REGVALUE);
  288. Status = NtQueryValueKey(hKeyThisIdentity,
  289. &ValueName,
  290. KeyValuePartialInformation,
  291. pPartialInformation,
  292. sizeof(RawQueryBuffer),
  293. &dwLength);
  294. if (!NT_SUCCESS(Status)) {
  295. break;
  296. }
  297. if (pPartialInformation->Type == REG_SZ ||
  298. pPartialInformation->Type == REG_EXPAND_SZ) {
  299. AuthzIdentsRec.ImageNameInfo.bExpandVars =
  300. (pPartialInformation->Type == REG_EXPAND_SZ);
  301. Status = RtlCreateUnicodeString(
  302. &AuthzIdentsRec.ImageNameInfo.ImagePath,
  303. (LPCWSTR) pPartialInformation->Data);
  304. if (!NT_SUCCESS(Status)) {
  305. break;
  306. }
  307. } else {
  308. Status = STATUS_UNSUCCESSFUL;
  309. break;
  310. }
  311. //
  312. // Read the extra WinSafer flags.
  313. //
  314. RtlInitUnicodeString(&ValueName,
  315. SAFER_IDS_SAFERFLAGS_REGVALUE);
  316. Status = NtQueryValueKey(hKeyThisIdentity,
  317. &ValueName,
  318. KeyValuePartialInformation,
  319. pPartialInformation,
  320. sizeof(RawQueryBuffer),
  321. &dwLength);
  322. if (NT_SUCCESS(Status) &&
  323. pPartialInformation->Type == REG_DWORD &&
  324. pPartialInformation->DataLength == sizeof(DWORD)) {
  325. AuthzIdentsRec.ImageNameInfo.dwSaferFlags =
  326. (*(PDWORD) pPartialInformation->Data);
  327. } else {
  328. // default the flags if they are missing.
  329. AuthzIdentsRec.ImageNameInfo.dwSaferFlags = 0;
  330. Status = STATUS_SUCCESS;
  331. }
  332. break;
  333. // --------------------
  334. case SaferIdentityTypeImageHash:
  335. //
  336. // Read the hash data and hash size.
  337. //
  338. RtlInitUnicodeString(&ValueName,
  339. SAFER_IDS_ITEMDATA_REGVALUE);
  340. Status = NtQueryValueKey(hKeyThisIdentity,
  341. &ValueName,
  342. KeyValuePartialInformation,
  343. pPartialInformation,
  344. sizeof(RawQueryBuffer),
  345. &dwLength);
  346. if (!NT_SUCCESS(Status)) {
  347. break;
  348. }
  349. if (pPartialInformation->Type == REG_BINARY &&
  350. pPartialInformation->DataLength > 0 &&
  351. pPartialInformation->DataLength <= SAFER_MAX_HASH_SIZE) {
  352. AuthzIdentsRec.ImageHashInfo.HashSize =
  353. pPartialInformation->DataLength;
  354. RtlCopyMemory(&AuthzIdentsRec.ImageHashInfo.ImageHash[0],
  355. pPartialInformation->Data,
  356. pPartialInformation->DataLength);
  357. } else {
  358. Status = STATUS_UNSUCCESSFUL;
  359. break;
  360. }
  361. //
  362. // Read the algorithm used to compute the hash.
  363. //
  364. RtlInitUnicodeString(&ValueName,
  365. SAFER_IDS_HASHALG_REGVALUE);
  366. Status = NtQueryValueKey(hKeyThisIdentity,
  367. &ValueName,
  368. KeyValuePartialInformation,
  369. pPartialInformation,
  370. sizeof(RawQueryBuffer),
  371. &dwLength);
  372. if (!NT_SUCCESS(Status)) {
  373. break;
  374. }
  375. if (pPartialInformation->Type == REG_DWORD &&
  376. pPartialInformation->DataLength == sizeof(DWORD)) {
  377. AuthzIdentsRec.ImageHashInfo.HashAlgorithm =
  378. *((PDWORD) pPartialInformation->Data);
  379. } else {
  380. Status = STATUS_UNSUCCESSFUL;
  381. break;
  382. }
  383. if ((AuthzIdentsRec.ImageHashInfo.HashAlgorithm &
  384. ALG_CLASS_ALL) != ALG_CLASS_HASH) {
  385. Status = STATUS_UNSUCCESSFUL;
  386. break;
  387. }
  388. //
  389. // Read the original image size.
  390. //
  391. RtlInitUnicodeString(&ValueName,
  392. SAFER_IDS_ITEMSIZE_REGVALUE);
  393. Status = NtQueryValueKey(hKeyThisIdentity,
  394. &ValueName,
  395. KeyValuePartialInformation,
  396. pPartialInformation,
  397. sizeof(RawQueryBuffer),
  398. &dwLength);
  399. if (!NT_SUCCESS(Status)) {
  400. break;
  401. }
  402. if (pPartialInformation->Type == REG_DWORD &&
  403. pPartialInformation->DataLength == sizeof(DWORD)) {
  404. AuthzIdentsRec.ImageHashInfo.ImageSize.LowPart =
  405. *((PDWORD) pPartialInformation->Data);
  406. AuthzIdentsRec.ImageHashInfo.ImageSize.HighPart = 0;
  407. } else if (pPartialInformation->Type == REG_QWORD &&
  408. pPartialInformation->DataLength == 2 * sizeof(DWORD) ) {
  409. AuthzIdentsRec.ImageHashInfo.ImageSize.QuadPart =
  410. ((PLARGE_INTEGER) pPartialInformation->Data)->QuadPart;
  411. } else {
  412. Status = STATUS_UNSUCCESSFUL;
  413. break;
  414. }
  415. //
  416. // Read the extra WinSafer flags.
  417. //
  418. RtlInitUnicodeString(&ValueName,
  419. SAFER_IDS_SAFERFLAGS_REGVALUE);
  420. Status = NtQueryValueKey(hKeyThisIdentity,
  421. &ValueName,
  422. KeyValuePartialInformation,
  423. pPartialInformation,
  424. sizeof(RawQueryBuffer),
  425. &dwLength);
  426. if (NT_SUCCESS(Status) &&
  427. pPartialInformation->Type == REG_DWORD &&
  428. pPartialInformation->DataLength == sizeof(DWORD)) {
  429. #ifdef SAFER_POLICY_ONLY_EXES
  430. AuthzIdentsRec.ImageHashInfo.dwSaferFlags =
  431. (*((PDWORD) pPartialInformation->Data)) &
  432. ~SAFER_POLICY_ONLY_EXES;
  433. #else
  434. AuthzIdentsRec.ImageHashInfo.dwSaferFlags =
  435. (*((PDWORD) pPartialInformation->Data));
  436. #endif
  437. } else {
  438. // default the flags if they are missing.
  439. AuthzIdentsRec.ImageHashInfo.dwSaferFlags = 0;
  440. Status = STATUS_SUCCESS;
  441. }
  442. break;
  443. // --------------------
  444. case SaferIdentityTypeUrlZone:
  445. //
  446. // Read the zone identifier.
  447. //
  448. RtlInitUnicodeString(&ValueName,
  449. SAFER_IDS_ITEMDATA_REGVALUE);
  450. Status = NtQueryValueKey(hKeyThisIdentity,
  451. &ValueName,
  452. KeyValuePartialInformation,
  453. pPartialInformation,
  454. sizeof(RawQueryBuffer),
  455. &dwLength);
  456. if (!NT_SUCCESS(Status)) {
  457. break;
  458. }
  459. if (pPartialInformation->Type == REG_DWORD &&
  460. pPartialInformation->DataLength == sizeof(DWORD)) {
  461. AuthzIdentsRec.ImageZone.UrlZoneId =
  462. * (PDWORD) pPartialInformation->Data;
  463. } else {
  464. Status = STATUS_UNSUCCESSFUL;
  465. break;
  466. }
  467. //
  468. // Read the extra WinSafer flags.
  469. //
  470. RtlInitUnicodeString(&ValueName,
  471. SAFER_IDS_SAFERFLAGS_REGVALUE);
  472. Status = NtQueryValueKey(hKeyThisIdentity,
  473. &ValueName,
  474. KeyValuePartialInformation,
  475. pPartialInformation,
  476. sizeof(RawQueryBuffer),
  477. &dwLength);
  478. if (NT_SUCCESS(Status) &&
  479. pPartialInformation->Type == REG_DWORD &&
  480. pPartialInformation->DataLength == sizeof(DWORD)) {
  481. #ifdef SAFER_POLICY_ONLY_EXES
  482. AuthzIdentsRec.ImageZone.dwSaferFlags =
  483. (*(PDWORD) pPartialInformation->Data) &
  484. ~SAFER_POLICY_ONLY_EXES;
  485. #else
  486. AuthzIdentsRec.ImageZone.dwSaferFlags =
  487. (*(PDWORD) pPartialInformation->Data);
  488. #endif
  489. } else {
  490. // default the flags if they are missing.
  491. AuthzIdentsRec.ImageZone.dwSaferFlags = 0;
  492. Status = STATUS_SUCCESS;
  493. }
  494. break;
  495. // --------------------
  496. default:
  497. ASSERT(0 && "unexpected identity type");
  498. Status = STATUS_INVALID_INFO_CLASS;
  499. }
  500. // Only insert the record if we don't have
  501. // any other entries with this same GUID.
  502. if (NT_SUCCESS(Status)) {
  503. RtlInsertElementGenericTable(
  504. pAuthzIdentTable,
  505. (PVOID) &AuthzIdentsRec,
  506. sizeof(AUTHZIDENTSTABLERECORD),
  507. NULL);
  508. }
  509. NtClose(hKeyThisIdentity);
  510. }
  511. NtClose(hKeyIdentityBase);
  512. return STATUS_SUCCESS;
  513. }
  514. NTSTATUS NTAPI
  515. CodeAuthzGuidIdentsLoadTableAll (
  516. IN PRTL_GENERIC_TABLE pAuthzLevelTable,
  517. IN OUT PRTL_GENERIC_TABLE pAuthzIdentTable,
  518. IN DWORD dwScopeId,
  519. IN HANDLE hKeyCustomBase
  520. )
  521. /*++
  522. Routine Description:
  523. Arguments:
  524. pAuthzLevelTable - specifies the table that has already been
  525. loaded with the WinSafer Levels that should be allowed.
  526. These Levels do not necessarily need to have been loaded
  527. from the same scope from which the Code Identities are
  528. being loaded from.
  529. pAuthzIdentTable - specifies the table into which the loaded
  530. Code Identities should be inserted.
  531. dwScopeId - scope from where the Code Identities should be loaded from.
  532. This may be AUTHZSCOPEID_MACHINE, AUTHZSCOPEID_USER, or
  533. AUTHZSCOPEID_REGISTRY.
  534. hKeyCustomBase - only used if dwScopeId was AUTHZSCOPEID_REGISTRY.
  535. Return Value:
  536. Returns STATUS_SUCCESS if no errors occurred.
  537. --*/
  538. {
  539. NTSTATUS Status;
  540. NTSTATUS WorstStatus = STATUS_SUCCESS;
  541. PVOID RestartKey;
  542. PAUTHZLEVELTABLERECORD pAuthzLevelRecord;
  543. //
  544. // Enumerate through all records and close the registry handles.
  545. //
  546. RestartKey = NULL;
  547. for (pAuthzLevelRecord = (PAUTHZLEVELTABLERECORD)
  548. RtlEnumerateGenericTableWithoutSplaying(
  549. pAuthzLevelTable, &RestartKey);
  550. pAuthzLevelRecord != NULL;
  551. pAuthzLevelRecord = (PAUTHZLEVELTABLERECORD)
  552. RtlEnumerateGenericTableWithoutSplaying(
  553. pAuthzLevelTable, &RestartKey)
  554. )
  555. {
  556. Status = SaferpGuidIdentsLoadTable(
  557. pAuthzIdentTable,
  558. dwScopeId,
  559. hKeyCustomBase,
  560. pAuthzLevelRecord->dwLevelId,
  561. SaferIdentityTypeImageName);
  562. if (!NT_SUCCESS(Status))
  563. WorstStatus = Status;
  564. Status = SaferpGuidIdentsLoadTable(
  565. pAuthzIdentTable,
  566. dwScopeId,
  567. hKeyCustomBase,
  568. pAuthzLevelRecord->dwLevelId,
  569. SaferIdentityTypeImageHash);
  570. if (!NT_SUCCESS(Status))
  571. WorstStatus = Status;
  572. Status = SaferpGuidIdentsLoadTable(
  573. pAuthzIdentTable,
  574. dwScopeId,
  575. hKeyCustomBase,
  576. pAuthzLevelRecord->dwLevelId,
  577. SaferIdentityTypeUrlZone);
  578. if (!NT_SUCCESS(Status))
  579. WorstStatus = Status;
  580. }
  581. return WorstStatus;
  582. }
  583. VOID NTAPI
  584. CodeAuthzGuidIdentsEntireTableFree (
  585. IN OUT PRTL_GENERIC_TABLE pAuthzIdentTable
  586. )
  587. /*++
  588. Routine Description:
  589. Frees the allocated memory associated with all of the entries
  590. currently within a Code Identities table. Once the table has
  591. been emptied, it may immediately be filled again without any
  592. other initialization necessary.
  593. Arguments:
  594. pAuthzIdentTable - pointer to the table that should be cleared.
  595. Return Value:
  596. Does not return any value.
  597. --*/
  598. {
  599. ULONG NumElements;
  600. //
  601. // Now iterate through the table again and free all of the
  602. // elements themselves.
  603. //
  604. NumElements = RtlNumberGenericTableElements(pAuthzIdentTable);
  605. while ( NumElements-- > 0 ) {
  606. // Delete all elements. Note that we pass NULL as the element
  607. // to delete because our compare function is smart enough to
  608. // allow treatment of NULL as a wildcard element.
  609. BOOL retval = RtlDeleteElementGenericTable( pAuthzIdentTable, NULL);
  610. ASSERT(retval == TRUE);
  611. }
  612. }
  613. PAUTHZIDENTSTABLERECORD NTAPI
  614. CodeAuthzIdentsLookupByGuid (
  615. IN PRTL_GENERIC_TABLE pAuthzIdentTable,
  616. IN REFGUID pIdentGuid
  617. )
  618. /*++
  619. Routine Description:
  620. This function searches for an identity within a GENERIC_TABLE.
  621. Arguments:
  622. pAuthzIdentTable - pointer to the Generic Table structure
  623. pIdentGuid -
  624. Return Value:
  625. Returns a pointer to the Code Identity record if the GUID
  626. specified was found. Otherwise NULL is returned.
  627. --*/
  628. {
  629. AUTHZIDENTSTABLERECORD AuthzIdentsRec;
  630. RtlCopyMemory(&AuthzIdentsRec.IdentGuid, pIdentGuid, sizeof(GUID));
  631. return (PAUTHZIDENTSTABLERECORD)
  632. RtlLookupElementGenericTable(pAuthzIdentTable,
  633. (PVOID) &AuthzIdentsRec);
  634. }