Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

2514 lines
86 KiB

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