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.

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