Based on a patch of Alexander Morozov.
Signed-off-by: Dmitry Timoshkov dmitry@baikal.ru --- dlls/crypt32/crypt32_private.h | 2 +- dlls/crypt32/main.c | 73 ++++++++++++++++++++++++++++++---- dlls/crypt32/tests/main.c | 2 +- 3 files changed, 68 insertions(+), 9 deletions(-)
diff --git a/dlls/crypt32/crypt32_private.h b/dlls/crypt32/crypt32_private.h index c6e20120fc..1b390f4a92 100644 --- a/dlls/crypt32/crypt32_private.h +++ b/dlls/crypt32/crypt32_private.h @@ -149,7 +149,7 @@ BOOL WINAPI CRYPT_AsnEncodePubKeyInfoNoNull(DWORD dwCertEncodingType, /* Returns a handle to the default crypto provider; loads it if necessary. * Returns NULL on failure. */ -HCRYPTPROV WINAPI I_CryptGetDefaultCryptProv(DWORD); +HCRYPTPROV WINAPI I_CryptGetDefaultCryptProv(ALG_ID);
HINSTANCE hInstance DECLSPEC_HIDDEN;
diff --git a/dlls/crypt32/main.c b/dlls/crypt32/main.c index d37bf4a712..d0643f4107 100644 --- a/dlls/crypt32/main.c +++ b/dlls/crypt32/main.c @@ -35,6 +35,16 @@ WINE_DEFAULT_DEBUG_CHANNEL(crypt); static HCRYPTPROV hDefProv; HINSTANCE hInstance;
+static CRITICAL_SECTION prov_param_cs; +static CRITICAL_SECTION_DEBUG prov_param_cs_debug = +{ + 0, 0, &prov_param_cs, + { &prov_param_cs_debug.ProcessLocksList, + &prov_param_cs_debug.ProcessLocksList }, + 0, 0, { (DWORD_PTR)(__FILE__ ": prov_param_cs") } +}; +static CRITICAL_SECTION prov_param_cs = { &prov_param_cs_debug, -1, 0, 0, 0, 0 }; + BOOL WINAPI DllMain(HINSTANCE hInst, DWORD fdwReason, PVOID pvReserved) { switch (fdwReason) @@ -174,20 +184,69 @@ BOOL WINAPI I_CryptGetOssGlobal(DWORD x) return FALSE; }
-HCRYPTPROV WINAPI DECLSPEC_HOTPATCH I_CryptGetDefaultCryptProv(DWORD reserved) +static BOOL is_supported_algid(HCRYPTPROV prov, ALG_ID algid) +{ + PROV_ENUMALGS prov_algs; + DWORD size = sizeof(prov_algs); + BOOL ret = FALSE; + + /* This enumeration is not thread safe */ + EnterCriticalSection(&prov_param_cs); + if (CryptGetProvParam(prov, PP_ENUMALGS, (BYTE *)&prov_algs, &size, CRYPT_FIRST)) + { + do + { + if (prov_algs.aiAlgid == algid) + { + ret = TRUE; + break; + } + } while (CryptGetProvParam(prov, PP_ENUMALGS, (BYTE *)&prov_algs, &size, CRYPT_NEXT)); + } + LeaveCriticalSection(&prov_param_cs); + return ret; +} + +HCRYPTPROV WINAPI DECLSPEC_HOTPATCH I_CryptGetDefaultCryptProv(ALG_ID algid) { - HCRYPTPROV ret; + HCRYPTPROV prov, defprov; + + TRACE("(%08x)\n", algid);
- TRACE("(%08x)\n", reserved); + defprov = CRYPT_GetDefaultProvider();
- if (reserved) + if (algid && !is_supported_algid(defprov, algid)) { + DWORD i = 0, type, size; + + while (CryptEnumProvidersW(i, NULL, 0, &type, NULL, &size)) + { + WCHAR *name = CryptMemAlloc(size); + if (name) + { + if (CryptEnumProvidersW(i, NULL, 0, &type, name, &size)) + { + if (CryptAcquireContextW(&prov, NULL, name, type, CRYPT_VERIFYCONTEXT)) + { + if (is_supported_algid(prov, algid)) + { + CryptMemFree(name); + return prov; + } + CryptReleaseContext(prov, 0); + } + } + CryptMemFree(name); + } + i++; + } + SetLastError(E_INVALIDARG); return 0; } - ret = CRYPT_GetDefaultProvider(); - CryptContextAddRef(ret, NULL, 0); - return ret; + + CryptContextAddRef(defprov, NULL, 0); + return defprov; }
BOOL WINAPI I_CryptReadTrustedPublisherDWORDValueFromRegistry(LPCWSTR name, diff --git a/dlls/crypt32/tests/main.c b/dlls/crypt32/tests/main.c index a490c51e3f..6a031527d8 100644 --- a/dlls/crypt32/tests/main.c +++ b/dlls/crypt32/tests/main.c @@ -357,7 +357,7 @@ static void test_getDefaultCryptProv(void) prov = pI_CryptGetDefaultCryptProv(test_prov[i].algid); if (!prov) { -todo_wine_if(!test_prov[i].optional) +todo_wine_if(test_prov[i].algid == CALG_DSS_SIGN || test_prov[i].algid == CALG_NO_SIGN) ok(test_prov[i].optional, "%u: I_CryptGetDefaultCryptProv(%#x) failed\n", i, test_prov[i].algid); continue; }