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.

1653 lines
53 KiB

  1. /*++
  2. Copyright (c) Microsoft Corporation
  3. Module Name:
  4. sxsasmidencdec.c
  5. Abstract:
  6. Implementation of the encoding/decoding support for the assembly identity data type.
  7. Author:
  8. Michael Grier (MGrier) 7/28/2000
  9. Revision History:
  10. --*/
  11. #include "stdinc.h"
  12. #include <setupapi.h>
  13. #include <sxsapi.h>
  14. #include <stdlib.h>
  15. #include <search.h>
  16. #include "idp.h"
  17. static const WCHAR s_rgHexChars[] = L"0123456789abcdef";
  18. BOOL
  19. SxspValidateXMLName(
  20. PCWSTR psz,
  21. SIZE_T cch,
  22. bool &rfValid
  23. );
  24. typedef struct _CHARPAIR
  25. {
  26. WCHAR wchStart;
  27. WCHAR wchEnd;
  28. } CHARPAIR, *PCHARPAIR;
  29. typedef const CHARPAIR *PCCHARPAIR;
  30. const CHARPAIR s_rgXMLBaseChar[] =
  31. {
  32. { 0x0041, 0x005a },
  33. { 0x0061, 0x007a },
  34. { 0x00c0, 0x00d6 },
  35. { 0x00d8, 0x00f6 },
  36. { 0x00f8, 0x00ff },
  37. { 0x0100, 0x0131 },
  38. { 0x0134, 0x013e },
  39. { 0x0141, 0x0148 },
  40. { 0x014a, 0x017e },
  41. { 0x0180, 0x01c3 },
  42. { 0x01cd, 0x01f0 },
  43. { 0x01f4, 0x01f5 },
  44. { 0x01fa, 0x0217 },
  45. { 0x0250, 0x02a8 },
  46. { 0x02bb, 0x02c1 },
  47. { 0x0386, 0x0386 },
  48. { 0x0388, 0x038a },
  49. { 0x038c, 0x038c },
  50. { 0x038e, 0x03a1 },
  51. { 0x03a3, 0x03ce },
  52. { 0x03d0, 0x03d6 },
  53. { 0x03da, 0x03da },
  54. { 0x03dc, 0x03dc },
  55. { 0x03de, 0x03de },
  56. { 0x03e0, 0x03e0 },
  57. { 0x03e2, 0x03f3 },
  58. { 0x0401, 0x040c },
  59. { 0x040e, 0x044f },
  60. { 0x0451, 0x045c },
  61. { 0x045e, 0x0481 },
  62. { 0x0490, 0x04c4 },
  63. { 0x04c7, 0x04c8 },
  64. { 0x04cb, 0x04cc },
  65. { 0x04d0, 0x04eb },
  66. { 0x04ee, 0x04f5 },
  67. { 0x04f8, 0x04f9 },
  68. { 0x0531, 0x0556 },
  69. { 0x0559, 0x0559 },
  70. { 0x0561, 0x0586 },
  71. { 0x05d0, 0x05ea },
  72. { 0x05f0, 0x05f2 },
  73. { 0x0621, 0x063a },
  74. { 0x0641, 0x064a },
  75. { 0x0671, 0x06b7 },
  76. { 0x06ba, 0x06be },
  77. { 0x06c0, 0x06ce },
  78. { 0x06d0, 0x06d3 },
  79. { 0x06d5, 0x06d5 },
  80. { 0x06e5, 0x06e6 },
  81. { 0x0905, 0x0939 },
  82. { 0x093d, 0x093d },
  83. { 0x0958, 0x0961 },
  84. { 0x0985, 0x098c },
  85. { 0x098f, 0x0990 },
  86. { 0x0993, 0x09a8 },
  87. { 0x09aa, 0x09b0 },
  88. { 0x09b2, 0x09b2 },
  89. { 0x09b6, 0x09b9 },
  90. { 0x09dc, 0x09dd },
  91. { 0x09df, 0x09e1 },
  92. { 0x09f0, 0x09f1 },
  93. { 0x0a05, 0x0a0a },
  94. { 0x0a0f, 0x0a10 },
  95. { 0x0a13, 0x0a28 },
  96. { 0x0a2a, 0x0a30 },
  97. { 0x0a32, 0x0a33 },
  98. { 0x0a35, 0x0a36 },
  99. { 0x0a38, 0x0a39 },
  100. { 0x0a59, 0x0a5c },
  101. { 0x0a5e, 0x0a5e },
  102. { 0x0a72, 0x0a74 },
  103. { 0x0a85, 0x0a8b },
  104. { 0x0a8d, 0x0a8d },
  105. { 0x0a8f, 0x0a91 },
  106. { 0x0a93, 0x0aa8 },
  107. { 0x0aaa, 0x0ab0 },
  108. { 0x0ab2, 0x0ab3 },
  109. { 0x0ab5, 0x0ab9 },
  110. { 0x0abd, 0x0abd },
  111. { 0x0ae0, 0x0ae0 },
  112. { 0x0b05, 0x0b0c },
  113. { 0x0b0f, 0x0b10 },
  114. { 0x0b13, 0x0b28 },
  115. { 0x0b2a, 0x0b30 },
  116. { 0x0b32, 0x0b33 },
  117. { 0x0b36, 0x0b39 },
  118. { 0x0b3d, 0x0b3d },
  119. { 0x0b5c, 0x0b5d },
  120. { 0x0b5f, 0x0b61 },
  121. { 0x0b85, 0x0b8a },
  122. { 0x0b8e, 0x0b90 },
  123. { 0x0b92, 0x0b95 },
  124. { 0x0b99, 0x0b9a },
  125. { 0x0b9c, 0x0b9c },
  126. { 0x0b9e, 0x0b9f },
  127. { 0x0ba3, 0x0ba4 },
  128. { 0x0ba8, 0x0baa },
  129. { 0x0bae, 0x0bb5 },
  130. { 0x0bb7, 0x0bb9 },
  131. { 0x0c05, 0x0c0c },
  132. { 0x0c0e, 0x0c10 },
  133. { 0x0c12, 0x0c28 },
  134. { 0x0c2a, 0x0c33 },
  135. { 0x0c35, 0x0c39 },
  136. { 0x0c60, 0x0c61 },
  137. { 0x0c85, 0x0c8c },
  138. { 0x0c8e, 0x0c90 },
  139. { 0x0c92, 0x0ca8 },
  140. { 0x0caa, 0x0cb3 },
  141. { 0x0cb5, 0x0cb9 },
  142. { 0x0cde, 0x0cde },
  143. { 0x0ce0, 0x0ce1 },
  144. { 0x0d05, 0x0d0c },
  145. { 0x0d0e, 0x0d10 },
  146. { 0x0d12, 0x0d28 },
  147. { 0x0d2a, 0x0d39 },
  148. { 0x0d60, 0x0d61 },
  149. { 0x0e01, 0x0e2e },
  150. { 0x0e30, 0x0e30 },
  151. { 0x0e32, 0x0e33 },
  152. { 0x0e40, 0x0e45 },
  153. { 0x0e81, 0x0e82 },
  154. { 0x0e84, 0x0e84 },
  155. { 0x0e87, 0x0e88 },
  156. { 0x0e8a, 0x0e8a },
  157. { 0x0e8d, 0x0e8d },
  158. { 0x0e94, 0x0e97 },
  159. { 0x0e99, 0x0e9f },
  160. { 0x0ea1, 0x0ea3 },
  161. { 0x0ea5, 0x0ea5 },
  162. { 0x0ea7, 0x0ea7 },
  163. { 0x0eaa, 0x0eab },
  164. { 0x0ead, 0x0eae },
  165. { 0x0eb0, 0x0eb0 },
  166. { 0x0eb2, 0x0eb3 },
  167. { 0x0ebd, 0x0ebd },
  168. { 0x0ec0, 0x0ec4 },
  169. { 0x0f40, 0x0f47 },
  170. { 0x0f49, 0x0f69 },
  171. { 0x10a0, 0x10c5 },
  172. { 0x10d0, 0x10f6 },
  173. { 0x1100, 0x1100 },
  174. { 0x1102, 0x1103 },
  175. { 0x1105, 0x1107 },
  176. { 0x1109, 0x1109 },
  177. { 0x110b, 0x110c },
  178. { 0x110e, 0x1112 },
  179. { 0x113c, 0x113c },
  180. { 0x113e, 0x113e },
  181. { 0x1140, 0x1140 },
  182. { 0x114c, 0x114c },
  183. { 0x114e, 0x114e },
  184. { 0x1150, 0x1150 },
  185. { 0x1154, 0x1155 },
  186. { 0x1159, 0x1159 },
  187. { 0x115f, 0x1161 },
  188. { 0x1163, 0x1163 },
  189. { 0x1165, 0x1165 },
  190. { 0x1167, 0x1167 },
  191. { 0x1169, 0x1169 },
  192. { 0x116d, 0x116e },
  193. { 0x1172, 0x1173 },
  194. { 0x1175, 0x1175 },
  195. { 0x119e, 0x119e },
  196. { 0x11a8, 0x11a8 },
  197. { 0x11ab, 0x11ab },
  198. { 0x11ae, 0x11af },
  199. { 0x11b7, 0x11b8 },
  200. { 0x11ba, 0x11ba },
  201. { 0x11bc, 0x11c2 },
  202. { 0x11eb, 0x11eb },
  203. { 0x11f0, 0x11f0 },
  204. { 0x11f9, 0x11f9 },
  205. { 0x1e00, 0x1e9b },
  206. { 0x1ea0, 0x1ef9 },
  207. { 0x1f00, 0x1f15 },
  208. { 0x1f18, 0x1f1d },
  209. { 0x1f20, 0x1f45 },
  210. { 0x1f48, 0x1f4d },
  211. { 0x1f50, 0x1f57 },
  212. { 0x1f59, 0x1f59 },
  213. { 0x1f5b, 0x1f5b },
  214. { 0x1f5d, 0x1f5d },
  215. { 0x1f5f, 0x1f7d },
  216. { 0x1f80, 0x1fb4 },
  217. { 0x1fb6, 0x1fbc },
  218. { 0x1fbe, 0x1fbe },
  219. { 0x1fc2, 0x1fc4 },
  220. { 0x1fc6, 0x1fcc },
  221. { 0x1fd0, 0x1fd3 },
  222. { 0x1fd6, 0x1fdb },
  223. { 0x1fe0, 0x1fec },
  224. { 0x1ff2, 0x1ff4 },
  225. { 0x1ff6, 0x1ffc },
  226. { 0x2126, 0x2126 },
  227. { 0x212a, 0x212b },
  228. { 0x212e, 0x212e },
  229. { 0x2180, 0x2182 },
  230. { 0x3041, 0x3094 },
  231. { 0x30a1, 0x30fa },
  232. { 0x3105, 0x312c },
  233. { 0xac00, 0xd7a3 },
  234. };
  235. BOOL
  236. SxsComputeAssemblyIdentityEncodedSize(
  237. IN ULONG Flags,
  238. IN PCASSEMBLY_IDENTITY AssemblyIdentity,
  239. IN const GUID *EncodingGroup OPTIONAL,
  240. IN ULONG EncodingFormat,
  241. OUT SIZE_T *SizeOut
  242. )
  243. {
  244. BOOL fSuccess = FALSE;
  245. FN_TRACE_WIN32(fSuccess);
  246. SIZE_T Size = 0;
  247. ULONG i;
  248. ULONG AttributeCount, NamespaceCount;
  249. PCINTERNAL_ASSEMBLY_IDENTITY_ATTRIBUTE *AttributePointerArray = NULL;
  250. PCASSEMBLY_IDENTITY_NAMESPACE *NamespacePointerArray = NULL;
  251. if (SizeOut != NULL)
  252. *SizeOut = 0;
  253. PARAMETER_CHECK(Flags == 0);
  254. PARAMETER_CHECK(AssemblyIdentity != NULL);
  255. PARAMETER_CHECK(SizeOut != NULL);
  256. if (EncodingGroup != NULL)
  257. ORIGINATE_WIN32_FAILURE_AND_EXIT(UnknownEncodingGroup, ERROR_SXS_UNKNOWN_ENCODING_GROUP);
  258. if ((EncodingFormat != SXS_ASSEMBLY_IDENTITY_ENCODING_DEFAULTGROUP_BINARY) &&
  259. (EncodingFormat != SXS_ASSEMBLY_IDENTITY_ENCODING_DEFAULTGROUP_TEXTUAL))
  260. ORIGINATE_WIN32_FAILURE_AND_EXIT(UnknownEncodingId, ERROR_SXS_UNKNOWN_ENCODING);
  261. IFW32FALSE_EXIT(::SxspValidateAssemblyIdentity(0, AssemblyIdentity));
  262. AttributeCount = AssemblyIdentity->AttributeCount;
  263. NamespaceCount = AssemblyIdentity->NamespaceCount;
  264. AttributePointerArray = AssemblyIdentity->AttributePointerArray;
  265. NamespacePointerArray = AssemblyIdentity->NamespacePointerArray;
  266. switch (EncodingFormat)
  267. {
  268. case SXS_ASSEMBLY_IDENTITY_ENCODING_DEFAULTGROUP_BINARY:
  269. // NTRAID#NTBUG9 - 586520 - 2002/03/26 - xiaoyuw:
  270. // - this function calculate the encoded size of assembly identity:
  271. // if it overflow, what to do...
  272. // First, we know we need a header.
  273. Size = sizeof(ENCODED_ASSEMBLY_IDENTITY_HEADER);
  274. // Then a ULONG hash per attribute:
  275. Size += (AssemblyIdentity->AttributeCount * sizeof(ULONG));
  276. // Then a ULONG per namespace...
  277. Size += (AssemblyIdentity->NamespaceCount * sizeof(ULONG));
  278. // Then we need an attribute header per attribute:
  279. Size += AssemblyIdentity->AttributeCount * sizeof(ENCODED_ASSEMBLY_IDENTITY_ATTRIBUTE_HEADER);
  280. // Then come the namespace strings...
  281. for (i=0; i<NamespaceCount; i++)
  282. Size += NamespacePointerArray[i]->NamespaceCch * sizeof(WCHAR);
  283. // Then we need space for each of the attributes' names and value.
  284. AttributePointerArray = AssemblyIdentity->AttributePointerArray;
  285. for (i=0; i<AttributeCount; i++)
  286. {
  287. INTERNAL_ERROR_CHECK(AttributePointerArray[i] != NULL);
  288. Size += AttributePointerArray[i]->Attribute.NameCch * sizeof(WCHAR);
  289. Size += AttributePointerArray[i]->Attribute.ValueCch * sizeof(WCHAR);
  290. }
  291. // We should at least be byte aligned here...
  292. ASSERT((Size % 2) == 0);
  293. // And finally pad out to a multiple of four if we are not...
  294. Size = (Size + 3) & ~3;
  295. break;
  296. case SXS_ASSEMBLY_IDENTITY_ENCODING_DEFAULTGROUP_TEXTUAL:
  297. for (i=0; i<AttributeCount; i++)
  298. {
  299. PCINTERNAL_ASSEMBLY_IDENTITY_ATTRIBUTE Attribute = AttributePointerArray[i];
  300. BOOL IsAssemblyName = FALSE;
  301. SIZE_T BytesThisAttribute = 0;
  302. INTERNAL_ERROR_CHECK(Attribute != NULL);
  303. IFW32FALSE_EXIT(::SxspIsInternalAssemblyIdentityAttribute(
  304. 0,
  305. Attribute,
  306. NULL,
  307. 0,
  308. SXS_ASSEMBLY_IDENTITY_STD_ATTRIBUTE_NAME_NAME,
  309. NUMBER_OF(SXS_ASSEMBLY_IDENTITY_STD_ATTRIBUTE_NAME_NAME) - 1,
  310. &IsAssemblyName));
  311. // It's the attribute name. Just account for the size of the encoded value string
  312. IFW32FALSE_EXIT(::SxspComputeInternalAssemblyIdentityAttributeEncodedTextualSize(
  313. IsAssemblyName ?
  314. SXSP_COMPUTE_INTERNAL_ASSEMBLY_IDENTITY_ATTRIBUTE_ENCODED_TEXTUAL_SIZE_FLAG_VALUE_ONLY |
  315. SXSP_COMPUTE_INTERNAL_ASSEMBLY_IDENTITY_ATTRIBUTE_ENCODED_TEXTUAL_SIZE_FLAG_OMIT_QUOTES
  316. : 0,
  317. Attribute,
  318. &BytesThisAttribute));
  319. // Account for the separator character
  320. if (i != 0)
  321. Size += sizeof(WCHAR);
  322. Size += BytesThisAttribute;
  323. }
  324. break;
  325. }
  326. *SizeOut = Size;
  327. fSuccess = TRUE;
  328. Exit:
  329. return fSuccess;
  330. }
  331. SIZE_T
  332. __fastcall
  333. SxspComputeQuotedStringSize(
  334. IN const WCHAR *StringIn,
  335. IN SIZE_T Cch
  336. )
  337. {
  338. SIZE_T Bytes = 0;
  339. while (Cch != 0)
  340. {
  341. const WCHAR wch = *StringIn++;
  342. if (((wch >= L'A') && (wch <= L'Z')) ||
  343. ((wch >= L'a') && (wch <= L'z')) ||
  344. ((wch >= L'0') && (wch <= L'9')) ||
  345. (wch == L'.') ||
  346. (wch == L'-') ||
  347. (wch == L'_'))
  348. {
  349. Bytes += sizeof(WCHAR);
  350. }
  351. else
  352. {
  353. switch (wch)
  354. {
  355. case L'&':
  356. // &amp;
  357. Bytes += (5 * sizeof(WCHAR));
  358. break;
  359. case L'"':
  360. // &quot;
  361. Bytes += (6 * sizeof(WCHAR));
  362. break;
  363. case L'<':
  364. // &lt;
  365. Bytes += (4 * sizeof(WCHAR));
  366. break;
  367. case L'>':
  368. // &gt;
  369. Bytes += (4 * sizeof(WCHAR));
  370. break;
  371. case L'\'':
  372. // &apos;
  373. Bytes += (6 * sizeof(WCHAR));
  374. break;
  375. default:
  376. // Otherwise, it's going to be &#xn;
  377. if (wch < 0x10)
  378. Bytes += (5 * sizeof(WCHAR));
  379. else if (wch < 0x100)
  380. Bytes += (6 * sizeof(WCHAR));
  381. else if (wch < 0x1000)
  382. Bytes += (7 * sizeof(WCHAR));
  383. else
  384. Bytes += (8 * sizeof(WCHAR));
  385. break;
  386. }
  387. }
  388. Cch--;
  389. }
  390. return Bytes;
  391. }
  392. BOOL
  393. SxspDequoteString(
  394. IN DWORD dwFlags,
  395. IN PCWSTR pcwszStringIn,
  396. IN SIZE_T cchStringIn,
  397. OUT PWSTR pwszStringOut,
  398. OUT SIZE_T *pcchStringOut
  399. )
  400. {
  401. FN_PROLOG_WIN32
  402. PCWSTR pcwszInputCursor = pcwszStringIn;
  403. PWSTR pwszOutputCursor = pwszStringOut;
  404. PCWSTR pcwszInputCursorEnd = pcwszStringIn + cchStringIn;
  405. SIZE_T cchOutputRemaining = 0;
  406. BOOL fInsufficient = FALSE;
  407. PARAMETER_CHECK(dwFlags == 0);
  408. if (pcchStringOut != NULL)
  409. {
  410. cchOutputRemaining = *pcchStringOut;
  411. *pcchStringOut = 0;
  412. }
  413. if (pwszStringOut != NULL)
  414. pwszStringOut[0] = UNICODE_NULL;
  415. PARAMETER_CHECK(pcchStringOut != NULL);
  416. //
  417. // reserve one wchar for trailing NULL
  418. //
  419. #define APPEND_OUTPUT_CHARACTER( toadd ) { \
  420. if ( cchOutputRemaining > 1 ) { \
  421. *pwszOutputCursor++ = (toadd); \
  422. cchOutputRemaining--; \
  423. (*pcchStringOut)++; \
  424. } else fInsufficient = TRUE; \
  425. }
  426. #define CONTAINS_TAG(tag) (::FusionpCompareStrings(pcwszInputCursor, cchToNextSemicolon, (tag), NUMBER_OF(tag)-1, false) == 0)
  427. #define REPLACE_TAG( tag, newchar ) if ( CONTAINS_TAG(tag) ) { APPEND_OUTPUT_CHARACTER(newchar) }
  428. //
  429. // Zing through the input string until there's nothing left
  430. //
  431. while ((pcwszInputCursor < pcwszInputCursorEnd) && (!fInsufficient))
  432. {
  433. const WCHAR wchCurrent = *pcwszInputCursor;
  434. // Something we know and love?
  435. if (wchCurrent == L'&')
  436. {
  437. pcwszInputCursor++;
  438. SIZE_T cchToNextSemicolon = StringComplimentSpan(
  439. pcwszInputCursor,
  440. pcwszInputCursorEnd,
  441. L";");
  442. PCWSTR pcwszSemicolon = pcwszInputCursor + cchToNextSemicolon;
  443. REPLACE_TAG(L"amp", L'&')
  444. else REPLACE_TAG(L"quot", L'"')
  445. else REPLACE_TAG(L"lt", L'<')
  446. else REPLACE_TAG(L"gt", L'>')
  447. else REPLACE_TAG(L"apos", L'\'')
  448. // This might be an encoded character...
  449. else if ( cchToNextSemicolon >= 2 )
  450. {
  451. bool fIsHexString = false;
  452. WCHAR wchReplacement = 0;
  453. // The only non-chunk think accepted is the # character
  454. PARAMETER_CHECK(*pcwszInputCursor == L'#');
  455. // which means we've skipped one
  456. pcwszInputCursor++;
  457. fIsHexString = (*pcwszInputCursor == L'x') || (*pcwszInputCursor == 'X');
  458. if (fIsHexString) {
  459. pcwszInputCursor++;
  460. }
  461. while ( pcwszInputCursor != pcwszSemicolon )
  462. {
  463. if ( fIsHexString )
  464. {
  465. wchReplacement <<= 4;
  466. switch ( *pcwszInputCursor++ ) {
  467. case L'0' : break;
  468. case L'1' : wchReplacement += 0x1; break;
  469. case L'2' : wchReplacement += 0x2; break;
  470. case L'3' : wchReplacement += 0x3; break;
  471. case L'4' : wchReplacement += 0x4; break;
  472. case L'5' : wchReplacement += 0x5; break;
  473. case L'6' : wchReplacement += 0x6; break;
  474. case L'7' : wchReplacement += 0x7; break;
  475. case L'8' : wchReplacement += 0x8; break;
  476. case L'9' : wchReplacement += 0x9; break;
  477. case L'a': case L'A': wchReplacement += 0xA; break;
  478. case L'b': case L'B': wchReplacement += 0xB; break;
  479. case L'c': case L'C': wchReplacement += 0xC; break;
  480. case L'd': case L'D': wchReplacement += 0xD; break;
  481. case L'e': case L'E': wchReplacement += 0xE; break;
  482. case L'f': case L'F': wchReplacement += 0xF; break;
  483. default:
  484. PARAMETER_CHECK(FALSE && L"wchReplacement contains a non-hex digit");
  485. break;
  486. }
  487. }
  488. else
  489. {
  490. wchReplacement *= 10;
  491. switch ( *pcwszInputCursor++ ) {
  492. case L'0' : break;
  493. case L'1' : wchReplacement += 0x1; break;
  494. case L'2' : wchReplacement += 0x2; break;
  495. case L'3' : wchReplacement += 0x3; break;
  496. case L'4' : wchReplacement += 0x4; break;
  497. case L'5' : wchReplacement += 0x5; break;
  498. case L'6' : wchReplacement += 0x6; break;
  499. case L'7' : wchReplacement += 0x7; break;
  500. case L'8' : wchReplacement += 0x8; break;
  501. case L'9' : wchReplacement += 0x9; break;
  502. default:
  503. PARAMETER_CHECK(FALSE && "wchReplacement contains a non-decimal digit");
  504. break;
  505. }
  506. }
  507. }
  508. APPEND_OUTPUT_CHARACTER(wchReplacement);
  509. }
  510. if (!fInsufficient)
  511. pcwszInputCursor = pcwszSemicolon + 1;
  512. }
  513. // Otherwise, simply copy the character to the output string
  514. else
  515. {
  516. APPEND_OUTPUT_CHARACTER(wchCurrent);
  517. if (!fInsufficient)
  518. pcwszInputCursor++;
  519. }
  520. }
  521. if (fInsufficient)
  522. ORIGINATE_WIN32_FAILURE_AND_EXIT(NoRoom, ERROR_INSUFFICIENT_BUFFER);
  523. pwszStringOut[*pcchStringOut] = L'\0';
  524. FN_EPILOG
  525. }
  526. BOOL
  527. SxspQuoteString(
  528. IN DWORD Flags,
  529. IN const WCHAR *StringIn,
  530. IN SIZE_T Cch,
  531. IN SIZE_T BufferSize,
  532. IN PVOID Buffer,
  533. OUT SIZE_T *BytesWrittenOut
  534. )
  535. {
  536. BOOL fSuccess = FALSE;
  537. WCHAR *Cursor;
  538. SIZE_T BytesWritten = 0;
  539. SIZE_T BytesLeft = BufferSize;
  540. if (BytesWrittenOut != NULL)
  541. *BytesWrittenOut = 0;
  542. W32PARAMETER_CHECK_NTC(Flags == 0);
  543. W32PARAMETER_CHECK_NTC(StringIn != NULL || Cch == 0);
  544. W32PARAMETER_CHECK_NTC(Buffer != NULL || BufferSize == 0);
  545. Cursor = (WCHAR *) Buffer;
  546. BytesWritten = 0;
  547. while (Cch != 0)
  548. {
  549. const WCHAR wch = *StringIn++;
  550. if (((wch >= L'A') && (wch <= L'Z')) ||
  551. ((wch >= L'a') && (wch <= L'z')) ||
  552. ((wch >= L'0') && (wch <= L'9')) ||
  553. (wch == L'.') ||
  554. (wch == L'-') ||
  555. (wch == L'_'))
  556. {
  557. if (BytesLeft < sizeof(WCHAR))
  558. ORIGINATE_WIN32_FAILURE_AND_EXIT_NTC(NoRoom, ERROR_INSUFFICIENT_BUFFER);
  559. *Cursor++ = wch;
  560. BytesLeft -= sizeof(WCHAR);
  561. BytesWritten += sizeof(WCHAR);
  562. }
  563. else
  564. {
  565. #define HANDLE_CASE(_wch, _wstr) \
  566. case _wch: \
  567. { \
  568. ULONG i; \
  569. if (BytesLeft < (sizeof(_wstr) - sizeof(WCHAR))) \
  570. ORIGINATE_WIN32_FAILURE_AND_EXIT_NTC(NoRoom, ERROR_INSUFFICIENT_BUFFER); \
  571. for (i=0; i<(NUMBER_OF(_wstr) - 1); i++) \
  572. *Cursor++ = _wstr[i]; \
  573. BytesLeft -= (sizeof(_wstr) - sizeof(WCHAR)); \
  574. BytesWritten += (sizeof(_wstr) - sizeof(WCHAR)); \
  575. break; \
  576. }
  577. switch (wch)
  578. {
  579. HANDLE_CASE(L'"', L"&quot;")
  580. HANDLE_CASE(L'&', L"&amp;")
  581. HANDLE_CASE(L'<', L"&lt;")
  582. HANDLE_CASE(L'>', L"&gt;")
  583. HANDLE_CASE(L'\'', L"&apos;")
  584. default:
  585. if (wch < 0x10)
  586. {
  587. if (BytesLeft < (5 * sizeof(WCHAR)))
  588. ORIGINATE_WIN32_FAILURE_AND_EXIT_NTC(NoRoom, ERROR_INSUFFICIENT_BUFFER);
  589. *Cursor++ = L'&';
  590. *Cursor++ = L'#';
  591. *Cursor++ = L'x';
  592. *Cursor++ = s_rgHexChars[wch];
  593. *Cursor++ = L';';
  594. BytesWritten += (5 * sizeof(WCHAR));
  595. BytesLeft -= (5 * sizeof(WCHAR));
  596. }
  597. else if (wch < 0x100)
  598. {
  599. if (BytesLeft < (6 * sizeof(WCHAR)))
  600. ORIGINATE_WIN32_FAILURE_AND_EXIT_NTC(NoRoom, ERROR_INSUFFICIENT_BUFFER);
  601. *Cursor++ = L'&';
  602. *Cursor++ = L'#';
  603. *Cursor++ = L'x';
  604. *Cursor++ = s_rgHexChars[(wch >> 4) & 0xf];
  605. *Cursor++ = s_rgHexChars[wch & 0xf];
  606. *Cursor++ = L';';
  607. BytesWritten += (6 * sizeof(WCHAR));
  608. BytesLeft -= (6 * sizeof(WCHAR));
  609. }
  610. else if (wch < 0x1000)
  611. {
  612. if (BytesLeft < (7 * sizeof(WCHAR)))
  613. ORIGINATE_WIN32_FAILURE_AND_EXIT_NTC(NoRoom, ERROR_INSUFFICIENT_BUFFER);
  614. *Cursor++ = L'&';
  615. *Cursor++ = L'#';
  616. *Cursor++ = L'x';
  617. *Cursor++ = s_rgHexChars[(wch >> 8) & 0xf];
  618. *Cursor++ = s_rgHexChars[(wch >> 4) & 0xf];
  619. *Cursor++ = s_rgHexChars[wch & 0xf];
  620. *Cursor++ = L';';
  621. BytesWritten += (7 * sizeof(WCHAR));
  622. BytesLeft -= (7 * sizeof(WCHAR));
  623. }
  624. else
  625. {
  626. W32INTERNAL_ERROR_CHECK_NTC(wch <= 0xffff);
  627. if (BytesLeft < (8 * sizeof(WCHAR)))
  628. ORIGINATE_WIN32_FAILURE_AND_EXIT_NTC(NoRoom, ERROR_INSUFFICIENT_BUFFER);
  629. *Cursor++ = L'&';
  630. *Cursor++ = L'#';
  631. *Cursor++ = L'x';
  632. *Cursor++ = s_rgHexChars[(wch >> 12) & 0xf];
  633. *Cursor++ = s_rgHexChars[(wch >> 8) & 0xf];
  634. *Cursor++ = s_rgHexChars[(wch >> 4) & 0xf];
  635. *Cursor++ = s_rgHexChars[wch & 0xf];
  636. *Cursor++ = L';';
  637. BytesWritten += (8 * sizeof(WCHAR));
  638. BytesLeft -= (8 * sizeof(WCHAR));
  639. }
  640. break;
  641. }
  642. }
  643. Cch--;
  644. }
  645. if (BytesWrittenOut != NULL)
  646. *BytesWrittenOut = BytesWritten;
  647. fSuccess = TRUE;
  648. Exit:
  649. return fSuccess;
  650. }
  651. BOOL
  652. SxspComputeInternalAssemblyIdentityAttributeEncodedTextualSize(
  653. IN DWORD Flags,
  654. IN PCINTERNAL_ASSEMBLY_IDENTITY_ATTRIBUTE Attribute,
  655. OUT SIZE_T *BytesOut
  656. )
  657. {
  658. BOOL fSuccess = FALSE;
  659. FN_TRACE_WIN32(fSuccess);
  660. SIZE_T Bytes = 0;
  661. if (BytesOut != NULL)
  662. *BytesOut = 0;
  663. PARAMETER_CHECK((Flags & ~(
  664. SXSP_COMPUTE_INTERNAL_ASSEMBLY_IDENTITY_ATTRIBUTE_ENCODED_TEXTUAL_SIZE_FLAG_VALUE_ONLY |
  665. SXSP_COMPUTE_INTERNAL_ASSEMBLY_IDENTITY_ATTRIBUTE_ENCODED_TEXTUAL_SIZE_FLAG_OMIT_QUOTES)) == 0);
  666. PARAMETER_CHECK(Attribute != NULL);
  667. PARAMETER_CHECK(BytesOut != NULL);
  668. Bytes = 0;
  669. if ((Flags & SXSP_COMPUTE_INTERNAL_ASSEMBLY_IDENTITY_ATTRIBUTE_ENCODED_TEXTUAL_SIZE_FLAG_VALUE_ONLY) == 0)
  670. {
  671. if (Attribute->Attribute.NamespaceCch != 0)
  672. {
  673. // Figure out the ns:n= part
  674. Bytes += ::SxspComputeQuotedStringSize(Attribute->Attribute.Namespace, Attribute->Attribute.NamespaceCch);
  675. Bytes += sizeof(WCHAR); // the ":"
  676. }
  677. Bytes += ::SxspComputeQuotedStringSize(Attribute->Attribute.Name, Attribute->Attribute.NameCch);
  678. Bytes += sizeof(WCHAR); // the "="
  679. }
  680. Bytes += ::SxspComputeQuotedStringSize(Attribute->Attribute.Value, Attribute->Attribute.ValueCch);
  681. if ((Flags & SXSP_COMPUTE_INTERNAL_ASSEMBLY_IDENTITY_ATTRIBUTE_ENCODED_TEXTUAL_SIZE_FLAG_OMIT_QUOTES) == 0)
  682. Bytes += 2 * sizeof(WCHAR); // the beginning and ending quotes
  683. *BytesOut = Bytes;
  684. fSuccess = TRUE;
  685. Exit:
  686. return fSuccess;
  687. }
  688. BOOL
  689. SxspEncodeInternalAssemblyIdentityAttributeAsText(
  690. IN DWORD Flags,
  691. IN PCINTERNAL_ASSEMBLY_IDENTITY_ATTRIBUTE Attribute,
  692. SIZE_T BufferSize,
  693. PVOID Buffer,
  694. SIZE_T *BytesWrittenOut
  695. )
  696. {
  697. BOOL fSuccess = FALSE;
  698. FN_TRACE_WIN32(fSuccess);
  699. SIZE_T BytesWritten = 0;
  700. SIZE_T BytesLeft = 0;
  701. SIZE_T BytesThisSegment;
  702. WCHAR *Cursor;
  703. if (BytesWrittenOut != NULL)
  704. *BytesWrittenOut = 0;
  705. PARAMETER_CHECK(Flags == 0);
  706. PARAMETER_CHECK(Attribute != NULL);
  707. PARAMETER_CHECK((Buffer != NULL) || (BufferSize == 0));
  708. BytesWritten = 0;
  709. BytesLeft = BufferSize;
  710. Cursor = reinterpret_cast<WCHAR *>(Buffer);
  711. if (Attribute->Attribute.NamespaceCch != 0)
  712. {
  713. IFW32FALSE_EXIT(::SxspQuoteString(0, Attribute->Namespace->Namespace, Attribute->Namespace->NamespaceCch, BytesLeft, Cursor, &BytesThisSegment));
  714. INTERNAL_ERROR_CHECK(BytesThisSegment <= BytesLeft);
  715. Cursor = (WCHAR *) (((ULONG_PTR) Cursor) + BytesThisSegment);
  716. BytesLeft -= BytesThisSegment;
  717. BytesWritten += BytesThisSegment;
  718. if (BytesLeft < sizeof(WCHAR))
  719. ORIGINATE_WIN32_FAILURE_AND_EXIT(NoRoom, ERROR_INSUFFICIENT_BUFFER);
  720. *Cursor++ = L':';
  721. BytesLeft -= sizeof(WCHAR);
  722. BytesWritten += sizeof(WCHAR);
  723. }
  724. IFW32FALSE_EXIT(::SxspQuoteString(0, Attribute->Attribute.Name, Attribute->Attribute.NameCch, BytesLeft, Cursor, &BytesThisSegment));
  725. INTERNAL_ERROR_CHECK(BytesThisSegment <= BytesLeft);
  726. Cursor = (WCHAR *) (((ULONG_PTR) Cursor) + BytesThisSegment);
  727. BytesLeft -= BytesThisSegment;
  728. BytesWritten += BytesThisSegment;
  729. if (BytesLeft < (2 * sizeof(WCHAR)))
  730. ORIGINATE_WIN32_FAILURE_AND_EXIT(NoRoom, ERROR_INSUFFICIENT_BUFFER);
  731. *Cursor++ = L'=';
  732. *Cursor++ = L'"';
  733. BytesLeft -= (2 * sizeof(WCHAR));
  734. BytesWritten += (2 * sizeof(WCHAR));
  735. IFW32FALSE_EXIT(::SxspQuoteString(0, Attribute->Attribute.Value, Attribute->Attribute.ValueCch, BytesLeft, Cursor, &BytesThisSegment));
  736. INTERNAL_ERROR_CHECK(BytesThisSegment <= BytesLeft);
  737. Cursor = (WCHAR *) (((ULONG_PTR) Cursor) + BytesThisSegment);
  738. BytesLeft -= BytesThisSegment;
  739. BytesWritten += BytesThisSegment;
  740. if (BytesLeft < sizeof(WCHAR))
  741. ORIGINATE_WIN32_FAILURE_AND_EXIT(NoRoom, ERROR_INSUFFICIENT_BUFFER);
  742. *Cursor++ = L'"';
  743. BytesLeft -= sizeof(WCHAR);
  744. BytesWritten += sizeof(WCHAR);
  745. *BytesWrittenOut = BytesWritten;
  746. fSuccess = TRUE;
  747. Exit:
  748. return fSuccess;
  749. }
  750. BOOL
  751. SxspEncodeAssemblyIdentityTextually(
  752. IN DWORD Flags,
  753. IN PCASSEMBLY_IDENTITY AssemblyIdentity,
  754. IN SIZE_T BufferSize,
  755. IN PVOID Buffer,
  756. OUT SIZE_T *BytesWrittenOut)
  757. {
  758. BOOL fSuccess = FALSE;
  759. FN_TRACE_WIN32(fSuccess);
  760. ULONG AttributeCount, NamespaceCount;
  761. PCINTERNAL_ASSEMBLY_IDENTITY_ATTRIBUTE *Attributes;
  762. PCASSEMBLY_IDENTITY_NAMESPACE *Namespaces;
  763. ULONG i;
  764. ASSEMBLY_IDENTITY_ATTRIBUTE Attribute;
  765. PCINTERNAL_ASSEMBLY_IDENTITY_ATTRIBUTE NameInternalAttribute = NULL;
  766. SIZE_T BytesLeft;
  767. SIZE_T BytesWritten;
  768. PVOID Cursor;
  769. SIZE_T TempBytesWritten;
  770. if (BytesWrittenOut != NULL)
  771. *BytesWrittenOut = 0;
  772. PARAMETER_CHECK(Flags == 0);
  773. PARAMETER_CHECK(AssemblyIdentity != NULL);
  774. PARAMETER_CHECK(BufferSize != 0);
  775. PARAMETER_CHECK(Buffer != NULL);
  776. PARAMETER_CHECK(BytesWrittenOut != NULL);
  777. Cursor = Buffer;
  778. BytesLeft = BufferSize;
  779. BytesWritten = 0;
  780. // The root assembly identity is actually totally empty, so we'll short-circuit that case.
  781. AttributeCount = AssemblyIdentity->AttributeCount;
  782. if (AttributeCount != 0)
  783. {
  784. NamespaceCount = AssemblyIdentity->NamespaceCount;
  785. Attributes = AssemblyIdentity->AttributePointerArray;
  786. Namespaces = AssemblyIdentity->NamespacePointerArray;
  787. // First, let's look for the "name" attribute.
  788. Attribute.Flags = 0;
  789. Attribute.Namespace = NULL;
  790. Attribute.NamespaceCch = 0;
  791. Attribute.Name = SXS_ASSEMBLY_IDENTITY_STD_ATTRIBUTE_NAME_NAME;
  792. Attribute.NameCch = NUMBER_OF(SXS_ASSEMBLY_IDENTITY_STD_ATTRIBUTE_NAME_NAME) - 1;
  793. NameInternalAttribute =
  794. ::SxspLocateInternalAssemblyIdentityAttribute(
  795. SXSP_LOCATE_INTERNAL_ASSEMBLY_IDENTITY_ATTRIBUTE_FLAG_MATCH_NAMESPACE |
  796. SXSP_LOCATE_INTERNAL_ASSEMBLY_IDENTITY_ATTRIBUTE_FLAG_MATCH_NAME,
  797. AssemblyIdentity,
  798. &Attribute,
  799. NULL);
  800. if (NameInternalAttribute == NULL)
  801. ORIGINATE_WIN32_FAILURE_AND_EXIT(AttributeNotFound, ERROR_NOT_FOUND);
  802. IFW32FALSE_EXIT(::SxspQuoteString(0, NameInternalAttribute->Attribute.Value, NameInternalAttribute->Attribute.ValueCch, BytesLeft, Cursor, &TempBytesWritten));
  803. INTERNAL_ERROR_CHECK(TempBytesWritten <= BytesLeft);
  804. Cursor = (PVOID) (((ULONG_PTR) Cursor) + TempBytesWritten);
  805. BytesLeft -= TempBytesWritten;
  806. BytesWritten += TempBytesWritten;
  807. for (i=0; i<AttributeCount; i++)
  808. {
  809. // Skip the standard "name" attribute
  810. if (Attributes[i] == NameInternalAttribute)
  811. continue;
  812. if (BytesLeft < sizeof(WCHAR))
  813. ORIGINATE_WIN32_FAILURE_AND_EXIT(NoRoom, ERROR_INSUFFICIENT_BUFFER);
  814. *((WCHAR *) Cursor) = L',';
  815. Cursor = (PVOID) (((ULONG_PTR) Cursor) + sizeof(WCHAR));
  816. BytesLeft -= sizeof(WCHAR);
  817. BytesWritten += sizeof(WCHAR);
  818. IFW32FALSE_EXIT(::SxspEncodeInternalAssemblyIdentityAttributeAsText(0, Attributes[i], BytesLeft, Cursor, &TempBytesWritten));
  819. INTERNAL_ERROR_CHECK(TempBytesWritten <= BytesLeft);
  820. Cursor = (PVOID) (((ULONG_PTR) Cursor) + TempBytesWritten);
  821. BytesLeft -= TempBytesWritten;
  822. BytesWritten += TempBytesWritten;
  823. }
  824. }
  825. *BytesWrittenOut = BytesWritten;
  826. fSuccess = TRUE;
  827. Exit:
  828. return fSuccess;
  829. }
  830. BOOL
  831. SxsEncodeAssemblyIdentity(
  832. IN ULONG Flags,
  833. IN PCASSEMBLY_IDENTITY AssemblyIdentity,
  834. IN const GUID *EncodingGroup OPTIONAL, // use NULL to use any of the SXS_ASSEMBLY_IDENTITY_ENCODING_DEFAULTGROUP_* encodings
  835. IN ULONG EncodingFormat,
  836. IN SIZE_T BufferSize,
  837. OUT PVOID Buffer,
  838. OUT SIZE_T *BytesWrittenOrRequired
  839. )
  840. {
  841. BOOL fSuccess = FALSE;
  842. FN_TRACE_WIN32(fSuccess);
  843. SIZE_T TotalSize = 0;
  844. PVOID Cursor = NULL;
  845. SIZE_T i;
  846. PENCODED_ASSEMBLY_IDENTITY_HEADER EncodedAssemblyIdentityHeader = NULL;
  847. PENCODED_ASSEMBLY_IDENTITY_ATTRIBUTE_HEADER EncodedAssemblyIdentityAttributeHeader = NULL;
  848. ULONG *TempULONGArrayPointer;
  849. SIZE_T BytesWritten = 0;
  850. ULONG AttributeCount, NamespaceCount;
  851. if (BytesWrittenOrRequired != NULL)
  852. *BytesWrittenOrRequired = 0;
  853. PARAMETER_CHECK(Flags == 0);
  854. PARAMETER_CHECK(AssemblyIdentity != NULL);
  855. PARAMETER_CHECK((BufferSize == 0) || (Buffer != NULL));
  856. PARAMETER_CHECK((BufferSize != 0) || (BytesWrittenOrRequired != NULL));
  857. if (EncodingGroup != NULL)
  858. ORIGINATE_WIN32_FAILURE_AND_EXIT(UnknownEncodingGroup, ERROR_SXS_UNKNOWN_ENCODING_GROUP);
  859. if ((EncodingFormat != SXS_ASSEMBLY_IDENTITY_ENCODING_DEFAULTGROUP_BINARY) &&
  860. (EncodingFormat != SXS_ASSEMBLY_IDENTITY_ENCODING_DEFAULTGROUP_TEXTUAL))
  861. ORIGINATE_WIN32_FAILURE_AND_EXIT(UnknownEncodingId, ERROR_SXS_UNKNOWN_ENCODING);
  862. IFW32FALSE_EXIT(::SxspValidateAssemblyIdentity(0, AssemblyIdentity));
  863. IFW32FALSE_EXIT(::SxsComputeAssemblyIdentityEncodedSize(0, AssemblyIdentity, EncodingGroup, EncodingFormat, &TotalSize));
  864. if (TotalSize > BufferSize)
  865. {
  866. if (BytesWrittenOrRequired != NULL)
  867. *BytesWrittenOrRequired = TotalSize;
  868. ORIGINATE_WIN32_FAILURE_AND_EXIT(NoRoom, ERROR_INSUFFICIENT_BUFFER);
  869. }
  870. AttributeCount = AssemblyIdentity->AttributeCount;
  871. NamespaceCount = AssemblyIdentity->NamespaceCount;
  872. //
  873. // Let's start filling it in.
  874. //
  875. switch (EncodingFormat)
  876. {
  877. case SXS_ASSEMBLY_IDENTITY_ENCODING_DEFAULTGROUP_BINARY:
  878. BytesWritten = 0;
  879. Cursor = Buffer;
  880. EncodedAssemblyIdentityHeader = (PENCODED_ASSEMBLY_IDENTITY_HEADER) Cursor;
  881. Cursor = (PVOID) (((ULONG_PTR) Cursor) + sizeof(ENCODED_ASSEMBLY_IDENTITY_HEADER));
  882. BytesWritten += sizeof(ENCODED_ASSEMBLY_IDENTITY_HEADER);
  883. EncodedAssemblyIdentityHeader->HeaderSize = sizeof(ENCODED_ASSEMBLY_IDENTITY_HEADER);
  884. EncodedAssemblyIdentityHeader->Magic = ENCODED_ASSEMBLY_IDENTITY_HEADER_MAGIC;
  885. EncodedAssemblyIdentityHeader->TotalSize = static_cast<ULONG>(TotalSize);
  886. // turn off any flags not relevant to persisted state
  887. EncodedAssemblyIdentityHeader->Type = AssemblyIdentity->Type;
  888. EncodedAssemblyIdentityHeader->Flags = AssemblyIdentity->Flags & ~(ASSEMBLY_IDENTITY_FLAG_FROZEN);
  889. EncodedAssemblyIdentityHeader->EncodingFlags = 0;
  890. EncodedAssemblyIdentityHeader->AttributeCount = AttributeCount;
  891. EncodedAssemblyIdentityHeader->NamespaceCount = NamespaceCount;
  892. EncodedAssemblyIdentityHeader->ReservedMustBeZero1 = 0;
  893. EncodedAssemblyIdentityHeader->ReservedMustBeZero2 = 0;
  894. EncodedAssemblyIdentityHeader->ReservedMustBeZero3 = 0;
  895. EncodedAssemblyIdentityHeader->ReservedMustBeZero4 = 0;
  896. TempULONGArrayPointer = (ULONG *) Cursor;
  897. Cursor = (PVOID) (TempULONGArrayPointer + AttributeCount);
  898. BytesWritten += (AttributeCount * sizeof(ULONG));
  899. for (i=0; i<AttributeCount; i++)
  900. TempULONGArrayPointer[i] = AssemblyIdentity->AttributePointerArray[i]->WholeAttributeHash;
  901. // sort 'em...
  902. qsort(TempULONGArrayPointer, AttributeCount, sizeof(ULONG), &SxspCompareULONGsForQsort);
  903. TempULONGArrayPointer = (ULONG *) Cursor;
  904. Cursor = (PVOID) (TempULONGArrayPointer + NamespaceCount);
  905. BytesWritten += (sizeof(ULONG) * NamespaceCount);
  906. for (i=0; i<NamespaceCount; i++)
  907. TempULONGArrayPointer[i] = static_cast<ULONG>(AssemblyIdentity->NamespacePointerArray[i]->NamespaceCch);
  908. EncodedAssemblyIdentityAttributeHeader = (PENCODED_ASSEMBLY_IDENTITY_ATTRIBUTE_HEADER) Cursor;
  909. Cursor = (PVOID) (EncodedAssemblyIdentityAttributeHeader + AttributeCount);
  910. BytesWritten += (AttributeCount * sizeof(ENCODED_ASSEMBLY_IDENTITY_ATTRIBUTE_HEADER));
  911. for (i=0; i<AttributeCount; i++)
  912. {
  913. PCINTERNAL_ASSEMBLY_IDENTITY_ATTRIBUTE InternalAttribute = AssemblyIdentity->AttributePointerArray[i];
  914. ULONG NamespaceIndex;
  915. // Totally gross linear search to determine the namespace index. Fortunately the common case
  916. // will be a single namespace for all attributes.
  917. for (NamespaceIndex = 0; NamespaceIndex < NamespaceCount; NamespaceIndex++)
  918. {
  919. if (AssemblyIdentity->NamespacePointerArray[NamespaceIndex] == InternalAttribute->Namespace)
  920. break;
  921. }
  922. // If this assert fires, the attribute refers to a namespace that's not in the identity; bad!
  923. INTERNAL_ERROR_CHECK(
  924. (InternalAttribute->Namespace == NULL) ||
  925. (NamespaceIndex < NamespaceCount));
  926. EncodedAssemblyIdentityAttributeHeader[i].NamespaceIndex = NamespaceIndex + 1;
  927. EncodedAssemblyIdentityAttributeHeader[i].NameCch = static_cast<ULONG>(InternalAttribute->Attribute.NameCch);
  928. EncodedAssemblyIdentityAttributeHeader[i].ValueCch = static_cast<ULONG>(InternalAttribute->Attribute.ValueCch);
  929. }
  930. // so much for the fixed length stuff; write the namespaces.
  931. for (i=0; i<NamespaceCount; i++)
  932. {
  933. PWSTR psz = (PWSTR) Cursor;
  934. Cursor = (PVOID) (((ULONG_PTR) psz) + (AssemblyIdentity->NamespacePointerArray[i]->NamespaceCch * sizeof(WCHAR)));
  935. BytesWritten += (AssemblyIdentity->NamespacePointerArray[i]->NamespaceCch * sizeof(WCHAR));
  936. memcpy(
  937. psz,
  938. AssemblyIdentity->NamespacePointerArray[i]->Namespace,
  939. AssemblyIdentity->NamespacePointerArray[i]->NamespaceCch * sizeof(WCHAR));
  940. }
  941. // And the attributes...
  942. for (i=0; i<AttributeCount; i++)
  943. {
  944. PCINTERNAL_ASSEMBLY_IDENTITY_ATTRIBUTE InternalAttribute = AssemblyIdentity->AttributePointerArray[i];
  945. PWSTR psz;
  946. psz = (PWSTR) Cursor;
  947. Cursor = (PVOID) (((ULONG_PTR) psz) + (InternalAttribute->Attribute.NameCch * sizeof(WCHAR)));
  948. BytesWritten += (InternalAttribute->Attribute.NameCch * sizeof(WCHAR));
  949. memcpy(
  950. psz,
  951. InternalAttribute->Attribute.Name,
  952. InternalAttribute->Attribute.NameCch * sizeof(WCHAR));
  953. psz = (PWSTR) Cursor;
  954. Cursor = (PVOID) (((ULONG_PTR) psz) + InternalAttribute->Attribute.ValueCch * sizeof(WCHAR));
  955. BytesWritten += InternalAttribute->Attribute.ValueCch * sizeof(WCHAR);
  956. memcpy(
  957. psz,
  958. InternalAttribute->Attribute.Value,
  959. InternalAttribute->Attribute.ValueCch * sizeof(WCHAR));
  960. }
  961. if ((BytesWritten % 4) != 0) {
  962. ASSERT((BytesWritten % 4) == sizeof(USHORT));
  963. *((USHORT *) Cursor) = 0;
  964. BytesWritten += sizeof(USHORT);
  965. }
  966. break;
  967. case SXS_ASSEMBLY_IDENTITY_ENCODING_DEFAULTGROUP_TEXTUAL:
  968. IFW32FALSE_EXIT(::SxspEncodeAssemblyIdentityTextually(0, AssemblyIdentity, BufferSize, Buffer, &BytesWritten));
  969. break;
  970. }
  971. INTERNAL_ERROR_CHECK(BytesWritten == TotalSize);
  972. if (BytesWrittenOrRequired != NULL)
  973. *BytesWrittenOrRequired = BytesWritten;
  974. fSuccess = TRUE;
  975. Exit:
  976. return fSuccess;
  977. }
  978. BOOL
  979. SxsDecodeAssemblyIdentity(
  980. ULONG Flags,
  981. IN const GUID *EncodingGroup,
  982. IN ULONG EncodingFormat,
  983. IN SIZE_T BufferSize,
  984. IN const VOID *Buffer,
  985. OUT PASSEMBLY_IDENTITY *AssemblyIdentityOut
  986. )
  987. {
  988. BOOL fSuccess = FALSE;
  989. FN_TRACE_WIN32(fSuccess);
  990. PCENCODED_ASSEMBLY_IDENTITY_HEADER EncodedAssemblyIdentityHeader = NULL;
  991. PCENCODED_ASSEMBLY_IDENTITY_ATTRIBUTE_HEADER EncodedAssemblyIdentityAttributeHeader = NULL;
  992. PCINTERNAL_ASSEMBLY_IDENTITY_ATTRIBUTE *AttributePointerArray = NULL;
  993. PCASSEMBLY_IDENTITY_NAMESPACE *NamespacePointerArray = NULL;
  994. PASSEMBLY_IDENTITY AssemblyIdentity = NULL;
  995. ULONG AttributeCount = 0;
  996. ULONG NamespaceCount = 0;
  997. ULONG AttributeArraySize = 0;
  998. ULONG NamespaceArraySize = 0;
  999. ULONG i;
  1000. const ULONG *NamespaceLengthArray = NULL;
  1001. const ULONG *AttributeHashArray = NULL;
  1002. const WCHAR *UnicodeStringArray = NULL;
  1003. if (AssemblyIdentityOut != NULL)
  1004. *AssemblyIdentityOut = NULL;
  1005. PARAMETER_CHECK((Flags & ~(SXS_DECODE_ASSEMBLY_IDENTITY_FLAG_FREEZE)) == 0);
  1006. PARAMETER_CHECK(BufferSize >= sizeof(ENCODED_ASSEMBLY_IDENTITY_HEADER));
  1007. PARAMETER_CHECK(Buffer != NULL);
  1008. PARAMETER_CHECK(AssemblyIdentityOut != NULL);
  1009. if (EncodingGroup != NULL)
  1010. ORIGINATE_WIN32_FAILURE_AND_EXIT(UnknownEncodingGroup, ERROR_SXS_UNKNOWN_ENCODING_GROUP);
  1011. if ((EncodingFormat != SXS_ASSEMBLY_IDENTITY_ENCODING_DEFAULTGROUP_BINARY) &&
  1012. (EncodingFormat != SXS_ASSEMBLY_IDENTITY_ENCODING_DEFAULTGROUP_TEXTUAL))
  1013. ORIGINATE_WIN32_FAILURE_AND_EXIT(UnknownEncoding, ERROR_SXS_UNKNOWN_ENCODING);
  1014. EncodedAssemblyIdentityHeader = (PCENCODED_ASSEMBLY_IDENTITY_HEADER) Buffer;
  1015. if ((EncodedAssemblyIdentityHeader->HeaderSize != sizeof(ENCODED_ASSEMBLY_IDENTITY_HEADER)) ||
  1016. (EncodedAssemblyIdentityHeader->Magic != ENCODED_ASSEMBLY_IDENTITY_HEADER_MAGIC) ||
  1017. (EncodedAssemblyIdentityHeader->TotalSize > BufferSize) ||
  1018. (EncodedAssemblyIdentityHeader->Flags != 0) ||
  1019. ((EncodedAssemblyIdentityHeader->Type != ASSEMBLY_IDENTITY_TYPE_DEFINITION) &&
  1020. (EncodedAssemblyIdentityHeader->Type != ASSEMBLY_IDENTITY_TYPE_REFERENCE) &&
  1021. (EncodedAssemblyIdentityHeader->Type != ASSEMBLY_IDENTITY_TYPE_WILDCARD)) ||
  1022. (EncodedAssemblyIdentityHeader->EncodingFlags != 0) ||
  1023. (EncodedAssemblyIdentityHeader->ReservedMustBeZero1 != 0) ||
  1024. (EncodedAssemblyIdentityHeader->ReservedMustBeZero2 != 0) ||
  1025. (EncodedAssemblyIdentityHeader->ReservedMustBeZero3 != 0) ||
  1026. (EncodedAssemblyIdentityHeader->ReservedMustBeZero4 != 0)) {
  1027. ::SetLastError(ERROR_INVALID_PARAMETER);
  1028. goto Exit;
  1029. }
  1030. IFALLOCFAILED_EXIT(AssemblyIdentity = new ASSEMBLY_IDENTITY);
  1031. NamespaceCount = EncodedAssemblyIdentityHeader->NamespaceCount;
  1032. if (Flags & SXS_DECODE_ASSEMBLY_IDENTITY_FLAG_FREEZE)
  1033. {
  1034. NamespaceArraySize = NamespaceCount;
  1035. }
  1036. else if (NamespaceCount == 0)
  1037. {
  1038. NamespaceArraySize = 8;
  1039. }
  1040. else
  1041. {
  1042. NamespaceArraySize = (NamespaceCount + 7) & ~7;
  1043. }
  1044. if (NamespaceArraySize != 0)
  1045. {
  1046. IFALLOCFAILED_EXIT(NamespacePointerArray = new PCASSEMBLY_IDENTITY_NAMESPACE[NamespaceArraySize]);
  1047. for (i=0; i<NamespaceArraySize; i++)
  1048. NamespacePointerArray[i] = NULL;
  1049. }
  1050. AttributeCount = EncodedAssemblyIdentityHeader->AttributeCount;
  1051. if (Flags & SXS_DECODE_ASSEMBLY_IDENTITY_FLAG_FREEZE)
  1052. {
  1053. // If we're going to freeze, just perform an exact allocation.
  1054. AttributeArraySize = AttributeCount;
  1055. }
  1056. else if (AttributeCount == 0)
  1057. {
  1058. AttributeArraySize = 8;
  1059. }
  1060. else
  1061. {
  1062. AttributeArraySize = (AttributeCount + 7) & ~7;
  1063. }
  1064. if (AttributeArraySize != 0)
  1065. {
  1066. IFALLOCFAILED_EXIT(AttributePointerArray = new PCINTERNAL_ASSEMBLY_IDENTITY_ATTRIBUTE[AttributeArraySize]);
  1067. for (i=0; i<AttributeArraySize; i++)
  1068. AttributePointerArray[i] = NULL;
  1069. }
  1070. AttributeHashArray = (const ULONG *) (EncodedAssemblyIdentityHeader + 1);
  1071. NamespaceLengthArray = (const ULONG *) (AttributeHashArray + AttributeCount);
  1072. EncodedAssemblyIdentityAttributeHeader = (PCENCODED_ASSEMBLY_IDENTITY_ATTRIBUTE_HEADER) (NamespaceLengthArray + NamespaceCount);
  1073. UnicodeStringArray = (const WCHAR *) (EncodedAssemblyIdentityAttributeHeader + AttributeCount);
  1074. // Start by building up those namespaces...
  1075. for (i=0; i<NamespaceCount; i++)
  1076. {
  1077. ULONG NamespaceHash = 0;
  1078. NamespaceHash = ::FusionpHashUnicodeStringCaseSensitive(UnicodeStringArray, NamespaceLengthArray[i]);
  1079. IFW32FALSE_EXIT(::SxspAllocateAssemblyIdentityNamespace(0, UnicodeStringArray, NamespaceLengthArray[i], NamespaceHash, &NamespacePointerArray[i]));
  1080. UnicodeStringArray += NamespaceLengthArray[i];
  1081. }
  1082. if (AttributeCount != 0)
  1083. {
  1084. // and now those attributes...
  1085. for (i=0; i<AttributeCount; i++)
  1086. {
  1087. const ULONG NamespaceIndex = EncodedAssemblyIdentityAttributeHeader[i].NamespaceIndex;
  1088. const ULONG NameCch = EncodedAssemblyIdentityAttributeHeader[i].NameCch;
  1089. const ULONG ValueCch = EncodedAssemblyIdentityAttributeHeader[i].ValueCch;
  1090. const WCHAR * const Name = UnicodeStringArray;
  1091. const WCHAR * const Value = &UnicodeStringArray[NameCch];
  1092. UnicodeStringArray = &Value[ValueCch];
  1093. IFW32FALSE_EXIT(
  1094. ::SxspAllocateInternalAssemblyIdentityAttribute(
  1095. 0,
  1096. NamespacePointerArray[NamespaceIndex],
  1097. Name,
  1098. NameCch,
  1099. Value,
  1100. ValueCch,
  1101. &AttributePointerArray[i]));
  1102. }
  1103. // sort 'em...
  1104. qsort((PVOID) AttributePointerArray, AttributeCount, sizeof(PINTERNAL_ASSEMBLY_IDENTITY_ATTRIBUTE), &SxspCompareInternalAttributesForQsort);
  1105. }
  1106. IFW32FALSE_EXIT(::SxspHashInternalAssemblyIdentityAttributes(0, AttributeCount, AttributePointerArray, &AssemblyIdentity->Hash));
  1107. AssemblyIdentity->Flags = 0;
  1108. AssemblyIdentity->Type = EncodedAssemblyIdentityHeader->Type;
  1109. AssemblyIdentity->InternalFlags = ASSEMBLY_IDENTITY_INTERNAL_FLAG_ATTRIBUTE_POINTERS_IN_SEPARATE_ALLOCATION | ASSEMBLY_IDENTITY_INTERNAL_FLAG_NAMESPACE_POINTERS_IN_SEPARATE_ALLOCATION;
  1110. AssemblyIdentity->AttributePointerArray = AttributePointerArray;
  1111. AssemblyIdentity->AttributeCount = AttributeCount;
  1112. AssemblyIdentity->AttributeArraySize = AttributeArraySize;
  1113. AssemblyIdentity->NamespacePointerArray = NamespacePointerArray;
  1114. AssemblyIdentity->NamespaceCount = NamespaceCount;
  1115. AssemblyIdentity->NamespaceArraySize = NamespaceArraySize;
  1116. AttributePointerArray = NULL;
  1117. NamespacePointerArray = NULL;
  1118. if (Flags & SXS_DECODE_ASSEMBLY_IDENTITY_FLAG_FREEZE)
  1119. AssemblyIdentity->Flags |= ASSEMBLY_IDENTITY_FLAG_FROZEN;
  1120. *AssemblyIdentityOut = AssemblyIdentity;
  1121. AssemblyIdentity = NULL;
  1122. fSuccess = TRUE;
  1123. Exit:
  1124. //
  1125. // REVIEW: Should this be an SxsDestroyAssemblyIdentity
  1126. //
  1127. if (AssemblyIdentity != NULL)
  1128. FUSION_DELETE_SINGLETON(AssemblyIdentity);
  1129. if ((AttributeCount != 0) && (AttributePointerArray != NULL))
  1130. {
  1131. for (i=0; i<AttributeCount; i++)
  1132. {
  1133. if (AttributePointerArray[i] != NULL)
  1134. {
  1135. ::SxspDeallocateInternalAssemblyIdentityAttribute(const_cast<PINTERNAL_ASSEMBLY_IDENTITY_ATTRIBUTE>(AttributePointerArray[i]));
  1136. AttributePointerArray[i] = NULL;
  1137. }
  1138. }
  1139. FUSION_DELETE_ARRAY(AttributePointerArray);
  1140. }
  1141. if ((NamespaceCount != 0) && (NamespacePointerArray != NULL))
  1142. {
  1143. for (i=0; i<NamespaceCount; i++)
  1144. {
  1145. if (NamespacePointerArray[i] != NULL)
  1146. {
  1147. ::SxspDeallocateAssemblyIdentityNamespace(NamespacePointerArray[i]);
  1148. NamespacePointerArray[i] = NULL;
  1149. }
  1150. }
  1151. FUSION_DELETE_ARRAY( NamespacePointerArray );
  1152. }
  1153. return fSuccess;
  1154. }
  1155. int __cdecl
  1156. SxspCharPairArrayComparisonCallback(
  1157. const void *pelem1,
  1158. const void *pelem2
  1159. )
  1160. {
  1161. PCCHARPAIR pcp1 = (PCCHARPAIR) pelem1;
  1162. PCCHARPAIR pcp2 = (PCCHARPAIR) pelem2;
  1163. if (pcp1->wchEnd < pcp2->wchStart)
  1164. return -1;
  1165. if (pcp2->wchEnd < pcp1->wchStart)
  1166. return 1;
  1167. return 0;
  1168. }
  1169. bool
  1170. __fastcall
  1171. SxspIsCharInCharPairArray(
  1172. WCHAR wch,
  1173. PCCHARPAIR prg,
  1174. SIZE_T n
  1175. )
  1176. {
  1177. CHARPAIR cp = { wch, wch };
  1178. return (::bsearch(&cp, prg, n, sizeof(CHARPAIR), &::SxspCharPairArrayComparisonCallback) != NULL);
  1179. }
  1180. __forceinline
  1181. bool
  1182. __fastcall
  1183. SxspIsCharXMLBaseChar(
  1184. WCHAR wch
  1185. )
  1186. {
  1187. if (wch < 0x41)
  1188. return false;
  1189. if (wch <= 0x5a)
  1190. return true;
  1191. if (wch < 0x61)
  1192. return false;
  1193. if (wch <= 0x7a)
  1194. return true;
  1195. return ::SxspIsCharInCharPairArray(wch, s_rgXMLBaseChar, NUMBER_OF(s_rgXMLBaseChar));
  1196. }
  1197. bool
  1198. __fastcall
  1199. SxspIsCharXMLIdeographic(
  1200. WCHAR wch
  1201. )
  1202. {
  1203. return (
  1204. (wch >= 0x4e00 && wch <= 0x9fa5) ||
  1205. (wch == 0x3007) ||
  1206. (wch >= 0x3021 && wch <= 0x3029)
  1207. );
  1208. }
  1209. __forceinline
  1210. bool
  1211. __fastcall
  1212. SxspIsCharXMLLetter(
  1213. WCHAR wch
  1214. )
  1215. {
  1216. return
  1217. ::SxspIsCharXMLBaseChar(wch) ||
  1218. ::SxspIsCharXMLIdeographic(wch);
  1219. }
  1220. bool
  1221. __fastcall
  1222. SxspIsCharXMLCombiningChar(
  1223. WCHAR wch
  1224. )
  1225. {
  1226. return (
  1227. (wch >= 0x0300 && wch <= 0x0345) ||
  1228. (wch >= 0x0360 && wch <= 0x0361) ||
  1229. (wch >= 0x0483 && wch <= 0x0486) ||
  1230. (wch >= 0x0591 && wch <= 0x05a1) ||
  1231. (wch >= 0x05a3 && wch <= 0x05b9) ||
  1232. (wch >= 0x05bb && wch <= 0x05bd) ||
  1233. wch == 0x05bf ||
  1234. (wch >= 0x05c1 && wch <= 0x05c2) ||
  1235. wch == 0x05c4 ||
  1236. (wch >= 0x064b && wch <= 0x0652) ||
  1237. wch == 0x0670 ||
  1238. (wch >= 0x06d6 && wch <= 0x06dc) ||
  1239. (wch >= 0x06dd && wch <= 0x06df) ||
  1240. (wch >= 0x06e0 && wch <= 0x06e4) ||
  1241. (wch >= 0x06e7 && wch <= 0x06e8) ||
  1242. (wch >= 0x06ea && wch <= 0x06ed) ||
  1243. (wch >= 0x0901 && wch <= 0x0903) ||
  1244. wch == 0x093c ||
  1245. (wch >= 0x093e && wch <= 0x094c) ||
  1246. wch == 0x094d ||
  1247. (wch >= 0x0951 && wch <= 0x0954) ||
  1248. (wch >= 0x0962 && wch <= 0x0963) ||
  1249. (wch >= 0x0981 && wch <= 0x0983) ||
  1250. wch == 0x09bc ||
  1251. wch == 0x09be ||
  1252. wch == 0x09bf ||
  1253. (wch >= 0x09c0 && wch <= 0x09c4) ||
  1254. (wch >= 0x09c7 && wch <= 0x09c8) ||
  1255. (wch >= 0x09cb && wch <= 0x09cd) ||
  1256. wch == 0x09d7 ||
  1257. (wch >= 0x09e2 && wch <= 0x09e3) ||
  1258. wch == 0x0a02 ||
  1259. wch == 0x0a3c ||
  1260. wch == 0x0a3e ||
  1261. wch == 0x0a3f ||
  1262. (wch >= 0x0a40 && wch <= 0x0a42) ||
  1263. (wch >= 0x0a47 && wch <= 0x0a48) ||
  1264. (wch >= 0x0a4b && wch <= 0x0a4d) ||
  1265. (wch >= 0x0a70 && wch <= 0x0a71) ||
  1266. (wch >= 0x0a81 && wch <= 0x0a83) ||
  1267. wch == 0x0abc ||
  1268. (wch >= 0x0abe && wch <= 0x0ac5) ||
  1269. (wch >= 0x0ac7 && wch <= 0x0ac9) ||
  1270. (wch >= 0x0acb && wch <= 0x0acd) ||
  1271. (wch >= 0x0b01 && wch <= 0x0b03) ||
  1272. wch == 0x0b3c ||
  1273. (wch >= 0x0b3e && wch <= 0x0b43) ||
  1274. (wch >= 0x0b47 && wch <= 0x0b48) ||
  1275. (wch >= 0x0b4b && wch <= 0x0b4d) ||
  1276. (wch >= 0x0b56 && wch <= 0x0b57) ||
  1277. (wch >= 0x0b82 && wch <= 0x0b83) ||
  1278. (wch >= 0x0bbe && wch <= 0x0bc2) ||
  1279. (wch >= 0x0bc6 && wch <= 0x0bc8) ||
  1280. (wch >= 0x0bca && wch <= 0x0bcd) ||
  1281. wch == 0x0bd7 ||
  1282. (wch >= 0x0c01 && wch <= 0x0c03) ||
  1283. (wch >= 0x0c3e && wch <= 0x0c44) ||
  1284. (wch >= 0x0c46 && wch <= 0x0c48) ||
  1285. (wch >= 0x0c4a && wch <= 0x0c4d) ||
  1286. (wch >= 0x0c55 && wch <= 0x0c56) ||
  1287. (wch >= 0x0c82 && wch <= 0x0c83) ||
  1288. (wch >= 0x0cbe && wch <= 0x0cc4) ||
  1289. (wch >= 0x0cc6 && wch <= 0x0cc8) ||
  1290. (wch >= 0x0cca && wch <= 0x0ccd) ||
  1291. (wch >= 0x0cd5 && wch <= 0x0cd6) ||
  1292. (wch >= 0x0d02 && wch <= 0x0d03) ||
  1293. (wch >= 0x0d3e && wch <= 0x0d43) ||
  1294. (wch >= 0x0d46 && wch <= 0x0d48) ||
  1295. (wch >= 0x0d4a && wch <= 0x0d4d) ||
  1296. wch == 0x0d57 ||
  1297. wch == 0x0e31 ||
  1298. (wch >= 0x0e34 && wch <= 0x0e3a) ||
  1299. (wch >= 0x0e47 && wch <= 0x0e4e) ||
  1300. wch == 0x0eb1 ||
  1301. (wch >= 0x0eb4 && wch <= 0x0eb9) ||
  1302. (wch >= 0x0ebb && wch <= 0x0ebc) ||
  1303. (wch >= 0x0ec8 && wch <= 0x0ecd) ||
  1304. (wch >= 0x0f18 && wch <= 0x0f19) ||
  1305. wch == 0x0f35 ||
  1306. wch == 0x0f37 ||
  1307. wch == 0x0f39 ||
  1308. wch == 0x0f3e ||
  1309. wch == 0x0f3f ||
  1310. (wch >= 0x0f71 && wch <= 0x0f84) ||
  1311. (wch >= 0x0f86 && wch <= 0x0f8b) ||
  1312. (wch >= 0x0f90 && wch <= 0x0f95) ||
  1313. wch == 0x0f97 ||
  1314. (wch >= 0x0f99 && wch <= 0x0fad) ||
  1315. (wch >= 0x0fb1 && wch <= 0x0fb7) ||
  1316. wch == 0x0fb9 ||
  1317. (wch >= 0x20d0 && wch <= 0x20dc) ||
  1318. wch == 0x20e1 ||
  1319. (wch >= 0x302a && wch <= 0x302f) ||
  1320. wch == 0x3099 ||
  1321. wch == 0x309a
  1322. );
  1323. }
  1324. __forceinline
  1325. bool
  1326. __fastcall
  1327. SxspIsCharXMLDigit(
  1328. WCHAR wch
  1329. )
  1330. {
  1331. return (
  1332. (wch >= 0x0030 && wch <= 0x0039) ||
  1333. (wch >= 0x0660 && wch <= 0x0669) ||
  1334. (wch >= 0x06f0 && wch <= 0x06f9) ||
  1335. (wch >= 0x0966 && wch <= 0x096f) ||
  1336. (wch >= 0x09e6 && wch <= 0x09ef) ||
  1337. (wch >= 0x0a66 && wch <= 0x0a6f) ||
  1338. (wch >= 0x0ae6 && wch <= 0x0aef) ||
  1339. (wch >= 0x0b66 && wch <= 0x0b6f) ||
  1340. (wch >= 0x0be7 && wch <= 0x0bef) ||
  1341. (wch >= 0x0c66 && wch <= 0x0c6f) ||
  1342. (wch >= 0x0ce6 && wch <= 0x0cef) ||
  1343. (wch >= 0x0d66 && wch <= 0x0d6f) ||
  1344. (wch >= 0x0e50 && wch <= 0x0e59) ||
  1345. (wch >= 0x0ed0 && wch <= 0x0ed9) ||
  1346. (wch >= 0x0f20 && wch <= 0x0f29)
  1347. );
  1348. }
  1349. __forceinline
  1350. bool
  1351. __fastcall
  1352. SxspIsCharXMLExtender(
  1353. WCHAR wch
  1354. )
  1355. {
  1356. return (
  1357. wch == 0x00b7 ||
  1358. wch == 0x02d0 ||
  1359. wch == 0x02d1 ||
  1360. wch == 0x0387 ||
  1361. wch == 0x0640 ||
  1362. wch == 0x0e46 ||
  1363. wch == 0x0ec6 ||
  1364. wch == 0x3005 ||
  1365. (wch >= 0x3031 && wch <= 0x3035) ||
  1366. (wch >= 0x309d && wch <= 0x309e) ||
  1367. (wch >= 0x30fc && wch <= 0x30fe)
  1368. );
  1369. }
  1370. BOOL
  1371. SxspValidateXMLName(
  1372. PCWSTR psz,
  1373. SIZE_T cch,
  1374. bool &rfValid
  1375. )
  1376. {
  1377. BOOL fSuccess = FALSE;
  1378. FN_TRACE_WIN32(fSuccess);
  1379. SIZE_T i;
  1380. rfValid = false;
  1381. // [4] NameChar ::= Letter | Digit | '.' | '-' | '_' | ':' | CombiningChar | Extender
  1382. // [5] Name ::= (Letter | '_' | ':') (NameChar)*
  1383. if (cch >= 1)
  1384. {
  1385. WCHAR wch = psz[0];
  1386. if (::SxspIsCharXMLLetter(wch) ||
  1387. (wch == L'_') ||
  1388. (wch == L':'))
  1389. {
  1390. for (i=1; i<cch; i++)
  1391. {
  1392. wch = psz[i];
  1393. if (!::SxspIsCharXMLLetter(wch) &&
  1394. !::SxspIsCharXMLDigit(wch) &&
  1395. (wch != L'.') &&
  1396. (wch != L'-') &&
  1397. (wch != L'_') &&
  1398. (wch != L':') &&
  1399. !::SxspIsCharXMLCombiningChar(wch) &&
  1400. !::SxspIsCharXMLExtender(wch))
  1401. break;
  1402. }
  1403. if (i == cch)
  1404. rfValid = true;
  1405. }
  1406. }
  1407. FN_EPILOG
  1408. }