[Wine-patches] [2/2] crypt32: Use a provider which supports required algorithm (eterbug #5348).

Alexander Morozov amorozov на etersoft.ru
Вт Апр 20 17:53:06 MSD 2010


----------- следующая часть -----------
From aa77d71daf22d36162bf4411d65a21103d1955d2 Mon Sep 17 00:00:00 2001
From: Alexander Morozov <amorozov на etersoft.ru>
Date: Tue, 20 Apr 2010 16:52:44 +0400
Subject: [PATCH 2/2] crypt32: Use a provider which supports required algorithm (eterbug #5348).

---
 dlls/crypt32/msg.c |   72 ++++++++++++++++++++++++++++++++++++++++++++++++++-
 1 files changed, 70 insertions(+), 2 deletions(-)

diff --git a/dlls/crypt32/msg.c b/dlls/crypt32/msg.c
index a16eef1..bb89ae6 100644
--- a/dlls/crypt32/msg.c
+++ b/dlls/crypt32/msg.c
@@ -550,6 +550,71 @@ static BOOL CHashEncodeMsg_Update(HCRYPTMSG hCryptMsg, const BYTE *pbData,
     return ret;
 }
 
+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 };
+
+static BOOL CRYPT_AlgIsSupported(HCRYPTPROV hProv, ALG_ID algID)
+{
+    PROV_ENUMALGS provEnumalgs;
+    DWORD size = sizeof(provEnumalgs);
+
+    /* This enumeration is not thread safe */
+    EnterCriticalSection(&prov_param_cs);
+    if (CryptGetProvParam(hProv, PP_ENUMALGS, (BYTE *)&provEnumalgs, &size,
+     CRYPT_FIRST))
+    {
+        do {
+            if (algID == provEnumalgs.aiAlgid)
+                return TRUE;
+        } while (CryptGetProvParam(hProv, PP_ENUMALGS, (BYTE *)&provEnumalgs,
+         &size, CRYPT_NEXT));
+    }
+    LeaveCriticalSection(&prov_param_cs);
+    return FALSE;
+}
+
+static HCRYPTPROV CRYPT_GetProvForAlgId(ALG_ID algID)
+{
+    LPWSTR provName;
+    HCRYPTPROV prov;
+    DWORD i = 0, type, nameSize;
+
+    while (CryptEnumProvidersW(i, NULL, 0, &type, NULL, &nameSize))
+    {
+        provName = CryptMemAlloc(nameSize);
+        if (!provName)
+        {
+            SetLastError(ERROR_NOT_ENOUGH_MEMORY);
+            return 0;
+        }
+        if (!CryptEnumProvidersW(i, NULL, 0, &type, provName, &nameSize))
+        {
+            CryptMemFree(provName);
+            return 0;
+        }
+        if (!CryptAcquireContextW(&prov, NULL, provName, type,
+         CRYPT_VERIFYCONTEXT))
+        {
+            CryptMemFree(provName);
+            return 0;
+        }
+        CryptMemFree(provName);
+        if (CRYPT_AlgIsSupported(prov, algID))
+            return prov;
+        CryptReleaseContext(prov, 0);
+        ++i;
+    }
+    SetLastError(NTE_BAD_ALGID);
+    return 0;
+}
+
 static HCRYPTMSG CHashEncodeMsg_Open(DWORD dwFlags, const void *pvMsgEncodeInfo,
  LPSTR pszInnerContentObjID, PCMSG_STREAM_INFO pStreamInfo)
 {
@@ -572,8 +637,9 @@ static HCRYPTMSG CHashEncodeMsg_Open(DWORD dwFlags, const void *pvMsgEncodeInfo,
         prov = info->hCryptProv;
     else
     {
-        prov = CRYPT_GetDefaultProvider();
-        dwFlags &= ~CMSG_CRYPT_RELEASE_CONTEXT_FLAG;
+        prov = CRYPT_GetProvForAlgId(algID);
+        if (!prov) return NULL;
+        dwFlags |= CMSG_CRYPT_RELEASE_CONTEXT_FLAG;
     }
     msg = CryptMemAlloc(sizeof(CHashEncodeMsg));
     if (msg)
@@ -590,6 +656,8 @@ static HCRYPTMSG CHashEncodeMsg_Open(DWORD dwFlags, const void *pvMsgEncodeInfo,
             msg = NULL;
         }
     }
+    else if (dwFlags & CMSG_CRYPT_RELEASE_CONTEXT_FLAG)
+        CryptReleaseContext(prov, 0);
     return msg;
 }
 
-- 
1.6.5.8



Подробная информация о списке рассылки Wine-patches