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.

513 lines
18 KiB

  1. #if !defined(_FUSION_ID_IDP_H_INCLUDED_)
  2. #define _FUSION_ID_IDP_H_INCLUDED_
  3. /*++
  4. Copyright (c) 1989 Microsoft Corporation
  5. Module Name:
  6. idp.h
  7. Abstract:
  8. private definitions for assembly identity
  9. Author:
  10. Michael Grier (MGrier) 7/27/2000
  11. Revision History:
  12. --*/
  13. #pragma once
  14. #include "debmacro.h"
  15. #include "fusiontrace.h"
  16. #include "fusionhashstring.h"
  17. #include "fusionheap.h"
  18. #include "util.h"
  19. #include <sxstypes.h>
  20. #include <sxsapi.h>
  21. //
  22. // Power of two to which to round the number of allocated attribute
  23. // pointers.
  24. //
  25. #define ROUNDING_FACTOR_BITS (3)
  26. #define WILDCARD_CHAR '*'
  27. //
  28. // Note! Do not change this algorithm lightly. Encoded identities stored in the
  29. // filesystem contain hashes using it. Actually, just do not change it.
  30. //
  31. #define HASH_ALGORITHM HASH_STRING_ALGORITHM_X65599
  32. typedef struct _ASSEMBLY_IDENTITY_NAMESPACE {
  33. ULONG Hash;
  34. DWORD Flags;
  35. SIZE_T NamespaceCch;
  36. const WCHAR *Namespace;
  37. } ASSEMBLY_IDENTITY_NAMESPACE, *PASSEMBLY_IDENTITY_NAMESPACE;
  38. typedef const ASSEMBLY_IDENTITY_NAMESPACE *PCASSEMBLY_IDENTITY_NAMESPACE;
  39. //
  40. // Internal-use ASSEMBLY_IDENTITY_ATTRIBUTE struct that
  41. // also contains the hash of the attribute definition.
  42. //
  43. typedef struct _INTERNAL_ASSEMBLY_IDENTITY_ATTRIBUTE {
  44. // NOTE!!! It is very important that the Attribute member appear first in this struct;
  45. // there are several places in the code that make this assumption. If it is not true,
  46. // the code will break!
  47. // Note also that the Attribute's namespace string is actually allocated in common
  48. // for all attributes with the same namespace.
  49. ASSEMBLY_IDENTITY_ATTRIBUTE Attribute;
  50. PCASSEMBLY_IDENTITY_NAMESPACE Namespace;
  51. ULONG NamespaceAndNameHash;
  52. ULONG WholeAttributeHash;
  53. } INTERNAL_ASSEMBLY_IDENTITY_ATTRIBUTE, *PINTERNAL_ASSEMBLY_IDENTITY_ATTRIBUTE;
  54. C_ASSERT(FIELD_OFFSET(INTERNAL_ASSEMBLY_IDENTITY_ATTRIBUTE, Attribute) == 0);
  55. typedef const INTERNAL_ASSEMBLY_IDENTITY_ATTRIBUTE *PCINTERNAL_ASSEMBLY_IDENTITY_ATTRIBUTE;
  56. #define ASSEMBLY_IDENTITY_INTERNAL_FLAG_ATTRIBUTE_POINTERS_IN_SEPARATE_ALLOCATION (0x00000001)
  57. #define ASSEMBLY_IDENTITY_INTERNAL_FLAG_SINGLE_ALLOCATION_FOR_EVERYTHING (0x00000002)
  58. #define ASSEMBLY_IDENTITY_INTERNAL_FLAG_NAMESPACE_POINTERS_IN_SEPARATE_ALLOCATION (0x00000004)
  59. //
  60. // Revelation of the ASSEMBLY_IDENTITY struct:
  61. //
  62. typedef struct _ASSEMBLY_IDENTITY {
  63. DWORD Flags;
  64. ULONG InternalFlags;
  65. ULONG Type;
  66. ULONG Hash;
  67. ULONG AttributeCount;
  68. ULONG AttributeArraySize; // preallocated a little larger so that we don't have to keep growing
  69. ULONG NamespaceCount;
  70. ULONG NamespaceArraySize;
  71. BOOL HashDirty;
  72. PCINTERNAL_ASSEMBLY_IDENTITY_ATTRIBUTE *AttributePointerArray;
  73. PCASSEMBLY_IDENTITY_NAMESPACE *NamespacePointerArray;
  74. } ASSEMBLY_IDENTITY;
  75. //
  76. // Header for encoded/serialized assembly identities:
  77. //
  78. #define ENCODED_ASSEMBLY_IDENTITY_HEADER_MAGIC ((ULONG) 'dIAE')
  79. //
  80. // Encoded assembly identity layout:
  81. //
  82. // ENCODED_ASSEMBLY_IDENTITY_HEADER
  83. // <AttributeCount hashes of the attributes, sorted by the hash value>
  84. // <NamespaceCount ENCODED_ASSEMBLY_IDENTITY_NAMESPACE_HEADER headers, each
  85. // followed by the unicode namespace value>
  86. // <AttributeCount ENCODED_ASSEMBLY_IDENTITY_ATTRIBUTE_HEADER headers, each
  87. // followed by the unicode attribute name and value>
  88. //
  89. //
  90. // e.g.
  91. //
  92. // <begin ENCODED_ASSEMBLY_IDENTITY_HEADER>
  93. // 00000000: 00000038 HeaderSize == sizeof(ENCODED_ASSEMBLY_IDENTITY_HEADER)
  94. // 00000004: 'EAId' Magic (ENCODED_ASSEMBLY_IDENTITY_HEADER_MAGIC)
  95. // 00000008: 0000014C TotalSize
  96. // 0000000C: 00000000 Flags
  97. // 00000010: 00000001 Type (1 = ASSEMBLY_IDENTITY_TYPE_DEFINITION)
  98. // 00000014: 00000000 EncodingFlags
  99. // 00000018: 00000001 HashAlgorithm (1 = HASH_STRING_ALGORITHM_X65599)
  100. // 0000001C: ???????? Logical hash value of entire identity based on hash algorithm
  101. // (algorithm described in more detail below...)
  102. // 00000020: 00000003 AttributeCount
  103. // 00000024: 00000002 NamespaceCount
  104. // 00000028: 00000000 ReservedMustBeZero1
  105. // 0000002C: 00000000 ReservedMustBeZero2
  106. // 00000030: 00000000 00000000 ReservedMustBeZero3
  107. // 00000038: 00000000 00000000 ReservedMustBeZero4
  108. // <end ENCODED_ASSEMBLY_IDENTITY_HEADER>
  109. // <begin sorted attribute hash list>
  110. // 00000040: xxxxxxxx hash of attribute #1
  111. // 00000044: yyyyyyyy hash of attribute #0 - note that yyyyyyyy >= xxxxxxxx
  112. // 00000048: zzzzzzzz hash of attribute #2 - note that zzzzzzzz >= yyyyyyyy
  113. // <end sorted attribute hash list>
  114. // <begin namespace length list>
  115. // 0000004C: 00000015 length (in Unicode chars) of namespace #1 - "http://www.amazon.com" - 21 chars = 0x00000015
  116. // 00000050: 00000018 length (in Unicode chars) of namespace #2 - "http://www.microsoft.com" - 24 chars = 0x00000018
  117. // <end namespace length list>
  118. // <begin attribute headers>
  119. // <begin ENCODED_ASSEMBLY_IDENTITY_ATTRIBUTE_HEADER>
  120. // 00000054: 00000001 NamespaceIndex: 1 (http://www.amazon.com)
  121. // 00000058: 00000004 Name length ("name" - 4 chars = 0x00000004)
  122. // 0000005C: 00000006 Value length ("foobar" - 6 chars = 0x00000006)
  123. // <end ENCODED_ASSEMBLY_IDENTITY_ATTRIBUTE_HEADER>
  124. // <begin ENCODED_ASSEMBLY_IDENTITY_ATTRIBUTE_HEADER>
  125. // 00000060: 00000002 NamespaceIndex: 2 (http://www.microsoft.com)
  126. // 00000064: 00000004 Name length ("guid" - 4 chars = 0x00000004)
  127. // 00000068: 00000026 Value length ("{xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx}" - 38 chars = 0x00000026)
  128. // <end ENCODED_ASSEMBLY_IDENTITY_ATTRIBUTE_HEADER>
  129. // <begin ENCODED_ASSEMBLY_IDENTITY_ATTRIBUTE_HEADER>
  130. // 0000006C: 00000002 NamespaceIndex: 2 (http://www.microsoft.com)
  131. // 00000070: 00000004 Name length ("type" - 4 chars = 0x00000004)
  132. // 00000074: 00000005 Value length ("win32" - 5 chars = 0x00000005)
  133. // <end ENCODED_ASSEMBLY_IDENTITY_ATTRIBUTE_HEADER>
  134. // <end attribute headers>
  135. // <begin namespace strings>
  136. // 00000078: "http://www.amazon.com"
  137. // 000000A2: "http://www.microsoft.com"
  138. // <end namespace strings>
  139. // <begin attribute values - names and values for each attribute in series>
  140. // 000000D2: "name"
  141. // 000000DA: "foobar"
  142. // 000000E6: "guid"
  143. // 000000EE: "{xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx}"
  144. // 0000013A: "type"
  145. // 00000142: "win32"
  146. // <end attribute values>
  147. // 0000014C:
  148. //
  149. // Computing the whole identity hash:
  150. //
  151. // The hash of the entire encoded identity is not the hash of the binary form, but
  152. // rather is a combination of the hashes for the various components.
  153. //
  154. // For any Unicode character string, its hash is computed according to HashAlgorithm.
  155. // Currently this must be HASH_STRING_ALGORITHM_X65599 which is a multiply-and-
  156. // accumulate algorithm, implemented essentially as follows:
  157. //
  158. // HashValue = 0;
  159. // for (i=0; i<Chars; i++)
  160. // HashValue = (HashValue * 65599) + OptionalToUpper(String[i]);
  161. //
  162. // Note that the characters are converted to upper case. This is somewhat in
  163. // conflict with the Unicode recommendation to convert to lower case for case
  164. // insensitive operations, but it is what the rest of the Windows NT system
  165. // does, so consistency matters more than doing the "right thing".
  166. //
  167. // Note also that no trailing null characters are included in the hash. This
  168. // is significant because of the fact that applying the loop to another character
  169. // even though its value is zero will significantly change the hash value.
  170. //
  171. // Namespaces and attribute names are case sensitive, derived from the fact
  172. // that they appear in case sensitive contexts in the real world. This is
  173. // unfortunate, but simpler in many ways.
  174. //
  175. // Assembly identity attributes are composed of a triple of:
  176. // - Namespace URI (e.g. http://www.microsoft.com/schemas/side-by-side)
  177. // - Name (e.g. "publicKey")
  178. // - Value (case insensitive Unicode string)
  179. //
  180. // The hash of an attribute is computed by computing the hash of the three
  181. // strings, and then combining them as:
  182. //
  183. // AttributeHashValue = (((NamespaceHash * 65599) + NameHash) * 65599) + ValueHash
  184. //
  185. // Now, sort the attributes based first on namespace, then on name then on
  186. // value (case sensitive, case sensitive and case insensitive respectively),
  187. // and combine their hashes as follows:
  188. //
  189. // IdentityHash = 0;
  190. // for (i=0; i<AttributeCount; i++)
  191. // IdentityHash = (IdentityHash * 65599) + AttributeHashes[i];
  192. //
  193. // IdentityHash is the value stored in the encoded header.
  194. //
  195. // The attribute hash array stored in the encoded data is the attribute
  196. // hashes as described above. The interesting thing is that they are stored
  197. // in order of ascending hash value, not in the canonical ordering for
  198. // attributes.
  199. //
  200. // This is because a common scenario is to find an identity which has a
  201. // superset of a given identity. While the actual attributes have to
  202. // be consulted to verify that the candidate is a true subset, non-
  203. // matches can be very quickly found by sorting both lists of hash
  204. // values and first looping over the smaller reference list, then
  205. // in a single pass walking the larger definition list. Attributes present
  206. // in one but not in the other will be immediately noticable due to
  207. // the missing hashes.
  208. //
  209. // As always with hashes, just because an encoded identity contains a
  210. // superset of the hash values in your candidate assembly reference,
  211. // it does not mean that the actual values appear and you must perform
  212. // real character string comparisons to verify containment.
  213. //
  214. #include <pshpack4.h>
  215. typedef struct _ENCODED_ASSEMBLY_IDENTITY_HEADER {
  216. ULONG HeaderSize; // bytes just in the header
  217. ULONG Magic;
  218. ULONG TotalSize; // bytes for the whole encoded thing
  219. DWORD Flags; // as defined for assembly identity flags
  220. ULONG Type; // type of identity - def, ref or wildcard
  221. ULONG EncodingFlags; // flags describing the encoding itself
  222. ULONG HashAlgorithm; // Algorithm ID for the hashes stored in the identity
  223. ULONG Hash; // Hash value of the entire identity
  224. ULONG AttributeCount; // number of attributes
  225. ULONG NamespaceCount; // number of distinct namespaces
  226. ULONG ReservedMustBeZero1;
  227. ULONG ReservedMustBeZero2;
  228. ULONGLONG ReservedMustBeZero3;
  229. ULONGLONG ReservedMustBeZero4;
  230. } ENCODED_ASSEMBLY_IDENTITY_HEADER, *PENCODED_ASSEMBLY_IDENTITY_HEADER;
  231. typedef const ENCODED_ASSEMBLY_IDENTITY_HEADER *PCENCODED_ASSEMBLY_IDENTITY_HEADER;
  232. typedef struct _ENCODED_ASSEMBLY_IDENTITY_ATTRIBUTE_HEADER {
  233. ULONG NamespaceIndex; // number of the namespace for this attribute
  234. ULONG NameCch; // size in Unicode characters of the name immediately following the
  235. // namespace
  236. ULONG ValueCch; // size in Unicode characters of the value immediately following the
  237. // name.
  238. } ENCODED_ASSEMBLY_IDENTITY_ATTRIBUTE_HEADER, *PENCODED_ASSEMBLY_IDENTITY_ATTRIBUTE_HEADER;
  239. typedef const ENCODED_ASSEMBLY_IDENTITY_ATTRIBUTE_HEADER *PCENCODED_ASSEMBLY_IDENTITY_ATTRIBUTE_HEADER;
  240. #include <poppack.h>
  241. #define SXSP_VALIDATE_ASSEMBLY_IDENTITY_FLAGS_MAY_BE_NULL (0x00000001)
  242. BOOL
  243. SxspValidateAssemblyIdentity(
  244. IN DWORD Flags,
  245. IN PCASSEMBLY_IDENTITY AssemblyIdentity
  246. );
  247. BOOL
  248. SxspValidateAssemblyIdentityAttributeNamespace(
  249. IN DWORD Flags,
  250. IN const WCHAR *Namespace,
  251. IN SIZE_T NamespaceCch
  252. );
  253. BOOL
  254. SxspValidateAssemblyIdentityAttributeName(
  255. IN DWORD Flags,
  256. IN const WCHAR *Name,
  257. IN SIZE_T NameCch
  258. );
  259. #define SXSP_VALIDATE_ASSEMBLY_IDENTITY_ATTRIBUTE_VALUE_FLAG_WILDCARDS_PERMITTED (0x00000001)
  260. BOOL
  261. SxspValidateAssemblyIdentityAttributeValue(
  262. IN DWORD Flags,
  263. IN const WCHAR *Value,
  264. IN SIZE_T ValueCch
  265. );
  266. BOOL
  267. SxspComputeInternalAssemblyIdentityAttributeBytesRequired(
  268. IN DWORD Flags,
  269. IN const WCHAR *Name,
  270. IN SIZE_T NameCch,
  271. IN const WCHAR *Value,
  272. IN SIZE_T ValueCch,
  273. OUT SIZE_T *BytesRequiredOut
  274. );
  275. BOOL
  276. SxspComputeAssemblyIdentityAttributeBytesRequired(
  277. IN DWORD Flags,
  278. IN PCASSEMBLY_IDENTITY_ATTRIBUTE Source,
  279. OUT SIZE_T *BytesRequiredOut
  280. );
  281. #define SXSP_FIND_ASSEMBLY_IDENTITY_NAMESPACE_IN_ARRAY_FLAG_ADD_IF_NOT_FOUND (0x00000001)
  282. BOOL
  283. SxspFindAssemblyIdentityNamespaceInArray(
  284. IN DWORD Flags,
  285. IN OUT PCASSEMBLY_IDENTITY_NAMESPACE **NamespacePointerArrayPtr,
  286. IN OUT ULONG *NamespaceArraySizePtr,
  287. IN OUT ULONG *NamespaceCountPtr,
  288. IN const WCHAR *Namespace,
  289. IN SIZE_T NamespaceCch,
  290. OUT PCASSEMBLY_IDENTITY_NAMESPACE *NamespaceOut
  291. );
  292. #define SXSP_FIND_ASSEMBLY_IDENTITY_NAMESPACE_FLAG_ADD_IF_NOT_FOUND (0x00000001)
  293. BOOL
  294. SxspFindAssemblyIdentityNamespace(
  295. IN DWORD Flags,
  296. IN struct _ASSEMBLY_IDENTITY* AssemblyIdentity,
  297. IN const WCHAR *Namespace,
  298. IN SIZE_T NamespaceCch,
  299. OUT PCASSEMBLY_IDENTITY_NAMESPACE *NamespaceOut
  300. );
  301. BOOL
  302. SxspAllocateAssemblyIdentityNamespace(
  303. IN DWORD Flags,
  304. IN const WCHAR *NamespaceString,
  305. IN SIZE_T NamespaceCch,
  306. IN ULONG NamespaceHash,
  307. OUT PCASSEMBLY_IDENTITY_NAMESPACE *NamespaceOut
  308. );
  309. VOID
  310. SxspDeallocateAssemblyIdentityNamespace(
  311. IN PCASSEMBLY_IDENTITY_NAMESPACE Namespace
  312. );
  313. BOOL
  314. SxspPopulateInternalAssemblyIdentityAttribute(
  315. IN DWORD Flags,
  316. IN PCASSEMBLY_IDENTITY_NAMESPACE Namespace,
  317. IN const WCHAR *Name,
  318. IN SIZE_T NameCch,
  319. IN const WCHAR *Value,
  320. IN SIZE_T ValueCch,
  321. OUT PINTERNAL_ASSEMBLY_IDENTITY_ATTRIBUTE Destination
  322. );
  323. BOOL
  324. SxspAllocateInternalAssemblyIdentityAttribute(
  325. IN DWORD Flags,
  326. IN PCASSEMBLY_IDENTITY_NAMESPACE Namespace,
  327. IN const WCHAR *Name,
  328. IN SIZE_T NameCch,
  329. IN const WCHAR *Value,
  330. IN SIZE_T ValueCch,
  331. OUT PCINTERNAL_ASSEMBLY_IDENTITY_ATTRIBUTE *Destination
  332. );
  333. VOID
  334. SxspCleanUpAssemblyIdentityNamespaceIfNotReferenced(
  335. IN DWORD Flags,
  336. IN struct _ASSEMBLY_IDENTITY* AssemblyIdentity,
  337. IN PCASSEMBLY_IDENTITY_NAMESPACE Namespace
  338. );
  339. VOID
  340. SxspDeallocateInternalAssemblyIdentityAttribute(
  341. PCINTERNAL_ASSEMBLY_IDENTITY_ATTRIBUTE Attribute
  342. );
  343. int
  344. __cdecl
  345. SxspCompareInternalAttributesForQsort(
  346. const void *elem1,
  347. const void *elem2
  348. );
  349. int
  350. __cdecl
  351. SxspCompareULONGsForQsort(
  352. const void *elem1,
  353. const void *elem2
  354. );
  355. BOOL
  356. SxspCompareAssemblyIdentityAttributeLists(
  357. DWORD Flags,
  358. ULONG AttributeCount,
  359. PCINTERNAL_ASSEMBLY_IDENTITY_ATTRIBUTE *List1,
  360. PCINTERNAL_ASSEMBLY_IDENTITY_ATTRIBUTE *List2,
  361. ULONG *ComparisonResultOut
  362. );
  363. BOOL
  364. SxspHashInternalAssemblyIdentityAttributes(
  365. DWORD Flags,
  366. ULONG Count,
  367. PCINTERNAL_ASSEMBLY_IDENTITY_ATTRIBUTE *Attributes,
  368. ULONG *HashOut
  369. );
  370. BOOL
  371. SxspCopyInternalAssemblyIdentityAttributeOut(
  372. DWORD Flags,
  373. PCINTERNAL_ASSEMBLY_IDENTITY_ATTRIBUTE Attribute,
  374. SIZE_T BufferSize,
  375. PASSEMBLY_IDENTITY_ATTRIBUTE DestinationBuffer,
  376. SIZE_T *BytesCopiedOrRequired
  377. );
  378. BOOL
  379. SxspIsInternalAssemblyIdentityAttribute(
  380. IN DWORD Flags,
  381. IN PCINTERNAL_ASSEMBLY_IDENTITY_ATTRIBUTE Attribute,
  382. IN const WCHAR *Namespace,
  383. IN SIZE_T NamespaceCch,
  384. IN const WCHAR *Name,
  385. IN SIZE_T NameCch,
  386. OUT BOOL *EqualsOut
  387. );
  388. #define SXSP_COMPUTE_INTERNAL_ASSEMBLY_IDENTITY_ATTRIBUTE_ENCODED_TEXTUAL_SIZE_FLAG_VALUE_ONLY (0x00000001)
  389. #define SXSP_COMPUTE_INTERNAL_ASSEMBLY_IDENTITY_ATTRIBUTE_ENCODED_TEXTUAL_SIZE_FLAG_OMIT_QUOTES (0x00000002)
  390. BOOL
  391. SxspComputeInternalAssemblyIdentityAttributeEncodedTextualSize(
  392. IN DWORD Flags,
  393. IN PCINTERNAL_ASSEMBLY_IDENTITY_ATTRIBUTE Attribute,
  394. OUT SIZE_T *BytesOut
  395. );
  396. #define SXSP_LOCATE_INTERNAL_ASSEMBLY_IDENTITY_ATTRIBUTE_FLAG_MATCH_NAMESPACE (0x00000001)
  397. #define SXSP_LOCATE_INTERNAL_ASSEMBLY_IDENTITY_ATTRIBUTE_FLAG_MATCH_NAME (0x00000002)
  398. #define SXSP_LOCATE_INTERNAL_ASSEMBLY_IDENTITY_ATTRIBUTE_FLAG_MATCH_VALUE (0x00000004)
  399. #define SXSP_LOCATE_INTERNAL_ASSEMBLY_IDENTITY_ATTRIBUTE_FLAG_NOT_FOUND_RETURNS_NULL (0x00000008)
  400. BOOL
  401. SxspLocateInternalAssemblyIdentityAttribute(
  402. IN DWORD Flags,
  403. IN PCASSEMBLY_IDENTITY AssemblyIdentity,
  404. IN PCASSEMBLY_IDENTITY_ATTRIBUTE Attribute,
  405. OUT PCINTERNAL_ASSEMBLY_IDENTITY_ATTRIBUTE *InternalAttributeOut,
  406. OUT ULONG *LastIndexSearched OPTIONAL
  407. );
  408. BOOL
  409. SxspComputeQuotedStringSize(
  410. IN DWORD Flags,
  411. IN const WCHAR *StringIn,
  412. IN SIZE_T Cch,
  413. OUT SIZE_T *BytesOut
  414. );
  415. VOID
  416. SxspDbgPrintInternalAssemblyIdentityAttribute(
  417. DWORD dwflags,
  418. PCINTERNAL_ASSEMBLY_IDENTITY_ATTRIBUTE Attribute
  419. );
  420. VOID
  421. SxspDbgPrintInternalAssemblyIdentityAttributes(
  422. DWORD dwflags,
  423. ULONG AttributeCount,
  424. PCINTERNAL_ASSEMBLY_IDENTITY_ATTRIBUTE const *Attributes
  425. );
  426. VOID
  427. SxspDbgPrintAssemblyIdentityAttribute(
  428. DWORD dwflags,
  429. PCASSEMBLY_IDENTITY_ATTRIBUTE Attribute
  430. );
  431. VOID
  432. SxspDbgPrintAssemblyIdentityAttributes(
  433. DWORD dwflags,
  434. ULONG AttributeCount,
  435. PCASSEMBLY_IDENTITY_ATTRIBUTE const *Attributes
  436. );
  437. BOOL
  438. SxspEnsureAssemblyIdentityHashIsUpToDate(
  439. DWORD dwFlags,
  440. PCASSEMBLY_IDENTITY AssemblyIdentity
  441. );
  442. #endif