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.

3205 lines
92 KiB

  1. /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  2. Microsoft Windows, Copyright (C) Microsoft Corporation, 2000
  3. File: Certificates.cpp
  4. Contents: Implementation of CCertificates class for collection of
  5. ICertificate objects.
  6. Remarks: This object is not creatable by user directly. It can only be
  7. created via property/method of other CAPICOM objects.
  8. The collection container is implemented usign STL::map of
  9. STL::pair of BSTR and ICertificate..
  10. See Chapter 9 of "BEGINNING ATL 3 COM Programming" for algorithm
  11. adopted in here.
  12. History: 11-15-99 dsie created
  13. ------------------------------------------------------------------------------*/
  14. #include "StdAfx.h"
  15. #include "CAPICOM.h"
  16. #include "Certificates.h"
  17. #include "Common.h"
  18. #include "Convert.h"
  19. #include "CertHlpr.h"
  20. #include "MsgHlpr.h"
  21. #include "PFXHlpr.h"
  22. #include "Policy.h"
  23. #include "Settings.h"
  24. ////////////////////////////////////////////////////////////////////////////////
  25. //
  26. // Exported functions.
  27. //
  28. /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  29. Function : CreateCertificatesObject
  30. Synopsis : Create an ICertificates collection object, and load the object with
  31. certificates from the specified source.
  32. Parameter: CAPICOM_CERTIFICATES_SOURCE ccs - Source where to get the
  33. certificates.
  34. DWORD dwCurrentSafety - Current safety setting.
  35. BOOL bIndexedByThumbprint - TRUE to index by thumbprint.
  36. ICertificates2 ** ppICertificates - Pointer to pointer to
  37. ICertificates to receive the
  38. interface pointer.
  39. Remark :
  40. ------------------------------------------------------------------------------*/
  41. HRESULT CreateCertificatesObject (CAPICOM_CERTIFICATES_SOURCE ccs,
  42. DWORD dwCurrentSafety,
  43. BOOL bIndexedByThumbprint,
  44. ICertificates2 ** ppICertificates)
  45. {
  46. HRESULT hr = S_OK;
  47. CComObject<CCertificates> * pCCertificates = NULL;
  48. DebugTrace("Entering CreateCertificatesObject().\n");
  49. //
  50. // Sanity check.
  51. //
  52. ATLASSERT(ppICertificates);
  53. try
  54. {
  55. //
  56. // Create the object. Note that the ref count will still be 0
  57. // after the object is created.
  58. //
  59. if (FAILED(hr = CComObject<CCertificates>::CreateInstance(&pCCertificates)))
  60. {
  61. DebugTrace("Error [%#x]: CComObject<CCertificates>::CreateInstance() failed.\n", hr);
  62. goto ErrorExit;
  63. }
  64. //
  65. // Initialize object.
  66. //
  67. if (FAILED(hr = pCCertificates->Init(ccs, dwCurrentSafety, bIndexedByThumbprint)))
  68. {
  69. DebugTrace("Error [%#x]: pCCertificates->Init() failed.\n", hr);
  70. goto ErrorExit;
  71. }
  72. //
  73. // Return interface pointer to caller.
  74. //
  75. if (FAILED(hr = pCCertificates->QueryInterface(ppICertificates)))
  76. {
  77. DebugTrace("Error [%#x]: pCCertificates->QueryInterface() failed.\n", hr);
  78. goto ErrorExit;
  79. }
  80. }
  81. catch(...)
  82. {
  83. hr = E_POINTER;
  84. DebugTrace("Exception: invalid parameter.\n");
  85. goto ErrorExit;
  86. }
  87. CommonExit:
  88. DebugTrace("Leaving CreateCertificatesObject().\n");
  89. return hr;
  90. ErrorExit:
  91. //
  92. // Sanity check.
  93. //
  94. ATLASSERT(FAILED(hr));
  95. //
  96. // Free resource.
  97. //
  98. if (pCCertificates)
  99. {
  100. delete pCCertificates;
  101. }
  102. goto CommonExit;
  103. }
  104. /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  105. Function : FindTimeValidCallback
  106. Synopsis : Callback for find-time-valid.
  107. Parameter: See CryptUI.h.
  108. Remark :
  109. ------------------------------------------------------------------------------*/
  110. static BOOL WINAPI FindTimeValidCallback (PCCERT_CONTEXT pCertContext,
  111. BOOL * pfInitialSelectedCert,
  112. LPVOID pvCallbackData)
  113. {
  114. LONG lResult = 0;
  115. BOOL bInclude = TRUE;
  116. DebugTrace("Entering FindTimeValidCallback().\n");
  117. //
  118. // Sanity check.
  119. //
  120. ATLASSERT(pCertContext);
  121. ATLASSERT(pvCallbackData);
  122. //
  123. // Skip it if not yet valid or expired.
  124. //
  125. if (0 != (lResult = ::CertVerifyTimeValidity((LPFILETIME) pvCallbackData,
  126. pCertContext->pCertInfo)))
  127. {
  128. bInclude = FALSE;
  129. DebugTrace("Info: Time is not valid (lResult = %d)\n", lResult);
  130. DebugTrace(" Time (High = %#x, Low = %#x).\n",
  131. ((LPFILETIME) pvCallbackData)->dwHighDateTime,
  132. ((LPFILETIME) pvCallbackData)->dwLowDateTime);
  133. DebugTrace(" NotBefore (High = %#x, Low = %#x).\n",
  134. pCertContext->pCertInfo->NotBefore.dwHighDateTime,
  135. pCertContext->pCertInfo->NotBefore.dwLowDateTime);
  136. DebugTrace(" NotAfter (High = %#x, Low = %#x).\n",
  137. pCertContext->pCertInfo->NotAfter.dwHighDateTime,
  138. pCertContext->pCertInfo->NotAfter.dwLowDateTime);
  139. }
  140. DebugTrace("Leaving FindTimeValidCallback().\n");
  141. return bInclude;
  142. }
  143. /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  144. Function : FindNotBeforeCallback
  145. Synopsis : Callback for find-by-not-before.
  146. Parameter: See CryptUI.h.
  147. Remark :
  148. ------------------------------------------------------------------------------*/
  149. static BOOL WINAPI FindNotBeforeCallback (PCCERT_CONTEXT pCertContext,
  150. BOOL * pfInitialSelectedCert,
  151. LPVOID pvCallbackData)
  152. {
  153. BOOL bInclude = TRUE;
  154. DebugTrace("Entering FindNotBeforeCallback().\n");
  155. //
  156. // Sanity check.
  157. //
  158. ATLASSERT(pCertContext);
  159. ATLASSERT(pvCallbackData);
  160. //
  161. // Skip it if time valid or expired.
  162. //
  163. if (!(-1 == ::CertVerifyTimeValidity((LPFILETIME) pvCallbackData,
  164. pCertContext->pCertInfo)))
  165. {
  166. bInclude = FALSE;
  167. DebugTrace("Info: time (High = %#x, Low = %#x) is either valid or expired.\n",
  168. ((LPFILETIME) pvCallbackData)->dwHighDateTime,
  169. ((LPFILETIME) pvCallbackData)->dwLowDateTime);
  170. }
  171. DebugTrace("Leaving FindNotBeforeCallback().\n");
  172. return bInclude;
  173. }
  174. /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  175. Function : FindNotAfterCallback
  176. Synopsis : Callback for find-by-not-after.
  177. Parameter: See CryptUI.h.
  178. Remark :
  179. ------------------------------------------------------------------------------*/
  180. static BOOL WINAPI FindNotAfterCallback (PCCERT_CONTEXT pCertContext,
  181. BOOL * pfInitialSelectedCert,
  182. LPVOID pvCallbackData)
  183. {
  184. BOOL bInclude = TRUE;
  185. DebugTrace("Entering FindNotAfterCallback().\n");
  186. //
  187. // Sanity check.
  188. //
  189. ATLASSERT(pCertContext);
  190. ATLASSERT(pvCallbackData);
  191. //
  192. // Skip it if not expired.
  193. //
  194. if (!(1 == ::CertVerifyTimeValidity((LPFILETIME) pvCallbackData,
  195. pCertContext->pCertInfo)))
  196. {
  197. bInclude = FALSE;
  198. DebugTrace("Info: time (High = %#x, Low = %#x) is not expired.\n",
  199. ((LPFILETIME) pvCallbackData)->dwHighDateTime,
  200. ((LPFILETIME) pvCallbackData)->dwLowDateTime);
  201. }
  202. DebugTrace("Leaving FindNotAfterCallback().\n");
  203. return bInclude;
  204. }
  205. /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  206. Function : FindTemplateCallback
  207. Synopsis : Callback for find-by-template.
  208. Parameter: See CryptUI.h.
  209. Remark :
  210. ------------------------------------------------------------------------------*/
  211. static BOOL WINAPI FindTemplateCallback (PCCERT_CONTEXT pCertContext,
  212. BOOL * pfInitialSelectedCert,
  213. LPVOID pvCallbackData)
  214. {
  215. HRESULT hr = S_OK;
  216. BOOL bInclude = FALSE;
  217. DATA_BLOB CertTypeBlob = {0, NULL};
  218. DATA_BLOB TemplateBlob = {0, NULL};
  219. PCERT_EXTENSION pCertType = NULL;
  220. PCERT_EXTENSION pCertTemp = NULL;
  221. DebugTrace("Entering FindTemplateCallback().\n");
  222. //
  223. // Sanity check.
  224. //
  225. ATLASSERT(pCertContext);
  226. ATLASSERT(pvCallbackData);
  227. //
  228. // Skip it if we don't have either szOID_ENROLL_CERTTYPE_EXTENSION or
  229. // szOID_CERTIFICATE_TEMPLATE extension.
  230. //
  231. if (!(pCertType = ::CertFindExtension(szOID_ENROLL_CERTTYPE_EXTENSION,
  232. pCertContext->pCertInfo->cExtension,
  233. pCertContext->pCertInfo->rgExtension)) &&
  234. !(pCertTemp = ::CertFindExtension(szOID_CERTIFICATE_TEMPLATE,
  235. pCertContext->pCertInfo->cExtension,
  236. pCertContext->pCertInfo->rgExtension)))
  237. {
  238. DebugTrace("Info: could not find both szOID_ENROLL_CERTTYPE_EXTENSION and szOID_CERTIFICATE_TEMPLATE.\n");
  239. goto CommonExit;
  240. }
  241. //
  242. // Check cert type template name if found.
  243. //
  244. if (pCertType)
  245. {
  246. PCERT_NAME_VALUE pNameValue = NULL;
  247. //
  248. // Decode the extension.
  249. //
  250. if (FAILED(hr = ::DecodeObject(X509_UNICODE_ANY_STRING,
  251. pCertType->Value.pbData,
  252. pCertType->Value.cbData,
  253. &CertTypeBlob)))
  254. {
  255. DebugTrace("Info [%#x]: DecodeObject() failed.\n", hr);
  256. goto CommonExit;
  257. }
  258. pNameValue = (PCERT_NAME_VALUE) CertTypeBlob.pbData;
  259. if (0 == ::_wcsicmp((LPWSTR) pNameValue->Value.pbData, (LPWSTR) pvCallbackData))
  260. {
  261. bInclude = TRUE;
  262. }
  263. }
  264. //
  265. // Look into cert template extension, if necessary.
  266. //
  267. if (!bInclude && pCertTemp)
  268. {
  269. PCCRYPT_OID_INFO pOidInfo = NULL;
  270. PCERT_TEMPLATE_EXT pTemplate = NULL;
  271. //
  272. // Decode the extension.
  273. //
  274. if (FAILED(hr = ::DecodeObject(szOID_CERTIFICATE_TEMPLATE,
  275. pCertTemp->Value.pbData,
  276. pCertTemp->Value.cbData,
  277. &TemplateBlob)))
  278. {
  279. DebugTrace("Info [%#x]: DecodeObject() failed.\n", hr);
  280. goto CommonExit;
  281. }
  282. pTemplate = (PCERT_TEMPLATE_EXT) TemplateBlob.pbData;
  283. //
  284. // Convert to OID if user passed in friendly name.
  285. //
  286. if (pOidInfo = ::CryptFindOIDInfo(CRYPT_OID_INFO_NAME_KEY,
  287. pvCallbackData,
  288. CRYPT_TEMPLATE_OID_GROUP_ID))
  289. {
  290. if (0 == ::strcmp(pTemplate->pszObjId, pOidInfo->pszOID))
  291. {
  292. bInclude = TRUE;
  293. }
  294. }
  295. else
  296. {
  297. CComBSTR bstrOID;
  298. if (!(bstrOID = pTemplate->pszObjId))
  299. {
  300. DebugTrace("Info: bstrOID = pTemplate->pszObjId failed.\n", hr);
  301. goto CommonExit;
  302. }
  303. if (0 == ::wcscmp(bstrOID, (LPWSTR) pvCallbackData))
  304. {
  305. bInclude = TRUE;
  306. }
  307. }
  308. }
  309. CommonExit:
  310. //
  311. // Free resources.
  312. //
  313. if (TemplateBlob.pbData)
  314. {
  315. ::CoTaskMemFree((LPVOID) TemplateBlob.pbData);
  316. }
  317. if (CertTypeBlob.pbData)
  318. {
  319. ::CoTaskMemFree((LPVOID) CertTypeBlob.pbData);
  320. }
  321. DebugTrace("Leaving FindTemplateCallback().\n");
  322. return bInclude;
  323. }
  324. /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  325. Function : FindExtensionCallback
  326. Synopsis : Callback for find-by-extension.
  327. Parameter: See CryptUI.h.
  328. Remark :
  329. ------------------------------------------------------------------------------*/
  330. static BOOL WINAPI FindExtensionCallback (PCCERT_CONTEXT pCertContext,
  331. BOOL * pfInitialSelectedCert,
  332. LPVOID pvCallbackData)
  333. {
  334. BOOL bInclude = TRUE;
  335. PCERT_EXTENSION pExtension = NULL;
  336. DebugTrace("Entering FindExtensionCallback().\n");
  337. //
  338. // Sanity check.
  339. //
  340. ATLASSERT(pCertContext);
  341. ATLASSERT(pvCallbackData);
  342. //
  343. // Skip it if we can't find the specified extension.
  344. //
  345. if (!(pExtension = ::CertFindExtension((LPSTR) pvCallbackData,
  346. pCertContext->pCertInfo->cExtension,
  347. pCertContext->pCertInfo->rgExtension)))
  348. {
  349. bInclude = FALSE;
  350. DebugTrace("Info: extension (%s) could not be found.\n", pvCallbackData);
  351. }
  352. DebugTrace("Leaving FindExtensionCallback().\n");
  353. return bInclude;
  354. }
  355. /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  356. Function : FindRootNameCallback
  357. Synopsis : Callback for find-by-rootname.
  358. Parameter: See CryptUI.h.
  359. Remark :
  360. ------------------------------------------------------------------------------*/
  361. static BOOL WINAPI FindRootNameCallback (PCCERT_CHAIN_CONTEXT pChainContext,
  362. BOOL * pfInitialSelectedChain,
  363. LPVOID pvCallbackData)
  364. {
  365. BOOL bInclude = FALSE;
  366. HCERTSTORE hCertStore = NULL;
  367. PCCERT_CONTEXT pRootContext = NULL;
  368. PCERT_SIMPLE_CHAIN pSimpleChain;
  369. DebugTrace("Entering FindRootNameCallback().\n");
  370. //
  371. // Sanity check.
  372. //
  373. ATLASSERT(pChainContext);
  374. ATLASSERT(pvCallbackData);
  375. //
  376. // Skip if we don't have a complete chain (we don't have a root cert).
  377. //
  378. if (CERT_TRUST_IS_PARTIAL_CHAIN & pChainContext->TrustStatus.dwErrorStatus)
  379. {
  380. DebugTrace("Info: certificate has only partial chain.\n");
  381. goto CommonExit;
  382. }
  383. //
  384. // Open a new temporary memory store.
  385. //
  386. if (!(hCertStore = ::CertOpenStore(CERT_STORE_PROV_MEMORY,
  387. CAPICOM_ASN_ENCODING,
  388. NULL,
  389. CERT_STORE_CREATE_NEW_FLAG,
  390. NULL)))
  391. {
  392. DebugTrace("Info [%#x]: CertOpenStore() failed.\n",
  393. HRESULT_FROM_WIN32(::GetLastError()));
  394. goto CommonExit;
  395. }
  396. //
  397. // Copy the root cert of simple chain to memory store.
  398. //
  399. pSimpleChain = pChainContext->rgpChain[0];
  400. if (!::CertAddCertificateContextToStore(hCertStore,
  401. pSimpleChain->rgpElement[pSimpleChain->cElement - 1]->pCertContext,
  402. CERT_STORE_ADD_ALWAYS,
  403. NULL))
  404. {
  405. DebugTrace("Info [%#x]: CertAddCertificateContextToStore() failed.\n",
  406. HRESULT_FROM_WIN32(::GetLastError()));
  407. goto CommonExit;
  408. }
  409. //
  410. // Does it match?
  411. //
  412. if (!(pRootContext = ::CertFindCertificateInStore(hCertStore,
  413. CAPICOM_ASN_ENCODING,
  414. 0,
  415. CERT_FIND_SUBJECT_STR,
  416. pvCallbackData,
  417. pRootContext)))
  418. {
  419. DebugTrace("Info [%#x]: CertFindCertificateInStore() failed.\n",
  420. HRESULT_FROM_WIN32(::GetLastError()));
  421. goto CommonExit;
  422. }
  423. //
  424. // We have a match.
  425. //
  426. bInclude = TRUE;
  427. CommonExit:
  428. //
  429. // Free resources.
  430. //
  431. if (pRootContext)
  432. {
  433. ::CertFreeCertificateContext(pRootContext);
  434. }
  435. if (hCertStore)
  436. {
  437. ::CertCloseStore(hCertStore, 0);
  438. }
  439. DebugTrace("Leaving FindRootNameCallback().\n");
  440. return bInclude;
  441. }
  442. /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  443. Function : FindApplicationPolicyCallback
  444. Synopsis : Callback for find-by-application-policy.
  445. Parameter: See CryptUI.h.
  446. Remark :
  447. ------------------------------------------------------------------------------*/
  448. static BOOL WINAPI FindApplicationPolicyCallback (PCCERT_CONTEXT pCertContext,
  449. BOOL * pfInitialSelectedChain,
  450. LPVOID pvCallbackData)
  451. {
  452. BOOL bInclude = FALSE;
  453. int cNumOIDs = 0;
  454. DWORD cbOIDs = 0;
  455. LPSTR * rghOIDs = NULL;
  456. DebugTrace("Entering FindApplicationPolicyCallback().\n");
  457. //
  458. // Sanity check.
  459. //
  460. ATLASSERT(pCertContext);
  461. ATLASSERT(pvCallbackData);
  462. //
  463. // Get all the valid application usages.
  464. //
  465. if (!::CertGetValidUsages(1, &pCertContext, &cNumOIDs, NULL, &cbOIDs))
  466. {
  467. DebugTrace("Info [%#x]: CertGetValidUsages() failed.\n",
  468. HRESULT_FROM_WIN32(::GetLastError()));
  469. goto CommonExit;
  470. }
  471. if (!(rghOIDs = (LPSTR *) ::CoTaskMemAlloc(cbOIDs)))
  472. {
  473. DebugTrace("Info: out of memory..\n");
  474. goto CommonExit;
  475. }
  476. if (!::CertGetValidUsages(1, &pCertContext, &cNumOIDs, rghOIDs, &cbOIDs))
  477. {
  478. DebugTrace("Info [%#x]: CertGetValidUsages() failed.\n",
  479. HRESULT_FROM_WIN32(::GetLastError()));
  480. goto CommonExit;
  481. }
  482. //
  483. // No EKU is consider good for all.
  484. //
  485. if (-1 == cNumOIDs)
  486. {
  487. bInclude = TRUE;
  488. }
  489. else
  490. {
  491. //
  492. // See if we can find it in the array.
  493. //
  494. while (cNumOIDs--)
  495. {
  496. if (0 == ::strcmp((LPSTR) pvCallbackData, rghOIDs[cNumOIDs]))
  497. {
  498. bInclude = TRUE;
  499. break;
  500. }
  501. }
  502. }
  503. CommonExit:
  504. //
  505. // Free resources.
  506. //
  507. if (rghOIDs)
  508. {
  509. ::CoTaskMemFree((LPVOID) rghOIDs);
  510. }
  511. DebugTrace("Leaving FindApplicationPolicyCallback().\n");
  512. return bInclude;
  513. }
  514. /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  515. Function : FindCertificatePolicyCallback
  516. Synopsis : Callback for find-by-certificate-policy.
  517. Parameter: See CryptUI.h.
  518. Remark :
  519. ------------------------------------------------------------------------------*/
  520. static BOOL WINAPI FindCertificatePolicyCallback (PCCERT_CONTEXT pCertContext,
  521. BOOL * pfInitialSelectedChain,
  522. LPVOID pvCallbackData)
  523. {
  524. HRESULT hr = S_OK;
  525. BOOL bInclude = FALSE;
  526. DWORD dwIndex = 0;
  527. DATA_BLOB DataBlob = {0, NULL};
  528. PCERT_EXTENSION pExtension = NULL;
  529. PCERT_POLICIES_INFO pInfo = NULL;
  530. DebugTrace("Entering FindCertificatePolicyCallback().\n");
  531. //
  532. // Sanity check.
  533. //
  534. ATLASSERT(pCertContext);
  535. ATLASSERT(pvCallbackData);
  536. //
  537. // Find the szOID_CERT_POLICIES extension.
  538. //
  539. if (!(pExtension = ::CertFindExtension(szOID_CERT_POLICIES,
  540. pCertContext->pCertInfo->cExtension,
  541. pCertContext->pCertInfo->rgExtension)))
  542. {
  543. DebugTrace("Info [%#x]: CertFindExtension() failed.\n",
  544. HRESULT_FROM_WIN32(::GetLastError()));
  545. goto CommonExit;
  546. }
  547. //
  548. // Decode the extension.
  549. //
  550. if (FAILED(hr = ::DecodeObject(szOID_CERT_POLICIES,
  551. pExtension->Value.pbData,
  552. pExtension->Value.cbData,
  553. &DataBlob)))
  554. {
  555. DebugTrace("Info [%#x]: DecodeObject() failed.\n", hr);
  556. goto CommonExit;
  557. }
  558. pInfo = (PCERT_POLICIES_INFO) DataBlob.pbData;
  559. dwIndex = pInfo->cPolicyInfo;
  560. //
  561. // Try to find a match.
  562. //
  563. while (dwIndex--)
  564. {
  565. if (0 == ::strcmp(pInfo->rgPolicyInfo[dwIndex].pszPolicyIdentifier, (LPSTR) pvCallbackData))
  566. {
  567. bInclude = TRUE;
  568. break;
  569. }
  570. }
  571. CommonExit:
  572. //
  573. // Free resources.
  574. //
  575. if (DataBlob.pbData)
  576. {
  577. ::CoTaskMemFree((LPVOID) DataBlob.pbData);
  578. }
  579. DebugTrace("Leaving FindCertificatePolicyCallback().\n");
  580. return bInclude;
  581. }
  582. /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  583. Function : FindKeyUsageCallback
  584. Synopsis : Callback for find-by-key-usage.
  585. Parameter: See CryptUI.h.
  586. Remark :
  587. ------------------------------------------------------------------------------*/
  588. static BOOL WINAPI FindKeyUsageCallback (PCCERT_CONTEXT pCertContext,
  589. BOOL * pfInitialSelectedChain,
  590. LPVOID pvCallbackData)
  591. {
  592. HRESULT hr = S_OK;
  593. BOOL bInclude = FALSE;
  594. DWORD dwActualUsages = 0;
  595. DWORD dwCheckUsages = 0;
  596. DebugTrace("Entering FindKeyUsageCallback().\n");
  597. //
  598. // Sanity check.
  599. //
  600. ATLASSERT(pCertContext);
  601. ATLASSERT(pvCallbackData);
  602. //
  603. // Check the key usage.
  604. //
  605. if (!::CertGetIntendedKeyUsage(CAPICOM_ASN_ENCODING,
  606. pCertContext->pCertInfo,
  607. (BYTE *) &dwActualUsages,
  608. sizeof(dwActualUsages)))
  609. {
  610. //
  611. // Could be extension not present or an error.
  612. //
  613. if (FAILED(hr = HRESULT_FROM_WIN32(::GetLastError())))
  614. {
  615. DebugTrace("Error [%#x]: CertGetIntendedKeyUsage() failed.\n", hr);
  616. goto CommonExit;
  617. }
  618. }
  619. //
  620. // Check the bit mask.
  621. //
  622. dwCheckUsages = *(LPDWORD) pvCallbackData;
  623. if ((dwActualUsages & dwCheckUsages) == dwCheckUsages)
  624. {
  625. bInclude = TRUE;
  626. }
  627. CommonExit:
  628. DebugTrace("Leaving FindKeyUsageCallback().\n");
  629. return bInclude;
  630. }
  631. /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  632. Function : FindByChain
  633. Synopsis : Find certificate(s) in store based on chain's criteria and filter
  634. with a callback.
  635. Parameter: HCERTSTORE hCertStore - Store to find certificate(s).
  636. DWORD dwFindType - Find type.
  637. LPCVOID pvFindPara - Content to be found.
  638. VARIANT_BOOL bFindValidOnly - True to find valid certs only.
  639. PFNCHAINFILTERPROC pfnFilterCallback - Callback filter.
  640. LPVOID pvCallbackData - Callback data.
  641. DWORD dwCurrentSafety - Current safety setting.
  642. ICertificates2 ** ppICertificates - Pointer to pointer
  643. ICertificates2 object.
  644. Remark :
  645. ------------------------------------------------------------------------------*/
  646. static HRESULT FindByChain (HCERTSTORE hCertStore,
  647. DWORD dwFindType,
  648. LPCVOID pvFindPara,
  649. VARIANT_BOOL bFindValidOnly,
  650. PFNCHAINFILTERPROC pfnFilterCallback,
  651. LPVOID pvCallbackData,
  652. DWORD dwCurrentSafety,
  653. ICertificates2 * pICertificates)
  654. {
  655. HRESULT hr = S_OK;
  656. DWORD dwWin32Error = 0;
  657. PCCERT_CHAIN_CONTEXT pChainContext = NULL;
  658. DebugTrace("Entering FindByChain().\n");
  659. //
  660. // Sanity check.
  661. //
  662. ATLASSERT(hCertStore);
  663. ATLASSERT(pICertificates);
  664. //
  665. // Find all chains in the store, matching the find criteria.
  666. //
  667. while (pChainContext = ::CertFindChainInStore(hCertStore,
  668. CAPICOM_ASN_ENCODING,
  669. 0,
  670. dwFindType,
  671. pvFindPara,
  672. pChainContext))
  673. {
  674. CComPtr<ICertificate2> pICertificate = NULL;
  675. //
  676. // Apply filter if available.
  677. //
  678. if (pfnFilterCallback && !pfnFilterCallback(pChainContext, NULL, pvCallbackData))
  679. {
  680. continue;
  681. }
  682. //
  683. // Skip it if check is required and the cert is not valid.
  684. //
  685. if (bFindValidOnly && (CERT_TRUST_NO_ERROR != pChainContext->TrustStatus.dwErrorStatus))
  686. {
  687. continue;
  688. }
  689. //
  690. // Sanity check.
  691. //
  692. ATLASSERT(pChainContext->cChain);
  693. ATLASSERT(pChainContext->rgpChain);
  694. ATLASSERT(pChainContext->rgpChain[0]);
  695. ATLASSERT(pChainContext->rgpChain[0]->cElement);
  696. ATLASSERT(pChainContext->rgpChain[0]->rgpElement);
  697. ATLASSERT(pChainContext->rgpChain[0]->rgpElement[0]);
  698. ATLASSERT(pChainContext->rgpChain[0]->rgpElement[0]->pCertContext);
  699. //
  700. // Create a ICertificate object for the found certificate.
  701. //
  702. if (FAILED (hr = ::CreateCertificateObject(
  703. pChainContext->rgpChain[0]->rgpElement[0]->pCertContext,
  704. dwCurrentSafety,
  705. &pICertificate)))
  706. {
  707. DebugTrace("Error [%#x]: CreateCertificateObject() failed.\n", hr);
  708. goto ErrorExit;
  709. }
  710. //
  711. // Add to collection.
  712. //
  713. if (FAILED(hr = pICertificates->Add(pICertificate)))
  714. {
  715. DebugTrace("Error [%#x]: pICertificates->Add() failed.\n", hr);
  716. goto ErrorExit;
  717. }
  718. }
  719. //
  720. // Above loop can exit with normal or error condition.
  721. //
  722. if (CRYPT_E_NOT_FOUND != (dwWin32Error = ::GetLastError()))
  723. {
  724. hr = HRESULT_FROM_WIN32(dwWin32Error);
  725. DebugTrace("Error [%#x]: CertFindChainInStore() failed.\n", hr);
  726. goto ErrorExit;
  727. }
  728. CommonExit:
  729. //
  730. // Free resources.
  731. //
  732. if (pChainContext)
  733. {
  734. ::CertFreeCertificateChain(pChainContext);
  735. }
  736. DebugTrace("Leaving FindByChain().\n");
  737. return hr;
  738. ErrorExit:
  739. //
  740. // Sanity check.
  741. //
  742. ATLASSERT(FAILED(hr));
  743. goto CommonExit;
  744. }
  745. /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  746. Function : FindByCert
  747. Synopsis : Find certificate(s) in store and filter with a callback.
  748. Parameter: HCERTSTORE hCertStore - Store to find certificate(s).
  749. DWORD dwFindType - Find type.
  750. LPCVOID pvFindPara - Content to be found.
  751. VARIANT_BOOL bFindValidOnly - True to find valid certs only.
  752. PFNCERTFILTERPROC pfnFilterCallback - Callback filter.
  753. LPVOID pvCallbackData - Callback data.
  754. DWORD dwCurrentSafety - Current safety setting.
  755. ICertificates2 ** ppICertificates - Pointer to pointer
  756. ICertificates2 object.
  757. Remark :
  758. ------------------------------------------------------------------------------*/
  759. static HRESULT FindByCert (HCERTSTORE hCertStore,
  760. DWORD dwFindType,
  761. LPCVOID pvFindPara,
  762. VARIANT_BOOL bFindValidOnly,
  763. PFNCFILTERPROC pfnFilterCallback,
  764. LPVOID pvCallbackData,
  765. DWORD dwCurrentSafety,
  766. ICertificates2 * pICertificates)
  767. {
  768. HRESULT hr = S_OK;
  769. DWORD dwWin32Error = 0;
  770. PCCERT_CONTEXT pCertContext = NULL;
  771. DebugTrace("Entering FindByCert().\n");
  772. //
  773. // Sanity check.
  774. //
  775. ATLASSERT(hCertStore);
  776. ATLASSERT(pICertificates);
  777. //
  778. // Find all certificates in the store, matching the find criteria.
  779. //
  780. while (pCertContext = ::CertFindCertificateInStore(hCertStore,
  781. CAPICOM_ASN_ENCODING,
  782. 0,
  783. dwFindType,
  784. pvFindPara,
  785. pCertContext))
  786. {
  787. CComPtr<ICertificate2> pICertificate = NULL;
  788. //
  789. // Apply filter if available.
  790. //
  791. if (pfnFilterCallback && !pfnFilterCallback(pCertContext, NULL, pvCallbackData))
  792. {
  793. continue;
  794. }
  795. //
  796. // Skip it if check is required and the cert is not valid.
  797. //
  798. if (bFindValidOnly)
  799. {
  800. if (FAILED(::VerifyCertificate(pCertContext, NULL, CERT_CHAIN_POLICY_BASE)))
  801. {
  802. continue;
  803. }
  804. }
  805. //
  806. // Create a ICertificate2 object for the found certificate.
  807. //
  808. if (FAILED (hr = ::CreateCertificateObject(pCertContext,
  809. dwCurrentSafety,
  810. &pICertificate)))
  811. {
  812. DebugTrace("Error [%#x]: CreateCertificateObject() failed.\n", hr);
  813. goto ErrorExit;
  814. }
  815. //
  816. // Add to collection.
  817. //
  818. if (FAILED(hr = pICertificates->Add(pICertificate)))
  819. {
  820. DebugTrace("Error [%#x]: pICertificates->Add() failed.\n", hr);
  821. goto ErrorExit;
  822. }
  823. }
  824. //
  825. // Above loop can exit with normal or error condition.
  826. //
  827. if (CRYPT_E_NOT_FOUND != (dwWin32Error = ::GetLastError()))
  828. {
  829. hr = HRESULT_FROM_WIN32(dwWin32Error);
  830. DebugTrace("Error [%#x]: CertFindCertificateInStore() failed.\n", hr);
  831. goto ErrorExit;
  832. }
  833. CommonExit:
  834. //
  835. // Free resources.
  836. //
  837. if (pCertContext)
  838. {
  839. ::CertFreeCertificateContext(pCertContext);
  840. }
  841. DebugTrace("Leaving FindByCert().\n");
  842. return hr;
  843. ErrorExit:
  844. //
  845. // Sanity check.
  846. //
  847. ATLASSERT(FAILED(hr));
  848. goto CommonExit;
  849. }
  850. ////////////////////////////////////////////////////////////////////////////////
  851. //
  852. // CCertificates
  853. //
  854. /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  855. Function : CCertificates::Find
  856. Synopsis : Find certificates in the collection that match the find criteria.
  857. Parameter: CAPICOM_CERTIFICATE_FIND_TYPE FindType - Find type (see CAPICOM.H
  858. for all possible values.)
  859. VARIANT varCriteria - Data type depends on FindType.
  860. VARIANT_BOOL bFindValidOnly - True to find valid certs only.
  861. ICertificates2 ** pVal - Pointer to pointer to ICertificates
  862. to receive the found certificate
  863. collection.
  864. Remark :
  865. ------------------------------------------------------------------------------*/
  866. STDMETHODIMP CCertificates::Find (CAPICOM_CERTIFICATE_FIND_TYPE FindType,
  867. VARIANT varCriteria,
  868. VARIANT_BOOL bFindValidOnly,
  869. ICertificates2 ** pVal)
  870. {
  871. USES_CONVERSION;
  872. HRESULT hr = S_OK;
  873. VARIANT * pvarCriteria = NULL;
  874. BOOL bFindByChain = FALSE;
  875. HCERTSTORE hCertStore = NULL;
  876. DWORD dwFindType = CERT_FIND_ANY;
  877. LPVOID pvFindPara = NULL;
  878. LPVOID pvCallbackData = NULL;
  879. LPSTR pszOid = NULL;
  880. SYSTEMTIME st = {0};
  881. FILETIME ftLocal = {0};
  882. FILETIME ftUTC = {0};
  883. CRYPT_HASH_BLOB HashBlob = {0, NULL};
  884. PCCRYPT_OID_INFO pOidInfo = NULL;
  885. PFNCFILTERPROC pfnCertCallback = NULL;
  886. PFNCHAINFILTERPROC pfnChainCallback = NULL;
  887. CComPtr<ICertificates2> pICertificates = NULL;
  888. CAPICOM_CERTIFICATES_SOURCE ccs = {CAPICOM_CERTIFICATES_LOAD_FROM_STORE, 0};
  889. CERT_CHAIN_FIND_BY_ISSUER_PARA ChainFindPara;
  890. DebugTrace("Entering CCertificates::Find().\n");
  891. try
  892. {
  893. //
  894. // Lock access to this object.
  895. //
  896. m_Lock.Lock();
  897. //
  898. // Make sure parameters are valid.
  899. //
  900. if (NULL == pVal)
  901. {
  902. hr = E_INVALIDARG;
  903. DebugTrace("Error [%#x]: pVal is NULL.\n", hr);
  904. goto ErrorExit;
  905. }
  906. //
  907. // Skip over BYREF.
  908. //
  909. for (pvarCriteria = &varCriteria;
  910. pvarCriteria && ((VT_VARIANT | VT_BYREF) == V_VT(pvarCriteria));
  911. pvarCriteria = V_VARIANTREF(pvarCriteria));
  912. //
  913. // Open a new memory store.
  914. //
  915. if (NULL == (hCertStore = ::CertOpenStore(CERT_STORE_PROV_MEMORY,
  916. CAPICOM_ASN_ENCODING,
  917. NULL,
  918. CERT_STORE_CREATE_NEW_FLAG | CERT_STORE_ENUM_ARCHIVED_FLAG,
  919. NULL)))
  920. {
  921. hr = HRESULT_FROM_WIN32(::GetLastError());
  922. DebugTrace("Error [%#x]: CertOpenStore() failed.\n", hr);
  923. goto ErrorExit;
  924. }
  925. //
  926. // Create a new collection.
  927. //
  928. ccs.hCertStore = hCertStore;
  929. if (FAILED(hr = ::CreateCertificatesObject(ccs, m_dwCurrentSafety, TRUE, &pICertificates)))
  930. {
  931. DebugTrace("Error [%#x]: CreateCertificatesObject() failed.\n", hr);
  932. goto ErrorExit;
  933. }
  934. //
  935. // Export current collection to the new memory store so that we can
  936. // use it with CAPI's find APIs.
  937. //
  938. if (FAILED(hr = _ExportToStore(hCertStore)))
  939. {
  940. DebugTrace("Error [%#x]: CCertificates::ExportToStore() failed.\n", hr);
  941. goto ErrorExit;
  942. }
  943. //
  944. // Setup find parameters.
  945. //
  946. switch (FindType)
  947. {
  948. //
  949. // Find by SHA1 hash.
  950. //
  951. case CAPICOM_CERTIFICATE_FIND_SHA1_HASH:
  952. {
  953. //
  954. // Make sure data type is OK.
  955. //
  956. if (VT_BSTR != pvarCriteria->vt)
  957. {
  958. if (FAILED(hr = ::VariantChangeType(pvarCriteria, pvarCriteria, 0, VT_BSTR)))
  959. {
  960. DebugTrace("Error [%#x]: invalid data type %d, expect %d.\n", hr, pvarCriteria->vt, VT_BSTR);
  961. goto ErrorExit;
  962. }
  963. }
  964. //
  965. // Convert hash to binary.
  966. //
  967. if (FAILED(hr = ::StringToBinary(pvarCriteria->bstrVal,
  968. ::SysStringLen(pvarCriteria->bstrVal),
  969. CRYPT_STRING_HEX,
  970. (PBYTE *) &HashBlob.pbData,
  971. &HashBlob.cbData)))
  972. {
  973. DebugTrace("Error [%#x]: StringToBinary() failed.\n", hr);
  974. goto ErrorExit;
  975. }
  976. dwFindType = CERT_FIND_HASH;
  977. pvFindPara = (LPVOID) &HashBlob;
  978. break;
  979. }
  980. //
  981. // Find by subject name substring-in-string.
  982. //
  983. case CAPICOM_CERTIFICATE_FIND_SUBJECT_NAME:
  984. {
  985. //
  986. // Make sure data type is OK.
  987. //
  988. if (VT_BSTR != pvarCriteria->vt)
  989. {
  990. if (FAILED(hr = ::VariantChangeType(pvarCriteria, pvarCriteria, 0, VT_BSTR)))
  991. {
  992. DebugTrace("Error [%#x]: invalid data type %d, expect %d.\n", hr, pvarCriteria->vt, VT_BSTR);
  993. goto ErrorExit;
  994. }
  995. }
  996. dwFindType = CERT_FIND_SUBJECT_STR;
  997. pvFindPara = (LPVOID) pvarCriteria->bstrVal;
  998. break;
  999. }
  1000. //
  1001. // Find by issuer name substring-in-string.
  1002. //
  1003. case CAPICOM_CERTIFICATE_FIND_ISSUER_NAME:
  1004. {
  1005. //
  1006. // Make sure data type is OK.
  1007. //
  1008. if (VT_BSTR != pvarCriteria->vt)
  1009. {
  1010. if (FAILED(hr = ::VariantChangeType(pvarCriteria, pvarCriteria, 0, VT_BSTR)))
  1011. {
  1012. DebugTrace("Error [%#x]: invalid data type %d, expect %d.\n", hr, pvarCriteria->vt, VT_BSTR);
  1013. goto ErrorExit;
  1014. }
  1015. }
  1016. dwFindType = CERT_FIND_ISSUER_STR;
  1017. pvFindPara = (LPVOID) pvarCriteria->bstrVal;
  1018. break;
  1019. }
  1020. //
  1021. // Find by issuer name of root cert subtring-in-string.
  1022. //
  1023. case CAPICOM_CERTIFICATE_FIND_ROOT_NAME:
  1024. {
  1025. //
  1026. // Make sure data type is OK.
  1027. //
  1028. if (VT_BSTR != pvarCriteria->vt)
  1029. {
  1030. if (FAILED(hr = ::VariantChangeType(pvarCriteria, pvarCriteria, 0, VT_BSTR)))
  1031. {
  1032. DebugTrace("Error [%#x]: invalid data type %d, expect %d.\n", hr, pvarCriteria->vt, VT_BSTR);
  1033. goto ErrorExit;
  1034. }
  1035. }
  1036. ::ZeroMemory(&ChainFindPara, sizeof(ChainFindPara));
  1037. ChainFindPara.cbSize = sizeof(ChainFindPara);
  1038. dwFindType = CERT_CHAIN_FIND_BY_ISSUER;
  1039. pvFindPara = (LPVOID) &ChainFindPara;
  1040. pfnChainCallback = FindRootNameCallback;
  1041. pvCallbackData = (LPVOID) pvarCriteria->bstrVal;
  1042. bFindByChain = TRUE;
  1043. break;
  1044. }
  1045. //
  1046. // Find by template name or OID.
  1047. //
  1048. case CAPICOM_CERTIFICATE_FIND_TEMPLATE_NAME:
  1049. {
  1050. //
  1051. // Make sure data type is OK.
  1052. //
  1053. if (VT_BSTR != pvarCriteria->vt)
  1054. {
  1055. if (FAILED(hr = ::VariantChangeType(pvarCriteria, pvarCriteria, 0, VT_BSTR)))
  1056. {
  1057. DebugTrace("Error [%#x]: invalid data type %d, expect %d.\n", hr, pvarCriteria->vt, VT_BSTR);
  1058. goto ErrorExit;
  1059. }
  1060. }
  1061. pfnCertCallback = FindTemplateCallback;
  1062. pvCallbackData = (LPVOID) pvarCriteria->bstrVal;
  1063. break;
  1064. }
  1065. //
  1066. // Find by extension.
  1067. //
  1068. case CAPICOM_CERTIFICATE_FIND_EXTENSION:
  1069. {
  1070. //
  1071. // Make sure data type is OK.
  1072. //
  1073. if (VT_BSTR != pvarCriteria->vt)
  1074. {
  1075. if (FAILED(hr = ::VariantChangeType(pvarCriteria, pvarCriteria, 0, VT_BSTR)))
  1076. {
  1077. DebugTrace("Error [%#x]: invalid data type %d, expect %d.\n", hr, pvarCriteria->vt, VT_BSTR);
  1078. goto ErrorExit;
  1079. }
  1080. }
  1081. //
  1082. // Convert to OID if user passed in friendly name.
  1083. //
  1084. if (pOidInfo = ::CryptFindOIDInfo(CRYPT_OID_INFO_NAME_KEY,
  1085. (LPWSTR) pvarCriteria->bstrVal,
  1086. CRYPT_EXT_OR_ATTR_OID_GROUP_ID))
  1087. {
  1088. pszOid = (LPSTR) pOidInfo->pszOID;
  1089. }
  1090. else
  1091. {
  1092. //
  1093. // Convert to ASCII.
  1094. //
  1095. if (!(pszOid = W2A(pvarCriteria->bstrVal)))
  1096. {
  1097. hr = E_OUTOFMEMORY;
  1098. DebugTrace("Error [%%#x]: pszOid = W2A(pvarCriteria->bstrVal) failed.\n", hr);
  1099. goto ErrorExit;
  1100. }
  1101. }
  1102. pfnCertCallback = FindExtensionCallback;
  1103. pvCallbackData = (LPVOID) pszOid;
  1104. break;
  1105. }
  1106. //
  1107. // Find by property ID.
  1108. //
  1109. case CAPICOM_CERTIFICATE_FIND_EXTENDED_PROPERTY:
  1110. {
  1111. //
  1112. // Make sure data type is OK.
  1113. //
  1114. if (VT_I4 != pvarCriteria->vt)
  1115. {
  1116. if (FAILED(hr = ::VariantChangeType(pvarCriteria, pvarCriteria, 0, VT_I4)))
  1117. {
  1118. DebugTrace("Error [%#x]: invalid data type %d, expect %d.\n", hr, pvarCriteria->vt, VT_I4);
  1119. goto ErrorExit;
  1120. }
  1121. }
  1122. dwFindType = CERT_FIND_PROPERTY;
  1123. pvFindPara = (LPVOID) &pvarCriteria->lVal;
  1124. break;
  1125. }
  1126. //
  1127. // Find by application policy (EKU).
  1128. //
  1129. case CAPICOM_CERTIFICATE_FIND_APPLICATION_POLICY:
  1130. {
  1131. //
  1132. // Make sure data type is OK.
  1133. //
  1134. if (VT_BSTR != pvarCriteria->vt)
  1135. {
  1136. if (FAILED(hr = ::VariantChangeType(pvarCriteria, pvarCriteria, 0, VT_BSTR)))
  1137. {
  1138. DebugTrace("Error [%#x]: invalid data type %d, expect %d.\n", hr, pvarCriteria->vt, VT_BSTR);
  1139. goto ErrorExit;
  1140. }
  1141. }
  1142. //
  1143. // Try to convert to OID if user passed in friendly name.
  1144. //
  1145. if (pOidInfo = ::CryptFindOIDInfo(CRYPT_OID_INFO_NAME_KEY,
  1146. (LPWSTR) pvarCriteria->bstrVal,
  1147. CRYPT_ENHKEY_USAGE_OID_GROUP_ID))
  1148. {
  1149. pszOid = (LPSTR) pOidInfo->pszOID;
  1150. }
  1151. else
  1152. {
  1153. //
  1154. // Convert to ASCII.
  1155. //
  1156. if (!(pszOid = W2A(pvarCriteria->bstrVal)))
  1157. {
  1158. hr = E_OUTOFMEMORY;
  1159. DebugTrace("Error [%#X]: pszOid = W2A(pvarCriteria->bstrVal) failed.\n", hr);
  1160. goto ErrorExit;
  1161. }
  1162. }
  1163. pfnCertCallback = FindApplicationPolicyCallback;
  1164. pvCallbackData = (LPVOID) pszOid;
  1165. break;
  1166. }
  1167. //
  1168. // Find by certificate policy.
  1169. //
  1170. case CAPICOM_CERTIFICATE_FIND_CERTIFICATE_POLICY:
  1171. {
  1172. //
  1173. // Make sure data type is OK.
  1174. //
  1175. if (VT_BSTR != pvarCriteria->vt)
  1176. {
  1177. if (FAILED(hr = ::VariantChangeType(pvarCriteria, pvarCriteria, 0, VT_BSTR)))
  1178. {
  1179. DebugTrace("Error [%#x]: invalid data type %d, expect %d.\n", hr, pvarCriteria->vt, VT_BSTR);
  1180. goto ErrorExit;
  1181. }
  1182. }
  1183. //
  1184. // Convert to OID if user passed in friendly name.
  1185. //
  1186. if (pOidInfo = ::CryptFindOIDInfo(CRYPT_OID_INFO_NAME_KEY,
  1187. (LPWSTR) pvarCriteria->bstrVal,
  1188. CRYPT_POLICY_OID_GROUP_ID))
  1189. {
  1190. pszOid = (LPSTR) pOidInfo->pszOID;
  1191. }
  1192. else
  1193. {
  1194. //
  1195. // Convert to ASCII.
  1196. //
  1197. if (!(pszOid = W2A(pvarCriteria->bstrVal)))
  1198. {
  1199. hr = E_OUTOFMEMORY;
  1200. DebugTrace("Error [%#x]: pszOid = W2A(pvarCriteria->bstrVal) failed.\n", hr);
  1201. goto ErrorExit;
  1202. }
  1203. }
  1204. pfnCertCallback = FindCertificatePolicyCallback;
  1205. pvCallbackData = (LPVOID) pszOid;
  1206. break;
  1207. }
  1208. //
  1209. // Find by time valid.
  1210. //
  1211. case CAPICOM_CERTIFICATE_FIND_TIME_VALID:
  1212. {
  1213. //
  1214. // !!! Warning, falling thru. !!!
  1215. //
  1216. }
  1217. //
  1218. // Find by notBefore time validity.
  1219. //
  1220. case CAPICOM_CERTIFICATE_FIND_TIME_NOT_YET_VALID:
  1221. {
  1222. //
  1223. // !!! Warning, falling thru. !!!
  1224. //
  1225. }
  1226. // Find by notAfter time validity.
  1227. //
  1228. case CAPICOM_CERTIFICATE_FIND_TIME_EXPIRED:
  1229. {
  1230. //
  1231. // Make sure data type is OK.
  1232. //
  1233. if (VT_DATE != pvarCriteria->vt)
  1234. {
  1235. if (FAILED(hr = ::VariantChangeType(pvarCriteria, pvarCriteria, 0, VT_DATE)))
  1236. {
  1237. DebugTrace("Error [%#x]: invalid data type %d, expect %d.\n", hr, pvarCriteria->vt, VT_DATE);
  1238. goto ErrorExit;
  1239. }
  1240. }
  1241. //
  1242. // Convert to SYSTEMTIME format.
  1243. //
  1244. if (0 == pvarCriteria->date)
  1245. {
  1246. ::GetLocalTime(&st);
  1247. }
  1248. else if (!::VariantTimeToSystemTime(pvarCriteria->date, &st))
  1249. {
  1250. hr = E_INVALIDARG;
  1251. DebugTrace("Error [%#x]: VariantTimeToSystemTime() failed.\n", hr);
  1252. goto ErrorExit;
  1253. }
  1254. //
  1255. // Convert to FILETIME format.
  1256. //
  1257. if (!::SystemTimeToFileTime(&st, &ftLocal))
  1258. {
  1259. hr = HRESULT_FROM_WIN32(::GetLastError());
  1260. DebugTrace("Error [%#x]: SystemTimeToFileTime() failed.\n", hr);
  1261. goto ErrorExit;
  1262. }
  1263. //
  1264. // Convert to UTC FILETIME.
  1265. //
  1266. if (!::LocalFileTimeToFileTime(&ftLocal, &ftUTC))
  1267. {
  1268. hr = HRESULT_FROM_WIN32(::GetLastError());
  1269. DebugTrace("Error [%#x]: LocalFileTimeToFileTime() failed.\n", hr);
  1270. goto ErrorExit;
  1271. }
  1272. if (CAPICOM_CERTIFICATE_FIND_TIME_VALID == FindType)
  1273. {
  1274. pfnCertCallback = FindTimeValidCallback;
  1275. }
  1276. else if (CAPICOM_CERTIFICATE_FIND_TIME_NOT_YET_VALID == FindType)
  1277. {
  1278. pfnCertCallback = FindNotBeforeCallback;
  1279. }
  1280. else
  1281. {
  1282. pfnCertCallback = FindNotAfterCallback;
  1283. }
  1284. pvCallbackData = (LPVOID) &ftUTC;
  1285. break;
  1286. }
  1287. //
  1288. // Find by key usage.
  1289. //
  1290. case CAPICOM_CERTIFICATE_FIND_KEY_USAGE:
  1291. {
  1292. //
  1293. // By Key Usage bit flag?
  1294. //
  1295. if (VT_I4 != pvarCriteria->vt)
  1296. {
  1297. //
  1298. // By key usage friendly's name?
  1299. //
  1300. if (VT_BSTR == pvarCriteria->vt)
  1301. {
  1302. typedef struct _KeyUsagesStruct
  1303. {
  1304. LPWSTR pwszKeyUsage;
  1305. DWORD dwKeyUsageBit;
  1306. } KEY_USAGE_STRUCT;
  1307. KEY_USAGE_STRUCT KeyUsages[] =
  1308. { {L"DigitalSignature", CERT_DIGITAL_SIGNATURE_KEY_USAGE},
  1309. {L"NonRepudiation", CERT_NON_REPUDIATION_KEY_USAGE},
  1310. {L"KeyEncipherment", CERT_KEY_ENCIPHERMENT_KEY_USAGE},
  1311. {L"DataEncipherment", CERT_DATA_ENCIPHERMENT_KEY_USAGE},
  1312. {L"KeyAgreement", CERT_KEY_AGREEMENT_KEY_USAGE},
  1313. {L"KeyCertSign", CERT_KEY_CERT_SIGN_KEY_USAGE},
  1314. {L"CRLSign", CERT_CRL_SIGN_KEY_USAGE},
  1315. {L"EncipherOnly", CERT_ENCIPHER_ONLY_KEY_USAGE},
  1316. {L"DecipherOnly", CERT_DECIPHER_ONLY_KEY_USAGE}
  1317. };
  1318. //
  1319. // Find the name.
  1320. //
  1321. for (DWORD i = 0; i < ARRAYSIZE(KeyUsages); i++)
  1322. {
  1323. if (0 == _wcsicmp(KeyUsages[i].pwszKeyUsage, (LPWSTR) pvarCriteria->bstrVal))
  1324. {
  1325. break;
  1326. }
  1327. }
  1328. if (i == ARRAYSIZE(KeyUsages))
  1329. {
  1330. hr = E_INVALIDARG;
  1331. DebugTrace("Error [%#x]: Unknown key usage (%ls).\n", hr, (LPWSTR) pvarCriteria->bstrVal);
  1332. goto ErrorExit;
  1333. }
  1334. //
  1335. // Convert to bit flag.
  1336. //
  1337. ::VariantClear(pvarCriteria);
  1338. pvarCriteria->vt = VT_I4;
  1339. pvarCriteria->lVal = KeyUsages[i].dwKeyUsageBit;
  1340. }
  1341. else
  1342. {
  1343. if (FAILED(hr = ::VariantChangeType(pvarCriteria, pvarCriteria, 0, VT_I4)))
  1344. {
  1345. DebugTrace("Error [%#x]: invalid data type %d, expect %d.\n", hr, pvarCriteria->vt, VT_I4);
  1346. goto ErrorExit;
  1347. }
  1348. }
  1349. }
  1350. pfnCertCallback = FindKeyUsageCallback;
  1351. pvCallbackData = (LPVOID) &pvarCriteria->lVal;
  1352. break;
  1353. }
  1354. default:
  1355. {
  1356. hr = CAPICOM_E_FIND_INVALID_TYPE;
  1357. DebugTrace("Error [%#x]: invalid CAPICOM_CERTIFICATE_FIND_TYPE (%d).\n", hr, FindType);
  1358. goto ErrorExit;
  1359. }
  1360. }
  1361. //
  1362. // Now find the certs.
  1363. //
  1364. if (bFindByChain)
  1365. {
  1366. if (FAILED(hr = ::FindByChain(hCertStore,
  1367. dwFindType,
  1368. pvFindPara,
  1369. bFindValidOnly,
  1370. pfnChainCallback,
  1371. pvCallbackData,
  1372. m_dwCurrentSafety,
  1373. pICertificates)))
  1374. {
  1375. DebugTrace("Error [%#x]: FindByChain() failed.\n", hr);
  1376. goto ErrorExit;
  1377. }
  1378. }
  1379. else
  1380. {
  1381. if (FAILED(hr = ::FindByCert(hCertStore,
  1382. dwFindType,
  1383. pvFindPara,
  1384. bFindValidOnly,
  1385. pfnCertCallback,
  1386. pvCallbackData,
  1387. m_dwCurrentSafety,
  1388. pICertificates)))
  1389. {
  1390. DebugTrace("Error [%#x]: FindByCert() failed.\n", hr);
  1391. goto ErrorExit;
  1392. }
  1393. }
  1394. //
  1395. // Return collection to caller.
  1396. //
  1397. if (FAILED(hr = pICertificates->QueryInterface(pVal)))
  1398. {
  1399. DebugTrace("Unexpected error [%#x]: pICertificates->QueryInterface() failed.\n", hr);
  1400. goto ErrorExit;
  1401. }
  1402. }
  1403. catch(...)
  1404. {
  1405. hr = E_INVALIDARG;
  1406. DebugTrace("Exception: invalid parameter.\n");
  1407. goto ErrorExit;
  1408. }
  1409. UnlockExit:
  1410. //
  1411. // Free reources.
  1412. //
  1413. if (HashBlob.pbData)
  1414. {
  1415. ::CoTaskMemFree((LPVOID) HashBlob.pbData);
  1416. }
  1417. if (hCertStore)
  1418. {
  1419. ::CertCloseStore(hCertStore, 0);
  1420. }
  1421. //
  1422. // Unlock access to this object.
  1423. //
  1424. m_Lock.Unlock();
  1425. DebugTrace("Leaving CCertificates::Find().\n");
  1426. return hr;
  1427. ErrorExit:
  1428. //
  1429. // Sanity check.
  1430. //
  1431. ATLASSERT(FAILED(hr));
  1432. ReportError(hr);
  1433. goto UnlockExit;
  1434. }
  1435. /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1436. Function : CCertificates::Select
  1437. Synopsis : Display the certificate selection dialog box.
  1438. Parameter: BSTR Title - Dialog box title.
  1439. BSTR DisplayString - Display string.
  1440. VARIANT_BOOL bMultiSelect - True for multi-select.
  1441. ICertificates2 ** pVal - Pointer to pointer to ICertificates
  1442. to receive the select certificate
  1443. collection.
  1444. Remark :
  1445. ------------------------------------------------------------------------------*/
  1446. STDMETHODIMP CCertificates::Select (BSTR Title,
  1447. BSTR DisplayString,
  1448. VARIANT_BOOL bMultiSelect,
  1449. ICertificates2 ** pVal)
  1450. {
  1451. HRESULT hr = S_OK;
  1452. HCERTSTORE hSrcStore = NULL;
  1453. HCERTSTORE hDstStore = NULL;
  1454. PCCERT_CONTEXT pCertContext = NULL;
  1455. CComPtr<ICertificates2> pICertificates = NULL;
  1456. CAPICOM_CERTIFICATES_SOURCE ccs = {0, NULL};
  1457. DebugTrace("Entering CCertificates::Select().\n");
  1458. try
  1459. {
  1460. //
  1461. // Lock access to this object.
  1462. //
  1463. m_Lock.Lock();
  1464. //
  1465. // Make sure parameters are valid.
  1466. //
  1467. if (NULL == pVal)
  1468. {
  1469. hr = E_INVALIDARG;
  1470. DebugTrace("Error [%#x]: pVal is NULL.\n", hr);
  1471. goto ErrorExit;
  1472. }
  1473. //
  1474. // Make sure we are allowed to pop UI.
  1475. //
  1476. if (!PromptForCertificateEnabled())
  1477. {
  1478. hr = CAPICOM_E_UI_DISABLED;
  1479. DebugTrace("Error [%#x]: UI is disabled.\n", hr);
  1480. goto ErrorExit;
  1481. }
  1482. //
  1483. // Work aroung MIDL default BSTR problem.
  1484. //
  1485. if (0 == ::SysStringLen(Title))
  1486. {
  1487. Title = NULL;
  1488. }
  1489. if (0 == ::SysStringLen(DisplayString))
  1490. {
  1491. DisplayString = NULL;
  1492. }
  1493. //
  1494. // Open a new memory source store.
  1495. //
  1496. if (NULL == (hSrcStore = ::CertOpenStore(CERT_STORE_PROV_MEMORY,
  1497. CAPICOM_ASN_ENCODING,
  1498. NULL,
  1499. CERT_STORE_CREATE_NEW_FLAG,
  1500. NULL)))
  1501. {
  1502. hr = HRESULT_FROM_WIN32(::GetLastError());
  1503. DebugTrace("Error [%#x]: CertOpenStore() failed.\n", hr);
  1504. goto ErrorExit;
  1505. }
  1506. //
  1507. // Export collections to the new memory source store.
  1508. //
  1509. if (FAILED(hr = _ExportToStore(hSrcStore)))
  1510. {
  1511. DebugTrace("Error [%#x]: CCertificates::_ExportToStore() failed.\n", hr);
  1512. goto ErrorExit;
  1513. }
  1514. //
  1515. // Open a new memory destination store for multi-select.
  1516. //
  1517. if (bMultiSelect)
  1518. {
  1519. if (!(hDstStore = ::CertOpenStore(CERT_STORE_PROV_MEMORY,
  1520. CAPICOM_ASN_ENCODING,
  1521. NULL,
  1522. CERT_STORE_CREATE_NEW_FLAG,
  1523. NULL)))
  1524. {
  1525. hr = HRESULT_FROM_WIN32(::GetLastError());
  1526. DebugTrace("Error [%#x]: CertOpenStore() failed.\n", hr);
  1527. goto ErrorExit;
  1528. }
  1529. }
  1530. //
  1531. // Display the cert selection dialog box.
  1532. //
  1533. if (FAILED(hr = ::SelectCertificateContext(hSrcStore,
  1534. Title,
  1535. DisplayString,
  1536. (BOOL) bMultiSelect,
  1537. NULL,
  1538. hDstStore,
  1539. &pCertContext)))
  1540. {
  1541. DebugTrace("Error [%#x]: SelectCertificateContext() failed.\n", hr);
  1542. goto ErrorExit;
  1543. }
  1544. //
  1545. // Create the collection object.
  1546. //
  1547. if (bMultiSelect)
  1548. {
  1549. //
  1550. // Create a new collection from the destination store.
  1551. //
  1552. ccs.dwSource = CAPICOM_CERTIFICATES_LOAD_FROM_STORE;
  1553. ccs.hCertStore = hDstStore;
  1554. }
  1555. else
  1556. {
  1557. //
  1558. // Create a new collection from the cert context.
  1559. //
  1560. ccs.dwSource = CAPICOM_CERTIFICATES_LOAD_FROM_CERT;
  1561. ccs.pCertContext = pCertContext;
  1562. }
  1563. if (FAILED(hr = ::CreateCertificatesObject(ccs, m_dwCurrentSafety, TRUE, &pICertificates)))
  1564. {
  1565. DebugTrace("Error [%#x]: CreateCertificatesObject() failed.\n", hr);
  1566. goto ErrorExit;
  1567. }
  1568. //
  1569. // Return collection to caller.
  1570. //
  1571. if (FAILED(hr = pICertificates->QueryInterface(pVal)))
  1572. {
  1573. DebugTrace("Unexpected error [%#x]: pICertificates->QueryInterface() failed.\n", hr);
  1574. goto ErrorExit;
  1575. }
  1576. }
  1577. catch(...)
  1578. {
  1579. hr = E_INVALIDARG;
  1580. DebugTrace("Exception: invalid parameter.\n");
  1581. goto ErrorExit;
  1582. }
  1583. UnlockExit:
  1584. //
  1585. // Free reources.
  1586. //
  1587. if (pCertContext)
  1588. {
  1589. ::CertFreeCertificateContext(pCertContext);
  1590. }
  1591. if (hDstStore)
  1592. {
  1593. ::CertCloseStore(hDstStore, 0);
  1594. }
  1595. if (hSrcStore)
  1596. {
  1597. ::CertCloseStore(hSrcStore, 0);
  1598. }
  1599. //
  1600. // Unlock access to this object.
  1601. //
  1602. m_Lock.Unlock();
  1603. DebugTrace("Leaving CCertificates::Select().\n");
  1604. return hr;
  1605. ErrorExit:
  1606. //
  1607. // Sanity check.
  1608. //
  1609. ATLASSERT(FAILED(hr));
  1610. ReportError(hr);
  1611. goto UnlockExit;
  1612. }
  1613. /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1614. Function : CCertificates::Add
  1615. Synopsis : Add a Certificate2 to the collection.
  1616. Parameter: ICertificate2 * pVal - Certificate2 to be added.
  1617. Remark :
  1618. ------------------------------------------------------------------------------*/
  1619. STDMETHODIMP CCertificates::Add (ICertificate2 * pVal)
  1620. {
  1621. HRESULT hr = S_OK;
  1622. char szIndex[33];
  1623. CComBSTR bstrIndex;
  1624. DebugTrace("Entering CCertificates::Add().\n");
  1625. try
  1626. {
  1627. //
  1628. // Lock access to this object.
  1629. //
  1630. m_Lock.Lock();
  1631. //
  1632. // Make sure parameters are valid.
  1633. //
  1634. if (NULL == pVal)
  1635. {
  1636. hr = E_INVALIDARG;
  1637. DebugTrace("Error [%#x]: pVal is NULL.\n", hr);
  1638. goto ErrorExit;
  1639. }
  1640. #if (0)
  1641. CComPtr<ICertificate2> pICertificate = NULL;
  1642. //
  1643. // Make sure we have a valid Certificate.
  1644. //
  1645. if (FAILED(hr = pVal->QueryInterface(__uuidof(ICertificate2), (void **) &pICertificate.p)))
  1646. {
  1647. hr = E_NOINTERFACE;
  1648. DebugTrace("Error [%#x]: pVal is not an Certificate object.\n", hr);
  1649. goto ErrorExit;
  1650. }
  1651. #endif
  1652. DebugTrace("Info: m_dwNextIndex = %#x, m_coll.max_size() = %#x.\n",
  1653. m_dwNextIndex, m_coll.max_size());
  1654. //
  1655. // If index by number, and the index exceeds our max, then we will
  1656. // force it to be indexed by thumbprint.
  1657. //
  1658. if ((m_bIndexedByThumbprint) || ((m_dwNextIndex + 1) > m_coll.max_size()))
  1659. {
  1660. if (FAILED(hr = pVal->get_Thumbprint(&bstrIndex)))
  1661. {
  1662. DebugTrace("Error [%#x]: pVal->get_Thumbprint() failed.\n", hr);
  1663. goto ErrorExit;
  1664. }
  1665. m_bIndexedByThumbprint = TRUE;
  1666. }
  1667. else
  1668. {
  1669. //
  1670. // BSTR index of numeric value.
  1671. //
  1672. wsprintfA(szIndex, "%#08x", ++m_dwNextIndex);
  1673. if (!(bstrIndex = szIndex))
  1674. {
  1675. hr = E_OUTOFMEMORY;
  1676. DebugTrace("Error [%#x]: bstrIndex = szIndex failed.\n", hr);
  1677. goto ErrorExit;
  1678. }
  1679. }
  1680. //
  1681. // Now add object to collection map.
  1682. //
  1683. // Note that the overloaded = operator for CComPtr will
  1684. // automatically AddRef to the object. Also, when the CComPtr
  1685. // is deleted (happens when the Remove or map destructor is called),
  1686. // the CComPtr destructor will automatically Release the object.
  1687. //
  1688. m_coll[bstrIndex] = pVal;
  1689. }
  1690. catch(...)
  1691. {
  1692. hr = E_POINTER;
  1693. DebugTrace("Exception: invalid parameter.\n");
  1694. goto ErrorExit;
  1695. }
  1696. UnlockExit:
  1697. //
  1698. // Unlock access to this object.
  1699. //
  1700. m_Lock.Unlock();
  1701. DebugTrace("Leaving CCertificates::Add().\n");
  1702. return hr;
  1703. ErrorExit:
  1704. //
  1705. // Sanity check.
  1706. //
  1707. ATLASSERT(FAILED(hr));
  1708. ReportError(hr);
  1709. goto UnlockExit;
  1710. }
  1711. /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1712. Function : CCertificates::Remove
  1713. Synopsis : Remove a Certificate2 from the collection.
  1714. Parameter: VARIANT Index - Can be numeric index (1-based), SHA1 string, or
  1715. Certificate object.
  1716. Remark :
  1717. ------------------------------------------------------------------------------*/
  1718. STDMETHODIMP CCertificates::Remove (VARIANT Index)
  1719. {
  1720. HRESULT hr = S_OK;
  1721. VARIANT * pvarIndex = NULL;
  1722. CComBSTR bstrIndex;
  1723. CertificateMap::iterator iter;
  1724. CComPtr<ICertificate2> pICertificate;
  1725. DebugTrace("Entering CCertificates::Remove().\n");
  1726. try
  1727. {
  1728. //
  1729. // Lock access to this object.
  1730. //
  1731. m_Lock.Lock();
  1732. //
  1733. // Skip over BYREF.
  1734. //
  1735. for (pvarIndex = &Index;
  1736. pvarIndex && ((VT_VARIANT | VT_BYREF) == V_VT(pvarIndex));
  1737. pvarIndex = V_VARIANTREF(pvarIndex));
  1738. //
  1739. // Which form of index?
  1740. //
  1741. switch (pvarIndex->vt)
  1742. {
  1743. case VT_DISPATCH:
  1744. {
  1745. //
  1746. // Get the thumbprint;
  1747. //
  1748. if (FAILED(hr = pvarIndex->pdispVal->QueryInterface(IID_ICertificate2, (void **) &pICertificate)))
  1749. {
  1750. DebugTrace("Error [%#x]: pvarIndex->pdispVal->QueryInterface() failed.\n", hr);
  1751. goto ErrorExit;
  1752. }
  1753. if (FAILED(hr = pICertificate->get_Thumbprint(&bstrIndex)))
  1754. {
  1755. DebugTrace("Error [%#x]: pICertificate->get_Thumbprint() failed.\n", hr);
  1756. goto ErrorExit;
  1757. }
  1758. //
  1759. // !!! WARNING. Falling thru !!!
  1760. //
  1761. }
  1762. case VT_BSTR:
  1763. {
  1764. //
  1765. // Because we could have felt thru, so need to check again.
  1766. //
  1767. if (VT_BSTR == pvarIndex->vt)
  1768. {
  1769. bstrIndex = pvarIndex->bstrVal;
  1770. }
  1771. //
  1772. // Find the cert matching this thumbprint.
  1773. //
  1774. for (iter = m_coll.begin(); iter != m_coll.end(); iter++)
  1775. {
  1776. CComBSTR bstrThumbprint;
  1777. //
  1778. // Point to the object.
  1779. //
  1780. pICertificate = (*iter).second;
  1781. //
  1782. // Get the thumbprint;
  1783. //
  1784. if (FAILED(hr = pICertificate->get_Thumbprint(&bstrThumbprint)))
  1785. {
  1786. DebugTrace("Error [%#x]: pICertificate->get_Thumbprint() failed.\n", hr);
  1787. goto ErrorExit;
  1788. }
  1789. //
  1790. // Same thumbprint?
  1791. //
  1792. if (0 == ::_wcsicmp(bstrThumbprint, bstrIndex))
  1793. {
  1794. break;
  1795. }
  1796. }
  1797. //
  1798. // Did we find in the map?
  1799. //
  1800. if (iter == m_coll.end())
  1801. {
  1802. hr = E_INVALIDARG;
  1803. DebugTrace("Error [%#x]: Requested certificate (sha1 = %ls) is not found in the collection.\n",
  1804. hr, bstrIndex);
  1805. goto ErrorExit;
  1806. }
  1807. //
  1808. // Now remove from map.
  1809. //
  1810. m_coll.erase(iter);
  1811. break;
  1812. }
  1813. default:
  1814. {
  1815. DWORD dwIndex;
  1816. //
  1817. // Assume numeric index.
  1818. //
  1819. if (VT_I4 != pvarIndex->vt &&
  1820. FAILED(hr = ::VariantChangeType(pvarIndex, pvarIndex, 0, VT_I4)))
  1821. {
  1822. DebugTrace("Error [%#x]: VariantChangeType() failed.\n", hr);
  1823. goto ErrorExit;
  1824. }
  1825. //
  1826. // Make sure index is valid.
  1827. //
  1828. dwIndex = (DWORD) pvarIndex->lVal;
  1829. if (dwIndex < 1 || dwIndex > m_coll.size())
  1830. {
  1831. hr = E_INVALIDARG;
  1832. DebugTrace("Error [%#x]: Index %d is out of range.\n", hr, dwIndex);
  1833. goto ErrorExit;
  1834. }
  1835. //
  1836. // Find object in map.
  1837. //
  1838. dwIndex--;
  1839. iter = m_coll.begin();
  1840. while (iter != m_coll.end() && dwIndex > 0)
  1841. {
  1842. iter++;
  1843. dwIndex--;
  1844. }
  1845. //
  1846. // Did we find in the map?
  1847. //
  1848. if (iter == m_coll.end())
  1849. {
  1850. hr = E_INVALIDARG;
  1851. DebugTrace("Error [%#x]: Requested certificate (Index = %d) is not found in the collection.\n",
  1852. hr, dwIndex);
  1853. goto ErrorExit;
  1854. }
  1855. //
  1856. // Now remove from map.
  1857. //
  1858. m_coll.erase(iter);
  1859. break;
  1860. }
  1861. }
  1862. }
  1863. catch(...)
  1864. {
  1865. hr = E_POINTER;
  1866. DebugTrace("Exception: invalid parameter.\n");
  1867. goto ErrorExit;
  1868. }
  1869. UnlockExit:
  1870. //
  1871. // Unlock access to this object.
  1872. //
  1873. m_Lock.Unlock();
  1874. DebugTrace("Leaving CCertificates::Remove().\n");
  1875. return hr;
  1876. ErrorExit:
  1877. //
  1878. // Sanity check.
  1879. //
  1880. ATLASSERT(FAILED(hr));
  1881. ReportError(hr);
  1882. goto UnlockExit;
  1883. }
  1884. /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1885. Function : CCertificates::Clear
  1886. Synopsis : Remove all Certificate2 from the collection.
  1887. Parameter: None.
  1888. Remark :
  1889. ------------------------------------------------------------------------------*/
  1890. STDMETHODIMP CCertificates::Clear (void)
  1891. {
  1892. HRESULT hr = S_OK;
  1893. DebugTrace("Entering CCertificates::Clear().\n");
  1894. try
  1895. {
  1896. //
  1897. // Lock access to this object.
  1898. //
  1899. m_Lock.Lock();
  1900. //
  1901. // Clear it.
  1902. //
  1903. m_coll.clear();
  1904. //
  1905. // Sanity check.
  1906. //
  1907. ATLASSERT(0 == m_coll.size());
  1908. }
  1909. catch(...)
  1910. {
  1911. hr = E_POINTER;
  1912. DebugTrace("Exception: invalid parameter.\n");
  1913. goto ErrorExit;
  1914. }
  1915. UnlockExit:
  1916. //
  1917. // Unlock access to this object.
  1918. //
  1919. m_Lock.Unlock();
  1920. DebugTrace("Leaving CCertificates::Clear().\n");
  1921. return hr;
  1922. ErrorExit:
  1923. //
  1924. // Sanity check.
  1925. //
  1926. ATLASSERT(FAILED(hr));
  1927. ReportError(hr);
  1928. goto UnlockExit;
  1929. }
  1930. /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1931. Function : CCertificates::Save
  1932. Synopsis : Method to save certificate collection to a file.
  1933. Parameter: BSTR FileName - File name.
  1934. BSTR Password - Password (required for PFX file.).
  1935. CAPICOM_CERTIFICATES_SAVE_AS_TYPE SaveAs - SaveAs type.
  1936. CAPICOM_EXPORT_FLAG ExportFlag - Export flags.
  1937. Remark :
  1938. ------------------------------------------------------------------------------*/
  1939. STDMETHODIMP CCertificates::Save (BSTR FileName,
  1940. BSTR Password,
  1941. CAPICOM_CERTIFICATES_SAVE_AS_TYPE SaveAs,
  1942. CAPICOM_EXPORT_FLAG ExportFlag)
  1943. {
  1944. HRESULT hr = S_OK;
  1945. HCERTSTORE hCertStore = NULL;
  1946. DebugTrace("Entering CCertificates::Save().\n");
  1947. try
  1948. {
  1949. //
  1950. // Lock access to this object.
  1951. //
  1952. m_Lock.Lock();
  1953. //
  1954. // Not allowed if called from WEB script.
  1955. //
  1956. if (m_dwCurrentSafety)
  1957. {
  1958. hr = CAPICOM_E_NOT_ALLOWED;
  1959. DebugTrace("Error [%#x]: Saving cert file from WEB script is not allowed.\n", hr);
  1960. goto ErrorExit;
  1961. }
  1962. //
  1963. // Check parameters.
  1964. //
  1965. if (0 == ::SysStringLen(FileName))
  1966. {
  1967. hr = E_INVALIDARG;
  1968. DebugTrace("Error [%#x]: Parameter FileName is NULL or empty.\n", hr);
  1969. goto ErrorExit;
  1970. }
  1971. //
  1972. // Work around MIDL problem.
  1973. //
  1974. if (0 == ::SysStringLen(Password))
  1975. {
  1976. Password = NULL;
  1977. }
  1978. //
  1979. // Open a new memory store.
  1980. //
  1981. if (NULL == (hCertStore = ::CertOpenStore(CERT_STORE_PROV_MEMORY,
  1982. CAPICOM_ASN_ENCODING,
  1983. NULL,
  1984. CERT_STORE_CREATE_NEW_FLAG | CERT_STORE_ENUM_ARCHIVED_FLAG,
  1985. NULL)))
  1986. {
  1987. hr = HRESULT_FROM_WIN32(::GetLastError());
  1988. DebugTrace("Error [%#x]: CertOpenStore() failed.\n", hr);
  1989. goto ErrorExit;
  1990. }
  1991. //
  1992. // Export current collection to the new memory store so that we can
  1993. // use it with CAPI's store save APIs.
  1994. //
  1995. if (FAILED(hr = _ExportToStore(hCertStore)))
  1996. {
  1997. DebugTrace("Error [%#x]: CCertificates::ExportToStore() failed.\n", hr);
  1998. goto ErrorExit;
  1999. }
  2000. //
  2001. // Check file type.
  2002. //
  2003. switch (SaveAs)
  2004. {
  2005. case CAPICOM_CERTIFICATES_SAVE_AS_PFX:
  2006. {
  2007. //
  2008. // Save as PFX file.
  2009. //
  2010. if (FAILED(hr = ::PFXSaveStore(hCertStore,
  2011. FileName,
  2012. Password,
  2013. EXPORT_PRIVATE_KEYS |
  2014. (ExportFlag & CAPICOM_EXPORT_IGNORE_PRIVATE_KEY_NOT_EXPORTABLE_ERROR ? 0 : REPORT_NOT_ABLE_TO_EXPORT_PRIVATE_KEY))))
  2015. {
  2016. DebugTrace("Error [%#x]: PFXSaveStore() failed.\n", hr);
  2017. goto ErrorExit;
  2018. }
  2019. break;
  2020. }
  2021. case CAPICOM_CERTIFICATES_SAVE_AS_SERIALIZED:
  2022. {
  2023. //
  2024. // Save as serialized store file.
  2025. //
  2026. if (!::CertSaveStore(hCertStore,
  2027. 0,
  2028. CERT_STORE_SAVE_AS_STORE,
  2029. CERT_STORE_SAVE_TO_FILENAME_W,
  2030. (void *) FileName,
  2031. 0))
  2032. {
  2033. hr = HRESULT_FROM_WIN32(::GetLastError());
  2034. DebugTrace("Error [%#x]: CertSaveStore() failed.\n", hr);
  2035. goto ErrorExit;
  2036. }
  2037. break;
  2038. }
  2039. case CAPICOM_CERTIFICATES_SAVE_AS_PKCS7:
  2040. {
  2041. //
  2042. // Save as PKCS 7 file.
  2043. //
  2044. if (!::CertSaveStore(hCertStore,
  2045. CAPICOM_ASN_ENCODING,
  2046. CERT_STORE_SAVE_AS_PKCS7,
  2047. CERT_STORE_SAVE_TO_FILENAME_W,
  2048. (void *) FileName,
  2049. 0))
  2050. {
  2051. hr = HRESULT_FROM_WIN32(::GetLastError());
  2052. DebugTrace("Error [%#x]: CertSaveStore() failed.\n", hr);
  2053. goto ErrorExit;
  2054. }
  2055. break;
  2056. }
  2057. default:
  2058. {
  2059. hr = E_INVALIDARG;
  2060. DebugTrace("Error [%#x]: Unknown save as type (%#x).\n", hr, SaveAs);
  2061. goto ErrorExit;
  2062. }
  2063. }
  2064. }
  2065. catch(...)
  2066. {
  2067. hr = E_POINTER;
  2068. DebugTrace("Exception: invalid parameter.\n");
  2069. goto ErrorExit;
  2070. }
  2071. UnlockExit:
  2072. //
  2073. // Free resources.
  2074. //
  2075. if (hCertStore)
  2076. {
  2077. ::CertCloseStore(hCertStore, 0);
  2078. }
  2079. //
  2080. // Unlock access to this object.
  2081. //
  2082. m_Lock.Unlock();
  2083. DebugTrace("Leaving CCertificates::Save().\n");
  2084. return hr;
  2085. ErrorExit:
  2086. //
  2087. // Sanity check.
  2088. //
  2089. ATLASSERT(FAILED(hr));
  2090. ReportError(hr);
  2091. goto UnlockExit;
  2092. }
  2093. ////////////////////////////////////////////////////////////////////////////////
  2094. //
  2095. // Non COM functions.
  2096. //
  2097. /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  2098. Function : CCertificates::AddContext
  2099. Synopsis : Add a cert to the collection.
  2100. Parameter: PCCERT_CONTEXT pCertContext - Cert to be added.
  2101. Remark : This method is not part of the COM interface (it is a normal C++
  2102. member function). We need it to initialize the object created
  2103. internally by us.
  2104. Since it is only a normal C++ member function, this function can
  2105. only be called from a C++ class pointer, not an interface pointer.
  2106. ------------------------------------------------------------------------------*/
  2107. STDMETHODIMP CCertificates::AddContext (PCCERT_CONTEXT pCertContext)
  2108. {
  2109. HRESULT hr = S_OK;
  2110. CComPtr<ICertificate2> pICertificate = NULL;
  2111. DebugTrace("Entering CCertificates::AddContext().\n");
  2112. //
  2113. // Sanity check.
  2114. //
  2115. ATLASSERT(pCertContext);
  2116. try
  2117. {
  2118. //
  2119. // Create the ICertificate object from CERT_CONTEXT.
  2120. //
  2121. if (FAILED(hr = ::CreateCertificateObject(pCertContext,
  2122. m_dwCurrentSafety,
  2123. &pICertificate)))
  2124. {
  2125. DebugTrace("Error [%#x]: CreateCertificateObject() failed.\n", hr);
  2126. goto ErrorExit;
  2127. }
  2128. //
  2129. // Add to collection.
  2130. //
  2131. if (FAILED(hr = Add(pICertificate)))
  2132. {
  2133. DebugTrace("Error [%#x]: CCertificates::Add() failed.\n", hr);
  2134. goto ErrorExit;
  2135. }
  2136. }
  2137. catch(...)
  2138. {
  2139. hr = E_POINTER;
  2140. DebugTrace("Exception: invalid parameter.\n");
  2141. goto ErrorExit;
  2142. }
  2143. CommonExit:
  2144. DebugTrace("Leaving CCertificates::AddContext().\n");
  2145. return hr;
  2146. ErrorExit:
  2147. //
  2148. // Sanity check.
  2149. //
  2150. ATLASSERT(FAILED(hr));
  2151. goto CommonExit;
  2152. }
  2153. /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  2154. Function : CCertificate::LoadFromCert
  2155. Synopsis : Load from the single certificate context.
  2156. Parameter: PCCERT_CONTEXT pContext - Pointer to a cert context.
  2157. Remark :
  2158. ------------------------------------------------------------------------------*/
  2159. STDMETHODIMP CCertificates::LoadFromCert (PCCERT_CONTEXT pCertContext)
  2160. {
  2161. HRESULT hr = S_OK;
  2162. DebugTrace("Entering CCertificates::LoadFromCert().\n");
  2163. //
  2164. // Sanity check.
  2165. //
  2166. ATLASSERT(pCertContext);
  2167. //
  2168. // Add the cert.
  2169. //
  2170. if (FAILED(hr = AddContext(pCertContext)))
  2171. {
  2172. DebugTrace("Error [%#x]: CCertificates::AddContext() failed.\n", hr);
  2173. goto ErrorExit;
  2174. }
  2175. CommonExit:
  2176. DebugTrace("Leaving CCertificates::LoadFromCert().\n");
  2177. return hr;
  2178. ErrorExit:
  2179. //
  2180. // Sanity check.
  2181. //
  2182. ATLASSERT(FAILED(hr));
  2183. //
  2184. // Free resource.
  2185. //
  2186. m_coll.clear();
  2187. goto CommonExit;
  2188. }
  2189. /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  2190. Function : CCertificate::LoadFromChain
  2191. Synopsis : Load all certificates from a chain.
  2192. Parameter: PCCERT_CHAIN_CONTEXT pChainContext - Pointer to a chain context.
  2193. Remark :
  2194. ------------------------------------------------------------------------------*/
  2195. STDMETHODIMP CCertificates::LoadFromChain (PCCERT_CHAIN_CONTEXT pChainContext)
  2196. {
  2197. HRESULT hr = S_OK;
  2198. DebugTrace("Entering CCertificates::LoadFromChain().\n");
  2199. //
  2200. // Sanity check.
  2201. //
  2202. ATLASSERT(pChainContext);
  2203. //
  2204. // Process only the simple chain.
  2205. //
  2206. PCERT_SIMPLE_CHAIN pSimpleChain = *pChainContext->rgpChain;
  2207. //
  2208. // Now loop through all certs in the chain.
  2209. //
  2210. for (DWORD i = 0; i < pSimpleChain->cElement; i++)
  2211. {
  2212. //
  2213. // Add the cert.
  2214. //
  2215. if (FAILED(hr = AddContext(pSimpleChain->rgpElement[i]->pCertContext)))
  2216. {
  2217. DebugTrace("Error [%#x]: CCertificates::AddContext() failed.\n", hr);
  2218. goto ErrorExit;
  2219. }
  2220. }
  2221. CommonExit:
  2222. DebugTrace("Leaving CCertificates::LoadFromChain().\n");
  2223. return hr;
  2224. ErrorExit:
  2225. //
  2226. // Sanity check.
  2227. //
  2228. ATLASSERT(FAILED(hr));
  2229. //
  2230. // Free resource.
  2231. //
  2232. m_coll.clear();
  2233. goto CommonExit;
  2234. }
  2235. /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  2236. Function : CCertificates::LoadFromStore
  2237. Synopsis : Load all certificates from a store.
  2238. Parameter: HCERTSTORE hCertStore - Store where all certificates are to be
  2239. loaded from.
  2240. Remark :
  2241. ------------------------------------------------------------------------------*/
  2242. STDMETHODIMP CCertificates::LoadFromStore (HCERTSTORE hCertStore)
  2243. {
  2244. HRESULT hr = S_OK;
  2245. PCCERT_CONTEXT pCertContext = NULL;
  2246. DebugTrace("Entering CCertificates::LoadFromStore().\n");
  2247. //
  2248. // Sanity check.
  2249. //
  2250. ATLASSERT(hCertStore);
  2251. //
  2252. // Now transfer all certificates from the store to the collection map.
  2253. //
  2254. while (pCertContext = ::CertEnumCertificatesInStore(hCertStore, pCertContext))
  2255. {
  2256. //
  2257. // Add the cert.
  2258. //
  2259. if (FAILED(hr = AddContext(pCertContext)))
  2260. {
  2261. DebugTrace("Error [%#x]: CCertificates::AddContext() failed.\n", hr);
  2262. goto ErrorExit;
  2263. }
  2264. //
  2265. // Don'f free cert context here, as CertEnumCertificatesInStore()
  2266. // will do that automatically!!!
  2267. //
  2268. }
  2269. //
  2270. // Above loop can exit either because there is no more certificate in
  2271. // the store or an error. Need to check last error to be certain.
  2272. //
  2273. if (CRYPT_E_NOT_FOUND != ::GetLastError())
  2274. {
  2275. hr = HRESULT_FROM_WIN32(::GetLastError());
  2276. DebugTrace("Error [%#x]: CertEnumCertificatesInStore() failed.\n", hr);
  2277. goto ErrorExit;
  2278. }
  2279. CommonExit:
  2280. DebugTrace("Leaving CCertificates::LoadFromStore().\n");
  2281. return hr;
  2282. ErrorExit:
  2283. //
  2284. // Sanity check.
  2285. //
  2286. ATLASSERT(FAILED(hr));
  2287. //
  2288. // Free resource.
  2289. //
  2290. if (pCertContext)
  2291. {
  2292. ::CertFreeCertificateContext(pCertContext);
  2293. }
  2294. if (FAILED(hr))
  2295. {
  2296. m_coll.clear();
  2297. }
  2298. goto CommonExit;
  2299. }
  2300. /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  2301. Function : CCertificates::LoadFromMessage
  2302. Synopsis : Load all certificates from a message.
  2303. Parameter: HCRYPTMSG hMsg - Message handle.
  2304. Remark :
  2305. ------------------------------------------------------------------------------*/
  2306. STDMETHODIMP CCertificates::LoadFromMessage (HCRYPTMSG hMsg)
  2307. {
  2308. HRESULT hr = S_OK;
  2309. DWORD dwCertCount = 0;
  2310. DWORD cbCertCount = sizeof(dwCertCount);
  2311. DebugTrace("Entering CCertificates::LoadFromMessage().\n");
  2312. //
  2313. // Sanity check.
  2314. //
  2315. ATLASSERT(hMsg);
  2316. //
  2317. // Get number of certs in message.
  2318. //
  2319. if (!::CryptMsgGetParam(hMsg,
  2320. CMSG_CERT_COUNT_PARAM,
  2321. 0,
  2322. (void **) &dwCertCount,
  2323. &cbCertCount))
  2324. {
  2325. hr = HRESULT_FROM_WIN32(::GetLastError());
  2326. DebugTrace("Error [%#x]: CryptMsgGetParam() failed.\n", hr);
  2327. goto ErrorExit;
  2328. }
  2329. //
  2330. // Loop thru all certs in the message.
  2331. //
  2332. while (dwCertCount--)
  2333. {
  2334. PCCERT_CONTEXT pCertContext = NULL;
  2335. CRYPT_DATA_BLOB EncodedCertBlob = {0, NULL};
  2336. //
  2337. // Get a cert from the bag of certs.
  2338. //
  2339. if (FAILED(hr = ::GetMsgParam(hMsg,
  2340. CMSG_CERT_PARAM,
  2341. dwCertCount,
  2342. (void **) &EncodedCertBlob.pbData,
  2343. &EncodedCertBlob.cbData)))
  2344. {
  2345. DebugTrace("Error [%#x]: GetMsgParam() failed.\n", hr);
  2346. goto ErrorExit;
  2347. }
  2348. //
  2349. // Create a context for the cert.
  2350. //
  2351. pCertContext = ::CertCreateCertificateContext(CAPICOM_ASN_ENCODING,
  2352. (const PBYTE) EncodedCertBlob.pbData,
  2353. EncodedCertBlob.cbData);
  2354. //
  2355. // Free encoded cert blob memory before checking result.
  2356. //
  2357. ::CoTaskMemFree((LPVOID) EncodedCertBlob.pbData);
  2358. if (!pCertContext)
  2359. {
  2360. hr = HRESULT_FROM_WIN32(::GetLastError());
  2361. DebugTrace("Error [%#x]: CertCreateCertificateContext() failed.\n", hr);
  2362. goto ErrorExit;
  2363. }
  2364. //
  2365. // Add the cert.
  2366. //
  2367. hr = AddContext(pCertContext);
  2368. //
  2369. // Free cert context before checking result.
  2370. //
  2371. ::CertFreeCertificateContext(pCertContext);
  2372. if (FAILED(hr))
  2373. {
  2374. DebugTrace("Error [%#x]: CCertificates::AddContext() failed.\n", hr);
  2375. goto ErrorExit;
  2376. }
  2377. }
  2378. CommonExit:
  2379. DebugTrace("Leaving CCertificates::LoadFromMessage().\n");
  2380. return hr;
  2381. ErrorExit:
  2382. //
  2383. // Sanity check.
  2384. //
  2385. ATLASSERT(FAILED(hr));
  2386. //
  2387. // Free resource.
  2388. //
  2389. m_coll.clear();
  2390. goto CommonExit;
  2391. }
  2392. ////////////////////////////////////////////////////////////////////////////////
  2393. //
  2394. // Custom interfaces.
  2395. //
  2396. /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  2397. Function : CCertificates::_ExportToStore
  2398. Synopsis : Export all certificates in the collection to a specified store.
  2399. Parameter: HCERTSTORE hCertStore - HCERSTORE to copy to.
  2400. Remark :
  2401. ------------------------------------------------------------------------------*/
  2402. STDMETHODIMP CCertificates::_ExportToStore (HCERTSTORE hCertStore)
  2403. {
  2404. HRESULT hr = S_OK;
  2405. CertificateMap::iterator iter;
  2406. DebugTrace("Entering CCertificates::_ExportToStore().\n");
  2407. //
  2408. // Sanity check.
  2409. //
  2410. ATLASSERT(hCertStore);
  2411. //
  2412. // Now, transfer all the certs in the collection to the store.
  2413. //
  2414. for (iter = m_coll.begin(); iter != m_coll.end(); iter++)
  2415. {
  2416. PCCERT_CONTEXT pCertContext = NULL;
  2417. CComPtr<ICertificate> pICertificate = NULL;
  2418. //
  2419. // Get to the stored interface pointer.
  2420. //
  2421. if (!(pICertificate = (*iter).second))
  2422. {
  2423. hr = CAPICOM_E_INTERNAL;
  2424. DebugTrace("Error [%#x]: iterator returns NULL pICertificate pointer.\n", hr);
  2425. goto ErrorExit;
  2426. }
  2427. //
  2428. // Get the CERT_CONTEXT.
  2429. //
  2430. if (FAILED(hr = ::GetCertContext(pICertificate, &pCertContext)))
  2431. {
  2432. DebugTrace("Error [%#x]: pICertificate->GetContext() failed.\n", hr);
  2433. goto ErrorExit;
  2434. }
  2435. //
  2436. // Add the link to store.
  2437. //
  2438. BOOL bResult = ::CertAddCertificateContextToStore(hCertStore,
  2439. pCertContext,
  2440. CERT_STORE_ADD_ALWAYS,
  2441. NULL);
  2442. //
  2443. // First free cert context.
  2444. //
  2445. ::CertFreeCertificateContext(pCertContext);
  2446. //
  2447. // then check result.
  2448. //
  2449. if (!bResult)
  2450. {
  2451. hr = HRESULT_FROM_WIN32(::GetLastError());
  2452. DebugTrace("Error [%#x]: CertAddCertificateContextToStore() failed.\n", hr);
  2453. goto ErrorExit;
  2454. }
  2455. }
  2456. CommonExit:
  2457. DebugTrace("Leaving CCertificates::_ExportToStore().\n");
  2458. return hr;
  2459. ErrorExit:
  2460. //
  2461. // Sanity check.
  2462. //
  2463. ATLASSERT(FAILED(hr));
  2464. goto CommonExit;
  2465. }
  2466. /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  2467. Function : CCertificates::Init
  2468. Synopsis : Initialize the object.
  2469. Parameter: CAPICOM_CERTIFICATES_SOURCE ccs - Source where to get the
  2470. certificates.
  2471. DWORD dwCurrentSafety - Current safety setting.
  2472. BOOL bIndexedByThumbprint - TRUE to index by thumbprint.
  2473. Remark : This method is not part of the COM interface (it is a normal C++
  2474. member function). We need it to initialize the object created
  2475. internally by us.
  2476. Since it is only a normal C++ member function, this function can
  2477. only be called from a C++ class pointer, not an interface pointer.
  2478. ------------------------------------------------------------------------------*/
  2479. STDMETHODIMP CCertificates::Init (CAPICOM_CERTIFICATES_SOURCE ccs,
  2480. DWORD dwCurrentSafety,
  2481. BOOL bIndexedByThumbprint)
  2482. {
  2483. HRESULT hr = S_OK;
  2484. DebugTrace("Entering CCertificates::Init().\n");
  2485. //
  2486. // Set safety setting.
  2487. //
  2488. m_dwCurrentSafety = dwCurrentSafety;
  2489. m_dwNextIndex = 0;
  2490. #if (1) // DSIE: Can turn on index by thumbprint if desired.
  2491. m_bIndexedByThumbprint = FALSE;
  2492. #else
  2493. m_bIndexedByThumbprint = bIndexedByThumbprint;
  2494. #endif
  2495. //
  2496. // Initialize object.
  2497. //
  2498. switch (ccs.dwSource)
  2499. {
  2500. case CAPICOM_CERTIFICATES_LOAD_FROM_CERT:
  2501. {
  2502. //
  2503. // Sanity check.
  2504. //
  2505. ATLASSERT(ccs.pCertContext);
  2506. if (FAILED(hr = LoadFromCert(ccs.pCertContext)))
  2507. {
  2508. DebugTrace("Error [%#x]: CCertificates::LoadFromCert() failed.\n", hr);
  2509. goto ErrorExit;
  2510. }
  2511. break;
  2512. }
  2513. case CAPICOM_CERTIFICATES_LOAD_FROM_CHAIN:
  2514. {
  2515. //
  2516. // Sanity check.
  2517. //
  2518. ATLASSERT(ccs.pChainContext);
  2519. if (FAILED(hr = LoadFromChain(ccs.pChainContext)))
  2520. {
  2521. DebugTrace("Error [%#x]: CCertificates::LoadFromChain() failed.\n", hr);
  2522. goto ErrorExit;
  2523. }
  2524. break;
  2525. }
  2526. case CAPICOM_CERTIFICATES_LOAD_FROM_STORE:
  2527. {
  2528. //
  2529. // Sanity check.
  2530. //
  2531. ATLASSERT(ccs.hCertStore);
  2532. if (FAILED(hr = LoadFromStore(ccs.hCertStore)))
  2533. {
  2534. DebugTrace("Error [%#x]: CCertificates::LoadFromStore() failed.\n", hr);
  2535. goto ErrorExit;
  2536. }
  2537. break;
  2538. }
  2539. case CAPICOM_CERTIFICATES_LOAD_FROM_MESSAGE:
  2540. {
  2541. //
  2542. // Sanity check.
  2543. //
  2544. ATLASSERT(ccs.hCryptMsg);
  2545. if (FAILED(hr = LoadFromMessage(ccs.hCryptMsg)))
  2546. {
  2547. DebugTrace("Error [%#x]: CCertificates::LoadFromMessage() failed.\n", hr);
  2548. goto ErrorExit;
  2549. }
  2550. break;
  2551. }
  2552. default:
  2553. {
  2554. //
  2555. // We have a bug.
  2556. //
  2557. ATLASSERT(FALSE);
  2558. hr = CAPICOM_E_INTERNAL;
  2559. DebugTrace("Error [%#x]: Unknown store source (ccs.dwSource = %d).\n", hr, ccs.dwSource);
  2560. goto ErrorExit;
  2561. }
  2562. }
  2563. CommonExit:
  2564. DebugTrace("Leaving CCertificates::Init().\n");
  2565. return hr;
  2566. ErrorExit:
  2567. //
  2568. // Sanity check.
  2569. //
  2570. ATLASSERT(FAILED(hr));
  2571. goto CommonExit;
  2572. }