From 21dce1d02d896d86c8cda122adf09ec1b5ccf0d5 Mon Sep 17 00:00:00 2001 From: Juan Lang Date: Tue, 8 May 2007 17:09:21 -0700 Subject: [PATCH] crypt32: Implement CertEnumSystemStore. --- dlls/crypt32/crypt32.spec | 1 + dlls/crypt32/store.c | 87 ++++++++++++++++++++++++++++++++++++++ dlls/crypt32/tests/store.c | 48 +++++++++++++++++++++ 3 files changed, 136 insertions(+) diff --git a/dlls/crypt32/crypt32.spec b/dlls/crypt32/crypt32.spec index 7ee23f4e683..81e60234648 100644 --- a/dlls/crypt32/crypt32.spec +++ b/dlls/crypt32/crypt32.spec @@ -34,6 +34,7 @@ @ stdcall CertEnumCTLsInStore(ptr ptr) @ stdcall CertEnumCertificateContextProperties(ptr long) @ stdcall CertEnumCertificatesInStore(long ptr) +@ stdcall CertEnumSystemStore(long ptr ptr ptr) @ stdcall CertFindAttribute(str long ptr) @ stdcall CertFindCRLInStore(long long long long ptr ptr) @ stub CertFindCTLInStore diff --git a/dlls/crypt32/store.c b/dlls/crypt32/store.c index 77a75b12f63..b3c5fcd225a 100644 --- a/dlls/crypt32/store.c +++ b/dlls/crypt32/store.c @@ -2603,3 +2603,90 @@ void WINAPI CertRemoveStoreFromCollection(HCERTSTORE hCollectionStore, } LeaveCriticalSection(&collection->cs); } + +static LONG CRYPT_OpenParentStore(DWORD dwFlags, + void *pvSystemStoreLocationPara, HKEY *key) +{ + HKEY root; + LPCWSTR base; + + TRACE("(%08x, %p)\n", dwFlags, pvSystemStoreLocationPara); + + switch (dwFlags & CERT_SYSTEM_STORE_LOCATION_MASK) + { + case CERT_SYSTEM_STORE_LOCAL_MACHINE: + root = HKEY_LOCAL_MACHINE; + base = CERT_LOCAL_MACHINE_SYSTEM_STORE_REGPATH; + break; + case CERT_SYSTEM_STORE_CURRENT_USER: + root = HKEY_CURRENT_USER; + base = CERT_LOCAL_MACHINE_SYSTEM_STORE_REGPATH; + break; + case CERT_SYSTEM_STORE_CURRENT_SERVICE: + /* hklm\Software\Microsoft\Cryptography\Services\servicename\ + * SystemCertificates + */ + FIXME("CERT_SYSTEM_STORE_CURRENT_SERVICE\n"); + return ERROR_FILE_NOT_FOUND; + case CERT_SYSTEM_STORE_SERVICES: + /* hklm\Software\Microsoft\Cryptography\Services\servicename\ + * SystemCertificates + */ + FIXME("CERT_SYSTEM_STORE_SERVICES"); + return ERROR_FILE_NOT_FOUND; + case CERT_SYSTEM_STORE_USERS: + /* hku\user sid\Software\Microsoft\SystemCertificates */ + FIXME("CERT_SYSTEM_STORE_USERS\n"); + return ERROR_FILE_NOT_FOUND; + case CERT_SYSTEM_STORE_CURRENT_USER_GROUP_POLICY: + root = HKEY_CURRENT_USER; + base = CERT_GROUP_POLICY_SYSTEM_STORE_REGPATH; + break; + case CERT_SYSTEM_STORE_LOCAL_MACHINE_GROUP_POLICY: + root = HKEY_LOCAL_MACHINE; + base = CERT_GROUP_POLICY_SYSTEM_STORE_REGPATH; + break; + case CERT_SYSTEM_STORE_LOCAL_MACHINE_ENTERPRISE: + /* hklm\Software\Microsoft\EnterpriseCertificates */ + FIXME("CERT_SYSTEM_STORE_LOCAL_MACHINE_ENTERPRISE\n"); + return ERROR_FILE_NOT_FOUND; + default: + return ERROR_FILE_NOT_FOUND; + } + + return RegOpenKeyExW(root, base, 0, KEY_READ, key); +} + +BOOL WINAPI CertEnumSystemStore(DWORD dwFlags, void *pvSystemStoreLocationPara, + void *pvArg, PFN_CERT_ENUM_SYSTEM_STORE pfnEnum) +{ + BOOL ret = FALSE; + LONG rc; + HKEY key; + + TRACE("(%08x, %p, %p, %p)\n", dwFlags, pvSystemStoreLocationPara, pvArg, + pfnEnum); + + rc = CRYPT_OpenParentStore(dwFlags, pvArg, &key); + if (!rc) + { + DWORD index = 0; + CERT_SYSTEM_STORE_INFO info = { sizeof(info) }; + + ret = TRUE; + do { + WCHAR name[MAX_PATH]; + DWORD size = sizeof(name) / sizeof(name[0]); + + rc = RegEnumKeyExW(key, index++, name, &size, NULL, NULL, NULL, + NULL); + if (!rc) + ret = pfnEnum(name, 0, &info, NULL, pvArg); + } while (ret && !rc); + if (ret && rc != ERROR_NO_MORE_ITEMS) + SetLastError(rc); + } + else + SetLastError(rc); + return ret; +} diff --git a/dlls/crypt32/tests/store.c b/dlls/crypt32/tests/store.c index e251d98405a..e464abbc21e 100644 --- a/dlls/crypt32/tests/store.c +++ b/dlls/crypt32/tests/store.c @@ -1379,6 +1379,53 @@ static void testCertOpenSystemStore(void) RegDeleteKeyW(HKEY_CURRENT_USER, BogusPathW); } +struct EnumSystemStoreInfo +{ + BOOL goOn; + DWORD storeCount; +}; + +static BOOL CALLBACK enumSystemStoreCB(const void *systemStore, DWORD dwFlags, + PCERT_SYSTEM_STORE_INFO pStoreInfo, void *pvReserved, void *pvArg) +{ + struct EnumSystemStoreInfo *info = (struct EnumSystemStoreInfo *)pvArg; + + info->storeCount++; + return info->goOn; +} + +static void testCertEnumSystemStore(void) +{ + BOOL ret; + struct EnumSystemStoreInfo info = { FALSE, 0 }; + + SetLastError(0xdeadbeef); + ret = CertEnumSystemStore(0, NULL, NULL, NULL); + ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND, + "Expected ERROR_FILE_NOT_FOUND, got %08x\n", GetLastError()); + /* Crashes + ret = CertEnumSystemStore(CERT_SYSTEM_STORE_LOCAL_MACHINE, NULL, NULL, + NULL); + */ + + SetLastError(0xdeadbeef); + ret = CertEnumSystemStore(CERT_SYSTEM_STORE_LOCAL_MACHINE, NULL, &info, + enumSystemStoreCB); + /* Callback returning FALSE stops enumeration */ + ok(!ret, "Expected CertEnumSystemStore to stop\n"); + ok(info.storeCount == 0 || info.storeCount == 1, + "Expected 0 or 1 stores\n"); + + info.goOn = TRUE; + info.storeCount = 0; + ret = CertEnumSystemStore(CERT_SYSTEM_STORE_LOCAL_MACHINE, NULL, &info, + enumSystemStoreCB); + ok(ret, "CertEnumSystemStore failed: %08x\n", GetLastError()); + /* There should always be at least My, Root, and CA stores */ + ok(info.storeCount == 0 || info.storeCount >= 3, + "Expected at least 3 stores\n"); +} + static void testAddSerialized(void) { BOOL ret; @@ -1545,6 +1592,7 @@ START_TEST(store) testFileNameStore(); testCertOpenSystemStore(); + testCertEnumSystemStore(); testAddSerialized(); }