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.

356 lines
6.9 KiB

  1. //+--------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1996 - 1999
  5. //
  6. // File: serial.cpp
  7. //
  8. // Contents: serial number string encode/decode implementation
  9. //
  10. //---------------------------------------------------------------------------
  11. #include <pch.cpp>
  12. #pragma hdrstop
  13. HRESULT
  14. ObsoleteMultiByteIntegerToWszBuf(
  15. IN BOOL fOctetString,
  16. IN DWORD cbIn,
  17. IN BYTE const *pbIn,
  18. IN OUT DWORD *pcbOut,
  19. OPTIONAL OUT WCHAR *pwszOut)
  20. {
  21. return MultiByteIntegerToWszBuf(
  22. fOctetString,
  23. cbIn,
  24. pbIn,
  25. pcbOut,
  26. pwszOut);
  27. }
  28. HRESULT
  29. ObsoleteMultiByteIntegerToBstr(
  30. IN BOOL fOctetString,
  31. IN DWORD cbIn,
  32. IN BYTE const *pbIn,
  33. OUT BSTR *pstrOut)
  34. {
  35. return MultiByteIntegerToBstr(
  36. fOctetString,
  37. cbIn,
  38. pbIn,
  39. pstrOut);
  40. }
  41. BOOL
  42. AsciiToNibble(
  43. IN WCHAR wc,
  44. BYTE *pb)
  45. {
  46. BOOL fOk = TRUE;
  47. do
  48. {
  49. wc -= L'0';
  50. if (wc <= 9)
  51. {
  52. break;
  53. }
  54. wc += (WCHAR) (L'0' - L'a' + 10);
  55. if (wc <= 15)
  56. {
  57. break;
  58. }
  59. wc += L'a' - L'A';
  60. if (wc <= 15)
  61. {
  62. break;
  63. }
  64. fOk = FALSE;
  65. } while (FALSE);
  66. *pb = (BYTE) wc;
  67. return(fOk);
  68. }
  69. __inline BOOL
  70. IsMultiByteSkipChar(
  71. IN WCHAR wc)
  72. {
  73. return(L' ' == wc || L'\t' == wc);
  74. }
  75. // WszToMultiByteIntegerBuf - convert a big endian null-terminated ascii-hex
  76. // encoded WCHAR string of even length to a little-endian integer blob.
  77. // If fOctetString is TRUE, preserve endian order, as in a hex dump
  78. HRESULT
  79. WszToMultiByteIntegerBuf(
  80. IN BOOL fOctetString,
  81. IN WCHAR const *pwszIn,
  82. IN OUT DWORD *pcbOut,
  83. OPTIONAL OUT BYTE *pbOut)
  84. {
  85. HRESULT hr;
  86. WCHAR const *pwsz;
  87. DWORD cbOut;
  88. cbOut = 0;
  89. hr = E_INVALIDARG;
  90. if (fOctetString)
  91. {
  92. for (pwsz = pwszIn; L'\0' != *pwsz; )
  93. {
  94. BYTE blo, bhi;
  95. while (IsMultiByteSkipChar(*pwsz))
  96. {
  97. pwsz++;
  98. }
  99. if (!AsciiToNibble(*pwsz, &bhi))
  100. {
  101. _JumpError2(
  102. hr,
  103. error,
  104. "WszToMultiByteInteger: bad string",
  105. E_INVALIDARG);
  106. }
  107. pwsz++;
  108. while (IsMultiByteSkipChar(*pwsz))
  109. {
  110. pwsz++;
  111. }
  112. if (!AsciiToNibble(*pwsz, &blo))
  113. {
  114. _JumpError(hr, error, "WszToMultiByteInteger: bad string");
  115. }
  116. pwsz++;
  117. cbOut++;
  118. if (NULL != pbOut)
  119. {
  120. if (cbOut > *pcbOut)
  121. {
  122. hr = TYPE_E_BUFFERTOOSMALL;
  123. _JumpError(hr, error, "WszToMultiByteInteger: overflow");
  124. }
  125. *pbOut++ = blo | (bhi << 4);
  126. }
  127. }
  128. }
  129. else
  130. {
  131. for (pwsz = &pwszIn[wcslen(pwszIn) - 1]; pwsz >= pwszIn; )
  132. {
  133. BYTE blo, bhi;
  134. while (pwsz >= pwszIn && IsMultiByteSkipChar(*pwsz))
  135. {
  136. pwsz--;
  137. }
  138. if (pwsz < pwszIn)
  139. {
  140. break;
  141. }
  142. if (!AsciiToNibble(*pwsz, &blo))
  143. {
  144. _JumpError(hr, error, "WszToMultiByteInteger: bad string");
  145. }
  146. pwsz--;
  147. while (pwsz >= pwszIn && IsMultiByteSkipChar(*pwsz))
  148. {
  149. pwsz--;
  150. }
  151. if (pwsz < pwszIn || !AsciiToNibble(*pwsz, &bhi))
  152. {
  153. _JumpError(hr, error, "WszToMultiByteInteger: bad string");
  154. }
  155. pwsz--;
  156. cbOut++;
  157. if (NULL != pbOut)
  158. {
  159. if (cbOut > *pcbOut)
  160. {
  161. hr = TYPE_E_BUFFERTOOSMALL;
  162. _JumpError(hr, error, "WszToMultiByteInteger: overflow");
  163. }
  164. *pbOut++ = blo | (bhi << 4);
  165. }
  166. }
  167. }
  168. *pcbOut = cbOut;
  169. hr = S_OK;
  170. error:
  171. return(hr);
  172. }
  173. // WszToMultiByteInteger - convert a big endian null-terminated ascii-hex
  174. // encoded WCHAR string of even length to a little-endian integer blob.
  175. // If fOctetString is TRUE, preserve endian order, as in a hex dump
  176. HRESULT
  177. WszToMultiByteInteger(
  178. IN BOOL fOctetString,
  179. IN WCHAR const *pwszIn,
  180. OUT DWORD *pcbOut,
  181. OUT BYTE **ppbOut)
  182. {
  183. HRESULT hr = S_OK;
  184. *pcbOut = 0;
  185. *ppbOut = NULL;
  186. while (TRUE)
  187. {
  188. hr = WszToMultiByteIntegerBuf(fOctetString, pwszIn, pcbOut, *ppbOut);
  189. if (S_OK != hr)
  190. {
  191. if (NULL != *ppbOut)
  192. {
  193. LocalFree(*ppbOut);
  194. *ppbOut = NULL;
  195. }
  196. _JumpError2(hr, error, "WszToMultiByteIntegerBuf", E_INVALIDARG);
  197. }
  198. if (NULL != *ppbOut)
  199. {
  200. break;
  201. }
  202. *ppbOut = (BYTE *) LocalAlloc(LMEM_FIXED, *pcbOut);
  203. if (NULL == *ppbOut)
  204. {
  205. hr = E_OUTOFMEMORY;
  206. _JumpError(hr, error, "LocalAlloc");
  207. }
  208. }
  209. error:
  210. return(hr);
  211. }
  212. HRESULT
  213. caTranslateFileTimePeriodToPeriodUnits(
  214. IN FILETIME const *pftGMT,
  215. IN BOOL fExact,
  216. OUT DWORD *pcPeriodUnits,
  217. OUT PERIODUNITS **prgPeriodUnits)
  218. {
  219. HRESULT hr;
  220. LLFILETIME llft;
  221. LONGLONG llRemain;
  222. DWORD i;
  223. DWORD cPeriodUnits;
  224. PERIODUNITS *rgPeriodUnits;
  225. #define IC_YEARS 0
  226. #define IC_MONTHS 1
  227. #define IC_WEEKS 2
  228. #define IC_DAYS 3
  229. #define IC_HOURS 4
  230. #define IC_MINUTES 5
  231. #define IC_SECONDS 6
  232. #define IC_MAX 7
  233. LONG alCount[IC_MAX];
  234. static const enum ENUM_PERIOD s_aenumPeriod[] =
  235. {
  236. ENUM_PERIOD_YEARS,
  237. ENUM_PERIOD_MONTHS,
  238. ENUM_PERIOD_WEEKS,
  239. ENUM_PERIOD_DAYS,
  240. ENUM_PERIOD_HOURS,
  241. ENUM_PERIOD_MINUTES,
  242. ENUM_PERIOD_SECONDS,
  243. };
  244. llft.ft = *pftGMT;
  245. if (0 <= llft.ll)
  246. {
  247. hr = E_INVALIDARG;
  248. _JumpError(hr, error, "Not a time period");
  249. }
  250. llft.ll = -llft.ll;
  251. llft.ll /= CVT_BASE; // now in seconds
  252. ZeroMemory(alCount, sizeof(alCount));
  253. alCount[IC_DAYS] = (LONG) (llft.ll / (60 * 60 * 24));
  254. llRemain = llft.ll - (LONGLONG) alCount[IC_DAYS] * (60 * 60 * 24);
  255. if (fExact || 4 > alCount[IC_DAYS]) // if less than 96 hrs
  256. {
  257. alCount[IC_HOURS] = (LONG) llRemain / (60 * 60);
  258. if (fExact || 2 > alCount[IC_HOURS]) // if less than 120 mins
  259. {
  260. alCount[IC_MINUTES] = ((LONG) llRemain / 60) % 60;
  261. if (fExact || 2 > alCount[IC_MINUTES]) // if less than 120 secs
  262. {
  263. alCount[IC_SECONDS] = (LONG) llRemain % 60;
  264. }
  265. }
  266. }
  267. if (0 != alCount[IC_DAYS])
  268. {
  269. if (0 == (alCount[IC_DAYS] % 365))
  270. {
  271. alCount[IC_YEARS] = alCount[IC_DAYS] / 365;
  272. alCount[IC_DAYS] = 0;
  273. }
  274. else if (0 == (alCount[IC_DAYS] % 30))
  275. {
  276. alCount[IC_MONTHS] = alCount[IC_DAYS] / 30;
  277. alCount[IC_DAYS] = 0;
  278. }
  279. else if (0 == (alCount[IC_DAYS] % 7))
  280. {
  281. alCount[IC_WEEKS] = alCount[IC_DAYS] / 7;
  282. alCount[IC_DAYS] = 0;
  283. }
  284. }
  285. cPeriodUnits = 0;
  286. for (i = 0; i < IC_MAX; i++)
  287. {
  288. if (0 != alCount[i])
  289. {
  290. cPeriodUnits++;
  291. }
  292. }
  293. if (0 == cPeriodUnits)
  294. {
  295. cPeriodUnits++;
  296. }
  297. rgPeriodUnits = (PERIODUNITS *) LocalAlloc(
  298. LMEM_FIXED,
  299. cPeriodUnits * sizeof(rgPeriodUnits[0]));
  300. if (NULL == rgPeriodUnits)
  301. {
  302. hr = E_OUTOFMEMORY;
  303. _JumpError(hr, error, "LocalAlloc");
  304. }
  305. *pcPeriodUnits = cPeriodUnits;
  306. *prgPeriodUnits = rgPeriodUnits;
  307. cPeriodUnits = 0;
  308. for (i = 0; i < IC_MAX; i++)
  309. {
  310. if (0 != alCount[i] || (0 == cPeriodUnits && i + 1 == IC_MAX))
  311. {
  312. rgPeriodUnits[cPeriodUnits].lCount = alCount[i];
  313. rgPeriodUnits[cPeriodUnits].enumPeriod = s_aenumPeriod[i];
  314. cPeriodUnits++;
  315. }
  316. }
  317. CSASSERT(cPeriodUnits == *pcPeriodUnits);
  318. hr = S_OK;
  319. error:
  320. return(hr);
  321. }