From 4c6988e8f0485adc79045233d762c1756ada4fff Mon Sep 17 00:00:00 2001 From: Juan Lang Date: Mon, 14 May 2007 18:05:43 -0700 Subject: [PATCH] crypt32: Implement CertGetStoreProperty and CertSetStoreProperty. --- dlls/crypt32/crypt32.spec | 2 + dlls/crypt32/store.c | 106 +++++++++++++++++++++++++++++++++++-- dlls/crypt32/tests/store.c | 74 ++++++++++++++++++++++++++ 3 files changed, 179 insertions(+), 3 deletions(-) diff --git a/dlls/crypt32/crypt32.spec b/dlls/crypt32/crypt32.spec index a3e3039d96d..aba9065a4c0 100644 --- a/dlls/crypt32/crypt32.spec +++ b/dlls/crypt32/crypt32.spec @@ -59,6 +59,7 @@ @ stdcall CertGetNameStringA(ptr long long ptr ptr long) @ stdcall CertGetNameStringW(ptr long long ptr ptr long) @ stdcall CertGetPublicKeyLength(long ptr) +@ stdcall CertGetStoreProperty(long long ptr ptr) @ stdcall CertGetSubjectCertificateFromStore(ptr long ptr) @ stdcall CertGetValidUsages(long ptr ptr ptr ptr) @ stub CertIsRDNAttrsInCertificateName @@ -81,6 +82,7 @@ @ stdcall CertSetCTLContextProperty(ptr long long ptr) @ stdcall CertSetCertificateContextProperty(ptr long long ptr) @ stdcall CertSetEnhancedKeyUsage(ptr ptr) +@ stdcall CertSetStoreProperty(ptr long long ptr) @ stdcall CertStrToNameA(long str long ptr ptr ptr ptr) @ stdcall CertStrToNameW(long wstr long ptr ptr ptr ptr) @ stdcall CertVerifyCRLRevocation(long ptr long ptr) diff --git a/dlls/crypt32/store.c b/dlls/crypt32/store.c index 5f44be4412b..46556d8a926 100644 --- a/dlls/crypt32/store.c +++ b/dlls/crypt32/store.c @@ -138,6 +138,7 @@ typedef struct WINE_CRYPTCERTSTORE CONTEXT_STORE certs; CONTEXT_STORE crls; PFN_CERT_STORE_PROV_CONTROL control; /* optional */ + PCONTEXT_PROPERTY_LIST properties; } WINECRYPT_CERTSTORE, *PWINECRYPT_CERTSTORE; typedef struct _WINE_MEMSTORE @@ -216,6 +217,14 @@ static void CRYPT_InitStore(WINECRYPT_CERTSTORE *store, HCRYPTPROV hCryptProv, } store->cryptProv = hCryptProv; store->dwOpenFlags = dwFlags; + store->properties = NULL; +} + +static void CRYPT_FreeStore(PWINECRYPT_CERTSTORE store) +{ + if (store->properties) + ContextPropertyList_Free(store->properties); + CryptMemFree(store); } static BOOL CRYPT_MemAddCert(PWINECRYPT_CERTSTORE store, void *cert, @@ -316,7 +325,7 @@ static void WINAPI CRYPT_MemCloseStore(HCERTSTORE hCertStore, DWORD dwFlags) ContextList_Free(store->certs); ContextList_Free(store->crls); - CryptMemFree(store); + CRYPT_FreeStore((PWINECRYPT_CERTSTORE)store); } static WINECRYPT_CERTSTORE *CRYPT_MemOpenStore(HCRYPTPROV hCryptProv, @@ -371,7 +380,7 @@ static void WINAPI CRYPT_CollectionCloseStore(HCERTSTORE store, DWORD dwFlags) } cs->cs.DebugInfo->Spare[0] = 0; DeleteCriticalSection(&cs->cs); - CryptMemFree(cs); + CRYPT_FreeStore((PWINECRYPT_CERTSTORE)store); } static void *CRYPT_CollectionCreateContextFromChild(PWINE_COLLECTIONSTORE store, @@ -692,7 +701,7 @@ static void WINAPI CRYPT_ProvCloseStore(HCERTSTORE hCertStore, DWORD dwFlags) store->provCloseStore(store->hStoreProv, dwFlags); if (!(store->dwStoreProvFlags & CERT_STORE_PROV_EXTERNAL_FLAG)) CertCloseStore(store->memStore, dwFlags); - CryptMemFree(store); + CRYPT_FreeStore((PWINECRYPT_CERTSTORE)store); } static BOOL CRYPT_ProvAddCert(PWINECRYPT_CERTSTORE store, void *cert, @@ -2476,6 +2485,97 @@ BOOL WINAPI CertControlStore(HCERTSTORE hCertStore, DWORD dwFlags, return ret; } +BOOL WINAPI CertGetStoreProperty(HCERTSTORE hCertStore, DWORD dwPropId, + void *pvData, DWORD *pcbData) +{ + PWINECRYPT_CERTSTORE store = (PWINECRYPT_CERTSTORE)hCertStore; + BOOL ret = FALSE; + + TRACE("(%p, %d, %p, %p)\n", hCertStore, dwPropId, pvData, pcbData); + + switch (dwPropId) + { + case CERT_ACCESS_STATE_PROP_ID: + if (!pvData) + { + *pcbData = sizeof(DWORD); + ret = TRUE; + } + else if (*pcbData < sizeof(DWORD)) + { + SetLastError(ERROR_MORE_DATA); + *pcbData = sizeof(DWORD); + } + else + { + *(DWORD *)pvData = CertStore_GetAccessState(hCertStore); + ret = TRUE; + } + break; + default: + if (store->properties) + { + CRYPT_DATA_BLOB blob; + + ret = ContextPropertyList_FindProperty(store->properties, dwPropId, + &blob); + if (ret) + { + if (!pvData) + *pcbData = blob.cbData; + else if (*pcbData < blob.cbData) + { + SetLastError(ERROR_MORE_DATA); + *pcbData = blob.cbData; + ret = FALSE; + } + else + { + memcpy(pvData, blob.pbData, blob.cbData); + *pcbData = blob.cbData; + } + } + else + SetLastError(CRYPT_E_NOT_FOUND); + } + else + SetLastError(CRYPT_E_NOT_FOUND); + } + return ret; +} + +BOOL WINAPI CertSetStoreProperty(HCERTSTORE hCertStore, DWORD dwPropId, + DWORD dwFlags, const void *pvData) +{ + PWINECRYPT_CERTSTORE store = (PWINECRYPT_CERTSTORE)hCertStore; + BOOL ret = FALSE; + + TRACE("(%p, %d, %08x, %p)\n", hCertStore, dwPropId, dwFlags, pvData); + + if (!store->properties) + store->properties = ContextPropertyList_Create(); + switch (dwPropId) + { + case CERT_ACCESS_STATE_PROP_ID: + SetLastError(E_INVALIDARG); + break; + default: + if (pvData) + { + const CRYPT_DATA_BLOB *blob = (const CRYPT_DATA_BLOB *)pvData; + + ret = ContextPropertyList_SetProperty(store->properties, dwPropId, + blob->pbData, blob->cbData); + } + else + { + ContextPropertyList_RemoveProperty(store->properties, dwPropId); + ret = TRUE; + } + } + return ret; +} + DWORD WINAPI CertEnumCTLContextProperties(PCCTL_CONTEXT pCTLContext, DWORD dwPropId) { diff --git a/dlls/crypt32/tests/store.c b/dlls/crypt32/tests/store.c index e464abbc21e..d00adb449e9 100644 --- a/dlls/crypt32/tests/store.c +++ b/dlls/crypt32/tests/store.c @@ -1426,6 +1426,79 @@ static void testCertEnumSystemStore(void) "Expected at least 3 stores\n"); } +static void testStoreProperty(void) +{ + HCERTSTORE store; + BOOL ret; + DWORD propID, size = 0, state; + CRYPT_DATA_BLOB blob; + + /* Crash + ret = CertGetStoreProperty(NULL, 0, NULL, NULL); + ret = CertGetStoreProperty(NULL, 0, NULL, &size); + ret = CertGetStoreProperty(store, 0, NULL, NULL); + */ + + store = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0, + CERT_STORE_CREATE_NEW_FLAG, NULL); + /* Check a missing prop ID */ + SetLastError(0xdeadbeef); + ret = CertGetStoreProperty(store, 0, NULL, &size); + ok(!ret && GetLastError() == CRYPT_E_NOT_FOUND, + "Expected CRYPT_E_NOT_FOUND, got %08x\n", GetLastError()); + /* Contrary to MSDN, CERT_ACCESS_STATE_PROP_ID is supported for stores.. */ + size = sizeof(state); + ret = CertGetStoreProperty(store, CERT_ACCESS_STATE_PROP_ID, &state, &size); + ok(ret, "CertGetStoreProperty failed for CERT_ACCESS_STATE_PROP_ID: %08x\n", + GetLastError()); + ok(!state, "Expected a non-persisted store\n"); + /* and CERT_STORE_LOCALIZED_NAME_PROP_ID isn't supported by default. */ + size = 0; + ret = CertGetStoreProperty(store, CERT_STORE_LOCALIZED_NAME_PROP_ID, NULL, + &size); + ok(!ret && GetLastError() == CRYPT_E_NOT_FOUND, + "Expected CRYPT_E_NOT_FOUND, got %08x\n", GetLastError()); + /* Delete an arbitrary property on a store */ + ret = CertSetStoreProperty(store, CERT_FIRST_USER_PROP_ID, 0, NULL); + ok(ret, "CertSetStoreProperty failed: %08x\n", GetLastError()); + /* Set an arbitrary property on a store */ + blob.pbData = (LPBYTE)&state; + blob.cbData = sizeof(state); + ret = CertSetStoreProperty(store, CERT_FIRST_USER_PROP_ID, 0, &blob); + ok(ret, "CertSetStoreProperty failed: %08x\n", GetLastError()); + /* Get an arbitrary property that's been set */ + ret = CertGetStoreProperty(store, CERT_FIRST_USER_PROP_ID, NULL, &size); + ok(ret, "CertGetStoreProperty failed: %08x\n", GetLastError()); + ok(size == sizeof(state), "Unexpected data size %d\n", size); + ret = CertGetStoreProperty(store, CERT_FIRST_USER_PROP_ID, &propID, &size); + ok(ret, "CertGetStoreProperty failed: %08x\n", GetLastError()); + ok(propID == state, "CertGetStoreProperty got the wrong value\n"); + /* Delete it again */ + ret = CertSetStoreProperty(store, CERT_FIRST_USER_PROP_ID, 0, NULL); + ok(ret, "CertSetStoreProperty failed: %08x\n", GetLastError()); + /* And check that it's missing */ + SetLastError(0xdeadbeef); + ret = CertGetStoreProperty(store, CERT_FIRST_USER_PROP_ID, NULL, &size); + ok(!ret && GetLastError() == CRYPT_E_NOT_FOUND, + "Expected CRYPT_E_NOT_FOUND, got %08x\n", GetLastError()); + CertCloseStore(store, 0); + + /* Recheck on the My store.. */ + store = CertOpenSystemStoreW(0, MyW); + size = sizeof(state); + ret = CertGetStoreProperty(store, CERT_ACCESS_STATE_PROP_ID, &state, &size); + ok(ret, "CertGetStoreProperty failed for CERT_ACCESS_STATE_PROP_ID: %08x\n", + GetLastError()); + ok(state, "Expected a persisted store\n"); + SetLastError(0xdeadbeef); + size = 0; + ret = CertGetStoreProperty(store, CERT_STORE_LOCALIZED_NAME_PROP_ID, NULL, + &size); + ok(!ret && GetLastError() == CRYPT_E_NOT_FOUND, + "Expected CRYPT_E_NOT_FOUND, got %08x\n", GetLastError()); + CertCloseStore(store, 0); +} + static void testAddSerialized(void) { BOOL ret; @@ -1593,6 +1666,7 @@ START_TEST(store) testCertOpenSystemStore(); testCertEnumSystemStore(); + testStoreProperty(); testAddSerialized(); }