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.

422 lines
9.2 KiB

  1. //+--------------------------------------------------------------------------
  2. //
  3. // Copyright (c) 1997-1999 Microsoft Corporation
  4. //
  5. // File:
  6. //
  7. // Contents:
  8. //
  9. // History:
  10. //
  11. //---------------------------------------------------------------------------
  12. #include <windows.h>
  13. #include <assert.h>
  14. #include <math.h>
  15. class CDataCoding {
  16. private:
  17. DWORD m_dwBaseDigits;
  18. DWORD m_dwEncodedLength;
  19. DWORD m_dwInputDataBits;
  20. DWORD m_dwInputDataBytes;
  21. DWORD m_dwDecodedLength;
  22. DWORD m_dwInputEncDataBytes;
  23. DWORD m_dwDecodedBits;
  24. TCHAR * m_tpBaseDigits;
  25. public:
  26. CDataCoding(TCHAR * tpBaseDigits = NULL);
  27. void SetInputDataBitLen(DWORD dwBits);
  28. void SetInputEncDataLen(DWORD dwChars);
  29. DWORD SetBaseDigits(TCHAR * tpBaseDigits);
  30. DWORD EncodeData(LPBYTE pbSource, //[IN] Stream of Bytes to be encoded
  31. TCHAR **pbEncodedData); //[OUT] Pointer to a string containing the encoded data
  32. DWORD DecodeData(TCHAR * pbEncodedData,
  33. LPBYTE * pbDecodedData);
  34. ~CDataCoding();
  35. };
  36. class CBase24Coding : public CDataCoding {
  37. public:
  38. CBase24Coding(void) : CDataCoding(L"BCDFGHJKMPQRTVWXY2346789")
  39. {
  40. return;
  41. }
  42. };
  43. static CBase24Coding b24Global;
  44. // **************************************************************
  45. DWORD B24EncodeMSID(LPBYTE pbSource, TCHAR **pbEncodedData)
  46. {
  47. b24Global.SetInputDataBitLen(160);
  48. return b24Global.EncodeData(pbSource, pbEncodedData);
  49. }
  50. // ***************************************************************
  51. DWORD B24DecodeMSID(TCHAR * pbEncodedData, LPBYTE * pbDecodedData)
  52. {
  53. b24Global.SetInputEncDataLen(35);
  54. return b24Global.DecodeData(pbEncodedData, pbDecodedData);
  55. }
  56. // ***********************************************************
  57. DWORD B24EncodeCNumber(LPBYTE pbSource, TCHAR **pbEncodedData)
  58. {
  59. b24Global.SetInputDataBitLen(32);
  60. return b24Global.EncodeData(pbSource, pbEncodedData);
  61. }
  62. // ******************************************************************
  63. DWORD B24DecodeCNumber(TCHAR * pbEncodedData, LPBYTE * pbDecodedData)
  64. {
  65. b24Global.SetInputEncDataLen(7);
  66. return b24Global.DecodeData(pbEncodedData, pbDecodedData);
  67. }
  68. // *******************************************************
  69. DWORD B24EncodeSPK(LPBYTE pbSource, TCHAR **pbEncodedData)
  70. {
  71. b24Global.SetInputDataBitLen(114);
  72. return b24Global.EncodeData(pbSource, pbEncodedData);
  73. }
  74. // ******************************************************************
  75. DWORD B24DecodeSPK(TCHAR * pbEncodedData, LPBYTE * pbDecodedData)
  76. {
  77. b24Global.SetInputEncDataLen(25);
  78. return b24Global.DecodeData(pbEncodedData, pbDecodedData);
  79. }
  80. // *****************************************
  81. CDataCoding::CDataCoding(TCHAR * tpBaseDigits)
  82. {
  83. m_tpBaseDigits = NULL;
  84. m_dwBaseDigits = 0;
  85. m_dwEncodedLength = 0;
  86. m_dwInputDataBits = 0;
  87. m_dwInputDataBytes = 0;
  88. SetBaseDigits(tpBaseDigits);
  89. }
  90. // ********************************************
  91. void CDataCoding::SetInputDataBitLen(DWORD dwBits)
  92. {
  93. assert(dwBits > 0);
  94. assert(log(m_dwBaseDigits) > 0);
  95. // Determine How many Characters would be required to encode the data
  96. // What we have is a dwDataLength of Binary Data stream.
  97. // So, we can represent 2^(dwDataLength*8) amount of information using these bits
  98. // Assuming that our set of digits (which form the base for encoding) is X,
  99. // the above number should then equal X^(NumberofEncoded Digits)
  100. // So,
  101. double dLength = ((double) dwBits*log10(2)) /
  102. ((double) log10(m_dwBaseDigits));
  103. // Now round - up
  104. m_dwEncodedLength = (DWORD) dLength;
  105. if ((double) m_dwEncodedLength < dLength)
  106. {
  107. // There was a decimal part
  108. m_dwEncodedLength++;
  109. }
  110. m_dwInputDataBits = dwBits;
  111. m_dwInputDataBytes = (dwBits / 8) + (dwBits % 8 ? 1 : 0);
  112. return;
  113. }
  114. // ***********************************************
  115. void CDataCoding::SetInputEncDataLen(DWORD dwBytes)
  116. {
  117. assert(dwBytes > 0);
  118. assert(log(m_dwBaseDigits) > 0);
  119. m_dwInputEncDataBytes = dwBytes;
  120. // Determine How many bits would be required to decode this data
  121. // So,
  122. double dLength = ((double) dwBytes*log10(m_dwBaseDigits))/
  123. ((double) log10(2));
  124. // Now round - up
  125. m_dwDecodedBits = (DWORD) dLength;
  126. if ((double) m_dwDecodedBits < dLength)
  127. {
  128. // There was a decimal part
  129. m_dwDecodedBits++;
  130. }
  131. m_dwDecodedLength = (m_dwDecodedBits / 8) + (m_dwDecodedBits % 8 ? 1 : 0);
  132. return;
  133. }
  134. // **************************************************
  135. DWORD CDataCoding::SetBaseDigits(TCHAR * tpBaseDigits)
  136. {
  137. DWORD dwReturn = ERROR_SUCCESS;
  138. if (tpBaseDigits != NULL)
  139. {
  140. DWORD dwLen = wcslen(tpBaseDigits);
  141. assert(dwLen > 0);
  142. m_tpBaseDigits = (TCHAR *) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, (dwLen+1)*sizeof(TCHAR));
  143. if (m_tpBaseDigits == NULL)
  144. {
  145. dwReturn = ERROR_NOT_ENOUGH_MEMORY;
  146. }
  147. else
  148. {
  149. memcpy(m_tpBaseDigits, tpBaseDigits, (dwLen+1)*sizeof(TCHAR));
  150. m_dwBaseDigits = dwLen;
  151. }
  152. }
  153. else
  154. {
  155. if (m_tpBaseDigits != NULL)
  156. {
  157. HeapFree(GetProcessHeap(), 0, m_tpBaseDigits);
  158. m_tpBaseDigits = NULL;
  159. m_dwBaseDigits = 0;
  160. }
  161. assert(m_tpBaseDigits == NULL && m_dwBaseDigits == 0);
  162. }
  163. return dwReturn;
  164. }
  165. // ************************************************
  166. DWORD CDataCoding::EncodeData(LPBYTE pbSource, //[IN] Stream of Bytes to be encoded
  167. TCHAR **pbEncodedData) //[OUT] Pointer to a string containing the encoded data
  168. // I allocate the Buffer, you should free it
  169. {
  170. assert(m_dwInputDataBits > 0);
  171. assert(m_dwInputDataBytes > 0);
  172. assert(m_dwEncodedLength > 0);
  173. assert(m_tpBaseDigits != NULL);
  174. DWORD dwReturn = ERROR_SUCCESS;
  175. int nStartIndex = m_dwEncodedLength;
  176. *pbEncodedData = NULL;
  177. BYTE * pbDataToEncode = NULL;
  178. TCHAR * pbEncodeBuffer = NULL;
  179. if (NULL == pbEncodedData)
  180. {
  181. dwReturn = ERROR_INVALID_PARAMETER;
  182. goto done;
  183. }
  184. *pbEncodedData = NULL;
  185. pbEncodeBuffer = (TCHAR *) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
  186. (m_dwEncodedLength+1)*sizeof(TCHAR));
  187. if (pbEncodeBuffer == NULL)
  188. {
  189. dwReturn = ERROR_NOT_ENOUGH_MEMORY;
  190. goto done;
  191. }
  192. // Now need to make a copy of the incoming data, so we can run the algorithm below
  193. pbDataToEncode = (BYTE *) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, m_dwInputDataBytes);
  194. if (pbDataToEncode == NULL)
  195. {
  196. dwReturn = ERROR_NOT_ENOUGH_MEMORY;
  197. goto done;
  198. }
  199. memcpy(pbDataToEncode, pbSource, m_dwInputDataBytes);
  200. // Let us get rid of the simple stuff
  201. pbEncodeBuffer[ nStartIndex--] = 0;
  202. for (; nStartIndex >= 0; --nStartIndex)
  203. {
  204. unsigned int i = 0;
  205. for (int nIndex = m_dwInputDataBytes-1; 0 <= nIndex; --nIndex)
  206. {
  207. i = (i * 256) + pbDataToEncode[nIndex];
  208. pbDataToEncode[ nIndex] = (BYTE)(i / m_dwBaseDigits);
  209. i %= m_dwBaseDigits;
  210. }
  211. // i now contains the remainder, which is the current digit
  212. pbEncodeBuffer[ nStartIndex] = m_tpBaseDigits[ i];
  213. }
  214. assert(dwReturn == ERROR_SUCCESS);
  215. *pbEncodedData = pbEncodeBuffer;
  216. done:
  217. if (pbDataToEncode != NULL)
  218. {
  219. HeapFree(GetProcessHeap(), 0, pbDataToEncode);
  220. }
  221. if (dwReturn != ERROR_SUCCESS)
  222. {
  223. // There was an error, so free the memory that you allocated
  224. if (pbEncodeBuffer != NULL)
  225. {
  226. HeapFree(GetProcessHeap(), 0, pbEncodeBuffer);
  227. }
  228. }
  229. return dwReturn;
  230. }
  231. // *************************************************
  232. DWORD CDataCoding::DecodeData(TCHAR * pbEncodedData,
  233. LPBYTE * pbDecodedData)
  234. // Again, I allocate the Buffer, you release it
  235. {
  236. assert(m_dwDecodedBits > 0);
  237. assert(m_dwDecodedLength > 0);
  238. assert(m_tpBaseDigits != NULL);
  239. assert((DWORD) lstrlen(pbEncodedData) == m_dwInputEncDataBytes);
  240. DWORD dwReturn = ERROR_SUCCESS;
  241. TCHAR * tpTemp;
  242. DWORD dwDigit;
  243. unsigned int i;
  244. unsigned int nDecodedBytes, nDecodedBytesMax = 0;
  245. BYTE * pbDecodeBuffer = NULL;
  246. if (NULL == pbDecodedData)
  247. {
  248. dwReturn = ERROR_INVALID_PARAMETER;
  249. goto done;
  250. }
  251. *pbDecodedData = NULL;
  252. pbDecodeBuffer = (BYTE *) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, m_dwDecodedLength);
  253. if ( pbDecodeBuffer == NULL)
  254. {
  255. dwReturn = ERROR_NOT_ENOUGH_MEMORY;
  256. goto done;
  257. }
  258. memset(pbDecodeBuffer, 0, m_dwDecodedLength);
  259. while (*pbEncodedData)
  260. {
  261. // First Find the position of this character in the Base Encoding Character Set
  262. tpTemp = wcschr(m_tpBaseDigits, *pbEncodedData);
  263. if (tpTemp == NULL)
  264. {
  265. // Found a character which is not in base character set
  266. // ERROR ERROR
  267. dwReturn = ERROR_INVALID_DATA;
  268. goto done;
  269. }
  270. dwDigit = (DWORD)(tpTemp - m_tpBaseDigits);
  271. nDecodedBytes = 0;
  272. i = (unsigned int) dwDigit;
  273. while (nDecodedBytes <= nDecodedBytesMax)
  274. {
  275. i += m_dwBaseDigits * pbDecodeBuffer[ nDecodedBytes];
  276. pbDecodeBuffer[ nDecodedBytes] = (unsigned char)i;
  277. i /= 256;
  278. ++nDecodedBytes;
  279. }
  280. if (i != 0)
  281. {
  282. assert(nDecodedBytes < m_dwDecodedLength);
  283. pbDecodeBuffer[ nDecodedBytes] = (unsigned char)i;
  284. nDecodedBytesMax = nDecodedBytes;
  285. }
  286. pbEncodedData++;
  287. }
  288. assert(dwReturn == ERROR_SUCCESS);
  289. *pbDecodedData = pbDecodeBuffer;
  290. done:
  291. if (dwReturn != ERROR_SUCCESS)
  292. {
  293. // There was an error, so free the memory that you allocated
  294. if (pbDecodeBuffer != NULL)
  295. {
  296. HeapFree(GetProcessHeap(), 0, pbDecodeBuffer);
  297. }
  298. }
  299. return dwReturn;
  300. }
  301. // **********************
  302. CDataCoding::~CDataCoding()
  303. {
  304. if (m_tpBaseDigits != NULL)
  305. {
  306. HeapFree(GetProcessHeap(), 0, m_tpBaseDigits);
  307. m_tpBaseDigits = NULL;
  308. m_dwBaseDigits = 0;
  309. }
  310. }