Based on a patch of Alexander Morozov.
Signed-off-by: Dmitry Timoshkov <dmitry(a)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;
}
--
2.17.1