------------------- CODE BEGINS -----------------------------
// Get the default container.
BOOL bResult;
bResult = ::CryptGetProvParam (hCrypt, PP_ENUMCONTAINERS,
(BYTE*)pbData, &cbData, CRYPT_FIRST);
HCERTSTORE hArrCertStore[2]; // hold the two cert store handles.
PCCERT_CONTEXT pArrCertContext[2]; // hold the two cert contexts
int i = 0;
do
{
<String> name;
name += card->szContainerName;
name += pbData;
name += TEXT ("\\");
if (hCrypt)
::CryptReleaseContext (hCrypt, 0);
// look for the first container
bResult = ::CryptAcquireContext (&hCrypt, name.toString (),
GetProviderName (), PROV_RSA_FULL, 0);
HCRYPTKEY hKey = NULL;
DWORD dwCertLength = 0;
BYTE* bCert = NULL;
// Only the AT_KEYEXCHANGE key pair exists
::CryptGetUserKey (hCrypt , AT_KEYEXCHANGE, &hKey);
// Get the certificate length
::CryptGetKeyParam (hKey, KP_CERTIFICATE, NULL, &dwCertLength,
0);
// allocate enough memory
bCert = (BYTE*)::malloc (dwCertLength);
// Retrieve the certificate into the byte array bCert
//
::CryptGetKeyParam (hKey, KP_CERTIFICATE, bCert,
&dwCertLength, 0);
// Dispose the local copy of the key
//
if (hKey)
::CryptDestroyKey (hKey);
// create a certificate context from the byte array
PCCERT_CONTEXT pCertContext = NULL;
pCertContext = ::CertCreateCertificateContext
(X509_ASN_ENCODING|PKCS_7_ASN_ENCODING, bCert, dwCertLength);
// save the cert context.
pArrCertContext[i] = pCertContext;
// save the cert store --> is this valid ?
hArrCertStore[i] = pCertContext->hCertStore;
TCHAR szName[1000];
DWORD dwLen = sizeof (TCHAR) * 1000, dwOut;
PCERT_INFO pCertInfo = NULL;
pCertInfo = pCertContext->pCertInfo;
// get the subject details for the cert
::CertNameToStr (pCertContext->dwCertEncodingType, &pCertInfo-
>Subject, CERT_X500_NAME_STR, szName, dwLen);
// free the context
//if (pCertContext)
// ::CertFreeCertificateContext (pCertContext);
if (bCert)
{
::free (bCert);
bCert = NULL;
}
i++;
}
while (::CryptGetProvParam (hCrypt, PP_ENUMCONTAINERS,
(BYTE*)pbData, &cbData, CRYPT_NEXT) == TRUE);
// Select a certificate
//
CERT_SELECT_STRUCT pCss;
pCss.dwSize = sizeof (pCss);
pCss.hwndParent = NULL;
pCss.hInstance = NULL;
pCss.dwFlags = (DWORD)0;
pCss.pTemplateName = TEXT ("");
pCss.szPurposeOid = NULL;
pCss.szTitle = TEXT ("");
pCss.cCertStore = (DWORD)i;
pCss.cCertContext = (DWORD)i;
pCss.arrayCertStore = hArrCertStore;
pCss.arrayCertContext = pArrCertContext;
pCss.hprov = hCrypt;
pCss.pfnFilter = NULL;
pCss.szHelpFileName = TEXT ("");
pCss.pfnHook = NULL;
pCss.lCustData = NULL;
typedef BOOL (WINAPI* CSD) (PCERT_SELECT_STRUCT_A);
HMODULE hMod = ::LoadLibrary ("cryptdlg.dll");
CSD csd;
if (hMod)
{
DWORD dwErr;
csd = (CSD)::GetProcAddress (hMod, "CertSelectCertificateA");
if (csd)
{
bResult = (*csd) (&pCss); // this throws a pop-up but no
certificates displayed at all.
if (bResult != TRUE)
{
dwErr = ::GetLastError ();
}
}
::FreeLibrary (hMod);
}
------------------- CODE ENDS -----------------------------
I suspect something about the array of CertStore handles. Note, I
cannot use the CryptUIDlgSelectCertificate because the
CRYPTUI_SELECTCERTIFICATE_STRUCT looks for cert store alone and no
cert contexts. But for a smart card, a cert context help better than
the cert store handle.
Thanks.
Your problem comes from the fact that you are using invalid HCERTSTORE
values for the arrayCertStore parameter of the CERT_SELECT_STRUCT. In your
code, you just copy the value of the hCertStore member of the certificate
contexte which is NULL.
In order to have the correct behavior, you must create a certificate store
in memory using CertOpenSore, add all your certificate contexts to it using
CertAddCertificateContextToStore and then point the arrayCertStore member of
CERT_SELECT_STRUCT to this handle.
I have written a small sample that perform all the necessary operations in
order to display all the certificates present on a smart card using
CertSelectCertificate. It will show you how to perform the correct steps. You
can get it at the following link :
http://www.idrix.fr/Root/Samples/ShowCertsDlg.cpp
Just replace the the CSP name by yours and run it.
I hope this will help.
Cheers,
--
Mounir IDRASSI
IDRIX
http://www.idrix.fr
To reach me: mounir_idrix_fr (replace the underscores with the at and dot
characters respectively)