ntdll/kernel32: #4

Eric Pouech eric.pouech at wanadoo.fr
Thu Mar 13 14:33:10 CST 2003


ChangeLog
- implementation of LdrUnloadDll out of loader/module.c
- in impacted functions, ensure that we only use ntdll functions
- making use of new LdrUnloadDll

A+
-- 
Eric Pouech
-------------- next part --------------
diff -u -x '*~' -x '.#*' dlls/ntdll3/loader.c dlls/ntdll/loader.c
--- dlls/ntdll3/loader.c	2003-03-07 10:25:57.000000000 +0100
+++ dlls/ntdll/loader.c	2003-03-07 13:24:21.000000000 +0100
@@ -25,8 +25,15 @@
 #include "wine/exception.h"
 #include "excpt.h"
 #include "wine/debug.h"
+#include "wine/server.h"
+#include "ntdll_misc.h"
 
 WINE_DEFAULT_DEBUG_CHANNEL(ntdll);
+WINE_DECLARE_DEBUG_CHANNEL(module);
+WINE_DECLARE_DEBUG_CHANNEL(module);
+WINE_DECLARE_DEBUG_CHANNEL(loaddll);
+
+static int free_lib_count;   /* recursion depth of FreeLibrary calls */
 
 /* filter for page-fault exceptions */
 static WINE_EXCEPTION_FILTER(page_fault)
@@ -154,7 +161,6 @@
     if ((wm = MODULE32_LookupHMODULE( hModule )))
     {
         retproc = wm->find_export( wm, function, hint, snoop );
-        if (!retproc) SetLastError(ERROR_PROC_NOT_FOUND);
     }
     RtlLeaveCriticalSection( &loader_section );
     return retproc;
@@ -172,7 +178,7 @@
 
     *address = MODULE_GetProcAddress( base, name ? name->Buffer : (LPSTR)ord, -1, TRUE );
 
-    return (*address) ? STATUS_SUCCESS : STATUS_DLL_NOT_FOUND;
+    return (*address) ? STATUS_SUCCESS : STATUS_PROCEDURE_NOT_FOUND;
 }
 
 
