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.

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