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.

1749 lines
54 KiB

  1. /*++
  2. Copyright (c) 1989 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. // First, we know we need a header.
  270. Size = sizeof(ENCODED_ASSEMBLY_IDENTITY_HEADER);
  271. // Then a ULONG hash per attribute:
  272. Size += (AssemblyIdentity->AttributeCount * sizeof(ULONG));
  273. // Then a USHORT per namespace...
  274. Size += (AssemblyIdentity->NamespaceCount * sizeof(ULONG));
  275. // Then we need an attribute header per attribute:
  276. Size += AssemblyIdentity->AttributeCount * sizeof(ENCODED_ASSEMBLY_IDENTITY_ATTRIBUTE_HEADER);
  277. // Then come the namespace strings...
  278. for (i=0; i<NamespaceCount; i++)
  279. Size += NamespacePointerArray[i]->NamespaceCch * sizeof(WCHAR);
  280. // Then we need space for each of the attributes' names and value.
  281. AttributePointerArray = AssemblyIdentity->AttributePointerArray;
  282. for (i=0; i<AttributeCount; i++)
  283. {
  284. INTERNAL_ERROR_CHECK(AttributePointerArray[i] != NULL);
  285. Size += AttributePointerArray[i]->Attribute.NameCch * sizeof(WCHAR);
  286. Size += AttributePointerArray[i]->Attribute.ValueCch * sizeof(WCHAR);
  287. }
  288. // We should at least be byte aligned here...
  289. ASSERT((Size % 2) == 0);
  290. // And finally pad out to a multiple of four if we are not...
  291. Size = (Size + 3) & ~3;
  292. break;
  293. case SXS_ASSEMBLY_IDENTITY_ENCODING_DEFAULTGROUP_TEXTUAL:
  294. for (i=0; i<AttributeCount; i++)
  295. {
  296. PCINTERNAL_ASSEMBLY_IDENTITY_ATTRIBUTE Attribute = AttributePointerArray[i];
  297. BOOL IsAssemblyName = FALSE;
  298. SIZE_T BytesThisAttribute = 0;
  299. INTERNAL_ERROR_CHECK(Attribute != NULL);
  300. IFW32FALSE_EXIT(SxspIsInternalAssemblyIdentityAttribute(
  301. 0,
  302. Attribute,
  303. NULL,
  304. 0,
  305. SXS_ASSEMBLY_IDENTITY_STD_ATTRIBUTE_NAME_NAME,
  306. NUMBER_OF(SXS_ASSEMBLY_IDENTITY_STD_ATTRIBUTE_NAME_NAME) - 1,
  307. &IsAssemblyName));
  308. // It's the attribute name. Just account for the size of the encoded value string
  309. IFW32FALSE_EXIT(::SxspComputeInternalAssemblyIdentityAttributeEncodedTextualSize(
  310. IsAssemblyName ?
  311. SXSP_COMPUTE_INTERNAL_ASSEMBLY_IDENTITY_ATTRIBUTE_ENCODED_TEXTUAL_SIZE_FLAG_VALUE_ONLY |
  312. SXSP_COMPUTE_INTERNAL_ASSEMBLY_IDENTITY_ATTRIBUTE_ENCODED_TEXTUAL_SIZE_FLAG_OMIT_QUOTES
  313. : 0,
  314. Attribute,
  315. &BytesThisAttribute));
  316. // Account for the separator character
  317. if (i != 0)
  318. Size += sizeof(WCHAR);
  319. Size += BytesThisAttribute;
  320. }
  321. break;
  322. }
  323. *SizeOut = Size;
  324. fSuccess = TRUE;
  325. Exit:
  326. return fSuccess;
  327. }
  328. BOOL
  329. SxspComputeQuotedStringSize(
  330. IN DWORD Flags,
  331. IN const WCHAR *StringIn,
  332. IN SIZE_T Cch,
  333. OUT SIZE_T *BytesOut
  334. )
  335. {
  336. BOOL fSuccess = FALSE;
  337. FN_TRACE_WIN32(fSuccess);
  338. SIZE_T Bytes = 0;
  339. if (BytesOut != NULL)
  340. *BytesOut = 0;
  341. PARAMETER_CHECK(Flags == 0);
  342. PARAMETER_CHECK(StringIn != NULL || Cch == 0);
  343. PARAMETER_CHECK(BytesOut != NULL);
  344. while (Cch != 0)
  345. {
  346. const WCHAR wch = *StringIn++;
  347. if (((wch >= L'A') && (wch <= L'Z')) ||
  348. ((wch >= L'a') && (wch <= L'z')) ||
  349. ((wch >= L'0') && (wch <= L'9')) ||
  350. (wch == L'.') ||
  351. (wch == L'-') ||
  352. (wch == L'_'))
  353. {
  354. Bytes += sizeof(WCHAR);
  355. }
  356. else
  357. {
  358. switch (wch)
  359. {
  360. case L'&':
  361. // &amp;
  362. Bytes += (5 * sizeof(WCHAR));
  363. break;
  364. case L'"':
  365. // &quot;
  366. Bytes += (6 * sizeof(WCHAR));
  367. break;
  368. case L'<':
  369. // &lt;
  370. Bytes += (4 * sizeof(WCHAR));
  371. break;
  372. case L'>':
  373. // &gt;
  374. Bytes += (4 * sizeof(WCHAR));
  375. break;
  376. case L'\'':
  377. // &apos;
  378. Bytes += (6 * sizeof(WCHAR));
  379. break;
  380. default:
  381. // Otherwise, it's going to be &#xn;
  382. if (wch < 0x10)
  383. Bytes += (5 * sizeof(WCHAR));
  384. else if (wch < 0x100)
  385. Bytes += (6 * sizeof(WCHAR));
  386. else if (wch < 0x1000)
  387. Bytes += (7 * sizeof(WCHAR));
  388. else
  389. Bytes += (8 * sizeof(WCHAR));
  390. break;
  391. }
  392. }
  393. Cch--;
  394. }
  395. *BytesOut = Bytes;
  396. fSuccess = TRUE;
  397. Exit:
  398. return fSuccess;
  399. }
  400. #if 0
  401. #define QUOTE_CHAR_HEADER_STRING (L"&#x")
  402. #define QUOTE_CHAR_HEADER_STRING_CCH (NUMBER_OF(QUOTE_CHAR_HEADER_STRING) - 1)
  403. BOOL
  404. SxspQuoteString(
  405. IN DWORD dwFlags,
  406. IN PCWSTR pcwszStringIn,
  407. IN SIZE_T cbStringInCch,
  408. OUT PWSTR pwszStringOut,
  409. IN OUT SIZE_T *pcbWrittenBytes
  410. )
  411. {
  412. FN_PROLOG_WIN32
  413. SIZE_T cbOutputBuffer;
  414. PCWSTR pcwszCursor = pcwszStringIn;
  415. PWSTR pwszOutputCursor = pwszStringOut;
  416. BOOL fInsufficient = FALSE;
  417. if ( pcbWrittenBytes != NULL ) {
  418. cbOutputBuffer = *pcbWrittenBytes;
  419. *pcbWrittenBytes = 0
  420. }
  421. if ( pwszStringOut == NULL )
  422. {
  423. cbOutputBuffer = NULL;
  424. pwszOutputCursor = NULL;
  425. }
  426. while ( ( cbStringInCch != 0 ) && ( pcwszCursor != NULL ) )
  427. {
  428. ULONG ulFoundQuoteMatch;
  429. SIZE_T cchReplacement;
  430. PCWSTR pcwszReplacement;
  431. const WCHAR wchThisCharacter = *pcwszCursor;
  432. // Some characters we know and love
  433. if (iswalnum(wchThisCharacter) ||
  434. (wchThisCharacter == L'.') ||
  435. (wchThisCharacter == L'_') ||
  436. (wchThisCharacter == L'-'))
  437. {
  438. if ( cbOutputBuffer > 0 )
  439. {
  440. *pwszOutputCursor++ = wchThisCharacter;
  441. cbOutputBuffer--;
  442. }
  443. (*pcbWrittenBytes)++;
  444. continue;
  445. }
  446. #define ADD_IF_REMAINING_AND_UPDATE( target, targetcch, targetcchoutput, toadd, toaddcch ) { \
  447. if ( (targetcch) > (toaddcch) ) { \
  448. wcsncpy( target, toadd, toaddcch ); \
  449. (targetcch) -= (toaddcch); } \
  450. (targetcchoutput) += toaddcch; }
  451. #define HANDLE_CASE(c, v) case (c) : \
  452. if (cbOutputBuffer > NUMBER_OF(v)) { \
  453. wcsncpy(pwszOutputCursor, (v), NUMBER_OF(v)); \
  454. pwszOutputCursor += NUMBER_OF(v); \
  455. cbOutputBuffer -= NUMBER_OF(v);\
  456. (*cbOutputBuffer) += NUMBER_OF(v); \
  457. } else fInsufficient = TRUE; \
  458. break;
  459. switch( wchThisCharacter )
  460. {
  461. HANDLE_CASE(L'"', L"&quot;")
  462. HANDLE_CASE(L'&', L"&amp;")
  463. HANDLE_CASE(L'<', L"&lt;")
  464. HANDLE_CASE(L'>', L"&gt;")
  465. HANDLE_CASE(L'\'', L"&apos;")
  466. #define ADD_ESCAPE_HEADER_AND_INCREMENT(h) (h)[0] = L'&'; (h)[1] = L'#'; (h)[2] = L'x'; (h) += 3;
  467. default:
  468. if (wchThisCharacter < 0x10) {
  469. ADD_IF_REMAINING_AND_UPDATE(
  470. pwszOutputCursor,
  471. cbOutputBuffer,
  472. (*pcbWrittenBytes),
  473. QUOTE_CHAR_HEADER_STRING,
  474. QUOTE_CHAR_HEADER_STRING_CCH);
  475. pwszOutputCursor[0] = s_rgHexChars[wchThisCharacter & 0xf];
  476. APPEND_TAIL_AND_INCREMENT(
  477. } else if (wchThisCharacter < 0x100) {
  478. } else if (wchThisCharacter < 0x1000) {
  479. } else if (wchThisCharacter <= 0xffff) {
  480. }
  481. }
  482. }
  483. FN_EPILOG
  484. }
  485. #endif
  486. BOOL
  487. SxspDequoteString(
  488. IN DWORD dwFlags,
  489. IN PCWSTR pcwszStringIn,
  490. IN SIZE_T cchStringIn,
  491. OUT PWSTR pwszStringOut,
  492. OUT SIZE_T *pcchStringOut
  493. )
  494. {
  495. FN_PROLOG_WIN32
  496. PCWSTR pcwszInputCursor = pcwszStringIn;
  497. PWSTR pwszOutputCursor = pwszStringOut;
  498. PCWSTR pcwszInputCursorEnd = pcwszStringIn + cchStringIn;
  499. SIZE_T cchOutputRemaining = 0;
  500. BOOL fInsufficient = FALSE;
  501. PARAMETER_CHECK(dwFlags == 0);
  502. if (pcchStringOut != NULL)
  503. {
  504. cchOutputRemaining = *pcchStringOut;
  505. *pcchStringOut = 0;
  506. }
  507. if (pwszStringOut != NULL)
  508. pwszStringOut[0] = UNICODE_NULL;
  509. PARAMETER_CHECK(pcchStringOut != NULL);
  510. //
  511. // reserve one wchar for trailing NULL
  512. //
  513. #define APPEND_OUTPUT_CHARACTER( toadd ) { \
  514. if ( cchOutputRemaining > 1 ) { \
  515. *pwszOutputCursor++ = (toadd); \
  516. cchOutputRemaining--; \
  517. (*pcchStringOut)++; \
  518. } else fInsufficient = TRUE; \
  519. }
  520. #define CONTAINS_TAG(tag) (FusionpCompareStrings(pcwszInputCursor, cchToNextSemicolon, (tag), NUMBER_OF(tag)-1, false) == 0)
  521. #define REPLACE_TAG( tag, newchar ) if ( CONTAINS_TAG(tag) ) { APPEND_OUTPUT_CHARACTER(newchar) }
  522. //
  523. // Zing through the input string until there's nothing left
  524. //
  525. while ((pcwszInputCursor < pcwszInputCursorEnd) && (!fInsufficient))
  526. {
  527. const WCHAR wchCurrent = *pcwszInputCursor;
  528. // Something we know and love?
  529. if (wchCurrent == L'&')
  530. {
  531. pcwszInputCursor++;
  532. SIZE_T cchToNextSemicolon = StringComplimentSpan(
  533. pcwszInputCursor,
  534. pcwszInputCursorEnd,
  535. L";");
  536. PCWSTR pcwszSemicolon = pcwszInputCursor + cchToNextSemicolon;
  537. REPLACE_TAG(L"amp", L'&')
  538. else REPLACE_TAG(L"quot", L'"')
  539. else REPLACE_TAG(L"lt", L'<')
  540. else REPLACE_TAG(L"gt", L'>')
  541. else REPLACE_TAG(L"apos", L'\'')
  542. // This might be an encoded character...
  543. else if ( cchToNextSemicolon >= 2 )
  544. {
  545. bool fIsHexString = false;
  546. WCHAR wchReplacement = 0;
  547. // The only non-chunk think accepted is the # character
  548. PARAMETER_CHECK(*pcwszInputCursor == L'#');
  549. // which means we've skipped one
  550. pcwszInputCursor++;
  551. fIsHexString = (*pcwszInputCursor == L'x') || (*pcwszInputCursor == 'X');
  552. if (fIsHexString) {
  553. pcwszInputCursor++;
  554. }
  555. while ( pcwszInputCursor != pcwszSemicolon )
  556. {
  557. if ( fIsHexString )
  558. {
  559. wchReplacement <<= 4;
  560. switch ( *pcwszInputCursor++ ) {
  561. case L'0' : break;
  562. case L'1' : wchReplacement += 0x1; break;
  563. case L'2' : wchReplacement += 0x2; break;
  564. case L'3' : wchReplacement += 0x3; break;
  565. case L'4' : wchReplacement += 0x4; break;
  566. case L'5' : wchReplacement += 0x5; break;
  567. case L'6' : wchReplacement += 0x6; break;
  568. case L'7' : wchReplacement += 0x7; break;
  569. case L'8' : wchReplacement += 0x8; break;
  570. case L'9' : wchReplacement += 0x9; break;
  571. case L'a': case L'A': wchReplacement += 0xA; break;
  572. case L'b': case L'B': wchReplacement += 0xB; break;
  573. case L'c': case L'C': wchReplacement += 0xC; break;
  574. case L'd': case L'D': wchReplacement += 0xD; break;
  575. case L'e': case L'E': wchReplacement += 0xE; break;
  576. case L'f': case L'F': wchReplacement += 0xF; break;
  577. default:
  578. PARAMETER_CHECK(FALSE && L"wchReplacement contains a non-hex digit");
  579. break;
  580. }
  581. }
  582. else
  583. {
  584. wchReplacement *= 10;
  585. switch ( *pcwszInputCursor++ ) {
  586. case L'0' : break;
  587. case L'1' : wchReplacement += 0x1; break;
  588. case L'2' : wchReplacement += 0x2; break;
  589. case L'3' : wchReplacement += 0x3; break;
  590. case L'4' : wchReplacement += 0x4; break;
  591. case L'5' : wchReplacement += 0x5; break;
  592. case L'6' : wchReplacement += 0x6; break;
  593. case L'7' : wchReplacement += 0x7; break;
  594. case L'8' : wchReplacement += 0x8; break;
  595. case L'9' : wchReplacement += 0x9; break;
  596. default:
  597. PARAMETER_CHECK(FALSE && "wchReplacement contains a non-decimal digit");
  598. break;
  599. }
  600. }
  601. }
  602. APPEND_OUTPUT_CHARACTER(wchReplacement);
  603. }
  604. if (!fInsufficient)
  605. pcwszInputCursor = pcwszSemicolon + 1;
  606. }
  607. // Otherwise, simply copy the character to the output string
  608. else
  609. {
  610. APPEND_OUTPUT_CHARACTER(wchCurrent);
  611. if (!fInsufficient)
  612. pcwszInputCursor++;
  613. }
  614. }
  615. if (fInsufficient)
  616. ORIGINATE_WIN32_FAILURE_AND_EXIT(NoRoom, ERROR_INSUFFICIENT_BUFFER);
  617. pwszStringOut[*pcchStringOut] = L'\0';
  618. FN_EPILOG
  619. }
  620. BOOL
  621. SxspQuoteString(
  622. IN DWORD Flags,
  623. IN const WCHAR *StringIn,
  624. IN SIZE_T Cch,
  625. IN SIZE_T BufferSize,
  626. IN PVOID Buffer,
  627. OUT SIZE_T *BytesWrittenOut
  628. )
  629. {
  630. BOOL fSuccess = FALSE;
  631. FN_TRACE_WIN32(fSuccess);
  632. WCHAR *Cursor;
  633. SIZE_T BytesWritten = 0;
  634. SIZE_T BytesLeft = BufferSize;
  635. if (BytesWrittenOut != NULL)
  636. *BytesWrittenOut = 0;
  637. PARAMETER_CHECK(Flags == 0);
  638. PARAMETER_CHECK(StringIn != NULL || Cch == 0);
  639. PARAMETER_CHECK(Buffer != NULL || BufferSize == 0);
  640. Cursor = (WCHAR *) Buffer;
  641. BytesWritten = 0;
  642. while (Cch != 0)
  643. {
  644. const WCHAR wch = *StringIn++;
  645. if (((wch >= L'A') && (wch <= L'Z')) ||
  646. ((wch >= L'a') && (wch <= L'z')) ||
  647. ((wch >= L'0') && (wch <= L'9')) ||
  648. (wch == L'.') ||
  649. (wch == L'-') ||
  650. (wch == L'_'))
  651. {
  652. if (BytesLeft < sizeof(WCHAR))
  653. ORIGINATE_WIN32_FAILURE_AND_EXIT(NoRoom, ERROR_INSUFFICIENT_BUFFER);
  654. *Cursor++ = wch;
  655. BytesLeft -= sizeof(WCHAR);
  656. BytesWritten += sizeof(WCHAR);
  657. }
  658. else
  659. {
  660. #define HANDLE_CASE(_wch, _wstr) \
  661. case _wch: \
  662. { \
  663. ULONG i; \
  664. if (BytesLeft < (sizeof(_wstr) - sizeof(WCHAR))) \
  665. ORIGINATE_WIN32_FAILURE_AND_EXIT(NoRoom, ERROR_INSUFFICIENT_BUFFER); \
  666. for (i=0; i<(NUMBER_OF(_wstr) - 1); i++) \
  667. *Cursor++ = _wstr[i]; \
  668. BytesLeft -= (sizeof(_wstr) - sizeof(WCHAR)); \
  669. BytesWritten += (sizeof(_wstr) - sizeof(WCHAR)); \
  670. break; \
  671. }
  672. switch (wch)
  673. {
  674. HANDLE_CASE(L'"', L"&quot;")
  675. HANDLE_CASE(L'&', L"&amp;")
  676. HANDLE_CASE(L'<', L"&lt;")
  677. HANDLE_CASE(L'>', L"&gt;")
  678. HANDLE_CASE(L'\'', L"&apos;")
  679. default:
  680. if (wch < 0x10)
  681. {
  682. if (BytesLeft < (5 * sizeof(WCHAR)))
  683. ORIGINATE_WIN32_FAILURE_AND_EXIT(NoRoom, ERROR_INSUFFICIENT_BUFFER);
  684. *Cursor++ = L'&';
  685. *Cursor++ = L'#';
  686. *Cursor++ = L'x';
  687. *Cursor++ = s_rgHexChars[wch];
  688. *Cursor++ = L';';
  689. BytesWritten += (5 * sizeof(WCHAR));
  690. BytesLeft -= (5 * sizeof(WCHAR));
  691. }
  692. else if (wch < 0x100)
  693. {
  694. if (BytesLeft < (6 * sizeof(WCHAR)))
  695. ORIGINATE_WIN32_FAILURE_AND_EXIT(NoRoom, ERROR_INSUFFICIENT_BUFFER);
  696. *Cursor++ = L'&';
  697. *Cursor++ = L'#';
  698. *Cursor++ = L'x';
  699. *Cursor++ = s_rgHexChars[(wch >> 4) & 0xf];
  700. *Cursor++ = s_rgHexChars[wch & 0xf];
  701. *Cursor++ = L';';
  702. BytesWritten += (6 * sizeof(WCHAR));
  703. BytesLeft -= (6 * sizeof(WCHAR));
  704. }
  705. else if (wch < 0x1000)
  706. {
  707. if (BytesLeft < (7 * sizeof(WCHAR)))
  708. ORIGINATE_WIN32_FAILURE_AND_EXIT(NoRoom, ERROR_INSUFFICIENT_BUFFER);
  709. *Cursor++ = L'&';
  710. *Cursor++ = L'#';
  711. *Cursor++ = L'x';
  712. *Cursor++ = s_rgHexChars[(wch >> 8) & 0xf];
  713. *Cursor++ = s_rgHexChars[(wch >> 4) & 0xf];
  714. *Cursor++ = s_rgHexChars[wch & 0xf];
  715. *Cursor++ = L';';
  716. BytesWritten += (7 * sizeof(WCHAR));
  717. BytesLeft -= (7 * sizeof(WCHAR));
  718. }
  719. else
  720. {
  721. INTERNAL_ERROR_CHECK(wch <= 0xffff);
  722. if (BytesLeft < (8 * sizeof(WCHAR)))
  723. ORIGINATE_WIN32_FAILURE_AND_EXIT(NoRoom, ERROR_INSUFFICIENT_BUFFER);
  724. *Cursor++ = L'&';
  725. *Cursor++ = L'#';
  726. *Cursor++ = L'x';
  727. *Cursor++ = s_rgHexChars[(wch >> 12) & 0xf];
  728. *Cursor++ = s_rgHexChars[(wch >> 8) & 0xf];
  729. *Cursor++ = s_rgHexChars[(wch >> 4) & 0xf];
  730. *Cursor++ = s_rgHexChars[wch & 0xf];
  731. *Cursor++ = L';';
  732. BytesWritten += (8 * sizeof(WCHAR));
  733. BytesLeft -= (8 * sizeof(WCHAR));
  734. }
  735. break;
  736. }
  737. }
  738. Cch--;
  739. }
  740. if (BytesWrittenOut != NULL)
  741. *BytesWrittenOut = BytesWritten;
  742. fSuccess = TRUE;
  743. Exit:
  744. return fSuccess;
  745. }
  746. BOOL
  747. SxspComputeInternalAssemblyIdentityAttributeEncodedTextualSize(
  748. IN DWORD Flags,
  749. IN PCINTERNAL_ASSEMBLY_IDENTITY_ATTRIBUTE Attribute,
  750. OUT SIZE_T *BytesOut
  751. )
  752. {
  753. BOOL fSuccess = FALSE;
  754. FN_TRACE_WIN32(fSuccess);
  755. SIZE_T Bytes = 0;
  756. SIZE_T BytesTemp = 0;
  757. if (BytesOut != NULL)
  758. *BytesOut = 0;
  759. PARAMETER_CHECK((Flags & ~(
  760. SXSP_COMPUTE_INTERNAL_ASSEMBLY_IDENTITY_ATTRIBUTE_ENCODED_TEXTUAL_SIZE_FLAG_VALUE_ONLY |
  761. SXSP_COMPUTE_INTERNAL_ASSEMBLY_IDENTITY_ATTRIBUTE_ENCODED_TEXTUAL_SIZE_FLAG_OMIT_QUOTES)) == 0);
  762. PARAMETER_CHECK(Attribute != NULL);
  763. PARAMETER_CHECK(BytesOut != NULL);
  764. Bytes = 0;
  765. if ((Flags & SXSP_COMPUTE_INTERNAL_ASSEMBLY_IDENTITY_ATTRIBUTE_ENCODED_TEXTUAL_SIZE_FLAG_VALUE_ONLY) == 0)
  766. {
  767. if (Attribute->Attribute.NamespaceCch != 0)
  768. {
  769. // Figure out the ns:n= part
  770. IFW32FALSE_EXIT(::SxspComputeQuotedStringSize(0, Attribute->Attribute.Namespace, Attribute->Attribute.NamespaceCch, &BytesTemp));
  771. Bytes += BytesTemp;
  772. Bytes += sizeof(WCHAR); // the ":"
  773. }
  774. IFW32FALSE_EXIT(::SxspComputeQuotedStringSize(0, Attribute->Attribute.Name, Attribute->Attribute.NameCch, &BytesTemp));
  775. Bytes += BytesTemp;
  776. Bytes += sizeof(WCHAR); // the "="
  777. }
  778. IFW32FALSE_EXIT(::SxspComputeQuotedStringSize(0, Attribute->Attribute.Value, Attribute->Attribute.ValueCch, &BytesTemp));
  779. Bytes += BytesTemp;
  780. if ((Flags & SXSP_COMPUTE_INTERNAL_ASSEMBLY_IDENTITY_ATTRIBUTE_ENCODED_TEXTUAL_SIZE_FLAG_OMIT_QUOTES) == 0)
  781. Bytes += 2 * sizeof(WCHAR); // the beginning and ending quotes
  782. *BytesOut = Bytes;
  783. fSuccess = TRUE;
  784. Exit:
  785. return fSuccess;
  786. }
  787. BOOL
  788. SxspEncodeInternalAssemblyIdentityAttributeAsText(
  789. IN DWORD Flags,
  790. IN PCINTERNAL_ASSEMBLY_IDENTITY_ATTRIBUTE Attribute,
  791. SIZE_T BufferSize,
  792. PVOID Buffer,
  793. SIZE_T *BytesWrittenOut
  794. )
  795. {
  796. BOOL fSuccess = FALSE;
  797. FN_TRACE_WIN32(fSuccess);
  798. SIZE_T BytesWritten = 0;
  799. SIZE_T BytesLeft = 0;
  800. SIZE_T BytesThisSegment;
  801. WCHAR *Cursor;
  802. if (BytesWrittenOut != NULL)
  803. *BytesWrittenOut = 0;
  804. PARAMETER_CHECK(Flags == 0);
  805. PARAMETER_CHECK(Attribute != NULL);
  806. PARAMETER_CHECK((Buffer != NULL) || (BufferSize == 0));
  807. BytesWritten = 0;
  808. BytesLeft = BufferSize;
  809. Cursor = reinterpret_cast<WCHAR *>(Buffer);
  810. if (Attribute->Attribute.NamespaceCch != 0)
  811. {
  812. IFW32FALSE_EXIT(::SxspQuoteString(0, Attribute->Namespace->Namespace, Attribute->Namespace->NamespaceCch, BytesLeft, Cursor, &BytesThisSegment));
  813. INTERNAL_ERROR_CHECK(BytesThisSegment <= BytesLeft);
  814. Cursor = (WCHAR *) (((ULONG_PTR) Cursor) + BytesThisSegment);
  815. BytesLeft -= BytesThisSegment;
  816. BytesWritten += BytesThisSegment;
  817. if (BytesLeft < sizeof(WCHAR))
  818. ORIGINATE_WIN32_FAILURE_AND_EXIT(NoRoom, ERROR_INSUFFICIENT_BUFFER);
  819. *Cursor++ = L':';
  820. BytesLeft -= sizeof(WCHAR);
  821. BytesWritten += sizeof(WCHAR);
  822. }
  823. IFW32FALSE_EXIT(::SxspQuoteString(0, Attribute->Attribute.Name, Attribute->Attribute.NameCch, BytesLeft, Cursor, &BytesThisSegment));
  824. INTERNAL_ERROR_CHECK(BytesThisSegment <= BytesLeft);
  825. Cursor = (WCHAR *) (((ULONG_PTR) Cursor) + BytesThisSegment);
  826. BytesLeft -= BytesThisSegment;
  827. BytesWritten += BytesThisSegment;
  828. if (BytesLeft < (2 * sizeof(WCHAR)))
  829. ORIGINATE_WIN32_FAILURE_AND_EXIT(NoRoom, ERROR_INSUFFICIENT_BUFFER);
  830. *Cursor++ = L'=';
  831. *Cursor++ = L'"';
  832. BytesLeft -= (2 * sizeof(WCHAR));
  833. BytesWritten += (2 * sizeof(WCHAR));
  834. IFW32FALSE_EXIT(::SxspQuoteString(0, Attribute->Attribute.Value, Attribute->Attribute.ValueCch, BytesLeft, Cursor, &BytesThisSegment));
  835. INTERNAL_ERROR_CHECK(BytesThisSegment <= BytesLeft);
  836. Cursor = (WCHAR *) (((ULONG_PTR) Cursor) + BytesThisSegment);
  837. BytesLeft -= BytesThisSegment;
  838. BytesWritten += BytesThisSegment;
  839. if (BytesLeft < sizeof(WCHAR))
  840. ORIGINATE_WIN32_FAILURE_AND_EXIT(NoRoom, ERROR_INSUFFICIENT_BUFFER);
  841. *Cursor++ = L'"';
  842. BytesLeft -= sizeof(WCHAR);
  843. BytesWritten += sizeof(WCHAR);
  844. *BytesWrittenOut = BytesWritten;
  845. fSuccess = TRUE;
  846. Exit:
  847. return fSuccess;
  848. }
  849. BOOL
  850. SxspEncodeAssemblyIdentityTextually(
  851. IN DWORD Flags,
  852. IN PCASSEMBLY_IDENTITY AssemblyIdentity,
  853. IN SIZE_T BufferSize,
  854. IN PVOID Buffer,
  855. OUT SIZE_T *BytesWrittenOut)
  856. {
  857. BOOL fSuccess = FALSE;
  858. FN_TRACE_WIN32(fSuccess);
  859. ULONG AttributeCount, NamespaceCount;
  860. PCINTERNAL_ASSEMBLY_IDENTITY_ATTRIBUTE *Attributes;
  861. PCASSEMBLY_IDENTITY_NAMESPACE *Namespaces;
  862. ULONG i;
  863. ASSEMBLY_IDENTITY_ATTRIBUTE Attribute;
  864. PCINTERNAL_ASSEMBLY_IDENTITY_ATTRIBUTE NameInternalAttribute = NULL;
  865. SIZE_T BytesLeft;
  866. SIZE_T BytesWritten;
  867. PVOID Cursor;
  868. SIZE_T TempBytesWritten;
  869. if (BytesWrittenOut != NULL)
  870. *BytesWrittenOut = 0;
  871. PARAMETER_CHECK(Flags == 0);
  872. PARAMETER_CHECK(AssemblyIdentity != NULL);
  873. PARAMETER_CHECK(BufferSize != 0);
  874. PARAMETER_CHECK(Buffer != NULL);
  875. PARAMETER_CHECK(BytesWrittenOut != NULL);
  876. Cursor = Buffer;
  877. BytesLeft = BufferSize;
  878. BytesWritten = 0;
  879. // The root assembly identity is actually totally empty, so we'll short-circuit that case.
  880. AttributeCount = AssemblyIdentity->AttributeCount;
  881. if (AttributeCount != 0)
  882. {
  883. NamespaceCount = AssemblyIdentity->NamespaceCount;
  884. Attributes = AssemblyIdentity->AttributePointerArray;
  885. Namespaces = AssemblyIdentity->NamespacePointerArray;
  886. // First, let's look for the "name" attribute.
  887. Attribute.Flags = 0;
  888. Attribute.Namespace = NULL;
  889. Attribute.NamespaceCch = 0;
  890. Attribute.Name = SXS_ASSEMBLY_IDENTITY_STD_ATTRIBUTE_NAME_NAME;
  891. Attribute.NameCch = NUMBER_OF(SXS_ASSEMBLY_IDENTITY_STD_ATTRIBUTE_NAME_NAME) - 1;
  892. IFW32FALSE_EXIT(
  893. ::SxspLocateInternalAssemblyIdentityAttribute(
  894. SXSP_LOCATE_INTERNAL_ASSEMBLY_IDENTITY_ATTRIBUTE_FLAG_MATCH_NAMESPACE |
  895. SXSP_LOCATE_INTERNAL_ASSEMBLY_IDENTITY_ATTRIBUTE_FLAG_MATCH_NAME,
  896. AssemblyIdentity,
  897. &Attribute,
  898. &NameInternalAttribute,
  899. NULL));
  900. INTERNAL_ERROR_CHECK(NameInternalAttribute != NULL);
  901. IFW32FALSE_EXIT(::SxspQuoteString(0, NameInternalAttribute->Attribute.Value, NameInternalAttribute->Attribute.ValueCch, BytesLeft, Cursor, &TempBytesWritten));
  902. INTERNAL_ERROR_CHECK(TempBytesWritten <= BytesLeft);
  903. Cursor = (PVOID) (((ULONG_PTR) Cursor) + TempBytesWritten);
  904. BytesLeft -= TempBytesWritten;
  905. BytesWritten += TempBytesWritten;
  906. for (i=0; i<AttributeCount; i++)
  907. {
  908. // Skip the standard "name" attribute
  909. if (Attributes[i] == NameInternalAttribute)
  910. continue;
  911. if (BytesLeft < sizeof(WCHAR))
  912. ORIGINATE_WIN32_FAILURE_AND_EXIT(NoRoom, ERROR_INSUFFICIENT_BUFFER);
  913. *((WCHAR *) Cursor) = L',';
  914. Cursor = (PVOID) (((ULONG_PTR) Cursor) + sizeof(WCHAR));
  915. BytesLeft -= sizeof(WCHAR);
  916. BytesWritten += sizeof(WCHAR);
  917. IFW32FALSE_EXIT(::SxspEncodeInternalAssemblyIdentityAttributeAsText(0, Attributes[i], BytesLeft, Cursor, &TempBytesWritten));
  918. INTERNAL_ERROR_CHECK(TempBytesWritten <= BytesLeft);
  919. Cursor = (PVOID) (((ULONG_PTR) Cursor) + TempBytesWritten);
  920. BytesLeft -= TempBytesWritten;
  921. BytesWritten += TempBytesWritten;
  922. }
  923. }
  924. *BytesWrittenOut = BytesWritten;
  925. fSuccess = TRUE;
  926. Exit:
  927. return fSuccess;
  928. }
  929. BOOL
  930. SxsEncodeAssemblyIdentity(
  931. IN ULONG Flags,
  932. IN PCASSEMBLY_IDENTITY AssemblyIdentity,
  933. IN const GUID *EncodingGroup OPTIONAL, // use NULL to use any of the SXS_ASSEMBLY_IDENTITY_ENCODING_DEFAULTGROUP_* encodings
  934. IN ULONG EncodingFormat,
  935. IN SIZE_T BufferSize,
  936. OUT PVOID Buffer,
  937. OUT SIZE_T *BytesWrittenOrRequired
  938. )
  939. {
  940. BOOL fSuccess = FALSE;
  941. FN_TRACE_WIN32(fSuccess);
  942. SIZE_T TotalSize = 0;
  943. PVOID Cursor = NULL;
  944. SIZE_T i;
  945. PENCODED_ASSEMBLY_IDENTITY_HEADER EncodedAssemblyIdentityHeader = NULL;
  946. PENCODED_ASSEMBLY_IDENTITY_ATTRIBUTE_HEADER EncodedAssemblyIdentityAttributeHeader = NULL;
  947. ULONG *TempULONGArrayPointer;
  948. SIZE_T BytesWritten = 0;
  949. ULONG AttributeCount, NamespaceCount;
  950. if (BytesWrittenOrRequired != NULL)
  951. *BytesWrittenOrRequired = 0;
  952. PARAMETER_CHECK(Flags == 0);
  953. PARAMETER_CHECK(AssemblyIdentity != NULL);
  954. PARAMETER_CHECK((BufferSize == 0) || (Buffer != NULL));
  955. PARAMETER_CHECK((BufferSize != 0) || (BytesWrittenOrRequired != NULL));
  956. if (EncodingGroup != NULL)
  957. ORIGINATE_WIN32_FAILURE_AND_EXIT(UnknownEncodingGroup, ERROR_SXS_UNKNOWN_ENCODING_GROUP);
  958. if ((EncodingFormat != SXS_ASSEMBLY_IDENTITY_ENCODING_DEFAULTGROUP_BINARY) &&
  959. (EncodingFormat != SXS_ASSEMBLY_IDENTITY_ENCODING_DEFAULTGROUP_TEXTUAL))
  960. ORIGINATE_WIN32_FAILURE_AND_EXIT(UnknownEncodingId, ERROR_SXS_UNKNOWN_ENCODING);
  961. IFW32FALSE_EXIT(::SxspValidateAssemblyIdentity(0, AssemblyIdentity));
  962. IFW32FALSE_EXIT(::SxsComputeAssemblyIdentityEncodedSize(0, AssemblyIdentity, EncodingGroup, EncodingFormat, &TotalSize));
  963. if (TotalSize > BufferSize)
  964. {
  965. if (BytesWrittenOrRequired != NULL)
  966. *BytesWrittenOrRequired = TotalSize;
  967. ORIGINATE_WIN32_FAILURE_AND_EXIT(NoRoom, ERROR_INSUFFICIENT_BUFFER);
  968. }
  969. AttributeCount = AssemblyIdentity->AttributeCount;
  970. NamespaceCount = AssemblyIdentity->NamespaceCount;
  971. //
  972. // Let's start filling it in.
  973. //
  974. switch (EncodingFormat)
  975. {
  976. case SXS_ASSEMBLY_IDENTITY_ENCODING_DEFAULTGROUP_BINARY:
  977. BytesWritten = 0;
  978. Cursor = Buffer;
  979. EncodedAssemblyIdentityHeader = (PENCODED_ASSEMBLY_IDENTITY_HEADER) Cursor;
  980. Cursor = (PVOID) (((ULONG_PTR) Cursor) + sizeof(ENCODED_ASSEMBLY_IDENTITY_HEADER));
  981. BytesWritten += sizeof(ENCODED_ASSEMBLY_IDENTITY_HEADER);
  982. EncodedAssemblyIdentityHeader->HeaderSize = sizeof(ENCODED_ASSEMBLY_IDENTITY_HEADER);
  983. EncodedAssemblyIdentityHeader->Magic = ENCODED_ASSEMBLY_IDENTITY_HEADER_MAGIC;
  984. EncodedAssemblyIdentityHeader->TotalSize = static_cast<ULONG>(TotalSize);
  985. // turn off any flags not relevant to persisted state
  986. EncodedAssemblyIdentityHeader->Type = AssemblyIdentity->Type;
  987. EncodedAssemblyIdentityHeader->Flags = AssemblyIdentity->Flags & ~(ASSEMBLY_IDENTITY_FLAG_FROZEN);
  988. EncodedAssemblyIdentityHeader->EncodingFlags = 0;
  989. EncodedAssemblyIdentityHeader->AttributeCount = AttributeCount;
  990. EncodedAssemblyIdentityHeader->NamespaceCount = NamespaceCount;
  991. EncodedAssemblyIdentityHeader->ReservedMustBeZero1 = 0;
  992. EncodedAssemblyIdentityHeader->ReservedMustBeZero2 = 0;
  993. EncodedAssemblyIdentityHeader->ReservedMustBeZero3 = 0;
  994. EncodedAssemblyIdentityHeader->ReservedMustBeZero4 = 0;
  995. TempULONGArrayPointer = (ULONG *) Cursor;
  996. Cursor = (PVOID) (TempULONGArrayPointer + AttributeCount);
  997. BytesWritten += (AttributeCount * sizeof(ULONG));
  998. for (i=0; i<AttributeCount; i++)
  999. TempULONGArrayPointer[i] = AssemblyIdentity->AttributePointerArray[i]->WholeAttributeHash;
  1000. // sort 'em...
  1001. qsort(TempULONGArrayPointer, AttributeCount, sizeof(ULONG), &SxspCompareULONGsForQsort);
  1002. TempULONGArrayPointer = (ULONG *) Cursor;
  1003. Cursor = (PVOID) (TempULONGArrayPointer + NamespaceCount);
  1004. BytesWritten += (sizeof(ULONG) * NamespaceCount);
  1005. for (i=0; i<NamespaceCount; i++)
  1006. TempULONGArrayPointer[i] = static_cast<ULONG>(AssemblyIdentity->NamespacePointerArray[i]->NamespaceCch);
  1007. EncodedAssemblyIdentityAttributeHeader = (PENCODED_ASSEMBLY_IDENTITY_ATTRIBUTE_HEADER) Cursor;
  1008. Cursor = (PVOID) (EncodedAssemblyIdentityAttributeHeader + AttributeCount);
  1009. BytesWritten += (AttributeCount * sizeof(ENCODED_ASSEMBLY_IDENTITY_ATTRIBUTE_HEADER));
  1010. for (i=0; i<AttributeCount; i++)
  1011. {
  1012. PCINTERNAL_ASSEMBLY_IDENTITY_ATTRIBUTE InternalAttribute = AssemblyIdentity->AttributePointerArray[i];
  1013. ULONG NamespaceIndex;
  1014. // Totally gross linear search to determine the namespace index. Fortunately the common case
  1015. // will be a single namespace for all attributes.
  1016. for (NamespaceIndex = 0; NamespaceIndex < NamespaceCount; NamespaceIndex++)
  1017. {
  1018. if (AssemblyIdentity->NamespacePointerArray[NamespaceIndex] == InternalAttribute->Namespace)
  1019. break;
  1020. }
  1021. // If this assert fires, the attribute refers to a namespace that's not in the identity; bad!
  1022. INTERNAL_ERROR_CHECK(
  1023. (InternalAttribute->Namespace == NULL) ||
  1024. (NamespaceIndex < NamespaceCount));
  1025. EncodedAssemblyIdentityAttributeHeader[i].NamespaceIndex = NamespaceIndex + 1;
  1026. EncodedAssemblyIdentityAttributeHeader[i].NameCch = static_cast<ULONG>(InternalAttribute->Attribute.NameCch);
  1027. EncodedAssemblyIdentityAttributeHeader[i].ValueCch = static_cast<ULONG>(InternalAttribute->Attribute.ValueCch);
  1028. }
  1029. // so much for the fixed length stuff; write the namespaces.
  1030. for (i=0; i<NamespaceCount; i++)
  1031. {
  1032. PWSTR psz = (PWSTR) Cursor;
  1033. Cursor = (PVOID) (((ULONG_PTR) psz) + (AssemblyIdentity->NamespacePointerArray[i]->NamespaceCch * sizeof(WCHAR)));
  1034. BytesWritten += (AssemblyIdentity->NamespacePointerArray[i]->NamespaceCch * sizeof(WCHAR));
  1035. memcpy(
  1036. psz,
  1037. AssemblyIdentity->NamespacePointerArray[i]->Namespace,
  1038. AssemblyIdentity->NamespacePointerArray[i]->NamespaceCch * sizeof(WCHAR));
  1039. }
  1040. // And the attributes...
  1041. for (i=0; i<AttributeCount; i++)
  1042. {
  1043. PCINTERNAL_ASSEMBLY_IDENTITY_ATTRIBUTE InternalAttribute = AssemblyIdentity->AttributePointerArray[i];
  1044. PWSTR psz;
  1045. psz = (PWSTR) Cursor;
  1046. Cursor = (PVOID) (((ULONG_PTR) psz) + (InternalAttribute->Attribute.NameCch * sizeof(WCHAR)));
  1047. BytesWritten += (InternalAttribute->Attribute.NameCch * sizeof(WCHAR));
  1048. memcpy(
  1049. psz,
  1050. InternalAttribute->Attribute.Name,
  1051. InternalAttribute->Attribute.NameCch * sizeof(WCHAR));
  1052. psz = (PWSTR) Cursor;
  1053. Cursor = (PVOID) (((ULONG_PTR) psz) + InternalAttribute->Attribute.ValueCch * sizeof(WCHAR));
  1054. BytesWritten += InternalAttribute->Attribute.ValueCch * sizeof(WCHAR);
  1055. memcpy(
  1056. psz,
  1057. InternalAttribute->Attribute.Value,
  1058. InternalAttribute->Attribute.ValueCch * sizeof(WCHAR));
  1059. }
  1060. if ((BytesWritten % 4) != 0) {
  1061. ASSERT((BytesWritten % 4) == sizeof(USHORT));
  1062. *((USHORT *) Cursor) = 0;
  1063. BytesWritten += sizeof(USHORT);
  1064. }
  1065. break;
  1066. case SXS_ASSEMBLY_IDENTITY_ENCODING_DEFAULTGROUP_TEXTUAL:
  1067. IFW32FALSE_EXIT(::SxspEncodeAssemblyIdentityTextually(0, AssemblyIdentity, BufferSize, Buffer, &BytesWritten));
  1068. break;
  1069. }
  1070. INTERNAL_ERROR_CHECK(BytesWritten == TotalSize);
  1071. if (BytesWrittenOrRequired != NULL)
  1072. *BytesWrittenOrRequired = BytesWritten;
  1073. fSuccess = TRUE;
  1074. Exit:
  1075. return fSuccess;
  1076. }
  1077. BOOL
  1078. SxsDecodeAssemblyIdentity(
  1079. ULONG Flags,
  1080. IN const GUID *EncodingGroup,
  1081. IN ULONG EncodingFormat,
  1082. IN SIZE_T BufferSize,
  1083. IN const VOID *Buffer,
  1084. OUT PASSEMBLY_IDENTITY *AssemblyIdentityOut
  1085. )
  1086. {
  1087. BOOL fSuccess = FALSE;
  1088. FN_TRACE_WIN32(fSuccess);
  1089. PCENCODED_ASSEMBLY_IDENTITY_HEADER EncodedAssemblyIdentityHeader = NULL;
  1090. PCENCODED_ASSEMBLY_IDENTITY_ATTRIBUTE_HEADER EncodedAssemblyIdentityAttributeHeader = NULL;
  1091. PCINTERNAL_ASSEMBLY_IDENTITY_ATTRIBUTE *AttributePointerArray = NULL;
  1092. PCASSEMBLY_IDENTITY_NAMESPACE *NamespacePointerArray = NULL;
  1093. PASSEMBLY_IDENTITY AssemblyIdentity = NULL;
  1094. ULONG AttributeCount = 0;
  1095. ULONG NamespaceCount = 0;
  1096. ULONG AttributeArraySize = 0;
  1097. ULONG NamespaceArraySize = 0;
  1098. ULONG i;
  1099. const ULONG *NamespaceLengthArray = NULL;
  1100. const ULONG *AttributeHashArray = NULL;
  1101. const WCHAR *UnicodeStringArray = NULL;
  1102. if (AssemblyIdentityOut != NULL)
  1103. *AssemblyIdentityOut = NULL;
  1104. PARAMETER_CHECK((Flags & ~(SXS_DECODE_ASSEMBLY_IDENTITY_FLAG_FREEZE)) == 0);
  1105. PARAMETER_CHECK(BufferSize >= sizeof(ENCODED_ASSEMBLY_IDENTITY_HEADER));
  1106. PARAMETER_CHECK(Buffer != NULL);
  1107. PARAMETER_CHECK(AssemblyIdentityOut != NULL);
  1108. if (EncodingGroup != NULL)
  1109. ORIGINATE_WIN32_FAILURE_AND_EXIT(UnknownEncodingGroup, ERROR_SXS_UNKNOWN_ENCODING_GROUP);
  1110. if ((EncodingFormat != SXS_ASSEMBLY_IDENTITY_ENCODING_DEFAULTGROUP_BINARY) &&
  1111. (EncodingFormat != SXS_ASSEMBLY_IDENTITY_ENCODING_DEFAULTGROUP_TEXTUAL))
  1112. ORIGINATE_WIN32_FAILURE_AND_EXIT(UnknownEncoding, ERROR_SXS_UNKNOWN_ENCODING);
  1113. EncodedAssemblyIdentityHeader = (PCENCODED_ASSEMBLY_IDENTITY_HEADER) Buffer;
  1114. if ((EncodedAssemblyIdentityHeader->HeaderSize != sizeof(ENCODED_ASSEMBLY_IDENTITY_HEADER)) ||
  1115. (EncodedAssemblyIdentityHeader->Magic != ENCODED_ASSEMBLY_IDENTITY_HEADER_MAGIC) ||
  1116. (EncodedAssemblyIdentityHeader->TotalSize > BufferSize) ||
  1117. (EncodedAssemblyIdentityHeader->Flags != 0) ||
  1118. ((EncodedAssemblyIdentityHeader->Type != ASSEMBLY_IDENTITY_TYPE_DEFINITION) &&
  1119. (EncodedAssemblyIdentityHeader->Type != ASSEMBLY_IDENTITY_TYPE_REFERENCE) &&
  1120. (EncodedAssemblyIdentityHeader->Type != ASSEMBLY_IDENTITY_TYPE_WILDCARD)) ||
  1121. (EncodedAssemblyIdentityHeader->EncodingFlags != 0) ||
  1122. (EncodedAssemblyIdentityHeader->ReservedMustBeZero1 != 0) ||
  1123. (EncodedAssemblyIdentityHeader->ReservedMustBeZero2 != 0) ||
  1124. (EncodedAssemblyIdentityHeader->ReservedMustBeZero3 != 0) ||
  1125. (EncodedAssemblyIdentityHeader->ReservedMustBeZero4 != 0)) {
  1126. ::SetLastError(ERROR_INVALID_PARAMETER);
  1127. goto Exit;
  1128. }
  1129. IFALLOCFAILED_EXIT(AssemblyIdentity = new ASSEMBLY_IDENTITY);
  1130. NamespaceCount = EncodedAssemblyIdentityHeader->NamespaceCount;
  1131. if (Flags & SXS_DECODE_ASSEMBLY_IDENTITY_FLAG_FREEZE)
  1132. {
  1133. NamespaceArraySize = NamespaceCount;
  1134. }
  1135. else if (NamespaceCount == 0)
  1136. {
  1137. NamespaceArraySize = 8;
  1138. }
  1139. else
  1140. {
  1141. NamespaceArraySize = (NamespaceCount + 7) & ~7;
  1142. }
  1143. if (NamespaceArraySize != 0)
  1144. {
  1145. IFALLOCFAILED_EXIT(NamespacePointerArray = new PCASSEMBLY_IDENTITY_NAMESPACE[NamespaceArraySize]);
  1146. for (i=0; i<NamespaceArraySize; i++)
  1147. NamespacePointerArray[i] = NULL;
  1148. }
  1149. AttributeCount = EncodedAssemblyIdentityHeader->AttributeCount;
  1150. if (Flags & SXS_DECODE_ASSEMBLY_IDENTITY_FLAG_FREEZE)
  1151. {
  1152. // If we're going to freeze, just perform an exact allocation.
  1153. AttributeArraySize = AttributeCount;
  1154. }
  1155. else if (AttributeCount == 0)
  1156. {
  1157. AttributeArraySize = 8;
  1158. }
  1159. else
  1160. {
  1161. AttributeArraySize = (AttributeCount + 7) & ~7;
  1162. }
  1163. if (AttributeArraySize != 0)
  1164. {
  1165. IFALLOCFAILED_EXIT(AttributePointerArray = new PCINTERNAL_ASSEMBLY_IDENTITY_ATTRIBUTE[AttributeArraySize]);
  1166. for (i=0; i<AttributeArraySize; i++)
  1167. AttributePointerArray[i] = NULL;
  1168. }
  1169. AttributeHashArray = (const ULONG *) (EncodedAssemblyIdentityHeader + 1);
  1170. NamespaceLengthArray = (const ULONG *) (AttributeHashArray + AttributeCount);
  1171. EncodedAssemblyIdentityAttributeHeader = (PCENCODED_ASSEMBLY_IDENTITY_ATTRIBUTE_HEADER) (NamespaceLengthArray + NamespaceCount);
  1172. UnicodeStringArray = (const WCHAR *) (EncodedAssemblyIdentityAttributeHeader + AttributeCount);
  1173. // Start by building up those namespaces...
  1174. for (i=0; i<NamespaceCount; i++)
  1175. {
  1176. ULONG NamespaceHash = 0;
  1177. IFW32FALSE_EXIT(::FusionpHashUnicodeString(UnicodeStringArray, NamespaceLengthArray[i], &NamespaceHash, false));
  1178. IFW32FALSE_EXIT(::SxspAllocateAssemblyIdentityNamespace(0, UnicodeStringArray, NamespaceLengthArray[i], NamespaceHash, &NamespacePointerArray[i]));
  1179. UnicodeStringArray += NamespaceLengthArray[i];
  1180. }
  1181. if (AttributeCount != 0)
  1182. {
  1183. // and now those attributes...
  1184. for (i=0; i<AttributeCount; i++)
  1185. {
  1186. const ULONG NamespaceIndex = EncodedAssemblyIdentityAttributeHeader[i].NamespaceIndex;
  1187. const ULONG NameCch = EncodedAssemblyIdentityAttributeHeader[i].NameCch;
  1188. const ULONG ValueCch = EncodedAssemblyIdentityAttributeHeader[i].ValueCch;
  1189. const WCHAR * const Name = UnicodeStringArray;
  1190. const WCHAR * const Value = &UnicodeStringArray[NameCch];
  1191. UnicodeStringArray = &Value[ValueCch];
  1192. IFW32FALSE_EXIT(
  1193. ::SxspAllocateInternalAssemblyIdentityAttribute(
  1194. 0,
  1195. NamespacePointerArray[NamespaceIndex],
  1196. Name,
  1197. NameCch,
  1198. Value,
  1199. ValueCch,
  1200. &AttributePointerArray[i]));
  1201. }
  1202. // sort 'em...
  1203. qsort((PVOID) AttributePointerArray, AttributeCount, sizeof(PINTERNAL_ASSEMBLY_IDENTITY_ATTRIBUTE), &SxspCompareInternalAttributesForQsort);
  1204. }
  1205. IFW32FALSE_EXIT(::SxspHashInternalAssemblyIdentityAttributes(0, AttributeCount, AttributePointerArray, &AssemblyIdentity->Hash));
  1206. AssemblyIdentity->Flags = 0;
  1207. AssemblyIdentity->Type = EncodedAssemblyIdentityHeader->Type;
  1208. AssemblyIdentity->InternalFlags = ASSEMBLY_IDENTITY_INTERNAL_FLAG_ATTRIBUTE_POINTERS_IN_SEPARATE_ALLOCATION | ASSEMBLY_IDENTITY_INTERNAL_FLAG_NAMESPACE_POINTERS_IN_SEPARATE_ALLOCATION;
  1209. AssemblyIdentity->AttributePointerArray = AttributePointerArray;
  1210. AssemblyIdentity->AttributeCount = AttributeCount;
  1211. AssemblyIdentity->AttributeArraySize = AttributeArraySize;
  1212. AssemblyIdentity->NamespacePointerArray = NamespacePointerArray;
  1213. AssemblyIdentity->NamespaceCount = NamespaceCount;
  1214. AssemblyIdentity->NamespaceArraySize = NamespaceArraySize;
  1215. AttributePointerArray = NULL;
  1216. NamespacePointerArray = NULL;
  1217. if (Flags & SXS_DECODE_ASSEMBLY_IDENTITY_FLAG_FREEZE)
  1218. AssemblyIdentity->Flags |= ASSEMBLY_IDENTITY_FLAG_FROZEN;
  1219. *AssemblyIdentityOut = AssemblyIdentity;
  1220. AssemblyIdentity = NULL;
  1221. fSuccess = TRUE;
  1222. Exit:
  1223. //
  1224. // REVIEW: Should this be an SxsDestroyAssemblyIdentity
  1225. //
  1226. if (AssemblyIdentity != NULL)
  1227. FUSION_DELETE_SINGLETON(AssemblyIdentity);
  1228. if ((AttributeCount != 0) && (AttributePointerArray != NULL))
  1229. {
  1230. for (i=0; i<AttributeCount; i++)
  1231. {
  1232. if (AttributePointerArray[i] != NULL)
  1233. {
  1234. ::SxspDeallocateInternalAssemblyIdentityAttribute(AttributePointerArray[i]);
  1235. AttributePointerArray[i] = NULL;
  1236. }
  1237. }
  1238. FUSION_DELETE_ARRAY( AttributePointerArray );
  1239. }
  1240. if ((NamespaceCount != 0) && (NamespacePointerArray != NULL))
  1241. {
  1242. for (i=0; i<NamespaceCount; i++)
  1243. {
  1244. if (NamespacePointerArray[i] != NULL)
  1245. {
  1246. ::SxspDeallocateAssemblyIdentityNamespace(NamespacePointerArray[i]);
  1247. NamespacePointerArray[i] = NULL;
  1248. }
  1249. }
  1250. FUSION_DELETE_ARRAY( NamespacePointerArray );
  1251. }
  1252. return fSuccess;
  1253. }
  1254. int __cdecl
  1255. SxspCharPairArrayComparisonCallback(
  1256. const void *pelem1,
  1257. const void *pelem2
  1258. )
  1259. {
  1260. PCCHARPAIR pcp1 = (PCCHARPAIR) pelem1;
  1261. PCCHARPAIR pcp2 = (PCCHARPAIR) pelem2;
  1262. if (pcp1->wchEnd < pcp2->wchStart)
  1263. return -1;
  1264. if (pcp2->wchEnd < pcp1->wchStart)
  1265. return 1;
  1266. return 0;
  1267. }
  1268. bool
  1269. SxspIsCharInCharPairArray(
  1270. WCHAR wch,
  1271. PCCHARPAIR prg,
  1272. SIZE_T n
  1273. )
  1274. {
  1275. CHARPAIR cp = { wch, wch };
  1276. return (bsearch(&cp, prg, n, sizeof(CHARPAIR), &SxspCharPairArrayComparisonCallback) != NULL);
  1277. }
  1278. bool
  1279. SxspIsCharXMLBaseChar(
  1280. WCHAR wch
  1281. )
  1282. {
  1283. return SxspIsCharInCharPairArray(wch, s_rgXMLBaseChar, NUMBER_OF(s_rgXMLBaseChar));
  1284. }
  1285. bool
  1286. SxspIsCharXMLIdeographic(
  1287. WCHAR wch
  1288. )
  1289. {
  1290. return (
  1291. (wch >= 0x4e00 && wch <= 0x9fa5) ||
  1292. (wch == 0x3007) ||
  1293. (wch >= 0x3021 && wch <= 0x3029)
  1294. );
  1295. }
  1296. bool
  1297. SxspIsCharXMLLetter(
  1298. WCHAR wch
  1299. )
  1300. {
  1301. return
  1302. ::SxspIsCharXMLBaseChar(wch) ||
  1303. ::SxspIsCharXMLIdeographic(wch);
  1304. }
  1305. bool
  1306. SxspIsCharXMLCombiningChar(
  1307. WCHAR wch
  1308. )
  1309. {
  1310. return (
  1311. (wch >= 0x0300 && wch <= 0x0345) ||
  1312. (wch >= 0x0360 && wch <= 0x0361) ||
  1313. (wch >= 0x0483 && wch <= 0x0486) ||
  1314. (wch >= 0x0591 && wch <= 0x05a1) ||
  1315. (wch >= 0x05a3 && wch <= 0x05b9) ||
  1316. (wch >= 0x05bb && wch <= 0x05bd) ||
  1317. wch == 0x05bf ||
  1318. (wch >= 0x05c1 && wch <= 0x05c2) ||
  1319. wch == 0x05c4 ||
  1320. (wch >= 0x064b && wch <= 0x0652) ||
  1321. wch == 0x0670 ||
  1322. (wch >= 0x06d6 && wch <= 0x06dc) ||
  1323. (wch >= 0x06dd && wch <= 0x06df) ||
  1324. (wch >= 0x06e0 && wch <= 0x06e4) ||
  1325. (wch >= 0x06e7 && wch <= 0x06e8) ||
  1326. (wch >= 0x06ea && wch <= 0x06ed) ||
  1327. (wch >= 0x0901 && wch <= 0x0903) ||
  1328. wch == 0x093c ||
  1329. (wch >= 0x093e && wch <= 0x094c) ||
  1330. wch == 0x094d ||
  1331. (wch >= 0x0951 && wch <= 0x0954) ||
  1332. (wch >= 0x0962 && wch <= 0x0963) ||
  1333. (wch >= 0x0981 && wch <= 0x0983) ||
  1334. wch == 0x09bc ||
  1335. wch == 0x09be ||
  1336. wch == 0x09bf ||
  1337. (wch >= 0x09c0 && wch <= 0x09c4) ||
  1338. (wch >= 0x09c7 && wch <= 0x09c8) ||
  1339. (wch >= 0x09cb && wch <= 0x09cd) ||
  1340. wch == 0x09d7 ||
  1341. (wch >= 0x09e2 && wch <= 0x09e3) ||
  1342. wch == 0x0a02 ||
  1343. wch == 0x0a3c ||
  1344. wch == 0x0a3e ||
  1345. wch == 0x0a3f ||
  1346. (wch >= 0x0a40 && wch <= 0x0a42) ||
  1347. (wch >= 0x0a47 && wch <= 0x0a48) ||
  1348. (wch >= 0x0a4b && wch <= 0x0a4d) ||
  1349. (wch >= 0x0a70 && wch <= 0x0a71) ||
  1350. (wch >= 0x0a81 && wch <= 0x0a83) ||
  1351. wch == 0x0abc ||
  1352. (wch >= 0x0abe && wch <= 0x0ac5) ||
  1353. (wch >= 0x0ac7 && wch <= 0x0ac9) ||
  1354. (wch >= 0x0acb && wch <= 0x0acd) ||
  1355. (wch >= 0x0b01 && wch <= 0x0b03) ||
  1356. wch == 0x0b3c ||
  1357. (wch >= 0x0b3e && wch <= 0x0b43) ||
  1358. (wch >= 0x0b47 && wch <= 0x0b48) ||
  1359. (wch >= 0x0b4b && wch <= 0x0b4d) ||
  1360. (wch >= 0x0b56 && wch <= 0x0b57) ||
  1361. (wch >= 0x0b82 && wch <= 0x0b83) ||
  1362. (wch >= 0x0bbe && wch <= 0x0bc2) ||
  1363. (wch >= 0x0bc6 && wch <= 0x0bc8) ||
  1364. (wch >= 0x0bca && wch <= 0x0bcd) ||
  1365. wch == 0x0bd7 ||
  1366. (wch >= 0x0c01 && wch <= 0x0c03) ||
  1367. (wch >= 0x0c3e && wch <= 0x0c44) ||
  1368. (wch >= 0x0c46 && wch <= 0x0c48) ||
  1369. (wch >= 0x0c4a && wch <= 0x0c4d) ||
  1370. (wch >= 0x0c55 && wch <= 0x0c56) ||
  1371. (wch >= 0x0c82 && wch <= 0x0c83) ||
  1372. (wch >= 0x0cbe && wch <= 0x0cc4) ||
  1373. (wch >= 0x0cc6 && wch <= 0x0cc8) ||
  1374. (wch >= 0x0cca && wch <= 0x0ccd) ||
  1375. (wch >= 0x0cd5 && wch <= 0x0cd6) ||
  1376. (wch >= 0x0d02 && wch <= 0x0d03) ||
  1377. (wch >= 0x0d3e && wch <= 0x0d43) ||
  1378. (wch >= 0x0d46 && wch <= 0x0d48) ||
  1379. (wch >= 0x0d4a && wch <= 0x0d4d) ||
  1380. wch == 0x0d57 ||
  1381. wch == 0x0e31 ||
  1382. (wch >= 0x0e34 && wch <= 0x0e3a) ||
  1383. (wch >= 0x0e47 && wch <= 0x0e4e) ||
  1384. wch == 0x0eb1 ||
  1385. (wch >= 0x0eb4 && wch <= 0x0eb9) ||
  1386. (wch >= 0x0ebb && wch <= 0x0ebc) ||
  1387. (wch >= 0x0ec8 && wch <= 0x0ecd) ||
  1388. (wch >= 0x0f18 && wch <= 0x0f19) ||
  1389. wch == 0x0f35 ||
  1390. wch == 0x0f37 ||
  1391. wch == 0x0f39 ||
  1392. wch == 0x0f3e ||
  1393. wch == 0x0f3f ||
  1394. (wch >= 0x0f71 && wch <= 0x0f84) ||
  1395. (wch >= 0x0f86 && wch <= 0x0f8b) ||
  1396. (wch >= 0x0f90 && wch <= 0x0f95) ||
  1397. wch == 0x0f97 ||
  1398. (wch >= 0x0f99 && wch <= 0x0fad) ||
  1399. (wch >= 0x0fb1 && wch <= 0x0fb7) ||
  1400. wch == 0x0fb9 ||
  1401. (wch >= 0x20d0 && wch <= 0x20dc) ||
  1402. wch == 0x20e1 ||
  1403. (wch >= 0x302a && wch <= 0x302f) ||
  1404. wch == 0x3099 ||
  1405. wch == 0x309a
  1406. );
  1407. }
  1408. bool
  1409. SxspIsCharXMLDigit(
  1410. WCHAR wch
  1411. )
  1412. {
  1413. return (
  1414. (wch >= 0x0030 && wch <= 0x0039) ||
  1415. (wch >= 0x0660 && wch <= 0x0669) ||
  1416. (wch >= 0x06f0 && wch <= 0x06f9) ||
  1417. (wch >= 0x0966 && wch <= 0x096f) ||
  1418. (wch >= 0x09e6 && wch <= 0x09ef) ||
  1419. (wch >= 0x0a66 && wch <= 0x0a6f) ||
  1420. (wch >= 0x0ae6 && wch <= 0x0aef) ||
  1421. (wch >= 0x0b66 && wch <= 0x0b6f) ||
  1422. (wch >= 0x0be7 && wch <= 0x0bef) ||
  1423. (wch >= 0x0c66 && wch <= 0x0c6f) ||
  1424. (wch >= 0x0ce6 && wch <= 0x0cef) ||
  1425. (wch >= 0x0d66 && wch <= 0x0d6f) ||
  1426. (wch >= 0x0e50 && wch <= 0x0e59) ||
  1427. (wch >= 0x0ed0 && wch <= 0x0ed9) ||
  1428. (wch >= 0x0f20 && wch <= 0x0f29)
  1429. );
  1430. }
  1431. bool
  1432. SxspIsCharXMLExtender(
  1433. WCHAR wch
  1434. )
  1435. {
  1436. return (
  1437. wch == 0x00b7 ||
  1438. wch == 0x02d0 ||
  1439. wch == 0x02d1 ||
  1440. wch == 0x0387 ||
  1441. wch == 0x0640 ||
  1442. wch == 0x0e46 ||
  1443. wch == 0x0ec6 ||
  1444. wch == 0x3005 ||
  1445. (wch >= 0x3031 && wch <= 0x3035) ||
  1446. (wch >= 0x309d && wch <= 0x309e) ||
  1447. (wch >= 0x30fc && wch <= 0x30fe)
  1448. );
  1449. }
  1450. BOOL
  1451. SxspValidateXMLName(
  1452. PCWSTR psz,
  1453. SIZE_T cch,
  1454. bool &rfValid
  1455. )
  1456. {
  1457. BOOL fSuccess = FALSE;
  1458. FN_TRACE_WIN32(fSuccess);
  1459. SIZE_T i;
  1460. rfValid = false;
  1461. // [4] NameChar ::= Letter | Digit | '.' | '-' | '_' | ':' | CombiningChar | Extender
  1462. // [5] Name ::= (Letter | '_' | ':') (NameChar)*
  1463. if (cch >= 1)
  1464. {
  1465. WCHAR wch = psz[0];
  1466. if (::SxspIsCharXMLLetter(wch) ||
  1467. (wch == L'_') ||
  1468. (wch == L':'))
  1469. {
  1470. for (i=1; i<cch; i++)
  1471. {
  1472. wch = psz[i];
  1473. if (!::SxspIsCharXMLLetter(wch) &&
  1474. !::SxspIsCharXMLDigit(wch) &&
  1475. (wch != L'.') &&
  1476. (wch != L'-') &&
  1477. (wch != L'_') &&
  1478. (wch != L':') &&
  1479. !::SxspIsCharXMLCombiningChar(wch) &&
  1480. !::SxspIsCharXMLExtender(wch))
  1481. break;
  1482. }
  1483. if (i == cch)
  1484. rfValid = true;
  1485. }
  1486. }
  1487. FN_EPILOG
  1488. }