@@ -217,6 +223,131 @@
 }
 
 /***********************************************************************
+ *           MODULE_FlushModrefs
+ *
+ * NOTE: Assumes that the process critical section is held!
+ *
+ * Remove all unused modrefs and call the internal unloading routines
+ * for the library type.
+ */
+static void MODULE_FlushModrefs(void)
+{
+    WINE_MODREF *wm, *next;
+
+    for (wm = MODULE_modref_list; wm; wm = next)
+    {
+        next = wm->next;
+
+        if (wm->refCount)
+            continue;
+
+        /* Unlink this modref from the chain */
+        if (wm->next)
+            wm->next->prev = wm->prev;
+        if (wm->prev)
+            wm->prev->next = wm->next;
+        if (wm == MODULE_modref_list)
+            MODULE_modref_list = wm->next;
+
+        TRACE(" unloading %s\n", wm->filename);
+        if (!TRACE_ON(module))
+            TRACE_(loaddll)("Unloaded module '%s' : %s\n", wm->filename,
+                            wm->dlhandle ? "builtin" : "native" );
+
+        SERVER_START_REQ( unload_dll )
+        {
+            req->base = (void *)wm->module;
+            wine_server_call( req );
+        }
+        SERVER_END_REQ;
+
+        if (wm->dlhandle) wine_dll_unload( wm->dlhandle );
+        else UnmapViewOfFile( (LPVOID)wm->module );
+        FreeLibrary16( wm->hDummyMod );
+        RtlFreeHeap( ntdll_get_process_heap(), 0, wm->deps );
+        RtlFreeHeap( ntdll_get_process_heap(), 0, wm );
+    }
+}
+
+/***********************************************************************
+ *           MODULE_DecRefCount
+ *
+ * NOTE: Assumes that the process critical section is held!
+ */
+static void MODULE_DecRefCount( WINE_MODREF *wm )
+{
+    int i;
+
+    if ( wm->flags & WINE_MODREF_MARKER )
+        return;
+
+    if ( wm->refCount <= 0 )
+        return;
+
+    --wm->refCount;
+    TRACE("(%s) refCount: %d\n", wm->modname, wm->refCount );
+
+    if ( wm->refCount == 0 )
+    {
+        wm->flags |= WINE_MODREF_MARKER;
+
+        for ( i = 0; i < wm->nDeps; i++ )
+            if ( wm->deps[i] )
+                MODULE_DecRefCount( wm->deps[i] );
+
+        wm->flags &= ~WINE_MODREF_MARKER;
+    }
+}
+
+/******************************************************************
+ *		LdrUnloadDll (NTDLL.@)
+ *
+ *
+ */
+NTSTATUS WINAPI LdrUnloadDll( HMODULE hModule )
+{
+    NTSTATUS retv = STATUS_SUCCESS;
+
+    TRACE("(%p)\n", hModule);
+
+    RtlEnterCriticalSection( &loader_section );
+
+    /* if we're stopping the whole process (and forcing the removal of all
+     * DLLs) the library will be freed anyway
+     */
+    if (!process_detaching)
+    {
+        WINE_MODREF *wm;
+
+        free_lib_count++;
+        if ((wm = MODULE32_LookupHMODULE( hModule )) != NULL)
+        {
+            TRACE("(%s) - START\n", wm->modname);
+
+            /* Recursively decrement reference counts */
+            MODULE_DecRefCount( wm );
+
+            /* Call process detach notifications */
+            if ( free_lib_count <= 1 )
+            {
+                MODULE_DllProcessDetach( FALSE, NULL );
+                MODULE_FlushModrefs();
+            }
+
+            TRACE("END\n");
+        }
+        else
+            retv = STATUS_DLL_NOT_FOUND;
+
+        free_lib_count--;
+    }
+
+    RtlLeaveCriticalSection( &loader_section );
+
+    return retv;
+}
+
+/***********************************************************************
  *           RtlImageNtHeader   (NTDLL.@)
  */
 PIMAGE_NT_HEADERS WINAPI RtlImageNtHeader(HMODULE hModule)
diff -u -x '*~' -x '.#*' dlls/ntdll3/ntdll_misc.h dlls/ntdll/ntdll_misc.h
--- dlls/ntdll3/ntdll_misc.h	2003-03-07 10:25:57.000000000 +0100
+++ dlls/ntdll/ntdll_misc.h	2003-03-07 10:31:34.000000000 +0100
@@ -21,6 +21,7 @@
 
 #include "winnt.h"
 #include "winternl.h"
+#include "thread.h"
 
 /* debug helper */
 extern LPCSTR debugstr_us( const UNICODE_STRING *str );
@@ -29,4 +30,10 @@
 /* module handling */
 extern FARPROC MODULE_GetProcAddress( HMODULE hModule, LPCSTR function, int hint, BOOL snoop );
 
+static inline HANDLE ntdll_get_process_heap(void)
+{
+    HANDLE *pdb = (HANDLE *)NtCurrentTeb()->process;
+    return pdb[0x18 / sizeof(HANDLE)];  /* get dword at offset 0x18 in pdb */
+}
+
 #endif
diff -u -x '*~' -x '.#*' dlls/ntdll3/ntdll.spec dlls/ntdll/ntdll.spec
--- dlls/ntdll3/ntdll.spec	2003-03-04 07:47:39.000000000 +0100
+++ dlls/ntdll/ntdll.spec	2003-03-07 10:49:41.000000000 +0100
@@ -48,7 +48,7 @@
 @ stub LdrQueryProcessModuleInformation
 @ stdcall LdrShutdownProcess() LdrShutdownProcess
 @ stdcall LdrShutdownThread() LdrShutdownThread
