what's new:
- a few more implemented functions (LdrQueryProcessModuleInformation)
- a few more used fields in the LDR_MODULE structure (mainly the internal lists)
- better split of resource related functions
- a few cleanups
daredevils can try to play with it :-O
A+
--
Eric Pouech
Name: ntkrnl ChangeLog: started splitting kernel & ntdll regarding module management License: X11 GenDate: 2003/01/11 17:07:45 UTC ModifiedFiles: dlls/ntdll/loader.c dlls/ntdll/ntdll.spec include/module.h loader/elf.c loader/module.c loader/pe_image.c loader/pe_resource.c loader/resource.c misc/version.c relay32/builtin32.c relay32/relay386.c scheduler/process.c scheduler/thread.c tools/winebuild/spec16.c AddedFiles: =================================================================== RCS file: /home/cvs/cvsroot/wine/wine/dlls/ntdll/loader.c,v retrieving revision 1.8 diff -u -u -r1.8 loader.c --- dlls/ntdll/loader.c 12 Dec 2002 23:34:02 -0000 1.8 +++ dlls/ntdll/loader.c 14 Dec 2002 20:17:22 -0000 @@ -36,49 +36,6 @@ } -NTSTATUS WINAPI LdrDisableThreadCalloutsForDll(HANDLE hModule) -{ - if (DisableThreadLibraryCalls(hModule)) - return STATUS_SUCCESS; - else - return STATUS_DLL_NOT_FOUND; -} - -/* FIXME : MODULE_FindModule should depend on LdrGetDllHandle, not vice-versa */ - -NTSTATUS WINAPI LdrGetDllHandle(ULONG x, LONG y, PUNICODE_STRING name, PVOID *base) -{ - STRING str; - WINE_MODREF *wm; - - FIXME("%08lx %08lx %s %p : partial stub\n",x,y,debugstr_wn(name->Buffer,name->Length),base); - - *base = 0; - - RtlUnicodeStringToAnsiString(&str, name, TRUE); - wm = MODULE_FindModule(str.Buffer); - if(!wm) - return STATUS_DLL_NOT_FOUND; - *base = (PVOID) wm->module; - - return STATUS_SUCCESS; -} - -/* FIXME : MODULE_GetProcAddress should depend on LdrGetProcedureAddress, not vice-versa */ - -NTSTATUS WINAPI LdrGetProcedureAddress(PVOID base, PANSI_STRING name, ULONG ord, PVOID *address) -{ - WARN("%p %s %ld %p\n",base, debugstr_an(name->Buffer,name->Length), ord, address); - - if(name) - *address = MODULE_GetProcAddress( (HMODULE) base, name->Buffer, -1, FALSE); - else - *address = MODULE_GetProcAddress( (HMODULE) base, (LPSTR) ord, -1, FALSE); - - return (*address) ? STATUS_SUCCESS : STATUS_DLL_NOT_FOUND; -} - - /*********************************************************************** * RtlImageNtHeader (NTDLL.@) */ Index: dlls/ntdll/ntdll.spec =================================================================== RCS file: /home/cvs/cvsroot/wine/wine/dlls/ntdll/ntdll.spec,v retrieving revision 1.86 diff -u -u -r1.86 ntdll.spec --- dlls/ntdll/ntdll.spec 12 Dec 2002 02:20:47 -0000 1.86 +++ dlls/ntdll/ntdll.spec 10 Jan 2003 20:12:18 -0000 @@ -33,22 +33,22 @@ @ stub KiUserApcDispatcher @ stub KiUserCallbackDispatcher @ stub KiUserExceptionDispatcher -@ stub LdrAccessResource +@ stdcall LdrAccessResource(ptr ptr ptr ptr) LdrAccessResource @ stdcall LdrDisableThreadCalloutsForDll(long) LdrDisableThreadCalloutsForDll @ stub LdrEnumResources -@ stub LdrFindEntryForAddress -@ stub LdrFindResourceDirectory_U -@ stub LdrFindResource_U +@ stdcall LdrFindEntryForAddress(ptr ptr) LdrFindEntryForAddress +@ stdcall LdrFindResourceDirectory_U(ptr ptr long ptr) LdrFindResourceDirectory_U +@ stdcall LdrFindResource_U(ptr ptr long ptr) LdrFindResource_U @ stdcall LdrGetDllHandle(long long ptr ptr) LdrGetDllHandle @ stdcall LdrGetProcedureAddress(ptr ptr long ptr) LdrGetProcedureAddress @ stub LdrInitializeThunk -@ stub LdrLoadDll +@ stdcall LdrLoadDll(str long ptr ptr) LdrLoadDll @ stub LdrProcessRelocationBlock @ stub LdrQueryImageFileExecutionOptions -@ stub LdrQueryProcessModuleInformation -@ stub LdrShutdownProcess -@ stub LdrShutdownThread -@ stub LdrUnloadDll +@ stdcall LdrQueryProcessModuleInformation(ptr long ptr) LdrQueryProcessModuleInformation +@ stdcall LdrShutdownProcess() LdrShutdownProcess +@ stdcall LdrShutdownThread() LdrShutdownThread +@ stdcall LdrUnloadDll(long) LdrUnloadDll @ stub LdrVerifyImageMatchesChecksum @ stub NPXEMULATORTABLE @ extern NlsAnsiCodePage NlsAnsiCodePage Index: include/module.h =================================================================== RCS file: /home/cvs/cvsroot/wine/wine/include/module.h,v retrieving revision 1.69 diff -u -u -r1.69 module.h --- include/module.h 16 Aug 2002 20:02:54 -0000 1.69 +++ include/module.h 11 Jan 2003 15:45:31 -0000 @@ -23,9 +23,93 @@ #include "windef.h" #include "winbase.h" +#include "winternl.h" #include "wine/windef16.h" #include "wine/winbase16.h" +/* FIXME: which place ? + * a few macros for double linked list manipulation + */ +#define InitializeListHead(head_list) ((head_list)->Flink = (head_list)->Blink = (head_list)) +#define IsListEmpty(head_list) ((head_list)->Flink == (head_list)) +#define RemoveHeadList(head_list) RemoveEntryList((head_list)->Flink) +#define RemoveTailList(head_list) RemoveEntryList((head_list)->Blink) +#define RemoveEntryList(entry) {\ + PLIST_ENTRY bl = (entry)->Flink, fl = (entry)->Blink; \ + bl->Flink = fl; fl->Blink = bl;} +#define InsertTailList(head_list,entry) {\ + PLIST_ENTRY bl = (head_list)->Blink, hl = (head_list);\ + (entry)->Flink = hl; (entry)->Blink = bl; bl->Flink = (entry); hl->Blink = (entry);} +#define InsertHeadList(head_list,entry) {\ + PLIST_ENTRY fl = head_list->Flink, hl = (head_list);\ + (entry)->Flink = fl; (entry)->Blink = hl; fl->Blink = (entry); hl->Flink = (entry);} + +#define RESOURCE_TYPE_LEVEL 0 +#define RESOURCE_NAME_LEVEL 1 +#define RESOURCE_LANGUAGE_LEVEL 2 +#define RESOURCE_DATA_LEVEL 3 + +typedef struct _LDR_RESOURCE_INFO +{ + ULONG Type; + ULONG Name; + ULONG Language; +} LDR_RESOURCE_INFO, *PLDR_RESOURCE_INFO; + +/* FIXME: the WINE_MODREF structure should include this structure */ +typedef struct _LDR_MODULE +{ + LIST_ENTRY InLoadOrderModuleList; /* not used */ + LIST_ENTRY InMemoryOrderModuleList;/* not used */ + LIST_ENTRY InInitializationOrderModuleList;/* not used */ + void* BaseAddress; + ULONG EntryPoint; /* not used */ + ULONG SizeOfImage; /* not used */ + UNICODE_STRING FullDllName; + UNICODE_STRING BaseDllName; + ULONG Flags; + SHORT LoadCount; /* number of refs to this module */ + SHORT TlsIndex; /* TLS index or -1 if none */ + HANDLE SectionHandle; /* not used */ + ULONG CheckSum; /* not used */ + ULONG TimeDateStamp; /* not used */ +} LDR_MODULE, *PLDR_MODULE; + +/* FIXME: to be checked */ +#define MAXIMUM_FILENAME_LENGTH 256 + +typedef struct _SYSTEM_MODULE +{ + ULONG Reserved1; + ULONG Reserved2; + PVOID ImageBaseAddress; + ULONG ImageSize; + ULONG Flags; + WORD Id; + WORD Rank; + WORD w018; + WORD NameOffset; + BYTE Name[MAXIMUM_FILENAME_LENGTH]; +} SYSTEM_MODULE, *PSYSTEM_MODULE; + +typedef struct _SYSTEM_MODULE_INFORMATION +{ + ULONG ModulesCount; + SYSTEM_MODULE Modules[0]; +} SYSTEM_MODULE_INFORMATION, *PSYSTEM_MODULE_INFORMATION; + + +/* Flags bit mask */ +#define WINE_MODREF_INTERNAL 0x00000001 +#define WINE_MODREF_NO_DLL_CALLS 0x00000002 +#define WINE_MODREF_PROCESS_ATTACHED 0x00000004 +#define WINE_MODREF_DONT_RESOLVE_REFS 0x00000020 +#define WINE_MODREF_MARKER 0x80000000 + +/* those following definitions are only for within NTDLL */ + +#if defined(_NTSYSTEM_) || defined(_KERNEL32_) + /* In-memory module structure. See 'Windows Internals' p. 219 */ typedef struct _NE_MODULE { @@ -114,6 +198,7 @@ FARPROC16 SetOwner; /* Set Owner procedure, exported by wine */ } SELFLOADHEADER; +#if 0 typedef struct { LPSTR lpEnvAddress; @@ -121,6 +206,7 @@ UINT16 *lpCmdShow; DWORD dwReserved; } LOADPARAMS; +#endif #include "poppack.h" @@ -129,10 +215,8 @@ { struct _wine_modref *next; struct _wine_modref *prev; - HMODULE module; HMODULE16 hDummyMod; /* Win16 dummy module */ void *dlhandle; /* handle returned by dlopen() */ - int tlsindex; /* TLS index or -1 if none */ FARPROC (*find_export)( struct _wine_modref *wm, LPCSTR func, int hint, BOOL snoop ); @@ -140,23 +224,16 @@ int nDeps; struct _wine_modref **deps; - int flags; - int refCount; + char *filename; + char *modname; - char *filename; - char *modname; char *short_filename; char *short_modname; - char data[1]; /* space for storing filename and short_filename */ + LDR_MODULE ldr_module; + char data[1]; /* space for storing filename and short_filename */ } WINE_MODREF; -#define WINE_MODREF_INTERNAL 0x00000001 -#define WINE_MODREF_NO_DLL_CALLS 0x00000002 -#define WINE_MODREF_PROCESS_ATTACHED 0x00000004 -#define WINE_MODREF_DONT_RESOLVE_REFS 0x00000020 -#define WINE_MODREF_MARKER 0x80000000 - extern WINE_MODREF *MODULE_modref_list; /* Resource types */ @@ -197,11 +274,8 @@ 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 void MODULE_DllThreadDetach( LPVOID lpReserved ); -extern WINE_MODREF *MODULE_LoadLibraryExA( LPCSTR libname, HANDLE hfile, DWORD flags ); -extern BOOL MODULE_FreeLibrary( WINE_MODREF *wm ); +extern WINE_MODREF *MODULE_LoadLibraryExA( LPCSTR libname, DWORD flags ); extern WINE_MODREF *MODULE_FindModule( LPCSTR path ); extern HMODULE16 MODULE_CreateDummyModule( LPCSTR filename, HMODULE module32 ); extern enum binary_type MODULE_GetBinaryType( HANDLE hfile ); @@ -222,7 +296,7 @@ extern DWORD NE_StartTask(void); /* loader/ne/resource.c */ -extern HGLOBAL16 WINAPI NE_DefResourceHandler(HGLOBAL16,HMODULE16,HRSRC16); +/* EPP extern HGLOBAL16 WINAPI NE_DefResourceHandler(HGLOBAL16,HMODULE16,HRSRC16); */ extern BOOL NE_InitResourceHandler( HMODULE16 hModule ); extern HRSRC NE_FindResource( NE_MODULE *pModule, LPCSTR name, LPCSTR type ); extern DWORD NE_SizeofResource( NE_MODULE *pModule, HRSRC hRsrc ); @@ -246,8 +320,6 @@ /* loader/pe_resource.c */ extern HRSRC PE_FindResourceW(HMODULE,LPCWSTR,LPCWSTR); extern HRSRC PE_FindResourceExW(HMODULE,LPCWSTR,LPCWSTR,WORD); -extern DWORD PE_SizeofResource(HRSRC); -extern HGLOBAL PE_LoadResource(HMODULE,HRSRC); /* loader/pe_image.c */ extern WINE_MODREF *PE_LoadLibraryExA(LPCSTR, DWORD); @@ -275,7 +347,9 @@ /* if1632/builtin.c */ extern HMODULE16 BUILTIN_LoadModule( LPCSTR name ); extern BOOL BUILTIN_IsPresent( LPCSTR name ); +#endif +#if defined(_NTSYSTEM_) || defined(_KERNEL32_) || defined(_USER32_) /* USER signal proc flags and codes */ /* See PROCESS_CallUserSignalProc for comments */ #define USIG_FLAGS_WIN32 0x0001 @@ -299,5 +373,20 @@ /* scheduler/process.c */ extern void PROCESS_CallUserSignalProc( UINT uCode, HMODULE16 hModule ); +#endif + +NTSTATUS WINAPI LdrDisableThreadCalloutsForDll(HMODULE); +NTSTATUS WINAPI LdrFindEntryForAddress(void*, PLDR_MODULE*); +NTSTATUS WINAPI LdrGetDllHandle(ULONG, ULONG, PUNICODE_STRING, void**); +NTSTATUS WINAPI LdrGetProcedureAddress(HMODULE, PANSI_STRING, ULONG, void**); +NTSTATUS WINAPI LdrLoadDll(LPCSTR, DWORD, PUNICODE_STRING, void**); +NTSTATUS WINAPI LdrShutdownThread(void); +NTSTATUS WINAPI LdrShutdownProcess(void); +NTSTATUS WINAPI LdrUnloadDll(HMODULE); +NTSTATUS WINAPI LdrAccessResource(HMODULE, PIMAGE_RESOURCE_DATA_ENTRY, void**, PULONG); +NTSTATUS WINAPI LdrFindResourceDirectory_U(HMODULE, PLDR_RESOURCE_INFO, DWORD, + PIMAGE_RESOURCE_DIRECTORY_ENTRY*); +NTSTATUS WINAPI LdrFindResource_U(HMODULE, PLDR_RESOURCE_INFO, ULONG, + PIMAGE_RESOURCE_DATA_ENTRY*); #endif /* __WINE_MODULE_H */ Index: loader/elf.c =================================================================== RCS file: /home/cvs/cvsroot/wine/wine/loader/elf.c,v retrieving revision 1.39 diff -u -u -r1.39 elf.c --- loader/elf.c 9 Aug 2002 19:57:39 -0000 1.39 +++ loader/elf.c 22 Dec 2002 13:56:12 -0000 @@ -221,7 +221,7 @@ * dlls using cdecl. If we find out the number of args the function * uses, we remove them from the stack using two small stubs. */ - stub = first_stub = (ELF_STDCALL_STUB *)((char *)wm->module + STUBOFFSET); + stub = first_stub = (ELF_STDCALL_STUB *)((char *)wm->ldr_module.BaseAddress + STUBOFFSET); for (i=0;i<STUBSIZE/sizeof(ELF_STDCALL_STUB);i++) { if (!stub->origfun) break; @@ -276,6 +276,6 @@ FIXME("function %s not found: %s\n",funcName,error); return fun; } - fun = SNOOP_GetProcAddress(wm->module,funcName,stub-first_stub,fun); + fun = SNOOP_GetProcAddress(wm->ldr_module.BaseAddress,funcName,stub-first_stub,fun); return (FARPROC)fun; } Index: loader/module.c =================================================================== RCS file: /home/cvs/cvsroot/wine/wine/loader/module.c,v retrieving revision 1.170 diff -u -u -r1.170 module.c --- loader/module.c 5 Dec 2002 19:56:15 -0000 1.170 +++ loader/module.c 11 Jan 2003 14:38:35 -0000 @@ -45,6 +45,10 @@ WINE_DECLARE_DEBUG_CHANNEL(win32); WINE_DECLARE_DEBUG_CHANNEL(loaddll); +/* FIXME FIXME */ +#define _KERNEL32_ + +#ifdef _NTSYSTEM_ WINE_MODREF *MODULE_modref_list = NULL; static WINE_MODREF *exe_modref; @@ -52,7 +56,9 @@ static int process_detaching; /* set on process detach to avoid deadlocks with thread detach */ static CRITICAL_SECTION loader_section = CRITICAL_SECTION_INIT( "loader_section" ); +#endif +#ifdef _KERNEL32_ /*********************************************************************** * wait_input_idle * @@ -70,8 +76,9 @@ } return 0; } +#endif - +#ifdef _NTSYSTEM_ /************************************************************************* * MODULE32_LookupHMODULE * looks for the referenced HMODULE in the current process @@ -86,13 +93,11 @@ 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) + if (wm->ldr_module.BaseAddress == (void*)hmod) return wm; - SetLastError( ERROR_INVALID_HANDLE ); return NULL; } @@ -109,11 +114,13 @@ DWORD long_len = strlen( filename ); DWORD short_len = GetShortPathNameA( filename, NULL, 0 ); - if ((wm = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, - sizeof(*wm) + long_len + short_len + 1 ))) - { - wm->module = hModule; - wm->tlsindex = -1; + /* FIXME: GetProcessHeap isn't part of NTDLL */ + if ((wm = RtlAllocateHeap( GetProcessHeap(), HEAP_ZERO_MEMORY, + sizeof(*wm) + long_len + short_len + 1 ))) + { + wm->ldr_module.BaseAddress = (void*)hModule; + wm->ldr_module.SizeOfImage = 1; /* FIXME */ + wm->ldr_module.TlsIndex = -1; wm->filename = wm->data; memcpy( wm->filename, filename, long_len + 1 ); @@ -121,19 +128,73 @@ else wm->modname = wm->filename; wm->short_filename = wm->filename + long_len + 1; - GetShortPathNameA( wm->filename, wm->short_filename, short_len + 1 ); + GetShortPathNameA( filename, wm->short_filename, short_len + 1 ); if ((wm->short_modname = strrchr( wm->short_filename, '\\' ))) wm->short_modname++; else wm->short_modname = wm->short_filename; + RtlCreateUnicodeStringFromAsciiz( &wm->ldr_module.FullDllName, wm->filename); + RtlCreateUnicodeStringFromAsciiz( &wm->ldr_module.BaseDllName, wm->modname); + wm->next = MODULE_modref_list; if (wm->next) wm->next->prev = wm; MODULE_modref_list = wm; if (!(RtlImageNtHeader(hModule)->FileHeader.Characteristics & IMAGE_FILE_DLL)) { - if (!exe_modref) exe_modref = wm; + if (!exe_modref) + { + exe_modref = wm; + InitializeListHead(&exe_modref->ldr_module.InLoadOrderModuleList); + InitializeListHead(&exe_modref->ldr_module.InMemoryOrderModuleList); + InitializeListHead(&exe_modref->ldr_module.InInitializationOrderModuleList); + } else FIXME( "Trying to load second .EXE file: %s\n", filename ); } + else + { + WINE_MODREF* mwm; + WINE_MODREF* before = NULL; + + if (!exe_modref) + { + /* FIXME: today, ntdll gets loaded before the process itself (because of the + * ELF level dependency from wine executable on ntdll.dll.so + * As a result, we won't link the ntdll DLL in the LoadOrder nor in + * the MemoryOrder modules list + * This shall disappear as soon as wine executable doesn't load the ntdll DLL + * before the main module + */ + FIXME("Loading DLL %s before executable image\n", filename); + } + else + { + InsertTailList(&exe_modref->ldr_module.InLoadOrderModuleList, + &wm->ldr_module.InLoadOrderModuleList); + mwm = exe_modref; + do + { + if (mwm->ldr_module.BaseAddress > wm->ldr_module.BaseAddress) + { + before = mwm; + break; + } + mwm = CONTAINING_RECORD(mwm->ldr_module.InMemoryOrderModuleList.Flink, + WINE_MODREF, ldr_module.InMemoryOrderModuleList); + } while (mwm != exe_modref); + if (before) + { + mwm = CONTAINING_RECORD(mwm->ldr_module.InMemoryOrderModuleList.Blink, + WINE_MODREF, ldr_module.InMemoryOrderModuleList); + mwm->ldr_module.InMemoryOrderModuleList.Flink = &wm->ldr_module.InMemoryOrderModuleList; + wm->ldr_module.InMemoryOrderModuleList.Flink = &before->ldr_module.InMemoryOrderModuleList; + before->ldr_module.InMemoryOrderModuleList.Blink = &wm->ldr_module.InMemoryOrderModuleList; + wm->ldr_module.InMemoryOrderModuleList.Blink = &mwm->ldr_module.InMemoryOrderModuleList; + } + else + InsertTailList(&exe_modref->ldr_module.InMemoryOrderModuleList, + &wm->ldr_module.InMemoryOrderModuleList); + } + } } return wm; } @@ -151,12 +212,13 @@ /* Skip calls for modules loaded with special load flags */ - if (wm->flags & WINE_MODREF_DONT_RESOLVE_REFS) return TRUE; + if (wm->ldr_module.Flags & WINE_MODREF_DONT_RESOLVE_REFS) return TRUE; - TRACE("(%s,%s,%p) - CALL\n", wm->modname, typeName[type], lpReserved ); + TRACE("(%s,%s,%p) - CALL\n", + debugstr_w(wm->ldr_module.BaseDllName.Buffer), typeName[type], lpReserved ); /* Call the initialization routine */ - retv = PE_InitDLL( wm->module, type, lpReserved ); + retv = PE_InitDLL( wm->ldr_module.BaseAddress, type, lpReserved ); /* The state of the module list may have changed due to the call to PE_InitDLL. We cannot assume that this module has not been @@ -210,14 +272,14 @@ assert( wm ); /* prevent infinite recursion in case of cyclical dependencies */ - if ( ( wm->flags & WINE_MODREF_MARKER ) - || ( wm->flags & WINE_MODREF_PROCESS_ATTACHED ) ) + if ( ( wm->ldr_module.Flags & WINE_MODREF_MARKER ) + || ( wm->ldr_module.Flags & WINE_MODREF_PROCESS_ATTACHED ) ) goto done; - TRACE("(%s,%p) - START\n", wm->modname, lpReserved ); + TRACE("(%s,%p) - START\n", debugstr_w(wm->ldr_module.BaseDllName.Buffer), lpReserved); /* Tag current MODREF to prevent recursive loop */ - wm->flags |= WINE_MODREF_MARKER; + wm->ldr_module.Flags |= WINE_MODREF_MARKER; /* Recursively attach all DLLs this one depends on */ for ( i = 0; retv && i < wm->nDeps; i++ ) @@ -229,7 +291,11 @@ { retv = MODULE_InitDLL( wm, DLL_PROCESS_ATTACH, lpReserved ); if ( retv ) - wm->flags |= WINE_MODREF_PROCESS_ATTACHED; + { + wm->ldr_module.Flags |= WINE_MODREF_PROCESS_ATTACHED; + InsertTailList(&exe_modref->ldr_module.InInitializationOrderModuleList, + &wm->ldr_module.InInitializationOrderModuleList); + } } /* Re-insert MODREF at head of list */ @@ -244,9 +310,9 @@ } /* Remove recursion flag */ - wm->flags &= ~WINE_MODREF_MARKER; + wm->ldr_module.Flags &= ~WINE_MODREF_MARKER; - TRACE("(%s,%p) - END\n", wm->modname, lpReserved ); + TRACE("(%s,%p) - END\n", debugstr_w(wm->ldr_module.BaseDllName.Buffer), lpReserved ); done: RtlLeaveCriticalSection( &loader_section ); @@ -260,7 +326,7 @@ * sequence at MODULE_DllProcessAttach. Unless the bForceDetach flag * is set, only DLLs with zero refcount are notified. */ -void MODULE_DllProcessDetach( BOOL bForceDetach, LPVOID lpReserved ) +static void MODULE_DllProcessDetach( BOOL bForceDetach, LPVOID lpReserved ) { WINE_MODREF *wm; @@ -271,13 +337,13 @@ for ( wm = MODULE_modref_list; wm; wm = wm->next ) { /* Check whether to detach this DLL */ - if ( !(wm->flags & WINE_MODREF_PROCESS_ATTACHED) ) + if ( !(wm->ldr_module.Flags & WINE_MODREF_PROCESS_ATTACHED) ) continue; - if ( wm->refCount > 0 && !bForceDetach ) + if ( wm->ldr_module.LoadCount > 0 && !bForceDetach ) continue; /* Call detach notification */ - wm->flags &= ~WINE_MODREF_PROCESS_ATTACHED; + wm->ldr_module.Flags &= ~WINE_MODREF_PROCESS_ATTACHED; MODULE_InitDLL( wm, DLL_PROCESS_DETACH, lpReserved ); /* Restart at head of WINE_MODREF list, as entries might have @@ -289,6 +355,18 @@ RtlLeaveCriticalSection( &loader_section ); } +/****************************************************************** + * LdrShutdownProcess + * + * + */ +NTSTATUS WINAPI LdrShutdownProcess(void) +{ + TRACE("()\n"); + MODULE_DllProcessDetach( TRUE, (LPVOID)1 ); + return STATUS_SUCCESS; /* FIXME */ +} + /************************************************************************* * MODULE_DllThreadAttach * @@ -314,9 +392,9 @@ for ( ; wm; wm = wm->prev ) { - if ( !(wm->flags & WINE_MODREF_PROCESS_ATTACHED) ) + if ( !(wm->ldr_module.Flags & WINE_MODREF_PROCESS_ATTACHED) ) continue; - if ( wm->flags & WINE_MODREF_NO_DLL_CALLS ) + if ( wm->ldr_module.Flags & WINE_MODREF_NO_DLL_CALLS ) continue; MODULE_InitDLL( wm, DLL_THREAD_ATTACH, lpReserved ); @@ -332,7 +410,7 @@ * same sequence as process detach notification. * */ -void MODULE_DllThreadDetach( LPVOID lpReserved ) +static void MODULE_DllThreadDetach( LPVOID lpReserved ) { WINE_MODREF *wm; @@ -344,9 +422,9 @@ for ( wm = MODULE_modref_list; wm; wm = wm->next ) { - if ( !(wm->flags & WINE_MODREF_PROCESS_ATTACHED) ) + if ( !(wm->ldr_module.Flags & WINE_MODREF_PROCESS_ATTACHED) ) continue; - if ( wm->flags & WINE_MODREF_NO_DLL_CALLS ) + if ( wm->ldr_module.Flags & WINE_MODREF_NO_DLL_CALLS ) continue; MODULE_InitDLL( wm, DLL_THREAD_DETACH, lpReserved ); @@ -355,6 +433,20 @@ RtlLeaveCriticalSection( &loader_section ); } +/****************************************************************** + * LdrShutdownThread + * + * + */ +NTSTATUS WINAPI LdrShutdownThread(void) +{ + TRACE("()\n"); + MODULE_DllThreadDetach( NULL ); + return STATUS_SUCCESS; +} +#endif + +#ifdef _KERNEL32_ /**************************************************************************** * DisableThreadLibraryCalls (KERNEL32.@) * @@ -362,23 +454,46 @@ */ BOOL WINAPI DisableThreadLibraryCalls( HMODULE hModule ) { + NTSTATUS nts; + + nts = LdrDisableThreadCalloutsForDll( hModule ); + if (nts != STATUS_SUCCESS) + { + SetLastError( RtlNtStatusToDosError( nts ) ); + return FALSE; + } + return TRUE; +} +#endif + +#ifdef _NTSYSTEM_ +/****************************************************************** + * LdrDisableThreadCalloutsForDll + * + * + */ +NTSTATUS WINAPI LdrDisableThreadCalloutsForDll( HMODULE hModule ) +{ WINE_MODREF *wm; - BOOL retval = TRUE; + NTSTATUS retval = STATUS_SUCCESS; + TRACE("(%p)\n", hModule); RtlEnterCriticalSection( &loader_section ); wm = MODULE32_LookupHMODULE( hModule ); if ( !wm ) - retval = FALSE; + retval = STATUS_DLL_NOT_FOUND; else - wm->flags |= WINE_MODREF_NO_DLL_CALLS; + wm->ldr_module.Flags |= WINE_MODREF_NO_DLL_CALLS; RtlLeaveCriticalSection( &loader_section ); return retval; } +#endif +#ifdef _KERNEL32_ /*********************************************************************** * MODULE_CreateDummyModule * @@ -482,8 +597,10 @@ NE_RegisterModule( pModule ); return hModule; } +#endif +#ifdef _NTSYSTEM_ /********************************************************************** * MODULE_FindModule * @@ -493,16 +610,15 @@ * the module handle if found * 0 if not */ -WINE_MODREF *MODULE_FindModule( - LPCSTR path /* [in] pathname of module/library to be found */ -) { +WINE_MODREF* MODULE_FindModule( LPCSTR path ) +{ WINE_MODREF *wm; char dllname[260], *p; /* Append .DLL to name if no extension present */ strcpy( dllname, path ); if (!(p = strrchr( dllname, '.')) || strchr( p, '/' ) || strchr( p, '\\')) - strcat( dllname, ".DLL" ); + strcat( dllname, ".DLL" ); for ( wm = MODULE_modref_list; wm; wm = wm->next ) { @@ -519,7 +635,38 @@ return wm; } +/********************************************************************** + * LdrGetDllHandle + * + * Find a (loaded) win32 module depending on path + * + */ +NTSTATUS WINAPI LdrGetDllHandle(ULONG u1, ULONG u2, PUNICODE_STRING wstr, PVOID* base) +{ + WINE_MODREF* wm; + + TRACE("(%s)\n", wstr ? debugstr_w(wstr->Buffer) : NULL); + + if (wstr) + { + STRING str; + + RtlUnicodeStringToAnsiString(&str, wstr, TRUE); + + wm = MODULE_FindModule( str.Buffer ); + RtlFreeAnsiString(&str); + } + else + wm = exe_modref; + + if (!wm) return STATUS_DLL_NOT_FOUND; + *base = wm->ldr_module.BaseAddress; + + return STATUS_SUCCESS; +} +#endif +#ifdef _KERNEL32_ /* Check whether a file is an OS/2 or a very old Windows executable * by testing on import of KERNEL. * @@ -898,6 +1045,7 @@ return ret; } + /*********************************************************************** * WinExec (KERNEL32.@) */ @@ -937,6 +1085,16 @@ return ret; } +#include "pshpack1.h" +typedef struct +{ + LPSTR lpEnvAddress; + LPSTR lpCmdLine; + UINT16 *lpCmdShow; + DWORD dwReserved; +} LOADPARAMS; +#include "poppack.h" + /********************************************************************** * LoadModule (KERNEL32.@) */ @@ -1002,14 +1160,28 @@ */ HMODULE WINAPI GetModuleHandleA(LPCSTR module) { - WINE_MODREF *wm; + NTSTATUS nts; + HMODULE ret; - if ( module == NULL ) - wm = exe_modref; + if (module) + { + UNICODE_STRING wstr; + + RtlCreateUnicodeStringFromAsciiz(&wstr, module); + nts = LdrGetDllHandle(0, 0, &wstr, (void**)&ret); + RtlFreeUnicodeString( &wstr ); + } else - wm = MODULE_FindModule( module ); + nts = LdrGetDllHandle(0, 0, NULL, (void**)&ret); + if (nts != STATUS_SUCCESS) + { + ret = 0; + SetLastError( RtlNtStatusToDosError( nts ) ); + } - return wm? wm->module : 0; + TRACE("%s => %p\n", module, ret); + + return ret; } /*********************************************************************** @@ -1017,14 +1189,30 @@ */ HMODULE WINAPI GetModuleHandleW(LPCWSTR module) { - HMODULE hModule; - LPSTR modulea = HEAP_strdupWtoA( GetProcessHeap(), 0, module ); - hModule = GetModuleHandleA( modulea ); - HeapFree( GetProcessHeap(), 0, modulea ); - return hModule; -} + NTSTATUS nts; + HMODULE ret; + if (module) + { + UNICODE_STRING wstr; + RtlInitUnicodeString( &wstr, module ); + nts = LdrGetDllHandle( 0, 0, &wstr, (void**)&ret); + } + else + nts = LdrGetDllHandle( 0, 0, NULL, (void**)&ret); + + if (nts != STATUS_SUCCESS) + { + SetLastError( RtlNtStatusToDosError( nts ) ); + ret = 0; + } + return ret; +} +#endif + +/* FIXME: should be in kernel */ +#ifdef _NTSYSTEM_ /*********************************************************************** * GetModuleFileNameA (KERNEL32.@) * GetModuleFileName32 (KERNEL.487) @@ -1052,6 +1240,7 @@ { WINE_MODREF *wm = MODULE32_LookupHMODULE( hModule ); if (wm) lstrcpynA( lpFileName, wm->filename, size ); + else SetLastError( ERROR_INVALID_HANDLE ); } RtlLeaveCriticalSection( &loader_section ); @@ -1065,24 +1254,53 @@ */ 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 ); + RtlEnterCriticalSection( &loader_section ); + + lpFileName[0] = 0; + if (!hModule && !(NtCurrentTeb()->tibflags & TEBF_WIN32)) + { + /* 16-bit task - get current NE module name */ + NE_MODULE *pModule = NE_GetPtr( GetCurrentTask() ); + LPSTR fnA = HeapAlloc( GetProcessHeap(), 0, size ); + if (!fnA) return 0; + + if (pModule) GetLongPathNameA(NE_MODULE_NAME(pModule), fnA, size); + if (size > 0 && !MultiByteToWideChar( CP_ACP, 0, fnA, -1, lpFileName, size )) + lpFileName[size-1] = 0; + HeapFree( GetProcessHeap(), 0, fnA ); + } + else + { + WINE_MODREF *wm = MODULE32_LookupHMODULE( hModule ); + if (wm) lstrcpynW( lpFileName, wm->ldr_module.FullDllName.Buffer, size ); + else SetLastError( ERROR_INVALID_HANDLE ); + } + + RtlLeaveCriticalSection( &loader_section ); + TRACE("%s\n", debugstr_w(lpFileName) ); + return strlenW(lpFileName); } +#endif +#ifdef _KERNEL32_ /*********************************************************************** * LoadLibraryExA (KERNEL32.@) + * + * The HFILE parameter is not used and marked reserved in the SDK. I can + * only guess that it should force a file to be mapped, but I rather + * ignore the parameter because it would be extremely difficult to + * integrate this with different types of module representations. + * */ HMODULE WINAPI LoadLibraryExA(LPCSTR libname, HANDLE hfile, DWORD flags) { - WINE_MODREF *wm; + UNICODE_STRING wstr; + HINSTANCE hInst; + NTSTATUS nts; - if(!libname) + if (!libname) { SetLastError(ERROR_INVALID_PARAMETER); return 0; @@ -1124,22 +1342,57 @@ /* Fallback to normal behaviour */ } + RtlCreateUnicodeStringFromAsciiz( &wstr, libname ); + nts = LdrLoadDll(NULL, flags, &wstr, (void**)&hInst); + if (nts != STATUS_SUCCESS) + { + hInst = 0; + SetLastError( RtlNtStatusToDosError( nts ) ); + } + RtlFreeUnicodeString( &wstr ); + + return hInst; +} +#endif + +#ifdef _NTSYSTEM_ +/****************************************************************** + * LdrLoadDll + * + * + */ +NTSTATUS WINAPI LdrLoadDll(LPCSTR searchPath, DWORD flags, PUNICODE_STRING wstr, + void** hInst) +{ + WINE_MODREF *wm; + NTSTATUS nts = STATUS_SUCCESS; + STRING str; + + RtlUnicodeStringToAnsiString(&str, wstr, TRUE); + RtlEnterCriticalSection( &loader_section ); - wm = MODULE_LoadLibraryExA( libname, hfile, flags ); + /* FIXME: searchPath isn't used (but normaly we don't use it) */ + wm = MODULE_LoadLibraryExA( str.Buffer, flags ); if ( wm ) { if ( !MODULE_DllProcessAttach( wm, NULL ) ) { - WARN_(module)("Attach failed for module '%s'.\n", libname); - MODULE_FreeLibrary(wm); - SetLastError(ERROR_DLL_INIT_FAILED); + WARN_(module)("Attach failed for module '%s'.\n", str.Buffer); + LdrUnloadDll(wm->ldr_module.BaseAddress); + nts = STATUS_DLL_INIT_FAILED; wm = NULL; } } + else nts = STATUS_DLL_NOT_FOUND; + *hInst = (wm) ? wm->ldr_module.BaseAddress : NULL; + RtlLeaveCriticalSection( &loader_section ); - return wm ? wm->module : 0; + + RtlFreeAnsiString(&str); + + return nts; } /*********************************************************************** @@ -1162,7 +1415,7 @@ length = pmax - libname; - result = HeapAlloc (GetProcessHeap(), 0, length+1); + result = RtlAllocateHeap (GetProcessHeap(), 0, length+1); if (result) { @@ -1178,11 +1431,6 @@ * * Load a PE style module according to the load order. * - * The HFILE parameter is not used and marked reserved in the SDK. I can - * only guess that it should force a file to be mapped, but I rather - * ignore the parameter because it would be extremely difficult to - * integrate this with different types of module representations. - * * libdir is used to support LOAD_WITH_ALTERED_SEARCH_PATH during the recursion * on this function. When first called from LoadLibraryExA it will be * NULL but thereafter it may point to a buffer containing the path @@ -1194,7 +1442,7 @@ * init function into load_library). * allocated_libdir is TRUE in the stack frame that allocated libdir */ -WINE_MODREF *MODULE_LoadLibraryExA( LPCSTR libname, HANDLE hfile, DWORD flags ) +WINE_MODREF *MODULE_LoadLibraryExA( LPCSTR libname, DWORD flags ) { DWORD err = GetLastError(); WINE_MODREF *pwm; @@ -1208,7 +1456,7 @@ if ( !libname ) return NULL; - filename = HeapAlloc ( GetProcessHeap(), 0, MAX_PATH + 1 ); + filename = RtlAllocateHeap ( GetProcessHeap(), 0, MAX_PATH + 1 ); if ( !filename ) return NULL; *filename = 0; /* Just in case we don't set it before goto error */ @@ -1234,7 +1482,7 @@ /* Check for already loaded module */ if (!(pwm = MODULE_FindModule(filename)) && !FILE_contains_path(libname)) { - LPSTR fn = HeapAlloc ( GetProcessHeap(), 0, MAX_PATH + 1 ); + LPSTR fn = RtlAllocateHeap ( GetProcessHeap(), 0, MAX_PATH + 1 ); if (fn) { /* since the default loading mechanism uses a more detailed algorithm @@ -1249,27 +1497,28 @@ if (!strrchr( fn, '.')) strcat( fn, ".dll" ); if ((pwm = MODULE_FindModule( fn )) != NULL) strcpy( filename, fn ); - HeapFree( GetProcessHeap(), 0, fn ); + RtlFreeHeap( GetProcessHeap(), 0, fn ); } } if (pwm) { - pwm->refCount++; + pwm->ldr_module.LoadCount++; - if ((pwm->flags & WINE_MODREF_DONT_RESOLVE_REFS) && + if ((pwm->ldr_module.Flags & WINE_MODREF_DONT_RESOLVE_REFS) && !(flags & DONT_RESOLVE_DLL_REFERENCES)) { - pwm->flags &= ~WINE_MODREF_DONT_RESOLVE_REFS; + pwm->ldr_module.Flags &= ~WINE_MODREF_DONT_RESOLVE_REFS; PE_fixup_imports( pwm ); } - TRACE("Already loaded module '%s' at %p, count=%d\n", filename, pwm->module, pwm->refCount); + TRACE("Already loaded module '%s' at %p, count=%d\n", + filename, pwm->ldr_module.BaseAddress, pwm->ldr_module.LoadCount); if (allocated_libdir) { - HeapFree ( GetProcessHeap(), 0, (LPSTR)libdir ); + RtlFreeHeap ( GetProcessHeap(), 0, (LPSTR)libdir ); libdir = NULL; } RtlLeaveCriticalSection( &loader_section ); - HeapFree ( GetProcessHeap(), 0, filename ); + RtlFreeHeap ( GetProcessHeap(), 0, filename ); return pwm; } @@ -1308,21 +1557,22 @@ if(pwm) { /* Initialize DLL just loaded */ - TRACE("Loaded module '%s' at %p\n", filename, pwm->module); + TRACE("Loaded module '%s' at %p\n", + filename, pwm->ldr_module.BaseAddress); if (!TRACE_ON(module)) TRACE_(loaddll)("Loaded module '%s' : %s\n", filename, filetype); - /* Set the refCount here so that an attach failure will */ + /* Set the ldr_module.LoadCount here so that an attach failure will */ /* decrement the dependencies through the MODULE_FreeLibrary call. */ - pwm->refCount = 1; + pwm->ldr_module.LoadCount = 1; if (allocated_libdir) { - HeapFree ( GetProcessHeap(), 0, (LPSTR)libdir ); + RtlFreeHeap ( GetProcessHeap(), 0, (LPSTR)libdir ); libdir = NULL; } RtlLeaveCriticalSection( &loader_section ); SetLastError( err ); /* restore last error */ - HeapFree ( GetProcessHeap(), 0, filename ); + RtlFreeHeap ( GetProcessHeap(), 0, filename ); return pwm; } @@ -1337,20 +1587,23 @@ error: if (allocated_libdir) { - HeapFree ( GetProcessHeap(), 0, (LPSTR)libdir ); + RtlFreeHeap ( GetProcessHeap(), 0, (LPSTR)libdir ); libdir = NULL; } RtlLeaveCriticalSection( &loader_section ); WARN("Failed to load module '%s'; error=%ld\n", filename, GetLastError()); - HeapFree ( GetProcessHeap(), 0, filename ); + RtlFreeHeap ( GetProcessHeap(), 0, filename ); return NULL; } +#endif +#ifdef _KERNEL32_ /*********************************************************************** * LoadLibraryA (KERNEL32.@) */ -HMODULE WINAPI LoadLibraryA(LPCSTR libname) { - return LoadLibraryExA(libname,0,0); +HMODULE WINAPI LoadLibraryA(LPCSTR libname) +{ + return LoadLibraryExA( libname, 0, 0 ); } /*********************************************************************** @@ -1358,7 +1611,7 @@ */ HMODULE WINAPI LoadLibraryW(LPCWSTR libnameW) { - return LoadLibraryExW(libnameW,0,0); + return LoadLibraryExW( libnameW, 0, 0 ); } /*********************************************************************** @@ -1387,7 +1640,9 @@ HeapFree( GetProcessHeap(), 0, libnameA ); return ret; } +#endif +#ifdef _NTSYSTEM_ /*********************************************************************** * MODULE_FlushModrefs * @@ -1404,7 +1659,7 @@ { next = wm->next; - if(wm->refCount) + if(wm->ldr_module.LoadCount) continue; /* Unlink this modref from the chain */ @@ -1415,19 +1670,29 @@ if(wm == MODULE_modref_list) MODULE_modref_list = wm->next; - TRACE(" unloading %s\n", wm->filename); + RemoveEntryList(&wm->ldr_module.InLoadOrderModuleList); + RemoveEntryList(&wm->ldr_module.InMemoryOrderModuleList); + RemoveEntryList(&wm->ldr_module.InInitializationOrderModuleList); + + TRACE(" unloading %s\n", debugstr_w(wm->ldr_module.FullDllName.Buffer)); if (!TRACE_ON(module)) - TRACE_(loaddll)("Unloaded module '%s' : %s\n", wm->filename, + TRACE_(loaddll)("Unloaded module '%s' : %s\n", + debugstr_w(wm->ldr_module.FullDllName.Buffer), wm->dlhandle ? "builtin" : "native" ); if (wm->dlhandle) wine_dll_unload( wm->dlhandle ); - else UnmapViewOfFile( (LPVOID)wm->module ); + else UnmapViewOfFile( wm->ldr_module.BaseAddress ); FreeLibrary16(wm->hDummyMod); - HeapFree( GetProcessHeap(), 0, wm->deps ); - HeapFree( GetProcessHeap(), 0, wm ); + RtlFreeUnicodeString( &wm->ldr_module.FullDllName ); + RtlFreeUnicodeString( &wm->ldr_module.BaseDllName ); + + RtlFreeHeap( GetProcessHeap(), 0, wm->deps ); + RtlFreeHeap( GetProcessHeap(), 0, wm ); } } +#endif +#ifdef _KERNEL32_ /*********************************************************************** * FreeLibrary (KERNEL32.@) * FreeLibrary32 (KERNEL.486) @@ -1435,7 +1700,7 @@ BOOL WINAPI FreeLibrary(HINSTANCE hLibModule) { BOOL retv = FALSE; - WINE_MODREF *wm; + NTSTATUS nts; if (!hLibModule) { @@ -1451,24 +1716,14 @@ 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 - { - free_lib_count++; - if ((wm = MODULE32_LookupHMODULE( hLibModule ))) retv = MODULE_FreeLibrary( wm ); - free_lib_count--; - } - - RtlLeaveCriticalSection( &loader_section ); + if ((nts = LdrUnloadDll( hLibModule )) == STATUS_SUCCESS) retv = TRUE; + else SetLastError( RtlNtStatusToDosError( nts ) ); return retv; } +#endif +#ifdef _NTSYSTEM_ /*********************************************************************** * MODULE_DecRefCount * @@ -1478,58 +1733,84 @@ { int i; - if ( wm->flags & WINE_MODREF_MARKER ) + if ( wm->ldr_module.Flags & WINE_MODREF_MARKER ) return; - if ( wm->refCount <= 0 ) + if ( wm->ldr_module.LoadCount <= 0 ) return; - --wm->refCount; - TRACE("(%s) refCount: %d\n", wm->modname, wm->refCount ); + --wm->ldr_module.LoadCount; + TRACE("(%s) refCount: %d\n", + debugstr_w(wm->ldr_module.BaseDllName.Buffer), wm->ldr_module.LoadCount ); - if ( wm->refCount == 0 ) + if ( wm->ldr_module.LoadCount == 0 ) { - wm->flags |= WINE_MODREF_MARKER; + wm->ldr_module.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; + wm->ldr_module.Flags &= ~WINE_MODREF_MARKER; } } /*********************************************************************** - * MODULE_FreeLibrary + * LdrUnloadDll * - * NOTE: Assumes that the process critical section is held! */ -BOOL MODULE_FreeLibrary( WINE_MODREF *wm ) +NTSTATUS WINAPI LdrUnloadDll( HMODULE hModule ) { - TRACE("(%s) - START\n", wm->modname ); + NTSTATUS retv = STATUS_SUCCESS; + + TRACE("(%p)\n", hModule); - /* Recursively decrement reference counts */ - MODULE_DecRefCount( wm ); + RtlEnterCriticalSection( &loader_section ); - /* Call process detach notifications */ - if ( free_lib_count <= 1 ) + /* if we're stopping the whole process (and forcing the removal of all + * DLLs) the library will be freed anyway + */ + if (!process_detaching) { - MODULE_DllProcessDetach( FALSE, NULL ); - SERVER_START_REQ( unload_dll ) + WINE_MODREF *wm; + + free_lib_count++; + if ((wm = MODULE32_LookupHMODULE( hModule )) != NULL) { - req->base = (void *)wm->module; - wine_server_call( req ); + TRACE("(%s) - START\n", debugstr_w(wm->ldr_module.BaseDllName.Buffer)); + + /* Recursively decrement reference counts */ + MODULE_DecRefCount( wm ); + + /* Call process detach notifications */ + if ( free_lib_count <= 1 ) + { + MODULE_DllProcessDetach( FALSE, NULL ); + SERVER_START_REQ( unload_dll ) + { + req->base = wm->ldr_module.BaseAddress; + wine_server_call( req ); + } + SERVER_END_REQ; + MODULE_FlushModrefs(); + } + + TRACE("END\n"); } - SERVER_END_REQ; - MODULE_FlushModrefs(); + else + retv = STATUS_DLL_NOT_FOUND; + + free_lib_count--; } - TRACE("END\n"); + RtlLeaveCriticalSection( &loader_section ); - return TRUE; + return retv; } +#endif +#ifdef _KERNEL32_ /*********************************************************************** * FreeLibraryAndExitThread (KERNEL32.@) */ @@ -1539,6 +1820,8 @@ ExitThread(dwExitCode); } + + /*********************************************************************** * PrivateLoadLibrary (KERNEL32.@) * @@ -1549,8 +1832,6 @@ return LoadLibrary16(libname); } - - /*********************************************************************** * PrivateFreeLibrary (KERNEL32.@) * @@ -1561,7 +1842,6 @@ FreeLibrary16(handle); } - /*********************************************************************** * GetProcAddress16 (KERNEL32.37) * Get procaddress in 16bit module from win32... (kernel32 undoc. ordinal func) @@ -1580,6 +1860,7 @@ return GetProcAddress16( LOWORD(hModule), name ); } + /*********************************************************************** * GetProcAddress (KERNEL.50) */ @@ -1615,7 +1896,25 @@ */ FARPROC WINAPI GetProcAddress( HMODULE hModule, LPCSTR function ) { - return MODULE_GetProcAddress( hModule, function, -1, TRUE ); + NTSTATUS nts; + FARPROC fp; + + if (HIWORD(function)) + { + ANSI_STRING str; + + RtlInitAnsiString( &str, function ); + /* FIXME: snoop has been desactivated */ + nts = LdrGetProcedureAddress( hModule, &str, 0, (void**)&fp); + } + else + nts = LdrGetProcedureAddress( hModule, NULL, (DWORD)function, (void**)&fp); + if (nts != STATUS_SUCCESS) + { + SetLastError( RtlNtStatusToDosError( nts ) ); + fp = NULL; + } + return fp; } /*********************************************************************** @@ -1623,9 +1922,12 @@ */ FARPROC WINAPI GetProcAddress32_16( HMODULE hModule, LPCSTR function ) { - return MODULE_GetProcAddress( hModule, function, -1, FALSE ); + /* FIXME: snoop has been desactivated */ + return GetProcAddress( hModule, function ); } +#endif +#ifdef _NTSYSTEM_ /*********************************************************************** * MODULE_GetProcAddress (internal) */ @@ -1652,8 +1954,10 @@ RtlLeaveCriticalSection( &loader_section ); return retproc; } +#endif +#ifdef _KERNEL32_ /*************************************************************************** * HasGPHandler (KERNEL.338) */ @@ -1693,3 +1997,116 @@ return 0; } +#endif + +#ifdef _NTSYSTEM_ +/****************************************************************** + * LdrGetProcedureAddress + * + * + */ +NTSTATUS WINAPI LdrGetProcedureAddress(HMODULE hModule, PANSI_STRING function, ULONG ord, PVOID *address) +{ + WINE_MODREF *wm; + NTSTATUS nts; + + TRACE("(%p, %s, %lu, %p)\n", + hModule, function ? debugstr_a(function->Buffer) : NULL, ord, address); + + /* FIXME: how to cope with snoop parameter ?? */ + + if (function) + TRACE_(win32)("(%08lx,%s)\n",(DWORD)hModule,function->Buffer); + else + TRACE_(win32)("(%08lx,%lu)\n",(DWORD)hModule,ord); + + RtlEnterCriticalSection( &loader_section ); + if ((wm = MODULE32_LookupHMODULE( hModule ))) + { + FARPROC retproc = wm->find_export( wm, function ? function->Buffer : (char*)ord, -1, FALSE ); + if (address) *address = retproc; + nts = (retproc) ? STATUS_SUCCESS : STATUS_PROCEDURE_NOT_FOUND; + } + else nts = STATUS_DLL_NOT_FOUND; + RtlLeaveCriticalSection( &loader_section ); + return nts; +} + + +/****************************************************************** + * LdrFindEntryForAddress + * + * + */ +NTSTATUS WINAPI LdrFindEntryForAddress(void* addr, PLDR_MODULE* mod) +{ + WINE_MODREF* wm; + + /* FIXME: could be faster if we implement the InMemoryOrder list of the LDR_MODULE + * we cannot use LDR_MODULE list yet as it doesn't contain all the loaded modules yet + */ + RtlEnterCriticalSection( &loader_section ); + for (wm = MODULE_modref_list; wm; wm = wm->next) + { + if (wm->ldr_module.BaseAddress <= addr && + (char*)addr < (char*)wm->ldr_module.BaseAddress + wm->ldr_module.SizeOfImage) + { + if (mod) *mod = &wm->ldr_module; + break; + } + } + RtlLeaveCriticalSection( &loader_section ); + + return (wm) ? STATUS_NO_MORE_ENTRIES : STATUS_SUCCESS; +} + +/****************************************************************** + * LdrQueryProcessModuleInformation + * + * + */ +NTSTATUS WINAPI LdrQueryProcessModuleInformation(PSYSTEM_MODULE_INFORMATION smibuf, + ULONG buf_size, PULONG req_size ) +{ + WINE_MODREF* wm; + SYSTEM_MODULE* sm = &smibuf->Modules[0]; + ULONG sz = sizeof(ULONG); + NTSTATUS nts = STATUS_SUCCESS; + ANSI_STRING astr; + BYTE* ptr; + + /* FIXME is smibuf->ModulesCount in the buf_size ? assume yes */ + if (buf_size < sz) nts = STATUS_INFO_LENGTH_MISMATCH; + + RtlEnterCriticalSection( &loader_section ); + for (wm = MODULE_modref_list; wm; wm = wm->next) + { + if (sz + sizeof(*sm) <= buf_size) + { + sm->Reserved1 = 0xBAADF00D; + sm->Reserved2 = 0; + sm->ImageBaseAddress = wm->ldr_module.BaseAddress; + sm->ImageSize = wm->ldr_module.SizeOfImage; + sm->Flags = wm->ldr_module.Flags; /* FIXME those are not Win32 compat */ + sm->Id = 0; + sm->Rank = 0; + sm->w018 = 0xFFFF; + + astr.Length = 0; + astr.MaximumLength = sizeof(sm->Name); + astr.Buffer = sm->Name; + RtlUnicodeStringToAnsiString(&astr, &wm->ldr_module.FullDllName, FALSE); + ptr = strrchr(sm->Name, '\\'); + sm->NameOffset = (ptr != NULL) ? ptr - sm->Name + 1 : 0; + } + else + nts = STATUS_INFO_LENGTH_MISMATCH; + sz += sizeof(*sm); + smibuf->ModulesCount++; + sm++; + } + RtlLeaveCriticalSection( &loader_section ); + if (req_size) *req_size = sz; + return nts; +} +#endif Index: loader/pe_image.c =================================================================== RCS file: /home/cvs/cvsroot/wine/wine/loader/pe_image.c,v retrieving revision 1.118 diff -u -u -r1.118 pe_image.c --- loader/pe_image.c 17 Dec 2002 21:09:50 -0000 1.118 +++ loader/pe_image.c 3 Jan 2003 19:51:27 -0000 @@ -125,18 +125,18 @@ IMAGE_EXPORT_DIRECTORY *exports; DWORD exp_size; - if (!(exports = RtlImageDirectoryEntryToData( wm->module, TRUE, + if (!(exports = RtlImageDirectoryEntryToData( wm->ldr_module.BaseAddress, TRUE, IMAGE_DIRECTORY_ENTRY_EXPORT, &exp_size ))) return NULL; if (HIWORD(funcName)) TRACE("(%s)\n",funcName); else TRACE("(%d)\n",LOWORD(funcName)); - ordinals= get_rva(wm->module, exports->AddressOfNameOrdinals); - function= get_rva(wm->module, exports->AddressOfFunctions); - name = get_rva(wm->module, exports->AddressOfNames); + ordinals= get_rva(wm->ldr_module.BaseAddress, exports->AddressOfNameOrdinals); + function= get_rva(wm->ldr_module.BaseAddress, exports->AddressOfFunctions); + name = get_rva(wm->ldr_module.BaseAddress, exports->AddressOfNames); forward = NULL; - rva_start = (char *)exports - (char *)wm->module; + rva_start = (char *)exports - (char *)wm->ldr_module.BaseAddress; if (HIWORD(funcName)) { @@ -145,7 +145,7 @@ /* first check the hint */ if (hint >= 0 && hint <= max) { - ename = get_rva(wm->module, name[hint]); + ename = get_rva(wm->ldr_module.BaseAddress, name[hint]); if (!strcmp( ename, funcName )) { ordinal = ordinals[hint]; @@ -157,7 +157,7 @@ while (min <= max) { int res, pos = (min + max) / 2; - ename = get_rva(wm->module, name[pos]); + ename = get_rva(wm->ldr_module.BaseAddress, name[pos]); if (!(res = strcmp( ename, funcName ))) { ordinal = ordinals[pos]; @@ -176,7 +176,7 @@ for (i = 0; i < exports->NumberOfNames; i++) if (ordinals[i] == ordinal) { - ename = get_rva(wm->module, name[i]); + ename = get_rva(wm->ldr_module.BaseAddress, name[i]); break; } } @@ -191,13 +191,13 @@ addr = function[ordinal]; if (!addr) return NULL; - proc = get_rva(wm->module, addr); + proc = get_rva(wm->ldr_module.BaseAddress, addr); if (((char *)proc < (char *)exports) || ((char *)proc >= (char *)exports + exp_size)) { if (snoop) { if (!ename) ename = "@"; - proc = SNOOP_GetProcAddress(wm->module,ename,ordinal,proc); + proc = SNOOP_GetProcAddress(wm->ldr_module.BaseAddress,ename,ordinal,proc); } return proc; } @@ -214,11 +214,15 @@ module[end-forward] = 0; if (!(wm_fw = MODULE_FindModule( module ))) { - ERR("module not found for forward '%s' used by '%s'\n", forward, wm->modname ); + ERR("module not found for forward '%s' used by '%s'\n", + forward, debugstr_w(wm->ldr_module.BaseDllName.Buffer)); return NULL; } - if (!(proc = MODULE_GetProcAddress( wm_fw->module, end + 1, -1, snoop ))) - ERR("function not found for forward '%s' used by '%s'. If you are using builtin '%s', try using the native one instead.\n", forward, wm->modname, wm->modname ); + if (!(proc = MODULE_GetProcAddress( wm_fw->ldr_module.BaseAddress, end + 1, -1, snoop ))) + ERR("function not found for forward '%s' used by '%s'. If you are using builtin '%s', try using the native one instead.\n", + forward, + debugstr_w(wm->ldr_module.BaseDllName.Buffer), + debugstr_w(wm->ldr_module.BaseDllName.Buffer)); return proc; } } @@ -232,7 +236,7 @@ IMAGE_IMPORT_DESCRIPTOR *imports, *pe_imp; DWORD size; - imports = RtlImageDirectoryEntryToData( wm->module, TRUE, IMAGE_DIRECTORY_ENTRY_IMPORT, &size ); + imports = RtlImageDirectoryEntryToData( wm->ldr_module.BaseAddress, TRUE, IMAGE_DIRECTORY_ENTRY_IMPORT, &size ); /* first, count the number of imported non-internal modules */ pe_imp = imports; @@ -256,7 +260,7 @@ /* Allocate module dependency list */ wm->nDeps = i; - wm->deps = HeapAlloc( GetProcessHeap(), 0, i*sizeof(WINE_MODREF *) ); + wm->deps = RtlAllocateHeap( GetProcessHeap(), 0, i*sizeof(WINE_MODREF *) ); /* load the imported modules. They are automatically * added to the modref list of the process. @@ -266,14 +270,15 @@ WINE_MODREF *wmImp; IMAGE_IMPORT_BY_NAME *pe_name; PIMAGE_THUNK_DATA import_list,thunk_list; - char *name = get_rva(wm->module, pe_imp->Name); + char *name = get_rva(wm->ldr_module.BaseAddress, pe_imp->Name); if (characteristics_detection && !pe_imp->u.Characteristics) break; - wmImp = MODULE_LoadLibraryExA( name, 0, 0 ); + wmImp = MODULE_LoadLibraryExA( name, 0 ); if (!wmImp) { - ERR_(module)("Module (file) %s (which is needed by %s) not found\n", name, wm->filename); + ERR_(module)("Module (file) %s (which is needed by %s) not found\n", + name, debugstr_w(wm->ldr_module.FullDllName.Buffer)); return 1; } wm->deps[i++] = wmImp; @@ -282,8 +287,8 @@ if (pe_imp->u.OriginalFirstThunk != 0) { /* original MS style */ TRACE("Microsoft style imports used\n"); - import_list = get_rva(wm->module, (DWORD)pe_imp->u.OriginalFirstThunk); - thunk_list = get_rva(wm->module, (DWORD)pe_imp->FirstThunk); + import_list = get_rva(wm->ldr_module.BaseAddress, (DWORD)pe_imp->u.OriginalFirstThunk); + thunk_list = get_rva(wm->ldr_module.BaseAddress, (DWORD)pe_imp->FirstThunk); while (import_list->u1.Ordinal) { if (IMAGE_SNAP_BY_ORDINAL(import_list->u1.Ordinal)) { @@ -291,22 +296,23 @@ TRACE("--- Ordinal %s,%d\n", name, ordinal); thunk_list->u1.Function=(PDWORD)MODULE_GetProcAddress( - wmImp->module, (LPCSTR)ordinal, -1, TRUE + wmImp->ldr_module.BaseAddress, (LPCSTR)ordinal, -1, TRUE ); if (!thunk_list->u1.Function) { ERR("No implementation for %s.%d imported from %s, setting to 0xdeadbeef\n", - name, ordinal, wm->filename ); + name, ordinal, debugstr_w(wm->ldr_module.FullDllName.Buffer)); thunk_list->u1.Function = (PDWORD)0xdeadbeef; } } else { /* import by name */ - pe_name = get_rva(wm->module, (DWORD)import_list->u1.AddressOfData); + pe_name = get_rva(wm->ldr_module.BaseAddress, (DWORD)import_list->u1.AddressOfData); TRACE("--- %s %s.%d\n", pe_name->Name, name, pe_name->Hint); thunk_list->u1.Function=(PDWORD)MODULE_GetProcAddress( - wmImp->module, pe_name->Name, pe_name->Hint, TRUE + wmImp->ldr_module.BaseAddress, pe_name->Name, pe_name->Hint, TRUE ); if (!thunk_list->u1.Function) { ERR("No implementation for %s.%d(%s) imported from %s, setting to 0xdeadbeef\n", - name,pe_name->Hint,pe_name->Name,wm->filename); + name,pe_name->Hint,pe_name->Name, + debugstr_w(wm->ldr_module.FullDllName.Buffer)); thunk_list->u1.Function = (PDWORD)0xdeadbeef; } } @@ -315,7 +321,7 @@ } } else { /* Borland style */ TRACE("Borland style imports used\n"); - thunk_list = get_rva(wm->module, (DWORD)pe_imp->FirstThunk); + thunk_list = get_rva(wm->ldr_module.BaseAddress, (DWORD)pe_imp->FirstThunk); while (thunk_list->u1.Ordinal) { if (IMAGE_SNAP_BY_ORDINAL(thunk_list->u1.Ordinal)) { /* not sure about this branch, but it seems to work */ @@ -323,23 +329,24 @@ TRACE("--- Ordinal %s.%d\n",name,ordinal); thunk_list->u1.Function=(PDWORD)MODULE_GetProcAddress( - wmImp->module, (LPCSTR) ordinal, -1, TRUE + wmImp->ldr_module.BaseAddress, (LPCSTR) ordinal, -1, TRUE ); if (!thunk_list->u1.Function) { ERR("No implementation for %s.%d imported from %s, setting to 0xdeadbeef\n", - name,ordinal, wm->filename); + name,ordinal, debugstr_w(wm->ldr_module.FullDllName.Buffer)); thunk_list->u1.Function = (PDWORD)0xdeadbeef; } } else { - pe_name=get_rva(wm->module, (DWORD)thunk_list->u1.AddressOfData); + pe_name=get_rva(wm->ldr_module.BaseAddress, (DWORD)thunk_list->u1.AddressOfData); TRACE("--- %s %s.%d\n", pe_name->Name,name,pe_name->Hint); thunk_list->u1.Function=(PDWORD)MODULE_GetProcAddress( - wmImp->module, pe_name->Name, pe_name->Hint, TRUE + wmImp->ldr_module.BaseAddress, pe_name->Name, pe_name->Hint, TRUE ); if (!thunk_list->u1.Function) { ERR("No implementation for %s.%d(%s) imported from %s, setting to 0xdeadbeef\n", - name, pe_name->Hint, pe_name->Name, wm->filename); + name, pe_name->Hint, pe_name->Name, + debugstr_w(wm->ldr_module.FullDllName.Buffer)); thunk_list->u1.Function = (PDWORD)0xdeadbeef; } } @@ -493,15 +500,16 @@ return NULL; } wm->hDummyMod = hModule16; + wm->ldr_module.SizeOfImage = nt->OptionalHeader.SizeOfImage; if ( builtin ) { NE_MODULE *pModule = (NE_MODULE *)GlobalLock16( hModule16 ); pModule->flags |= NE_FFLAGS_BUILTIN; - wm->flags |= WINE_MODREF_INTERNAL; + wm->ldr_module.Flags |= WINE_MODREF_INTERNAL; } else if ( flags & DONT_RESOLVE_DLL_REFERENCES ) - wm->flags |= WINE_MODREF_DONT_RESOLVE_REFS; + wm->ldr_module.Flags |= WINE_MODREF_DONT_RESOLVE_REFS; wm->find_export = PE_FindExportedFunction; @@ -512,7 +520,7 @@ /* Fixup Imports */ - if (!(wm->flags & WINE_MODREF_DONT_RESOLVE_REFS) && + if (!(wm->ldr_module.Flags & WINE_MODREF_DONT_RESOLVE_REFS) && PE_fixup_imports( wm )) { /* remove entry from modref chain */ @@ -619,11 +627,11 @@ (nt->OptionalHeader.AddressOfEntryPoint)) { DLLENTRYPROC entry = (void*)((char*)module + nt->OptionalHeader.AddressOfEntryPoint); - if (TRACE_ON(relay)) + if (TRACE_ON(relay) || TRACE_ON(module)) DPRINTF("%08lx:Call PE DLL (proc=%p,module=%p,type=%ld,res=%p)\n", GetCurrentThreadId(), entry, module, type, lpReserved ); retv = entry( module, type, lpReserved ); - if (TRACE_ON(relay)) + if (TRACE_ON(relay) || TRACE_ON(module)) DPRINTF("%08lx:Ret PE DLL (proc=%p,module=%p,type=%ld,res=%p) retval=%x\n", GetCurrentThreadId(), entry, module, type, lpReserved, retv ); } @@ -659,19 +667,19 @@ int delta; for (wm = MODULE_modref_list;wm;wm=wm->next) { - peh = RtlImageNtHeader(wm->module); - pdir = RtlImageDirectoryEntryToData( wm->module, TRUE, + peh = RtlImageNtHeader(wm->ldr_module.BaseAddress); + pdir = RtlImageDirectoryEntryToData( wm->ldr_module.BaseAddress, TRUE, IMAGE_DIRECTORY_ENTRY_TLS, &dirsize ); if (!pdir) continue; - delta = (char *)wm->module - (char *)peh->OptionalHeader.ImageBase; + delta = (char *)wm->ldr_module.BaseAddress - (char *)peh->OptionalHeader.ImageBase; - if ( wm->tlsindex == -1 ) { + if ( wm->ldr_module.TlsIndex == -1 ) { LPDWORD xaddr; - wm->tlsindex = TlsAlloc(); + wm->ldr_module.TlsIndex = TlsAlloc(); xaddr = _fixup_address(&(peh->OptionalHeader),delta, pdir->AddressOfIndex ); - *xaddr=wm->tlsindex; + *xaddr=wm->ldr_module.TlsIndex; } datasize= pdir->EndAddressOfRawData-pdir->StartAddressOfRawData; size = datasize + pdir->SizeOfZeroFill; @@ -685,6 +693,6 @@ FIXME("TLS Callbacks aren't going to be called\n"); } - TlsSetValue( wm->tlsindex, mem ); + TlsSetValue( wm->ldr_module.TlsIndex, mem ); } } Index: loader/pe_resource.c =================================================================== RCS file: /home/cvs/cvsroot/wine/wine/loader/pe_resource.c,v retrieving revision 1.40 diff -u -u -r1.40 pe_resource.c --- loader/pe_resource.c 7 Jan 2003 20:36:22 -0000 1.40 +++ loader/pe_resource.c 11 Jan 2003 13:41:40 -0000 @@ -37,10 +37,14 @@ #include "winternl.h" #include "winerror.h" #include "wine/debug.h" +#include "module.h" WINE_DEFAULT_DEBUG_CHANNEL(resource); +/* FIXME FIXME */ +#define _KERNEL32_ +#ifdef _NTSYSTEM_ /********************************************************************** * is_data_file_module * @@ -156,11 +160,11 @@ } len = MultiByteToWideChar( CP_ACP, 0, name, -1, NULL, 0 ); - if ((nameW = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) ))) + if ((nameW = RtlAllocateHeap( GetProcessHeap(), 0, len * sizeof(WCHAR) ))) { MultiByteToWideChar( CP_ACP, 0, name, -1, nameW, len ); ret = find_entry_by_nameW( dir, nameW, root ); - HeapFree( GetProcessHeap(), 0, nameW ); + RtlFreeHeap( GetProcessHeap(), 0, nameW ); } return ret; } @@ -206,12 +210,18 @@ if ((result = (HRSRC)find_entry_by_id( resdirptr, lang, root ))) goto found; /* 2. Language with neutral sublanguage */ - lang = MAKELANGID(PRIMARYLANGID(lang), SUBLANG_NEUTRAL); - if ((result = (HRSRC)find_entry_by_id( resdirptr, lang, root ))) goto found; + if (1 || SUBLANGID(lang) != SUBLANG_NEUTRAL) + { + lang = MAKELANGID(PRIMARYLANGID(lang), SUBLANG_NEUTRAL); + if ((result = (HRSRC)find_entry_by_id( resdirptr, lang, root ))) goto found; + } /* 3. Neutral language with neutral sublanguage */ - lang = MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL); - if ((result = (HRSRC)find_entry_by_id( resdirptr, lang, root ))) goto found; + if (1 || PRIMARYLANGID(lang) != LANG_NEUTRAL) + { + lang = MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL); + if ((result = (HRSRC)find_entry_by_id( resdirptr, lang, root ))) goto found; + } /* 4. Neutral language with default sublanguage */ lang = MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT); @@ -272,40 +282,9 @@ found: return result; } +#endif - -/********************************************************************** - * PE_LoadResource - */ -HGLOBAL PE_LoadResource( HMODULE hmod, HRSRC hRsrc ) -{ - DWORD offset; - - if (!hRsrc) return 0; - if (!hmod) hmod = GetModuleHandleA( NULL ); - - offset = ((PIMAGE_RESOURCE_DATA_ENTRY)hRsrc)->OffsetToData; - - if (is_data_file_module(hmod)) - { - hmod = (HMODULE)((ULONG_PTR)hmod & ~1); - return (HGLOBAL)RtlImageRvaToVa( RtlImageNtHeader(hmod), hmod, offset, NULL ); - } - else - return (HGLOBAL)((char *)hmod + offset); -} - - -/********************************************************************** - * PE_SizeofResource - */ -DWORD PE_SizeofResource( HRSRC hRsrc ) -{ - if (!hRsrc) return 0; - return ((PIMAGE_RESOURCE_DATA_ENTRY)hRsrc)->Size; -} - - +#ifdef _KERNEL32_ /********************************************************************** * EnumResourceTypesA (KERNEL32.@) */ @@ -528,3 +507,69 @@ } return ret; } +#endif + +#ifdef _NTSYSTEM_ +NTSTATUS WINAPI LdrAccessResource(HMODULE hModule, PIMAGE_RESOURCE_DATA_ENTRY resDataEntry, + void** pres, PULONG size) +{ + DWORD offset; + NTSTATUS nts; + + if (!resDataEntry) return STATUS_RESOURCE_DATA_NOT_FOUND; + if (!hModule && + (nts = LdrGetDllHandle(0, 0, NULL, (void**)&hModule)) != STATUS_SUCCESS) + return nts; + + offset = resDataEntry->OffsetToData; + + if (is_data_file_module(hModule)) + { + hModule = (HMODULE)((ULONG_PTR)hModule & ~1); + if (pres) + *pres = RtlImageRvaToVa( RtlImageNtHeader(hModule), (void*)hModule, offset, NULL ); + } + else + if (pres) *pres = ((char *)hModule + offset); + if (size) *size = resDataEntry->Size; + return STATUS_SUCCESS; +} + + +NTSTATUS WINAPI LdrFindResourceDirectory_U(HMODULE hModule, PLDR_RESOURCE_INFO resinfo, + DWORD level, + PIMAGE_RESOURCE_DIRECTORY_ENTRY* addr) +{ + return STATUS_NOT_IMPLEMENTED; +} + +NTSTATUS WINAPI LdrFindResource_U(HMODULE hModule, PLDR_RESOURCE_INFO resinfo, + ULONG level, PIMAGE_RESOURCE_DATA_ENTRY* resDataEntry) +{ + const IMAGE_RESOURCE_DIRECTORY* resdirptr; + const void* root; + + if (!(resdirptr = get_resdir(hModule))) return STATUS_RESOURCE_TYPE_NOT_FOUND; + root = resdirptr; + + if (level > RESOURCE_TYPE_LEVEL) + { + if (!(resdirptr = find_entry_by_nameW(resdirptr, (LPCWSTR)resinfo->Type, root))) + return STATUS_RESOURCE_NAME_NOT_FOUND; + + if (level > RESOURCE_NAME_LEVEL) + { + if (!(resdirptr = find_entry_by_nameW(resdirptr, (LPCWSTR)resinfo->Name, root))) + return STATUS_RESOURCE_LANG_NOT_FOUND; + + if (level > RESOURCE_LANGUAGE_LEVEL) + { + if (!(resdirptr = find_entry_by_id(resdirptr, resinfo->Language, root))) + return STATUS_RESOURCE_DATA_NOT_FOUND; + } + } + } + if (resDataEntry) *resDataEntry = (void*)resdirptr; + return STATUS_SUCCESS; +} +#endif Index: loader/resource.c =================================================================== RCS file: /home/cvs/cvsroot/wine/wine/loader/resource.c,v retrieving revision 1.65 diff -u -u -r1.65 resource.c --- loader/resource.c 12 Dec 2002 23:34:01 -0000 1.65 +++ loader/resource.c 22 Dec 2002 10:39:23 -0000 @@ -259,6 +259,8 @@ */ static DWORD RES_SizeofResource( HMODULE hModule, HRSRC hRsrc, BOOL bRet16 ) { + DWORD size = 0; + if (!hRsrc) return 0; TRACE("(%p, %p, %s)\n", hModule, hRsrc, bRet16? "NE" : "PE" ); @@ -272,15 +274,22 @@ if (!pModule->module32) /* 16-bit NE module */ { /* If we got a 32-bit hRsrc, we don't need to convert it */ - return NE_SizeofResource( pModule, hRsrc ); + size = NE_SizeofResource( pModule, hRsrc ); + } + else + { + /* If we got a 16-bit hRsrc, convert it */ + if (!HIWORD(hRsrc)) hRsrc = MapHRsrc16To32( pModule, hRsrc ); + if (hRsrc) size = ((PIMAGE_RESOURCE_DATA_ENTRY)hRsrc)->Size; } - - /* If we got a 16-bit hRsrc, convert it */ - if (!HIWORD(hRsrc)) hRsrc = MapHRsrc16To32( pModule, hRsrc ); } - - /* 32-bit PE module */ - return PE_SizeofResource( hRsrc ); + else + { + /* 32-bit PE module */ + if (LdrAccessResource( hModule, (PIMAGE_RESOURCE_DATA_ENTRY)hRsrc, NULL, &size) != STATUS_SUCCESS) + size = 0; + } + return size; } /********************************************************************** @@ -314,8 +323,13 @@ { /* If we got a 16-bit hRsrc, convert it */ HRSRC hRsrc32 = HIWORD(hRsrc)? hRsrc : MapHRsrc16To32( pModule, hRsrc ); + void* res; - hMem = PE_LoadResource( pModule->module32, hRsrc32 ); + if (LdrAccessResource( pModule->module32, + (PIMAGE_RESOURCE_DATA_ENTRY)hRsrc32, + &res, NULL ) != STATUS_SUCCESS) + res = NULL; + hMem = (HGLOBAL)res; /* If we need to return a 16-bit resource, convert it */ if ( bRet16 ) @@ -331,7 +345,13 @@ else { /* 32-bit PE module */ - hMem = PE_LoadResource( hModule, hRsrc ); + void* res; + + if (LdrAccessResource( hModule, + (PIMAGE_RESOURCE_DATA_ENTRY)hRsrc, + &res, NULL ) != STATUS_SUCCESS) + res = NULL; + hMem = (HGLOBAL)res; } return hMem; @@ -352,7 +372,7 @@ HRSRC WINAPI FindResourceA( HMODULE hModule, LPCSTR name, LPCSTR type ) { return RES_FindResource( hModule, type, name, - MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL), FALSE, FALSE ); + MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL), FALSE, FALSE ); } /********************************************************************** @@ -381,7 +401,7 @@ HRSRC WINAPI FindResourceW(HINSTANCE hModule, LPCWSTR name, LPCWSTR type) { return RES_FindResource( hModule, (LPCSTR)type, (LPCSTR)name, - MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL), TRUE, FALSE ); + MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL), TRUE, FALSE ); } /********************************************************************** @@ -489,3 +509,4 @@ { return RES_SizeofResource( hModule, hRsrc, FALSE ); } + Index: misc/version.c =================================================================== RCS file: /home/cvs/cvsroot/wine/wine/misc/version.c,v retrieving revision 1.61 diff -u -u -r1.61 version.c --- misc/version.c 13 Sep 2002 17:47:44 -0000 1.61 +++ misc/version.c 11 Jan 2003 15:05:46 -0000 @@ -453,18 +453,18 @@ from one windows version */ for ( wm = MODULE_modref_list; wm; wm=wm->next ) { - nt = RtlImageNtHeader(wm->module); + nt = RtlImageNtHeader(wm->ldr_module.BaseAddress); ophd = &nt->OptionalHeader; TRACE("%s: %02x.%02x/%02x.%02x/%02x.%02x/%02x.%02x\n", - wm->modname, + debugstr_w(wm->ldr_module.BaseDllName.Buffer), ophd->MajorLinkerVersion, ophd->MinorLinkerVersion, ophd->MajorOperatingSystemVersion, ophd->MinorOperatingSystemVersion, ophd->MajorImageVersion, ophd->MinorImageVersion, ophd->MajorSubsystemVersion, ophd->MinorSubsystemVersion); /* test if it is an external (native) dll */ - if (!(wm->flags & WINE_MODREF_INTERNAL)) + if (!(wm->ldr_module.Flags & WINE_MODREF_INTERNAL)) { int i; for (i = 0; special_dlls[i]; i++) @@ -472,13 +472,13 @@ /* test if it is a special dll */ if (!strcasecmp(wm->modname, special_dlls[i])) { - DWORD DllVersion = VERSION_GetSystemDLLVersion(wm->module); + DWORD DllVersion = VERSION_GetSystemDLLVersion(wm->ldr_module.BaseAddress); if (WinVersion == NB_WINDOWS_VERSIONS) WinVersion = DllVersion; else { if (WinVersion != DllVersion) { ERR("You mixed system DLLs from different windows versions! Expect a crash! (%s: expected version '%s', but is '%s')\n", - wm->modname, + debugstr_w(wm->ldr_module.BaseDllName.Buffer), VersionData[WinVersion].getVersionEx.szCSDVersion, VersionData[DllVersion].getVersionEx.szCSDVersion); return WIN20; /* this may let the exe exiting */ Index: relay32/builtin32.c =================================================================== RCS file: /home/cvs/cvsroot/wine/wine/relay32/builtin32.c,v retrieving revision 1.90 diff -u -u -r1.90 builtin32.c --- relay32/builtin32.c 21 Nov 2002 03:45:02 -0000 1.90 +++ relay32/builtin32.c 11 Jan 2003 15:09:31 -0000 @@ -134,7 +134,7 @@ } TRACE( "loaded %s %p %p\n", fullname, wm, module ); HeapFree( GetProcessHeap(), 0, fullname ); - wm->refCount++; /* we don't support freeing builtin dlls (FIXME)*/ + wm->ldr_module.LoadCount++; /* we don't support freeing builtin dlls (FIXME)*/ /* setup relay debugging entry points */ if (TRACE_ON(relay)) RELAY_SetupDLL( (void *)module ); Index: relay32/relay386.c =================================================================== RCS file: /home/cvs/cvsroot/wine/wine/relay32/relay386.c,v retrieving revision 1.50 diff -u -u -r1.50 relay386.c --- relay32/relay386.c 10 Dec 2002 22:56:44 -0000 1.50 +++ relay32/relay386.c 22 Dec 2002 14:01:40 -0000 @@ -238,8 +238,8 @@ for (wm = MODULE_modref_list; wm; wm = wm->next) { - if (!(wm->flags & WINE_MODREF_INTERNAL)) continue; - exp = RtlImageDirectoryEntryToData( wm->module, TRUE, IMAGE_DIRECTORY_ENTRY_EXPORT, &size ); + if (!(wm->ldr_module.Flags & WINE_MODREF_INTERNAL)) continue; + exp = RtlImageDirectoryEntryToData( wm->ldr_module.BaseAddress, TRUE, IMAGE_DIRECTORY_ENTRY_EXPORT, &size ); if (!exp) continue; debug = (DEBUG_ENTRY_POINT *)((char *)exp + size); if (debug <= relay && relay < debug + exp->NumberOfFunctions) @@ -251,7 +251,7 @@ /* Now find the function */ - base = (char *)wm->module; + base = (char *)wm->ldr_module.BaseAddress; strcpy( buffer, base + exp->Name ); p = buffer + strlen(buffer); if (p > buffer + 4 && !strcasecmp( p - 4, ".dll" )) p -= 4; Index: scheduler/process.c =================================================================== RCS file: /home/cvs/cvsroot/wine/wine/scheduler/process.c,v retrieving revision 1.205 diff -u -u -r1.205 process.c --- scheduler/process.c 5 Dec 2002 19:56:15 -0000 1.205 +++ scheduler/process.c 22 Dec 2002 13:45:44 -0000 @@ -533,7 +533,7 @@ /* create the main modref and load dependencies */ if (!(wm = PE_CreateModule( current_process.module, main_exe_name, 0, 0, FALSE ))) goto error; - wm->refCount++; + wm->ldr_module.LoadCount++; if (main_exe_file) CloseHandle( main_exe_file ); /* we no longer need it */ @@ -1355,7 +1355,7 @@ */ void WINAPI ExitProcess( DWORD status ) { - MODULE_DllProcessDetach( TRUE, (LPVOID)1 ); + LdrShutdownProcess(); SERVER_START_REQ( terminate_process ) { /* send the exit code to the server */ Index: scheduler/thread.c =================================================================== RCS file: /home/cvs/cvsroot/wine/wine/scheduler/thread.c,v retrieving revision 1.128 diff -u -u -r1.128 thread.c --- scheduler/thread.c 5 Dec 2002 19:56:15 -0000 1.128 +++ scheduler/thread.c 2 Jan 2003 14:12:32 -0000 @@ -376,12 +376,12 @@ if (last) { - MODULE_DllProcessDetach( TRUE, (LPVOID)1 ); + LdrShutdownProcess(); exit( code ); } else { - MODULE_DllThreadDetach( NULL ); + LdrShutdownThread(); if (!(NtCurrentTeb()->tibflags & TEBF_WIN32)) TASK_ExitTask(); SYSDEPS_ExitThread( code ); } Index: tools/winebuild/spec16.c =================================================================== RCS file: /home/cvs/cvsroot/wine/wine/tools/winebuild/spec16.c,v retrieving revision 1.38 diff -u -u -r1.38 spec16.c --- tools/winebuild/spec16.c 18 Oct 2002 00:29:32 -0000 1.38 +++ tools/winebuild/spec16.c 21 Dec 2002 20:21:37 -0000 @@ -31,6 +31,7 @@ #include "wine/exception.h" #include "wine/library.h" #include "builtin16.h" +#define _KERNEL32_ /* hack */ #include "module.h" #include "stackframe.h"