Nikolay Sivov : ntdll: Support pinning module refcount with LdrAddRefDll().

Alexandre Julliard julliard at winehq.org
Mon Oct 14 12:39:28 CDT 2013


Module: wine
Branch: master
Commit: 146ff49161fb35095ae9ac6f4c40281cd8f748f4
URL:    http://source.winehq.org/git/wine.git/?a=commit;h=146ff49161fb35095ae9ac6f4c40281cd8f748f4

Author: Nikolay Sivov <nsivov at codeweavers.com>
Date:   Mon Oct 14 08:07:58 2013 +0400

ntdll: Support pinning module refcount with LdrAddRefDll().

---

 dlls/ntdll/loader.c    |    7 ++++-
 dlls/ntdll/tests/rtl.c |   52 ++++++++++++++++++++++++++++++++++++++++++++++++
 include/winternl.h     |    3 ++
 3 files changed, 60 insertions(+), 2 deletions(-)

diff --git a/dlls/ntdll/loader.c b/dlls/ntdll/loader.c
index b1c7600..3a28b41 100644
--- a/dlls/ntdll/loader.c
+++ b/dlls/ntdll/loader.c
@@ -2124,13 +2124,16 @@ NTSTATUS WINAPI LdrAddRefDll( ULONG flags, HMODULE module )
     NTSTATUS ret = STATUS_SUCCESS;
     WINE_MODREF *wm;
 
-    if (flags) FIXME( "%p flags %x not implemented\n", module, flags );
+    if (flags & ~LDR_ADDREF_DLL_PIN) FIXME( "%p flags %x not implemented\n", module, flags );
 
     RtlEnterCriticalSection( &loader_section );
 
     if ((wm = get_modref( module )))
     {
-        if (wm->ldr.LoadCount != -1) wm->ldr.LoadCount++;
+        if (flags & LDR_ADDREF_DLL_PIN)
+            wm->ldr.LoadCount = -1;
+        else
+            if (wm->ldr.LoadCount != -1) wm->ldr.LoadCount++;
         TRACE( "(%s) ldr.LoadCount: %d\n", debugstr_w(wm->ldr.BaseDllName.Buffer), wm->ldr.LoadCount );
     }
     else ret = STATUS_INVALID_PARAMETER;
diff --git a/dlls/ntdll/tests/rtl.c b/dlls/ntdll/tests/rtl.c
index 38909a3..54e3db5 100644
--- a/dlls/ntdll/tests/rtl.c
+++ b/dlls/ntdll/tests/rtl.c
@@ -89,6 +89,7 @@ static IMAGE_BASE_RELOCATION *(WINAPI *pLdrProcessRelocationBlock)(void*,UINT,US
 static CHAR *    (WINAPI *pRtlIpv4AddressToStringA)(const IN_ADDR *, LPSTR);
 static NTSTATUS  (WINAPI *pRtlIpv4AddressToStringExA)(const IN_ADDR *, USHORT, LPSTR, PULONG);
 static NTSTATUS  (WINAPI *pRtlIpv4StringToAddressA)(PCSTR, BOOLEAN, PCSTR *, IN_ADDR *);
+static NTSTATUS  (WINAPI *pLdrAddRefDll)(ULONG, HMODULE);
 
 static HMODULE hkernel32 = 0;
 static BOOL      (WINAPI *pIsWow64Process)(HANDLE, PBOOL);
@@ -133,6 +134,7 @@ static void InitFunctionPtrs(void)
         pRtlIpv4AddressToStringA = (void *)GetProcAddress(hntdll, "RtlIpv4AddressToStringA");
         pRtlIpv4AddressToStringExA = (void *)GetProcAddress(hntdll, "RtlIpv4AddressToStringExA");
         pRtlIpv4StringToAddressA = (void *)GetProcAddress(hntdll, "RtlIpv4StringToAddressA");
+        pLdrAddRefDll = (void *)GetProcAddress(hntdll, "LdrAddRefDll");
     }
     hkernel32 = LoadLibraryA("kernel32.dll");
     ok(hkernel32 != 0, "LoadLibrary failed\n");
@@ -1486,6 +1488,55 @@ static void test_RtlIpv4StringToAddress(void)
     }
 }
 
+static void test_LdrAddRefDll(void)
+{
+    HMODULE mod, mod2;
+    NTSTATUS status;
+    BOOL ret;
+
+    mod = LoadLibraryA("comctl32.dll");
+    ok(mod != NULL, "got %p\n", mod);
+    ret = FreeLibrary(mod);
+    ok(ret, "got %d\n", ret);
+
+    mod2 = GetModuleHandleA("comctl32.dll");
+    ok(mod2 == NULL, "got %p\n", mod2);
+
+    /* load, addref and release 2 times */
+    mod = LoadLibraryA("comctl32.dll");
+    ok(mod != NULL, "got %p\n", mod);
+    status = pLdrAddRefDll(0, mod);
+    ok(status == STATUS_SUCCESS, "got 0x%08x\n", status);
+    ret = FreeLibrary(mod);
+    ok(ret, "got %d\n", ret);
+
+    mod2 = GetModuleHandleA("comctl32.dll");
+    ok(mod2 != NULL, "got %p\n", mod2);
+    ret = FreeLibrary(mod);
+    ok(ret, "got %d\n", ret);
+
+    mod2 = GetModuleHandleA("comctl32.dll");
+    ok(mod2 == NULL, "got %p\n", mod2);
+
+    /* pin refcount */
+    mod = LoadLibraryA("comctl32.dll");
+    ok(mod != NULL, "got %p\n", mod);
+    status = pLdrAddRefDll(LDR_ADDREF_DLL_PIN, mod);
+    ok(status == STATUS_SUCCESS, "got 0x%08x\n", status);
+
+    ret = FreeLibrary(mod);
+    ok(ret, "got %d\n", ret);
+    ret = FreeLibrary(mod);
+    ok(ret, "got %d\n", ret);
+    ret = FreeLibrary(mod);
+    ok(ret, "got %d\n", ret);
+    ret = FreeLibrary(mod);
+    ok(ret, "got %d\n", ret);
+
+    mod2 = GetModuleHandleA("comctl32.dll");
+    ok(mod2 != NULL, "got %p\n", mod2);
+}
+
 START_TEST(rtl)
 {
     InitFunctionPtrs();
@@ -1510,4 +1561,5 @@ START_TEST(rtl)
     test_RtlIpv4AddressToString();
     test_RtlIpv4AddressToStringEx();
     test_RtlIpv4StringToAddress();
+    test_LdrAddRefDll();
 }
diff --git a/include/winternl.h b/include/winternl.h
index c879450..d93b37a 100644
--- a/include/winternl.h
+++ b/include/winternl.h
@@ -1970,6 +1970,9 @@ typedef struct _LDR_MODULE
 #define LDR_DONT_RESOLVE_REFS           0x40000000
 #define LDR_WINE_INTERNAL               0x80000000
 
+/* flag for LdrAddRefDll */
+#define LDR_ADDREF_DLL_PIN              0x00000001
+
 /* FIXME: to be checked */
 #define MAXIMUM_FILENAME_LENGTH 256
 




More information about the wine-cvs mailing list