From 632676b17e140df69aa25dc6815de12bdf2ade3a Mon Sep 17 00:00:00 2001 From: Alexandre Julliard Date: Mon, 6 Oct 2003 21:18:51 +0000 Subject: [PATCH] Moved the final process init and dependency loading to dlls/ntdll/loader.c, (ab)using the LdrInitializeThunk entry point. --- dlls/kernel/process.c | 82 +++++---------------------- dlls/ntdll/loader.c | 122 +++++++++++++++++++++++++++++----------- dlls/ntdll/ntdll.spec | 2 +- dlls/ntdll/ntdll_misc.h | 1 + include/module.h | 4 -- include/winternl.h | 1 + 6 files changed, 106 insertions(+), 106 deletions(-) diff --git a/dlls/kernel/process.c b/dlls/kernel/process.c index ba2d5ff3fd6..22fe135db98 100644 --- a/dlls/kernel/process.c +++ b/dlls/kernel/process.c @@ -45,7 +45,6 @@ WINE_DEFAULT_DEBUG_CHANNEL(process); WINE_DECLARE_DEBUG_CHANNEL(server); WINE_DECLARE_DEBUG_CHANNEL(relay); -WINE_DECLARE_DEBUG_CHANNEL(snoop); /* Win32 process database */ typedef struct _PDB @@ -125,7 +124,6 @@ static const WCHAR winevdmW[] = {'w','i','n','e','v','d','m','.','e','x','e',0}; /* dlls/ntdll/env.c */ extern BOOL build_command_line( char **argv ); -extern void RELAY_InitDebugLists(void); extern void SHELL_LoadRegistry(void); extern void VERSION_Init( const WCHAR *appname ); extern void MODULE_InitLoadPath(void); @@ -331,7 +329,7 @@ static BOOL find_exe_file( const WCHAR *name, WCHAR *buffer, int buflen, HANDLE * * Load a PE format EXE file. */ -static HMODULE load_pe_exe( HANDLE file ) +static HMODULE load_pe_exe( const WCHAR *name, HANDLE file ) { IMAGE_NT_HEADERS *nt; HANDLE mapping; @@ -339,6 +337,7 @@ static HMODULE load_pe_exe( HANDLE file ) OBJECT_ATTRIBUTES attr; LARGE_INTEGER size; DWORD len = 0; + UINT drive_type; attr.Length = sizeof(attr); attr.RootDirectory = 0; @@ -364,10 +363,19 @@ static HMODULE load_pe_exe( HANDLE file ) if (nt->OptionalHeader.AddressOfEntryPoint) { if (!RtlImageRvaToSection( nt, module, nt->OptionalHeader.AddressOfEntryPoint )) - MESSAGE("VIRUS WARNING: PE module has an invalid entrypoint (0x%08lx) " + MESSAGE("VIRUS WARNING: PE module %s has an invalid entrypoint (0x%08lx) " "outside all sections (possibly infected by Tchernobyl/SpaceFiller virus)!\n", - nt->OptionalHeader.AddressOfEntryPoint ); + debugstr_w(name), nt->OptionalHeader.AddressOfEntryPoint ); } + + drive_type = GetDriveTypeW( name ); + /* don't keep the file handle open on removable media */ + if (drive_type == DRIVE_REMOVABLE || drive_type == DRIVE_CDROM) + { + CloseHandle( main_exe_file ); + main_exe_file = 0; + } + return module; } @@ -610,8 +618,6 @@ static BOOL process_init( char *argv[] ) } SERVER_END_REQ; - if (TRACE_ON(relay) || TRACE_ON(snoop)) RELAY_InitDebugLists(); - return TRUE; } @@ -625,65 +631,7 @@ static void start_process( void *arg ) { __TRY { - LPTHREAD_START_ROUTINE entry; - HANDLE main_file = main_exe_file; - IMAGE_NT_HEADERS *nt; - PEB *peb = NtCurrentTeb()->Peb; - UNICODE_STRING *main_exe_name = &peb->ProcessParameters->ImagePathName; - - if (main_file) - { - UINT drive_type = GetDriveTypeW( main_exe_name->Buffer ); - /* don't keep the file handle open on removable media */ - if (drive_type == DRIVE_REMOVABLE || drive_type == DRIVE_CDROM) main_file = 0; - } - - /* Retrieve entry point address */ - nt = RtlImageNtHeader( peb->ImageBaseAddress ); - entry = (LPTHREAD_START_ROUTINE)((char*)peb->ImageBaseAddress + - nt->OptionalHeader.AddressOfEntryPoint); - - /* Install signal handlers; this cannot be done before, since we cannot - * send exceptions to the debugger before the create process event that - * is sent by REQ_INIT_PROCESS_DONE. - * We do need the handlers in place by the time the request is over, so - * we set them up here. If we segfault between here and the server call - * something is very wrong... */ - if (!SIGNAL_Init()) goto error; - - /* Signal the parent process to continue */ - SERVER_START_REQ( init_process_done ) - { - req->module = peb->ImageBaseAddress; - req->module_size = nt->OptionalHeader.SizeOfImage; - req->entry = entry; - /* API requires a double indirection */ - req->name = &main_exe_name->Buffer; - req->exe_file = main_file; - req->gui = (nt->OptionalHeader.Subsystem != IMAGE_SUBSYSTEM_WINDOWS_CUI); - wine_server_add_data( req, main_exe_name->Buffer, main_exe_name->Length ); - wine_server_call( req ); - peb->BeingDebugged = reply->debugged; - } - SERVER_END_REQ; - - /* create the main modref and load dependencies */ - if (main_exe_file) CloseHandle( main_exe_file ); /* we no longer need it */ - if (MODULE_DllProcessAttach( NULL, (LPVOID)1 ) != STATUS_SUCCESS) - { - ERR( "Main exe initialization failed\n" ); - goto error; - } - - if (TRACE_ON(relay)) - DPRINTF( "%04lx:Starting process %s (entryproc=%p)\n", - GetCurrentThreadId(), debugstr_w(main_exe_name->Buffer), entry ); - if (peb->BeingDebugged) DbgBreakPoint(); - SetLastError(0); /* clear error code */ - ExitThread( entry( NtCurrentTeb()->Peb ) ); - - error: - ExitProcess( GetLastError() ); + LdrInitializeThunk( main_exe_file, 0, 0, 0 ); } __EXCEPT(UnhandledExceptionFilter) { @@ -753,7 +701,7 @@ void __wine_process_init( int argc, char *argv[] ) { case BINARY_PE_EXE: TRACE( "starting Win32 binary %s\n", debugstr_w(main_exe_name) ); - if ((current_process.module = load_pe_exe( main_exe_file ))) goto found; + if ((current_process.module = load_pe_exe( main_exe_name, main_exe_file ))) goto found; MESSAGE( "wine: could not load %s as Win32 binary\n", debugstr_w(main_exe_name) ); ExitProcess(1); case BINARY_PE_DLL: diff --git a/dlls/ntdll/loader.c b/dlls/ntdll/loader.c index edce7f6ca60..28bcef7f75f 100644 --- a/dlls/ntdll/loader.c +++ b/dlls/ntdll/loader.c @@ -66,12 +66,12 @@ static const char * const reason_names[] = static const WCHAR dllW[] = {'.','d','l','l',0}; /* internal representation of 32bit modules. per process. */ -struct _wine_modref +typedef struct _wine_modref { LDR_MODULE ldr; int nDeps; struct _wine_modref **deps; -}; +} WINE_MODREF; static UINT tls_module_count; /* number of modules with TLS directory */ static UINT tls_total_size; /* total size of TLS storage */ @@ -675,7 +675,7 @@ static BOOL MODULE_InitDLL( WINE_MODREF *wm, UINT reason, LPVOID lpReserved ) /************************************************************************* - * MODULE_DllProcessAttach + * process_attach * * Send the process attach notification to all DLLs the given module * depends on (recursively). This is somewhat complicated due to the fact that @@ -702,34 +702,18 @@ static BOOL MODULE_InitDLL( WINE_MODREF *wm, UINT reason, LPVOID lpReserved ) * list after the attach notification has returned. This implies that the * detach notifications are called in the reverse of the sequence the attach * notifications *returned*. + * + * The loader_section must be locked while calling this function. */ -NTSTATUS MODULE_DllProcessAttach( WINE_MODREF *wm, LPVOID lpReserved ) +static NTSTATUS process_attach( WINE_MODREF *wm, LPVOID lpReserved ) { NTSTATUS status = STATUS_SUCCESS; int i; - RtlEnterCriticalSection( &loader_section ); - - if (!wm) - { - /* allocate the modref for the main exe */ - if (!(wm = alloc_module( NtCurrentTeb()->Peb->ImageBaseAddress, - NtCurrentTeb()->Peb->ProcessParameters->ImagePathName.Buffer ))) - { - status = STATUS_NO_MEMORY; - goto done; - } - wm->ldr.LoadCount = -1; /* can't unload main exe */ - if ((status = fixup_imports( wm )) != STATUS_SUCCESS) goto done; - if ((status = alloc_process_tls()) != STATUS_SUCCESS) goto done; - if ((status = alloc_thread_tls()) != STATUS_SUCCESS) goto done; - } - assert( wm ); - /* prevent infinite recursion in case of cyclical dependencies */ if ( ( wm->ldr.Flags & LDR_LOAD_IN_PROGRESS ) || ( wm->ldr.Flags & LDR_PROCESS_ATTACHED ) ) - goto done; + return status; TRACE("(%s,%p) - START\n", debugstr_w(wm->ldr.BaseDllName.Buffer), lpReserved ); @@ -740,7 +724,7 @@ NTSTATUS MODULE_DllProcessAttach( WINE_MODREF *wm, LPVOID lpReserved ) for ( i = 0; i < wm->nDeps; i++ ) { if (!wm->deps[i]) continue; - if ((status = MODULE_DllProcessAttach( wm->deps[i], lpReserved )) != STATUS_SUCCESS) break; + if ((status = process_attach( wm->deps[i], lpReserved )) != STATUS_SUCCESS) break; } /* Call DLL entry point */ @@ -757,25 +741,22 @@ NTSTATUS MODULE_DllProcessAttach( WINE_MODREF *wm, LPVOID lpReserved ) InsertTailList(&NtCurrentTeb()->Peb->LdrData->InInitializationOrderModuleList, &wm->ldr.InInitializationOrderModuleList); - + /* Remove recursion flag */ wm->ldr.Flags &= ~LDR_LOAD_IN_PROGRESS; TRACE("(%s,%p) - END\n", debugstr_w(wm->ldr.BaseDllName.Buffer), lpReserved ); - - done: - RtlLeaveCriticalSection( &loader_section ); return status; } /************************************************************************* - * MODULE_DllProcessDetach + * process_detach * * Send DLL process detach notifications. See the comment about calling - * sequence at MODULE_DllProcessAttach. Unless the bForceDetach flag + * sequence at process_attach. Unless the bForceDetach flag * is set, only DLLs with zero refcount are notified. */ -static void MODULE_DllProcessDetach( BOOL bForceDetach, LPVOID lpReserved ) +static void process_detach( BOOL bForceDetach, LPVOID lpReserved ) { PLIST_ENTRY mark, entry; PLDR_MODULE mod; @@ -1393,7 +1374,7 @@ NTSTATUS WINAPI LdrLoadDll(LPCWSTR path_name, DWORD flags, if (nts == STATUS_SUCCESS && !(wm->ldr.Flags & LDR_DONT_RESOLVE_REFS)) { - nts = MODULE_DllProcessAttach( wm, NULL ); + nts = process_attach( wm, NULL ); if (nts != STATUS_SUCCESS) { WARN("Attach failed for module %s\n", debugstr_w(libname->Buffer)); @@ -1466,7 +1447,7 @@ NTSTATUS WINAPI LdrQueryProcessModuleInformation(PSYSTEM_MODULE_INFORMATION smi, void WINAPI LdrShutdownProcess(void) { TRACE("()\n"); - MODULE_DllProcessDetach( TRUE, (LPVOID)1 ); + process_detach( TRUE, (LPVOID)1 ); } /****************************************************************** @@ -1614,7 +1595,7 @@ NTSTATUS WINAPI LdrUnloadDll( HMODULE hModule ) /* Call process detach notifications */ if ( free_lib_count <= 1 ) { - MODULE_DllProcessDetach( FALSE, NULL ); + process_detach( FALSE, NULL ); MODULE_FlushModrefs(); } @@ -1658,6 +1639,79 @@ PIMAGE_NT_HEADERS WINAPI RtlImageNtHeader(HMODULE hModule) } +/****************************************************************** + * LdrInitializeThunk (NTDLL.@) + * + * FIXME: the arguments are not correct, main_file is a Wine invention. + */ +void WINAPI LdrInitializeThunk( HANDLE main_file, ULONG unknown2, ULONG unknown3, ULONG unknown4 ) +{ + NTSTATUS status; + WINE_MODREF *wm; + LPTHREAD_START_ROUTINE entry; + PEB *peb = NtCurrentTeb()->Peb; + UNICODE_STRING *main_exe_name = &peb->ProcessParameters->ImagePathName; + IMAGE_NT_HEADERS *nt = RtlImageNtHeader( peb->ImageBaseAddress ); + + /* allocate the modref for the main exe */ + if (!(wm = alloc_module( peb->ImageBaseAddress, main_exe_name->Buffer ))) + { + status = STATUS_NO_MEMORY; + goto error; + } + wm->ldr.LoadCount = -1; /* can't unload main exe */ + entry = wm->ldr.EntryPoint; + + /* Install signal handlers; this cannot be done before, since we cannot + * send exceptions to the debugger before the create process event that + * is sent by REQ_INIT_PROCESS_DONE. + * We do need the handlers in place by the time the request is over, so + * we set them up here. If we segfault between here and the server call + * something is very wrong... */ + if (!SIGNAL_Init()) exit(1); + + /* Signal the parent process to continue */ + SERVER_START_REQ( init_process_done ) + { + req->module = peb->ImageBaseAddress; + req->module_size = wm->ldr.SizeOfImage; + req->entry = entry; + /* API requires a double indirection */ + req->name = &main_exe_name->Buffer; + req->exe_file = main_file; + req->gui = (nt->OptionalHeader.Subsystem != IMAGE_SUBSYSTEM_WINDOWS_CUI); + wine_server_add_data( req, main_exe_name->Buffer, main_exe_name->Length ); + wine_server_call( req ); + peb->BeingDebugged = reply->debugged; + } + SERVER_END_REQ; + + if (main_file) NtClose( main_file ); /* we no longer need it */ + if (TRACE_ON(relay) || TRACE_ON(snoop)) RELAY_InitDebugLists(); + + RtlEnterCriticalSection( &loader_section ); + + if ((status = fixup_imports( wm )) != STATUS_SUCCESS) goto error; + if ((status = alloc_process_tls()) != STATUS_SUCCESS) goto error; + if ((status = alloc_thread_tls()) != STATUS_SUCCESS) goto error; + if ((status = process_attach( wm, (LPVOID)1 )) != STATUS_SUCCESS) goto error; + + RtlLeaveCriticalSection( &loader_section ); + + if (TRACE_ON(relay)) + DPRINTF( "%04lx:Starting process %s (entryproc=%p)\n", GetCurrentThreadId(), + debugstr_w(peb->ProcessParameters->ImagePathName.Buffer), entry ); + + NtCurrentTeb()->last_error = 0; /* clear error code */ + if (peb->BeingDebugged) DbgBreakPoint(); + NtTerminateProcess( GetCurrentProcess(), entry( peb ) ); + +error: + ERR( "Main exe initialization failed, status %lx\n", status ); + exit(1); +} + + /*********************************************************************** * RtlImageDirectoryEntryToData (NTDLL.@) */ diff --git a/dlls/ntdll/ntdll.spec b/dlls/ntdll/ntdll.spec index a0b74a246d2..6dead1e104e 100644 --- a/dlls/ntdll/ntdll.spec +++ b/dlls/ntdll/ntdll.spec @@ -41,7 +41,7 @@ @ stdcall LdrFindResource_U(long ptr long ptr) @ stdcall LdrGetDllHandle(long long ptr ptr) @ stdcall LdrGetProcedureAddress(ptr ptr long ptr) -@ stub LdrInitializeThunk +@ stdcall LdrInitializeThunk(long long long long) @ stdcall LdrLoadDll(wstr long ptr ptr) @ stdcall LdrLockLoaderLock(long ptr ptr) @ stub LdrProcessRelocationBlock diff --git a/dlls/ntdll/ntdll_misc.h b/dlls/ntdll/ntdll_misc.h index fc261168829..56bab09f6f1 100644 --- a/dlls/ntdll/ntdll_misc.h +++ b/dlls/ntdll/ntdll_misc.h @@ -40,6 +40,7 @@ extern NTSTATUS NTDLL_wait_for_multiple_objects( UINT count, const HANDLE *handl const LARGE_INTEGER *timeout ); /* module handling */ +extern void RELAY_InitDebugLists(void); extern FARPROC RELAY_GetProcAddress( HMODULE module, IMAGE_EXPORT_DIRECTORY *exports, DWORD exp_size, FARPROC proc, const WCHAR *user ); extern FARPROC SNOOP_GetProcAddress( HMODULE hmod, IMAGE_EXPORT_DIRECTORY *exports, DWORD exp_size, diff --git a/include/module.h b/include/module.h index 16bf2d70ada..fddcfc6883b 100644 --- a/include/module.h +++ b/include/module.h @@ -128,9 +128,6 @@ typedef struct #include -struct _wine_modref; -typedef struct _wine_modref WINE_MODREF; - /* Resource types */ #define NE_SEG_TABLE(pModule) \ @@ -165,7 +162,6 @@ enum binary_type }; /* module.c */ -extern NTSTATUS MODULE_DllProcessAttach( WINE_MODREF *wm, LPVOID lpReserved ); extern NTSTATUS MODULE_DllThreadAttach( LPVOID lpReserved ); extern enum binary_type MODULE_GetBinaryType( HANDLE hfile ); extern FARPROC16 WINAPI WIN32_GetProcAddress16( HMODULE hmodule, LPCSTR name ); diff --git a/include/winternl.h b/include/winternl.h index e3b6f72ef41..751ede4314b 100644 --- a/include/winternl.h +++ b/include/winternl.h @@ -954,6 +954,7 @@ NTSTATUS WINAPI LdrFindResourceDirectory_U(HMODULE,const LDR_RESOURCE_INFO*,ULO NTSTATUS WINAPI LdrFindResource_U(HMODULE,const LDR_RESOURCE_INFO*,ULONG,const IMAGE_RESOURCE_DATA_ENTRY**); NTSTATUS WINAPI LdrGetDllHandle(ULONG, ULONG, const UNICODE_STRING*, HMODULE*); NTSTATUS WINAPI LdrGetProcedureAddress(HMODULE, const ANSI_STRING*, ULONG, void**); +void WINAPI LdrInitializeThunk(HANDLE,ULONG,ULONG,ULONG); NTSTATUS WINAPI LdrLoadDll(LPCWSTR, DWORD, const UNICODE_STRING*, HMODULE*); void WINAPI LdrShutdownProcess(void); void WINAPI LdrShutdownThread(void);