- implementation of LdrUnloadDll out of loader/module.c
- in impacted functions, ensure that we only use ntdll functions - making use of new LdrUnloadDll
This commit is contained in:
parent
580da246f5
commit
1efa50e47e
|
@ -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 @@ 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.@)
|
||||
*/
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 );
|
||||
|
|
134
loader/module.c
134
loader/module.c
|
@ -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.@)
|
||||
*/
|
||||
|
|
Loading…
Reference in New Issue