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.

1262 lines
30 KiB

  1. /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  2. Microsoft Windows, Copyright (C) Microsoft Corporation, 2000
  3. File: Signer.cpp
  4. Content: Implementation of CSigner.
  5. History: 11-15-99 dsie created
  6. ------------------------------------------------------------------------------*/
  7. #include "StdAfx.h"
  8. #include "CAPICOM.h"
  9. #include "Signer2.h"
  10. #include "CertHlpr.h"
  11. #include "Certificate.h"
  12. #include "Chain.h"
  13. #include "PFXHlpr.h"
  14. #include "SignHlpr.h"
  15. ////////////////////////////////////////////////////////////////////////////////
  16. //
  17. // Exported functions.
  18. //
  19. /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  20. Function : CreateSignerObject
  21. Synopsis : Create a ISigner object and initialize the object with the
  22. specified certificate.
  23. Parameter: PCCERT_CONTEXT pCertContext - Pointer to CERT_CONTEXT.
  24. CRYPT_ATTRIBUTES * pAuthAttrs - Pointer to CRYPT_ATTRIBUTES
  25. of authenticated attributes.
  26. PCCERT_CHAIN_CONTEXT pChainContext - Chain context.
  27. DWORD dwCurrentSafety - Current safety setting.
  28. ISigner2 ** ppISigner2 - Pointer to pointer to ISigner object to
  29. receive the interface pointer.
  30. Remark :
  31. ------------------------------------------------------------------------------*/
  32. HRESULT CreateSignerObject (PCCERT_CONTEXT pCertContext,
  33. CRYPT_ATTRIBUTES * pAuthAttrs,
  34. PCCERT_CHAIN_CONTEXT pChainContext,
  35. DWORD dwCurrentSafety,
  36. ISigner2 ** ppISigner2)
  37. {
  38. HRESULT hr = S_OK;
  39. CComObject<CSigner> * pCSigner = NULL;
  40. DebugTrace("Entering CreateSignerObject().\n");
  41. //
  42. // Sanity check.
  43. //
  44. ATLASSERT(pCertContext);
  45. ATLASSERT(pAuthAttrs);
  46. ATLASSERT(ppISigner2);
  47. try
  48. {
  49. //
  50. // Create the object. Note that the ref count will still be 0
  51. // after the object is created.
  52. //
  53. if (FAILED(hr = CComObject<CSigner>::CreateInstance(&pCSigner)))
  54. {
  55. DebugTrace("Error [%#x]: CComObject<CSigner>::CreateInstance() failed.\n", hr);
  56. goto ErrorExit;
  57. }
  58. //
  59. // Initialize object.
  60. //
  61. if (FAILED(hr = pCSigner->Init(pCertContext,
  62. pAuthAttrs,
  63. pChainContext,
  64. dwCurrentSafety)))
  65. {
  66. DebugTrace("Error [%#x]: pCSigner->Init() failed.\n", hr);
  67. goto ErrorExit;
  68. }
  69. //
  70. // Return interface pointer to caller.
  71. //
  72. if (FAILED(hr = pCSigner->QueryInterface(ppISigner2)))
  73. {
  74. DebugTrace("Error [%#x]: pCSigner->QueryInterface() failed.\n", hr);
  75. goto ErrorExit;
  76. }
  77. }
  78. catch(...)
  79. {
  80. hr = E_INVALIDARG;
  81. DebugTrace("Exception: invalid parameter.\n");
  82. goto ErrorExit;
  83. }
  84. CommonExit:
  85. DebugTrace("Leaving CreateSignerObject().\n");
  86. return hr;
  87. ErrorExit:
  88. //
  89. // Sanity check.
  90. //
  91. ATLASSERT(FAILED(hr));
  92. //
  93. // Free resource.
  94. //
  95. if (pCSigner)
  96. {
  97. delete pCSigner;
  98. }
  99. goto CommonExit;
  100. }
  101. /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  102. Function : GetSignerAdditionalStore
  103. Synopsis : Return the additional store, if any.
  104. Parameter: ISigner2 * pISigner - Pointer to signer object.
  105. HCERTSTORE * phCertStore - Pointer to HCERTSOTRE.
  106. Remark : Caller must call CertCloseStore() for the handle returned.
  107. ------------------------------------------------------------------------------*/
  108. HRESULT GetSignerAdditionalStore (ISigner2 * pISigner,
  109. HCERTSTORE * phCertStore)
  110. {
  111. HRESULT hr = S_OK;
  112. CComPtr<ICSigner> pICSigner = NULL;
  113. DebugTrace("Entering GetSignerAdditionalStore().\n");
  114. //
  115. // Sanity check.
  116. //
  117. ATLASSERT(pISigner);
  118. ATLASSERT(phCertStore);
  119. //
  120. // Get ICSigner interface pointer.
  121. //
  122. if (FAILED(hr = pISigner->QueryInterface(IID_ICSigner, (void **) &pICSigner)))
  123. {
  124. DebugTrace("Error [%#x]: pISigner->QueryInterface() failed.\n", hr);
  125. goto ErrorExit;
  126. }
  127. //
  128. // Get the HCERTSTORE.
  129. //
  130. if (FAILED(hr = pICSigner->get_AdditionalStore((long *) phCertStore)))
  131. {
  132. DebugTrace("Error [%#x]: pICSigner->get_AdditionalStore() failed.\n", hr);
  133. goto ErrorExit;
  134. }
  135. CommonExit:
  136. DebugTrace("Leaving GetSignerAdditionalStore().\n");
  137. return hr;
  138. ErrorExit:
  139. //
  140. // Sanity check.
  141. //
  142. ATLASSERT(FAILED(hr));
  143. goto CommonExit;
  144. }
  145. /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  146. Function : PutSignerAdditionalStore
  147. Synopsis : Set the additional store.
  148. Parameter: ISigner2 * pISigner - Pointer to signer object.
  149. HCERTSTORE hCertStore - Additional store handle.
  150. Remark :
  151. ------------------------------------------------------------------------------*/
  152. HRESULT PutSignerAdditionalStore (ISigner2 * pISigner,
  153. HCERTSTORE hCertStore)
  154. {
  155. HRESULT hr = S_OK;
  156. CComPtr<ICSigner> pICSigner = NULL;
  157. DebugTrace("Entering PutSignerAdditionalStore().\n");
  158. //
  159. // Sanity check.
  160. //
  161. ATLASSERT(pISigner);
  162. ATLASSERT(hCertStore);
  163. //
  164. // Get ICSigner interface pointer.
  165. //
  166. if (FAILED(hr = pISigner->QueryInterface(IID_ICSigner, (void **) &pICSigner)))
  167. {
  168. DebugTrace("Error [%#x]: pISigner->QueryInterface() failed.\n", hr);
  169. goto ErrorExit;
  170. }
  171. //
  172. // Get the HCERTSTORE.
  173. //
  174. if (FAILED(hr = pICSigner->put_AdditionalStore((long) hCertStore)))
  175. {
  176. DebugTrace("Error [%#x]: pICSigner->put_AdditionalStore() failed.\n", hr);
  177. goto ErrorExit;
  178. }
  179. CommonExit:
  180. DebugTrace("Leaving PutSignerAdditionalStore().\n");
  181. return hr;
  182. ErrorExit:
  183. //
  184. // Sanity check.
  185. //
  186. ATLASSERT(FAILED(hr));
  187. goto CommonExit;
  188. }
  189. ////////////////////////////////////////////////////////////////////////////////
  190. //
  191. // Local functions.
  192. //
  193. /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  194. Function : SelectSignerCertCallback
  195. Synopsis : Callback routine for CryptUIDlgSelectCertificateW() API for
  196. signer's cert selection.
  197. Parameter: See CryptUI.h for defination.
  198. Remark : Filter out any cert that is not time valid or has no associated
  199. private key.
  200. Also, note that we are not building chain here, since chain
  201. building is costly, and thus present poor user's experience.
  202. Instead, we will build the chain and check validity of the cert
  203. selected (see GetSignerCert function).
  204. ------------------------------------------------------------------------------*/
  205. static BOOL WINAPI SelectSignerCertCallback (PCCERT_CONTEXT pCertContext,
  206. BOOL * pfInitialSelectedCert,
  207. void * pvCallbackData)
  208. {
  209. BOOL bResult = FALSE;
  210. int nValidity = 0;
  211. DWORD cb = 0;
  212. //
  213. // Check availability of private key.
  214. //
  215. if (!::CertGetCertificateContextProperty(pCertContext,
  216. CERT_KEY_PROV_INFO_PROP_ID,
  217. NULL,
  218. &cb))
  219. {
  220. DebugTrace("Info: SelectSignerCertCallback() - private key not found.\n");
  221. goto CommonExit;
  222. }
  223. //
  224. // Check cert time validity.
  225. //
  226. if (0 != (nValidity = ::CertVerifyTimeValidity(NULL, pCertContext->pCertInfo)))
  227. {
  228. DebugTrace("Info: SelectSignerCertCallback() - invalid time (%s).\n",
  229. nValidity < 0 ? "not yet valid" : "expired");
  230. goto CommonExit;
  231. }
  232. bResult = TRUE;
  233. CommonExit:
  234. return bResult;
  235. }
  236. ///////////////////////////////////////////////////////////////////////////////
  237. //
  238. // CSigner
  239. //
  240. /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  241. Function : CSigner::get_Certificate
  242. Synopsis : Return the signer's cert as an ICertificate object.
  243. Parameter: ICertificate ** pVal - Pointer to pointer to ICertificate to receive
  244. interface pointer.
  245. Remark :
  246. ------------------------------------------------------------------------------*/
  247. STDMETHODIMP CSigner::get_Certificate (ICertificate ** pVal)
  248. {
  249. HRESULT hr = S_OK;
  250. DebugTrace("Entering CSigner::get_Certificate().\n");
  251. try
  252. {
  253. //
  254. // Lock access to this object.
  255. //
  256. m_Lock.Lock();
  257. //
  258. // Make sure we indeed have a certificate.
  259. //
  260. if (!m_pICertificate)
  261. {
  262. hr = CAPICOM_E_SIGNER_NOT_INITIALIZED;
  263. DebugTrace("Error [%#x]: signer object currently does not have a certificate.\n", hr);
  264. goto ErrorExit;
  265. }
  266. //
  267. // Return interface pointer.
  268. //
  269. if (FAILED(hr = m_pICertificate->QueryInterface(pVal)))
  270. {
  271. DebugTrace("Unexpected error [%#x]: m_pICertificate->QueryInterface() failed.\n", hr);
  272. goto ErrorExit;
  273. }
  274. }
  275. catch(...)
  276. {
  277. hr = E_POINTER;
  278. DebugTrace("Exception: invalid parameter.\n");
  279. goto ErrorExit;
  280. }
  281. UnlockExit:
  282. //
  283. // Unlock access to this object.
  284. //
  285. m_Lock.Unlock();
  286. DebugTrace("Leaving CSigner::get_Certificate().\n");
  287. return hr;
  288. ErrorExit:
  289. //
  290. // Sanity check.
  291. //
  292. ATLASSERT(FAILED(hr));
  293. ReportError(hr);
  294. goto UnlockExit;
  295. }
  296. /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  297. Function : CSigner::put_Certificate
  298. Synopsis : Set signer's cert.
  299. Parameter: ICertificate * newVal - Pointer to ICertificate.
  300. Remark :
  301. ------------------------------------------------------------------------------*/
  302. STDMETHODIMP CSigner::put_Certificate (ICertificate * newVal)
  303. {
  304. HRESULT hr = S_OK;
  305. PCCERT_CONTEXT pCertContext = NULL;
  306. DebugTrace("Entering CSigner::put_Certificate().\n");
  307. try
  308. {
  309. //
  310. // Lock access to this object.
  311. //
  312. m_Lock.Lock();
  313. //
  314. // Make sure is a valid ICertificate by getting its CERT_CONTEXT.
  315. //
  316. if (FAILED(hr = ::GetCertContext(newVal, &pCertContext)))
  317. {
  318. DebugTrace("Error [%#x]: GetCertContext() failed.\n", hr);
  319. goto ErrorExit;
  320. }
  321. //
  322. // Free the CERT_CONTEXT.
  323. //
  324. if (!::CertFreeCertificateContext(pCertContext))
  325. {
  326. hr = HRESULT_FROM_WIN32(::GetLastError());
  327. DebugTrace("Error [%#x]: CertFreeCertificateContext() failed.\n", hr);
  328. goto ErrorExit;
  329. }
  330. //
  331. // Reset.
  332. //
  333. if (FAILED(hr = m_pIAttributes->Clear()))
  334. {
  335. DebugTrace("Error [%#x]: m_pIAttributes->Clear() failed.\n", hr);
  336. goto ErrorExit;
  337. }
  338. //
  339. // Store new ICertificate.
  340. //
  341. m_pICertificate = newVal;
  342. }
  343. catch(...)
  344. {
  345. hr = E_POINTER;
  346. DebugTrace("Exception: invalid parameter.\n");
  347. goto ErrorExit;
  348. }
  349. UnlockExit:
  350. //
  351. // Unlock access to this object.
  352. //
  353. m_Lock.Unlock();
  354. DebugTrace("Leaving CSigner::put_Certificate().\n");
  355. return hr;
  356. ErrorExit:
  357. //
  358. // Sanity check.
  359. //
  360. ATLASSERT(FAILED(hr));
  361. ReportError(hr);
  362. goto UnlockExit;
  363. }
  364. /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  365. Function : CSigner::get_AuthenticatedAttributes
  366. Synopsis : Property to return the IAttributes collection object authenticated
  367. attributes.
  368. Parameter: IAttributes ** pVal - Pointer to pointer to IAttributes to receive
  369. the interface pointer.
  370. Remark :
  371. ------------------------------------------------------------------------------*/
  372. STDMETHODIMP CSigner::get_AuthenticatedAttributes (IAttributes ** pVal)
  373. {
  374. HRESULT hr = S_OK;
  375. DebugTrace("Entering CSigner::get_AuthenticatedAttributes().\n");
  376. try
  377. {
  378. //
  379. // Lock access to this object.
  380. //
  381. m_Lock.Lock();
  382. //
  383. // Sanity check.
  384. //
  385. ATLASSERT(m_pIAttributes);
  386. //
  387. // Return interface pointer to caller.
  388. //
  389. if (FAILED(hr = m_pIAttributes->QueryInterface(pVal)))
  390. {
  391. DebugTrace("Unexpected error [%#x]: m_pIAttributes->QueryInterface() failed.\n", hr);
  392. goto ErrorExit;
  393. }
  394. }
  395. catch(...)
  396. {
  397. hr = E_POINTER;
  398. DebugTrace("Exception: invalid parameter.\n");
  399. goto ErrorExit;
  400. }
  401. UnlockExit:
  402. //
  403. // Unlock access to this object.
  404. //
  405. m_Lock.Unlock();
  406. DebugTrace("Leaving CSigner::get_AuthenticatedAttributes().\n");
  407. return hr;
  408. ErrorExit:
  409. //
  410. // Sanity check.
  411. //
  412. ATLASSERT(FAILED(hr));
  413. ReportError(hr);
  414. goto UnlockExit;
  415. }
  416. /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  417. Function : CSigner::get_Chain
  418. Synopsis : Return the signer's chain as an IChain object.
  419. Parameter: ICertificate ** pVal - Pointer to pointer to ICertificate to receive
  420. interface pointer.
  421. Remark :
  422. ------------------------------------------------------------------------------*/
  423. STDMETHODIMP CSigner::get_Chain (IChain ** pVal)
  424. {
  425. HRESULT hr = S_OK;
  426. PCCERT_CONTEXT pCertContext = NULL;
  427. PCCERT_CHAIN_CONTEXT pChainContext = NULL;
  428. DebugTrace("Entering CSigner::get_Chain().\n");
  429. try
  430. {
  431. //
  432. // Lock access to this object.
  433. //
  434. m_Lock.Lock();
  435. //
  436. // Build the chain, if not available.
  437. //
  438. if (!m_pIChain)
  439. {
  440. //
  441. // Make sure we have a certificate to build the chain.
  442. //
  443. if (!m_pICertificate)
  444. {
  445. hr = CAPICOM_E_SIGNER_NOT_INITIALIZED;
  446. DebugTrace("Error [%#x]: signer object currently does not have a certificate.\n", hr);
  447. goto ErrorExit;
  448. }
  449. if (FAILED(hr = ::GetCertContext(m_pICertificate, &pCertContext)))
  450. {
  451. DebugTrace("Error [%#x]: GetCertContext() failed.\n", hr);
  452. goto ErrorExit;
  453. }
  454. if (FAILED(hr = ::BuildChain(pCertContext, NULL, CERT_CHAIN_POLICY_BASE, &pChainContext)))
  455. {
  456. DebugTrace("Error [%#x]: BuildChain() failed.\n", hr);
  457. goto ErrorExit;
  458. }
  459. //
  460. // Now create the chain object.
  461. //
  462. if (FAILED(hr = ::CreateChainObject(pChainContext, &m_pIChain)))
  463. {
  464. DebugTrace("Error [%#x]: CreateChainObject() failed.\n", hr);
  465. goto ErrorExit;
  466. }
  467. }
  468. //
  469. // Return the signer's chain.
  470. //
  471. if (FAILED(hr = m_pIChain->QueryInterface(pVal)))
  472. {
  473. DebugTrace("Unexpected error [%#x]: m_pIChain->QueryInterface() failed.\n", hr);
  474. goto ErrorExit;
  475. }
  476. }
  477. catch(...)
  478. {
  479. hr = E_POINTER;
  480. DebugTrace("Exception: invalid parameter.\n");
  481. goto ErrorExit;
  482. }
  483. UnlockExit:
  484. //
  485. // Free resources.
  486. //
  487. if (pCertContext)
  488. {
  489. ::CertFreeCertificateContext(pCertContext);
  490. }
  491. if (pChainContext)
  492. {
  493. ::CertFreeCertificateChain(pChainContext);
  494. }
  495. //
  496. // Unlock access to this object.
  497. //
  498. m_Lock.Unlock();
  499. DebugTrace("Leaving CSigner::get_Chain().\n");
  500. return hr;
  501. ErrorExit:
  502. //
  503. // Sanity check.
  504. //
  505. ATLASSERT(FAILED(hr));
  506. ReportError(hr);
  507. goto UnlockExit;
  508. }
  509. /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  510. Function : CSigner::get_Options
  511. Synopsis : Get signer's options.
  512. Parameter: CAPICOM_CERTIFICATE_INCLUDE_OPTION * pVal - Pointer to variable
  513. receive value.
  514. Remark :
  515. ------------------------------------------------------------------------------*/
  516. STDMETHODIMP CSigner::get_Options (CAPICOM_CERTIFICATE_INCLUDE_OPTION * pVal)
  517. {
  518. HRESULT hr = S_OK;
  519. DebugTrace("Entering CSigner::get_Options().\n");
  520. try
  521. {
  522. //
  523. // Lock access to this object.
  524. //
  525. m_Lock.Lock();
  526. *pVal = (CAPICOM_CERTIFICATE_INCLUDE_OPTION) m_dwIncludeOption;
  527. }
  528. catch(...)
  529. {
  530. hr = E_POINTER;
  531. DebugTrace("Exception: invalid parameter.\n");
  532. goto ErrorExit;
  533. }
  534. UnlockExit:
  535. //
  536. // Unlock access to this object.
  537. //
  538. m_Lock.Unlock();
  539. DebugTrace("Leaving CSigner::get_Options().\n");
  540. return hr;
  541. ErrorExit:
  542. //
  543. // Sanity check.
  544. //
  545. ATLASSERT(FAILED(hr));
  546. ReportError(hr);
  547. goto UnlockExit;
  548. }
  549. /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  550. Function : CSigner::put_Options
  551. Synopsis : Set signer's options.
  552. Parameter: CAPICOM_CERTIFICATE_INCLUDE_OPTION newVal - Include option.
  553. Remark :
  554. ------------------------------------------------------------------------------*/
  555. STDMETHODIMP CSigner::put_Options (CAPICOM_CERTIFICATE_INCLUDE_OPTION newVal)
  556. {
  557. HRESULT hr = S_OK;
  558. DebugTrace("Entering CSigner::put_Options().\n");
  559. try
  560. {
  561. //
  562. // Lock access to this object.
  563. //
  564. m_Lock.Lock();
  565. m_dwIncludeOption = (DWORD) newVal;
  566. }
  567. catch(...)
  568. {
  569. hr = E_POINTER;
  570. DebugTrace("Exception: invalid parameter.\n");
  571. goto ErrorExit;
  572. }
  573. UnlockExit:
  574. //
  575. // Unlock access to this object.
  576. //
  577. m_Lock.Unlock();
  578. DebugTrace("Leaving CSigner::put_Options().\n");
  579. return hr;
  580. ErrorExit:
  581. //
  582. // Sanity check.
  583. //
  584. ATLASSERT(FAILED(hr));
  585. ReportError(hr);
  586. goto UnlockExit;
  587. }
  588. /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  589. Function : CSigner::Load
  590. Synopsis : Method to load signing certificate from a PFX file.
  591. Parameter: BSTR FileName - PFX file name.
  592. BSTR Password - Password.
  593. Remark :
  594. ------------------------------------------------------------------------------*/
  595. STDMETHODIMP CSigner::Load (BSTR FileName,
  596. BSTR Password)
  597. {
  598. HRESULT hr = S_OK;
  599. CAPICOM_STORE_INFO StoreInfo = {CAPICOM_STORE_INFO_HCERTSTORE, NULL};
  600. CComPtr<ICertificate2> pICertificate = NULL;
  601. DebugTrace("Entering CSigner::Load().\n");
  602. try
  603. {
  604. //
  605. // Lock access to this object.
  606. //
  607. m_Lock.Lock();
  608. //
  609. // Not allowed if called from WEB script.
  610. //
  611. if (m_dwCurrentSafety)
  612. {
  613. hr = CAPICOM_E_NOT_ALLOWED;
  614. DebugTrace("Error [%#x]: Loading cert file from WEB script is not allowed.\n", hr);
  615. goto ErrorExit;
  616. }
  617. //
  618. // Check parameters.
  619. //
  620. if (NULL == FileName)
  621. {
  622. hr = E_INVALIDARG;
  623. DebugTrace("Error [%#x]: FileName parameter is NULL.\n", hr);
  624. goto ErrorExit;
  625. }
  626. //
  627. // Work around MIDL problem.
  628. //
  629. if (0 == ::SysStringLen(Password))
  630. {
  631. Password = NULL;
  632. }
  633. //
  634. // Load the PFX.
  635. //
  636. if (FAILED(hr = ::PFXLoadStore((LPWSTR) FileName,
  637. (LPWSTR) Password,
  638. 0,
  639. &StoreInfo.hCertStore)))
  640. {
  641. DebugTrace("Error [%#x]: PFXLoadStore() failed.\n", hr);
  642. goto ErrorExit;
  643. }
  644. //
  645. // Get the signer's cert (may prompt user to select signer's cert).
  646. //
  647. if (FAILED(hr = ::SelectCertificate(StoreInfo,
  648. SelectSignerCertCallback,
  649. &pICertificate)))
  650. {
  651. DebugTrace("Error [%#x]: SelectCertificate() failed.\n", hr);
  652. goto ErrorExit;
  653. }
  654. if (FAILED(hr = pICertificate->QueryInterface(__uuidof(ICertificate), (void **) &m_pICertificate)))
  655. {
  656. DebugTrace("Error [%#x]: pICertificate2->QueryInterface() failed.\n", hr);
  657. goto ErrorExit;
  658. }
  659. //
  660. // Free any existing store, and then update the store.
  661. //
  662. if (m_hCertStore)
  663. {
  664. HRESULT hr2;
  665. //
  666. // Ignore error.
  667. //
  668. if (m_bPFXStore)
  669. {
  670. if (FAILED(hr2 = ::PFXFreeStore(m_hCertStore)))
  671. {
  672. DebugTrace("Info [%#x]: PFXFreeStore() failed.\n", hr2);
  673. }
  674. }
  675. else
  676. {
  677. if (!::CertCloseStore(m_hCertStore, 0))
  678. {
  679. hr2 = HRESULT_FROM_WIN32(::GetLastError());
  680. DebugTrace("Info [%#x]: CertCloseStore() failed.\n", hr2);
  681. }
  682. }
  683. }
  684. m_hCertStore = StoreInfo.hCertStore;
  685. m_bPFXStore = TRUE;
  686. }
  687. catch(...)
  688. {
  689. hr = E_POINTER;
  690. DebugTrace("Exception: invalid parameter.\n");
  691. goto ErrorExit;
  692. }
  693. UnlockExit:
  694. //
  695. // Unlock access to this object.
  696. //
  697. m_Lock.Unlock();
  698. DebugTrace("Leaving CSigner::Load().\n");
  699. return hr;
  700. ErrorExit:
  701. //
  702. // Sanity check.
  703. //
  704. ATLASSERT(FAILED(hr));
  705. //
  706. // Free resources.
  707. //
  708. if (StoreInfo.hCertStore)
  709. {
  710. ::PFXFreeStore(StoreInfo.hCertStore);
  711. }
  712. ReportError(hr);
  713. goto UnlockExit;
  714. }
  715. ////////////////////////////////////////////////////////////////////////////////
  716. //
  717. // Custom interfaces.
  718. //
  719. /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  720. Function : CSigner::get_AdditionalStore
  721. Synopsis : Return the signer additional store handle.
  722. Parameter: long * phAdditionalStore - Pointer to long to receive the HCERTSTORE.
  723. Remark : Caller must call CertCloseStore() for the handle returned.
  724. ------------------------------------------------------------------------------*/
  725. STDMETHODIMP CSigner::get_AdditionalStore (long * phAdditionalStore)
  726. {
  727. HRESULT hr = S_OK;
  728. HCERTSTORE hCertStore = NULL;
  729. DebugTrace("Entering CSigner::get_AdditionalStore().\n");
  730. try
  731. {
  732. //
  733. // Lock access to this object.
  734. //
  735. m_Lock.Lock();
  736. //
  737. // Check parameter.
  738. //
  739. if (NULL == phAdditionalStore)
  740. {
  741. hr = E_INVALIDARG;
  742. DebugTrace("Error [%#x]: Parameter phAdditionalStore is NULL.\n", hr);
  743. goto ErrorExit;
  744. }
  745. //
  746. // Initialize.
  747. //
  748. *phAdditionalStore = NULL;
  749. //
  750. // Duplicate store handle, if available.
  751. //
  752. if (NULL != m_hCertStore)
  753. {
  754. if (NULL == (hCertStore = ::CertDuplicateStore(m_hCertStore)))
  755. {
  756. hr = HRESULT_FROM_WIN32(::GetLastError());
  757. DebugTrace("Error [%#x]: CertDuplicateStore() failed.\n", hr);
  758. goto ErrorExit;
  759. }
  760. *phAdditionalStore = (long) hCertStore;
  761. }
  762. }
  763. catch(...)
  764. {
  765. hr = E_POINTER;
  766. DebugTrace("Exception: invalid parameter.\n");
  767. goto ErrorExit;
  768. }
  769. UnlockExit:
  770. //
  771. // Unlock access to this object.
  772. //
  773. m_Lock.Unlock();
  774. DebugTrace("Leaving CSigner::get_AdditionalStore().\n");
  775. return hr;
  776. ErrorExit:
  777. //
  778. // Sanity check.
  779. //
  780. ATLASSERT(FAILED(hr));
  781. ReportError(hr);
  782. //
  783. // Release resources.
  784. //
  785. if (hCertStore)
  786. {
  787. ::CertCloseStore(hCertStore, 0);
  788. }
  789. goto UnlockExit;
  790. }
  791. /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  792. Function : CSigner::put_AdditionalStore
  793. Synopsis : Set the additional sore handle.
  794. Parameter: long hAdditionalStore - Additional store handle.
  795. Remark :
  796. ------------------------------------------------------------------------------*/
  797. STDMETHODIMP CSigner::put_AdditionalStore (long hAdditionalStore)
  798. {
  799. HRESULT hr = S_OK;
  800. HCERTSTORE hCertStore = (HCERTSTORE) hAdditionalStore;
  801. DebugTrace("Entering CSigner::put_AdditionalStore().\n");
  802. try
  803. {
  804. //
  805. // Lock access to this object.
  806. //
  807. m_Lock.Lock();
  808. //
  809. // Check parameter.
  810. //
  811. if (NULL == hCertStore)
  812. {
  813. hr = E_INVALIDARG;
  814. DebugTrace("Error [%#x]: Parameter hAdditionalStore is NULL.\n", hr);
  815. goto ErrorExit;
  816. }
  817. //
  818. // Free any existing store, and then update the store.
  819. //
  820. if (m_hCertStore)
  821. {
  822. HRESULT hr2;
  823. //
  824. // Ignore error.
  825. //
  826. if (m_bPFXStore)
  827. {
  828. if (FAILED(hr2 = ::PFXFreeStore(m_hCertStore)))
  829. {
  830. DebugTrace("Info [%#x]: PFXFreeStore() failed.\n", hr2);
  831. }
  832. }
  833. else
  834. {
  835. if (!::CertCloseStore(m_hCertStore, 0))
  836. {
  837. hr2 = HRESULT_FROM_WIN32(::GetLastError());
  838. DebugTrace("Info [%#x]: CertCloseStore() failed.\n", hr2);
  839. }
  840. }
  841. }
  842. //
  843. // Don't know what kind of store this is, so mark it as such so that we
  844. // will always close it with CertCloseStore(), instead of PFXFreeStore().
  845. //
  846. m_bPFXStore = FALSE;
  847. //
  848. // Duplicate store handle.
  849. //
  850. if (NULL == (m_hCertStore = ::CertDuplicateStore(hCertStore)))
  851. {
  852. hr = HRESULT_FROM_WIN32(::GetLastError());
  853. DebugTrace("Error [%#x]: CertDuplicateStore() failed.\n", hr);
  854. goto ErrorExit;
  855. }
  856. }
  857. catch(...)
  858. {
  859. hr = E_POINTER;
  860. DebugTrace("Exception: invalid parameter.\n");
  861. goto ErrorExit;
  862. }
  863. UnlockExit:
  864. //
  865. // Unlock access to this object.
  866. //
  867. m_Lock.Unlock();
  868. DebugTrace("Leaving CSigner::put_AdditionalStore().\n");
  869. return hr;
  870. ErrorExit:
  871. //
  872. // Sanity check.
  873. //
  874. ATLASSERT(FAILED(hr));
  875. ReportError(hr);
  876. goto UnlockExit;
  877. }
  878. ////////////////////////////////////////////////////////////////////////////////
  879. //
  880. // Private methods.
  881. //
  882. /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  883. Function : CSigner::Init
  884. Synopsis : Initialize the object.
  885. Parameter: PCERT_CONTEXT pCertContext - Poiner to CERT_CONTEXT used to
  886. initialize this object, or NULL.
  887. CRYPT_ATTRIBUTES * pAuthAttrs - Pointer to CRYPT_ATTRIBUTES
  888. of authenticated attributes.
  889. PCCERT_CHAIN_CONTEXT pChainContext - Chain context.
  890. DWORD dwCurrentSafety - Current safety setting.
  891. Remark : This method is not part of the COM interface (it is a normal C++
  892. member function). We need it to initialize the object created
  893. internally by us.
  894. Since it is only a normal C++ member function, this function can
  895. only be called from a C++ class pointer, not an interface pointer.
  896. ------------------------------------------------------------------------------*/
  897. STDMETHODIMP CSigner::Init (PCCERT_CONTEXT pCertContext,
  898. CRYPT_ATTRIBUTES * pAuthAttrs,
  899. PCCERT_CHAIN_CONTEXT pChainContext,
  900. DWORD dwCurrentSafety)
  901. {
  902. HRESULT hr = S_OK;
  903. CComPtr<ICertificate2> pICertificate = NULL;
  904. CComPtr<IAttributes> pIAttributes = NULL;
  905. CComPtr<IChain> pIChain = NULL;
  906. DebugTrace("Entering CSigner::Init().\n");
  907. //
  908. // Sanity check.
  909. //
  910. ATLASSERT(pCertContext);
  911. ATLASSERT(pAuthAttrs);
  912. //
  913. // Create the embeded ICertificate2 object.
  914. //
  915. if (FAILED(hr = ::CreateCertificateObject(pCertContext, dwCurrentSafety, &pICertificate)))
  916. {
  917. DebugTrace("Error [%#x]: CreateCertificateObject() failed.\n", hr);
  918. goto ErrorExit;
  919. }
  920. //
  921. // Create the embeded IAttributes collection object.
  922. //
  923. if (FAILED(hr = ::CreateAttributesObject(pAuthAttrs, &pIAttributes)))
  924. {
  925. DebugTrace("Error [%#x]: CreateAttributesObject() failed.\n", hr);
  926. goto ErrorExit;
  927. }
  928. //
  929. // Created the embeded IChain object if available.
  930. //
  931. if (pChainContext)
  932. {
  933. if (FAILED(hr = ::CreateChainObject(pChainContext, &pIChain)))
  934. {
  935. DebugTrace("Error [%#x]: CreateChainObject() failed.\n", hr);
  936. goto ErrorExit;
  937. }
  938. }
  939. //
  940. // Reset.
  941. //
  942. m_pICertificate = pICertificate;
  943. m_pIAttributes = pIAttributes;
  944. m_pIChain = pIChain;
  945. m_dwCurrentSafety = dwCurrentSafety;
  946. CommonExit:
  947. DebugTrace("Leaving CSigner::Init().\n");
  948. return hr;
  949. ErrorExit:
  950. //
  951. // Sanity check.
  952. //
  953. ATLASSERT(FAILED(hr));
  954. goto CommonExit;
  955. }