-@ stub LdrUnloadDll
+@ stdcall LdrUnloadDll(ptr) LdrUnloadDll
 @ stub LdrVerifyImageMatchesChecksum
 @ stub NPXEMULATORTABLE
 @ extern NlsAnsiCodePage NlsAnsiCodePage
diff -u -x '*~' -x '.#*' include3/module.h include/module.h
--- include3/module.h	2003-03-07 10:26:00.000000000 +0100
+++ include/module.h	2003-03-07 06:58:46.000000000 +0100
@@ -194,12 +194,10 @@
 
 /* module.c */
 extern WINE_MODREF *MODULE_AllocModRef( HMODULE hModule, LPCSTR filename );
-extern FARPROC MODULE_GetProcAddress( HMODULE hModule, LPCSTR function, int hint, BOOL snoop );
 extern BOOL MODULE_DllProcessAttach( WINE_MODREF *wm, LPVOID lpReserved );
 extern void MODULE_DllProcessDetach( BOOL bForceDetach, LPVOID lpReserved );
 extern void MODULE_DllThreadAttach( LPVOID lpReserved );
 extern WINE_MODREF *MODULE_LoadLibraryExA( LPCSTR libname, HANDLE hfile, DWORD flags );
-extern BOOL MODULE_FreeLibrary( WINE_MODREF *wm );
 extern WINE_MODREF *MODULE_FindModule( LPCSTR path );
 extern HMODULE16 MODULE_CreateDummyModule( LPCSTR filename, HMODULE module32 );
 extern enum binary_type MODULE_GetBinaryType( HANDLE hfile );
diff -u -x '*~' -x '.#*' loader3/module.c loader/module.c
--- loader3/module.c	2003-03-07 10:26:01.000000000 +0100
+++ loader/module.c	2003-03-07 13:26:09.000000000 +0100
@@ -48,7 +48,6 @@
 WINE_MODREF *MODULE_modref_list = NULL;
 
 WINE_MODREF *exe_modref;
-static int free_lib_count;   /* recursion depth of FreeLibrary calls */
 int process_detaching = 0;  /* set on process detach to avoid deadlocks with thread detach */
 
 CRITICAL_SECTION loader_section = CRITICAL_SECTION_INIT( "loader_section" );
@@ -1083,7 +1082,7 @@
 		if ( !MODULE_DllProcessAttach( wm, NULL ) )
 		{
 			WARN_(module)("Attach failed for module '%s'.\n", libname);
-			MODULE_FreeLibrary(wm);
+			LdrUnloadDll(wm->module);
 			SetLastError(ERROR_DLL_INIT_FAILED);
 			wm = NULL;
 		}
