- implementation of LdrUnloadDll out of loader/module.c
authorEric Pouech <eric.pouech@wanadoo.fr>
Fri, 14 Mar 2003 04:00:52 +0000 (04:00 +0000)
committerAlexandre Julliard <julliard@winehq.org>
Fri, 14 Mar 2003 04:00:52 +0000 (04:00 +0000)
- in impacted functions, ensure that we only use ntdll functions
- making use of new LdrUnloadDll

dlls/ntdll/loader.c
dlls/ntdll/ntdll.spec
dlls/ntdll/ntdll_misc.h
include/module.h
loader/module.c

index d72db1d0bf6c3c5ff6296f5218e1841e56fd76de..541c465a8ccc37092d38963ccbb3b8359291eb8f 100644 (file)
 #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 @@ FARPROC MODULE_GetProcAddress(
     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 @@ NTSTATUS WINAPI LdrGetProcedureAddress(HMODULE base, PANSI_STRING name, ULONG or
 
     *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;
 }
 
 
@@ -216,6 +222,131 @@ NTSTATUS WINAPI LdrShutdownThread(void)
     return STATUS_SUCCESS; /* FIXME */
 }
 
+/***********************************************************************
+ *           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.@)
  */
index 39e2c848bbda3e5a64f43e111b94fae0b6f7091a..64d848e63de5e81a75a3b9495791a79478d4a2df 100644 (file)
@@ -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
index 618001ecad403ade78f752ba484c34295c7bed71..38ebcb40c858570b45284245e82b60b5008b9f3b 100644 (file)
@@ -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 @@ extern void dump_ObjectAttributes (const OBJECT_ATTRIBUTES *ObjectAttributes);
 /* 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
index b8688fe8b20d0d68aa0e5043ada4a0cda02a33e2..195eaf57a6c1720195051d7b7b63b4903be4dcb6 100644 (file)
@@ -194,12 +194,10 @@ enum binary_type
 
 /* 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 );
index a27d5cc31f8453d0bd7bcd0b9af4d515da36f09a..649de9ce28b622e585dd9a07330e6677062ada50 100644 (file)
@@ -48,7 +48,6 @@ WINE_DECLARE_DEBUG_CHANNEL(loaddll);
 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 @@ HMODULE WINAPI LoadLibraryExA(LPCSTR libname, HANDLE hfile, DWORD flags)
                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;
                }
@@ -1333,67 +1332,14 @@ HMODULE WINAPI LoadLibraryExW(LPCWSTR libnameW,HANDLE hfile,DWORD flags)
     return ret;
 }
 
-/***********************************************************************
- *           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,80 +1348,20 @@ BOOL WINAPI FreeLibrary(HINSTANCE hLibModule)
         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.@)
  */