Commit 4c6988e8 authored by Juan Lang's avatar Juan Lang Committed by Alexandre Julliard

crypt32: Implement CertGetStoreProperty and CertSetStoreProperty.

parent 0170a41e
......@@ -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)
......
......@@ -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)
{
......
......@@ -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();
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment