crypt32: Simplify CertOpenSystemStore, fix CertDuplicateCertificateContext.

- now that CertOpenStore is correct for system stores, simplify
  CertOpenSystemStore
- correct CertDuplicateCertificateStore, with a test
This commit is contained in:
Juan Lang 2006-02-16 19:38:45 +01:00 committed by Alexandre Julliard
parent dc8f5ee48b
commit 15e5dc29c1
2 changed files with 129 additions and 65 deletions

View File

@ -154,6 +154,8 @@ typedef struct _WINE_CERT_CONTEXT_REF * (*CreateRefFunc)
*/
typedef void (*FreeCertFunc)(struct _WINE_CERT_CONTEXT_REF *ref);
typedef PCCERT_CONTEXT (*DupCertFunc)(PCCERT_CONTEXT context);
typedef enum _CertStoreType {
StoreTypeMem,
StoreTypeCollection,
@ -180,6 +182,7 @@ typedef struct WINE_CRYPTCERTSTORE
CreateRefFunc createCertRef;
EnumCertFunc enumCert;
PFN_CERT_STORE_PROV_DELETE_CERT deleteCert;
DupCertFunc dupCert;
FreeCertFunc freeCert; /* optional */
PFN_CERT_STORE_PROV_CONTROL control; /* optional */
} WINECRYPT_CERTSTORE, *PWINECRYPT_CERTSTORE;
@ -580,6 +583,21 @@ static void WINAPI CRYPT_MemCloseStore(HCERTSTORE hCertStore, DWORD dwFlags)
CryptMemFree(store);
}
static PCCERT_CONTEXT CRYPT_MemDupCert(PCCERT_CONTEXT pCertContext)
{
const WINE_CERT_LIST_ENTRY *context =
(const WINE_CERT_LIST_ENTRY *)pCertContext;
PWINE_CERT_LIST_ENTRY ret;
ret = CryptMemAlloc(sizeof(WINE_CERT_LIST_ENTRY));
if (ret)
{
memcpy(ret, context, sizeof(WINE_CERT_LIST_ENTRY));
InterlockedIncrement(&ret->cert.context->ref);
}
return (PCCERT_CONTEXT)ret;
}
static WINECRYPT_CERTSTORE *CRYPT_MemOpenStore(HCRYPTPROV hCryptProv,
DWORD dwFlags, const void *pvPara)
{
@ -605,6 +623,7 @@ static WINECRYPT_CERTSTORE *CRYPT_MemOpenStore(HCRYPTPROV hCryptProv,
store->hdr.enumCert = CRYPT_MemEnumCert;
store->hdr.deleteCert = CRYPT_MemDeleteCert;
store->hdr.freeCert = NULL;
store->hdr.dupCert = CRYPT_MemDupCert;
store->hdr.control = NULL;
InitializeCriticalSection(&store->cs);
list_init(&store->certs);
@ -780,6 +799,21 @@ static BOOL WINAPI CRYPT_CollectionDeleteCert(HCERTSTORE hCertStore,
return ret;
}
static PCCERT_CONTEXT CRYPT_CollectionDupCert(PCCERT_CONTEXT pCertContext)
{
const WINE_COLLECTION_CERT_CONTEXT *context =
(const WINE_COLLECTION_CERT_CONTEXT *)pCertContext;
PWINE_COLLECTION_CERT_CONTEXT ret;
ret = CryptMemAlloc(sizeof(WINE_COLLECTION_CERT_CONTEXT));
if (ret)
{
memcpy(ret, context, sizeof(WINE_COLLECTION_CERT_CONTEXT));
InterlockedIncrement(&ret->cert.context->ref);
}
return (PCCERT_CONTEXT)ret;
}
static void CRYPT_CollectionFreeCert(PWINE_CERT_CONTEXT_REF ref)
{
PWINE_COLLECTION_CERT_CONTEXT context = (PWINE_COLLECTION_CERT_CONTEXT)ref;
@ -813,6 +847,7 @@ static WINECRYPT_CERTSTORE *CRYPT_CollectionOpenStore(HCRYPTPROV hCryptProv,
store->hdr.createCertRef = CRYPT_CollectionCreateCertRef;
store->hdr.enumCert = CRYPT_CollectionEnumCert;
store->hdr.deleteCert = CRYPT_CollectionDeleteCert;
store->hdr.dupCert = CRYPT_CollectionDupCert;
store->hdr.freeCert = CRYPT_CollectionFreeCert;
InitializeCriticalSection(&store->cs);
list_init(&store->stores);
@ -902,6 +937,21 @@ static PWINE_CERT_CONTEXT_REF CRYPT_ProvEnumCert(PWINECRYPT_CERTSTORE store,
return (PWINE_CERT_CONTEXT_REF)ret;
}
static PCCERT_CONTEXT CRYPT_ProvDupCert(PCCERT_CONTEXT pCertContext)
{
const WINE_PROV_CERT_CONTEXT *context =
(const WINE_PROV_CERT_CONTEXT *)pCertContext;
PWINE_PROV_CERT_CONTEXT ret;
ret = CryptMemAlloc(sizeof(WINE_PROV_CERT_CONTEXT));
if (ret)
{
memcpy(ret, context, sizeof(WINE_PROV_CERT_CONTEXT));
InterlockedIncrement(&ret->cert.context->ref);
}
return (PCCERT_CONTEXT)ret;
}
static BOOL WINAPI CRYPT_ProvDeleteCert(HCERTSTORE hCertStore,
PCCERT_CONTEXT cert, DWORD dwFlags)
{
@ -966,6 +1016,7 @@ static PWINECRYPT_CERTSTORE CRYPT_ProvCreateStore(HCRYPTPROV hCryptProv,
ret->hdr.createCertRef = CRYPT_ProvCreateCertRef;
ret->hdr.enumCert = CRYPT_ProvEnumCert;
ret->hdr.deleteCert = CRYPT_ProvDeleteCert;
ret->hdr.dupCert = CRYPT_ProvDupCert;
ret->hdr.freeCert = CRYPT_ProvFreeCert;
ret->hdr.control = CRYPT_ProvControl;
if (pProvInfo->cStoreProvFunc > CERT_STORE_PROV_CLOSE_FUNC)
@ -1839,64 +1890,25 @@ HCERTSTORE WINAPI CertOpenStore(LPCSTR lpszStoreProvider,
HCERTSTORE WINAPI CertOpenSystemStoreA(HCRYPTPROV hProv,
LPCSTR szSubSystemProtocol)
{
HCERTSTORE ret = 0;
if (szSubSystemProtocol)
{
int len = MultiByteToWideChar(CP_ACP, 0, szSubSystemProtocol, -1, NULL,
0);
LPWSTR param = CryptMemAlloc(len * sizeof(WCHAR));
if (param)
{
MultiByteToWideChar(CP_ACP, 0, szSubSystemProtocol, -1, param, len);
ret = CertOpenSystemStoreW(hProv, param);
CryptMemFree(param);
}
}
else
SetLastError(HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER));
return ret;
}
HCERTSTORE WINAPI CertOpenSystemStoreW(HCRYPTPROV hProv,
LPCWSTR szSubSystemProtocol)
{
HCERTSTORE ret;
if (!szSubSystemProtocol)
{
SetLastError(HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER));
return 0;
}
return CertOpenStore(CERT_STORE_PROV_SYSTEM_A, 0, hProv,
CERT_SYSTEM_STORE_CURRENT_USER, szSubSystemProtocol);
}
/* FIXME: needs some tests. It seems to open both HKEY_LOCAL_MACHINE and
* HKEY_CURRENT_USER stores, but I'm not sure under what conditions, if any,
* it fails.
*/
ret = CertOpenStore(CERT_STORE_PROV_COLLECTION, 0, hProv,
CERT_STORE_CREATE_NEW_FLAG, NULL);
if (ret)
HCERTSTORE WINAPI CertOpenSystemStoreW(HCRYPTPROV hProv,
LPCWSTR szSubSystemProtocol)
{
if (!szSubSystemProtocol)
{
HCERTSTORE store = CertOpenStore(CERT_STORE_PROV_SYSTEM_REGISTRY_W,
0, hProv, CERT_SYSTEM_STORE_LOCAL_MACHINE, szSubSystemProtocol);
if (store)
{
CertAddStoreToCollection(ret, store,
CERT_PHYSICAL_STORE_ADD_ENABLE_FLAG, 0);
CertCloseStore(store, 0);
}
store = CertOpenStore(CERT_STORE_PROV_SYSTEM_REGISTRY_W,
0, hProv, CERT_SYSTEM_STORE_CURRENT_USER, szSubSystemProtocol);
if (store)
{
CertAddStoreToCollection(ret, store,
CERT_PHYSICAL_STORE_ADD_ENABLE_FLAG, 0);
CertCloseStore(store, 0);
}
SetLastError(HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER));
return 0;
}
return ret;
return CertOpenStore(CERT_STORE_PROV_SYSTEM_W, 0, hProv,
CERT_SYSTEM_STORE_CURRENT_USER, szSubSystemProtocol);
}
BOOL WINAPI CertSaveStore(HCERTSTORE hCertStore, DWORD dwMsgAndCertEncodingType,
@ -2374,29 +2386,35 @@ BOOL WINAPI CertSetCertificateContextProperty(PCCERT_CONTEXT pCertContext,
return ret;
}
/* Only the reference portion of the context is duplicated. The returned
* context has the cert store set to 0, to prevent the store's certificate free
* function from getting called on partial data.
* FIXME: is this okay? Needs a test.
*/
PCCERT_CONTEXT WINAPI CertDuplicateCertificateContext(
PCCERT_CONTEXT pCertContext)
{
PWINE_CERT_CONTEXT_REF ref = (PWINE_CERT_CONTEXT_REF)pCertContext, ret;
PCCERT_CONTEXT ret;
TRACE("(%p)\n", pCertContext);
if (ref)
if (pCertContext->hCertStore)
{
ret = CryptMemAlloc(sizeof(WINE_CERT_CONTEXT_REF));
if (ret)
{
memcpy(ret, ref, sizeof(*ret));
ret->cert.hCertStore = 0;
InterlockedIncrement(&ret->context->ref);
}
PWINECRYPT_CERTSTORE store =
(PWINECRYPT_CERTSTORE)pCertContext->hCertStore;
ret = store->dupCert(pCertContext);
}
else
ret = NULL;
{
PWINE_CERT_CONTEXT_REF context = (PWINE_CERT_CONTEXT_REF)pCertContext,
ref;
ref = CryptMemAlloc(sizeof(WINE_CERT_CONTEXT_REF));
if (ref)
{
memcpy(ref, context, sizeof(*ret));
ref->cert.hCertStore = 0;
InterlockedIncrement(&ref->context->ref);
ret = (PCCERT_CONTEXT)ref;
}
else
ret = NULL;
}
return (PCCERT_CONTEXT)ret;
}

View File

@ -138,6 +138,51 @@ static const BYTE signedCRL[] = { 0x30, 0x45, 0x30, 0x2c, 0x30, 0x02, 0x06,
0x30, 0x5a, 0x30, 0x02, 0x06, 0x00, 0x03, 0x11, 0x00, 0x0f, 0x0e, 0x0d, 0x0c,
0x0b, 0x0a, 0x09, 0x08, 0x07, 0x06, 0x05, 0x04, 0x03, 0x02, 0x01, 0x00 };
static void testDupCert(void)
{
HCERTSTORE store;
store = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0,
CERT_STORE_CREATE_NEW_FLAG, NULL);
ok(store != NULL, "CertOpenStore failed: %ld\n", GetLastError());
if (store != NULL)
{
PCCERT_CONTEXT context, dupContext;
BOOL ret;
ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
bigCert, sizeof(bigCert) - 1, CERT_STORE_ADD_ALWAYS, &context);
ok(ret, "CertAddEncodedCertificateToStore failed: %08lx\n",
GetLastError());
ok(context != NULL, "Expected a valid cert context\n");
if (context)
{
ok(context->cbCertEncoded == sizeof(bigCert) - 1,
"Expected cert of %d bytes, got %ld\n", sizeof(bigCert) - 1,
context->cbCertEncoded);
ok(!memcmp(context->pbCertEncoded, bigCert, sizeof(bigCert) - 1),
"Unexpected encoded cert in context\n");
ok(context->hCertStore == store, "Unexpected store\n");
dupContext = CertDuplicateCertificateContext(context);
ok(dupContext != NULL, "Expected valid duplicate\n");
if (dupContext)
{
ok(dupContext->cbCertEncoded == sizeof(bigCert) - 1,
"Expected cert of %d bytes, got %ld\n", sizeof(bigCert) - 1,
dupContext->cbCertEncoded);
ok(!memcmp(dupContext->pbCertEncoded, bigCert,
sizeof(bigCert) - 1),
"Unexpected encoded cert in context\n");
ok(dupContext->hCertStore == store, "Unexpected store\n");
CertFreeCertificateContext(dupContext);
}
CertFreeCertificateContext(context);
}
CertCloseStore(store, 0);
}
}
static void testMemStore(void)
{
HCERTSTORE store1, store2;
@ -1633,6 +1678,7 @@ START_TEST(cert)
init_function_pointers();
testCryptHashCert();
testDupCert();
/* various combinations of CertOpenStore */
testMemStore();