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.

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