Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1327 lines
35 KiB

  1. //+---------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1997-2001.
  5. //
  6. // File: Certifct.cpp
  7. //
  8. // Contents: Implementation of CCertmgrApp and DLL registration.
  9. //
  10. //----------------------------------------------------------------------------
  11. #include "stdafx.h"
  12. #include "Certifct.h"
  13. #ifdef _DEBUG
  14. #ifndef ALPHA
  15. #define new DEBUG_NEW
  16. #endif
  17. #undef THIS_FILE
  18. static char THIS_FILE[] = __FILE__;
  19. #endif
  20. USE_HANDLE_MACROS("CERTMGR(Certifct.cpp)")
  21. /////////////////////////////////////////////////////////////////////////////
  22. //
  23. const int FIELD_ISSUER_ALT_NAME = 0x00000001;
  24. const int FIELD_SUBJECT_ALT_NAME = 0x00000002;
  25. const int FIELD_CAN_DELETE = 0x00000004;
  26. const int FIELD_IS_ARCHIVED = 0x00000008;
  27. const int FIELD_TEMPLATE_NAME = 0x00000010;
  28. CCertificate::CCertificate(const PCCERT_CONTEXT pCertContext, CCertStore* pCertStore)
  29. : CCertMgrCookie (CERTMGR_CERTIFICATE),
  30. m_pCertContext (::CertDuplicateCertificateContext (pCertContext)),
  31. m_pCertInfo (0),
  32. m_fieldChecked (0),
  33. m_pCertStore (pCertStore),
  34. m_bCanDelete (false),
  35. m_bIsArchived (false)
  36. {
  37. // _TRACE (1, L"Entering CCertificate::CCertificate\n");
  38. ASSERT (CERTMGR_CERTIFICATE == m_objecttype);
  39. ASSERT (m_pCertStore);
  40. if ( m_pCertStore )
  41. m_pCertStore->AddRef ();
  42. ASSERT (m_pCertContext);
  43. if ( m_pCertContext )
  44. m_pCertInfo = m_pCertContext->pCertInfo;
  45. // _TRACE (-1, L"Leaving CCertificate::CCertificate\n");
  46. }
  47. CCertificate::~CCertificate()
  48. {
  49. // _TRACE (1, L"Entering CCertificate::~CCertificate\n");
  50. ASSERT (CERTMGR_CERTIFICATE == m_objecttype);
  51. if ( m_pCertContext )
  52. ::CertFreeCertificateContext (m_pCertContext);
  53. if ( m_pCertStore )
  54. m_pCertStore->Release ();
  55. // _TRACE (-1, L"Leaving CCertificate::~CCertificate\n");
  56. }
  57. CString CCertificate::GetFriendlyName ()
  58. {
  59. // _TRACE (1, L"Entering CCertificate::GetFriendlyName\n");
  60. ASSERT (CERTMGR_CERTIFICATE == m_objecttype);
  61. ASSERT (m_pCertContext);
  62. if ( m_pCertContext && m_szFriendlyName.IsEmpty () )
  63. {
  64. AFX_MANAGE_STATE (AfxGetStaticModuleState ());
  65. DWORD cbData = 0;
  66. BOOL bResult = ::CertGetCertificateContextProperty (
  67. m_pCertContext,
  68. CERT_FRIENDLY_NAME_PROP_ID,
  69. NULL,
  70. &cbData);
  71. if ( bResult )
  72. {
  73. LPWSTR pszName = new WCHAR[cbData];
  74. if ( pszName )
  75. {
  76. ::ZeroMemory (pszName, cbData*sizeof (WCHAR));
  77. bResult = ::CertGetCertificateContextProperty (
  78. m_pCertContext,
  79. CERT_FRIENDLY_NAME_PROP_ID,
  80. pszName,
  81. &cbData);
  82. ASSERT (bResult);
  83. if ( bResult )
  84. {
  85. m_szFriendlyName = pszName;
  86. }
  87. else
  88. {
  89. VERIFY (m_szFriendlyName.LoadString (IDS_NOT_AVAILABLE));
  90. }
  91. delete [] pszName;
  92. }
  93. }
  94. else
  95. {
  96. if ( GetLastError () == CRYPT_E_NOT_FOUND )
  97. {
  98. VERIFY (m_szFriendlyName.LoadString (IDS_NONE));
  99. }
  100. else
  101. {
  102. ASSERT (0);
  103. VERIFY (m_szFriendlyName.LoadString (IDS_NOT_AVAILABLE));
  104. }
  105. }
  106. }
  107. // _TRACE (-1, L"Leaving CCertificate::GetFriendlyName\n");
  108. return m_szFriendlyName;
  109. }
  110. CString CCertificate::GetIssuerName ()
  111. {
  112. // _TRACE (1, L"Entering CCertificate::GetIssuerName\n");
  113. ASSERT (CERTMGR_CERTIFICATE == m_objecttype);
  114. ASSERT (m_pCertInfo);
  115. if ( m_pCertInfo )
  116. {
  117. // Decode issuer name if not already present
  118. if ( m_szIssuerName.IsEmpty () )
  119. {
  120. m_szIssuerName = ::GetNameString (m_pCertContext, CERT_NAME_ISSUER_FLAG);
  121. }
  122. }
  123. else
  124. return _T("");
  125. // _TRACE (-1, L"Leaving CCertificate::GetIssuerName\n");
  126. return m_szIssuerName;
  127. }
  128. ///////////////////////////////////////////////////////////////////////////
  129. // GetSubjectName ()
  130. //
  131. // pszName (IN / OPTIONAL) - returns the alternate issuer name. An empty
  132. // string is a valid return value
  133. // cbName (IN / OUT) - If pszName is NULL, then the required length
  134. // of pszName is returned.
  135. // Otherwise, contains the length of pszName.
  136. ///////////////////////////////////////////////////////////////////////////
  137. CString CCertificate::GetSubjectName()
  138. {
  139. // _TRACE (1, L"Entering CCertificate::GetSubjectName\n");
  140. ASSERT (CERTMGR_CERTIFICATE == m_objecttype);
  141. ASSERT (m_pCertInfo);
  142. if ( m_pCertInfo )
  143. {
  144. // Decode subject name if not already present
  145. if ( m_szSubjectName.IsEmpty () )
  146. {
  147. m_szSubjectName = ::GetNameString (m_pCertContext, 0);
  148. }
  149. }
  150. else
  151. return _T("");
  152. // _TRACE (-1, L"Leaving CCertificate::GetSubjectName\n");
  153. return m_szSubjectName;
  154. }
  155. ///////////////////////////////////////////////////////////////////////////
  156. // GetValidNotBefore ()
  157. //
  158. // pszDateTime (IN / OPTIONAL) - returns the formatted date and time.
  159. // cbDateTime (IN / OUT) - If pszDateTime is NULL, then the required length
  160. // of pszDateTime is returned.
  161. // Otherwise, contains the length of pszDateTime.
  162. ///////////////////////////////////////////////////////////////////////////
  163. CString CCertificate::GetValidNotBefore()
  164. {
  165. // _TRACE (1, L"Entering CCertificate::GetValidNotBefore\n");
  166. ASSERT (CERTMGR_CERTIFICATE == m_objecttype);
  167. ASSERT (m_pCertInfo);
  168. if ( m_pCertInfo )
  169. {
  170. // Format date/time string if not already present
  171. if ( m_szValidNotBefore.IsEmpty () )
  172. {
  173. HRESULT hResult = FormatDate (m_pCertInfo->NotBefore, m_szValidNotBefore);
  174. if ( !SUCCEEDED (hResult) )
  175. return _T("");
  176. }
  177. }
  178. else
  179. return _T("");
  180. // _TRACE (-1, L"Leaving CCertificate::GetValidNotBefore\n");
  181. return m_szValidNotBefore;
  182. }
  183. ///////////////////////////////////////////////////////////////////////////
  184. // GetValidNotAfter ()
  185. //
  186. // pszDateTime (IN / OPTIONAL) - returns the formatted date and time.
  187. // cbDateTime (IN / OUT) - If pszDateTime is NULL, then the required length
  188. // of pszDateTime is returned.
  189. // Otherwise, contains the length of pszDateTime.
  190. ///////////////////////////////////////////////////////////////////////////
  191. CString CCertificate::GetValidNotAfter ()
  192. {
  193. // _TRACE (1, L"Entering CCertificate::GetValidNotAfter\n");
  194. ASSERT (CERTMGR_CERTIFICATE == m_objecttype);
  195. ASSERT (m_pCertInfo);
  196. if ( m_pCertInfo )
  197. {
  198. // Format date/time string if not already present
  199. if ( m_szValidNotAfter.IsEmpty () )
  200. {
  201. HRESULT hResult = FormatDate (m_pCertInfo->NotAfter, m_szValidNotAfter);
  202. if ( !SUCCEEDED (hResult) )
  203. m_szValidNotAfter = _T("");
  204. }
  205. }
  206. else
  207. m_szValidNotAfter = _T("");
  208. // _TRACE (-1, L"Leaving CCertificate::GetValidNotAfter\n");
  209. return m_szValidNotAfter;
  210. }
  211. CString CCertificate::GetEnhancedKeyUsage ()
  212. {
  213. // _TRACE (1, L"Entering CCertificate::GetEnhancedKeyUsage\n");
  214. ASSERT (CERTMGR_CERTIFICATE == m_objecttype);
  215. ASSERT (m_pCertInfo);
  216. if ( m_pCertInfo )
  217. {
  218. // Format date/time string if not already present
  219. if ( m_szEnhancedKeyUsage.IsEmpty () )
  220. {
  221. FormatEnhancedKeyUsagePropertyString (
  222. m_szEnhancedKeyUsage);
  223. }
  224. }
  225. else
  226. m_szEnhancedKeyUsage = _T("");
  227. // _TRACE (-1, L"Leaving CCertificate::GetEnhancedKeyUsage\n");
  228. return m_szEnhancedKeyUsage;
  229. }
  230. bool CCertificate::FormatEnhancedKeyUsagePropertyString (CString& string)
  231. {
  232. // _TRACE (1, L"Entering CCertificate::FormatEnhancedKeyUsagePropertyString\n");
  233. AFX_MANAGE_STATE(AfxGetStaticModuleState());
  234. ASSERT (CERTMGR_CERTIFICATE == m_objecttype);
  235. BOOL bReturn = TRUE;
  236. DWORD cbUsage = 0;
  237. bReturn = ::CertGetEnhancedKeyUsage (m_pCertContext, 0, // get extension and property
  238. NULL, &cbUsage);
  239. if ( bReturn )
  240. {
  241. CString usageName;
  242. PCERT_ENHKEY_USAGE pUsage = (PCERT_ENHKEY_USAGE) ::LocalAlloc (LPTR, cbUsage);
  243. if ( pUsage )
  244. {
  245. bReturn = ::CertGetEnhancedKeyUsage (m_pCertContext, 0, // get extension and property
  246. pUsage, &cbUsage);
  247. if ( bReturn )
  248. {
  249. if ( !pUsage->cUsageIdentifier )
  250. {
  251. switch (GetLastError ())
  252. {
  253. case CRYPT_E_NOT_FOUND:
  254. VERIFY (string.LoadString (IDS_ANY));
  255. break;
  256. case 0:
  257. VERIFY (string.LoadString (IDS_NONE));
  258. break;
  259. default:
  260. break;
  261. }
  262. }
  263. else
  264. {
  265. for (DWORD dwIndex = 0; dwIndex < pUsage->cUsageIdentifier; dwIndex++)
  266. {
  267. if ( MyGetOIDInfo (usageName, pUsage->rgpszUsageIdentifier[dwIndex]) )
  268. {
  269. // add delimeter if not first iteration
  270. if ( dwIndex )
  271. string += _T(", ");
  272. string += usageName;
  273. }
  274. }
  275. }
  276. }
  277. else
  278. {
  279. switch (GetLastError ())
  280. {
  281. case CRYPT_E_NOT_FOUND:
  282. VERIFY (string.LoadString (IDS_ANY));
  283. break;
  284. case 0:
  285. VERIFY (string.LoadString (IDS_NONE));
  286. break;
  287. default:
  288. break;
  289. }
  290. }
  291. ::LocalFree (pUsage);
  292. }
  293. else
  294. {
  295. bReturn = FALSE;
  296. }
  297. }
  298. else
  299. {
  300. switch (GetLastError ())
  301. {
  302. case CRYPT_E_NOT_FOUND:
  303. VERIFY (string.LoadString (IDS_ANY));
  304. break;
  305. case 0:
  306. VERIFY (string.LoadString (IDS_NONE));
  307. break;
  308. default:
  309. break;
  310. }
  311. }
  312. // _TRACE (-1, L"Leaving CCertificate::FormatEnhancedKeyUsagePropertyString\n");
  313. return bReturn ? true : false;
  314. }
  315. ///////////////////////////////////////////////////////////////////////////
  316. // GetAlternateIssuerName ()
  317. //
  318. // pszName (IN / OPTIONAL) - returns the alternate issuer name. An empty
  319. // string is a valid return value
  320. // cbName (IN / OUT) - If pszName is NULL, then the required length
  321. // of pszName is returned.
  322. // Otherwise, contains the length of pszName.
  323. ///////////////////////////////////////////////////////////////////////////
  324. CString CCertificate::GetAlternateIssuerName ()
  325. {
  326. // _TRACE (1, L"Entering CCertificate::GetAlternateIssuerName\n");
  327. ASSERT (CERTMGR_CERTIFICATE == m_objecttype);
  328. ASSERT (m_pCertInfo);
  329. if ( m_pCertInfo )
  330. {
  331. if ( !(m_fieldChecked & FIELD_ISSUER_ALT_NAME) )
  332. {
  333. HRESULT hResult = ConvertAltNameToString (_T(szOID_ISSUER_ALT_NAME),
  334. CERT_ALT_NAME_URL, m_szAltIssuerName);
  335. ASSERT (SUCCEEDED (hResult));
  336. if ( !SUCCEEDED (hResult) )
  337. m_szAltIssuerName = _T("");
  338. m_fieldChecked |= FIELD_ISSUER_ALT_NAME;
  339. }
  340. }
  341. else
  342. m_szAltIssuerName = _T("");
  343. // _TRACE (-1, L"Leaving CCertificate::GetAlternateIssuerName\n");
  344. return m_szAltIssuerName;
  345. }
  346. ///////////////////////////////////////////////////////////////////////////
  347. // GetAlternateSubjectName ()
  348. //
  349. // pszName (IN / OPTIONAL) - returns the alternate issuer name. An empty
  350. // string is a valid return value
  351. // cbName (IN / OUT) - If pszName is NULL, then the required length
  352. // of pszName is returned.
  353. // Otherwise, contains the length of pszName.
  354. ///////////////////////////////////////////////////////////////////////////
  355. CString CCertificate::GetAlternateSubjectName ()
  356. {
  357. // _TRACE (1, L"Entering CCertificate::GetAlternateSubjectName\n");
  358. ASSERT (CERTMGR_CERTIFICATE == m_objecttype);
  359. ASSERT (m_pCertInfo);
  360. if ( m_pCertInfo )
  361. {
  362. if ( !(m_fieldChecked & FIELD_SUBJECT_ALT_NAME) )
  363. {
  364. HRESULT hResult = ConvertAltNameToString (_T(szOID_SUBJECT_ALT_NAME),
  365. CERT_ALT_NAME_URL, m_szAltSubjectName);
  366. if ( !SUCCEEDED (hResult) )
  367. m_szAltSubjectName = _T("");
  368. m_fieldChecked |= FIELD_SUBJECT_ALT_NAME;
  369. }
  370. }
  371. else
  372. m_szAltSubjectName = _T("");
  373. // _TRACE (-1, L"Leaving CCertificate::GetAlternateSubjectName\n");
  374. return m_szAltSubjectName;
  375. }
  376. ///////////////////////////////////////////////////////////////////////////
  377. // GetSerialNumber ()
  378. //
  379. // pszSerNum (IN / OPTIONAL) - returns the alternate issuer name. An empty
  380. // string is a valid return value
  381. // cbSerNum (IN / OUT) - If pszSerNum is NULL, then the required length
  382. // of pszSerNum is returned.
  383. // Otherwise, contains the length of pszSerNum.
  384. ///////////////////////////////////////////////////////////////////////////
  385. CString CCertificate::GetSerialNumber ()
  386. {
  387. // _TRACE (1, L"Entering CCertificate::GetSerialNumber\n");
  388. ASSERT (CERTMGR_CERTIFICATE == m_objecttype);
  389. ASSERT (m_pCertInfo);
  390. if ( m_pCertInfo )
  391. {
  392. // Decode issuer name if not already present
  393. if ( m_szSerNum.IsEmpty () )
  394. {
  395. LPWSTR pwszText = 0;
  396. if ( SUCCEEDED (FormatSerialNoString (&pwszText, & (m_pCertInfo->SerialNumber))) )
  397. {
  398. m_szSerNum = pwszText;
  399. CoTaskMemFree (pwszText);
  400. }
  401. }
  402. }
  403. else
  404. m_szSerNum = _T("");
  405. // _TRACE (-1, L"Leaving CCertificate::GetSerialNumber\n");
  406. return m_szSerNum;
  407. }
  408. //////////////////////////////////////////////////////////////////////////////
  409. // ConvertAltNameToString ()
  410. //
  411. // szOID (IN) - The OID of the alternate name to retrieve
  412. // dwNameChoice (IN) - The type of alternate name to return
  413. // altName (OUT) - The version of the desired alternate name indicated
  414. // by dwNameChoice
  415. //////////////////////////////////////////////////////////////////////////////
  416. HRESULT CCertificate::ConvertAltNameToString(LPCWSTR szOID, const DWORD dwNameChoice, CString & altName)
  417. {
  418. // _TRACE (1, L"Entering CCertificate::ConvertAltNameToString\n");
  419. ASSERT (CERTMGR_CERTIFICATE == m_objecttype);
  420. HRESULT hResult = S_OK;
  421. // Iterate through the extensions until the one indicated by the
  422. // passed-in szOID is found.
  423. for (DWORD index = 0; index < m_pCertInfo->cExtension; index++)
  424. {
  425. ASSERT (m_pCertInfo->rgExtension);
  426. size_t len = strlen (m_pCertInfo->rgExtension[index].pszObjId);
  427. LPWSTR wcsObjId = new WCHAR[len];
  428. if ( wcsObjId )
  429. {
  430. ::ZeroMemory (wcsObjId, len * sizeof (WCHAR));
  431. mbstowcs (wcsObjId, m_pCertInfo->rgExtension[index].pszObjId, len);
  432. if ( !wcscmp (wcsObjId, szOID) )
  433. {
  434. CERT_ALT_NAME_INFO nameInfo;
  435. DWORD cbNameInfo = sizeof (CERT_ALT_NAME_INFO);
  436. BOOL bResult = CryptDecodeObject(
  437. MY_ENCODING_TYPE,
  438. X509_ALTERNATE_NAME, // in
  439. m_pCertInfo->rgExtension[index].Value.pbData, // in
  440. m_pCertInfo->rgExtension[index].Value.cbData, // in
  441. 0, // in
  442. (void *) &nameInfo, // out
  443. &cbNameInfo); // in/out
  444. ASSERT (bResult);
  445. if ( bResult )
  446. {
  447. // We've found the right extension, now iterate through
  448. // the alternate names until we find the desired type.
  449. for (DWORD dwAltEntryIndex = 0; dwAltEntryIndex < nameInfo.cAltEntry; dwAltEntryIndex++)
  450. {
  451. if ( nameInfo.rgAltEntry[dwAltEntryIndex].dwAltNameChoice ==
  452. dwNameChoice )
  453. {
  454. altName = nameInfo.rgAltEntry[dwAltEntryIndex].pwszURL;
  455. break;
  456. }
  457. }
  458. }
  459. else
  460. hResult = E_UNEXPECTED;
  461. break;
  462. }
  463. delete [] wcsObjId;
  464. }
  465. else
  466. {
  467. hResult = E_OUTOFMEMORY;
  468. }
  469. }
  470. // _TRACE (-1, L"Leaving CCertificate::ConvertAltNameToString\n");
  471. return hResult;
  472. }
  473. VOID CCertificate::DataToHex(PBYTE pSrc, CString & dest, int cb, bool bIncludeSpaces)
  474. {
  475. // _TRACE (1, L"Entering CCertificate::DataToHex\n");
  476. ASSERT (CERTMGR_CERTIFICATE == m_objecttype);
  477. unsigned char ch = 0;
  478. TCHAR szDest[3];
  479. UINT uLen = 0;
  480. dest.Empty ();
  481. while (cb-- > 0)
  482. {
  483. #pragma warning (once: 4244)
  484. ch = 0x00FF & (unsigned char) (*pSrc++);
  485. wsprintf(szDest, _T("%02X"), ch);
  486. dest += szDest;
  487. uLen++;
  488. if ( bIncludeSpaces && !(uLen % 2) && cb )
  489. dest += _T(" ");
  490. }
  491. // _TRACE (-1, L"Leaving CCertificate::DataToHex\n");
  492. }
  493. CCertStore* CCertificate::GetCertStore() const
  494. {
  495. // _TRACE (0, L"Entering and leaving CCertificate::GetCertStore\n");
  496. ASSERT (CERTMGR_CERTIFICATE == m_objecttype);
  497. return m_pCertStore;
  498. }
  499. PCCERT_CONTEXT CCertificate::GetCertContext() const
  500. {
  501. // _TRACE (0, L"Entering and leaving CCertificate::GetCertContext\n");
  502. ASSERT (CERTMGR_CERTIFICATE == m_objecttype);
  503. return m_pCertContext;
  504. }
  505. bool CCertificate::IsValid()
  506. {
  507. // _TRACE (1, L"Entering CCertificate::IsValid\n");
  508. ASSERT (CERTMGR_CERTIFICATE == m_objecttype);
  509. bool bIsValid = false;
  510. ASSERT (m_pCertInfo);
  511. if ( m_pCertInfo )
  512. {
  513. FILETIME systemTime;
  514. ::GetSystemTimeAsFileTime (&systemTime);
  515. LONG lBefore = ::CompareFileTime (&m_pCertInfo->NotBefore, &systemTime);
  516. LONG lAfter = ::CompareFileTime (&systemTime, &m_pCertInfo->NotAfter);
  517. if ( lBefore < 1 && lAfter < 1 )
  518. bIsValid = true;
  519. }
  520. // _TRACE (-1, L"Leaving CCertificate::IsValid\n");
  521. return bIsValid;
  522. }
  523. const SPECIAL_STORE_TYPE CCertificate::GetStoreType () const
  524. {
  525. // _TRACE (0, L"Entering and leaving CCertificate::GetStoreType\n");
  526. ASSERT (CERTMGR_CERTIFICATE == m_objecttype);
  527. if ( m_pCertStore )
  528. return m_pCertStore->GetStoreType ();
  529. else
  530. return NO_SPECIAL_TYPE;
  531. }
  532. void CCertificate::Refresh()
  533. {
  534. // _TRACE (1, L"Entering CCertificate::Refresh\n");
  535. ASSERT (CERTMGR_CERTIFICATE == m_objecttype);
  536. // Clearing all fields forces rereading of the data.
  537. m_szAltIssuerName = L"";
  538. m_szAltSubjectName = L"";
  539. m_szAuthorityKeyID = L"";
  540. m_szEnhancedKeyUsage = L"";
  541. m_szFriendlyName = L"";
  542. m_szIssuerName = L"";
  543. m_szMD5Hash = L"";
  544. m_szPolicyURL = L"";
  545. m_szSerNum = L"";
  546. m_szSHAHash = L"";
  547. m_szSubjectKeyID = L"";
  548. m_szSubjectName = L"";
  549. m_szValidNotAfter = L"";
  550. m_szValidNotBefore = L"";
  551. m_fieldChecked = 0;
  552. // _TRACE (-1, L"Leaving CCertificate::Refresh\n");
  553. }
  554. CString CCertificate::GetMD5Hash()
  555. {
  556. // _TRACE (1, L"Entering CCertificate::GetMD5Hash\n");
  557. ASSERT (CERTMGR_CERTIFICATE == m_objecttype);
  558. ASSERT (m_pCertContext);
  559. if ( m_pCertContext && m_szMD5Hash.IsEmpty ())
  560. {
  561. m_szMD5Hash = GetGenericHash (CERT_MD5_HASH_PROP_ID);
  562. }
  563. // _TRACE (-1, L"Leaving CCertificate::GetMD5Hash\n");
  564. return m_szMD5Hash;
  565. }
  566. CString CCertificate::GetSHAHash()
  567. {
  568. // _TRACE (1, L"Entering CCertificate::GetSHAHash\n");
  569. ASSERT (CERTMGR_CERTIFICATE == m_objecttype);
  570. ASSERT (m_pCertContext);
  571. if ( m_pCertContext && m_szSHAHash.IsEmpty ())
  572. {
  573. m_szSHAHash = GetGenericHash (CERT_SHA1_HASH_PROP_ID);
  574. }
  575. // _TRACE (-1, L"Leaving CCertificate::GetSHAHash\n");
  576. return m_szSHAHash;
  577. }
  578. CString CCertificate::GetGenericHash(DWORD dwPropId)
  579. {
  580. // _TRACE (1, L"Entering CCertificate::GetGenericHash\n");
  581. ASSERT (CERTMGR_CERTIFICATE == m_objecttype);
  582. CString szHash;
  583. DWORD cbData = 0;
  584. BOOL bReturn = ::CertGetCertificateContextProperty (
  585. m_pCertContext,
  586. dwPropId,
  587. NULL,
  588. &cbData);
  589. if ( bReturn )
  590. {
  591. cbData += 2; // for null terminator
  592. BYTE* pCertHash = new BYTE[cbData];
  593. if ( pCertHash )
  594. {
  595. ::ZeroMemory (pCertHash, cbData);
  596. bReturn = CertGetCertificateContextProperty (
  597. m_pCertContext,
  598. dwPropId,
  599. pCertHash,
  600. &cbData);
  601. ASSERT (bReturn);
  602. if ( bReturn )
  603. {
  604. DataToHex (pCertHash, szHash, cbData, false);
  605. }
  606. delete [] pCertHash;
  607. }
  608. }
  609. // _TRACE (-1, L"Leaving CCertificate::GetGenericHash\n");
  610. return szHash;
  611. }
  612. int CCertificate::CompareExpireDate(const CCertificate & cert) const
  613. {
  614. // _TRACE (1, L"Entering CCertificate::CompareExpireDate\n");
  615. ASSERT (CERTMGR_CERTIFICATE == m_objecttype);
  616. int compVal = 0;
  617. ASSERT (m_pCertInfo && cert.m_pCertInfo);
  618. if ( m_pCertInfo && cert.m_pCertInfo )
  619. {
  620. compVal = ::CompareFileTime (&m_pCertInfo->NotAfter,
  621. &cert.m_pCertInfo->NotAfter);
  622. }
  623. // _TRACE (-1, L"Leaving CCertificate::CompareExpireDate\n");
  624. return compVal;
  625. }
  626. bool CCertificate::CanDelete()
  627. {
  628. // _TRACE (1, L"Entering CCertificate::CanDelete\n");
  629. if ( m_pCertContext && !(m_fieldChecked & FIELD_CAN_DELETE) )
  630. {
  631. DWORD dwAccessFlags = 0;
  632. DWORD cbData = sizeof (DWORD);
  633. BOOL bResult = ::CertGetCertificateContextProperty (
  634. m_pCertContext,
  635. CERT_ACCESS_STATE_PROP_ID,
  636. &dwAccessFlags,
  637. &cbData);
  638. if ( bResult )
  639. {
  640. if ( dwAccessFlags & CERT_ACCESS_STATE_WRITE_PERSIST_FLAG )
  641. m_bCanDelete = true;
  642. }
  643. m_fieldChecked |= FIELD_CAN_DELETE;
  644. }
  645. // _TRACE (-1, L"Leaving CCertificate::CanDelete\n");
  646. return m_bCanDelete;
  647. }
  648. bool CCertificate::IsReadOnly()
  649. {
  650. bool bResult = false;
  651. if ( m_pCertStore )
  652. bResult = (m_pCertStore->IsReadOnly () || !CanDelete ());
  653. return bResult;
  654. }
  655. bool CCertificate::IsArchived()
  656. {
  657. // _TRACE (1, L"Entering CCertificate::IsArchived\n");
  658. if ( m_pCertContext && !(m_fieldChecked & FIELD_IS_ARCHIVED) )
  659. {
  660. DWORD cbData = sizeof (DWORD);
  661. BOOL bResult = ::CertGetCertificateContextProperty (
  662. m_pCertContext,
  663. CERT_ARCHIVED_PROP_ID,
  664. NULL,
  665. &cbData);
  666. if ( bResult )
  667. {
  668. m_bIsArchived = true;
  669. }
  670. else
  671. m_bIsArchived = false;
  672. m_fieldChecked |= FIELD_IS_ARCHIVED;
  673. }
  674. // _TRACE (-1, L"Leaving CCertificate::IsArchived\n");
  675. return m_bIsArchived;
  676. }
  677. BOOL CCertificate::DeleteFromStore(bool bDoCommit)
  678. {
  679. _TRACE (1, L"Entering CCertificate::DeleteFromStore\n");
  680. BOOL bResult = FALSE;
  681. if ( m_pCertStore )
  682. {
  683. PCCERT_CONTEXT pCertContext = GetNewCertContext ();
  684. if ( pCertContext )
  685. {
  686. bResult = ::CertDeleteCertificateFromStore (pCertContext);
  687. if ( bResult )
  688. {
  689. m_pCertStore->InvalidateCertCount ();
  690. m_pCertStore->SetDirty ();
  691. if ( bDoCommit )
  692. {
  693. HRESULT hr = m_pCertStore->Commit ();
  694. if ( SUCCEEDED (hr) )
  695. m_pCertStore->Resync ();
  696. else
  697. bResult = FALSE;
  698. }
  699. m_pCertStore->Release ();
  700. m_pCertStore = 0;
  701. }
  702. }
  703. }
  704. _TRACE (-1, L"Leaving CCertificate::DeleteFromStore\n");
  705. return bResult;
  706. }
  707. PCCERT_CONTEXT CCertificate::GetNewCertContext()
  708. {
  709. PCCERT_CONTEXT pCertContext = 0;
  710. if ( m_pCertStore )
  711. {
  712. HCERTSTORE hCertStore = m_pCertStore->GetStoreHandle ();
  713. if ( hCertStore )
  714. {
  715. DWORD cbData = 20;
  716. BYTE certHash[20];
  717. BOOL bReturn = ::CertGetCertificateContextProperty (
  718. m_pCertContext,
  719. CERT_SHA1_HASH_PROP_ID,
  720. &certHash,
  721. &cbData);
  722. ASSERT (bReturn);
  723. if ( bReturn )
  724. {
  725. CRYPT_DATA_BLOB blob = {sizeof (certHash), certHash};
  726. pCertContext = CertFindCertificateInStore(
  727. hCertStore,
  728. 0,
  729. 0,
  730. CERT_FIND_SHA1_HASH,
  731. &blob,
  732. 0);
  733. if ( pCertContext )
  734. {
  735. ::CertFreeCertificateContext (m_pCertContext);
  736. m_pCertContext = ::CertDuplicateCertificateContext (pCertContext);
  737. }
  738. }
  739. }
  740. }
  741. return pCertContext;
  742. }
  743. CString CCertificate::FormatStatus()
  744. {
  745. CString status;
  746. status.FormatMessage (L"%1 %2",
  747. (IsReadOnly () ? L"R" : L" "),
  748. (IsArchived () ? L"A" : L" "));
  749. return status;
  750. }
  751. //////////////////////////////////////////////////////////////////////////////////////
  752. // Stolen from private\ispu\ui\cryptui\frmtutil.cpp
  753. //////////////////////////////////////////////////////////////////////////////////////
  754. const WCHAR RgwchHex[] = {'0', '1', '2', '3', '4', '5', '6', '7',
  755. '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'};
  756. HRESULT CCertificate::FormatSerialNoString(LPWSTR *ppString, CRYPT_INTEGER_BLOB const *pblob)
  757. {
  758. if ( !ppString || !pblob )
  759. return E_POINTER;
  760. DWORD i = 0;
  761. LPBYTE pb;
  762. DWORD numCharsInserted = 0;
  763. //
  764. // calculate size needed
  765. //
  766. pb = &pblob->pbData[pblob->cbData-1];
  767. while (pb >= &pblob->pbData[0])
  768. {
  769. if (numCharsInserted == 4)
  770. {
  771. i += sizeof(WCHAR);
  772. numCharsInserted = 0;
  773. }
  774. else
  775. {
  776. i += 2 * sizeof(WCHAR);
  777. pb--;
  778. numCharsInserted += 2;
  779. }
  780. }
  781. if (NULL == (*ppString = (LPWSTR) CoTaskMemAlloc (i+sizeof(WCHAR))))
  782. {
  783. return E_OUTOFMEMORY;
  784. }
  785. // fill the buffer
  786. i=0;
  787. numCharsInserted = 0;
  788. pb = &pblob->pbData[pblob->cbData-1];
  789. while (pb >= &pblob->pbData[0])
  790. {
  791. if (numCharsInserted == 4)
  792. {
  793. (*ppString)[i++] = L' ';
  794. numCharsInserted = 0;
  795. }
  796. else
  797. {
  798. (*ppString)[i++] = RgwchHex[(*pb & 0xf0) >> 4];
  799. (*ppString)[i++] = RgwchHex[*pb & 0x0f];
  800. pb--;
  801. numCharsInserted += 2;
  802. }
  803. }
  804. (*ppString)[i] = 0;
  805. return S_OK;
  806. }
  807. CString CCertificate::GetDescription()
  808. {
  809. ASSERT (CERTMGR_CERTIFICATE == m_objecttype);
  810. if ( m_pCertContext && m_szDescription.IsEmpty () )
  811. {
  812. AFX_MANAGE_STATE (AfxGetStaticModuleState ());
  813. DWORD cbData = 0;
  814. BOOL bResult = ::CertGetCertificateContextProperty (
  815. m_pCertContext,
  816. CERT_DESCRIPTION_PROP_ID,
  817. NULL,
  818. &cbData);
  819. if ( bResult )
  820. {
  821. LPWSTR pszName = new WCHAR[cbData];
  822. if ( pszName )
  823. {
  824. ::ZeroMemory (pszName, cbData*sizeof (WCHAR));
  825. bResult = ::CertGetCertificateContextProperty (
  826. m_pCertContext,
  827. CERT_DESCRIPTION_PROP_ID,
  828. pszName,
  829. &cbData);
  830. ASSERT (bResult);
  831. if ( bResult )
  832. {
  833. m_szDescription = pszName;
  834. }
  835. delete [] pszName;
  836. }
  837. }
  838. else
  839. {
  840. DWORD dwErr = GetLastError ();
  841. if ( CRYPT_E_NOT_FOUND == dwErr )
  842. {
  843. _TRACE (0, L"CertGetCertificateContextProperty (CERT_DESCRIPTION_PROP_ID) found no description.\n");
  844. }
  845. else
  846. {
  847. _TRACE (0, L"CertGetCertificateContextProperty (CERT_DESCRIPTION_PROP_ID) failed: 0x%x\n", dwErr);
  848. }
  849. }
  850. }
  851. return m_szDescription;
  852. }
  853. HRESULT CCertificate::SetDescription(const CString &szDescription)
  854. {
  855. _TRACE (1, L"Entering CCertificate::SetDescription (%s)\n",
  856. (PCWSTR) szDescription);
  857. HRESULT hr = S_OK;
  858. CRYPT_DATA_BLOB cryptDataBlob;
  859. ::ZeroMemory (&cryptDataBlob, sizeof (CRYPT_DATA_BLOB));
  860. cryptDataBlob.pbData = (LPBYTE) (PCWSTR) szDescription;
  861. cryptDataBlob.cbData = (DWORD) (wcslen (szDescription) + 1) * sizeof (WCHAR);
  862. BOOL bResult = ::CertSetCertificateContextProperty (m_pCertContext,
  863. CERT_DESCRIPTION_PROP_ID, 0, &cryptDataBlob);
  864. ASSERT (bResult);
  865. if ( bResult )
  866. {
  867. m_szDescription = szDescription;
  868. }
  869. else
  870. {
  871. DWORD dwErr = GetLastError ();
  872. _TRACE (0, L"CertSetCertificateContextProperty (CERT_DESCRIPTION_PROP_ID, %s) failed: %d\n",
  873. (PCWSTR) szDescription, dwErr);
  874. hr = HRESULT_FROM_WIN32 (dwErr);
  875. }
  876. _TRACE (1, L"Entering CCertificate::SetDescription (%s): 0x%x\n",
  877. (PCWSTR) szDescription, hr);
  878. return hr;
  879. }
  880. HRESULT CCertificate::SetLastModified ()
  881. {
  882. HRESULT hr = S_OK;
  883. if ( m_pCertContext )
  884. {
  885. SYSTEMTIME st;
  886. FILETIME ft;
  887. GetSystemTime (&st);
  888. VERIFY (SystemTimeToFileTime(&st, &ft));
  889. CRYPT_DATA_BLOB cryptDataBlob;
  890. ::ZeroMemory (&cryptDataBlob, sizeof (CRYPT_DATA_BLOB));
  891. cryptDataBlob.pbData = (LPBYTE) &ft;
  892. cryptDataBlob.cbData = sizeof (FILETIME);
  893. BOOL bResult = ::CertSetCertificateContextProperty (
  894. m_pCertContext,
  895. CERT_DATE_STAMP_PROP_ID, 0, &cryptDataBlob);
  896. ASSERT (bResult);
  897. if ( !bResult )
  898. {
  899. DWORD dwErr = GetLastError ();
  900. _TRACE (0, L"CertSetCertificateContextProperty (CERT_DATE_STAMP_PROP_ID) failed: %d\n",
  901. dwErr);
  902. hr = HRESULT_FROM_WIN32 (dwErr);
  903. }
  904. }
  905. return hr;
  906. }
  907. CString CCertificate::GetShortLastModified ()
  908. {
  909. return GetLastModified (DATE_SHORTDATE);
  910. }
  911. CString CCertificate::GetLongLastModified ()
  912. {
  913. return GetLastModified (DATE_LONGDATE);
  914. }
  915. ///////////////////////////////////////////////////////////////////////////////
  916. //
  917. // Method: GetLastModified
  918. // Purpose: Get the date stamp property of the cert and format for display
  919. // Inputs: dwDateFlags - as defined in SDK, specify DATE_SHORTDATE or
  920. // DATE_LONGDATE
  921. // bRetryIfNotPresent - to prevent stack overflow. Used if the property
  922. // is not set, to set the property to the current time and
  923. // retrieve again.
  924. //
  925. // Output: locale-formatted date and time string
  926. //
  927. ///////////////////////////////////////////////////////////////////////////////
  928. CString CCertificate::GetLastModified(DWORD dwDateFlags, bool bRetryIfNotPresent /* true */)
  929. {
  930. CString szDate;
  931. ASSERT (CERTMGR_CERTIFICATE == m_objecttype);
  932. if ( m_pCertContext )
  933. {
  934. AFX_MANAGE_STATE (AfxGetStaticModuleState ());
  935. FILETIME ft;
  936. DWORD cbData = sizeof (ft);
  937. BOOL bResult = ::CertGetCertificateContextProperty (
  938. m_pCertContext,
  939. CERT_DATE_STAMP_PROP_ID,
  940. &ft,
  941. &cbData);
  942. if ( bResult )
  943. {
  944. VERIFY (SUCCEEDED (FormatDate (ft, szDate, dwDateFlags, true)) );
  945. }
  946. else
  947. {
  948. if ( bRetryIfNotPresent )
  949. {
  950. if ( SUCCEEDED (SetLastModified ()) ) // not present - set the value
  951. {
  952. szDate = GetLastModified (dwDateFlags, false);
  953. CCertStore* pCertStore = GetCertStore ();
  954. if ( pCertStore )
  955. pCertStore->Commit ();
  956. }
  957. }
  958. DWORD dwErr = GetLastError ();
  959. if ( CRYPT_E_NOT_FOUND == dwErr )
  960. {
  961. _TRACE (0, L"CertGetCertificateContextProperty (CERT_DATE_STAMP_PROP_ID) found no property.\n");
  962. }
  963. else
  964. {
  965. _TRACE (0, L"CertGetCertificateContextProperty (CERT_DATE_STAMP_PROP_ID) failed: 0x%x\n", dwErr);
  966. }
  967. }
  968. }
  969. return szDate;
  970. }
  971. HRESULT CCertificate::GetLastModifiedFileTime (FILETIME& ft)
  972. {
  973. HRESULT hr = S_OK;
  974. ASSERT (CERTMGR_CERTIFICATE == m_objecttype);
  975. ASSERT (m_pCertContext);
  976. if ( m_pCertContext )
  977. {
  978. DWORD cbData = sizeof (ft);
  979. BOOL bResult = ::CertGetCertificateContextProperty (
  980. m_pCertContext,
  981. CERT_DATE_STAMP_PROP_ID,
  982. &ft,
  983. &cbData);
  984. if ( !bResult )
  985. {
  986. DWORD dwErr = GetLastError ();
  987. if ( CRYPT_E_NOT_FOUND == dwErr )
  988. {
  989. _TRACE (0, L"CertGetCertificateContextProperty (CERT_DATE_STAMP_PROP_ID) found no property.\n");
  990. }
  991. else
  992. {
  993. _TRACE (0, L"CertGetCertificateContextProperty (CERT_DATE_STAMP_PROP_ID) failed: 0x%x\n", dwErr);
  994. }
  995. hr = HRESULT_FROM_WIN32 (dwErr);
  996. }
  997. }
  998. else
  999. hr = E_FAIL;
  1000. return hr;
  1001. }
  1002. BOOL CCertificate::operator==(CCertificate& rCert)
  1003. {
  1004. if ( GetMD5Hash () == rCert.GetMD5Hash () )
  1005. return TRUE;
  1006. else
  1007. return FALSE;
  1008. }
  1009. // NTRAID# 247237 Cert UI: Cert Snapin: Certificates snapin should show template name
  1010. CString CCertificate::GetTemplateName()
  1011. {
  1012. if ( m_pCertInfo && !(m_fieldChecked & FIELD_TEMPLATE_NAME) )
  1013. {
  1014. // Iterate through the extensions until szOID_CERTIFICATE_TEMPLATE is found.
  1015. for (DWORD index = 0; index < m_pCertInfo->cExtension; index++)
  1016. {
  1017. ASSERT (m_pCertInfo->rgExtension);
  1018. if ( !strcmp (szOID_CERTIFICATE_TEMPLATE, m_pCertInfo->rgExtension[index].pszObjId) )
  1019. {
  1020. m_szTemplateName = DecodeV2TemplateName (&(m_pCertInfo->rgExtension[index]));
  1021. break;
  1022. }
  1023. else if ( !strcmp (szOID_ENROLL_CERTTYPE_EXTENSION, m_pCertInfo->rgExtension[index].pszObjId) )
  1024. {
  1025. m_szTemplateName = DecodeV1TemplateName (&(m_pCertInfo->rgExtension[index]));
  1026. break;
  1027. }
  1028. }
  1029. m_fieldChecked |= FIELD_TEMPLATE_NAME;
  1030. }
  1031. return m_szTemplateName;
  1032. }
  1033. // NTRAID# 247237 Cert UI: Cert Snapin: Certificates snapin should show template name
  1034. CString CCertificate::DecodeV1TemplateName (PCERT_EXTENSION pCertExtension)
  1035. {
  1036. CString szTemplateName;
  1037. ASSERT (pCertExtension);
  1038. if ( pCertExtension )
  1039. {
  1040. DWORD cbValue = 0;
  1041. if ( ::CryptDecodeObject(
  1042. CRYPT_ASN_ENCODING,
  1043. X509_UNICODE_ANY_STRING,
  1044. pCertExtension->Value.pbData,
  1045. pCertExtension->Value.cbData,
  1046. 0,
  1047. 0,
  1048. &cbValue) )
  1049. {
  1050. CERT_NAME_VALUE* pCNValue = (CERT_NAME_VALUE*)
  1051. ::LocalAlloc(LPTR, cbValue);
  1052. if ( pCNValue )
  1053. {
  1054. if ( ::CryptDecodeObject(
  1055. CRYPT_ASN_ENCODING,
  1056. X509_UNICODE_ANY_STRING,
  1057. pCertExtension->Value.pbData,
  1058. pCertExtension->Value.cbData,
  1059. 0,
  1060. pCNValue,
  1061. &cbValue) )
  1062. {
  1063. szTemplateName = (LPWSTR) pCNValue->Value.pbData;
  1064. // NTRAID# 395173 Certificates Snapin:The column "
  1065. // Certificate Template" should contain value of "Template
  1066. // Name" for V1 templates
  1067. HCERTTYPE hCertType = 0;
  1068. HRESULT hr = CAFindCertTypeByName (szTemplateName,
  1069. NULL,
  1070. CT_ENUM_MACHINE_TYPES | CT_ENUM_USER_TYPES,
  1071. &hCertType);
  1072. if ( SUCCEEDED (hr) )
  1073. {
  1074. PWSTR* rgwszProp = 0;
  1075. hr = CAGetCertTypePropertyEx (hCertType,
  1076. CERTTYPE_PROP_FRIENDLY_NAME, &rgwszProp);
  1077. if ( SUCCEEDED (hr) && rgwszProp )
  1078. {
  1079. szTemplateName = *rgwszProp;
  1080. CAFreeCertTypeProperty (hCertType, rgwszProp);
  1081. }
  1082. else
  1083. {
  1084. _TRACE (0, L"CAGetCertTypePropertyEx (CERTTYPE_PROP_FRIENDLY_NAME) failed: 0x%x\n", hr);
  1085. }
  1086. CACloseCertType (hCertType);
  1087. }
  1088. }
  1089. else
  1090. {
  1091. _TRACE (0, L"CryptDecodeObject (CRYPT_ASN_ENCODING, X509_UNICODE_ANY_STRING, ...) failed: 0x%x\n",
  1092. GetLastError ());
  1093. }
  1094. ::LocalFree (pCNValue);
  1095. }
  1096. }
  1097. else
  1098. {
  1099. _TRACE (0, L"CryptDecodeObject (CRYPT_ASN_ENCODING, X509_UNICODE_ANY_STRING, ...) failed: 0x%x\n",
  1100. GetLastError ());
  1101. }
  1102. }
  1103. return szTemplateName;
  1104. }
  1105. // NTRAID# 247237 Cert UI: Cert Snapin: Certificates snapin should show template name
  1106. CString CCertificate::DecodeV2TemplateName (PCERT_EXTENSION pCertExtension)
  1107. {
  1108. CString szTemplateName;
  1109. ASSERT (pCertExtension);
  1110. if ( pCertExtension )
  1111. {
  1112. DWORD cbData = 0;
  1113. if ( CryptDecodeObject(X509_ASN_ENCODING,
  1114. szOID_CERTIFICATE_TEMPLATE,
  1115. pCertExtension->Value.pbData,
  1116. pCertExtension->Value.cbData,
  1117. 0,
  1118. NULL,
  1119. &cbData) )
  1120. {
  1121. CERT_TEMPLATE_EXT* pbTemplate = (CERT_TEMPLATE_EXT*) LocalAlloc(LPTR, cbData);
  1122. if ( pbTemplate )
  1123. {
  1124. if ( CryptDecodeObject(X509_ASN_ENCODING,
  1125. szOID_CERTIFICATE_TEMPLATE,
  1126. pCertExtension->Value.pbData,
  1127. pCertExtension->Value.cbData,
  1128. 0,
  1129. pbTemplate,
  1130. &cbData) )
  1131. {
  1132. CString text;
  1133. CString description;
  1134. //copy the extension oid
  1135. if ( pbTemplate->pszObjId )
  1136. {
  1137. MyGetOIDInfo (szTemplateName, pbTemplate->pszObjId);
  1138. }
  1139. }
  1140. else
  1141. {
  1142. _TRACE (0, L"CryptDecodeObject (X509_ASN_ENCODING, szOID_CERTIFICATE_TEMPLATE, ...) failed: 0x%x\n",
  1143. GetLastError ());
  1144. }
  1145. LocalFree (pbTemplate);
  1146. }
  1147. }
  1148. else
  1149. {
  1150. _TRACE (0, L"CryptDecodeObject (X509_ASN_ENCODING, szOID_CERTIFICATE_TEMPLATE, ...) failed: 0x%x\n",
  1151. GetLastError ());
  1152. }
  1153. }
  1154. return szTemplateName;
  1155. }
  1156. void CCertificate::SetStore (CCertStore* pStore)
  1157. {
  1158. if ( !m_pCertStore && !pStore )
  1159. return;
  1160. if ( m_pCertStore && pStore )
  1161. {
  1162. if ( *m_pCertStore == *pStore )
  1163. return; // don't change if the same
  1164. }
  1165. if ( m_pCertStore )
  1166. {
  1167. m_pCertStore->Release ();
  1168. m_pCertStore = 0;
  1169. }
  1170. if ( pStore )
  1171. {
  1172. m_pCertStore = pStore;
  1173. m_pCertStore->AddRef ();
  1174. }
  1175. if ( m_pCertContext )
  1176. {
  1177. PCCERT_CONTEXT pCertContext = GetNewCertContext ();
  1178. ::CertFreeCertificateContext (m_pCertContext);
  1179. m_pCertInfo = 0;
  1180. m_pCertContext = 0;
  1181. m_pCertContext = pCertContext;
  1182. if ( m_pCertContext )
  1183. m_pCertInfo = m_pCertContext->pCertInfo;
  1184. }
  1185. }