diff --git a/dlls/crypt32/crypt32.spec b/dlls/crypt32/crypt32.spec index 4fc11b3ec62..0d08594c369 100644 --- a/dlls/crypt32/crypt32.spec +++ b/dlls/crypt32/crypt32.spec @@ -55,7 +55,7 @@ @ stdcall CertGetNameStringA(ptr long long ptr ptr long) @ stdcall CertGetNameStringW(ptr long long ptr ptr long) @ stub CertGetPublicKeyLength -@ stub CertGetSubjectCertificateFromStore +@ stdcall CertGetSubjectCertificateFromStore(ptr long ptr) @ stdcall CertGetValidUsages(long ptr ptr ptr ptr) @ stub CertIsRDNAttrsInCertificateName @ stdcall CertNameToStrA(long ptr long ptr long) diff --git a/dlls/crypt32/store.c b/dlls/crypt32/store.c index 495ca03b917..cf896f70d5d 100644 --- a/dlls/crypt32/store.c +++ b/dlls/crypt32/store.c @@ -866,9 +866,10 @@ static PWINECRYPT_CERTSTORE CRYPT_ProvOpenStore(LPCSTR lpszStoreProvider, dwFlags, pvPara, NULL, &provInfo); else { - PWINECRYPT_CERTSTORE memStore; + HCERTSTORE memStore; - memStore = CRYPT_MemOpenStore(hCryptProv, dwFlags, NULL); + memStore = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0, + CERT_STORE_CREATE_NEW_FLAG, NULL); if (memStore) { if (provOpenFunc(lpszStoreProvider, dwEncodingType, hCryptProv, @@ -2559,6 +2560,20 @@ PCCERT_CONTEXT WINAPI CertFindCertificateInStore(HCERTSTORE hCertStore, return ret; } +PCCERT_CONTEXT WINAPI CertGetSubjectCertificateFromStore(HCERTSTORE hCertStore, + DWORD dwCertEncodingType, PCERT_INFO pCertId) +{ + TRACE("(%p, %08lx, %p)\n", hCertStore, dwCertEncodingType, pCertId); + + if (!pCertId) + { + SetLastError(HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER)); + return NULL; + } + return CertFindCertificateInStore(hCertStore, dwCertEncodingType, 0, + CERT_FIND_SUBJECT_CERT, pCertId, NULL); +} + BOOL WINAPI CertAddStoreToCollection(HCERTSTORE hCollectionStore, HCERTSTORE hSiblingStore, DWORD dwUpdateFlags, DWORD dwPriority) { diff --git a/dlls/crypt32/tests/store.c b/dlls/crypt32/tests/store.c index c147afbd1c9..68356f7de79 100644 --- a/dlls/crypt32/tests/store.c +++ b/dlls/crypt32/tests/store.c @@ -261,6 +261,66 @@ static void testFindCert(void) } } +static void testGetSubjectCert(void) +{ + HCERTSTORE store; + + store = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0, + CERT_STORE_CREATE_NEW_FLAG, NULL); + ok(store, "CertOpenStore failed: %ld\n", GetLastError()); + if (store != NULL) + { + PCCERT_CONTEXT context1, context2; + CERT_INFO info = { 0 }; + BOOL ret; + + ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING, + bigCert, sizeof(bigCert), CERT_STORE_ADD_ALWAYS, NULL); + ok(ret, "CertAddEncodedCertificateToStore failed: %08lx\n", + GetLastError()); + ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING, + bigCert2, sizeof(bigCert2), CERT_STORE_ADD_NEW, &context1); + ok(ret, "CertAddEncodedCertificateToStore failed: %08lx\n", + GetLastError()); + ok(context1 != NULL, "Expected a context\n"); + ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING, + certWithUsage, sizeof(certWithUsage), CERT_STORE_ADD_NEW, NULL); + ok(ret, "CertAddEncodedCertificateToStore failed: %08lx\n", + GetLastError()); + + context2 = CertGetSubjectCertificateFromStore(store, X509_ASN_ENCODING, + NULL); + ok(!context2 && GetLastError() == + HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER), + "Expected HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER), got %08lx\n", + GetLastError()); + context2 = CertGetSubjectCertificateFromStore(store, X509_ASN_ENCODING, + &info); + ok(!context2 && GetLastError() == CRYPT_E_NOT_FOUND, + "Expected CRYPT_E_NOT_FOUND, got %08lx\n", GetLastError()); + info.SerialNumber.cbData = sizeof(serialNum); + info.SerialNumber.pbData = (LPBYTE)serialNum; + context2 = CertGetSubjectCertificateFromStore(store, X509_ASN_ENCODING, + &info); + ok(!context2 && GetLastError() == CRYPT_E_NOT_FOUND, + "Expected CRYPT_E_NOT_FOUND, got %08lx\n", GetLastError()); + info.Issuer.cbData = sizeof(subjectName2); + info.Issuer.pbData = (LPBYTE)subjectName2; + context2 = CertGetSubjectCertificateFromStore(store, X509_ASN_ENCODING, + &info); + ok(context2 != NULL, + "CertGetSubjectCertificateFromStore failed: %08lx\n", GetLastError()); + /* Not only should this find a context, but it should be the same + * (same address) as context1. + */ + ok(context1 == context2, "Expected identical context addresses\n"); + CertFreeCertificateContext(context2); + + CertFreeCertificateContext(context1); + CertCloseStore(store, 0); + } +} + static void testMemStore(void) { HCERTSTORE store1, store2; @@ -1534,6 +1594,7 @@ START_TEST(store) { testDupCert(); testFindCert(); + testGetSubjectCert(); /* various combinations of CertOpenStore */ testMemStore(); diff --git a/include/wincrypt.h b/include/wincrypt.h index 9784223e9bc..085d3107aee 100644 --- a/include/wincrypt.h +++ b/include/wincrypt.h @@ -2693,6 +2693,9 @@ PCCTL_CONTEXT WINAPI CertFindCTLInStore(HCERTSTORE hCertStore, DWORD dwCertEncodingType, DWORD dwFindFlags, DWORD dwFindType, const void *pvFindPara, PCCTL_CONTEXT pPrevCtlContext); +PCCERT_CONTEXT WINAPI CertGetSubjectCertificateFromStore(HCERTSTORE hCertStore, + DWORD dwCertEncodingType, PCERT_INFO pCertId); + BOOL WINAPI CertSerializeCertificateStoreElement(PCCERT_CONTEXT pCertContext, DWORD dwFlags, BYTE *pbElement, DWORD *pcbElement);