#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)
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;
*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;
}
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.@)
*/
@ stub LdrQueryProcessModuleInformation
@ stdcall LdrShutdownProcess() LdrShutdownProcess
@ stdcall LdrShutdownThread() LdrShutdownThread
-@ stub LdrUnloadDll
+@ stdcall LdrUnloadDll(ptr) LdrUnloadDll
@ stub LdrVerifyImageMatchesChecksum
@ stub NPXEMULATORTABLE
@ extern NlsAnsiCodePage NlsAnsiCodePage
#include "winnt.h"
#include "winternl.h"
+#include "thread.h"
/* debug helper */
extern LPCSTR debugstr_us( const UNICODE_STRING *str );
/* 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
/* 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 );
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" );
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;
}
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)
{
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.@)
*/