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.

736 lines
18 KiB

  1. //+---------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1997 - 1999
  5. //
  6. // File: Certifct.cpp
  7. //
  8. // Contents: Implementation of CCertmgrApp and DLL registration.
  9. //
  10. //----------------------------------------------------------------------------
  11. #include "stdafx.h"
  12. #include "certca.h"
  13. #include "tfcprop.h"
  14. #include "genpage.h"
  15. #include "Certifct.h"
  16. /////////////////////////////////////////////////////////////////////////////
  17. //
  18. enum {
  19. FIELD_CAN_DELETE = 0x00000001
  20. };
  21. CCertificate::CCertificate(const PCCERT_CONTEXT pCertContext,
  22. HCERTSTORE hCertStore)
  23. : m_pCertContext (::CertDuplicateCertificateContext (pCertContext)),
  24. m_pCertInfo (0),
  25. m_hCertStore (::CertDuplicateStore (hCertStore)),
  26. m_bCertContextFreed (false),
  27. m_fieldChecked (0),
  28. m_bCanDelete (false)
  29. {
  30. ASSERT (m_pCertContext);
  31. if ( m_pCertContext )
  32. m_pCertInfo = m_pCertContext->pCertInfo;
  33. }
  34. CCertificate::~CCertificate()
  35. {
  36. if ( m_pCertContext && !m_bCertContextFreed )
  37. ::CertFreeCertificateContext (m_pCertContext);
  38. if ( m_hCertStore )
  39. ::CertCloseStore (m_hCertStore, 0);
  40. }
  41. HRESULT CCertificate::GetIssuerName (PWSTR *ppszIssuerName)
  42. {
  43. HRESULT hResult = S_OK;
  44. ASSERT (m_pCertInfo && ppszIssuerName);
  45. if ( m_pCertInfo && ppszIssuerName )
  46. {
  47. // Decode issuer name if not already present
  48. if ( m_szIssuerName.IsEmpty() )
  49. {
  50. hResult = GetNameString (CERT_NAME_ISSUER_FLAG, m_szIssuerName);
  51. }
  52. if ( SUCCEEDED (hResult) )
  53. {
  54. if ( *ppszIssuerName )
  55. delete [] *ppszIssuerName;
  56. *ppszIssuerName = new WCHAR[wcslen (m_szIssuerName) + 1];
  57. if ( *ppszIssuerName )
  58. {
  59. wcscpy (*ppszIssuerName, m_szIssuerName);
  60. }
  61. else
  62. hResult = E_OUTOFMEMORY;
  63. }
  64. }
  65. else
  66. hResult = E_POINTER;
  67. return hResult;
  68. }
  69. ///////////////////////////////////////////////////////////////////////////
  70. // GetSubjectName ()
  71. //
  72. // pszName (IN / OPTIONAL) - returns the alternate issuer name. An empty
  73. // string is a valid return value
  74. // cbName (IN / OUT) - If pszName is NULL, then the required length
  75. // of pszName is returned.
  76. // Otherwise, contains the length of pszName.
  77. ///////////////////////////////////////////////////////////////////////////
  78. HRESULT CCertificate::GetSubjectName(PWSTR *ppszSubjectName)
  79. {
  80. HRESULT hResult = S_OK;
  81. ASSERT (m_pCertInfo && ppszSubjectName);
  82. if ( m_pCertInfo && ppszSubjectName )
  83. {
  84. // Decode issuer name if not already present
  85. if ( m_szSubjectName.IsEmpty() )
  86. {
  87. hResult = GetNameString (0, m_szSubjectName);
  88. }
  89. if ( SUCCEEDED (hResult) )
  90. {
  91. if ( *ppszSubjectName )
  92. delete [] *ppszSubjectName;
  93. *ppszSubjectName = new WCHAR[wcslen (m_szSubjectName) + 1];
  94. if ( *ppszSubjectName )
  95. {
  96. wcscpy (*ppszSubjectName, m_szSubjectName);
  97. }
  98. else
  99. hResult = E_OUTOFMEMORY;
  100. }
  101. }
  102. else
  103. hResult = E_POINTER;
  104. return hResult;
  105. }
  106. ///////////////////////////////////////////////////////////////////////////
  107. // GetValidNotAfter ()
  108. //
  109. // pszDateTime (IN / OPTIONAL) - returns the formatted date and time.
  110. // cbDateTime (IN / OUT) - If pszDateTime is NULL, then the required length
  111. // of pszDateTime is returned.
  112. // Otherwise, contains the length of pszDateTime.
  113. ///////////////////////////////////////////////////////////////////////////
  114. HRESULT CCertificate::GetValidNotAfter (PWSTR* ppszValidNotAfter)
  115. {
  116. HRESULT hResult = S_OK;
  117. ASSERT (m_pCertInfo && ppszValidNotAfter);
  118. if ( m_pCertInfo && ppszValidNotAfter )
  119. {
  120. // Format date/time string if not already present
  121. if ( m_szValidNotAfter.IsEmpty() )
  122. {
  123. hResult = FormatDate (m_pCertInfo->NotAfter, m_szValidNotAfter);
  124. if ( SUCCEEDED (hResult) )
  125. {
  126. if ( *ppszValidNotAfter )
  127. delete [] *ppszValidNotAfter;
  128. *ppszValidNotAfter = new WCHAR[wcslen (m_szValidNotAfter)+1];
  129. if ( *ppszValidNotAfter )
  130. {
  131. wcscpy (*ppszValidNotAfter, m_szValidNotAfter);
  132. }
  133. else
  134. hResult = E_OUTOFMEMORY;
  135. }
  136. }
  137. }
  138. else
  139. hResult = E_POINTER;
  140. return hResult;
  141. }
  142. HRESULT CCertificate::GetEnhancedKeyUsage (PWSTR* ppszUsages)
  143. {
  144. HRESULT hResult = S_OK;
  145. ASSERT (m_pCertInfo && ppszUsages);
  146. if ( m_pCertInfo && ppszUsages )
  147. {
  148. // Format date/time string if not already present
  149. if ( m_szEnhancedKeyUsage.IsEmpty() )
  150. {
  151. hResult = FormatEnhancedKeyUsagePropertyString ();
  152. if ( SUCCEEDED (hResult) && !m_szEnhancedKeyUsage.IsEmpty() )
  153. {
  154. if ( *ppszUsages )
  155. delete [] *ppszUsages;
  156. *ppszUsages = new WCHAR[wcslen (m_szEnhancedKeyUsage)+1];
  157. if ( *ppszUsages )
  158. {
  159. wcscpy (*ppszUsages, m_szEnhancedKeyUsage);
  160. }
  161. else
  162. hResult = E_OUTOFMEMORY;
  163. }
  164. }
  165. }
  166. else
  167. hResult = E_POINTER;
  168. return hResult;
  169. }
  170. HRESULT CCertificate::FormatEnhancedKeyUsagePropertyString ()
  171. {
  172. HRESULT hResult = S_OK;
  173. DWORD cbUsage = 0;
  174. DWORD dwErr = 0;
  175. LPWSTR wszEnhUsage = NULL;
  176. BOOL bReturn = ::CertGetEnhancedKeyUsage (m_pCertContext, 0, // get extension and property
  177. NULL, &cbUsage);
  178. if ( bReturn )
  179. {
  180. PCERT_ENHKEY_USAGE pUsage = (PCERT_ENHKEY_USAGE) new BYTE[cbUsage];
  181. if ( pUsage )
  182. {
  183. bReturn = ::CertGetEnhancedKeyUsage (m_pCertContext, 0, // get extension and property
  184. pUsage, &cbUsage);
  185. if ( bReturn )
  186. {
  187. size_t dwLen = 0;
  188. PWSTR pszComma = _T(", ");
  189. size_t dwCommaLen = wcslen (pszComma);
  190. PWSTR pszUsageName = 0;
  191. // Get accumulated lengths first
  192. for (DWORD dwIndex = 0; dwIndex < pUsage->cUsageIdentifier; dwIndex++)
  193. {
  194. hResult = GetOIDInfo (&pszUsageName, pUsage->rgpszUsageIdentifier[dwIndex]);
  195. if ( SUCCEEDED (hResult) )
  196. {
  197. // add delimeter if not first iteration
  198. if ( dwIndex != 0 )
  199. dwLen += dwCommaLen;
  200. dwLen += wcslen (pszUsageName);
  201. delete [] pszUsageName;
  202. pszUsageName = 0;
  203. }
  204. else
  205. break;
  206. }
  207. // Allocate buffer and get strings
  208. wszEnhUsage = m_szEnhancedKeyUsage.GetBuffer(dwLen+1);
  209. if ( wszEnhUsage )
  210. {
  211. ::ZeroMemory (wszEnhUsage, (dwLen+1)* sizeof (WCHAR));
  212. for (DWORD dwIndex = 0; dwIndex < pUsage->cUsageIdentifier; dwIndex++)
  213. {
  214. hResult = GetOIDInfo (&pszUsageName, pUsage->rgpszUsageIdentifier[dwIndex]);
  215. if ( SUCCEEDED (hResult) )
  216. {
  217. // add delimeter if not first iteration
  218. if ( dwIndex != 0 )
  219. wcscat (wszEnhUsage, pszComma);
  220. wcscat (wszEnhUsage, pszUsageName);
  221. ASSERT (wcslen (wszEnhUsage) <= dwLen);
  222. delete [] pszUsageName;
  223. pszUsageName = 0;
  224. }
  225. else
  226. break;
  227. }
  228. }
  229. else
  230. hResult = E_OUTOFMEMORY;
  231. }
  232. else
  233. {
  234. dwErr = GetLastError ();
  235. ASSERT (dwErr == CRYPT_E_NOT_FOUND);
  236. if ( dwErr == CRYPT_E_NOT_FOUND )
  237. {
  238. if ( !m_szEnhancedKeyUsage.LoadString (IDS_ANY) )
  239. hResult = E_UNEXPECTED;
  240. }
  241. else
  242. {
  243. hResult = HRESULT_FROM_WIN32(dwErr);
  244. }
  245. }
  246. delete [] pUsage;
  247. }
  248. else
  249. hResult = E_OUTOFMEMORY;
  250. }
  251. else
  252. {
  253. dwErr = GetLastError ();
  254. ASSERT (dwErr == CRYPT_E_NOT_FOUND);
  255. if ( dwErr != CRYPT_E_NOT_FOUND )
  256. {
  257. hResult = HRESULT_FROM_WIN32(dwErr);
  258. }
  259. }
  260. return hResult;
  261. }
  262. ///////////////////////////////////////////////////////////////////////////
  263. // GetAlternateIssuerName ()
  264. //
  265. // pszName (IN / OPTIONAL) - returns the alternate issuer name. An empty
  266. // string is a valid return value
  267. // cbName (IN / OUT) - If pszName is NULL, then the required length
  268. // of pszName is returned.
  269. // Otherwise, contains the length of pszName.
  270. ///////////////////////////////////////////////////////////////////////////
  271. HRESULT CCertificate::GetAlternateIssuerName (PWSTR* ppszAltIssuerName)
  272. {
  273. HRESULT hResult = S_OK;
  274. ASSERT (m_pCertInfo && ppszAltIssuerName);
  275. if ( m_pCertInfo && ppszAltIssuerName )
  276. {
  277. if ( m_szAltIssuerName.IsEmpty() )
  278. {
  279. hResult = ConvertAltNameToString (_T(szOID_ISSUER_ALT_NAME),
  280. CERT_ALT_NAME_URL, m_szAltIssuerName);
  281. ASSERT (SUCCEEDED (hResult));
  282. if ( SUCCEEDED (hResult) )
  283. {
  284. if ( *ppszAltIssuerName )
  285. delete [] *ppszAltIssuerName;
  286. *ppszAltIssuerName = new WCHAR[wcslen (m_szAltIssuerName)+1];
  287. if ( *ppszAltIssuerName )
  288. {
  289. wcscpy (*ppszAltIssuerName, m_szAltIssuerName);
  290. }
  291. else
  292. hResult = E_OUTOFMEMORY;
  293. }
  294. }
  295. }
  296. else
  297. hResult = E_POINTER;
  298. return hResult;
  299. }
  300. ///////////////////////////////////////////////////////////////////////////
  301. // GetAlternateSubjectName ()
  302. //
  303. // pszName (IN / OPTIONAL) - returns the alternate issuer name. An empty
  304. // string is a valid return value
  305. // cbName (IN / OUT) - If pszName is NULL, then the required length
  306. // of pszName is returned.
  307. // Otherwise, contains the length of pszName.
  308. ///////////////////////////////////////////////////////////////////////////
  309. HRESULT CCertificate::GetAlternateSubjectName (PWSTR* ppszAltSubjectName)
  310. {
  311. HRESULT hResult = S_OK;
  312. ASSERT (m_pCertInfo && ppszAltSubjectName);
  313. if ( m_pCertInfo && ppszAltSubjectName )
  314. {
  315. if ( m_szAltSubjectName.IsEmpty() )
  316. {
  317. hResult = ConvertAltNameToString (_T(szOID_SUBJECT_ALT_NAME),
  318. CERT_ALT_NAME_URL, m_szAltSubjectName);
  319. ASSERT (SUCCEEDED (hResult));
  320. if ( SUCCEEDED (hResult) )
  321. {
  322. if ( *ppszAltSubjectName )
  323. delete [] *ppszAltSubjectName;
  324. *ppszAltSubjectName = new WCHAR[wcslen (m_szAltSubjectName)+1];
  325. if ( *ppszAltSubjectName )
  326. {
  327. wcscpy (*ppszAltSubjectName, m_szAltSubjectName);
  328. }
  329. else
  330. hResult = E_OUTOFMEMORY;
  331. }
  332. }
  333. }
  334. else
  335. hResult = E_POINTER;
  336. return hResult;
  337. }
  338. //////////////////////////////////////////////////////////////////////////////
  339. // ConvertAltNameToString ()
  340. //
  341. // szOID (IN) - The OID of the alternate name to retrieve
  342. // dwNameChoice (IN) - The type of alternate name to return
  343. // altName (OUT) - The version of the desired alternate name indicated
  344. // by dwNameChoice
  345. //////////////////////////////////////////////////////////////////////////////
  346. HRESULT CCertificate::ConvertAltNameToString (PWSTR szOID, const DWORD dwNameChoice, CString & strAltName)
  347. {
  348. HRESULT hResult = S_OK;
  349. ASSERT (szOID);
  350. if ( !szOID )
  351. return E_POINTER;
  352. // Iterate through the extensions until the one indicated by the
  353. // passed-in szOID is found.
  354. for (DWORD index = 0; index < m_pCertInfo->cExtension; index++)
  355. {
  356. ASSERT (m_pCertInfo->rgExtension);
  357. size_t len = strlen (m_pCertInfo->rgExtension[index].pszObjId);
  358. LPTSTR wcsObjId = new WCHAR[len];
  359. if ( !wcsObjId )
  360. {
  361. hResult = E_OUTOFMEMORY;
  362. break;
  363. }
  364. else
  365. wcsObjId[0] = L'\0';
  366. mbstowcs (wcsObjId, m_pCertInfo->rgExtension[index].pszObjId, len);
  367. if ( !wcscmp (wcsObjId, szOID) )
  368. {
  369. CERT_ALT_NAME_INFO nameInfo;
  370. DWORD cbNameInfo = sizeof (CERT_ALT_NAME_INFO);
  371. BOOL bResult = CryptDecodeObject(
  372. MY_ENCODING_TYPE,
  373. X509_ALTERNATE_NAME, // in
  374. m_pCertInfo->rgExtension[index].Value.pbData, // in
  375. m_pCertInfo->rgExtension[index].Value.cbData, // in
  376. 0, // in
  377. (void *) &nameInfo, // out
  378. &cbNameInfo); // in/out
  379. ASSERT (bResult);
  380. if ( bResult )
  381. {
  382. // We've found the right extension, now iterate through
  383. // the alternate names until we find the desired type.
  384. for (DWORD index1 = 0; index1 < nameInfo.cAltEntry; index1++)
  385. {
  386. if ( nameInfo.rgAltEntry[index1].dwAltNameChoice ==
  387. dwNameChoice )
  388. {
  389. strAltName = nameInfo.rgAltEntry[index1].pwszURL;
  390. break;
  391. }
  392. }
  393. }
  394. else
  395. hResult = E_UNEXPECTED;
  396. break;
  397. }
  398. delete [] wcsObjId;
  399. }
  400. return hResult;
  401. }
  402. HCERTSTORE CCertificate::GetCertStore() const
  403. {
  404. return m_hCertStore;
  405. }
  406. PCCERT_CONTEXT CCertificate::GetCertContext() const
  407. {
  408. return m_pCertContext;
  409. }
  410. HRESULT CCertificate::GetNameString (DWORD dwFlag, CString &strName)
  411. {
  412. HRESULT hResult = S_OK;
  413. DWORD dwTypePara = CERT_SIMPLE_NAME_STR;
  414. DWORD cchNameString = 0;
  415. DWORD dwResult = ::CertGetNameString (m_pCertContext,
  416. CERT_NAME_SIMPLE_DISPLAY_TYPE,
  417. dwFlag,
  418. &dwTypePara,
  419. NULL,
  420. cchNameString);
  421. if ( dwResult > 1 )
  422. {
  423. cchNameString = dwResult;
  424. dwResult = ::CertGetNameString (m_pCertContext,
  425. CERT_NAME_SIMPLE_DISPLAY_TYPE,
  426. dwFlag,
  427. &dwTypePara,
  428. strName.GetBuffer(cchNameString),
  429. cchNameString);
  430. ASSERT (dwResult > 1);
  431. if ( dwResult <= 1 )
  432. {
  433. if ( !strName.LoadString (IDS_NOT_AVAILABLE) )
  434. hResult = E_FAIL;
  435. }
  436. }
  437. else
  438. {
  439. dwResult = ::CertGetNameString (m_pCertContext,
  440. CERT_NAME_EMAIL_TYPE,
  441. dwFlag,
  442. NULL,
  443. NULL,
  444. cchNameString);
  445. if ( dwResult > 1 )
  446. {
  447. cchNameString = dwResult;
  448. dwResult = ::CertGetNameString (m_pCertContext,
  449. CERT_NAME_EMAIL_TYPE,
  450. dwFlag,
  451. NULL,
  452. strName.GetBuffer(cchNameString),
  453. cchNameString);
  454. ASSERT (dwResult > 1);
  455. if ( dwResult <= 1 )
  456. {
  457. if ( !strName.LoadString (IDS_NOT_AVAILABLE) )
  458. hResult = E_FAIL;
  459. }
  460. }
  461. else
  462. {
  463. if ( !strName.LoadString (IDS_NOT_AVAILABLE))
  464. hResult = E_FAIL;
  465. }
  466. }
  467. return hResult;
  468. }
  469. int CCertificate::CompareExpireDate(const CCertificate & cert) const
  470. {
  471. int compVal = 0;
  472. ASSERT (m_pCertInfo && cert.m_pCertInfo);
  473. if ( m_pCertInfo && cert.m_pCertInfo )
  474. {
  475. compVal = ::CompareFileTime (&m_pCertInfo->NotAfter,
  476. &cert.m_pCertInfo->NotAfter);
  477. }
  478. return compVal;
  479. }
  480. HRESULT CCertificate::GetOIDInfo (PWSTR* ppszString, PSTR pszObjId)
  481. {
  482. HRESULT hResult = S_OK;
  483. ASSERT (pszObjId && ppszString);
  484. if ( pszObjId && ppszString )
  485. {
  486. PCCRYPT_OID_INFO pOIDInfo;
  487. BOOL bResult = TRUE;
  488. pOIDInfo = ::CryptFindOIDInfo (CRYPT_OID_INFO_OID_KEY, (void *) pszObjId, 0);
  489. if ( pOIDInfo )
  490. {
  491. if ( *ppszString )
  492. delete [] *ppszString;
  493. *ppszString = new WCHAR[wcslen (pOIDInfo->pwszName)+1];
  494. if ( *ppszString )
  495. {
  496. wcscpy (*ppszString, pOIDInfo->pwszName);
  497. }
  498. else
  499. hResult = E_OUTOFMEMORY;
  500. }
  501. else
  502. {
  503. int nLen = ::MultiByteToWideChar (CP_ACP, 0, pszObjId, -1, NULL, 0);
  504. ASSERT (nLen);
  505. if ( nLen )
  506. {
  507. if ( *ppszString )
  508. delete [] *ppszString;
  509. *ppszString = new WCHAR[nLen];
  510. if ( *ppszString )
  511. {
  512. nLen = ::MultiByteToWideChar (CP_ACP, 0, pszObjId, -1,
  513. *ppszString, nLen);
  514. ASSERT (nLen);
  515. if ( !nLen )
  516. hResult = E_UNEXPECTED;
  517. }
  518. else
  519. hResult = E_OUTOFMEMORY;
  520. }
  521. else
  522. hResult = E_FAIL;
  523. }
  524. }
  525. else
  526. hResult = E_POINTER;
  527. return hResult;
  528. }
  529. ///////////////////////////////////////////////////////////////////////////////
  530. // FormatDate ()
  531. //
  532. // utcDateTime (IN) - A FILETIME in UTC format.
  533. // pszDateTime (OUT) - A string containing the local date and time
  534. // formatted by locale and user preference
  535. //
  536. ///////////////////////////////////////////////////////////////////////////////
  537. HRESULT CCertificate::FormatDate (FILETIME utcDateTime, CString &strDateTime)
  538. {
  539. // Time is returned as UTC, will be displayed as local.
  540. // Use FileTimeToLocalFileTime () to make it local,
  541. // then call FileTimeToSystemTime () to convert to system time, then
  542. // format with GetDateFormat () and GetTimeFormat () to display
  543. // according to user and locale preferences
  544. HRESULT hResult = S_OK;
  545. FILETIME localDateTime;
  546. BOOL bResult = FileTimeToLocalFileTime (&utcDateTime, // pointer to UTC file time to convert
  547. &localDateTime); // pointer to converted file time
  548. ASSERT (bResult);
  549. if ( bResult )
  550. {
  551. SYSTEMTIME sysTime;
  552. bResult = FileTimeToSystemTime (
  553. &localDateTime, // pointer to file time to convert
  554. &sysTime); // pointer to structure to receive system time
  555. if ( bResult )
  556. {
  557. // Get date
  558. // Get length to allocate buffer of sufficient size
  559. int iLen = GetDateFormat (
  560. LOCALE_USER_DEFAULT, // locale for which date is to be formatted
  561. 0, // flags specifying function options
  562. &sysTime, // date to be formatted
  563. 0, // date format string
  564. 0, // buffer for storing formatted string
  565. 0); // size of buffer
  566. ASSERT (iLen > 0);
  567. if ( iLen > 0 )
  568. {
  569. int iResult = GetDateFormat (
  570. LOCALE_USER_DEFAULT, // locale for which date is to be formatted
  571. 0, // flags specifying function options
  572. &sysTime, // date to be formatted
  573. 0, // date format string
  574. strDateTime.GetBuffer(iLen), // buffer for storing formatted string
  575. iLen); // size of buffer
  576. ASSERT (iResult);
  577. if ( !iResult )
  578. {
  579. hResult = GetLastError();
  580. hResult = HRESULT_FROM_WIN32(hResult);
  581. }
  582. }
  583. else
  584. {
  585. hResult = GetLastError();
  586. hResult = HRESULT_FROM_WIN32(hResult);
  587. }
  588. }
  589. else
  590. {
  591. hResult = GetLastError();
  592. hResult = HRESULT_FROM_WIN32(hResult);
  593. }
  594. }
  595. else
  596. {
  597. hResult = GetLastError();
  598. hResult = HRESULT_FROM_WIN32(hResult);
  599. }
  600. return hResult;
  601. }
  602. void CCertificate::Refresh()
  603. {
  604. }
  605. HRESULT CCertificate::WriteToFile(HANDLE hFile)
  606. {
  607. ASSERT (hFile && hFile != INVALID_HANDLE_VALUE && m_pCertContext);
  608. HRESULT hResult = S_OK;
  609. if ( hFile && hFile != INVALID_HANDLE_VALUE && m_pCertContext )
  610. {
  611. DWORD dwBytesWritten = 0;
  612. BOOL bResult = ::WriteFile (hFile,
  613. m_pCertContext->pbCertEncoded,
  614. m_pCertContext->cbCertEncoded,
  615. &dwBytesWritten,
  616. NULL);
  617. ASSERT (bResult && (dwBytesWritten == m_pCertContext->cbCertEncoded));
  618. if ( !bResult )
  619. hResult = E_FAIL;
  620. }
  621. else
  622. hResult = E_FAIL;
  623. return hResult;
  624. }
  625. BOOL CCertificate::DeleteFromStore()
  626. {
  627. BOOL bResult = ::CertDeleteCertificateFromStore (m_pCertContext);
  628. if ( bResult )
  629. {
  630. // NB: PhilH says "CertDeleteCertificateFromStore (), always does an
  631. // implicit CertFreeCertificateContext."
  632. // Can't set m_pCertContext to 0 because it is const - set this flag instead
  633. m_bCertContextFreed = true;
  634. }
  635. return bResult;
  636. }
  637. bool CCertificate::CanDelete()
  638. {
  639. if ( m_pCertContext && !(m_fieldChecked & FIELD_CAN_DELETE) )
  640. {
  641. DWORD dwAccessFlags = 0;
  642. DWORD cbData = sizeof (DWORD);
  643. BOOL bResult = ::CertGetCertificateContextProperty (
  644. m_pCertContext,
  645. CERT_ACCESS_STATE_PROP_ID,
  646. &dwAccessFlags,
  647. &cbData);
  648. if ( bResult )
  649. {
  650. if ( dwAccessFlags & CERT_ACCESS_STATE_WRITE_PERSIST_FLAG )
  651. m_bCanDelete = true;
  652. }
  653. m_fieldChecked |= FIELD_CAN_DELETE;
  654. }
  655. return m_bCanDelete;
  656. }