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.

591 lines
14 KiB

  1. /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  2. Microsoft Windows, Copyright (C) Microsoft Corporation, 2000
  3. File: EncodedData.cpp
  4. Content: Implementation of CEncodedData.
  5. History: 06-15-2001 dsie created
  6. ------------------------------------------------------------------------------*/
  7. #include "StdAfx.h"
  8. #include "CAPICOM.h"
  9. #include "EncodedData.h"
  10. #include "Convert.h"
  11. #include "Decoder.h"
  12. #include "OID.h"
  13. ////////////////////////////////////////////////////////////////////////////////
  14. //
  15. // Exported functions.
  16. //
  17. /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  18. Function : CreateEncodedDataObject
  19. Synopsis : Create and initialize an CEncodedData object.
  20. Parameter: LPSTR pszOid - Pointer to OID string.
  21. CRYPT_DATA_BLOB * pEncodedBlob - Pointer to encoded data blob.
  22. IEncodedData ** ppIEncodedData - Pointer to pointer IEncodedData
  23. object.
  24. Remark :
  25. ------------------------------------------------------------------------------*/
  26. HRESULT CreateEncodedDataObject (LPSTR pszOid,
  27. CRYPT_DATA_BLOB * pEncodedBlob,
  28. IEncodedData ** ppIEncodedData)
  29. {
  30. HRESULT hr = S_OK;
  31. CComObject<CEncodedData> * pCEncodedData = NULL;
  32. DebugTrace("Entering CreateEncodedDataObject().\n");
  33. //
  34. // Sanity check.
  35. //
  36. ATLASSERT(pszOid);
  37. ATLASSERT(pEncodedBlob);
  38. ATLASSERT(ppIEncodedData);
  39. try
  40. {
  41. //
  42. // Create the object. Note that the ref count will still be 0
  43. // after the object is created.
  44. //
  45. if (FAILED(hr = CComObject<CEncodedData>::CreateInstance(&pCEncodedData)))
  46. {
  47. DebugTrace("Error [%#x]: CComObject<CEncodedData>::CreateInstance() failed.\n", hr);
  48. goto ErrorExit;
  49. }
  50. //
  51. // Initialize object.
  52. //
  53. if (FAILED(hr = pCEncodedData->Init(pszOid, pEncodedBlob)))
  54. {
  55. DebugTrace("Error [%#x]: pCEncodedData->Init() failed.\n", hr);
  56. goto ErrorExit;
  57. }
  58. //
  59. // Return interface pointer to caller.
  60. //
  61. if (FAILED(hr = pCEncodedData->QueryInterface(ppIEncodedData)))
  62. {
  63. DebugTrace("Error [%#x]: pCEncodedData->QueryInterface() failed.\n", hr);
  64. goto ErrorExit;
  65. }
  66. }
  67. catch(...)
  68. {
  69. hr = E_POINTER;
  70. DebugTrace("Exception: invalid parameter.\n");
  71. goto ErrorExit;
  72. }
  73. CommonExit:
  74. DebugTrace("Leaving CreateEncodedDataObject().\n");
  75. return hr;
  76. ErrorExit:
  77. //
  78. // Sanity check.
  79. //
  80. ATLASSERT(FAILED(hr));
  81. if (pCEncodedData)
  82. {
  83. delete pCEncodedData;
  84. }
  85. goto CommonExit;
  86. }
  87. ////////////////////////////////////////////////////////////////////////////////
  88. //
  89. // CEncodedData
  90. //
  91. /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  92. Function : CEncodedData::get_Value
  93. Synopsis : Return the encoded data.
  94. Parameter: CAPICOM_ENCODING_TYPE EncodingType - Encoding type.
  95. BSTR * pVal - Pointer to BSTR to receive the EncodedData blob.
  96. Remark :
  97. NOTE : The OID is not exported, so it is up to the caller to corelate
  98. the blob to the proper OID it represents.
  99. ------------------------------------------------------------------------------*/
  100. STDMETHODIMP CEncodedData::get_Value (CAPICOM_ENCODING_TYPE EncodingType,
  101. BSTR * pVal)
  102. {
  103. HRESULT hr = S_OK;
  104. DebugTrace("Entering CEncodedData::get_Value().\n");
  105. try
  106. {
  107. //
  108. // Lock access to this object.
  109. //
  110. m_Lock.Lock();
  111. //
  112. // Check parameters.
  113. //
  114. if (NULL == pVal)
  115. {
  116. hr = E_INVALIDARG;
  117. DebugTrace("Error [%#x]: Parameter pVal is NULL.\n", hr);
  118. goto ErrorExit;
  119. }
  120. //
  121. // Sanity check.
  122. //
  123. ATLASSERT(m_pszOid);
  124. ATLASSERT(m_EncodedBlob.cbData);
  125. ATLASSERT(m_EncodedBlob.pbData);
  126. //
  127. // Export EncodedData.
  128. //
  129. if (FAILED(hr = ::ExportData(m_EncodedBlob, EncodingType, pVal)))
  130. {
  131. DebugTrace("Error [%#x]: ExportData() failed.\n", hr);
  132. goto ErrorExit;
  133. }
  134. }
  135. catch(...)
  136. {
  137. hr = E_POINTER;
  138. DebugTrace("Exception: invalid parameter.\n");
  139. goto ErrorExit;
  140. }
  141. UnlockExit:
  142. //
  143. // Unlock access to this object.
  144. //
  145. m_Lock.Unlock();
  146. DebugTrace("Leaving CEncodedData::get_Value().\n");
  147. return hr;
  148. ErrorExit:
  149. //
  150. // Sanity check.
  151. //
  152. ATLASSERT(FAILED(hr));
  153. ReportError(hr);
  154. goto UnlockExit;
  155. }
  156. /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  157. Function : CEncodedData::Format
  158. Synopsis : Format the encoded data.
  159. Parameter: VARIANT_BOOL bMultiLines - True for multi-lines format.
  160. BSTR * pVal - Pointer to BSTR to receive formatted output.
  161. Remark :
  162. ------------------------------------------------------------------------------*/
  163. STDMETHODIMP CEncodedData::Format (VARIANT_BOOL bMultiLines,
  164. BSTR * pVal)
  165. {
  166. HRESULT hr = S_OK;
  167. DWORD cbFormat = 0;
  168. LPWSTR pwszFormat = NULL;
  169. DebugTrace("Entering CEncodedData::Format().\n");
  170. try
  171. {
  172. //
  173. // Lock access to this object.
  174. //
  175. m_Lock.Lock();
  176. //
  177. // Check parameters.
  178. //
  179. if (NULL == pVal)
  180. {
  181. hr = E_INVALIDARG;
  182. DebugTrace("Error [%#x]: Parameter pVal is NULL.\n", hr);
  183. goto ErrorExit;
  184. }
  185. //
  186. // Sanity check.
  187. //
  188. ATLASSERT(m_pszOid);
  189. ATLASSERT(m_EncodedBlob.cbData);
  190. ATLASSERT(m_EncodedBlob.pbData);
  191. //
  192. // Format.
  193. //
  194. if (!::CryptFormatObject(X509_ASN_ENCODING,
  195. 0,
  196. bMultiLines ? CRYPT_FORMAT_STR_MULTI_LINE : 0,
  197. NULL,
  198. m_pszOid,
  199. m_EncodedBlob.pbData,
  200. m_EncodedBlob.cbData,
  201. NULL,
  202. &cbFormat))
  203. {
  204. hr = HRESULT_FROM_WIN32(::GetLastError());
  205. DebugTrace("Info [%#x]: CryptFormatObject() failed to get size, so converting to hex.\n", hr);
  206. //
  207. // Most likely CryptFormatObject() does not understand the OID (downlevel platforms),
  208. // so try to convert it to hex ourselves.
  209. //
  210. if (FAILED(hr = ::BinaryToString(m_EncodedBlob.pbData,
  211. m_EncodedBlob.cbData,
  212. CRYPT_STRING_HEX,
  213. &*pVal,
  214. NULL)))
  215. {
  216. DebugTrace("Error [%#x]: BinaryToString() failed.\n", hr);
  217. goto ErrorExit;
  218. }
  219. goto UnlockExit;
  220. }
  221. if (!(pwszFormat = (LPWSTR) ::CoTaskMemAlloc(cbFormat)))
  222. {
  223. hr = E_OUTOFMEMORY;
  224. DebugTrace("Error: out of memory.\n");
  225. goto ErrorExit;
  226. }
  227. if (!::CryptFormatObject(X509_ASN_ENCODING,
  228. 0,
  229. bMultiLines ? CRYPT_FORMAT_STR_MULTI_LINE : 0,
  230. NULL,
  231. m_pszOid,
  232. m_EncodedBlob.pbData,
  233. m_EncodedBlob.cbData,
  234. (LPVOID) pwszFormat,
  235. &cbFormat))
  236. {
  237. hr = HRESULT_FROM_WIN32(::GetLastError());
  238. DebugTrace("Error [%#x]: CryptFormatObject() failed to get data.\n", hr);
  239. goto ErrorExit;
  240. }
  241. //
  242. // Return formatted string to caller.
  243. //
  244. if (!(*pVal = ::SysAllocString(pwszFormat)))
  245. {
  246. hr = E_OUTOFMEMORY;
  247. DebugTrace("Error: out of memory.\n");
  248. goto ErrorExit;
  249. }
  250. }
  251. catch(...)
  252. {
  253. hr = E_POINTER;
  254. DebugTrace("Exception: invalid parameter.\n");
  255. goto ErrorExit;
  256. }
  257. UnlockExit:
  258. //
  259. // Free resources.
  260. //
  261. if (pwszFormat)
  262. {
  263. ::CoTaskMemFree((LPVOID) pwszFormat);
  264. }
  265. //
  266. // Unlock access to this object.
  267. //
  268. m_Lock.Unlock();
  269. DebugTrace("Leaving CEncodedData::Format().\n");
  270. return hr;
  271. ErrorExit:
  272. //
  273. // Sanity check.
  274. //
  275. ATLASSERT(FAILED(hr));
  276. ReportError(hr);
  277. goto UnlockExit;
  278. }
  279. /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  280. Function : CEncodedData::Decoder
  281. Synopsis : Return the decoder object.
  282. Parameter: IDispatch ** pVal - Pointer to pointer to IDispatch to receive
  283. the decoder object.
  284. Remark : Not all EncodedData has an associated decoder. CAPICOM only
  285. provides certain decoders.
  286. ------------------------------------------------------------------------------*/
  287. STDMETHODIMP CEncodedData::Decoder (IDispatch ** pVal)
  288. {
  289. HRESULT hr = S_OK;
  290. DebugTrace("Entering CEncodedData::Decoder().\n");
  291. try
  292. {
  293. //
  294. // Lock access to this object.
  295. //
  296. m_Lock.Lock();
  297. //
  298. // Check parameters.
  299. //
  300. if (NULL == pVal)
  301. {
  302. hr = E_INVALIDARG;
  303. DebugTrace("Error [%#x]: Parameter pVal is NULL.\n", hr);
  304. goto ErrorExit;
  305. }
  306. #if (0) // DSIE: is only created by us, so it is always initialized.
  307. //
  308. // Make sure object is already initialized.
  309. //
  310. if (!m_pszOid)
  311. {
  312. hr = CAPICOM_E_ENCODE_NOT_INITIALIZED;
  313. DebugTrace("Error [%#x]: encode object has not been initialized.\n", hr);
  314. goto ErrorExit;
  315. }
  316. #endif
  317. //
  318. // Sanity check.
  319. //
  320. ATLASSERT(m_pszOid);
  321. ATLASSERT(m_EncodedBlob.cbData);
  322. ATLASSERT(m_EncodedBlob.pbData);
  323. //
  324. // Do we have a decoder?
  325. //
  326. if (!m_pIDecoder)
  327. {
  328. //
  329. // Attempt to create one.
  330. //
  331. if (FAILED(hr = ::CreateDecoderObject(m_pszOid, &m_EncodedBlob, &m_pIDecoder)))
  332. {
  333. DebugTrace("Error [%#x]: CreateDecoderObject() failed for OID = %s.\n", hr, m_pszOid);
  334. goto ErrorExit;
  335. }
  336. //
  337. // Did we get a decoder?
  338. if (!m_pIDecoder)
  339. {
  340. DebugTrace("Info: no decoder found for OID = %s.\n", hr, m_pszOid);
  341. goto UnlockExit;
  342. }
  343. }
  344. //
  345. // Return result.
  346. //
  347. if (FAILED(hr = m_pIDecoder->QueryInterface(pVal)))
  348. {
  349. DebugTrace("Error [%#x]: m_pIDecoder->QueryInterface() failed.\n", hr);
  350. goto ErrorExit;
  351. }
  352. }
  353. catch(...)
  354. {
  355. hr = E_POINTER;
  356. DebugTrace("Exception: invalid parameter.\n");
  357. goto ErrorExit;
  358. }
  359. UnlockExit:
  360. //
  361. // Unlock access to this object.
  362. //
  363. m_Lock.Unlock();
  364. DebugTrace("Leaving CEncodedData::Decoder().\n");
  365. return hr;
  366. ErrorExit:
  367. //
  368. // Sanity check.
  369. //
  370. ATLASSERT(FAILED(hr));
  371. ReportError(hr);
  372. goto UnlockExit;
  373. }
  374. ////////////////////////////////////////////////////////////////////////////////
  375. //
  376. // Private methods.
  377. //
  378. /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  379. Function : CEncodedData::Init
  380. Synopsis : Initialize the object.
  381. Parameter: LPSTR pszOid - Pointer to OID string.
  382. CRYPT_DATA_BLOB * pEncodedBlob - Pointer to encoded data blob.
  383. Remark : This method is not part of the COM interface (it is a normal C++
  384. member function). We need it to initialize the object created
  385. internally by us.
  386. Since it is only a normal C++ member function, this function can
  387. only be called from a C++ class pointer, not an interface pointer.
  388. ------------------------------------------------------------------------------*/
  389. STDMETHODIMP CEncodedData::Init (LPSTR pszOid,
  390. CRYPT_DATA_BLOB * pEncodedBlob)
  391. {
  392. HRESULT hr = S_OK;
  393. LPSTR pszOid2 = NULL;
  394. PBYTE pbEncodedData = NULL;
  395. DebugTrace("Entering CEncodedData::Init().\n");
  396. //
  397. // Sanity check.
  398. //
  399. ATLASSERT(pszOid);
  400. ATLASSERT(pEncodedBlob);
  401. ATLASSERT(pEncodedBlob->cbData);
  402. ATLASSERT(pEncodedBlob->pbData);
  403. //
  404. // Allocate memory for OID.
  405. //
  406. if (NULL == (pszOid2 = (LPSTR) ::CoTaskMemAlloc(::strlen(pszOid) + 1)))
  407. {
  408. hr = E_OUTOFMEMORY;
  409. DebugTrace("Error [%#x]: CoTaskMemAlloc() failed.\n", hr);
  410. goto ErrorExit;
  411. }
  412. //
  413. // Copy.
  414. //
  415. ::strcpy(pszOid2, pszOid);
  416. //
  417. // Allocate memory for encoded blob.
  418. //
  419. if (NULL == (pbEncodedData = (PBYTE) ::CoTaskMemAlloc(pEncodedBlob->cbData)))
  420. {
  421. hr = E_OUTOFMEMORY;
  422. DebugTrace("Error [%#x]: CoTaskMemAlloc() failed.\n", hr);
  423. goto ErrorExit;
  424. }
  425. //
  426. // Copy.
  427. //
  428. ::CopyMemory(pbEncodedData, pEncodedBlob->pbData, pEncodedBlob->cbData);
  429. //
  430. // Update states.
  431. //
  432. m_pszOid = pszOid2;
  433. m_pIDecoder = NULL;
  434. m_EncodedBlob.cbData = pEncodedBlob->cbData;
  435. m_EncodedBlob.pbData = pbEncodedData;
  436. CommonExit:
  437. DebugTrace("Leaving CEncodedData::Init().\n");
  438. return hr;
  439. ErrorExit:
  440. //
  441. // Sanity check.
  442. //
  443. ATLASSERT(FAILED(hr));
  444. //
  445. // Free resources.
  446. //
  447. if (pszOid2)
  448. {
  449. ::CoTaskMemFree(pszOid2);
  450. }
  451. if (pbEncodedData)
  452. {
  453. ::CoTaskMemFree(pbEncodedData);
  454. }
  455. goto CommonExit;
  456. }