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.

1228 lines
31 KiB

  1. /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  2. Microsoft Windows
  3. Copyright (C) Microsoft Corporation, 1995 - 1999.
  4. File: Convert.cpp
  5. Contents: Implementation of encoding conversion routines.
  6. History: 11-15-99 dsie created
  7. ------------------------------------------------------------------------------*/
  8. #define _CRYPT32_ // This is required to statically link in pkifmt.lib.
  9. #include "StdAfx.h"
  10. #include "CAPICOM.h"
  11. #include "Convert.h"
  12. #include "Base64.h"
  13. #include <ctype.h>
  14. /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  15. Function : UnicodeToAnsi
  16. Synopsis : Convert an array of unicode character to ANSI.
  17. Parameter: LPWSTR pwszUnicodeString - Pointer to Unicode string to be
  18. converted to ANSI string.
  19. int cchWideChar - Number of characters, or -1 if
  20. pwszUnicodeString is NULL terminated.
  21. LPSTR * ppszAnsiString - Pointer to LPSTR to received the
  22. converted ANSI string.
  23. int * pcchAnsiChar (Optional) - Pointer to int to receive
  24. the number of characters
  25. translated.
  26. Remark : Caller must call CoTaskMemFree to free the returned ANSI string.
  27. ------------------------------------------------------------------------------*/
  28. HRESULT UnicodeToAnsi (LPWSTR pwszUnicodeString,
  29. int cchWideChar,
  30. LPSTR * ppszAnsiString,
  31. int * pcchAnsiChar)
  32. {
  33. HRESULT hr = S_OK;
  34. int cchAnsiChar = 0;
  35. LPSTR pszAnsiString = NULL;
  36. DebugTrace("Entering UnicodeToAnsi().\n");
  37. //
  38. // Make sure parameter is valid.
  39. //
  40. if (NULL == pwszUnicodeString || NULL == ppszAnsiString)
  41. {
  42. hr = E_INVALIDARG;
  43. DebugTrace("Error [%#x]: pwszUnicodeString = %#x, ppszAnsiString = %#x.\n",
  44. hr, pwszUnicodeString, ppszAnsiString);
  45. goto ErrorExit;
  46. }
  47. //
  48. // Determine ANSI length.
  49. //
  50. cchAnsiChar = ::WideCharToMultiByte(CP_ACP, // code page
  51. 0, // performance and mapping flags
  52. pwszUnicodeString, // wide-character string
  53. cchWideChar, // number of chars in string
  54. NULL, // buffer for new string
  55. 0, // size of buffer
  56. NULL, // default for unmappable chars
  57. NULL); // set when default char used
  58. if (0 == cchAnsiChar)
  59. {
  60. hr = HRESULT_FROM_WIN32(::GetLastError());
  61. DebugTrace("Error [%#x]: WideCharToMultiByte() failed.\n", hr);
  62. goto ErrorExit;
  63. }
  64. //
  65. // Allocate memory for ANSI string.
  66. //
  67. if (!(pszAnsiString = (LPSTR) ::CoTaskMemAlloc(cchAnsiChar)))
  68. {
  69. hr = E_OUTOFMEMORY;
  70. DebugTrace("Error [%#x]: CoTaskMemAlloc() failed.\n", hr);
  71. goto ErrorExit;
  72. }
  73. //
  74. // Conver to ANSI.
  75. //
  76. cchAnsiChar = ::WideCharToMultiByte(CP_ACP,
  77. 0,
  78. pwszUnicodeString,
  79. cchWideChar,
  80. pszAnsiString,
  81. cchAnsiChar,
  82. NULL,
  83. NULL);
  84. if (0 == cchAnsiChar)
  85. {
  86. hr = HRESULT_FROM_WIN32(::GetLastError());
  87. DebugTrace("Error [%#x]: WideCharToMultiByte() failed.\n", hr);
  88. goto ErrorExit;
  89. }
  90. //
  91. // Return values to caller.
  92. //
  93. if (pcchAnsiChar)
  94. {
  95. *pcchAnsiChar = cchAnsiChar;
  96. }
  97. *ppszAnsiString = pszAnsiString;
  98. CommonExit:
  99. DebugTrace("Leaving UnicodeToAnsi().\n");
  100. return hr;
  101. ErrorExit:
  102. //
  103. // Sanity check.
  104. //
  105. ATLASSERT(FAILED(hr));
  106. //
  107. // Free resources.
  108. //
  109. if (pszAnsiString)
  110. {
  111. ::CoTaskMemFree(pszAnsiString);
  112. }
  113. goto CommonExit;
  114. }
  115. #if (0)
  116. /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  117. Function : AnsiToUnicode
  118. Synopsis : Convert a array of ANSI character to Unicode.
  119. Parameter: LPSTR pszAnsiString - Pointer to ANSI string to be converted to
  120. ANSI string.
  121. DWORD cchAnsiChar - Number of characters, or -1 if pszAnsiString
  122. is NULL terminated.
  123. LPWSTR * ppwszUnicodeString - Pointer to LPWSTR to received the
  124. converted Unicode string.
  125. DWORD * pcchUnicodeChar (Optional) - Pointer to DWORD to receive
  126. the number of characters
  127. translated.
  128. Remark : Caller must call CoTaskMemFree to free the returned Unicode string.
  129. ------------------------------------------------------------------------------*/
  130. HRESULT AnsiToUnicode (LPSTR pszAnsiString,
  131. DWORD cchAnsiChar,
  132. LPWSTR * ppwszUnicodeString,
  133. DWORD * pcchUnicodeChar)
  134. {
  135. HRESULT hr = S_OK;
  136. DWORD cchUnicodeChar = 0;
  137. LPWSTR pwszUnicodeString = NULL;
  138. DebugTrace("Entering AnsiToUnicode().\n");
  139. //
  140. // Make sure parameter is valid.
  141. //
  142. if (NULL == pszAnsiString || NULL == ppwszUnicodeString)
  143. {
  144. hr = E_INVALIDARG;
  145. DebugTrace("Error [%#x]: pszAnsiString = %#x, ppwszUnicodeString = %#x.\n",
  146. hr, pszAnsiString, ppwszUnicodeString);
  147. goto ErrorExit;
  148. }
  149. //
  150. // Determine Unicode length.
  151. //
  152. cchUnicodeChar = ::MultiByteToWideChar(CP_ACP, // code page
  153. 0, // performance and mapping flags
  154. pszAnsiString, // ANSI string
  155. cchAnsiChar, // number of chars in string
  156. NULL, // buffer for new Unicode string
  157. 0); // size of buffer
  158. if (0 == cchUnicodeChar)
  159. {
  160. hr = HRESULT_FROM_WIN32(::GetLastError());
  161. DebugTrace("Error [%#x]: MultiByteToWideChar() failed.\n", hr);
  162. goto ErrorExit;
  163. }
  164. //
  165. // Allocate memory for Unicode string.
  166. //
  167. if (!(pwszUnicodeString = (LPWSTR) ::CoTaskMemAlloc(cchUnicodeChar * sizeof(WCHAR))))
  168. {
  169. hr = E_OUTOFMEMORY;
  170. DebugTrace("Error [%#x]: CoTaskMemAlloc() failed.\n", hr);
  171. goto ErrorExit;
  172. }
  173. //
  174. // Conver to ANSI.
  175. //
  176. cchUnicodeChar = ::MultiByteToWideChar(CP_ACP,
  177. 0,
  178. pszAnsiString,
  179. cchAnsiChar,
  180. pwszUnicodeString,
  181. cchUnicodeChar);
  182. if (0 == cchUnicodeChar)
  183. {
  184. hr = HRESULT_FROM_WIN32(::GetLastError());
  185. DebugTrace("Error [%#x]: MultiByteToWideChar() failed.\n", hr);
  186. goto ErrorExit;
  187. }
  188. //
  189. // Return values to caller.
  190. //
  191. if (pcchUnicodeChar)
  192. {
  193. *pcchUnicodeChar = cchUnicodeChar;
  194. }
  195. *ppwszUnicodeString = pwszUnicodeString;
  196. CommonExit:
  197. DebugTrace("Leaving AnsiToUnicode().\n");
  198. return hr;
  199. ErrorExit:
  200. //
  201. // Sanity check.
  202. //
  203. ATLASSERT(FAILED(hr));
  204. //
  205. // Free resources.
  206. //
  207. if (pwszUnicodeString)
  208. {
  209. ::CoTaskMemFree(pwszUnicodeString);
  210. }
  211. goto CommonExit;
  212. }
  213. #endif
  214. /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  215. Function : ByteToHex
  216. Synopsis : Convert a byte to hex character.
  217. Parameter: BYTE byte - Byte to be converted.
  218. Remark : Data must be valid, i.e. 0 through 15.
  219. ------------------------------------------------------------------------------*/
  220. static inline WCHAR ByteToHex (BYTE byte)
  221. {
  222. ATLASSERT(byte < 16);
  223. if(byte < 10)
  224. {
  225. return (WCHAR) (byte + L'0');
  226. }
  227. else
  228. {
  229. return (WCHAR) ((byte - 10) + L'A');
  230. }
  231. }
  232. /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  233. Function : HexToByte
  234. Synopsis : Convert a hex character to byte.
  235. Parameter: WCHAR wc - Hex character to be converted.
  236. Remark : 0xff is returned if wc is not a hex character.
  237. ------------------------------------------------------------------------------*/
  238. static inline BYTE HexToByte (WCHAR wc)
  239. {
  240. BYTE b;
  241. if (!iswxdigit(wc))
  242. {
  243. return (BYTE) 0xff;
  244. }
  245. if (iswdigit(wc))
  246. {
  247. b = (BYTE) (wc - L'0');
  248. }
  249. else if (iswupper(wc))
  250. {
  251. b = (BYTE) (wc - L'A' + 10);
  252. }
  253. else
  254. {
  255. b = (BYTE) (wc - L'a' + 10);
  256. }
  257. return (b);
  258. }
  259. /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  260. Function : IntBlobToHexString
  261. Synopsis : Convert an interger blob to hex string.
  262. Parameter: BYTE byte - Byte to be converted.
  263. Remark :
  264. ------------------------------------------------------------------------------*/
  265. HRESULT IntBlobToHexString (CRYPT_INTEGER_BLOB * pBlob, BSTR * pbstrHex)
  266. {
  267. HRESULT hr = S_OK;
  268. LPWSTR pwszStr = NULL;
  269. LPWSTR pwszTemp = NULL;
  270. DWORD cbData = 0;
  271. DebugTrace("Entering IntBlobToHexString().\n");
  272. //
  273. // Sanity check.
  274. //
  275. ATLASSERT(pBlob);
  276. ATLASSERT(pbstrHex);
  277. try
  278. {
  279. //
  280. // Make sure parameters are valid.
  281. //
  282. if (!pBlob->cbData || !pBlob->pbData)
  283. {
  284. hr = E_INVALIDARG;
  285. DebugTrace("Error: invalid parameter, empty integer blob.\n");
  286. goto ErrorExit;
  287. }
  288. //
  289. // Allocate memory (Need 2 wchars for each byte, plus a NULL character).
  290. //
  291. if (NULL == (pwszStr = (LPWSTR) ::CoTaskMemAlloc((pBlob->cbData * 2 + 1) * sizeof(WCHAR))))
  292. {
  293. hr = E_OUTOFMEMORY;
  294. DebugTrace("Error: out of memory.\n");
  295. goto ErrorExit;
  296. }
  297. //
  298. // Now convert it to hex string (Remember data is stored in little-endian).
  299. //
  300. pwszTemp = pwszStr;
  301. cbData = pBlob->cbData;
  302. while (cbData--)
  303. {
  304. //
  305. // Get the byte.
  306. //
  307. BYTE byte = pBlob->pbData[cbData];
  308. //
  309. // Convert upper nibble.
  310. //
  311. *pwszTemp++ = ::ByteToHex((BYTE) ((byte & 0xf0) >> 4));
  312. //
  313. // Conver lower nibble.
  314. //
  315. *pwszTemp++ = ::ByteToHex((BYTE) (byte & 0x0f));
  316. }
  317. //
  318. // NULL terminate it.
  319. //
  320. *pwszTemp = L'\0';
  321. //
  322. // Return BSTR to caller.
  323. //
  324. if (NULL == (*pbstrHex = ::SysAllocString(pwszStr)))
  325. {
  326. hr = E_OUTOFMEMORY;
  327. DebugTrace("Error: out of memory.\n");
  328. goto ErrorExit;
  329. }
  330. }
  331. catch(...)
  332. {
  333. hr = E_POINTER;
  334. DebugTrace("Exception: invalid parameter.\n");
  335. goto ErrorExit;
  336. }
  337. CommonExit:
  338. //
  339. // Free resources.
  340. //
  341. if (pwszStr)
  342. {
  343. ::CoTaskMemFree(pwszStr);
  344. }
  345. DebugTrace("Leaving IntBlobToHexString().\n");
  346. return hr;
  347. ErrorExit:
  348. //
  349. // Sanity check.
  350. //
  351. ATLASSERT(FAILED(hr));
  352. goto CommonExit;
  353. }
  354. /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  355. Function : BinaryToHexString
  356. Synopsis : Convert binary data to hex string.
  357. Parameter: BYTE * pbBytes - Bytes to be converted.
  358. DWORD cBytes - Number of bytes to be converted.
  359. BSTR * pbstrHex - Pointer to BSTR to received converted hex string.
  360. Remark :
  361. ------------------------------------------------------------------------------*/
  362. HRESULT BinaryToHexString (BYTE * pbBytes, DWORD cBytes, BSTR * pbstrHex)
  363. {
  364. HRESULT hr = S_OK;
  365. LPWSTR pwszTemp = NULL;
  366. LPWSTR pwszStr = NULL;
  367. DebugTrace("Entering BinaryToHexString().\n");
  368. //
  369. // Sanity check.
  370. //
  371. ATLASSERT(pbBytes);
  372. ATLASSERT(pbstrHex);
  373. //
  374. // Allocate memory. (Need 2 wchars for each byte, plus a NULL character).
  375. //
  376. if (NULL == (pwszStr = (LPWSTR) ::CoTaskMemAlloc((cBytes * 2 + 1) * sizeof(WCHAR))))
  377. {
  378. hr = E_OUTOFMEMORY;
  379. DebugTrace("Error: out of memory.\n");
  380. goto ErrorExit;
  381. }
  382. //
  383. // Now convert it to hex string.
  384. //
  385. pwszTemp = pwszStr;
  386. while (cBytes--)
  387. {
  388. //
  389. // Get the byte.
  390. //
  391. BYTE byte = *pbBytes++;
  392. //
  393. // Convert upper nibble.
  394. //
  395. *pwszTemp++ = ::ByteToHex((BYTE) ((byte & 0xf0) >> 4));
  396. //
  397. // Conver lower nibble.
  398. //
  399. *pwszTemp++ = ::ByteToHex((BYTE) (byte & 0x0f));
  400. }
  401. //
  402. // NULL terminate it.
  403. //
  404. *pwszTemp = L'\0';
  405. //
  406. // Return BSTR to caller.
  407. //
  408. if (NULL == (*pbstrHex = ::SysAllocString(pwszStr)))
  409. {
  410. hr = E_OUTOFMEMORY;
  411. DebugTrace("Error [%#x]: SysAllocString() failed.\n", hr);
  412. goto ErrorExit;
  413. }
  414. CommonExit:
  415. //
  416. // Free resources.
  417. //
  418. if (pwszStr)
  419. {
  420. ::CoTaskMemFree(pwszStr);
  421. }
  422. DebugTrace("Leaving BinaryToHexString().\n");
  423. return hr;
  424. ErrorExit:
  425. //
  426. // Sanity check.
  427. //
  428. ATLASSERT(FAILED(hr));
  429. goto CommonExit;
  430. }
  431. /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  432. Function : HexToBinaryString
  433. Synopsis : Convert hex string to binary data.
  434. Parameter: BSTR bstrHex - Hex string to be converted.
  435. BSTR * pbstrBinary - Pointer to BSTR to received converted string.
  436. Remark :
  437. ------------------------------------------------------------------------------*/
  438. HRESULT HexToBinaryString (BSTR bstrHex, BSTR * pbstrBinary)
  439. {
  440. HRESULT hr = S_OK;
  441. LPWSTR pwszHex = NULL;
  442. LPSTR pbBinary = NULL;
  443. DebugTrace("Entering HexToBinaryString().\n");
  444. //
  445. // Sanity check.
  446. //
  447. ATLASSERT(bstrHex);
  448. ATLASSERT(pbstrBinary);
  449. DWORD i;
  450. DWORD cchHex = ::SysStringLen(bstrHex);
  451. //
  452. // Make sure even number of hex chars.
  453. //
  454. if (cchHex & 0x00000001)
  455. {
  456. hr = E_INVALIDARG;
  457. DebugTrace("Error [%#x]: bstrHex does not contain even number of characters.\n", hr);
  458. goto ErrorExit;
  459. }
  460. //
  461. // Allocate memory. (Need 1 byte for two hex chars).
  462. //
  463. cchHex /= 2;
  464. if (NULL == (pbBinary = (LPSTR) ::CoTaskMemAlloc(cchHex)))
  465. {
  466. hr = E_OUTOFMEMORY;
  467. DebugTrace("Error [%#x]: CoTaskMemAlloc() failed.\n", hr);
  468. goto ErrorExit;
  469. }
  470. //
  471. // Now convert it to binary.
  472. //
  473. pwszHex = bstrHex;
  474. for (i = 0; i < cchHex; i++)
  475. {
  476. //
  477. // Convert upper and lower nibbles.
  478. //
  479. #if (0) // DSIE - Work around compiler's bug.
  480. pbBinary[i] = (BYTE) ((::HexToByte(*pwszHex++) << 4) | ::HexToByte(*pwszHex++));
  481. #else
  482. pbBinary[i] = (BYTE) ((::HexToByte(*pwszHex) << 4) | ::HexToByte(*(pwszHex + 1)));
  483. pwszHex += 2;
  484. #endif
  485. }
  486. //
  487. // Return BSTR to caller.
  488. //
  489. if (NULL == (*pbstrBinary = ::SysAllocStringByteLen(pbBinary, cchHex)))
  490. {
  491. hr = E_OUTOFMEMORY;
  492. DebugTrace("Error [%#x]: SysAllocStringByteLen() failed.\n", hr);
  493. goto ErrorExit;
  494. }
  495. CommonExit:
  496. //
  497. // Free resources.
  498. //
  499. if (pbBinary)
  500. {
  501. ::CoTaskMemFree(pbBinary);
  502. }
  503. DebugTrace("Leaving HexToBinaryString().\n");
  504. return hr;
  505. ErrorExit:
  506. //
  507. // Sanity check.
  508. //
  509. ATLASSERT(FAILED(hr));
  510. goto CommonExit;
  511. }
  512. /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  513. Function : StringToBinary
  514. Synopsis : Convert a formatted string to binary value.
  515. Parameter: LPCWSTR pwszString - Pointer to string to be converted.
  516. DWORD cchString - Number of characters in pwszString.
  517. DWORD dwFormat - Conversion format (See WinCrypt.h).
  518. PBYTE * ppbBinary - Pointer to pointer to buffer to hold binary
  519. data.
  520. DWORD * pdwBinary - Number of bytes in the binary buffer.
  521. Remark : Caller free the buffer by calling CoTaskMemFree().
  522. ------------------------------------------------------------------------------*/
  523. HRESULT StringToBinary (LPCWSTR pwszString,
  524. DWORD cchString,
  525. DWORD dwFormat,
  526. PBYTE * ppbBinary,
  527. DWORD * pdwBinary)
  528. {
  529. HRESULT hr = S_OK;
  530. PBYTE pbBinary = NULL;
  531. DWORD dwBinary = 0;
  532. DebugTrace("Entering StringToBinary().\n");
  533. //
  534. // Sanity check.
  535. //
  536. ATLASSERT(pwszString);
  537. if (!::CryptStringToBinaryW(pwszString,
  538. cchString,
  539. dwFormat,
  540. NULL,
  541. &dwBinary,
  542. NULL,
  543. NULL))
  544. {
  545. hr = HRESULT_FROM_WIN32(::GetLastError());
  546. DebugTrace("Error [%#x]: CryptStringToBinaryW() failed.\n", hr);
  547. goto ErrorExit;
  548. }
  549. if (pdwBinary)
  550. {
  551. *pdwBinary = dwBinary;
  552. }
  553. if (ppbBinary)
  554. {
  555. if (NULL == (pbBinary = (PBYTE) ::CoTaskMemAlloc(dwBinary)))
  556. {
  557. hr = E_OUTOFMEMORY;
  558. DebugTrace("Error [%#x]: CoTaskMemAlloc() failed.\n", hr);
  559. goto ErrorExit;
  560. }
  561. if (!::CryptStringToBinaryW(pwszString,
  562. cchString,
  563. dwFormat,
  564. pbBinary,
  565. &dwBinary,
  566. NULL,
  567. NULL))
  568. {
  569. hr = HRESULT_FROM_WIN32(::GetLastError());
  570. DebugTrace("Error [%#x]: CryptStringToBinaryW() failed.\n", hr);
  571. goto ErrorExit;
  572. }
  573. *ppbBinary = pbBinary;
  574. }
  575. CommonExit:
  576. DebugTrace("Leaving StringToBinary().\n");
  577. return hr;
  578. ErrorExit:
  579. //
  580. // Sanity check.
  581. //
  582. ATLASSERT(FAILED(hr));
  583. //
  584. // Free resources.
  585. //
  586. if (pbBinary)
  587. {
  588. ::CoTaskMemFree(pbBinary);
  589. }
  590. goto CommonExit;
  591. }
  592. /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  593. Function : BinaryToString
  594. Synopsis : Convert a binary value to formatted string.
  595. Parameter: PBYTE pbBinary - Pointer to buffer of binary data.
  596. DWORD cbBinary - Number of bytes in the binary buffer.
  597. DWORD dwFormat - Conversion format (See WinCrypt.h).
  598. BSTR * pbstrString - Pointer to BSTR to receive converted
  599. string.
  600. DWORD * pcchString - Number of characters in *pbstrString.
  601. Remark : Caller free the string by calling SysFreeString().
  602. ------------------------------------------------------------------------------*/
  603. HRESULT BinaryToString (PBYTE pbBinary,
  604. DWORD cbBinary,
  605. DWORD dwFormat,
  606. BSTR * pbstrString,
  607. DWORD * pcchString)
  608. {
  609. HRESULT hr = S_OK;
  610. DWORD cchString = 0;
  611. PWSTR pwszString = NULL;
  612. DebugTrace("Entering BinaryToString().\n");
  613. //
  614. // Sanity check.
  615. //
  616. ATLASSERT(pbBinary);
  617. if (!::CryptBinaryToStringW(pbBinary,
  618. cbBinary,
  619. dwFormat,
  620. NULL,
  621. &cchString))
  622. {
  623. hr = HRESULT_FROM_WIN32(::GetLastError());
  624. DebugTrace("Error [%#x]: CryptBinaryToStringW() failed.\n", hr);
  625. goto ErrorExit;
  626. }
  627. if (pbstrString)
  628. {
  629. //
  630. // Sanity check.
  631. //
  632. ATLASSERT(cchString);
  633. //
  634. // Allocate memory.
  635. //
  636. if (NULL == (pwszString = (LPWSTR) ::CoTaskMemAlloc(cchString * sizeof(WCHAR))))
  637. {
  638. hr = E_OUTOFMEMORY;
  639. DebugTrace("Error [%#x]: CoTaskMemAlloc() failed.\n", hr);
  640. goto ErrorExit;
  641. }
  642. if (!::CryptBinaryToStringW(pbBinary,
  643. cbBinary,
  644. dwFormat,
  645. pwszString,
  646. &cchString))
  647. {
  648. hr = HRESULT_FROM_WIN32(::GetLastError());
  649. DebugTrace("Error [%#x]: CryptBinaryToStringW() failed.\n", hr);
  650. goto ErrorExit;
  651. }
  652. //
  653. // Return base64 encoded string to caller.
  654. //
  655. if (NULL == (*pbstrString = ::SysAllocString(pwszString)))
  656. {
  657. hr = E_OUTOFMEMORY;
  658. DebugTrace("Error [%#x]: SysAllocString() failed.\n", hr);
  659. goto ErrorExit;
  660. }
  661. }
  662. if (pcchString)
  663. {
  664. *pcchString = cchString;
  665. }
  666. CommonExit:
  667. //
  668. // Free resources.
  669. //
  670. if (pwszString)
  671. {
  672. ::CoTaskMemFree((LPVOID) pwszString);
  673. }
  674. DebugTrace("Leaving BinaryToString().\n");
  675. return hr;
  676. ErrorExit:
  677. //
  678. // Sanity check.
  679. //
  680. ATLASSERT(FAILED(hr));
  681. goto CommonExit;
  682. }
  683. /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  684. Function : BlobToBstr
  685. Synopsis : Convert a blob to BSTR.
  686. Parameter: DATA_BLOB * pDataBlob - Pointer to blob to be converted to BSTR.
  687. BSTR * lpBstr - Pointer to BSTR to receive the converted BSTR.
  688. Remark : Caller free allocated memory for the returned BSTR.
  689. ------------------------------------------------------------------------------*/
  690. HRESULT BlobToBstr (DATA_BLOB * pDataBlob,
  691. BSTR * lpBstr)
  692. {
  693. //
  694. // Return NULL if requested.
  695. //
  696. if (!lpBstr)
  697. {
  698. DebugTrace("Error: invalid parameter, lpBstr is NULL.\n");
  699. return E_INVALIDARG;
  700. }
  701. //
  702. // Make sure parameter is valid.
  703. //
  704. if (!pDataBlob->cbData || !pDataBlob->pbData)
  705. {
  706. *lpBstr = NULL;
  707. return S_OK;
  708. }
  709. //
  710. // Convert to BSTR without code page conversion.
  711. //
  712. if (!(*lpBstr = ::SysAllocStringByteLen((LPCSTR) pDataBlob->pbData, pDataBlob->cbData)))
  713. {
  714. DebugTrace("Error: out of memory.\n");
  715. return E_OUTOFMEMORY;
  716. }
  717. return S_OK;
  718. }
  719. /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  720. Function : BstrToBlob
  721. Synopsis : Convert a BSTR to blob.
  722. Parameter: BSTR bstr - BSTR to be converted to blob.
  723. DATA_BLOB * lpBlob - Pointer to DATA_BLOB to receive converted blob.
  724. Remark : Caller free allocated memory for the returned BLOB.
  725. ------------------------------------------------------------------------------*/
  726. HRESULT BstrToBlob (BSTR bstr,
  727. DATA_BLOB * lpBlob)
  728. {
  729. //
  730. // Sanity check.
  731. //
  732. ATLASSERT(lpBlob);
  733. //
  734. // Return NULL if requested.
  735. //
  736. if (0 == ::SysStringByteLen(bstr))
  737. {
  738. lpBlob->cbData = 0;
  739. lpBlob->pbData = NULL;
  740. return S_OK;
  741. }
  742. //
  743. // Allocate memory.
  744. //
  745. lpBlob->cbData = ::SysStringByteLen(bstr);
  746. if (!(lpBlob->pbData = (LPBYTE) ::CoTaskMemAlloc(lpBlob->cbData)))
  747. {
  748. DebugTrace("Error: out of memory.\n");
  749. return E_OUTOFMEMORY;
  750. }
  751. //
  752. // Convert to blob without code page conversion.
  753. //
  754. ::CopyMemory(lpBlob->pbData, (LPBYTE) bstr, lpBlob->cbData);
  755. return S_OK;
  756. }
  757. /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  758. Function : ExportData
  759. Synopsis : Export binary data to a BSTR with specified encoding type.
  760. Parameter: DATA_BLOB DataBlob - Binary data blob.
  761. CAPICOM_ENCODING_TYPE EncodingType - Encoding type.
  762. BSTR * pbstrEncoded - Pointer to BSTR to receive the encoded data.
  763. Remark :
  764. ------------------------------------------------------------------------------*/
  765. HRESULT ExportData (DATA_BLOB DataBlob,
  766. CAPICOM_ENCODING_TYPE EncodingType,
  767. BSTR * pbstrEncoded)
  768. {
  769. HRESULT hr = S_OK;
  770. DebugTrace("Entering ExportData().\n");
  771. //
  772. // Sanity check.
  773. //
  774. ATLASSERT(pbstrEncoded);
  775. //
  776. // Intialize.
  777. //
  778. *pbstrEncoded = NULL;
  779. //
  780. // Make sure there is something to convert.
  781. //
  782. if (DataBlob.cbData)
  783. {
  784. //
  785. // Sanity check.
  786. //
  787. ATLASSERT(DataBlob.pbData);
  788. //
  789. // Determine encoding type.
  790. //
  791. switch (EncodingType)
  792. {
  793. case CAPICOM_ENCODE_ANY:
  794. {
  795. //
  796. // Fall through to base64.
  797. //
  798. }
  799. case CAPICOM_ENCODE_BASE64:
  800. {
  801. //
  802. // Base64 encode.
  803. //
  804. if (FAILED(hr = ::Base64Encode(DataBlob, pbstrEncoded)))
  805. {
  806. DebugTrace("Error [%#x]: Base64Encode() failed.\n", hr);
  807. goto ErrorExit;
  808. }
  809. break;
  810. }
  811. case CAPICOM_ENCODE_BINARY:
  812. {
  813. //
  814. // No encoding needed, simply convert blob to bstr.
  815. //
  816. if (FAILED(hr = ::BlobToBstr(&DataBlob, pbstrEncoded)))
  817. {
  818. DebugTrace("Error [%#x]: BlobToBstr() failed.\n", hr);
  819. goto ErrorExit;
  820. }
  821. break;
  822. }
  823. default:
  824. {
  825. hr = CAPICOM_E_ENCODE_INVALID_TYPE;
  826. DebugTrace("Error [%#x]: invalid CAPICOM_ENCODING_TYPE.\n", hr);
  827. goto ErrorExit;
  828. }
  829. }
  830. }
  831. CommonExit:
  832. DebugTrace("Leaving ExportData().\n");
  833. return hr;
  834. ErrorExit:
  835. //
  836. // Sanity check.
  837. //
  838. ATLASSERT(FAILED(hr));
  839. goto CommonExit;
  840. }
  841. /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  842. Function : ImportData
  843. Synopsis : Import encoded data.
  844. Parameter: BSTR bstrEncoded - BSTR containing the data to be imported.
  845. CAPICOM_ENCODING_TYPE EncodingType - Encoding type.
  846. DATA_BLOB * pDataBlob - Pointer to DATA_BLOB to receive the
  847. decoded data.
  848. Remark : There is no need for encoding type parameter, as the encoding type
  849. will be determined automatically by this routine.
  850. ------------------------------------------------------------------------------*/
  851. HRESULT ImportData (BSTR bstrEncoded,
  852. CAPICOM_ENCODING_TYPE EncodingType,
  853. DATA_BLOB * pDataBlob)
  854. {
  855. HRESULT hr = S_OK;
  856. DebugTrace("Entering ImportData().\n");
  857. //
  858. // Sanity check.
  859. //
  860. ATLASSERT(pDataBlob);
  861. ATLASSERT(bstrEncoded);
  862. //
  863. // Initialize.
  864. //
  865. ::ZeroMemory((void *) pDataBlob, sizeof(DATA_BLOB));
  866. //
  867. // Which encoding type?
  868. //
  869. switch (EncodingType)
  870. {
  871. case CAPICOM_ENCODE_BASE64:
  872. {
  873. //
  874. // Decode data.
  875. //
  876. if (FAILED(hr = ::Base64Decode(bstrEncoded, pDataBlob)))
  877. {
  878. DebugTrace("Error [%#x]: Base64Decode() failed.\n", hr);
  879. goto ErrorExit;
  880. }
  881. break;
  882. }
  883. case CAPICOM_ENCODE_BINARY:
  884. {
  885. //
  886. // Decode data.
  887. //
  888. if (FAILED(hr = ::BstrToBlob(bstrEncoded, pDataBlob)))
  889. {
  890. DebugTrace("Error [%#x]: BstrToBlob() failed.\n", hr);
  891. goto ErrorExit;
  892. }
  893. break;
  894. }
  895. case CAPICOM_ENCODE_ANY:
  896. {
  897. //
  898. // Try base64 first.
  899. //
  900. if (FAILED(hr = ::Base64Decode(bstrEncoded, pDataBlob)))
  901. {
  902. //
  903. // Try HEX.
  904. //
  905. hr = S_OK;
  906. DebugTrace("Info [%#x]: Base64Decode() failed, try HEX.\n", hr);
  907. if (FAILED(hr = ::StringToBinary(bstrEncoded,
  908. ::SysStringLen(bstrEncoded),
  909. CRYPT_STRING_HEX,
  910. &pDataBlob->pbData,
  911. &pDataBlob->cbData)))
  912. {
  913. //
  914. // Try binary.
  915. //
  916. hr = S_OK;
  917. DebugTrace("Info [%#x]: All known decoding failed, so assume binary.\n", hr);
  918. if (FAILED(hr = ::BstrToBlob(bstrEncoded, pDataBlob)))
  919. {
  920. DebugTrace("Error [%#x]: BstrToBlob() failed.\n", hr);
  921. goto ErrorExit;
  922. }
  923. }
  924. }
  925. break;
  926. }
  927. default:
  928. {
  929. hr = E_INVALIDARG;
  930. DebugTrace("Error [%#x]: invalid encoding type (%d).\n", hr, EncodingType);
  931. goto ErrorExit;
  932. }
  933. }
  934. CommonExit:
  935. DebugTrace("Leaving ImportData().\n");
  936. return hr;
  937. ErrorExit:
  938. //
  939. // Sanity check.
  940. //
  941. ATLASSERT(FAILED(hr));
  942. goto CommonExit;
  943. }