@@ -1334,66 +1333,13 @@
 }
 
 /***********************************************************************
- *           MODULE_FlushModrefs
- *
- * NOTE: Assumes that the process critical section is held!
- *
- * Remove all unused modrefs and call the internal unloading routines
- * for the library type.
- */
-static void MODULE_FlushModrefs(void)
-{
-	WINE_MODREF *wm, *next;
-
-	for(wm = MODULE_modref_list; wm; wm = next)
-	{
-		next = wm->next;
-
-		if(wm->refCount)
-			continue;
-
-		/* Unlink this modref from the chain */
-		if(wm->next)
-                        wm->next->prev = wm->prev;
-		if(wm->prev)
-                        wm->prev->next = wm->next;
-		if(wm == MODULE_modref_list)
-			MODULE_modref_list = wm->next;
-
-                TRACE(" unloading %s\n", wm->filename);
-                if (!TRACE_ON(module))
-                    TRACE_(loaddll)("Unloaded module '%s' : %s\n", wm->filename,
-                                    wm->dlhandle ? "builtin" : "native" );
-
-                SERVER_START_REQ( unload_dll )
-                {
-                    req->base = (void *)wm->module;
-                    wine_server_call( req );
-                }
-                SERVER_END_REQ;
-
-                if (wm->dlhandle) wine_dll_unload( wm->dlhandle );
-                else UnmapViewOfFile( (LPVOID)wm->module );
-                FreeLibrary16(wm->hDummyMod);
-                HeapFree( GetProcessHeap(), 0, wm->deps );
-                HeapFree( GetProcessHeap(), 0, wm );
-	}
-}
-
-/***********************************************************************
  *           FreeLibrary   (KERNEL32.@)
  *           FreeLibrary32 (KERNEL.486)
  */
 BOOL WINAPI FreeLibrary(HINSTANCE hLibModule)
 {
-    BOOL retv = FALSE;
-    WINE_MODREF *wm;
-
-    if (!hLibModule)
-    {
-        SetLastError( ERROR_INVALID_HANDLE );
-        return FALSE;
-    }
+    BOOL                retv = FALSE;
+    NTSTATUS            nts;
 
     if ((ULONG_PTR)hLibModule & 1)
     {
@@ -1402,81 +1348,21 @@
         UnmapViewOfFile( ptr );
         return TRUE;
     }
-
-    RtlEnterCriticalSection( &loader_section );
-
-    /* if we're stopping the whole process (and forcing the removal of all
-     * DLLs) the library will be freed anyway
-     */
-    if (process_detaching) retv = TRUE;
-    else
+    
+    if (!hLibModule)
     {
-        free_lib_count++;
-        if ((wm = MODULE32_LookupHMODULE( hLibModule ))) retv = MODULE_FreeLibrary( wm );
-        free_lib_count--;
+        SetLastError( ERROR_INVALID_HANDLE );
+        RtlLeaveCriticalSection( &loader_section );
+        return FALSE;
     }
 
-    RtlLeaveCriticalSection( &loader_section );
+    if ((nts = LdrUnloadDll( hLibModule )) == STATUS_SUCCESS) retv = TRUE;
+    else SetLastError( RtlNtStatusToDosError( nts ) );
 
     return retv;
 }
 
 /***********************************************************************
- *           MODULE_DecRefCount
- *
- * NOTE: Assumes that the process critical section is held!
- */
-static void MODULE_DecRefCount( WINE_MODREF *wm )
-{
-    int i;
-
-    if ( wm->flags & WINE_MODREF_MARKER )
-        return;
-
-    if ( wm->refCount <= 0 )
-        return;
-
-    --wm->refCount;
-    TRACE("(%s) refCount: %d\n", wm->modname, wm->refCount );
-
-    if ( wm->refCount == 0 )
-    {
-        wm->flags |= WINE_MODREF_MARKER;
-
-        for ( i = 0; i < wm->nDeps; i++ )
-            if ( wm->deps[i] )
-                MODULE_DecRefCount( wm->deps[i] );
-
-        wm->flags &= ~WINE_MODREF_MARKER;
-    }
-}
-
-/***********************************************************************
- *           MODULE_FreeLibrary
- *
- * NOTE: Assumes that the process critical section is held!
- */
-BOOL MODULE_FreeLibrary( WINE_MODREF *wm )
-{
-    TRACE("(%s) - START\n", wm->modname );
-
-    /* Recursively decrement reference counts */
-    MODULE_DecRefCount( wm );
-
-    /* Call process detach notifications */
-    if ( free_lib_count <= 1 )
-    {
-        MODULE_DllProcessDetach( FALSE, NULL );
-        MODULE_FlushModrefs();
-    }
-
-    TRACE("END\n");
-
-    return TRUE;
-}
-
-
-/***********************************************************************
  *           FreeLibraryAndExitThread (KERNEL32.@)
  */
 VOID WINAPI FreeLibraryAndExitThread(HINSTANCE hLibModule, DWORD dwExitCode)


More information about the wine-patches mailing list