diff --git a/dlls/kernel32/tests/loader.c b/dlls/kernel32/tests/loader.c index d44c052a87e..2f549681d8c 100644 --- a/dlls/kernel32/tests/loader.c +++ b/dlls/kernel32/tests/loader.c @@ -599,32 +599,32 @@ todo_wine dos_header.e_magic = 0; status = map_image_section( &nt_header ); - todo_wine ok( status == STATUS_INVALID_IMAGE_NOT_MZ, "NtCreateSection error %08x\n", status ); + ok( status == STATUS_INVALID_IMAGE_NOT_MZ, "NtCreateSection error %08x\n", status ); dos_header.e_magic = IMAGE_DOS_SIGNATURE; nt_header.Signature = IMAGE_OS2_SIGNATURE; status = map_image_section( &nt_header ); - todo_wine ok( status == STATUS_INVALID_IMAGE_NE_FORMAT, "NtCreateSection error %08x\n", status ); + ok( status == STATUS_INVALID_IMAGE_NE_FORMAT, "NtCreateSection error %08x\n", status ); nt_header.Signature = 0xdeadbeef; status = map_image_section( &nt_header ); - todo_wine ok( status == STATUS_INVALID_IMAGE_PROTECT, "NtCreateSection error %08x\n", status ); + ok( status == STATUS_INVALID_IMAGE_PROTECT, "NtCreateSection error %08x\n", status ); nt_header.Signature = IMAGE_NT_SIGNATURE; nt_header.OptionalHeader.Magic = 0xdead; status = map_image_section( &nt_header ); - todo_wine ok( status == STATUS_INVALID_IMAGE_FORMAT, "NtCreateSection error %08x\n", status ); + ok( status == STATUS_INVALID_IMAGE_FORMAT, "NtCreateSection error %08x\n", status ); nt_header.OptionalHeader.Magic = IMAGE_NT_OPTIONAL_HDR_MAGIC; nt_header.FileHeader.Machine = 0xdead; status = map_image_section( &nt_header ); - todo_wine ok( status == STATUS_INVALID_IMAGE_FORMAT || broken(status == STATUS_SUCCESS), /* win2k */ - "NtCreateSection error %08x\n", status ); + ok( status == STATUS_INVALID_IMAGE_FORMAT || broken(status == STATUS_SUCCESS), /* win2k */ + "NtCreateSection error %08x\n", status ); nt_header.FileHeader.Machine = IMAGE_FILE_MACHINE_UNKNOWN; status = map_image_section( &nt_header ); - todo_wine ok( status == STATUS_INVALID_IMAGE_FORMAT || broken(status == STATUS_SUCCESS), /* win2k */ - "NtCreateSection error %08x\n", status ); + ok( status == STATUS_INVALID_IMAGE_FORMAT || broken(status == STATUS_SUCCESS), /* win2k */ + "NtCreateSection error %08x\n", status ); switch (orig_machine) { @@ -634,7 +634,7 @@ todo_wine case IMAGE_FILE_MACHINE_ARM64: nt_header.FileHeader.Machine = IMAGE_FILE_MACHINE_ARMNT; break; } status = map_image_section( &nt_header ); - todo_wine ok( status == STATUS_INVALID_IMAGE_FORMAT || broken(status == STATUS_SUCCESS), /* win2k */ + ok( status == STATUS_INVALID_IMAGE_FORMAT || broken(status == STATUS_SUCCESS), /* win2k */ "NtCreateSection error %08x\n", status ); if (nt_header.OptionalHeader.Magic == IMAGE_NT_OPTIONAL_HDR32_MAGIC) @@ -656,7 +656,7 @@ todo_wine nt64.OptionalHeader.SizeOfImage = nt64.OptionalHeader.SizeOfHeaders + 0x1000; nt64.OptionalHeader.Subsystem = IMAGE_SUBSYSTEM_WINDOWS_CUI; status = map_image_section( (IMAGE_NT_HEADERS *)&nt64 ); - todo_wine ok( status == STATUS_INVALID_IMAGE_FORMAT, "NtCreateSection error %08x\n", status ); + ok( status == STATUS_INVALID_IMAGE_FORMAT, "NtCreateSection error %08x\n", status ); } else { @@ -677,7 +677,7 @@ todo_wine nt32.OptionalHeader.SizeOfImage = nt32.OptionalHeader.SizeOfHeaders + 0x1000; nt32.OptionalHeader.Subsystem = IMAGE_SUBSYSTEM_WINDOWS_CUI; status = map_image_section( (IMAGE_NT_HEADERS *)&nt32 ); - todo_wine ok( status == STATUS_INVALID_IMAGE_FORMAT, "NtCreateSection error %08x\n", status ); + ok( status == STATUS_INVALID_IMAGE_FORMAT, "NtCreateSection error %08x\n", status ); } nt_header.FileHeader.Machine = orig_machine; /* restore it for the next tests */ diff --git a/dlls/ntdll/loader.c b/dlls/ntdll/loader.c index a4552bb7663..5eb87551033 100644 --- a/dlls/ntdll/loader.c +++ b/dlls/ntdll/loader.c @@ -2000,7 +2000,7 @@ static NTSTATUS load_dll( LPCWSTR load_path, LPCWSTR libname, DWORD flags, WINE_ else { nts = load_native_dll( load_path, filename, handle, flags, pwm ); - if (nts == STATUS_INVALID_FILE_FOR_SECTION) + if (nts == STATUS_INVALID_IMAGE_NOT_MZ) /* not in PE format, maybe it's a builtin */ nts = load_builtin_dll( load_path, filename, handle, flags, pwm ); } diff --git a/dlls/ntdll/virtual.c b/dlls/ntdll/virtual.c index 3b9cad8e57e..e93ce2ec98f 100644 --- a/dlls/ntdll/virtual.c +++ b/dlls/ntdll/virtual.c @@ -1031,67 +1031,6 @@ static NTSTATUS allocate_dos_memory( struct file_view **view, unsigned int vprot } -/*********************************************************************** - * check_architecture - * - * Check the architecture of a PE binary. - */ -static NTSTATUS check_architecture( const IMAGE_NT_HEADERS *nt ) -{ - static const char *arch; - -#ifdef __i386__ - if (nt->FileHeader.Machine == IMAGE_FILE_MACHINE_I386) return STATUS_SUCCESS; - if (nt->FileHeader.Machine == IMAGE_FILE_MACHINE_AMD64) - { - if (nt->FileHeader.Characteristics & IMAGE_FILE_DLL) /* don't warn for a 64-bit exe */ - WARN( "loading amd64 dll in 32-bit mode will fail\n" ); - return STATUS_INVALID_IMAGE_FORMAT; - } -#elif defined(__x86_64__) - if (nt->FileHeader.Machine == IMAGE_FILE_MACHINE_AMD64) return STATUS_SUCCESS; - if (nt->FileHeader.Machine == IMAGE_FILE_MACHINE_I386) - { - if (nt->FileHeader.Characteristics & IMAGE_FILE_DLL) /* don't warn for a 32-bit exe */ - WARN( "loading 32-bit dll in 64-bit mode will fail\n" ); - return STATUS_INVALID_IMAGE_FORMAT; - } -#elif defined(__arm__) && !defined(__ARMEB__) - if (nt->FileHeader.Machine == IMAGE_FILE_MACHINE_ARM || - nt->FileHeader.Machine == IMAGE_FILE_MACHINE_THUMB) - return STATUS_SUCCESS; - if (nt->FileHeader.Machine == IMAGE_FILE_MACHINE_ARMNT) - { - SYSTEM_CPU_INFORMATION sci; - if (SUCCEEDED(NtQuerySystemInformation( SystemCpuInformation, &sci, sizeof(sci), NULL )) && - sci.Architecture == PROCESSOR_ARCHITECTURE_ARM && sci.Level >= 7) - return STATUS_SUCCESS; - } -#endif - - switch (nt->FileHeader.Machine) - { - case IMAGE_FILE_MACHINE_UNKNOWN: arch = "Unknown"; break; - case IMAGE_FILE_MACHINE_I860: arch = "I860"; break; - case IMAGE_FILE_MACHINE_I386: arch = "I386"; break; - case IMAGE_FILE_MACHINE_R3000: arch = "R3000"; break; - case IMAGE_FILE_MACHINE_R4000: arch = "R4000"; break; - case IMAGE_FILE_MACHINE_R10000: arch = "R10000"; break; - case IMAGE_FILE_MACHINE_ALPHA: arch = "Alpha"; break; - case IMAGE_FILE_MACHINE_POWERPC: arch = "PowerPC"; break; - case IMAGE_FILE_MACHINE_IA64: arch = "IA-64"; break; - case IMAGE_FILE_MACHINE_ALPHA64: arch = "Alpha-64"; break; - case IMAGE_FILE_MACHINE_AMD64: arch = "AMD-64"; break; - case IMAGE_FILE_MACHINE_ARM: arch = "ARM"; break; - case IMAGE_FILE_MACHINE_ARMNT: arch = "ARMNT"; break; - case IMAGE_FILE_MACHINE_THUMB: arch = "ARM Thumb"; break; - default: arch = wine_dbg_sprintf( "Unknown-%04x", nt->FileHeader.Machine ); break; - } - ERR( "Trying to load PE image for unsupported architecture %s\n", arch ); - return STATUS_INVALID_IMAGE_FORMAT; -} - - /*********************************************************************** * stat_mapping_file * @@ -1179,8 +1118,6 @@ static NTSTATUS map_image( HANDLE hmapping, int fd, char *base, SIZE_T total_siz imports = nt->OptionalHeader.DataDirectory + IMAGE_DIRECTORY_ENTRY_IMPORT; if (!imports->Size || !imports->VirtualAddress) imports = NULL; - if (check_architecture( nt )) goto error; - /* check for non page-aligned binary */ if (nt->OptionalHeader.SectionAlignment <= page_mask) diff --git a/server/mapping.c b/server/mapping.c index be0d8857496..64b3003b7c9 100644 --- a/server/mapping.c +++ b/server/mapping.c @@ -39,6 +39,7 @@ #include "file.h" #include "handle.h" #include "thread.h" +#include "process.h" #include "request.h" #include "security.h" @@ -60,6 +61,7 @@ struct mapping mem_size_t size; /* mapping size */ int protect; /* protection flags */ struct fd *fd; /* fd for mapped file */ + enum cpu_type cpu; /* client CPU (for PE image mapping) */ int header_size; /* size of headers (for PE image mapping) */ client_ptr_t base; /* default base addr (for PE image mapping) */ struct ranges *committed; /* list of committed ranges in this mapping */ @@ -366,7 +368,7 @@ static int build_shared_mapping( struct mapping *mapping, int fd, } /* retrieve the mapping parameters for an executable (PE) image */ -static int get_image_params( struct mapping *mapping, int unix_fd, int protect ) +static unsigned int get_image_params( struct mapping *mapping, int unix_fd, int protect ) { IMAGE_DOS_HEADER dos; IMAGE_SECTION_HEADER *sec = NULL; @@ -385,15 +387,48 @@ static int get_image_params( struct mapping *mapping, int unix_fd, int protect ) /* load the headers */ - if (pread( unix_fd, &dos, sizeof(dos), 0 ) != sizeof(dos)) goto error; - if (dos.e_magic != IMAGE_DOS_SIGNATURE) goto error; + if (pread( unix_fd, &dos, sizeof(dos), 0 ) != sizeof(dos)) return STATUS_INVALID_IMAGE_NOT_MZ; + if (dos.e_magic != IMAGE_DOS_SIGNATURE) return STATUS_INVALID_IMAGE_NOT_MZ; pos = dos.e_lfanew; size = pread( unix_fd, &nt, sizeof(nt), pos ); - if (size < sizeof(nt.Signature) + sizeof(nt.FileHeader)) goto error; + if (size < sizeof(nt.Signature) + sizeof(nt.FileHeader)) return STATUS_INVALID_IMAGE_FORMAT; /* zero out Optional header in the case it's not present or partial */ if (size < sizeof(nt)) memset( (char *)&nt + size, 0, sizeof(nt) - size ); - if (nt.Signature != IMAGE_NT_SIGNATURE) goto error; + if (nt.Signature != IMAGE_NT_SIGNATURE) + { + if (*(WORD *)&nt.Signature == IMAGE_OS2_SIGNATURE) return STATUS_INVALID_IMAGE_NE_FORMAT; + return STATUS_INVALID_IMAGE_PROTECT; + } + + mapping->cpu = current->process->cpu; + switch (mapping->cpu) + { + case CPU_x86: + if (nt.FileHeader.Machine != IMAGE_FILE_MACHINE_I386) return STATUS_INVALID_IMAGE_FORMAT; + if (nt.opt.hdr32.Magic != IMAGE_NT_OPTIONAL_HDR32_MAGIC) return STATUS_INVALID_IMAGE_FORMAT; + break; + case CPU_x86_64: + if (nt.FileHeader.Machine != IMAGE_FILE_MACHINE_AMD64) return STATUS_INVALID_IMAGE_FORMAT; + if (nt.opt.hdr64.Magic != IMAGE_NT_OPTIONAL_HDR64_MAGIC) return STATUS_INVALID_IMAGE_FORMAT; + break; + case CPU_POWERPC: + if (nt.FileHeader.Machine != IMAGE_FILE_MACHINE_POWERPC) return STATUS_INVALID_IMAGE_FORMAT; + if (nt.opt.hdr32.Magic != IMAGE_NT_OPTIONAL_HDR32_MAGIC) return STATUS_INVALID_IMAGE_FORMAT; + break; + case CPU_ARM: + if (nt.FileHeader.Machine != IMAGE_FILE_MACHINE_ARM && + nt.FileHeader.Machine != IMAGE_FILE_MACHINE_THUMB && + nt.FileHeader.Machine != IMAGE_FILE_MACHINE_ARMNT) return STATUS_INVALID_IMAGE_FORMAT; + if (nt.opt.hdr32.Magic != IMAGE_NT_OPTIONAL_HDR32_MAGIC) return STATUS_INVALID_IMAGE_FORMAT; + break; + case CPU_ARM64: + if (nt.FileHeader.Machine != IMAGE_FILE_MACHINE_ARM64) return STATUS_INVALID_IMAGE_FORMAT; + if (nt.opt.hdr64.Magic != IMAGE_NT_OPTIONAL_HDR64_MAGIC) return STATUS_INVALID_IMAGE_FORMAT; + break; + default: + return STATUS_INVALID_IMAGE_FORMAT; + } switch (nt.opt.hdr32.Magic) { @@ -407,8 +442,6 @@ static int get_image_params( struct mapping *mapping, int unix_fd, int protect ) mapping->base = nt.opt.hdr64.ImageBase; mapping->header_size = nt.opt.hdr64.SizeOfHeaders; break; - default: - goto error; } /* load the section headers */ @@ -426,12 +459,11 @@ static int get_image_params( struct mapping *mapping, int unix_fd, int protect ) mapping->protect = protect; free( sec ); - return 1; + return 0; error: free( sec ); - set_error( STATUS_INVALID_FILE_FOR_SECTION ); - return 0; + return STATUS_INVALID_FILE_FOR_SECTION; } static struct object *create_mapping( struct directory *root, const struct unicode_str *name, @@ -494,8 +526,10 @@ static struct object *create_mapping( struct directory *root, const struct unico if ((unix_fd = get_unix_fd( mapping->fd )) == -1) goto error; if (protect & VPROT_IMAGE) { - if (!get_image_params( mapping, unix_fd, protect )) goto error; - return &mapping->obj; + unsigned int err = get_image_params( mapping, unix_fd, protect ); + if (!err) return &mapping->obj; + set_error( err ); + goto error; } if (fstat( unix_fd, &st ) == -1) { @@ -680,29 +714,34 @@ DECL_HANDLER(get_mapping_info) struct mapping *mapping; struct fd *fd; - if ((mapping = get_mapping_obj( current->process, req->handle, req->access ))) + if (!(mapping = get_mapping_obj( current->process, req->handle, req->access ))) return; + + if ((mapping->protect & VPROT_IMAGE) && mapping->cpu != current->process->cpu) { - reply->size = mapping->size; - reply->protect = mapping->protect; - reply->header_size = mapping->header_size; - reply->base = mapping->base; - reply->shared_file = 0; - if ((fd = get_obj_fd( &mapping->obj ))) - { - if (!is_fd_removable(fd)) - reply->mapping = alloc_handle( current->process, mapping, 0, 0 ); - release_object( fd ); - } - if (mapping->shared_file) - { - if (!(reply->shared_file = alloc_handle( current->process, mapping->shared_file, - GENERIC_READ|GENERIC_WRITE, 0 ))) - { - if (reply->mapping) close_handle( current->process, reply->mapping ); - } - } + set_error( STATUS_INVALID_IMAGE_FORMAT ); release_object( mapping ); + return; } + + reply->size = mapping->size; + reply->protect = mapping->protect; + reply->header_size = mapping->header_size; + reply->base = mapping->base; + reply->shared_file = 0; + if ((fd = get_obj_fd( &mapping->obj ))) + { + if (!is_fd_removable(fd)) reply->mapping = alloc_handle( current->process, mapping, 0, 0 ); + release_object( fd ); + } + if (mapping->shared_file) + { + if (!(reply->shared_file = alloc_handle( current->process, mapping->shared_file, + GENERIC_READ|GENERIC_WRITE, 0 ))) + { + if (reply->mapping) close_handle( current->process, reply->mapping ); + } + } + release_object( mapping ); } /* get a range of committed pages in a file mapping */