- added LDR_MODULE structure to WINE_MODREF and made dummy filling of this structure
- implementation of LdrFindEntry
- implementation of GetModuleFileName[AW] on top of LdrFindEntry
(from previous version, NULL address testing remains in kernel32, as NT does)
A+ -- Eric Pouech
diff -u -x '*~' -x '.#*' dlls/ntdll5/loader.c dlls/ntdll/loader.c --- dlls/ntdll5/loader.c 2003-03-15 08:46:31.000000000 +0100 +++ dlls/ntdll/loader.c 2003-03-15 09:57:50.000000000 +0100 @@ -16,6 +16,8 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ +#include <assert.h> + #include "winbase.h" #include "winnt.h" #include "winternl.h" @@ -33,7 +35,7 @@ WINE_DECLARE_DEBUG_CHANNEL(module); WINE_DECLARE_DEBUG_CHANNEL(loaddll); -static int free_lib_count; /* recursion depth of FreeLibrary calls */ +static int free_lib_count; /* recursion depth of LdrUnloadDll calls */ /* filter for page-fault exceptions */ static WINE_EXCEPTION_FILTER(page_fault) @@ -43,6 +45,29 @@ return EXCEPTION_CONTINUE_SEARCH; } +CRITICAL_SECTION loader_section = CRITICAL_SECTION_INIT( "loader_section" ); + +/************************************************************************* + * MODULE32_LookupHMODULE + * looks for the referenced HMODULE in the current process + * NOTE: Assumes that the process critical section is held! + */ +static WINE_MODREF *MODULE32_LookupHMODULE( HMODULE hmod ) +{ + WINE_MODREF *wm; + + if (!hmod) + return exe_modref; + + if (!HIWORD(hmod)) { + ERR("tried to lookup %p in win32 module handler!\n",hmod); + return NULL; + } + for ( wm = MODULE_modref_list; wm; wm=wm->next ) + if (wm->module == hmod) + return wm; + return NULL; +} /************************************************************************* * MODULE_AllocModRef @@ -53,6 +78,7 @@ WINE_MODREF *MODULE_AllocModRef( HMODULE hModule, LPCSTR filename ) { WINE_MODREF *wm; + IMAGE_NT_HEADERS *nt = RtlImageNtHeader(hModule); DWORD long_len = strlen( filename ); DWORD short_len = GetShortPathNameA( filename, NULL, 0 ); @@ -77,7 +103,26 @@ if (wm->next) wm->next->prev = wm; MODULE_modref_list = wm; - if (!(RtlImageNtHeader(hModule)->FileHeader.Characteristics & IMAGE_FILE_DLL)) + wm->ldr.InLoadOrderModuleList.Flink = NULL; + wm->ldr.InLoadOrderModuleList.Blink = NULL; + wm->ldr.InMemoryOrderModuleList.Flink = NULL; + wm->ldr.InMemoryOrderModuleList.Blink = NULL; + wm->ldr.InInitializationOrderModuleList.Flink = NULL; + wm->ldr.InInitializationOrderModuleList.Blink = NULL; + wm->ldr.BaseAddress = hModule; + wm->ldr.EntryPoint = (nt->OptionalHeader.AddressOfEntryPoint) ? + (void*)((ULONG)hModule + nt->OptionalHeader.AddressOfEntryPoint) : 0; + wm->ldr.SizeOfImage = nt->OptionalHeader.SizeOfImage; + RtlCreateUnicodeStringFromAsciiz( &wm->ldr.FullDllName, wm->filename); + RtlCreateUnicodeStringFromAsciiz( &wm->ldr.BaseDllName, wm->modname); + wm->ldr.Flags = 0; + wm->ldr.LoadCount = 0; + wm->ldr.TlsIndex = 0; + wm->ldr.SectionHandle = NULL; + wm->ldr.CheckSum = 0; + wm->ldr.TimeDateStamp = 0; + + if (!(nt->FileHeader.Characteristics & IMAGE_FILE_DLL)) { if (!exe_modref) exe_modref = wm; else FIXME( "Trying to load second .EXE file: %s\n", filename ); @@ -108,6 +153,32 @@ return ret; } +/****************************************************************** + * LdrFindEntryForAddress (NTDLL.@) + * + */ +NTSTATUS WINAPI LdrFindEntryForAddress(const void* addr, PLDR_MODULE* mod) +{ + WINE_MODREF* wm; + NTSTATUS nts = STATUS_NO_MORE_ENTRIES; + + RtlEnterCriticalSection( &loader_section ); + for ( wm = MODULE_modref_list; wm; wm = wm->next ) + { + if ((const void*)wm->module <= addr && + addr < (const void*)((const char*)wm->module + wm->ldr.SizeOfImage)) + break; + } + if (wm) + { + *mod = &wm->ldr; + nts = STATUS_SUCCESS; + } + RtlLeaveCriticalSection( &loader_section ); + + return nts; +} + /********************************************************************** * MODULE_FindModule * diff -u -x '*~' -x '.#*' dlls/ntdll5/ntdll.spec dlls/ntdll/ntdll.spec --- dlls/ntdll5/ntdll.spec 2003-03-15 08:44:53.000000000 +0100 +++ dlls/ntdll/ntdll.spec 2003-03-15 08:49:00.000000000 +0100 @@ -36,7 +36,7 @@ @ stub LdrAccessResource @ stdcall LdrDisableThreadCalloutsForDll(long) LdrDisableThreadCalloutsForDll @ stub LdrEnumResources -@ stub LdrFindEntryForAddress +@ stdcall LdrFindEntryForAddress(ptr ptr) LdrFindEntryForAddress @ stub LdrFindResourceDirectory_U @ stub LdrFindResource_U @ stdcall LdrGetDllHandle(long long ptr ptr) LdrGetDllHandle diff -u -x '*~' -x '.#*' include5/module.h include/module.h --- include5/module.h 2003-03-15 11:08:29.000000000 +0100 +++ include/module.h 2003-03-15 13:08:19.000000000 +0100 @@ -134,7 +134,7 @@ HMODULE16 hDummyMod; /* Win16 dummy module */ void *dlhandle; /* handle returned by dlopen() */ int tlsindex; /* TLS index or -1 if none */ - + LDR_MODULE ldr; FARPROC (*find_export)( struct _wine_modref *wm, LPCSTR func, int hint, BOOL snoop ); @@ -210,7 +210,6 @@ extern CRITICAL_SECTION loader_section; extern int process_detaching; extern BOOL MODULE_InitDLL( WINE_MODREF *wm, DWORD type, LPVOID lpReserved ); -extern WINE_MODREF* MODULE32_LookupHMODULE( HMODULE ); /* loader/ne/module.c */ extern NE_MODULE *NE_GetPtr( HMODULE16 hModule ); diff -u -x '*~' -x '.#*' include5/winternl.h include/winternl.h --- include5/winternl.h 2003-03-15 08:44:55.000000000 +0100 +++ include/winternl.h 2003-03-15 08:49:00.000000000 +0100 @@ -1184,7 +1184,7 @@ } LDR_RESOURCE_INFO, *PLDR_RESOURCE_INFO; NTSTATUS WINAPI LdrDisableThreadCalloutsForDll(HMODULE); -NTSTATUS WINAPI LdrFindEntryForAddress(void*, PLDR_MODULE*); +NTSTATUS WINAPI LdrFindEntryForAddress(const void*, PLDR_MODULE*); NTSTATUS WINAPI LdrGetDllHandle(ULONG, ULONG, PUNICODE_STRING, HMODULE*); NTSTATUS WINAPI LdrGetProcedureAddress(HMODULE, PANSI_STRING, ULONG, void**); NTSTATUS WINAPI LdrLoadDll(LPCWSTR, DWORD, PUNICODE_STRING, HMODULE*); diff -u -x '*~' -x '.#*' loader5/module.c loader/module.c --- loader5/module.c 2003-03-15 08:48:36.000000000 +0100 +++ loader/module.c 2003-03-15 15:06:59.000000000 +0100 @@ -50,8 +50,6 @@ WINE_MODREF *exe_modref; int process_detaching = 0; /* set on process detach to avoid deadlocks with thread detach */ -CRITICAL_SECTION loader_section = CRITICAL_SECTION_INIT( "loader_section" ); - /*********************************************************************** * wait_input_idle * @@ -72,31 +70,7 @@ /************************************************************************* - * MODULE32_LookupHMODULE - * looks for the referenced HMODULE in the current process - * NOTE: Assumes that the process critical section is held! - */ -WINE_MODREF *MODULE32_LookupHMODULE( HMODULE hmod ) -{ - WINE_MODREF *wm; - - if (!hmod) - return exe_modref; - - if (!HIWORD(hmod)) { - ERR("tried to lookup %p in win32 module handler!\n",hmod); - SetLastError( ERROR_INVALID_HANDLE ); - return NULL; - } - for ( wm = MODULE_modref_list; wm; wm=wm->next ) - if (wm->module == hmod) - return wm; - SetLastError( ERROR_INVALID_HANDLE ); - return NULL; -} - -/************************************************************************* - * MODULE_InitDLL + * MODULE_InitDLL */ BOOL MODULE_InitDLL( WINE_MODREF *wm, DWORD type, LPVOID lpReserved ) { @@ -123,6 +97,7 @@ return retv; } + /************************************************************************* * MODULE_DllProcessAttach * @@ -947,24 +922,36 @@ LPSTR lpFileName, /* [out] filenamebuffer */ DWORD size ) /* [in] size of filenamebuffer */ { - RtlEnterCriticalSection( &loader_section ); + DWORD len = 0; lpFileName[0] = 0; + + RtlEnterCriticalSection( &loader_section ); if (!hModule && !(NtCurrentTeb()->tibflags & TEBF_WIN32)) { /* 16-bit task - get current NE module name */ NE_MODULE *pModule = NE_GetPtr( GetCurrentTask() ); - if (pModule) GetLongPathNameA(NE_MODULE_NAME(pModule), lpFileName, size); + if (pModule) len = GetLongPathNameA(NE_MODULE_NAME(pModule), lpFileName, size); } - else + else if (hModule || LdrGetDllHandle( 0, 0, NULL, &hModule ) == STATUS_SUCCESS) { - WINE_MODREF *wm = MODULE32_LookupHMODULE( hModule ); - if (wm) lstrcpynA( lpFileName, wm->filename, size ); - } + LDR_MODULE* pldr; + NTSTATUS nts; + nts = LdrFindEntryForAddress( hModule, &pldr ); + if (nts == STATUS_SUCCESS) + { + WideCharToMultiByte( CP_ACP, 0, + pldr->FullDllName.Buffer, pldr->FullDllName.Length, + lpFileName, size, NULL, NULL ); + len = min(size, pldr->FullDllName.Length / sizeof(WCHAR)); + } + else SetLastError( RtlNtStatusToDosError( nts ) ); + } RtlLeaveCriticalSection( &loader_section ); - TRACE("%s\n", lpFileName ); - return strlen(lpFileName); + + TRACE( "%s\n", debugstr_an(lpFileName, len) ); + return len; } @@ -973,13 +960,43 @@ */ DWORD WINAPI GetModuleFileNameW( HMODULE hModule, LPWSTR lpFileName, DWORD size ) { - LPSTR fnA = HeapAlloc( GetProcessHeap(), 0, size * 2 ); - if (!fnA) return 0; - GetModuleFileNameA( hModule, fnA, size * 2 ); - if (size > 0 && !MultiByteToWideChar( CP_ACP, 0, fnA, -1, lpFileName, size )) - lpFileName[size-1] = 0; - HeapFree( GetProcessHeap(), 0, fnA ); - return strlenW(lpFileName); + DWORD len = 0; + + lpFileName[0] = 0; + + RtlEnterCriticalSection( &loader_section ); + if (!hModule && !(NtCurrentTeb()->tibflags & TEBF_WIN32)) + { + /* 16-bit task - get current NE module name */ + NE_MODULE *pModule = NE_GetPtr( GetCurrentTask() ); + if (pModule) + { + WCHAR path[MAX_PATH]; + + MultiByteToWideChar( CP_ACP, 0, NE_MODULE_NAME(pModule), -1, + path, MAX_PATH ); + len = GetLongPathNameW(path, lpFileName, size); + } + } + else if (hModule || LdrGetDllHandle( 0, 0, NULL, &hModule ) == STATUS_SUCCESS) + { + LDR_MODULE* pldr; + NTSTATUS nts; + + nts = LdrFindEntryForAddress( hModule, &pldr ); + if (nts == STATUS_SUCCESS) + { + len = min(size, pldr->FullDllName.Length / sizeof(WCHAR)); + strncpyW(lpFileName, pldr->FullDllName.Buffer, len); + if (len < size) lpFileName[len] = 0; + } + else SetLastError( RtlNtStatusToDosError( nts ) ); + + } + RtlLeaveCriticalSection( &loader_section ); + + TRACE( "%s\n", debugstr_wn(lpFileName, len) ); + return len; } /******************************************************************