- 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
(Alexandre, in order to handle correctly the loader_critsect between ntdll & kernel32, what do you suggest ? NT does it thru the fastpeblock in the PEB, which we don't implement. shall we add to the PDB in some unused field (which means we do export the PDB struct out of scheduler/process.c, but you seemed to reluctant to do so so far)
A+ -- Eric Pouech
diff -u -x '*~' -x '.#*' dlls/ntdll5/loader.c dlls/ntdll/loader.c --- dlls/ntdll5/loader.c 2003-03-09 16:01:11.000000000 +0100 +++ dlls/ntdll/loader.c 2003-03-12 21:15:00.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) ? + ((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,36 @@ 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 ); + if (!addr) + { + wm = exe_modref; + } + else 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 * @@ -547,6 +622,8 @@ if (wm->dlhandle) wine_dll_unload( wm->dlhandle ); else UnmapViewOfFile( (LPVOID)wm->module ); FreeLibrary16(wm->hDummyMod); + RtlFreeUnicodeString( &wm->ldr.FullDllName ); + RtlFreeUnicodeString( &wm->ldr.BaseDllName ); RtlFreeHeap( ntdll_get_process_heap(), 0, wm->deps ); RtlFreeHeap( ntdll_get_process_heap(), 0, wm ); } diff -u -x '*~' -x '.#*' dlls/ntdll5/ntdll.spec dlls/ntdll/ntdll.spec --- dlls/ntdll5/ntdll.spec 2003-03-07 11:11:19.000000000 +0100 +++ dlls/ntdll/ntdll.spec 2003-03-09 15:10:40.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-07 12:38:05.000000000 +0100 +++ include/module.h 2003-03-12 21:27:49.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-07 06:01:03.000000000 +0100 +++ include/winternl.h 2003-03-09 15:16:01.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-09 14:50:22.000000000 +0100 +++ loader/module.c 2003-03-12 21:15:09.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,30 +70,6 @@ /************************************************************************* - * 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 */ BOOL MODULE_InitDLL( WINE_MODREF *wm, DWORD type, LPVOID lpReserved ) @@ -947,9 +921,9 @@ LPSTR lpFileName, /* [out] filenamebuffer */ DWORD size ) /* [in] size of filenamebuffer */ { - RtlEnterCriticalSection( &loader_section ); - lpFileName[0] = 0; + + RtlEnterCriticalSection( &loader_section ); if (!hModule && !(NtCurrentTeb()->tibflags & TEBF_WIN32)) { /* 16-bit task - get current NE module name */ @@ -958,11 +932,18 @@ } else { - WINE_MODREF *wm = MODULE32_LookupHMODULE( hModule ); - if (wm) lstrcpynA( lpFileName, wm->filename, size ); - } + LDR_MODULE* pldr; + if (LdrFindEntryForAddress( hModule, &pldr) == STATUS_SUCCESS) + { + WideCharToMultiByte( CP_ACP, 0, + pldr->FullDllName.Buffer, pldr->FullDllName.Length, + lpFileName, size, NULL, NULL ); + lpFileName[size - 1] = '\0'; + } + } RtlLeaveCriticalSection( &loader_section ); + TRACE("%s\n", lpFileName ); return strlen(lpFileName); } @@ -973,12 +954,37 @@ */ 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 ); + 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 ); + GetLongPathNameW(path, lpFileName, size); + } + } + else + { + LDR_MODULE* pldr; + + if (LdrFindEntryForAddress( hModule, &pldr) == STATUS_SUCCESS) + { + size = min(pldr->FullDllName.Length / sizeof(WCHAR), size - 1); + strncpyW( lpFileName, pldr->FullDllName.Buffer, size ); + lpFileName[size] = '\0'; + } + } + + RtlLeaveCriticalSection( &loader_section ); + + TRACE("%s\n", debugstr_w(lpFileName) ); return strlenW(lpFileName); }