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.

2358 lines
76 KiB

  1. /*++
  2. Copyright (c) 1989 Microsoft Corporation
  3. Module Name:
  4. id.cpp
  5. Abstract:
  6. Implementation of the assembly identity data type.
  7. Author:
  8. Michael Grier (MGrier) 7/20/2000
  9. Revision History:
  10. --*/
  11. #include "stdinc.h"
  12. #include <sxsapi.h>
  13. #include <stdlib.h>
  14. #include <search.h>
  15. #include "idp.h"
  16. #include <identhandles.h>
  17. LONG FORCEINLINE
  18. RtlSxspCompareStrings(
  19. PCWSTR pcwsz1,
  20. SIZE_T cch1,
  21. PCWSTR pcwsz2,
  22. SIZE_T cch2,
  23. BOOLEAN fInsensitive
  24. )
  25. {
  26. //
  27. // Note that these are initialized with the deconstified pcwsz,
  28. // but the underlying RtlCompareUnicodeString functions doesn't
  29. // modify the const input structures at all. I couldn't get this
  30. // to work out without this cast, even though it's ugly.
  31. //
  32. const UNICODE_STRING a = {
  33. (USHORT)cch1,
  34. (USHORT)cch1,
  35. (PWSTR)pcwsz1
  36. };
  37. const UNICODE_STRING b = {
  38. (USHORT)cch2,
  39. (USHORT)cch2,
  40. (PWSTR)pcwsz2
  41. };
  42. return RtlCompareUnicodeString(&a, &b, fInsensitive ? TRUE : FALSE);
  43. }
  44. //
  45. // Power of two to which to round the number of allocated attribute
  46. // pointers.
  47. //
  48. #define ROUNDING_FACTOR_BITS (3)
  49. #define WILDCARD_CHAR '*'
  50. #define ENTRY(x) { x, NUMBER_OF(x) - 1 },
  51. const static struct
  52. {
  53. const WCHAR *String;
  54. SIZE_T Cch;
  55. } s_rgLegalNamesNotInANamespace[] =
  56. {
  57. ENTRY(SXS_ASSEMBLY_IDENTITY_STD_ATTRIBUTE_NAME_NAME)
  58. ENTRY(SXS_ASSEMBLY_IDENTITY_STD_ATTRIBUTE_NAME_VERSION)
  59. ENTRY(SXS_ASSEMBLY_IDENTITY_STD_ATTRIBUTE_NAME_LANGUAGE)
  60. ENTRY(SXS_ASSEMBLY_IDENTITY_STD_ATTRIBUTE_NAME_PUBLIC_KEY)
  61. ENTRY(SXS_ASSEMBLY_IDENTITY_STD_ATTRIBUTE_NAME_PUBLIC_KEY_TOKEN)
  62. ENTRY(SXS_ASSEMBLY_IDENTITY_STD_ATTRIBUTE_NAME_PROCESSOR_ARCHITECTURE)
  63. ENTRY(SXS_ASSEMBLY_IDENTITY_STD_ATTRIBUTE_NAME_TYPE)
  64. };
  65. #undef ENTRY
  66. NTSTATUS
  67. RtlSxspValidateAssemblyIdentity(
  68. IN ULONG Flags,
  69. IN PCASSEMBLY_IDENTITY AssemblyIdentity
  70. )
  71. {
  72. if ((Flags & ~SXSP_VALIDATE_ASSEMBLY_IDENTITY_FLAGS_MAY_BE_NULL) != 0) {
  73. return STATUS_INVALID_PARAMETER;
  74. }
  75. if (AssemblyIdentity == NULL)
  76. {
  77. if (!(Flags & SXSP_VALIDATE_ASSEMBLY_IDENTITY_FLAGS_MAY_BE_NULL)) {
  78. return STATUS_INVALID_PARAMETER;
  79. }
  80. }
  81. else
  82. {
  83. const ULONG IdentityType = AssemblyIdentity->Type;
  84. if ((IdentityType != ASSEMBLY_IDENTITY_TYPE_DEFINITION) &&
  85. (IdentityType != ASSEMBLY_IDENTITY_TYPE_REFERENCE) &&
  86. (IdentityType != ASSEMBLY_IDENTITY_TYPE_WILDCARD)) {
  87. return STATUS_INVALID_PARAMETER;
  88. }
  89. }
  90. return STATUS_SUCCESS;
  91. }
  92. //
  93. // Note!
  94. //
  95. // We currently are very very restrictive on the legal characters in namespaces.
  96. //
  97. // This is because the various rules for equivalences of namespaces are extremely
  98. // complex w.r.t. when "a" == "A" and "%Ab" == "%aB" etc.
  99. //
  100. // We're side-stepping this issue by requireing everything to be lower case and
  101. // not permitting the "%" character.
  102. //
  103. const WCHAR s_rgLegalNamespaceChars[] = L"abcdefghijklmnopqrstuvwxyz0123456789.-_/\\:";
  104. NTSTATUS
  105. RtlSxspValidateAssemblyIdentityAttributeNamespace(
  106. IN ULONG Flags,
  107. IN const WCHAR *Namespace,
  108. IN SIZE_T NamespaceCch
  109. )
  110. {
  111. SIZE_T i;
  112. if ((Flags != 0) || ((Namespace == NULL) && (NamespaceCch != 0))) {
  113. return STATUS_INVALID_PARAMETER;
  114. }
  115. //
  116. // We really should ensure that the namespace is a well-formed URI
  117. //
  118. for (i=0; i<NamespaceCch; i++)
  119. {
  120. if (wcschr(s_rgLegalNamespaceChars, Namespace[i]) == NULL) {
  121. return STATUS_SXS_INVALID_XML_NAMESPACE_URI;
  122. }
  123. }
  124. return STATUS_SUCCESS;
  125. }
  126. NTSTATUS
  127. RtlSxspValidateAssemblyIdentityAttributeName(
  128. IN ULONG Flags,
  129. IN const WCHAR *Name,
  130. IN SIZE_T NameCch
  131. )
  132. {
  133. NTSTATUS status = STATUS_SUCCESS;
  134. BOOLEAN fNameWellFormed = FALSE;
  135. if ((Flags != 0) || ((Name == NULL) && (NameCch != 0))) {
  136. return STATUS_INVALID_PARAMETER;
  137. }
  138. //
  139. // We should ensure that Name is a well-formed XML identifier
  140. //
  141. if (!NT_SUCCESS(status = RtlSxspValidateXMLName(Name, NameCch, &fNameWellFormed))) {
  142. return status;
  143. }
  144. if (!fNameWellFormed) {
  145. status = STATUS_SXS_INVALID_ASSEMBLY_IDENTITY_ATTRIBUTE_NAME;
  146. }
  147. return status;
  148. }
  149. NTSTATUS
  150. RtlSxspValidateAssemblyIdentityAttributeValue(
  151. IN ULONG Flags,
  152. IN const WCHAR *wch,
  153. SIZE_T ValueCch
  154. )
  155. {
  156. if ((Flags & ~SXSP_VALIDATE_ASSEMBLY_IDENTITY_ATTRIBUTE_VALUE_FLAG_WILDCARDS_PERMITTED) != 0) {
  157. return STATUS_INVALID_PARAMETER;
  158. }
  159. return STATUS_SUCCESS;
  160. }
  161. NTSTATUS
  162. RtlSxsValidateAssemblyIdentityAttribute(
  163. ULONG Flags,
  164. PCASSEMBLY_IDENTITY_ATTRIBUTE Attribute
  165. )
  166. {
  167. NTSTATUS status = STATUS_SUCCESS;
  168. if ((Flags & ~(
  169. SXS_VALIDATE_ASSEMBLY_IDENTITY_ATTRIBUTE_FLAG_VALIDATE_NAMESPACE |
  170. SXS_VALIDATE_ASSEMBLY_IDENTITY_ATTRIBUTE_FLAG_VALIDATE_NAME |
  171. SXS_VALIDATE_ASSEMBLY_IDENTITY_ATTRIBUTE_FLAG_VALIDATE_VALUE |
  172. SXS_VALIDATE_ASSEMBLY_IDENTITY_ATTRIBUTE_FLAG_WILDCARDS_PERMITTED)) != 0) {
  173. return STATUS_INVALID_PARAMETER;
  174. }
  175. else if (Attribute == NULL) {
  176. return STATUS_INVALID_PARAMETER;
  177. }
  178. //
  179. // apply useful defaults. Note that by default, wildcards are not permitted.
  180. //
  181. if (Flags == 0)
  182. {
  183. Flags =
  184. SXS_VALIDATE_ASSEMBLY_IDENTITY_ATTRIBUTE_FLAG_VALIDATE_NAMESPACE |
  185. SXS_VALIDATE_ASSEMBLY_IDENTITY_ATTRIBUTE_FLAG_VALIDATE_NAME |
  186. SXS_VALIDATE_ASSEMBLY_IDENTITY_ATTRIBUTE_FLAG_VALIDATE_VALUE;
  187. }
  188. // No attribute flags defined or permitted at this time.
  189. if (Attribute->Flags != 0) {
  190. return STATUS_INVALID_PARAMETER;
  191. }
  192. if (Flags & SXS_VALIDATE_ASSEMBLY_IDENTITY_ATTRIBUTE_FLAG_VALIDATE_NAMESPACE) {
  193. status = RtlSxspValidateAssemblyIdentityAttributeNamespace(0, Attribute->Namespace, Attribute->NamespaceCch);
  194. if (!NT_SUCCESS(status)) {
  195. return status;
  196. }
  197. }
  198. if (Flags & SXS_VALIDATE_ASSEMBLY_IDENTITY_ATTRIBUTE_FLAG_VALIDATE_NAME) {
  199. status = RtlSxspValidateAssemblyIdentityAttributeName(0, Attribute->Name, Attribute->NameCch);
  200. if (!NT_SUCCESS(status)) {
  201. return status;
  202. }
  203. }
  204. if (Flags & SXS_VALIDATE_ASSEMBLY_IDENTITY_ATTRIBUTE_FLAG_VALIDATE_VALUE) {
  205. status = RtlSxspValidateAssemblyIdentityAttributeValue(
  206. (Flags & SXS_VALIDATE_ASSEMBLY_IDENTITY_ATTRIBUTE_FLAG_WILDCARDS_PERMITTED) ?
  207. SXSP_VALIDATE_ASSEMBLY_IDENTITY_ATTRIBUTE_VALUE_FLAG_WILDCARDS_PERMITTED : 0,
  208. Attribute->Value,
  209. Attribute->ValueCch);
  210. if (!NT_SUCCESS(status)) {
  211. return status;
  212. }
  213. }
  214. if ((Flags & SXS_VALIDATE_ASSEMBLY_IDENTITY_ATTRIBUTE_FLAG_VALIDATE_NAMESPACE) &&
  215. (Flags & SXS_VALIDATE_ASSEMBLY_IDENTITY_ATTRIBUTE_FLAG_VALIDATE_NAME) &&
  216. (Attribute->NamespaceCch == 0))
  217. {
  218. SIZE_T i;
  219. // There is only a small set of legal attribute names when the namespace is omitted.
  220. for (i=0; i<NUMBER_OF(s_rgLegalNamesNotInANamespace); i++)
  221. {
  222. if (Attribute->NameCch == s_rgLegalNamesNotInANamespace[i].Cch)
  223. {
  224. if (RtlCompareMemory(Attribute->Name, s_rgLegalNamesNotInANamespace[i].String, Attribute->NameCch * sizeof(WCHAR)) == 0)
  225. break;
  226. }
  227. }
  228. if (i == NUMBER_OF(s_rgLegalNamesNotInANamespace))
  229. {
  230. // Someone had an attribute on the <assemblyIdentity> element which was not in a namespace and
  231. // was not listed as a builtin attribute. Boom.
  232. return STATUS_SXS_INVALID_ASSEMBLY_IDENTITY_ATTRIBUTE;
  233. }
  234. }
  235. return STATUS_SUCCESS;
  236. }
  237. NTSTATUS
  238. RtlSxsHashAssemblyIdentityAttribute(
  239. ULONG Flags,
  240. PCASSEMBLY_IDENTITY_ATTRIBUTE Attribute,
  241. ULONG *HashOut
  242. )
  243. {
  244. NTSTATUS status;
  245. ULONG Hash = 0;
  246. ULONG TempHash = 0;
  247. if (HashOut != NULL)
  248. *HashOut = 0;
  249. if (Flags == 0)
  250. Flags = SXS_HASH_ASSEMBLY_IDENTITY_ATTRIBUTES_FLAG_HASH_NAMESPACE |
  251. SXS_HASH_ASSEMBLY_IDENTITY_ATTRIBUTES_FLAG_HASH_NAME |
  252. SXS_HASH_ASSEMBLY_IDENTITY_ATTRIBUTES_FLAG_HASH_VALUE;
  253. if ((Flags & ~(SXS_HASH_ASSEMBLY_IDENTITY_ATTRIBUTES_FLAG_HASH_NAMESPACE |
  254. SXS_HASH_ASSEMBLY_IDENTITY_ATTRIBUTES_FLAG_HASH_NAME |
  255. SXS_HASH_ASSEMBLY_IDENTITY_ATTRIBUTES_FLAG_HASH_VALUE)) != 0)
  256. {
  257. return STATUS_INVALID_PARAMETER;
  258. }
  259. // if hash value, must hash name, if hash name, must hash namespace
  260. if (((Flags & SXS_HASH_ASSEMBLY_IDENTITY_ATTRIBUTES_FLAG_HASH_VALUE) && (
  261. (Flags & SXS_HASH_ASSEMBLY_IDENTITY_ATTRIBUTES_FLAG_HASH_NAME) == 0)) ||
  262. ((Flags & SXS_HASH_ASSEMBLY_IDENTITY_ATTRIBUTES_FLAG_HASH_NAME) && (
  263. (Flags & SXS_HASH_ASSEMBLY_IDENTITY_ATTRIBUTES_FLAG_HASH_NAMESPACE) == 0))) {
  264. return STATUS_INVALID_PARAMETER;
  265. }
  266. if ((Attribute == NULL) || (HashOut == NULL)) {
  267. return STATUS_INVALID_PARAMETER;
  268. }
  269. if (Flags & SXS_HASH_ASSEMBLY_IDENTITY_ATTRIBUTES_FLAG_HASH_NAMESPACE) {
  270. status = RtlSxspHashUnicodeString(Attribute->Namespace, Attribute->NamespaceCch, &TempHash, TRUE);
  271. if (!NT_SUCCESS(status)) {
  272. return status;
  273. }
  274. Hash = TempHash;
  275. }
  276. if (Flags & SXS_HASH_ASSEMBLY_IDENTITY_ATTRIBUTES_FLAG_HASH_NAME) {
  277. status = RtlSxspHashUnicodeString(Attribute->Name, Attribute->NameCch, &TempHash, TRUE);
  278. if (!NT_SUCCESS(status)) {
  279. return status;
  280. }
  281. Hash = (Hash * 65599) + TempHash;
  282. }
  283. if (Flags & SXS_HASH_ASSEMBLY_IDENTITY_ATTRIBUTES_FLAG_HASH_VALUE) {
  284. status = RtlSxspHashUnicodeString(Attribute->Value, Attribute->ValueCch, &TempHash, TRUE);
  285. if (!NT_SUCCESS(status)) {
  286. return status;
  287. }
  288. Hash = (Hash * 65599) + TempHash;
  289. }
  290. *HashOut = Hash;
  291. return status;
  292. }
  293. NTSTATUS
  294. RtlSxspComputeInternalAssemblyIdentityAttributeBytesRequired(
  295. IN ULONG Flags,
  296. IN const WCHAR *Name,
  297. IN SIZE_T NameCch,
  298. IN const WCHAR *Value,
  299. IN SIZE_T ValueCch,
  300. OUT SIZE_T *BytesRequiredOut
  301. )
  302. {
  303. NTSTATUS status = STATUS_SUCCESS;
  304. SIZE_T BytesNeeded = 0;
  305. if (BytesRequiredOut != NULL)
  306. *BytesRequiredOut = 0;
  307. if ((Flags != 0) ||
  308. (BytesRequiredOut == NULL) ||
  309. ((NameCch != 0) && (Name == NULL)) ||
  310. ((ValueCch != 0) && (Value == NULL))) {
  311. return STATUS_INVALID_PARAMETER;
  312. }
  313. BytesNeeded = sizeof(INTERNAL_ASSEMBLY_IDENTITY_ATTRIBUTE);
  314. // Note that we do not account for the namespace length because namespaces are pooled
  315. // for the identity object and come from a separate allocation.
  316. if ((Name != NULL) && (NameCch != 0))
  317. BytesNeeded += ((NameCch + 1) * sizeof(WCHAR));
  318. if ((Value != NULL) && (ValueCch != 0))
  319. BytesNeeded += ((ValueCch + 1) * sizeof(WCHAR));
  320. *BytesRequiredOut = BytesNeeded;
  321. return status;
  322. }
  323. NTSTATUS
  324. RtlSxspComputeAssemblyIdentityAttributeBytesRequired(
  325. IN ULONG Flags,
  326. IN PCASSEMBLY_IDENTITY_ATTRIBUTE Source,
  327. OUT SIZE_T *BytesRequiredOut
  328. )
  329. {
  330. NTSTATUS status = STATUS_SUCCESS;
  331. SIZE_T BytesNeeded = 0;
  332. if (BytesRequiredOut != NULL)
  333. *BytesRequiredOut = 0;
  334. if ((Flags != 0) || (Source == NULL) || (BytesRequiredOut == NULL)) {
  335. return STATUS_INVALID_PARAMETER;
  336. }
  337. BytesNeeded = sizeof(ASSEMBLY_IDENTITY_ATTRIBUTE);
  338. // We do account for the namespace length here because we're presumably about
  339. // to copy into an ASSEMBLY_IDENTITY_ATTRIBUTE where the namespace isn't pooled.
  340. if (Source->NamespaceCch != 0)
  341. BytesNeeded += ((Source->NamespaceCch + 1) * sizeof(WCHAR));
  342. if (Source->NameCch != 0)
  343. BytesNeeded += ((Source->NameCch + 1) * sizeof(WCHAR));
  344. if (Source->ValueCch != 0)
  345. BytesNeeded += ((Source->ValueCch + 1) * sizeof(WCHAR));
  346. *BytesRequiredOut = BytesNeeded;
  347. return status;
  348. }
  349. NTSTATUS
  350. RtlSxspFindAssemblyIdentityNamespaceInArray(
  351. IN ULONG Flags,
  352. IN OUT PCASSEMBLY_IDENTITY_NAMESPACE **NamespacePointerArrayPtr,
  353. IN OUT ULONG *NamespaceArraySizePtr,
  354. IN OUT ULONG *NamespaceCountPtr,
  355. IN const WCHAR *Namespace,
  356. IN SIZE_T NamespaceCch,
  357. OUT PCASSEMBLY_IDENTITY_NAMESPACE *NamespaceOut
  358. )
  359. {
  360. NTSTATUS status = STATUS_SUCCESS;
  361. ULONG i, j;
  362. ULONG NamespaceHash = 0;
  363. ULONG NamespaceCount;
  364. PCASSEMBLY_IDENTITY_NAMESPACE *NamespacePointerArray;
  365. ULONG NewNamespaceArraySize = 0;
  366. PCASSEMBLY_IDENTITY_NAMESPACE *NewNamespacePointerArray = NULL;
  367. PCASSEMBLY_IDENTITY_NAMESPACE NamespacePointer = NULL;
  368. PCASSEMBLY_IDENTITY_NAMESPACE NewNamespacePointer = NULL;
  369. ULONG NamespaceArraySize = 0;
  370. LONG Comparison;
  371. if (NamespaceOut != NULL)
  372. *NamespaceOut = NULL;
  373. PARAMETER_CHECK((Flags & ~(SXSP_FIND_ASSEMBLY_IDENTITY_NAMESPACE_IN_ARRAY_FLAG_ADD_IF_NOT_FOUND)) == 0);
  374. PARAMETER_CHECK(NamespacePointerArrayPtr != NULL);
  375. PARAMETER_CHECK(NamespaceCountPtr != NULL);
  376. PARAMETER_CHECK(NamespaceArraySizePtr != NULL);
  377. PARAMETER_CHECK((NamespaceCch == 0) || (Namespace != NULL));
  378. NamespacePointerArray = *NamespacePointerArrayPtr;
  379. NamespaceCount = *NamespaceCountPtr;
  380. NamespaceArraySize = *NamespaceArraySizePtr;
  381. if (!NT_SUCCESS(status = RtlSxspHashUnicodeString(Namespace, NamespaceCch, &NamespaceHash, FALSE))) {
  382. return STATUS_INVALID_PARAMETER;
  383. }
  384. for (i=0; i<NamespaceCount; i++)
  385. {
  386. if (NamespaceHash <= NamespacePointerArray[i]->Hash)
  387. break;
  388. }
  389. // Loop through the duplicate hash values seeing if we have a match.
  390. while ((i < NamespaceCount) && (NamespacePointerArray[i]->Hash == NamespaceHash) && (NamespacePointerArray[i]->NamespaceCch == NamespaceCch))
  391. {
  392. NamespacePointer = NamespacePointerArray[i];
  393. Comparison = memcmp(Namespace, NamespacePointerArray[i]->Namespace, NamespaceCch * sizeof(WCHAR));
  394. if (Comparison == 0)
  395. break;
  396. NamespacePointer = NULL;
  397. i++;
  398. }
  399. if ((NamespacePointer == NULL) && (Flags & SXSP_FIND_ASSEMBLY_IDENTITY_NAMESPACE_IN_ARRAY_FLAG_ADD_IF_NOT_FOUND))
  400. {
  401. // We didn't find a match. Allocate a new one and push it into the array at the
  402. // appropriate location. If the namespace isn't null.
  403. if (NamespaceCch != 0)
  404. {
  405. status = RtlSxspAllocateAssemblyIdentityNamespace(0, Namespace, NamespaceCch, NamespaceHash, &NewNamespacePointer);
  406. if (!NT_SUCCESS(status)) {
  407. goto Exit;
  408. }
  409. // the "i" variable is where we want to insert this one.
  410. if (i >= NamespaceArraySize)
  411. {
  412. NewNamespaceArraySize = NamespaceArraySize + 8;
  413. NewNamespacePointerArray = (PCASSEMBLY_IDENTITY_NAMESPACE*)RtlAllocateHeap(
  414. RtlProcessHeap(),
  415. HEAP_ZERO_MEMORY,
  416. sizeof(ASSEMBLY_IDENTITY_NAMESPACE) * NewNamespaceArraySize);
  417. if (NewNamespacePointerArray == NULL) {
  418. status = STATUS_NO_MEMORY;
  419. goto Exit;
  420. }
  421. for (j=0; j<NamespaceCount; j++)
  422. NewNamespacePointerArray[j] = NamespacePointerArray[j];
  423. while (j < NewNamespaceArraySize)
  424. NewNamespacePointerArray[j++] = NULL;
  425. RtlFreeHeap(RtlProcessHeap(), 0, (PVOID)NamespacePointerArray);
  426. NamespacePointerArray = NULL;
  427. *NamespacePointerArrayPtr = NewNamespacePointerArray;
  428. *NamespaceArraySizePtr = NewNamespaceArraySize;
  429. NamespacePointerArray = NewNamespacePointerArray;
  430. NamespaceArraySize = NewNamespaceArraySize;
  431. NewNamespacePointerArray = NULL;
  432. NewNamespaceArraySize = 0;
  433. }
  434. ASSERT(i < NamespaceArraySize);
  435. for (j = NamespaceCount; j > i; j--)
  436. NamespacePointerArray[j] = NamespacePointerArray[j-1];
  437. ASSERT(j == i);
  438. NamespacePointerArray[i] = NewNamespacePointer;
  439. NamespacePointer = NewNamespacePointer;
  440. NewNamespacePointer = NULL;
  441. *NamespaceCountPtr = NamespaceCount + 1;
  442. }
  443. }
  444. if (NamespaceOut != NULL)
  445. *NamespaceOut = NamespacePointer;
  446. Exit:
  447. if (NewNamespacePointer != NULL)
  448. RtlSxspDeallocateAssemblyIdentityNamespace(NewNamespacePointer);
  449. if (NewNamespacePointerArray != NULL) {
  450. RtlFreeHeap(RtlProcessHeap(), 0, (PVOID)NewNamespacePointerArray);
  451. NewNamespacePointerArray = NULL;
  452. }
  453. return status;
  454. }
  455. NTSTATUS
  456. RtlSxspFindAssemblyIdentityNamespace(
  457. IN ULONG Flags,
  458. IN PASSEMBLY_IDENTITY AssemblyIdentity,
  459. IN const WCHAR *Namespace,
  460. IN SIZE_T NamespaceCch,
  461. OUT PCASSEMBLY_IDENTITY_NAMESPACE *NamespaceOut
  462. )
  463. {
  464. NTSTATUS status = STATUS_SUCCESS;
  465. PCASSEMBLY_IDENTITY_NAMESPACE NamespacePointer = NULL;
  466. if (NamespaceOut != NULL)
  467. *NamespaceOut = NULL;
  468. PARAMETER_CHECK((Flags & ~(SXSP_FIND_ASSEMBLY_IDENTITY_NAMESPACE_FLAG_ADD_IF_NOT_FOUND)) == 0);
  469. PARAMETER_CHECK(AssemblyIdentity != NULL);
  470. PARAMETER_CHECK(NamespaceOut != NULL);
  471. PARAMETER_CHECK((Namespace != NULL) || (NamespaceCch == 0));
  472. if (!NT_SUCCESS(status = RtlSxspValidateAssemblyIdentity(0, AssemblyIdentity))) {
  473. return status;
  474. }
  475. status = RtlSxspFindAssemblyIdentityNamespaceInArray(
  476. (Flags & SXSP_FIND_ASSEMBLY_IDENTITY_NAMESPACE_FLAG_ADD_IF_NOT_FOUND) ?
  477. SXSP_FIND_ASSEMBLY_IDENTITY_NAMESPACE_IN_ARRAY_FLAG_ADD_IF_NOT_FOUND : 0,
  478. &AssemblyIdentity->NamespacePointerArray,
  479. &AssemblyIdentity->NamespaceArraySize,
  480. &AssemblyIdentity->NamespaceCount,
  481. Namespace,
  482. NamespaceCch,
  483. &NamespacePointer);
  484. *NamespaceOut = NamespacePointer;
  485. return status;
  486. }
  487. NTSTATUS
  488. RtlSxspAllocateAssemblyIdentityNamespace(
  489. IN ULONG Flags,
  490. IN const WCHAR *Namespace,
  491. IN SIZE_T NamespaceCch,
  492. IN ULONG NamespaceHash,
  493. OUT PCASSEMBLY_IDENTITY_NAMESPACE *NamespaceOut
  494. )
  495. {
  496. NTSTATUS status = STATUS_SUCCESS;
  497. PASSEMBLY_IDENTITY_NAMESPACE NewNamespace = NULL;
  498. SIZE_T BytesRequired = 0;
  499. if (NamespaceOut != NULL)
  500. *NamespaceOut = NULL;
  501. PARAMETER_CHECK(Flags == 0);
  502. PARAMETER_CHECK(NamespaceOut != NULL);
  503. PARAMETER_CHECK((Namespace != NULL) || (NamespaceHash == 0));
  504. PARAMETER_CHECK((Namespace != NULL) || (NamespaceCch == 0));
  505. BytesRequired = sizeof(ASSEMBLY_IDENTITY_NAMESPACE);
  506. if (NamespaceCch != 0)
  507. BytesRequired += (NamespaceCch + 1) * sizeof(WCHAR);
  508. NewNamespace = (PASSEMBLY_IDENTITY_NAMESPACE)RtlAllocateHeap(
  509. RtlProcessHeap(),
  510. HEAP_ZERO_MEMORY,
  511. BytesRequired);
  512. if (NewNamespace == NULL) {
  513. status = STATUS_NO_MEMORY;
  514. goto Exit;
  515. }
  516. NewNamespace->Flags = 0;
  517. if (NamespaceCch != 0)
  518. {
  519. NewNamespace->Namespace = (PWSTR) (NewNamespace + 1);
  520. NewNamespace->NamespaceCch = NamespaceCch;
  521. memcpy(
  522. (PVOID) NewNamespace->Namespace,
  523. Namespace,
  524. NamespaceCch * sizeof(WCHAR));
  525. ((PWSTR) NewNamespace->Namespace) [NamespaceCch] = L'\0';
  526. NewNamespace->NamespaceCch = NamespaceCch;
  527. }
  528. else
  529. {
  530. NewNamespace->Namespace = NULL;
  531. NewNamespace->NamespaceCch = 0;
  532. }
  533. NewNamespace->Hash = NamespaceHash;
  534. *NamespaceOut = NewNamespace;
  535. NewNamespace = NULL;
  536. status = STATUS_SUCCESS;
  537. Exit:
  538. if (NewNamespace != NULL) {
  539. RtlFreeHeap(RtlProcessHeap(), 0, NewNamespace);
  540. NewNamespace = NULL;
  541. }
  542. return status;
  543. }
  544. VOID
  545. RtlSxspDeallocateAssemblyIdentityNamespace(
  546. IN PCASSEMBLY_IDENTITY_NAMESPACE Namespace
  547. )
  548. {
  549. ASSERT(Namespace != NULL);
  550. if (Namespace != NULL) {
  551. RtlFreeHeap(RtlProcessHeap(), 0, (PVOID)Namespace);
  552. Namespace = NULL;
  553. }
  554. }
  555. NTSTATUS
  556. RtlSxspPopulateInternalAssemblyIdentityAttribute(
  557. IN ULONG Flags,
  558. IN PCASSEMBLY_IDENTITY_NAMESPACE Namespace,
  559. IN const WCHAR *Name,
  560. IN SIZE_T NameCch,
  561. IN const WCHAR *Value,
  562. IN SIZE_T ValueCch,
  563. OUT PINTERNAL_ASSEMBLY_IDENTITY_ATTRIBUTE Destination
  564. )
  565. {
  566. NTSTATUS status = STATUS_SUCCESS;
  567. PVOID Cursor = NULL;
  568. PARAMETER_CHECK(Flags == 0);
  569. PARAMETER_CHECK(Destination != NULL);
  570. Destination->Attribute.Flags = 0;
  571. Destination->Namespace = Namespace;
  572. Cursor = (PVOID) (Destination + 1);
  573. if (Namespace != NULL)
  574. {
  575. Destination->Attribute.Namespace = Namespace->Namespace;
  576. Destination->Attribute.NamespaceCch = Namespace->NamespaceCch;
  577. }
  578. else
  579. {
  580. Destination->Attribute.Namespace = NULL;
  581. Destination->Attribute.NamespaceCch = 0;
  582. }
  583. if ((Name != NULL) && (NameCch != 0))
  584. {
  585. Destination->Attribute.Name = (PWSTR) Cursor;
  586. memcpy(
  587. Cursor,
  588. Name,
  589. NameCch * sizeof(WCHAR));
  590. ((PWSTR) Destination->Attribute.Name) [NameCch] = L'\0';
  591. Destination->Attribute.NameCch = NameCch;
  592. Cursor = (PVOID) (((ULONG_PTR) Cursor) + ((NameCch + 1) * sizeof(WCHAR)));
  593. }
  594. else
  595. {
  596. Destination->Attribute.Name = NULL;
  597. Destination->Attribute.NameCch = 0;
  598. }
  599. if ((Value != NULL) && (ValueCch != 0))
  600. {
  601. Destination->Attribute.Value = (PWSTR) Cursor;
  602. memcpy(
  603. Cursor,
  604. Value,
  605. ValueCch * sizeof(WCHAR));
  606. ((PWSTR) Destination->Attribute.Value)[ValueCch] = L'\0';
  607. Destination->Attribute.ValueCch = ValueCch;
  608. Cursor = (PVOID) (((ULONG_PTR) Cursor) + ((ValueCch + 1) * sizeof(WCHAR)));
  609. }
  610. else
  611. {
  612. Destination->Attribute.Value = NULL;
  613. Destination->Attribute.ValueCch = 0;
  614. }
  615. status = RtlSxsHashAssemblyIdentityAttribute(0, &Destination->Attribute, &Destination->WholeAttributeHash);
  616. if (!NT_SUCCESS(status)) {
  617. goto Exit;
  618. }
  619. status = RtlSxsHashAssemblyIdentityAttribute(SXS_HASH_ASSEMBLY_IDENTITY_ATTRIBUTES_FLAG_HASH_NAMESPACE | SXS_HASH_ASSEMBLY_IDENTITY_ATTRIBUTES_FLAG_HASH_NAME,
  620. &Destination->Attribute, &Destination->NamespaceAndNameHash);
  621. if (!NT_SUCCESS(status)) {
  622. goto Exit;
  623. }
  624. Exit:
  625. return status;
  626. }
  627. NTSTATUS
  628. RtlSxspAllocateInternalAssemblyIdentityAttribute(
  629. IN ULONG Flags,
  630. PCASSEMBLY_IDENTITY_NAMESPACE Namespace,
  631. IN const WCHAR *Name,
  632. IN SIZE_T NameCch,
  633. IN const WCHAR *Value,
  634. IN SIZE_T ValueCch,
  635. OUT PCINTERNAL_ASSEMBLY_IDENTITY_ATTRIBUTE *Destination
  636. )
  637. {
  638. NTSTATUS status = STATUS_SUCCESS;
  639. SIZE_T BytesNeeded = 0;
  640. PINTERNAL_ASSEMBLY_IDENTITY_ATTRIBUTE NewAttribute = NULL;
  641. if (Destination != NULL)
  642. *Destination = NULL;
  643. PARAMETER_CHECK(Flags == 0);
  644. PARAMETER_CHECK(Destination != NULL);
  645. PARAMETER_CHECK((NameCch == 0) || (Name != NULL));
  646. PARAMETER_CHECK((ValueCch == 0) || (Value != NULL));
  647. status = RtlSxspComputeInternalAssemblyIdentityAttributeBytesRequired(
  648. 0,
  649. Name,
  650. NameCch,
  651. Value,
  652. ValueCch,
  653. &BytesNeeded);
  654. if (!NT_SUCCESS(status)) {
  655. goto Exit;
  656. }
  657. NewAttribute = (PINTERNAL_ASSEMBLY_IDENTITY_ATTRIBUTE)RtlAllocateHeap(
  658. RtlProcessHeap(),
  659. 0,
  660. BytesNeeded);
  661. if (NewAttribute == NULL) {
  662. status = STATUS_NO_MEMORY;
  663. goto Exit;
  664. }
  665. status = RtlSxspPopulateInternalAssemblyIdentityAttribute(0, Namespace, Name, NameCch, Value, ValueCch, NewAttribute);
  666. if (!NT_SUCCESS(status)) {
  667. goto Exit;
  668. }
  669. *Destination = NewAttribute;
  670. NewAttribute = NULL;
  671. Exit:
  672. if (NewAttribute != NULL) {
  673. RtlFreeHeap(RtlProcessHeap(), 0, NewAttribute);
  674. NewAttribute = NULL;
  675. }
  676. return status;
  677. }
  678. VOID
  679. RtlSxspDeallocateInternalAssemblyIdentityAttribute(
  680. PCINTERNAL_ASSEMBLY_IDENTITY_ATTRIBUTE Attribute
  681. )
  682. {
  683. if (Attribute != NULL) {
  684. RtlFreeHeap(RtlProcessHeap(), 0, (PVOID)Attribute);
  685. Attribute = NULL;
  686. }
  687. }
  688. NTSTATUS
  689. RtlSxsCompareAssemblyIdentityAttributes(
  690. ULONG Flags,
  691. IN PCASSEMBLY_IDENTITY_ATTRIBUTE Attribute1,
  692. IN PCASSEMBLY_IDENTITY_ATTRIBUTE Attribute2,
  693. OUT ULONG *ComparisonResult
  694. )
  695. {
  696. NTSTATUS status = STATUS_SUCCESS;
  697. LONG Comparison = 0, Comparison1, Comparison2, Comparison3;
  698. if (Flags == 0)
  699. Flags = SXS_COMPARE_ASSEMBLY_IDENTITY_ATTRIBUTES_FLAG_COMPARE_NAMESPACE |
  700. SXS_COMPARE_ASSEMBLY_IDENTITY_ATTRIBUTES_FLAG_COMPARE_NAME |
  701. SXS_COMPARE_ASSEMBLY_IDENTITY_ATTRIBUTES_FLAG_COMPARE_VALUE;
  702. PARAMETER_CHECK((Flags & ~(SXS_COMPARE_ASSEMBLY_IDENTITY_ATTRIBUTES_FLAG_COMPARE_NAMESPACE |
  703. SXS_COMPARE_ASSEMBLY_IDENTITY_ATTRIBUTES_FLAG_COMPARE_NAME |
  704. SXS_COMPARE_ASSEMBLY_IDENTITY_ATTRIBUTES_FLAG_COMPARE_VALUE)) == 0);
  705. PARAMETER_CHECK(Attribute1 != NULL);
  706. PARAMETER_CHECK(Attribute2 != NULL);
  707. PARAMETER_CHECK(ComparisonResult != NULL);
  708. if ( Flags & SXS_COMPARE_ASSEMBLY_IDENTITY_ATTRIBUTES_FLAG_COMPARE_NAMESPACE) {
  709. Comparison1 = RtlSxspCompareStrings(Attribute1->Namespace, Attribute1->NamespaceCch, Attribute2->Namespace, Attribute2->NamespaceCch, FALSE);
  710. if (Comparison1 != 0) { // we have get the result
  711. Comparison = Comparison1 ;
  712. goto done;
  713. }
  714. }
  715. if ( Flags & SXS_COMPARE_ASSEMBLY_IDENTITY_ATTRIBUTES_FLAG_COMPARE_NAME) {
  716. Comparison2 = RtlSxspCompareStrings(Attribute1->Name, Attribute1->NameCch, Attribute2->Name, Attribute2->NameCch, FALSE);
  717. if (Comparison2 != 0) { // we have get the result
  718. Comparison = Comparison2;
  719. goto done;
  720. }
  721. }
  722. if ( Flags & SXS_COMPARE_ASSEMBLY_IDENTITY_ATTRIBUTES_FLAG_COMPARE_VALUE){
  723. Comparison3 = RtlSxspCompareStrings(Attribute1->Value, Attribute1->ValueCch, Attribute2->Value, Attribute2->ValueCch, TRUE);
  724. if (Comparison3 != 0) { // we have get the result
  725. Comparison = Comparison3;
  726. goto done;
  727. }
  728. }
  729. Comparison = 0;
  730. done:
  731. if (Comparison < 0)
  732. *ComparisonResult = SXS_COMPARE_ASSEMBLY_IDENTITY_ATTRIBUTES_COMPARISON_RESULT_LESS_THAN;
  733. else if (Comparison == 0)
  734. *ComparisonResult = SXS_COMPARE_ASSEMBLY_IDENTITY_ATTRIBUTES_COMPARISON_RESULT_EQUAL;
  735. else
  736. *ComparisonResult = SXS_COMPARE_ASSEMBLY_IDENTITY_ATTRIBUTES_COMPARISON_RESULT_GREATER_THAN;
  737. status = STATUS_SUCCESS;
  738. return status;
  739. }
  740. int
  741. __cdecl
  742. RtlSxspCompareInternalAttributesForQsort(
  743. const void *elem1,
  744. const void *elem2
  745. )
  746. {
  747. PCINTERNAL_ASSEMBLY_IDENTITY_ATTRIBUTE * p1 = (PCINTERNAL_ASSEMBLY_IDENTITY_ATTRIBUTE *)elem1;
  748. PCINTERNAL_ASSEMBLY_IDENTITY_ATTRIBUTE patt1 = *p1;
  749. PCINTERNAL_ASSEMBLY_IDENTITY_ATTRIBUTE * p2 = (PCINTERNAL_ASSEMBLY_IDENTITY_ATTRIBUTE *)elem2;
  750. PCINTERNAL_ASSEMBLY_IDENTITY_ATTRIBUTE patt2 = *p2;
  751. LONG Comparison;
  752. Comparison = RtlSxspCompareStrings(patt1->Attribute.Namespace, patt1->Attribute.NamespaceCch, patt2->Attribute.Namespace, patt2->Attribute.NamespaceCch, FALSE);
  753. if (Comparison == 0)
  754. Comparison = RtlSxspCompareStrings(patt1->Attribute.Name, patt1->Attribute.NameCch, patt2->Attribute.Name, patt2->Attribute.NameCch, FALSE);
  755. if (Comparison == 0)
  756. Comparison = RtlSxspCompareStrings(patt1->Attribute.Value, patt1->Attribute.ValueCch, patt2->Attribute.Value, patt2->Attribute.ValueCch, TRUE);
  757. return Comparison;
  758. }
  759. int
  760. __cdecl
  761. RtlSxspCompareULONGsForQsort(
  762. const void *elem1,
  763. const void *elem2
  764. )
  765. {
  766. ULONG *pul1 = (ULONG *) elem1;
  767. ULONG *pul2 = (ULONG *) elem2;
  768. return ((LONG) *pul1) - ((LONG) *pul2);
  769. }
  770. NTSTATUS
  771. RtlSxspCompareAssemblyIdentityAttributeLists(
  772. ULONG Flags,
  773. ULONG AttributeCount,
  774. PCINTERNAL_ASSEMBLY_IDENTITY_ATTRIBUTE *List1,
  775. PCINTERNAL_ASSEMBLY_IDENTITY_ATTRIBUTE *List2,
  776. ULONG *ComparisonResultOut
  777. )
  778. {
  779. NTSTATUS status = STATUS_SUCCESS;
  780. ULONG ComparisonResult = SXS_COMPARE_ASSEMBLY_IDENTITY_ATTRIBUTES_COMPARISON_RESULT_EQUAL;
  781. ULONG i;
  782. if ((Flags != 0) ||
  783. ((AttributeCount != 0) &&
  784. ((List1 == NULL) ||
  785. (List2 == NULL))) ||
  786. (ComparisonResultOut == NULL))
  787. {
  788. return STATUS_INVALID_PARAMETER;
  789. }
  790. for (i=0; i<AttributeCount; i++)
  791. {
  792. status = RtlSxsCompareAssemblyIdentityAttributes(0, &List1[i]->Attribute, &List2[i]->Attribute, &ComparisonResult);
  793. if (!NT_SUCCESS(status)) {
  794. return status;
  795. }
  796. if (ComparisonResult != SXS_COMPARE_ASSEMBLY_IDENTITY_ATTRIBUTES_COMPARISON_RESULT_EQUAL){
  797. break;
  798. }
  799. }
  800. *ComparisonResultOut = ComparisonResult;
  801. return status;
  802. }
  803. NTSTATUS
  804. RtlSxspHashInternalAssemblyIdentityAttributes(
  805. ULONG Flags,
  806. ULONG Count,
  807. PCINTERNAL_ASSEMBLY_IDENTITY_ATTRIBUTE *Attributes,
  808. ULONG *HashOut
  809. )
  810. {
  811. NTSTATUS status = STATUS_SUCCESS;
  812. ULONG Hash = 0;
  813. ULONG i;
  814. if (HashOut != NULL)
  815. *HashOut = 0;
  816. if ((Flags != 0) ||
  817. ((Count != 0) && (Attributes == NULL)) ||
  818. (HashOut == NULL))
  819. {
  820. return STATUS_INVALID_PARAMETER;
  821. }
  822. for (i=0; i<Count; i++)
  823. Hash = (Hash * 65599) + Attributes[i]->WholeAttributeHash;
  824. *HashOut = Hash;
  825. return STATUS_SUCCESS;
  826. }
  827. VOID SxspDbgPrintInternalAssemblyIdentityAttribute(ULONG dwflags, PCINTERNAL_ASSEMBLY_IDENTITY_ATTRIBUTE Attribute)
  828. {
  829. RtlSxspDbgPrintEx(dwflags, "Attribute: \n"
  830. "\tNamespace = %S, \tNamespaceCch = %d\n"
  831. "\tAttributeName = %S, \tAttributeNameCch = %d\n"
  832. "\tAttributeValue = %S, \tAttributeValueCch = %d\n\n",
  833. Attribute->Attribute.Namespace == NULL ? L"" : Attribute->Attribute.Namespace, Attribute->Attribute.NamespaceCch,
  834. Attribute->Attribute.Name == NULL ? L"" : Attribute->Attribute.Name, Attribute->Attribute.NameCch,
  835. Attribute->Attribute.Value == NULL ? L"" : Attribute->Attribute.Value, Attribute->Attribute.ValueCch);
  836. return;
  837. }
  838. VOID
  839. RtlSxspDbgPrintInternalAssemblyIdentityAttributes(ULONG dwflags, ULONG AttributeCount, PCINTERNAL_ASSEMBLY_IDENTITY_ATTRIBUTE const *Attributes)
  840. {
  841. ULONG i;
  842. for (i = 0; i < AttributeCount; i++) {
  843. RtlSxspDbgPrintInternalAssemblyIdentityAttribute(dwflags, Attributes[i]);
  844. }
  845. return;
  846. }
  847. VOID SxspDbgPrintAssemblyIdentity(ULONG dwflags, PCASSEMBLY_IDENTITY pAssemblyIdentity){
  848. if ( pAssemblyIdentity) {
  849. RtlSxspDbgPrintInternalAssemblyIdentityAttributes(dwflags, pAssemblyIdentity->AttributeCount,
  850. pAssemblyIdentity->AttributePointerArray);
  851. }
  852. return;
  853. }
  854. VOID SxspDbgPrintAssemblyIdentityAttribute(ULONG dwflags, PCASSEMBLY_IDENTITY_ATTRIBUTE Attribute)
  855. {
  856. RtlSxspDbgPrintEx(dwflags, "Attribute: \n"
  857. "\tNamespace = %S, \tNamespaceCch = %d\n"
  858. "\tAttributeName = %S, \tAttributeNameCch = %d\n"
  859. "\tAttributeValue = %S, \tAttributeValueCch = %d\n\n",
  860. Attribute->Namespace == NULL ? L"" : Attribute->Namespace, Attribute->NamespaceCch,
  861. Attribute->Name == NULL ? L"" : Attribute->Name, Attribute->NameCch,
  862. Attribute->Value == NULL ? L"" : Attribute->Value, Attribute->ValueCch);
  863. return;
  864. }
  865. VOID
  866. RtlSxspDbgPrintAssemblyIdentityAttributes(ULONG dwflags, ULONG AttributeCount, PCASSEMBLY_IDENTITY_ATTRIBUTE const *Attributes)
  867. {
  868. ULONG i;
  869. for (i=0;i<AttributeCount;i++){
  870. RtlSxspDbgPrintAssemblyIdentityAttribute(dwflags, Attributes[i]);
  871. }
  872. }
  873. NTSTATUS
  874. RtlSxsCreateAssemblyIdentity(
  875. ULONG Flags,
  876. ULONG Type,
  877. PASSEMBLY_IDENTITY *AssemblyIdentityOut,
  878. ULONG AttributeCount,
  879. PCASSEMBLY_IDENTITY_ATTRIBUTE const *Attributes
  880. )
  881. {
  882. NTSTATUS status = STATUS_SUCCESS;
  883. PASSEMBLY_IDENTITY AssemblyIdentity = NULL;
  884. PCINTERNAL_ASSEMBLY_IDENTITY_ATTRIBUTE *AttributePointerArray = NULL;
  885. ULONG AttributeArraySize = 0;
  886. SIZE_T BytesNeeded = 0;
  887. ULONG i;
  888. PCASSEMBLY_IDENTITY_NAMESPACE *NamespacePointerArray = NULL;
  889. ULONG NamespaceArraySize = 0;
  890. ULONG NamespaceCount = 0;
  891. #if DBG
  892. RtlSxspDbgPrintAssemblyIdentityAttributes(0x4, AttributeCount, Attributes);
  893. #endif
  894. if (AssemblyIdentityOut != NULL)
  895. *AssemblyIdentityOut = NULL;
  896. if (((Flags & ~(SXS_CREATE_ASSEMBLY_IDENTITY_FLAG_FREEZE)) != 0) ||
  897. ((Type != ASSEMBLY_IDENTITY_TYPE_DEFINITION) &&
  898. (Type != ASSEMBLY_IDENTITY_TYPE_REFERENCE) &&
  899. (Type != ASSEMBLY_IDENTITY_TYPE_WILDCARD)) ||
  900. ((AttributeCount != 0) && (Attributes == NULL)))
  901. {
  902. return STATUS_INVALID_PARAMETER;
  903. }
  904. //
  905. // Validate all our inputs before we get started...
  906. for (i=0; i<AttributeCount; i++)
  907. {
  908. status = RtlSxsValidateAssemblyIdentityAttribute(0, Attributes[i]);
  909. if (!NT_SUCCESS(status)) {
  910. return status;
  911. }
  912. }
  913. //
  914. // If we were told that this is a frozen assembly identity, we could be super-smart and
  915. // have a single allocation for the whole thing. Instead we'll leave that optimization
  916. // for a future maintainer. We'll at least be smart enough to allocate both the
  917. // assembly identity and the array of attribute pointers in a single whack tho'.
  918. //
  919. if (Flags & SXS_CREATE_ASSEMBLY_IDENTITY_FLAG_FREEZE)
  920. {
  921. AttributeArraySize = AttributeCount;
  922. }
  923. else
  924. {
  925. // For non-frozen identities, we'll add a rounding factor and round up for the number of
  926. // array elements.
  927. AttributeArraySize = (AttributeCount + (1 << ROUNDING_FACTOR_BITS)) & ~((1 << ROUNDING_FACTOR_BITS) - 1);
  928. }
  929. // allocate everything except namespace array
  930. BytesNeeded = sizeof(ASSEMBLY_IDENTITY) + (AttributeArraySize * sizeof(PINTERNAL_ASSEMBLY_IDENTITY_ATTRIBUTE));
  931. AssemblyIdentity = (PASSEMBLY_IDENTITY)RtlAllocateHeap(RtlProcessHeap(), HEAP_ZERO_MEMORY, BytesNeeded);
  932. if (AssemblyIdentity == NULL) {
  933. status = STATUS_NO_MEMORY;
  934. goto Exit;
  935. }
  936. if (AttributeArraySize != 0)
  937. {
  938. AttributePointerArray = (PCINTERNAL_ASSEMBLY_IDENTITY_ATTRIBUTE *) (AssemblyIdentity + 1);
  939. // Initialize the pointers so we can clean up non-NULL ones in the error path
  940. for (i=0; i<AttributeArraySize; i++)
  941. AttributePointerArray[i] = NULL;
  942. }
  943. for (i=0; i<AttributeCount; i++)
  944. {
  945. PCASSEMBLY_IDENTITY_NAMESPACE NamespacePointer = NULL;
  946. status = RtlSxspFindAssemblyIdentityNamespaceInArray(
  947. SXSP_FIND_ASSEMBLY_IDENTITY_NAMESPACE_IN_ARRAY_FLAG_ADD_IF_NOT_FOUND,
  948. &NamespacePointerArray,
  949. &NamespaceArraySize,
  950. &NamespaceCount,
  951. Attributes[i]->Namespace,
  952. Attributes[i]->NamespaceCch,
  953. &NamespacePointer);
  954. if (!NT_SUCCESS(status)) {
  955. goto Exit;
  956. }
  957. status = RtlSxspAllocateInternalAssemblyIdentityAttribute(
  958. 0,
  959. NamespacePointer,
  960. Attributes[i]->Name,
  961. Attributes[i]->NameCch,
  962. Attributes[i]->Value,
  963. Attributes[i]->ValueCch,
  964. &AttributePointerArray[i]);
  965. if (!NT_SUCCESS(status)) {
  966. goto Exit;
  967. }
  968. }
  969. // sort 'em.
  970. qsort((PVOID) AttributePointerArray, AttributeCount, sizeof(PINTERNAL_ASSEMBLY_IDENTITY_ATTRIBUTE), RtlSxspCompareInternalAttributesForQsort);
  971. AssemblyIdentity->AttributeArraySize = AttributeArraySize;
  972. AssemblyIdentity->AttributeCount = AttributeCount;
  973. AssemblyIdentity->AttributePointerArray = AttributePointerArray;
  974. AssemblyIdentity->NamespaceArraySize = NamespaceArraySize;
  975. AssemblyIdentity->NamespaceCount = NamespaceCount;
  976. AssemblyIdentity->NamespacePointerArray = NamespacePointerArray;
  977. AssemblyIdentity->Flags = 0;
  978. AssemblyIdentity->InternalFlags = ASSEMBLY_IDENTITY_INTERNAL_FLAG_NAMESPACE_POINTERS_IN_SEPARATE_ALLOCATION; // namespace is allocated sperately
  979. AssemblyIdentity->Type = Type;
  980. AssemblyIdentity->HashDirty = TRUE;
  981. AttributePointerArray = NULL;
  982. NamespacePointerArray = NULL;
  983. status = RtlSxspEnsureAssemblyIdentityHashIsUpToDate(0, AssemblyIdentity);
  984. if (!NT_SUCCESS(status)) {
  985. goto Exit;
  986. }
  987. if (Flags & SXS_CREATE_ASSEMBLY_IDENTITY_FLAG_FREEZE)
  988. AssemblyIdentity->Flags |= ASSEMBLY_IDENTITY_FLAG_FROZEN;
  989. *AssemblyIdentityOut = AssemblyIdentity;
  990. AssemblyIdentity = NULL;
  991. Exit:
  992. if ((AttributePointerArray != NULL) && (AttributeCount != 0))
  993. {
  994. for (i=0; i<AttributeCount; i++)
  995. RtlSxspDeallocateInternalAssemblyIdentityAttribute(AttributePointerArray[i]);
  996. }
  997. if ((NamespacePointerArray != NULL) && (NamespaceCount != 0))
  998. {
  999. for (i=0; i<NamespaceCount; i++)
  1000. RtlSxspDeallocateAssemblyIdentityNamespace(NamespacePointerArray[i]);
  1001. RtlFreeHeap(RtlProcessHeap(), 0, (PVOID)NamespacePointerArray);
  1002. }
  1003. if (AssemblyIdentity != NULL)
  1004. {
  1005. RtlFreeHeap(RtlProcessHeap(), 0, AssemblyIdentity);
  1006. }
  1007. return status;
  1008. }
  1009. NTSTATUS
  1010. RtlSxsFreezeAssemblyIdentity(
  1011. ULONG Flags,
  1012. PASSEMBLY_IDENTITY AssemblyIdentity
  1013. )
  1014. {
  1015. NTSTATUS status = STATUS_SUCCESS;
  1016. if ((Flags != 0) ||
  1017. (AssemblyIdentity == NULL))
  1018. {
  1019. status = STATUS_INVALID_PARAMETER;
  1020. goto Exit;
  1021. }
  1022. // We could possibly do something really interesting like realloc the whole thing but
  1023. // instead we'll just set the flag that stops future modifications.
  1024. AssemblyIdentity->Flags |= ASSEMBLY_IDENTITY_FLAG_FROZEN;
  1025. Exit:
  1026. return status;
  1027. }
  1028. VOID
  1029. RtlSxsDestroyAssemblyIdentity(
  1030. PASSEMBLY_IDENTITY AssemblyIdentity
  1031. )
  1032. {
  1033. ULONG i;
  1034. if (AssemblyIdentity == NULL)
  1035. return;
  1036. //
  1037. // An identity that's created frozen (whether created new or copied from an existing identity)
  1038. // uses a single allocation for everything. Only free the suballocations if we're not
  1039. // in this state.
  1040. //
  1041. if (!(AssemblyIdentity->InternalFlags & ASSEMBLY_IDENTITY_INTERNAL_FLAG_SINGLE_ALLOCATION_FOR_EVERYTHING))
  1042. {
  1043. const ULONG AttributeCount = AssemblyIdentity->AttributeCount;
  1044. PCINTERNAL_ASSEMBLY_IDENTITY_ATTRIBUTE *AttributePointerArray = AssemblyIdentity->AttributePointerArray;
  1045. const ULONG NamespaceCount = AssemblyIdentity->NamespaceCount;
  1046. PCASSEMBLY_IDENTITY_NAMESPACE *NamespacePointerArray = AssemblyIdentity->NamespacePointerArray;
  1047. for (i=0; i<AttributeCount; i++)
  1048. {
  1049. RtlSxspDeallocateInternalAssemblyIdentityAttribute((PINTERNAL_ASSEMBLY_IDENTITY_ATTRIBUTE) AttributePointerArray[i]);
  1050. AttributePointerArray[i] = NULL;
  1051. }
  1052. for (i=0; i<NamespaceCount; i++)
  1053. {
  1054. RtlSxspDeallocateAssemblyIdentityNamespace(NamespacePointerArray[i]);
  1055. NamespacePointerArray[i] = NULL;
  1056. }
  1057. if (AssemblyIdentity->InternalFlags & ASSEMBLY_IDENTITY_INTERNAL_FLAG_ATTRIBUTE_POINTERS_IN_SEPARATE_ALLOCATION)
  1058. {
  1059. RtlFreeHeap(RtlProcessHeap(), 0, (PVOID)AttributePointerArray);
  1060. AssemblyIdentity->AttributePointerArray = NULL;
  1061. }
  1062. if (AssemblyIdentity->InternalFlags & ASSEMBLY_IDENTITY_INTERNAL_FLAG_NAMESPACE_POINTERS_IN_SEPARATE_ALLOCATION)
  1063. {
  1064. RtlFreeHeap(RtlProcessHeap(), 0, (PVOID)NamespacePointerArray);
  1065. AssemblyIdentity->NamespacePointerArray = NULL;
  1066. }
  1067. }
  1068. RtlFreeHeap(RtlProcessHeap(), 0, (PVOID)AssemblyIdentity);
  1069. }
  1070. NTSTATUS
  1071. RtlSxspCopyInternalAssemblyIdentityAttributeOut(
  1072. ULONG Flags,
  1073. PCINTERNAL_ASSEMBLY_IDENTITY_ATTRIBUTE Attribute,
  1074. SIZE_T BufferSize,
  1075. PASSEMBLY_IDENTITY_ATTRIBUTE DestinationBuffer,
  1076. SIZE_T *BytesCopiedOrRequired
  1077. )
  1078. {
  1079. NTSTATUS status = STATUS_SUCCESS;
  1080. SIZE_T BytesRequired = 0;
  1081. PVOID Cursor;
  1082. if (BytesCopiedOrRequired != NULL)
  1083. *BytesCopiedOrRequired = 0;
  1084. PARAMETER_CHECK(Flags == 0);
  1085. PARAMETER_CHECK(Attribute != NULL);
  1086. PARAMETER_CHECK((BufferSize == 0) || (DestinationBuffer != NULL));
  1087. PARAMETER_CHECK((BufferSize != 0) || (BytesCopiedOrRequired != NULL));
  1088. status = RtlSxspComputeAssemblyIdentityAttributeBytesRequired(0, &Attribute->Attribute, &BytesRequired);
  1089. if (!NT_SUCCESS(status)) {
  1090. goto Exit;
  1091. }
  1092. if (BufferSize < BytesRequired)
  1093. {
  1094. if (BytesCopiedOrRequired != NULL)
  1095. *BytesCopiedOrRequired = BytesRequired;
  1096. status = STATUS_BUFFER_TOO_SMALL;
  1097. goto Exit;
  1098. }
  1099. // We must be in the clear...
  1100. DestinationBuffer->Flags = 0;
  1101. Cursor = (PVOID) (DestinationBuffer + 1);
  1102. if (Attribute->Attribute.NamespaceCch != 0)
  1103. {
  1104. DestinationBuffer->Namespace = (PWSTR) Cursor;
  1105. DestinationBuffer->NamespaceCch = Attribute->Attribute.NamespaceCch;
  1106. // We always internally store the strings with a null terminating character, so just copy
  1107. // it with the body of the string.
  1108. memcpy(
  1109. Cursor,
  1110. Attribute->Attribute.Namespace,
  1111. (Attribute->Attribute.NamespaceCch + 1) * sizeof(WCHAR));
  1112. Cursor = (PVOID) (((ULONG_PTR) Cursor) + ((Attribute->Attribute.NamespaceCch + 1) * sizeof(WCHAR)));
  1113. }
  1114. else
  1115. {
  1116. DestinationBuffer->Namespace = NULL;
  1117. DestinationBuffer->NamespaceCch = 0;
  1118. }
  1119. if (Attribute->Attribute.NameCch != 0)
  1120. {
  1121. DestinationBuffer->Name = (PWSTR) Cursor;
  1122. DestinationBuffer->NameCch = Attribute->Attribute.NameCch;
  1123. // We always internally store the strings with a null terminating character, so just copy
  1124. // it with the body of the string.
  1125. memcpy(
  1126. Cursor,
  1127. Attribute->Attribute.Name,
  1128. (Attribute->Attribute.NameCch + 1) * sizeof(WCHAR));
  1129. Cursor = (PVOID) (((ULONG_PTR) Cursor) + ((Attribute->Attribute.NameCch + 1) * sizeof(WCHAR)));
  1130. }
  1131. else
  1132. {
  1133. DestinationBuffer->Name = NULL;
  1134. DestinationBuffer->NameCch = 0;
  1135. }
  1136. if (Attribute->Attribute.ValueCch != 0)
  1137. {
  1138. DestinationBuffer->Value = (PWSTR) Cursor;
  1139. DestinationBuffer->ValueCch = Attribute->Attribute.ValueCch;
  1140. // We always internally store the strings with a null terminating character, so just copy
  1141. // it with the body of the string.
  1142. memcpy(
  1143. Cursor,
  1144. Attribute->Attribute.Value,
  1145. (Attribute->Attribute.ValueCch + 1) * sizeof(WCHAR));
  1146. Cursor = (PVOID) (((ULONG_PTR) Cursor) + ((Attribute->Attribute.ValueCch + 1) * sizeof(WCHAR)));
  1147. }
  1148. else
  1149. {
  1150. DestinationBuffer->Value = NULL;
  1151. DestinationBuffer->ValueCch = 0;
  1152. }
  1153. if (BytesCopiedOrRequired != NULL)
  1154. {
  1155. *BytesCopiedOrRequired = (((ULONG_PTR) Cursor) - ((ULONG_PTR) DestinationBuffer));
  1156. }
  1157. Exit:
  1158. return status;
  1159. }
  1160. NTSTATUS
  1161. RtlSxspLocateInternalAssemblyIdentityAttribute(
  1162. IN ULONG Flags,
  1163. IN PCASSEMBLY_IDENTITY AssemblyIdentity,
  1164. IN PCASSEMBLY_IDENTITY_ATTRIBUTE Attribute,
  1165. OUT PCINTERNAL_ASSEMBLY_IDENTITY_ATTRIBUTE *InternalAttributeOut,
  1166. OUT ULONG *LastIndexSearched OPTIONAL
  1167. )
  1168. {
  1169. NTSTATUS status = STATUS_SUCCESS;
  1170. ULONG i = 0;
  1171. ULONG AttributeCount = 0;
  1172. PCINTERNAL_ASSEMBLY_IDENTITY_ATTRIBUTE *AttributePointerArray = NULL;
  1173. ULONG ComparisonResult = SXS_COMPARE_ASSEMBLY_IDENTITY_ATTRIBUTES_COMPARISON_RESULT_LESS_THAN;
  1174. PCINTERNAL_ASSEMBLY_IDENTITY_ATTRIBUTE InternalAttribute = NULL;
  1175. ULONG LowIndex = 0;
  1176. ULONG HighIndexPlusOne = 0;
  1177. ULONG CompareAttributesFlags = 0;
  1178. if (InternalAttributeOut != NULL)
  1179. *InternalAttributeOut = NULL;
  1180. if (LastIndexSearched != NULL)
  1181. *LastIndexSearched = 0;
  1182. if (((Flags & ~(SXSP_LOCATE_INTERNAL_ASSEMBLY_IDENTITY_ATTRIBUTE_FLAG_MATCH_NAMESPACE |
  1183. SXSP_LOCATE_INTERNAL_ASSEMBLY_IDENTITY_ATTRIBUTE_FLAG_MATCH_NAME |
  1184. SXSP_LOCATE_INTERNAL_ASSEMBLY_IDENTITY_ATTRIBUTE_FLAG_MATCH_VALUE |
  1185. SXSP_LOCATE_INTERNAL_ASSEMBLY_IDENTITY_ATTRIBUTE_FLAG_NOT_FOUND_RETURNS_NULL)) != 0) ||
  1186. (AssemblyIdentity == NULL) ||
  1187. (Attribute == NULL) ||
  1188. (InternalAttributeOut == NULL))
  1189. {
  1190. status = STATUS_INVALID_PARAMETER;
  1191. goto Exit;
  1192. }
  1193. if ((Flags & SXSP_LOCATE_INTERNAL_ASSEMBLY_IDENTITY_ATTRIBUTE_FLAG_MATCH_NAME) &&
  1194. !(Flags & SXSP_LOCATE_INTERNAL_ASSEMBLY_IDENTITY_ATTRIBUTE_FLAG_MATCH_NAMESPACE))
  1195. {
  1196. status = STATUS_INVALID_PARAMETER;
  1197. goto Exit;
  1198. }
  1199. if ((Flags & SXSP_LOCATE_INTERNAL_ASSEMBLY_IDENTITY_ATTRIBUTE_FLAG_MATCH_VALUE) &&
  1200. !(Flags & SXSP_LOCATE_INTERNAL_ASSEMBLY_IDENTITY_ATTRIBUTE_FLAG_MATCH_NAME))
  1201. {
  1202. status = STATUS_INVALID_PARAMETER;
  1203. goto Exit;
  1204. }
  1205. if (Flags & SXSP_LOCATE_INTERNAL_ASSEMBLY_IDENTITY_ATTRIBUTE_FLAG_MATCH_NAMESPACE)
  1206. {
  1207. CompareAttributesFlags |= SXS_COMPARE_ASSEMBLY_IDENTITY_ATTRIBUTES_FLAG_COMPARE_NAMESPACE;
  1208. }
  1209. if (Flags & SXSP_LOCATE_INTERNAL_ASSEMBLY_IDENTITY_ATTRIBUTE_FLAG_MATCH_NAME)
  1210. {
  1211. CompareAttributesFlags |= SXS_COMPARE_ASSEMBLY_IDENTITY_ATTRIBUTES_FLAG_COMPARE_NAME;
  1212. }
  1213. if (Flags & SXSP_LOCATE_INTERNAL_ASSEMBLY_IDENTITY_ATTRIBUTE_FLAG_MATCH_VALUE)
  1214. {
  1215. CompareAttributesFlags |= SXS_COMPARE_ASSEMBLY_IDENTITY_ATTRIBUTES_FLAG_COMPARE_VALUE;
  1216. }
  1217. AttributeCount = AssemblyIdentity->AttributeCount;
  1218. AttributePointerArray = AssemblyIdentity->AttributePointerArray;
  1219. LowIndex = 0;
  1220. HighIndexPlusOne = AttributeCount;
  1221. i = 0;
  1222. while (LowIndex < HighIndexPlusOne)
  1223. {
  1224. i = (LowIndex + HighIndexPlusOne) / 2;
  1225. if (i == HighIndexPlusOne)
  1226. {
  1227. i = LowIndex;
  1228. }
  1229. status = RtlSxsCompareAssemblyIdentityAttributes(
  1230. CompareAttributesFlags,
  1231. Attribute,
  1232. &AttributePointerArray[i]->Attribute,
  1233. &ComparisonResult);
  1234. if (!NT_SUCCESS(status)) {
  1235. goto Exit;
  1236. }
  1237. if ((ComparisonResult != SXS_COMPARE_ASSEMBLY_IDENTITY_ATTRIBUTES_COMPARISON_RESULT_EQUAL) &&
  1238. (ComparisonResult != SXS_COMPARE_ASSEMBLY_IDENTITY_ATTRIBUTES_COMPARISON_RESULT_LESS_THAN) &&
  1239. (ComparisonResult != SXS_COMPARE_ASSEMBLY_IDENTITY_ATTRIBUTES_COMPARISON_RESULT_GREATER_THAN))
  1240. {
  1241. ASSERT(TRUE);
  1242. status = STATUS_INTERNAL_ERROR;
  1243. goto Exit;
  1244. }
  1245. if (ComparisonResult == SXS_COMPARE_ASSEMBLY_IDENTITY_ATTRIBUTES_COMPARISON_RESULT_EQUAL)
  1246. {
  1247. InternalAttribute = AttributePointerArray[i];
  1248. break;
  1249. }
  1250. else if (ComparisonResult == SXS_COMPARE_ASSEMBLY_IDENTITY_ATTRIBUTES_COMPARISON_RESULT_LESS_THAN)
  1251. {
  1252. if ( HighIndexPlusOne == i){
  1253. i--;
  1254. break;
  1255. }
  1256. else
  1257. HighIndexPlusOne = i;
  1258. }
  1259. else if (ComparisonResult == SXS_COMPARE_ASSEMBLY_IDENTITY_ATTRIBUTES_COMPARISON_RESULT_GREATER_THAN)
  1260. {
  1261. if ( LowIndex == i){
  1262. i++;
  1263. break;
  1264. }
  1265. else
  1266. LowIndex = i;
  1267. }
  1268. }
  1269. // If it's equal, there's no guarantee it's the first. Back up to find the first non-equal match
  1270. if (InternalAttribute != NULL)
  1271. {
  1272. while (i > 0)
  1273. {
  1274. status = RtlSxsCompareAssemblyIdentityAttributes(
  1275. CompareAttributesFlags,
  1276. Attribute,
  1277. &AttributePointerArray[i - 1]->Attribute,
  1278. &ComparisonResult);
  1279. if (!NT_SUCCESS(status)) {
  1280. return status;
  1281. }
  1282. if (ComparisonResult != SXS_COMPARE_ASSEMBLY_IDENTITY_ATTRIBUTES_COMPARISON_RESULT_EQUAL)
  1283. break;
  1284. i--;
  1285. InternalAttribute = AttributePointerArray[i];
  1286. }
  1287. }
  1288. if (InternalAttribute != NULL)
  1289. *InternalAttributeOut = InternalAttribute;
  1290. if (LastIndexSearched != NULL)
  1291. *LastIndexSearched = i;
  1292. // If we didn't find it, return ERROR_NOT_FOUND.
  1293. if (((Flags & SXSP_LOCATE_INTERNAL_ASSEMBLY_IDENTITY_ATTRIBUTE_FLAG_NOT_FOUND_RETURNS_NULL) == 0) &&
  1294. (InternalAttribute == NULL))
  1295. {
  1296. #if DBG
  1297. SxspDbgPrintAssemblyIdentityAttribute(0x4, Attribute);
  1298. #endif
  1299. status = STATUS_NOT_FOUND;
  1300. }
  1301. Exit:
  1302. return status;
  1303. }
  1304. NTSTATUS
  1305. RtlSxsInsertAssemblyIdentityAttribute(
  1306. ULONG Flags,
  1307. PASSEMBLY_IDENTITY AssemblyIdentity,
  1308. PCASSEMBLY_IDENTITY_ATTRIBUTE AssemblyIdentityAttribute
  1309. )
  1310. {
  1311. NTSTATUS status = STATUS_SUCCESS;
  1312. PCASSEMBLY_IDENTITY_NAMESPACE Namespace = NULL;
  1313. PCINTERNAL_ASSEMBLY_IDENTITY_ATTRIBUTE NewInternalAttribute = NULL;
  1314. PCINTERNAL_ASSEMBLY_IDENTITY_ATTRIBUTE InternalAttribute = NULL;
  1315. PCINTERNAL_ASSEMBLY_IDENTITY_ATTRIBUTE *NewAttributePointerArray = NULL;
  1316. ULONG NewAttributeArraySize = 0;
  1317. ULONG i;
  1318. ULONG LastIndexSearched;
  1319. PARAMETER_CHECK((Flags & ~(SXS_INSERT_ASSEMBLY_IDENTITY_ATTRIBUTE_FLAG_OVERWRITE_EXISTING)) == 0);
  1320. PARAMETER_CHECK(AssemblyIdentity != NULL);
  1321. PARAMETER_CHECK(AssemblyIdentityAttribute != NULL);
  1322. status = RtlSxspValidateAssemblyIdentity(0, AssemblyIdentity);
  1323. if (!NT_SUCCESS(status)) {
  1324. goto Exit;
  1325. }
  1326. status = RtlSxsValidateAssemblyIdentityAttribute(0, AssemblyIdentityAttribute);
  1327. if (!NT_SUCCESS(status)) {
  1328. goto Exit;
  1329. }
  1330. if ((AssemblyIdentity->Flags & ASSEMBLY_IDENTITY_FLAG_FROZEN) != 0) {
  1331. ASSERT(TRUE);
  1332. status = STATUS_INTERNAL_ERROR;
  1333. goto Exit;
  1334. }
  1335. status = RtlSxspFindAssemblyIdentityNamespace(
  1336. SXSP_FIND_ASSEMBLY_IDENTITY_NAMESPACE_FLAG_ADD_IF_NOT_FOUND,
  1337. AssemblyIdentity,
  1338. AssemblyIdentityAttribute->Namespace,
  1339. AssemblyIdentityAttribute->NamespaceCch,
  1340. &Namespace);
  1341. if (!NT_SUCCESS(status)) {
  1342. goto Exit;
  1343. }
  1344. // Let's see if we can find it.
  1345. status = RtlSxspLocateInternalAssemblyIdentityAttribute(
  1346. SXSP_LOCATE_INTERNAL_ASSEMBLY_IDENTITY_ATTRIBUTE_FLAG_MATCH_NAMESPACE |
  1347. SXSP_LOCATE_INTERNAL_ASSEMBLY_IDENTITY_ATTRIBUTE_FLAG_MATCH_NAME |
  1348. SXSP_LOCATE_INTERNAL_ASSEMBLY_IDENTITY_ATTRIBUTE_FLAG_NOT_FOUND_RETURNS_NULL,
  1349. AssemblyIdentity,
  1350. AssemblyIdentityAttribute,
  1351. &InternalAttribute,
  1352. &LastIndexSearched);
  1353. if (!NT_SUCCESS(status)) {
  1354. goto Exit;
  1355. }
  1356. if (InternalAttribute != NULL)
  1357. {
  1358. if (Flags & SXS_INSERT_ASSEMBLY_IDENTITY_ATTRIBUTE_FLAG_OVERWRITE_EXISTING)
  1359. {
  1360. // Ok, replace it!
  1361. status = RtlSxspAllocateInternalAssemblyIdentityAttribute(
  1362. 0,
  1363. Namespace,
  1364. AssemblyIdentityAttribute->Name,
  1365. AssemblyIdentityAttribute->NameCch,
  1366. AssemblyIdentityAttribute->Value,
  1367. AssemblyIdentityAttribute->ValueCch,
  1368. &NewInternalAttribute);
  1369. if (!NT_SUCCESS(status)) {
  1370. goto Exit;
  1371. }
  1372. AssemblyIdentity->AttributePointerArray[LastIndexSearched] = NewInternalAttribute;
  1373. NewInternalAttribute = NULL;
  1374. RtlSxspDeallocateInternalAssemblyIdentityAttribute(InternalAttribute);
  1375. }
  1376. else
  1377. {
  1378. // We actually wanted it to fail...
  1379. status = STATUS_DUPLICATE_NAME;
  1380. goto Exit;
  1381. }
  1382. }
  1383. else
  1384. {
  1385. status = RtlSxspAllocateInternalAssemblyIdentityAttribute(
  1386. 0,
  1387. Namespace,
  1388. AssemblyIdentityAttribute->Name,
  1389. AssemblyIdentityAttribute->NameCch,
  1390. AssemblyIdentityAttribute->Value,
  1391. AssemblyIdentityAttribute->ValueCch,
  1392. &NewInternalAttribute);
  1393. if (!NT_SUCCESS(status)) {
  1394. goto Exit;
  1395. }
  1396. // Now we have it and we even know where to put it. Grow the array if we need to.
  1397. if (AssemblyIdentity->AttributeCount == AssemblyIdentity->AttributeArraySize)
  1398. {
  1399. NewAttributeArraySize = AssemblyIdentity->AttributeCount + 8;
  1400. NewAttributePointerArray = (PCINTERNAL_ASSEMBLY_IDENTITY_ATTRIBUTE *) RtlAllocateHeap(
  1401. RtlProcessHeap(),
  1402. HEAP_ZERO_MEMORY,
  1403. sizeof(PCINTERNAL_ASSEMBLY_IDENTITY_ATTRIBUTE) * NewAttributeArraySize);
  1404. if (NewAttributePointerArray == NULL) {
  1405. status = STATUS_NO_MEMORY;
  1406. goto Exit;
  1407. }
  1408. // Instead of copying the data and then shuffling, we'll copy the stuff before the insertion
  1409. // point, fill in at the insertion point and then copy the rest.
  1410. for (i=0; i<LastIndexSearched; i++)
  1411. NewAttributePointerArray[i] = AssemblyIdentity->AttributePointerArray[i];
  1412. for (i=LastIndexSearched; i<AssemblyIdentity->AttributeCount; i++)
  1413. NewAttributePointerArray[i+1] = AssemblyIdentity->AttributePointerArray[i];
  1414. if (AssemblyIdentity->AttributePointerArray != NULL)
  1415. RtlFreeHeap(RtlProcessHeap(), 0, (PVOID)AssemblyIdentity->AttributePointerArray);
  1416. AssemblyIdentity->AttributePointerArray = NewAttributePointerArray;
  1417. AssemblyIdentity->AttributeArraySize = NewAttributeArraySize;
  1418. }
  1419. else
  1420. {
  1421. // The array's big enough; shuffle the ending part of the array down one.
  1422. for (i=AssemblyIdentity->AttributeCount; i>LastIndexSearched; i--)
  1423. AssemblyIdentity->AttributePointerArray[i] = AssemblyIdentity->AttributePointerArray[i-1];
  1424. }
  1425. AssemblyIdentity->AttributePointerArray[LastIndexSearched] = NewInternalAttribute;
  1426. NewInternalAttribute = NULL;
  1427. AssemblyIdentity->AttributeCount++;
  1428. }
  1429. AssemblyIdentity->HashDirty = TRUE;
  1430. Exit:
  1431. if (NewInternalAttribute != NULL)
  1432. RtlSxspDeallocateInternalAssemblyIdentityAttribute(NewInternalAttribute);
  1433. return status;
  1434. }
  1435. NTSTATUS
  1436. RtlSxsRemoveAssemblyIdentityAttributesByOrdinal(
  1437. ULONG Flags,
  1438. PASSEMBLY_IDENTITY AssemblyIdentity,
  1439. ULONG Ordinal,
  1440. ULONG Count
  1441. )
  1442. {
  1443. NTSTATUS status = STATUS_SUCCESS;
  1444. ULONG AttributeCount;
  1445. ULONG i;
  1446. PCINTERNAL_ASSEMBLY_IDENTITY_ATTRIBUTE *AttributePointerArray = NULL;
  1447. ULONG StopIndex;
  1448. if ((Flags != 0) ||
  1449. (AssemblyIdentity == NULL) ||
  1450. (Count == 0))
  1451. {
  1452. status = STATUS_INVALID_PARAMETER;
  1453. goto Exit;
  1454. }
  1455. status = RtlSxspValidateAssemblyIdentity(0, AssemblyIdentity);
  1456. if (!NT_SUCCESS(status)) {
  1457. goto Exit;
  1458. }
  1459. AttributeCount = AssemblyIdentity->AttributeCount;
  1460. AttributePointerArray = AssemblyIdentity->AttributePointerArray;
  1461. // We can't delete outside the bounds of [0 .. AttributeCount - 1]
  1462. if ((Ordinal >= AssemblyIdentity->AttributeCount) ||
  1463. (Count > AssemblyIdentity->AttributeCount) ||
  1464. ((Ordinal + Count) > AssemblyIdentity->AttributeCount))
  1465. {
  1466. status = STATUS_INVALID_PARAMETER;
  1467. goto Exit;
  1468. }
  1469. StopIndex = Ordinal + Count;
  1470. // Let's get rid of them! We're going to go through the array twice; it's somewhat
  1471. // unnecessary but in the first run, we're going to NULL out any attribute pointers
  1472. // that we're removing and clean up namespaces that aren't in use any more. On the
  1473. // second pass, we'll compress the array down. This is somewhat wasteful, but
  1474. // in the alternative case, we end up doing "Count" shifts down of the tail of the array.
  1475. for (i = Ordinal; i < StopIndex; i++)
  1476. {
  1477. PCASSEMBLY_IDENTITY_NAMESPACE Namespace = NULL;
  1478. PCINTERNAL_ASSEMBLY_IDENTITY_ATTRIBUTE InternalAttribute = AttributePointerArray[i];
  1479. // If this is the last use of this namespace, keep track of it so we can
  1480. // clean it up.
  1481. if ((i + 1) < AttributeCount)
  1482. {
  1483. // If the next attribute has a different namespace, there's some possibility
  1484. // that this attribute was the last one that used it, so we'll delete the
  1485. // attribute then ask to get rid of the namespace if there aren't any more
  1486. // attributes using it.
  1487. if (AttributePointerArray[i+1]->Namespace != InternalAttribute->Namespace)
  1488. Namespace = InternalAttribute->Namespace;
  1489. }
  1490. AttributePointerArray[i] = NULL;
  1491. RtlSxspDeallocateInternalAssemblyIdentityAttribute(InternalAttribute);
  1492. if (Namespace != NULL)
  1493. RtlSxspCleanUpAssemblyIdentityNamespaceIfNotReferenced(0, AssemblyIdentity, Namespace);
  1494. }
  1495. for (i = StopIndex; i < AttributeCount; i++)
  1496. {
  1497. AttributePointerArray[i - Count] = AttributePointerArray[i];
  1498. AttributePointerArray[i] = NULL;
  1499. }
  1500. AssemblyIdentity->AttributeCount -= Count;
  1501. AssemblyIdentity->HashDirty = TRUE;
  1502. Exit:
  1503. return status;
  1504. }
  1505. NTSTATUS
  1506. RtlSxsFindAssemblyIdentityAttribute(
  1507. ULONG Flags,
  1508. PCASSEMBLY_IDENTITY AssemblyIdentity,
  1509. PCASSEMBLY_IDENTITY_ATTRIBUTE Attribute,
  1510. ULONG *OrdinalOut,
  1511. ULONG *CountOut OPTIONAL
  1512. )
  1513. {
  1514. NTSTATUS status = STATUS_SUCCESS;
  1515. ULONG ValidateAttributeFlags = 0;
  1516. ULONG LocateAttributeFlags = 0;
  1517. ULONG CompareAttributesFlags = 0;
  1518. ULONG Ordinal;
  1519. PCINTERNAL_ASSEMBLY_IDENTITY_ATTRIBUTE InternalAttribute = NULL;
  1520. ULONG AttributeCount = 0;
  1521. PCINTERNAL_ASSEMBLY_IDENTITY_ATTRIBUTE *AttributePointerArray = NULL;
  1522. ULONG i;
  1523. ULONG ComparisonResult;
  1524. if (OrdinalOut != NULL)
  1525. *OrdinalOut = 0;
  1526. if (CountOut != NULL)
  1527. *CountOut = 0;
  1528. if (((Flags & ~(SXS_FIND_ASSEMBLY_IDENTITY_ATTRIBUTE_FLAG_MATCH_NAMESPACE |
  1529. SXS_FIND_ASSEMBLY_IDENTITY_ATTRIBUTE_FLAG_MATCH_NAME |
  1530. SXS_FIND_ASSEMBLY_IDENTITY_ATTRIBUTE_FLAG_MATCH_VALUE |
  1531. SXS_FIND_ASSEMBLY_IDENTITY_ATTRIBUTE_FLAG_NOT_FOUND_SUCCEEDS)) != 0) ||
  1532. (AssemblyIdentity == NULL) ||
  1533. (Attribute == NULL))
  1534. {
  1535. status = STATUS_INVALID_PARAMETER;
  1536. goto Exit;
  1537. }
  1538. if (Flags == 0)
  1539. Flags = SXS_FIND_ASSEMBLY_IDENTITY_ATTRIBUTE_FLAG_MATCH_NAMESPACE |
  1540. SXS_FIND_ASSEMBLY_IDENTITY_ATTRIBUTE_FLAG_MATCH_NAME |
  1541. SXS_FIND_ASSEMBLY_IDENTITY_ATTRIBUTE_FLAG_MATCH_VALUE;
  1542. PARAMETER_CHECK(
  1543. ((Flags & SXS_FIND_ASSEMBLY_IDENTITY_ATTRIBUTE_FLAG_MATCH_NAME) == 0) ||
  1544. ((Flags & SXS_FIND_ASSEMBLY_IDENTITY_ATTRIBUTE_FLAG_MATCH_NAMESPACE) != 0));
  1545. PARAMETER_CHECK((Flags &
  1546. (SXS_FIND_ASSEMBLY_IDENTITY_ATTRIBUTE_FLAG_MATCH_VALUE |
  1547. SXS_FIND_ASSEMBLY_IDENTITY_ATTRIBUTE_FLAG_MATCH_NAME |
  1548. SXS_FIND_ASSEMBLY_IDENTITY_ATTRIBUTE_FLAG_MATCH_NAMESPACE)) != 0);
  1549. PARAMETER_CHECK(
  1550. ((Flags & SXS_FIND_ASSEMBLY_IDENTITY_ATTRIBUTE_FLAG_MATCH_VALUE) == 0) ||
  1551. (((Flags & SXS_FIND_ASSEMBLY_IDENTITY_ATTRIBUTE_FLAG_MATCH_NAME) != 0) &&
  1552. ((Flags & SXS_FIND_ASSEMBLY_IDENTITY_ATTRIBUTE_FLAG_MATCH_NAMESPACE) != 0)));
  1553. status = RtlSxspValidateAssemblyIdentity(0, AssemblyIdentity);
  1554. if (!NT_SUCCESS(status)) {
  1555. goto Exit;
  1556. }
  1557. ValidateAttributeFlags = 0;
  1558. if (Flags & SXS_FIND_ASSEMBLY_IDENTITY_ATTRIBUTE_FLAG_MATCH_NAMESPACE)
  1559. {
  1560. ValidateAttributeFlags |= SXS_VALIDATE_ASSEMBLY_IDENTITY_ATTRIBUTE_FLAG_VALIDATE_NAMESPACE;
  1561. LocateAttributeFlags |= SXSP_LOCATE_INTERNAL_ASSEMBLY_IDENTITY_ATTRIBUTE_FLAG_MATCH_NAMESPACE;
  1562. CompareAttributesFlags |= SXS_COMPARE_ASSEMBLY_IDENTITY_ATTRIBUTES_FLAG_COMPARE_NAMESPACE;
  1563. }
  1564. if (Flags & SXS_FIND_ASSEMBLY_IDENTITY_ATTRIBUTE_FLAG_MATCH_NAME)
  1565. {
  1566. ValidateAttributeFlags |= SXS_VALIDATE_ASSEMBLY_IDENTITY_ATTRIBUTE_FLAG_VALIDATE_NAME;
  1567. LocateAttributeFlags |= SXSP_LOCATE_INTERNAL_ASSEMBLY_IDENTITY_ATTRIBUTE_FLAG_MATCH_NAME;
  1568. CompareAttributesFlags |= SXS_COMPARE_ASSEMBLY_IDENTITY_ATTRIBUTES_FLAG_COMPARE_NAME;
  1569. }
  1570. if (Flags & SXS_FIND_ASSEMBLY_IDENTITY_ATTRIBUTE_FLAG_MATCH_VALUE)
  1571. {
  1572. ValidateAttributeFlags |= SXS_VALIDATE_ASSEMBLY_IDENTITY_ATTRIBUTE_FLAG_VALIDATE_VALUE;
  1573. LocateAttributeFlags |= SXSP_LOCATE_INTERNAL_ASSEMBLY_IDENTITY_ATTRIBUTE_FLAG_MATCH_VALUE;
  1574. CompareAttributesFlags |= SXS_COMPARE_ASSEMBLY_IDENTITY_ATTRIBUTES_FLAG_COMPARE_VALUE;
  1575. }
  1576. status = RtlSxsValidateAssemblyIdentityAttribute(ValidateAttributeFlags, Attribute);
  1577. if (!NT_SUCCESS(status)) {
  1578. goto Exit;
  1579. }
  1580. if (Flags & SXS_FIND_ASSEMBLY_IDENTITY_ATTRIBUTE_FLAG_NOT_FOUND_SUCCEEDS)
  1581. LocateAttributeFlags |= SXSP_LOCATE_INTERNAL_ASSEMBLY_IDENTITY_ATTRIBUTE_FLAG_NOT_FOUND_RETURNS_NULL;
  1582. status = RtlSxspLocateInternalAssemblyIdentityAttribute(LocateAttributeFlags, AssemblyIdentity, Attribute, &InternalAttribute, &Ordinal);
  1583. if (!NT_SUCCESS(status)) {
  1584. goto Exit;
  1585. }
  1586. if ((InternalAttribute == NULL) && !(Flags & SXS_FIND_ASSEMBLY_IDENTITY_ATTRIBUTE_FLAG_NOT_FOUND_SUCCEEDS)) {
  1587. ASSERT(FALSE);
  1588. status = STATUS_INTERNAL_ERROR;
  1589. goto Exit;
  1590. }
  1591. if (InternalAttribute != NULL)
  1592. {
  1593. if (CountOut != NULL)
  1594. {
  1595. // We found it, now let's look for how many matches we have. We'll separately handle the three levels
  1596. // of specificity:
  1597. AttributeCount = AssemblyIdentity->AttributeCount;
  1598. AttributePointerArray = AssemblyIdentity->AttributePointerArray;
  1599. for (i = (Ordinal + 1); i<AttributeCount; i++)
  1600. {
  1601. PCINTERNAL_ASSEMBLY_IDENTITY_ATTRIBUTE AnotherInternalAttribute = AttributePointerArray[i];
  1602. if (Flags & SXS_FIND_ASSEMBLY_IDENTITY_ATTRIBUTE_FLAG_MATCH_VALUE)
  1603. {
  1604. // If the hashes are different, we're certainly different.
  1605. if (AnotherInternalAttribute->WholeAttributeHash != InternalAttribute->WholeAttributeHash)
  1606. break;
  1607. }
  1608. else if (Flags & SXS_FIND_ASSEMBLY_IDENTITY_ATTRIBUTE_FLAG_MATCH_NAME)
  1609. {
  1610. // If the hashes are different, we're certainly different.
  1611. if (AnotherInternalAttribute->NamespaceAndNameHash != InternalAttribute->NamespaceAndNameHash)
  1612. break;
  1613. }
  1614. else
  1615. {
  1616. if ((Flags & SXS_FIND_ASSEMBLY_IDENTITY_ATTRIBUTE_FLAG_MATCH_NAMESPACE) == 0) {
  1617. status = STATUS_INTERNAL_ERROR;
  1618. goto Exit;
  1619. }
  1620. // If the hashes are different, we're certainly different.
  1621. if (AnotherInternalAttribute->Namespace->Hash != InternalAttribute->Namespace->Hash)
  1622. break;
  1623. }
  1624. status = RtlSxsCompareAssemblyIdentityAttributes(
  1625. CompareAttributesFlags,
  1626. Attribute,
  1627. &AnotherInternalAttribute->Attribute,
  1628. &ComparisonResult);
  1629. if (!NT_SUCCESS(status)) {
  1630. goto Exit;
  1631. }
  1632. if (ComparisonResult != SXS_COMPARE_ASSEMBLY_IDENTITY_ATTRIBUTES_COMPARISON_RESULT_EQUAL)
  1633. break;
  1634. }
  1635. *CountOut = i - Ordinal;
  1636. }
  1637. if (OrdinalOut != NULL)
  1638. *OrdinalOut = Ordinal;
  1639. }
  1640. Exit:
  1641. return status;
  1642. }
  1643. VOID
  1644. RtlSxspCleanUpAssemblyIdentityNamespaceIfNotReferenced(
  1645. ULONG Flags,
  1646. PASSEMBLY_IDENTITY AssemblyIdentity,
  1647. PCASSEMBLY_IDENTITY_NAMESPACE Namespace
  1648. )
  1649. {
  1650. ASSERT(AssemblyIdentity != NULL);
  1651. ASSERT(Flags == 0);
  1652. if ((AssemblyIdentity != NULL) && (Namespace != NULL))
  1653. {
  1654. const ULONG AttributeCount = AssemblyIdentity->AttributeCount;
  1655. PCINTERNAL_ASSEMBLY_IDENTITY_ATTRIBUTE *AttributePointerArray = AssemblyIdentity->AttributePointerArray;
  1656. ULONG i;
  1657. // We could do some sort of binary search here based on the text string of the namespace since
  1658. // the attributes are sorted first on namespace, but my guess is that a single text comparison
  1659. // is worth a few dozen simple pointer comparisons, so the attribute array would have to be
  1660. // pretty darned huge for the k1*O(log n) to be faster than the k2*(n) algorithm to actually
  1661. // dominate.
  1662. for (i=0; i<AttributeCount; i++)
  1663. {
  1664. const PCINTERNAL_ASSEMBLY_IDENTITY_ATTRIBUTE InternalAttribute = AttributePointerArray[i];
  1665. if ((InternalAttribute != NULL) &&
  1666. (InternalAttribute->Namespace == Namespace))
  1667. break;
  1668. }
  1669. if (i == AttributeCount)
  1670. {
  1671. // We fell through; it must be orphaned.
  1672. const ULONG NamespaceCount = AssemblyIdentity->NamespaceCount;
  1673. PCASSEMBLY_IDENTITY_NAMESPACE *NamespacePointerArray = AssemblyIdentity->NamespacePointerArray;
  1674. for (i=0; i<NamespaceCount; i++)
  1675. {
  1676. if (NamespacePointerArray[i] == Namespace)
  1677. break;
  1678. }
  1679. // This assert should only fire if the namespace isn't actually present.
  1680. ASSERT(i != NamespaceCount);
  1681. if (i != NamespaceCount)
  1682. {
  1683. ULONG j;
  1684. for (j=(i+1); j<NamespaceCount; j++)
  1685. NamespacePointerArray[j-1] = NamespacePointerArray[j];
  1686. NamespacePointerArray[NamespaceCount - 1] = NULL;
  1687. RtlSxspDeallocateAssemblyIdentityNamespace(Namespace);
  1688. AssemblyIdentity->NamespaceCount--;
  1689. }
  1690. }
  1691. }
  1692. AssemblyIdentity->HashDirty = TRUE;
  1693. }
  1694. NTSTATUS
  1695. RtlSxsGetAssemblyIdentityAttributeByOrdinal(
  1696. ULONG Flags,
  1697. PCASSEMBLY_IDENTITY AssemblyIdentity,
  1698. ULONG Ordinal,
  1699. SIZE_T BufferSize,
  1700. PASSEMBLY_IDENTITY_ATTRIBUTE AssemblyIdentityAttributeBuffer,
  1701. SIZE_T *BytesWrittenOrRequired
  1702. )
  1703. {
  1704. NTSTATUS status = STATUS_SUCCESS;
  1705. if (BytesWrittenOrRequired != NULL)
  1706. *BytesWrittenOrRequired = 0;
  1707. PARAMETER_CHECK(Flags == 0);
  1708. PARAMETER_CHECK(AssemblyIdentity != NULL);
  1709. PARAMETER_CHECK((BufferSize == 0) || (AssemblyIdentityAttributeBuffer != NULL));
  1710. PARAMETER_CHECK((BufferSize != 0) || (BytesWrittenOrRequired != NULL));
  1711. PARAMETER_CHECK(Ordinal < AssemblyIdentity->AttributeCount);
  1712. status = RtlSxspCopyInternalAssemblyIdentityAttributeOut(
  1713. 0,
  1714. AssemblyIdentity->AttributePointerArray[Ordinal],
  1715. BufferSize,
  1716. AssemblyIdentityAttributeBuffer,
  1717. BytesWrittenOrRequired);
  1718. return status;
  1719. }
  1720. NTSTATUS
  1721. RtlSxsDuplicateAssemblyIdentity(
  1722. ULONG Flags,
  1723. PCASSEMBLY_IDENTITY Source,
  1724. PASSEMBLY_IDENTITY *Destination
  1725. )
  1726. {
  1727. NTSTATUS status = STATUS_SUCCESS;
  1728. PASSEMBLY_IDENTITY NewIdentity = NULL;
  1729. ULONG CreateAssemblyIdentityFlags = 0;
  1730. if (Destination != NULL)
  1731. *Destination = NULL;
  1732. PARAMETER_CHECK((Flags & ~(SXS_DUPLICATE_ASSEMBLY_IDENTITY_FLAG_FREEZE | SXS_DUPLICATE_ASSEMBLY_IDENTITY_FLAG_ALLOW_NULL)) == 0);
  1733. PARAMETER_CHECK(((Flags & SXS_DUPLICATE_ASSEMBLY_IDENTITY_FLAG_ALLOW_NULL) != 0) || (Source != NULL));
  1734. PARAMETER_CHECK(Destination != NULL);
  1735. if (Flags & SXS_DUPLICATE_ASSEMBLY_IDENTITY_FLAG_FREEZE)
  1736. CreateAssemblyIdentityFlags |= SXS_CREATE_ASSEMBLY_IDENTITY_FLAG_FREEZE;
  1737. //
  1738. // We depend on the Attribute field being first in the internal attribute
  1739. // structure below where we callously cast a pointer to an array of
  1740. // internal attribute pointers into a pointer to an array of attribute pointers.
  1741. //
  1742. ASSERT(FIELD_OFFSET(INTERNAL_ASSEMBLY_IDENTITY_ATTRIBUTE, Attribute) == 0);
  1743. if (Source != NULL)
  1744. {
  1745. status = RtlSxsCreateAssemblyIdentity(
  1746. CreateAssemblyIdentityFlags,
  1747. Source->Type,
  1748. &NewIdentity,
  1749. Source->AttributeCount,
  1750. (PASSEMBLY_IDENTITY_ATTRIBUTE const *) Source->AttributePointerArray);
  1751. }
  1752. *Destination = NewIdentity;
  1753. NewIdentity = NULL;
  1754. if (NewIdentity != NULL)
  1755. RtlSxsDestroyAssemblyIdentity(NewIdentity);
  1756. return status;
  1757. }
  1758. NTSTATUS
  1759. RtlSxsQueryAssemblyIdentityInformation(
  1760. ULONG Flags,
  1761. PCASSEMBLY_IDENTITY AssemblyIdentity,
  1762. PVOID Buffer,
  1763. SIZE_T BufferSize,
  1764. ASSEMBLY_IDENTITY_INFORMATION_CLASS AssemblyIdentityInformationClass
  1765. )
  1766. {
  1767. NTSTATUS status = STATUS_SUCCESS;
  1768. PARAMETER_CHECK(Flags == 0);
  1769. PARAMETER_CHECK(AssemblyIdentity != NULL);
  1770. PARAMETER_CHECK(AssemblyIdentityInformationClass == AssemblyIdentityBasicInformation);
  1771. status = RtlSxspValidateAssemblyIdentity(0, AssemblyIdentity);
  1772. if (!NT_SUCCESS(status)) {
  1773. return status;
  1774. }
  1775. switch (AssemblyIdentityInformationClass)
  1776. {
  1777. case AssemblyIdentityBasicInformation: {
  1778. PASSEMBLY_IDENTITY_BASIC_INFORMATION BasicBuffer = NULL;
  1779. if (BufferSize < sizeof(ASSEMBLY_IDENTITY_BASIC_INFORMATION)) {
  1780. status = STATUS_BUFFER_TOO_SMALL;
  1781. goto Exit;
  1782. }
  1783. BasicBuffer = (PASSEMBLY_IDENTITY_BASIC_INFORMATION) Buffer;
  1784. BasicBuffer->Flags = AssemblyIdentity->Flags;
  1785. BasicBuffer->Type = AssemblyIdentity->Type;
  1786. BasicBuffer->AttributeCount = AssemblyIdentity->AttributeCount;
  1787. BasicBuffer->Hash = AssemblyIdentity->Hash;
  1788. break;
  1789. }
  1790. }
  1791. Exit:
  1792. return status;
  1793. }
  1794. NTSTATUS
  1795. RtlSxsEnumerateAssemblyIdentityAttributes(
  1796. IN ULONG Flags,
  1797. IN PCASSEMBLY_IDENTITY AssemblyIdentity,
  1798. IN PCASSEMBLY_IDENTITY_ATTRIBUTE Attribute,
  1799. IN PRTLSXS_ASSEMBLY_IDENTITY_ATTRIBUTE_ENUMERATION_ROUTINE EnumerationRoutine,
  1800. IN PVOID Context
  1801. )
  1802. {
  1803. NTSTATUS status = STATUS_SUCCESS;
  1804. ULONG AttributeCount;
  1805. ULONG i;
  1806. ULONG ValidateFlags = 0;
  1807. ULONG CompareFlags = 0;
  1808. if (((Flags & ~(SXS_ENUMERATE_ASSEMBLY_IDENTITY_ATTRIBUTES_FLAG_MATCH_NAMESPACE |
  1809. SXS_ENUMERATE_ASSEMBLY_IDENTITY_ATTRIBUTES_FLAG_MATCH_NAME |
  1810. SXS_ENUMERATE_ASSEMBLY_IDENTITY_ATTRIBUTES_FLAG_MATCH_VALUE)) != 0) ||
  1811. ((Flags & (SXS_ENUMERATE_ASSEMBLY_IDENTITY_ATTRIBUTES_FLAG_MATCH_NAMESPACE |
  1812. SXS_ENUMERATE_ASSEMBLY_IDENTITY_ATTRIBUTES_FLAG_MATCH_NAME |
  1813. SXS_ENUMERATE_ASSEMBLY_IDENTITY_ATTRIBUTES_FLAG_MATCH_VALUE)) &&
  1814. (Attribute == NULL)) ||
  1815. (AssemblyIdentity == NULL) ||
  1816. (EnumerationRoutine == NULL))
  1817. {
  1818. status = STATUS_INVALID_PARAMETER;
  1819. goto Exit;
  1820. }
  1821. status = RtlSxspValidateAssemblyIdentity(0, AssemblyIdentity);
  1822. if (!NT_SUCCESS(status)) {
  1823. goto Exit;
  1824. }
  1825. if (Flags & SXS_ENUMERATE_ASSEMBLY_IDENTITY_ATTRIBUTES_FLAG_MATCH_NAMESPACE)
  1826. {
  1827. ValidateFlags |= SXS_VALIDATE_ASSEMBLY_IDENTITY_ATTRIBUTE_FLAG_VALIDATE_NAMESPACE;
  1828. CompareFlags |= SXS_COMPARE_ASSEMBLY_IDENTITY_ATTRIBUTES_FLAG_COMPARE_NAMESPACE;
  1829. }
  1830. if (Flags & SXS_ENUMERATE_ASSEMBLY_IDENTITY_ATTRIBUTES_FLAG_MATCH_NAME)
  1831. {
  1832. ValidateFlags |= SXS_VALIDATE_ASSEMBLY_IDENTITY_ATTRIBUTE_FLAG_VALIDATE_NAME;
  1833. CompareFlags |= SXS_COMPARE_ASSEMBLY_IDENTITY_ATTRIBUTES_FLAG_COMPARE_NAME;
  1834. }
  1835. if (Flags & SXS_ENUMERATE_ASSEMBLY_IDENTITY_ATTRIBUTES_FLAG_MATCH_VALUE)
  1836. {
  1837. ValidateFlags |= SXS_VALIDATE_ASSEMBLY_IDENTITY_ATTRIBUTE_FLAG_VALIDATE_VALUE;
  1838. CompareFlags |= SXS_COMPARE_ASSEMBLY_IDENTITY_ATTRIBUTES_FLAG_COMPARE_VALUE;
  1839. }
  1840. status = RtlSxsValidateAssemblyIdentityAttribute(ValidateFlags, Attribute);
  1841. if (!NT_SUCCESS(status)) {
  1842. goto Exit;
  1843. }
  1844. AttributeCount = AssemblyIdentity->AttributeCount;
  1845. for (i=0; i<AttributeCount; i++)
  1846. {
  1847. PCASSEMBLY_IDENTITY_ATTRIBUTE CandidateAttribute = &AssemblyIdentity->AttributePointerArray[i]->Attribute;
  1848. ULONG ComparisonResult = 0;
  1849. if (CompareFlags != 0)
  1850. {
  1851. status = RtlSxsCompareAssemblyIdentityAttributes(
  1852. CompareFlags,
  1853. Attribute,
  1854. CandidateAttribute,
  1855. &ComparisonResult);
  1856. if (!NT_SUCCESS(status)) {
  1857. goto Exit;
  1858. }
  1859. // If they're not equal, skip it!
  1860. if (ComparisonResult != SXS_COMPARE_ASSEMBLY_IDENTITY_ATTRIBUTES_COMPARISON_RESULT_EQUAL)
  1861. continue;
  1862. }
  1863. (*EnumerationRoutine)(
  1864. AssemblyIdentity,
  1865. CandidateAttribute,
  1866. Context);
  1867. }
  1868. Exit:
  1869. return status;
  1870. }
  1871. NTSTATUS
  1872. RtlSxspIsInternalAssemblyIdentityAttribute(
  1873. IN ULONG Flags,
  1874. IN PCINTERNAL_ASSEMBLY_IDENTITY_ATTRIBUTE Attribute,
  1875. IN const WCHAR *Namespace,
  1876. IN SIZE_T NamespaceCch,
  1877. IN const WCHAR *Name,
  1878. IN SIZE_T NameCch,
  1879. OUT BOOLEAN *EqualsOut
  1880. )
  1881. {
  1882. NTSTATUS status = STATUS_SUCCESS;
  1883. if (EqualsOut != NULL)
  1884. *EqualsOut = FALSE;
  1885. PARAMETER_CHECK(Flags == 0);
  1886. PARAMETER_CHECK(Attribute != NULL);
  1887. PARAMETER_CHECK(Namespace != NULL || NamespaceCch == 0);
  1888. PARAMETER_CHECK(Name != NULL || NameCch == 0);
  1889. PARAMETER_CHECK(EqualsOut != NULL);
  1890. if ((NamespaceCch == Attribute->Attribute.NamespaceCch) &&
  1891. (NameCch == Attribute->Attribute.NameCch))
  1892. {
  1893. if ((NamespaceCch == 0) ||
  1894. (memcmp(Attribute->Attribute.Namespace, Namespace, NamespaceCch * sizeof(WCHAR)) == 0))
  1895. {
  1896. if ((NameCch == 0) ||
  1897. (memcmp(Attribute->Attribute.Name, Name, NameCch * sizeof(WCHAR)) == 0))
  1898. {
  1899. *EqualsOut = TRUE;
  1900. }
  1901. }
  1902. }
  1903. return status;
  1904. }
  1905. NTSTATUS
  1906. RtlSxspHashUnicodeString(
  1907. PCWSTR String,
  1908. SIZE_T cch,
  1909. PULONG HashValue,
  1910. BOOLEAN fCaseInsensitive
  1911. )
  1912. {
  1913. NTSTATUS status = STATUS_SUCCESS;
  1914. ULONG TmpHashValue = 0;
  1915. if (HashValue != NULL)
  1916. *HashValue = 0;
  1917. if (HashValue == NULL) {
  1918. return STATUS_INVALID_PARAMETER;
  1919. }
  1920. //
  1921. // Note that if you change this implementation, you have to have the implementation inside
  1922. // ntdll change to match it. Since that's hard and will affect everyone else in the world,
  1923. // DON'T CHANGE THIS ALGORITHM NO MATTER HOW GOOD OF AN IDEA IT SEEMS TO BE! This isn't the
  1924. // most perfect hashing algorithm, but its stability is critical to being able to match
  1925. // previously persisted hash values.
  1926. //
  1927. if (fCaseInsensitive)
  1928. {
  1929. while (cch-- != 0)
  1930. {
  1931. WCHAR Char = *String++;
  1932. TmpHashValue = (TmpHashValue * 65599) + RtlUpcaseUnicodeChar(Char);
  1933. }
  1934. }
  1935. else
  1936. {
  1937. while (cch-- != 0)
  1938. TmpHashValue = (TmpHashValue * 65599) + *String++;
  1939. }
  1940. *HashValue = TmpHashValue;
  1941. return STATUS_SUCCESS;
  1942. }