[PATCH 2/3] crypt32: Add support for a particular ALG_ID to I_CryptGetDefaultCryptProv.

Dmitry Timoshkov dmitry at baikal.ru
Tue Nov 6 04:40:59 CST 2018


Based on a patch of Alexander Morozov.

Signed-off-by: Dmitry Timoshkov <dmitry at 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




More information about the wine-devel mailing list