Commit 97ad311e authored by Alexandre Julliard's avatar Alexandre Julliard

Moved the 32-bit builtin loader and the remaining bits of the PE

loader into dlls/ntdll/loader.c.
parent ce85a905
......@@ -124,6 +124,8 @@ int main_create_flags = 0;
extern BOOL init_user_process_pmts( size_t, char*, size_t );
extern BOOL build_command_line( char **argv );
extern WINE_MODREF *MODULE_AllocModRef( HMODULE hModule, LPCSTR filename ); /* FIXME */
extern void RELAY_InitDebugLists(void);
extern void SHELL_LoadRegistry(void);
extern void VERSION_Init( const char *appname );
......@@ -276,6 +278,51 @@ static BOOL find_exe_file( const char *name, char *buffer, int buflen, HANDLE *h
}
/**********************************************************************
* load_pe_exe
*
* Load a PE format EXE file.
*/
static HMODULE load_pe_exe( HANDLE file )
{
IMAGE_NT_HEADERS *nt;
HANDLE mapping;
void *module;
OBJECT_ATTRIBUTES attr;
LARGE_INTEGER size;
DWORD len = 0;
attr.Length = sizeof(attr);
attr.RootDirectory = 0;
attr.ObjectName = NULL;
attr.Attributes = 0;
attr.SecurityDescriptor = NULL;
attr.SecurityQualityOfService = NULL;
size.QuadPart = 0;
if (NtCreateSection( &mapping, STANDARD_RIGHTS_REQUIRED | SECTION_QUERY | SECTION_MAP_READ,
&attr, &size, 0, SEC_IMAGE, file ) != STATUS_SUCCESS)
return NULL;
module = NULL;
if (NtMapViewOfSection( mapping, GetCurrentProcess(), &module, 0, 0, &size, &len,
ViewShare, 0, PAGE_READONLY ) != STATUS_SUCCESS)
return NULL;
NtClose( mapping );
/* virus check */
nt = RtlImageNtHeader( module );
if (nt->OptionalHeader.AddressOfEntryPoint)
{
if (!RtlImageRvaToSection( nt, module, nt->OptionalHeader.AddressOfEntryPoint ))
MESSAGE("VIRUS WARNING: PE module has an invalid entrypoint (0x%08lx) "
"outside all sections (possibly infected by Tchernobyl/SpaceFiller virus)!\n",
nt->OptionalHeader.AddressOfEntryPoint );
}
return module;
}
/***********************************************************************
* process_init
*
......@@ -411,6 +458,7 @@ static void start_process( void *arg )
LPTHREAD_START_ROUTINE entry;
HANDLE main_file = main_exe_file;
IMAGE_NT_HEADERS *nt;
WINE_MODREF *wm;
PEB *peb = NtCurrentTeb()->Peb;
if (main_file)
......@@ -450,11 +498,13 @@ static void start_process( void *arg )
SERVER_END_REQ;
/* create the main modref and load dependencies */
if (!PE_CreateModule( peb->ImageBaseAddress, main_exe_name, 0, 0, FALSE )) goto error;
if (!(wm = MODULE_AllocModRef( peb->ImageBaseAddress, main_exe_name ))) goto error;
if (main_exe_file) CloseHandle( main_exe_file ); /* we no longer need it */
MODULE_DllProcessAttach( NULL, (LPVOID)1 );
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",
......@@ -523,7 +573,7 @@ void __wine_process_init( int argc, char *argv[] )
{
case BINARY_PE_EXE:
TRACE( "starting Win32 binary %s\n", debugstr_a(main_exe_name) );
if ((current_process.module = PE_LoadImage( main_exe_file, main_exe_name, 0 ))) goto found;
if ((current_process.module = load_pe_exe( main_exe_file ))) goto found;
MESSAGE( "%s: could not load '%s' as Win32 binary\n", argv0, main_exe_name );
ExitProcess(1);
case BINARY_PE_DLL:
......
......@@ -14,7 +14,6 @@ C_SRCS = \
$(TOPOBJDIR)/files/smb.c \
$(TOPOBJDIR)/loader/loadorder.c \
$(TOPOBJDIR)/loader/module.c \
$(TOPOBJDIR)/loader/pe_image.c \
$(TOPOBJDIR)/loader/task.c \
$(TOPOBJDIR)/loader/ne/module.c \
$(TOPOBJDIR)/memory/codepage.c \
......@@ -28,7 +27,6 @@ C_SRCS = \
$(TOPOBJDIR)/misc/registry.c \
$(TOPOBJDIR)/misc/version.c \
$(TOPOBJDIR)/msdos/dpmi.c \
$(TOPOBJDIR)/relay32/builtin32.c \
$(TOPOBJDIR)/relay32/relay386.c \
$(TOPOBJDIR)/relay32/snoop.c \
$(TOPOBJDIR)/scheduler/handle.c \
......
......@@ -40,13 +40,12 @@ extern NTSTATUS NTDLL_wait_for_multiple_objects( UINT count, const HANDLE *handl
const LARGE_INTEGER *timeout );
/* module handling */
extern WINE_MODREF *MODULE_AllocModRef( HMODULE hModule, LPCSTR filename );
extern FARPROC RELAY_GetProcAddress( HMODULE module, IMAGE_EXPORT_DIRECTORY *exports,
DWORD exp_size, FARPROC proc, const char *user );
extern FARPROC SNOOP_GetProcAddress( HMODULE hmod, IMAGE_EXPORT_DIRECTORY *exports, DWORD exp_size,
FARPROC origfun, DWORD ordinal );
extern void RELAY_SetupDLL( const char *module );
extern void SNOOP_SetupDLL( HMODULE hmod );
static inline HANDLE ntdll_get_process_heap(void)
{
......
......@@ -181,7 +181,6 @@ enum binary_type
/* module.c */
extern NTSTATUS MODULE_DllProcessAttach( WINE_MODREF *wm, LPVOID lpReserved );
extern NTSTATUS MODULE_DllThreadAttach( LPVOID lpReserved );
extern WINE_MODREF *MODULE_FindModule( LPCSTR path );
extern enum binary_type MODULE_GetBinaryType( HANDLE hfile );
extern FARPROC16 WINAPI WIN32_GetProcAddress16( HMODULE hmodule, LPCSTR name );
extern void MODULE_WalkModref( DWORD id );
......@@ -216,20 +215,12 @@ extern void NE_CallUserSignalProc( HMODULE16 hModule, UINT16 code );
extern HRSRC PE_FindResourceW(HMODULE,LPCWSTR,LPCWSTR);
extern HRSRC PE_FindResourceExW(HMODULE,LPCWSTR,LPCWSTR,WORD);
/* loader/pe_image.c */
extern NTSTATUS PE_LoadLibraryExA(LPCSTR, DWORD, WINE_MODREF**);
extern HMODULE PE_LoadImage( HANDLE hFile, LPCSTR filename, DWORD flags );
extern WINE_MODREF *PE_CreateModule( HMODULE hModule, LPCSTR filename,
DWORD flags, HANDLE hFile, BOOL builtin );
extern DWORD PE_fixup_imports(WINE_MODREF *wm);
/* loader/loadorder.c */
extern BOOL MODULE_GetBuiltinPath( const char *libname, const char *ext, char *filename, UINT size );
extern void MODULE_GetLoadOrder( enum loadorder_type plo[], const char *path, BOOL win32 );
extern void MODULE_AddLoadOrderOption( const char *option );
/* relay32/builtin.c */
extern NTSTATUS BUILTIN32_LoadLibraryExA(LPCSTR name, DWORD flags, WINE_MODREF**);
extern HMODULE BUILTIN32_LoadExeModule( HMODULE main );
#endif /* __WINE_MODULE_H */
......@@ -23,7 +23,6 @@
#include <module.h>
extern void SNOOP_RegisterDLL(HMODULE,LPCSTR,DWORD,DWORD);
extern void SNOOP16_RegisterDLL(NE_MODULE*,LPCSTR);
extern FARPROC16 SNOOP16_GetProcAddress16(HMODULE16,DWORD,FARPROC16);
extern int SNOOP_ShowDebugmsgSnoop(const char *dll,int ord,const char *fname);
......
/*
* Win32 builtin functions
*
* Copyright 1997 Alexandre Julliard
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "config.h"
#include "wine/port.h"
#include <assert.h>
#include <string.h>
#include <stdarg.h>
#include <stdio.h>
#include <ctype.h>
#include <sys/types.h>
#ifdef HAVE_SYS_MMAN_H
#include <sys/mman.h>
#endif
#include "ntstatus.h"
#include "windef.h"
#include "winbase.h"
#include "wine/winbase16.h"
#include "wine/library.h"
#include "module.h"
#include "file.h"
#include "ntdll_misc.h"
#include "wine/server.h"
#include "wine/debug.h"
WINE_DEFAULT_DEBUG_CHANNEL(module);
WINE_DECLARE_DEBUG_CHANNEL(relay);
static HMODULE main_module;
static NTSTATUS last_status; /* use to gather all errors in callback */
/***********************************************************************
* load_library
*
* Load a library in memory; callback function for wine_dll_register
*/
static void load_library( void *base, const char *filename )
{
UNICODE_STRING wstr;
HMODULE module = (HMODULE)base, ret;
IMAGE_NT_HEADERS *nt;
WINE_MODREF *wm;
char *fullname;
DWORD len;
if (!base)
{
ERR("could not map image for %s\n", filename ? filename : "main exe" );
return;
}
if (!(nt = RtlImageNtHeader( module )))
{
ERR( "bad module for %s\n", filename ? filename : "main exe" );
last_status = STATUS_INVALID_IMAGE_FORMAT;
return;
}
if (!(nt->FileHeader.Characteristics & IMAGE_FILE_DLL))
{
/* if we already have an executable, ignore this one */
if (!main_module) main_module = module;
return; /* don't create the modref here, will be done later on */
}
RtlCreateUnicodeStringFromAsciiz(&wstr, filename);
if (LdrGetDllHandle(0, 0, &wstr, &ret) == STATUS_SUCCESS)
MESSAGE( "Warning: loading builtin %s, but native version already present. "
"Expect trouble.\n", filename );
RtlFreeUnicodeString( &wstr );
len = GetSystemDirectoryA( NULL, 0 );
if (!(fullname = RtlAllocateHeap( ntdll_get_process_heap(), 0, len + strlen(filename) + 1 )))
{
ERR( "can't load %s\n", filename );
last_status = STATUS_NO_MEMORY;
return;
}
GetSystemDirectoryA( fullname, len );
strcat( fullname, "\\" );
strcat( fullname, filename );
/* Create 32-bit MODREF */
if (!(wm = PE_CreateModule( module, fullname, 0, 0, TRUE )))
{
ERR( "can't load %s\n", filename );
RtlFreeHeap( ntdll_get_process_heap(), 0, fullname );
last_status = STATUS_NO_MEMORY;
return;
}
TRACE( "loaded %s %p %p\n", fullname, wm, module );
RtlFreeHeap( ntdll_get_process_heap(), 0, fullname );
/* setup relay debugging entry points */
if (TRACE_ON(relay)) RELAY_SetupDLL( (void *)module );
}
/***********************************************************************
* BUILTIN32_LoadLibraryExA
*
* Partly copied from the original PE_ version.
*
*/
NTSTATUS BUILTIN32_LoadLibraryExA(LPCSTR path, DWORD flags, WINE_MODREF** pwm)
{
char error[256], dllname[MAX_PATH], *p;
int file_exists;
LPCSTR name;
void *handle;
/* Fix the name in case we have a full path and extension */
name = path;
if ((p = strrchr( name, '\\' ))) name = p + 1;
if ((p = strrchr( name, '/' ))) name = p + 1;
if (strlen(name) >= sizeof(dllname)-4) return STATUS_NO_SUCH_FILE;
strcpy( dllname, name );
p = strrchr( dllname, '.' );
if (!p) strcat( dllname, ".dll" );
for (p = dllname; *p; p++) *p = FILE_tolower(*p);
last_status = STATUS_SUCCESS;
/* load_library will modify last_status. Note also that load_library can be
* called several times, if the .so file we're loading has dependencies.
* last_status will gather all the errors we may get while loading all these
* libraries
*/
if (!(handle = wine_dll_load( dllname, error, sizeof(error), &file_exists )))
{
if (!file_exists)
{
/* The file does not exist -> WARN() */
WARN("cannot open .so lib for builtin %s: %s\n", name, error);
return STATUS_NO_SUCH_FILE;
}
/* ERR() for all other errors (missing functions, ...) */
ERR("failed to load .so lib for builtin %s: %s\n", name, error );
return STATUS_PROCEDURE_NOT_FOUND;
}
if (last_status != STATUS_SUCCESS) return last_status;
if (!((*pwm) = MODULE_FindModule( path ))) *pwm = MODULE_FindModule( dllname );
if (!*pwm)
{
ERR( "loaded .so but dll %s still not found - 16-bit dll or version conflict.\n", dllname );
/* wine_dll_unload( handle );*/
return STATUS_INVALID_IMAGE_FORMAT;
}
(*pwm)->dlhandle = handle;
return STATUS_SUCCESS;
}
/***********************************************************************
* BUILTIN32_Init
*
* Initialize loading callbacks and return HMODULE of main exe.
* 'main' is the main exe in case it was already loaded from a PE file.
*/
HMODULE BUILTIN32_LoadExeModule( HMODULE main )
{
main_module = main;
last_status = STATUS_SUCCESS;
wine_dll_set_callback( load_library );
if (!main_module)
MESSAGE( "No built-in EXE module loaded! Did you create a .spec file?\n" );
if (last_status != STATUS_SUCCESS)
MESSAGE( "Error while processing initial modules\n");
return main_module;
}
......@@ -142,47 +142,51 @@ int SNOOP_ShowDebugmsgSnoop(const char *dll, int ord, const char *fname) {
return 1;
}
void
SNOOP_RegisterDLL(HMODULE hmod,LPCSTR name,DWORD ordbase,DWORD nrofordinals) {
SNOOP_DLL **dll = &(firstdll);
char *s;
void *addr;
SIZE_T size;
TRACE("hmod=%p, name=%s, ordbase=%ld, nrofordinals=%ld\n",
hmod, name, ordbase, nrofordinals);
if (!TRACE_ON(snoop)) return;
while (*dll) {
if ((*dll)->hmod == hmod)
{
/* another dll, loaded at the same address */
addr = (*dll)->funs;
size = (*dll)->nrofordinals * sizeof(SNOOP_FUN);
NtFreeVirtualMemory(GetCurrentProcess(), &addr, &size, MEM_RELEASE);
break;
}
dll = &((*dll)->next);
}
*dll = RtlReAllocateHeap(ntdll_get_process_heap(),
HEAP_ZERO_MEMORY, *dll,
sizeof(SNOOP_DLL) + strlen(name));
(*dll)->hmod = hmod;
(*dll)->ordbase = ordbase;
(*dll)->nrofordinals = nrofordinals;
strcpy( (*dll)->name, name );
if ((s=strrchr((*dll)->name,'.')))
*s='\0';
size = nrofordinals * sizeof(SNOOP_FUN);
NtAllocateVirtualMemory(GetCurrentProcess(), &addr, NULL, &size,
MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
if (!addr) {
RtlFreeHeap(ntdll_get_process_heap(),0,*dll);
FIXME("out of memory\n");
return;
}
(*dll)->funs = addr;
memset((*dll)->funs,0,size);
void SNOOP_SetupDLL(HMODULE hmod)
{
SNOOP_DLL **dll = &firstdll;
char *p, *name;
void *addr;
SIZE_T size;
IMAGE_EXPORT_DIRECTORY *exports;
exports = RtlImageDirectoryEntryToData( hmod, TRUE, IMAGE_DIRECTORY_ENTRY_EXPORT, &size );
if (!exports) return;
name = (char *)hmod + exports->Name;
TRACE("hmod=%p, name=%s\n", hmod, name);
while (*dll) {
if ((*dll)->hmod == hmod)
{
/* another dll, loaded at the same address */
addr = (*dll)->funs;
size = (*dll)->nrofordinals * sizeof(SNOOP_FUN);
NtFreeVirtualMemory(GetCurrentProcess(), &addr, &size, MEM_RELEASE);
break;
}
dll = &((*dll)->next);
}
*dll = RtlReAllocateHeap(ntdll_get_process_heap(),
HEAP_ZERO_MEMORY, *dll,
sizeof(SNOOP_DLL) + strlen(name));
(*dll)->hmod = hmod;
(*dll)->ordbase = exports->Base;
(*dll)->nrofordinals = exports->NumberOfFunctions;
strcpy( (*dll)->name, name );
p = (*dll)->name + strlen((*dll)->name) - 4;
if (p > (*dll)->name && !strcasecmp( p, ".dll" )) *p = 0;
size = exports->NumberOfFunctions * sizeof(SNOOP_FUN);
NtAllocateVirtualMemory(GetCurrentProcess(), &addr, NULL, &size,
MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
if (!addr) {
RtlFreeHeap(ntdll_get_process_heap(),0,*dll);
FIXME("out of memory\n");
return;
}
(*dll)->funs = addr;
memset((*dll)->funs,0,size);
}
FARPROC SNOOP_GetProcAddress( HMODULE hmod, IMAGE_EXPORT_DIRECTORY *exports, DWORD exp_size,
......@@ -432,9 +436,10 @@ __ASM_GLOBAL_FUNC( SNOOP_Return,
".long " __ASM_NAME("SNOOP_DoReturn") ",0" );
#else /* !__i386__ */
void SNOOP_RegisterDLL(HMODULE hmod,LPCSTR name,DWORD nrofordinals, DWORD dw) {
if (!TRACE_ON(snoop)) return;
FIXME("snooping works only on i386 for now.\n");
void SNOOP_SetupDLL(HMODULE hmod)
{
FIXME("snooping works only on i386 for now.\n");
}
FARPROC SNOOP_GetProcAddress( HMODULE hmod, IMAGE_EXPORT_DIRECTORY *exports, DWORD exp_size,
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment