[PATCH] crypt32: CryptFreeOIDFunctionAddress should not unload a registered module.

Dmitry Timoshkov dmitry at baikal.ru
Wed Oct 31 07:43:08 CDT 2018


MSDN states that hModule passed to CryptInstallOIDFunctionAddress() should be
used to prevent this module to be unloaded by CryptFreeOIDFunctionAddress in
case the provider's DLL uses CryptRegisterOIDFunction to add its own entries.

This patch fixes a crash that is caused by exactly this scenario.

Signed-off-by: Dmitry Timoshkov <dmitry at baikal.ru>
---
 dlls/crypt32/oid.c | 43 ++++++++++++++++++++++++++++++++++++++++---
 1 file changed, 40 insertions(+), 3 deletions(-)

diff --git a/dlls/crypt32/oid.c b/dlls/crypt32/oid.c
index d6c411c791..6dc894e60c 100644
--- a/dlls/crypt32/oid.c
+++ b/dlls/crypt32/oid.c
@@ -59,6 +59,7 @@ struct OIDFunctionSet
 
 struct OIDFunction
 {
+    HMODULE hModule;
     DWORD encoding;
     CRYPT_OID_FUNC_ENTRY entry;
     struct list next;
@@ -271,6 +272,7 @@ BOOL WINAPI CryptInstallOIDFunctionAddress(HMODULE hModule,
                 else
                     func->entry.pszOID = rgFuncEntry[i].pszOID;
                 func->entry.pvFuncAddr = rgFuncEntry[i].pvFuncAddr;
+                func->hModule = hModule;
                 list_add_tail(&set->functions, &func->next);
             }
             else
@@ -428,6 +430,38 @@ BOOL WINAPI CryptGetOIDFunctionAddress(HCRYPTOIDFUNCSET hFuncSet,
     return ret;
 }
 
+static BOOL is_module_registered(HMODULE hModule)
+{
+    struct OIDFunctionSet *set;
+    BOOL ret = FALSE;
+
+    EnterCriticalSection(&funcSetCS);
+
+    LIST_FOR_EACH_ENTRY(set, &funcSets, struct OIDFunctionSet, next)
+    {
+        struct OIDFunction *function;
+
+        EnterCriticalSection(&set->cs);
+
+        LIST_FOR_EACH_ENTRY(function, &set->functions, struct OIDFunction, next)
+        {
+            if (function->hModule == hModule)
+            {
+                ret = TRUE;
+                break;
+            }
+        }
+
+        LeaveCriticalSection(&set->cs);
+
+        if (ret) break;
+    }
+
+    LeaveCriticalSection(&funcSetCS);
+
+    return ret;
+}
+
 BOOL WINAPI CryptFreeOIDFunctionAddress(HCRYPTOIDFUNCADDR hFuncAddr,
  DWORD dwFlags)
 {
@@ -441,9 +475,12 @@ BOOL WINAPI CryptFreeOIDFunctionAddress(HCRYPTOIDFUNCADDR hFuncAddr,
     {
         struct FuncAddr *addr = hFuncAddr;
 
-        CryptMemFree(addr->dllList);
-        FreeLibrary(addr->lib);
-        CryptMemFree(addr);
+        if (!is_module_registered(addr->lib))
+        {
+            CryptMemFree(addr->dllList);
+            FreeLibrary(addr->lib);
+            CryptMemFree(addr);
+        }
     }
     return TRUE;
 }
-- 
2.17.1




More information about the wine-devel mailing list