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.

267 lines
6.2 KiB

  1. #include "stdinc.h"
  2. #include "debmacro.h"
  3. #include "ntdef.h"
  4. #include "fusionparser.h"
  5. #include "shlwapi.h"
  6. #if !defined(NUMBER_OF)
  7. #define NUMBER_OF(x) (sizeof(x) / sizeof((x)[0]))
  8. #endif
  9. BOOL
  10. CFusionParser::ParseVersion(
  11. ASSEMBLY_VERSION &rav,
  12. PCWSTR sz,
  13. SIZE_T cch,
  14. bool &rfSyntaxValid
  15. )
  16. {
  17. FN_PROLOG_WIN32
  18. ULONG cDots = 0;
  19. PCWSTR pszTemp;
  20. SIZE_T cchLeft;
  21. ULONG ulTemp = 0;
  22. ASSEMBLY_VERSION avTemp;
  23. PCWSTR pszLast;
  24. bool fSyntaxValid = true;
  25. rfSyntaxValid = false;
  26. PARAMETER_CHECK((sz != NULL) || (cch == 0));
  27. avTemp.Major = 0;
  28. avTemp.Minor = 0;
  29. avTemp.Revision = 0;
  30. avTemp.Build = 0;
  31. while ((cch != 0) && (sz[cch - 1] == L'\0'))
  32. cch--;
  33. // Unfortunately there isn't a StrChrN(), so we'll look for the dots ourselves...
  34. pszTemp = sz;
  35. cchLeft = cch;
  36. while (cchLeft-- != 0)
  37. {
  38. WCHAR wch = *pszTemp++;
  39. if (wch == L'.')
  40. {
  41. cDots++;
  42. if (cDots >= 4)
  43. {
  44. fSyntaxValid = false;
  45. break;
  46. }
  47. }
  48. else if ((wch < L'0') || (wch > L'9'))
  49. {
  50. fSyntaxValid = false;
  51. break;
  52. }
  53. }
  54. if (fSyntaxValid && (cDots < 3))
  55. fSyntaxValid = false;
  56. //
  57. // CODECLEANUP:2002-3-29:jonwis - I think we could be better here if we used a
  58. // slightly smarter parsing logic, like "knowing which version slot we're
  59. // parsing for" rather than four for(;;) loops... In the current world,
  60. // we're probably likely to fall off the end of our allocation at some
  61. // point or another..
  62. //
  63. // NTRAID#NTBUG9 - 538512 - jonwis - 2002/04/25 - Request for smarter parser
  64. if (fSyntaxValid)
  65. {
  66. pszTemp = sz;
  67. pszLast = sz + cch;
  68. ulTemp = 0;
  69. for (;;)
  70. {
  71. WCHAR wch = *pszTemp++;
  72. if (wch == L'.')
  73. break;
  74. ulTemp = (ulTemp * 10) + (wch - L'0');
  75. if (ulTemp > 65535)
  76. {
  77. // rfSyntaxValid implicitly false
  78. ASSERT(!rfSyntaxValid);
  79. FN_SUCCESSFUL_EXIT();
  80. }
  81. }
  82. avTemp.Major = (USHORT) ulTemp;
  83. ulTemp = 0;
  84. for (;;)
  85. {
  86. WCHAR wch = *pszTemp++;
  87. if (wch == L'.')
  88. break;
  89. ulTemp = (ulTemp * 10) + (wch - L'0');
  90. if (ulTemp > 65535)
  91. {
  92. // rfSyntaxValid implicitly false
  93. ASSERT(!rfSyntaxValid);
  94. FN_SUCCESSFUL_EXIT();
  95. }
  96. }
  97. avTemp.Minor = (USHORT) ulTemp;
  98. ulTemp = 0;
  99. for (;;)
  100. {
  101. WCHAR wch = *pszTemp++;
  102. if (wch == L'.')
  103. break;
  104. ulTemp = (ulTemp * 10) + (wch - L'0');
  105. if (ulTemp > 65535)
  106. {
  107. // rfSyntaxValid implicitly false
  108. ASSERT(!rfSyntaxValid);
  109. FN_SUCCESSFUL_EXIT();
  110. }
  111. }
  112. avTemp.Revision = (USHORT) ulTemp;
  113. // Now the tricky bit. We aren't necessarily null-terminated, so we
  114. // have to just look for hitting the end.
  115. ulTemp = 0;
  116. while (pszTemp < pszLast)
  117. {
  118. WCHAR wch = *pszTemp++;
  119. ulTemp = (ulTemp * 10) + (wch - L'0');
  120. if (ulTemp > 65535)
  121. {
  122. // rfSyntaxValid implicitly false
  123. ASSERT(!rfSyntaxValid);
  124. FN_SUCCESSFUL_EXIT();
  125. }
  126. }
  127. avTemp.Build = (USHORT) ulTemp;
  128. rav = avTemp;
  129. }
  130. rfSyntaxValid = fSyntaxValid;
  131. FN_EPILOG
  132. }
  133. BOOL
  134. CFusionParser::ParseULONG(
  135. ULONG &rul,
  136. PCWSTR sz,
  137. SIZE_T cch,
  138. ULONG Radix
  139. )
  140. {
  141. BOOL fSuccess = FALSE;
  142. FN_TRACE_WIN32(fSuccess);
  143. ULONG ulTemp = 0;
  144. PARAMETER_CHECK((Radix >= 2) && (Radix <= 36));
  145. while (cch != 0)
  146. {
  147. const WCHAR wch = *sz++;
  148. ULONG Digit = 0;
  149. cch--;
  150. if ((wch >= L'0') && (wch <= L'9'))
  151. Digit = (wch - L'0');
  152. else if ((wch >= L'a') && (wch <= L'z'))
  153. Digit = (10 + wch - L'a');
  154. else if ((wch >= L'A') && (wch <= L'Z'))
  155. Digit = (10 + wch - L'A');
  156. else
  157. ORIGINATE_WIN32_FAILURE_AND_EXIT(InvalidDigit, ERROR_SXS_MANIFEST_PARSE_ERROR);
  158. if (Digit >= Radix)
  159. ORIGINATE_WIN32_FAILURE_AND_EXIT(InvalidDigitForRadix, ERROR_SXS_MANIFEST_PARSE_ERROR);
  160. //
  161. // Simple overflow detection - if the new number is less than the current, oops.
  162. //
  163. // NTRAID#NTBUG9 - 538512 - jonwis - 2002/04/25 - Better overflow detection requested
  164. if (((ulTemp * Radix) + Digit) < ulTemp)
  165. {
  166. ORIGINATE_WIN32_FAILURE_AND_EXIT(CFusionParser::ParseULONG::Overflow, ERROR_ARITHMETIC_OVERFLOW);
  167. }
  168. ulTemp = (ulTemp * Radix) + Digit;
  169. }
  170. rul = ulTemp;
  171. fSuccess = TRUE;
  172. Exit:
  173. return fSuccess;
  174. }
  175. BOOL
  176. FusionDupString(
  177. LPWSTR *ppszOut,
  178. PCWSTR szIn,
  179. SIZE_T cchIn
  180. )
  181. {
  182. BOOL fSuccess = FALSE;
  183. FN_TRACE_WIN32(fSuccess);
  184. if (ppszOut != NULL)
  185. *ppszOut = NULL;
  186. PARAMETER_CHECK((cchIn == 0) || (szIn != NULL));
  187. PARAMETER_CHECK(ppszOut != NULL);
  188. IFALLOCFAILED_EXIT(*ppszOut = FUSION_NEW_ARRAY(WCHAR, cchIn + 1));
  189. if (cchIn != 0)
  190. memcpy(*ppszOut, szIn, cchIn * sizeof(WCHAR));
  191. (*ppszOut)[cchIn] = L'\0';
  192. fSuccess = TRUE;
  193. Exit:
  194. return fSuccess;
  195. }
  196. int SxspHexDigitToValue(WCHAR wch)
  197. {
  198. if ((wch >= L'a') && (wch <= L'f'))
  199. return 10 + (wch - L'a');
  200. else if ((wch >= L'A') && (wch <= 'F'))
  201. return 10 + (wch - L'A');
  202. else if (wch >= '0' && wch <= '9')
  203. return (wch - L'0');
  204. else
  205. return -1;
  206. }
  207. bool SxspIsHexDigit(WCHAR wch)
  208. {
  209. return (((wch >= L'0') && (wch <= L'9')) ||
  210. ((wch >= L'a') && (wch <= L'f')) ||
  211. ((wch >= L'A') && (wch <= L'F')));
  212. }