Commit ebc1b099 authored by Alexandre Julliard's avatar Alexandre Julliard

ntdll: Support the machine extended parameter in NtMapViewOfSectionEx().

parent af01944a
......@@ -1655,7 +1655,6 @@ static void test_NtMapViewOfSectionEx(void)
ptr = NULL;
size = 0;
status = pNtMapViewOfSectionEx( mapping, process, &ptr, &offset, &size, 0, PAGE_READONLY, ext, 1 );
todo_wine
ok(status == STATUS_NOT_SUPPORTED, "NtMapViewOfSection returned %08lx\n", status);
}
else win_skip( "MemExtendedParameterImageMachine not supported\n" );
......
......@@ -30,6 +30,7 @@ static USHORT (WINAPI *pRtlWow64GetCurrentMachine)(void);
static NTSTATUS (WINAPI *pRtlWow64GetProcessMachines)(HANDLE,WORD*,WORD*);
static NTSTATUS (WINAPI *pRtlWow64GetThreadContext)(HANDLE,WOW64_CONTEXT*);
static NTSTATUS (WINAPI *pRtlWow64IsWowGuestMachineSupported)(USHORT,BOOLEAN*);
static NTSTATUS (WINAPI *pNtMapViewOfSectionEx)(HANDLE,HANDLE,PVOID*,const LARGE_INTEGER*,SIZE_T*,ULONG,ULONG,MEM_EXTENDED_PARAMETER*,ULONG);
#ifdef _WIN64
static NTSTATUS (WINAPI *pRtlWow64GetCpuAreaInfo)(WOW64_CPURESERVED*,ULONG,WOW64_CPU_AREA_INFO*);
static NTSTATUS (WINAPI *pRtlWow64GetThreadSelectorEntry)(HANDLE,THREAD_DESCRIPTOR_INFORMATION*,ULONG,ULONG*);
......@@ -80,6 +81,7 @@ static void init(void)
}
#define GET_PROC(func) p##func = (void *)GetProcAddress( ntdll, #func )
GET_PROC( NtMapViewOfSectionEx );
GET_PROC( NtQuerySystemInformation );
GET_PROC( NtQuerySystemInformationEx );
GET_PROC( RtlGetNativeSystemInformation );
......@@ -99,7 +101,7 @@ static void init(void)
#endif
#undef GET_PROC
if (is_wow64)
if (pRtlGetNativeSystemInformation)
{
SYSTEM_CPU_INFORMATION info;
ULONG len;
......@@ -595,6 +597,153 @@ static void test_selectors(void)
#undef GET_ENTRY
}
static void test_image_mappings(void)
{
MEM_EXTENDED_PARAMETER ext = { .Type = MemExtendedParameterImageMachine };
HANDLE file, mapping, process = GetCurrentProcess();
NTSTATUS status;
SIZE_T size;
LARGE_INTEGER offset;
void *ptr;
if (!pNtMapViewOfSectionEx)
{
win_skip( "NtMapViewOfSectionEx() not supported\n" );
return;
}
offset.QuadPart = 0;
file = CreateFileA( "c:\\windows\\system32\\version.dll", GENERIC_READ, 0, NULL, OPEN_EXISTING, 0, 0 );
ok( file != INVALID_HANDLE_VALUE, "Failed to open version.dll\n" );
mapping = CreateFileMappingA( file, NULL, PAGE_READONLY | SEC_IMAGE, 0, 0, NULL );
ok( mapping != 0, "CreateFileMapping failed\n" );
CloseHandle( file );
ptr = NULL;
size = 0;
ext.ULong = IMAGE_FILE_MACHINE_AMD64;
status = pNtMapViewOfSectionEx( mapping, process, &ptr, &offset, &size, 0, PAGE_READONLY, &ext, 1 );
if (status == STATUS_INVALID_PARAMETER)
{
win_skip( "MemExtendedParameterImageMachine not supported\n" );
NtClose( mapping );
return;
}
if (current_machine == IMAGE_FILE_MACHINE_AMD64)
{
ok( status == STATUS_SUCCESS || status == STATUS_IMAGE_NOT_AT_BASE,
"NtMapViewOfSection returned %08lx\n", status );
NtUnmapViewOfSection( process, ptr );
}
else if (current_machine == IMAGE_FILE_MACHINE_ARM64)
{
ok( status == STATUS_IMAGE_MACHINE_TYPE_MISMATCH, "NtMapViewOfSection returned %08lx\n", status );
NtUnmapViewOfSection( process, ptr );
}
else ok( status == STATUS_NOT_SUPPORTED, "NtMapViewOfSection returned %08lx\n", status );
ptr = NULL;
size = 0;
ext.ULong = IMAGE_FILE_MACHINE_I386;
status = pNtMapViewOfSectionEx( mapping, process, &ptr, &offset, &size, 0, PAGE_READONLY, &ext, 1 );
if (current_machine == IMAGE_FILE_MACHINE_I386)
{
ok( status == STATUS_SUCCESS || status == STATUS_IMAGE_NOT_AT_BASE,
"NtMapViewOfSection returned %08lx\n", status );
NtUnmapViewOfSection( process, ptr );
}
else ok( status == STATUS_NOT_SUPPORTED, "NtMapViewOfSection returned %08lx\n", status );
ptr = NULL;
size = 0;
ext.ULong = IMAGE_FILE_MACHINE_ARM64;
status = pNtMapViewOfSectionEx( mapping, process, &ptr, &offset, &size, 0, PAGE_READONLY, &ext, 1 );
if (native_machine == IMAGE_FILE_MACHINE_ARM64)
{
switch (current_machine)
{
case IMAGE_FILE_MACHINE_ARM64:
ok( status == STATUS_SUCCESS || status == STATUS_IMAGE_NOT_AT_BASE,
"NtMapViewOfSection returned %08lx\n", status );
NtUnmapViewOfSection( process, ptr );
break;
case IMAGE_FILE_MACHINE_AMD64:
ok( status == STATUS_IMAGE_MACHINE_TYPE_MISMATCH, "NtMapViewOfSection returned %08lx\n", status );
NtUnmapViewOfSection( process, ptr );
break;
default:
ok( status == STATUS_NOT_SUPPORTED, "NtMapViewOfSection returned %08lx\n", status );
break;
}
}
else ok( status == STATUS_NOT_SUPPORTED, "NtMapViewOfSection returned %08lx\n", status );
ptr = NULL;
size = 0;
ext.ULong = IMAGE_FILE_MACHINE_R3000;
status = pNtMapViewOfSectionEx( mapping, process, &ptr, &offset, &size, 0, PAGE_READONLY, &ext, 1 );
ok( status == STATUS_NOT_SUPPORTED, "NtMapViewOfSection returned %08lx\n", status );
ptr = NULL;
size = 0;
ext.ULong = 0;
status = pNtMapViewOfSectionEx( mapping, process, &ptr, &offset, &size, 0, PAGE_READONLY, &ext, 1 );
ok( status == STATUS_SUCCESS || status == STATUS_IMAGE_NOT_AT_BASE,
"NtMapViewOfSection returned %08lx\n", status );
NtUnmapViewOfSection( process, ptr );
NtClose( mapping );
if (is_wow64)
{
file = CreateFileA( "c:\\windows\\sysnative\\version.dll", GENERIC_READ, 0, NULL, OPEN_EXISTING, 0, 0 );
ok( file != INVALID_HANDLE_VALUE, "Failed to open version.dll\n" );
mapping = CreateFileMappingA( file, NULL, PAGE_READONLY | SEC_IMAGE, 0, 0, NULL );
ok( mapping != 0, "CreateFileMapping failed\n" );
CloseHandle( file );
ptr = NULL;
size = 0;
ext.ULong = native_machine;
status = pNtMapViewOfSectionEx( mapping, process, &ptr, &offset, &size, 0, PAGE_READONLY, &ext, 1 );
ok( status == STATUS_SUCCESS || status == STATUS_IMAGE_NOT_AT_BASE,
"NtMapViewOfSection returned %08lx\n", status );
NtUnmapViewOfSection( process, ptr );
ptr = NULL;
size = 0;
ext.ULong = IMAGE_FILE_MACHINE_I386;
status = pNtMapViewOfSectionEx( mapping, process, &ptr, &offset, &size, 0, PAGE_READONLY, &ext, 1 );
ok( status == STATUS_NOT_SUPPORTED, "NtMapViewOfSection returned %08lx\n", status );
NtClose( mapping );
}
else if (native_machine == IMAGE_FILE_MACHINE_AMD64 || native_machine == IMAGE_FILE_MACHINE_ARM64)
{
file = CreateFileA( "c:\\windows\\syswow64\\version.dll", GENERIC_READ, 0, NULL, OPEN_EXISTING, 0, 0 );
ok( file != INVALID_HANDLE_VALUE, "Failed to open version.dll\n" );
mapping = CreateFileMappingA( file, NULL, PAGE_READONLY | SEC_IMAGE, 0, 0, NULL );
ok( mapping != 0, "CreateFileMapping failed\n" );
CloseHandle( file );
ptr = NULL;
size = 0;
ext.ULong = native_machine;
status = pNtMapViewOfSectionEx( mapping, process, &ptr, &offset, &size, 0, PAGE_READONLY, &ext, 1 );
ok( status == STATUS_NOT_SUPPORTED, "NtMapViewOfSection returned %08lx\n", status );
ptr = NULL;
size = 0;
ext.ULong = IMAGE_FILE_MACHINE_I386;
status = pNtMapViewOfSectionEx( mapping, process, &ptr, &offset, &size, 0, PAGE_READONLY, &ext, 1 );
todo_wine
ok( status == STATUS_IMAGE_MACHINE_TYPE_MISMATCH, "NtMapViewOfSection returned %08lx\n", status );
NtUnmapViewOfSection( process, ptr );
NtClose( mapping );
}
}
#ifdef _WIN64
static void test_cpu_area(void)
......@@ -1396,6 +1545,7 @@ START_TEST(wow64)
test_query_architectures();
test_peb_teb();
test_selectors();
test_image_mappings();
#ifndef _WIN64
test_nt_wow64();
test_modules();
......
......@@ -1451,13 +1451,13 @@ static NTSTATUS open_builtin_so_file( const char *name, OBJECT_ATTRIBUTES *attr,
* find_builtin_dll
*/
static NTSTATUS find_builtin_dll( UNICODE_STRING *nt_name, void **module, SIZE_T *size_ptr,
SECTION_IMAGE_INFORMATION *image_info,
ULONG_PTR limit, WORD machine, BOOL prefer_native )
SECTION_IMAGE_INFORMATION *image_info, ULONG_PTR limit,
USHORT search_machine, USHORT load_machine, BOOL prefer_native )
{
unsigned int i, pos, namepos, maxlen = 0;
unsigned int len = nt_name->Length / sizeof(WCHAR);
char *ptr = NULL, *file, *ext = NULL;
const char *pe_dir = get_pe_dir( machine );
const char *pe_dir = get_pe_dir( search_machine );
OBJECT_ATTRIBUTES attr;
NTSTATUS status = STATUS_DLL_NOT_FOUND;
BOOL found_image = FALSE;
......@@ -1489,21 +1489,23 @@ static NTSTATUS find_builtin_dll( UNICODE_STRING *nt_name, void **module, SIZE_T
/* try as a dll */
file[pos + len + 1] = 0;
ptr = prepend_build_dir_path( file + pos, ".dll", pe_dir, "/dlls" );
status = open_builtin_pe_file( ptr, &attr, module, size_ptr, image_info, limit, machine, prefer_native );
status = open_builtin_pe_file( ptr, &attr, module, size_ptr, image_info,
limit, load_machine, prefer_native );
ptr = prepend_build_dir_path( file + pos, ".dll", "", "/dlls" );
if (status != STATUS_DLL_NOT_FOUND) goto done;
strcpy( file + pos + len + 1, ".so" );
status = open_builtin_so_file( ptr, &attr, module, image_info, machine, prefer_native );
status = open_builtin_so_file( ptr, &attr, module, image_info, load_machine, prefer_native );
if (status != STATUS_DLL_NOT_FOUND) goto done;
/* now as a program */
file[pos + len + 1] = 0;
ptr = prepend_build_dir_path( file + pos, ".exe", pe_dir, "/programs" );
status = open_builtin_pe_file( ptr, &attr, module, size_ptr, image_info, limit, machine, prefer_native );
status = open_builtin_pe_file( ptr, &attr, module, size_ptr, image_info,
limit, load_machine, prefer_native );
ptr = prepend_build_dir_path( file + pos, ".exe", "", "/programs" );
if (status != STATUS_DLL_NOT_FOUND) goto done;
strcpy( file + pos + len + 1, ".so" );
status = open_builtin_so_file( ptr, &attr, module, image_info, machine, prefer_native );
status = open_builtin_so_file( ptr, &attr, module, image_info, load_machine, prefer_native );
if (status != STATUS_DLL_NOT_FOUND) goto done;
}
......@@ -1513,18 +1515,20 @@ static NTSTATUS find_builtin_dll( UNICODE_STRING *nt_name, void **module, SIZE_T
file[pos + len + 1] = 0;
ptr = prepend( ptr, pe_dir, strlen(pe_dir) );
ptr = prepend( ptr, dll_paths[i], strlen(dll_paths[i]) );
status = open_builtin_pe_file( ptr, &attr, module, size_ptr, image_info, limit, machine, prefer_native );
status = open_builtin_pe_file( ptr, &attr, module, size_ptr, image_info, limit,
load_machine, prefer_native );
/* use so dir for unix lib */
ptr = file + pos;
ptr = prepend( ptr, so_dir, strlen(so_dir) );
ptr = prepend( ptr, dll_paths[i], strlen(dll_paths[i]) );
if (status != STATUS_DLL_NOT_FOUND) goto done;
strcpy( file + pos + len + 1, ".so" );
status = open_builtin_so_file( ptr, &attr, module, image_info, machine, prefer_native );
status = open_builtin_so_file( ptr, &attr, module, image_info, load_machine, prefer_native );
if (status != STATUS_DLL_NOT_FOUND) goto done;
file[pos + len + 1] = 0;
ptr = prepend( file + pos, dll_paths[i], strlen(dll_paths[i]) );
status = open_builtin_pe_file( ptr, &attr, module, size_ptr, image_info, limit, machine, prefer_native );
status = open_builtin_pe_file( ptr, &attr, module, size_ptr, image_info, limit,
load_machine, prefer_native );
if (status == STATUS_NOT_SUPPORTED)
{
found_image = TRUE;
......@@ -1532,7 +1536,7 @@ static NTSTATUS find_builtin_dll( UNICODE_STRING *nt_name, void **module, SIZE_T
}
if (status != STATUS_DLL_NOT_FOUND) goto done;
strcpy( file + pos + len + 1, ".so" );
status = open_builtin_so_file( ptr, &attr, module, image_info, machine, prefer_native );
status = open_builtin_so_file( ptr, &attr, module, image_info, load_machine, prefer_native );
if (status == STATUS_NOT_SUPPORTED) found_image = TRUE;
else if (status != STATUS_DLL_NOT_FOUND) goto done;
}
......@@ -1556,10 +1560,9 @@ done:
* Load the builtin dll if specified by load order configuration.
* Return STATUS_IMAGE_ALREADY_LOADED if we should keep the native one that we have found.
*/
NTSTATUS load_builtin( const pe_image_info_t *image_info, WCHAR *filename,
NTSTATUS load_builtin( const pe_image_info_t *image_info, WCHAR *filename, USHORT machine,
void **module, SIZE_T *size, ULONG_PTR limit )
{
WORD machine = image_info->machine; /* request same machine as the native one */
NTSTATUS status;
UNICODE_STRING nt_name;
SECTION_IMAGE_INFORMATION info;
......@@ -1588,9 +1591,11 @@ NTSTATUS load_builtin( const pe_image_info_t *image_info, WCHAR *filename,
case LO_NATIVE_BUILTIN:
return STATUS_IMAGE_ALREADY_LOADED;
case LO_BUILTIN:
return find_builtin_dll( &nt_name, module, size, &info, limit, machine, FALSE );
return find_builtin_dll( &nt_name, module, size, &info, limit,
image_info->machine, machine, FALSE );
default:
status = find_builtin_dll( &nt_name, module, size, &info, limit, machine, (loadorder == LO_DEFAULT) );
status = find_builtin_dll( &nt_name, module, size, &info, limit,
image_info->machine, machine, (loadorder == LO_DEFAULT) );
if (status == STATUS_DLL_NOT_FOUND || status == STATUS_NOT_SUPPORTED)
return STATUS_IMAGE_ALREADY_LOADED;
return status;
......@@ -1753,7 +1758,7 @@ NTSTATUS load_main_exe( const WCHAR *dos_name, const char *unix_name, const WCHA
/* if path is in system dir, we can load the builtin even if the file itself doesn't exist */
if (loadorder != LO_NATIVE && is_builtin_path( &nt_name, &machine ))
{
status = find_builtin_dll( &nt_name, module, &size, &main_image_info, 0, machine, FALSE );
status = find_builtin_dll( &nt_name, module, &size, &main_image_info, 0, machine, 0, FALSE );
if (status != STATUS_DLL_NOT_FOUND) return status;
}
if (!contains_path) return STATUS_DLL_NOT_FOUND;
......@@ -1782,7 +1787,7 @@ NTSTATUS load_start_exe( WCHAR **image, void **module )
wcscpy( *image, get_machine_wow64_dir( current_machine ));
wcscat( *image, startW );
init_unicode_string( &nt_name, *image );
status = find_builtin_dll( &nt_name, module, &size, &main_image_info, 0, current_machine, FALSE );
status = find_builtin_dll( &nt_name, module, &size, &main_image_info, 0, current_machine, 0, FALSE );
if (status)
{
MESSAGE( "wine: failed to load start.exe: %x\n", status );
......@@ -1993,7 +1998,7 @@ static void load_wow64_ntdll( USHORT machine )
wcscpy( path, get_machine_wow64_dir( machine ));
wcscat( path, ntdllW );
init_unicode_string( &nt_name, path );
status = find_builtin_dll( &nt_name, &module, &size, &info, 0, machine, FALSE );
status = find_builtin_dll( &nt_name, &module, &size, &info, 0, machine, 0, FALSE );
switch (status)
{
case STATUS_IMAGE_NOT_AT_BASE:
......
......@@ -569,7 +569,7 @@ static void invoke_system_apc( const apc_call_t *call, apc_result_t *result, BOO
case APC_MAP_VIEW_EX:
{
MEM_ADDRESS_REQUIREMENTS addr_req;
MEM_EXTENDED_PARAMETER ext[1];
MEM_EXTENDED_PARAMETER ext[2];
ULONG count = 0;
LARGE_INTEGER offset;
......@@ -596,6 +596,12 @@ static void invoke_system_apc( const apc_call_t *call, apc_result_t *result, BOO
ext[count].Pointer = &addr_req;
count++;
}
if (call->map_view_ex.machine)
{
ext[count].Type = MemExtendedParameterImageMachine;
ext[count].ULong = call->map_view_ex.machine;
count++;
}
result->map_view_ex.status = NtMapViewOfSectionEx( wine_server_ptr_handle(call->map_view_ex.handle),
NtCurrentProcess(), &addr, &offset, &size,
call->map_view_ex.alloc_type,
......
......@@ -174,7 +174,7 @@ extern void *create_startup_info( const UNICODE_STRING *nt_image, const RTL_USER
extern char **build_envp( const WCHAR *envW ) DECLSPEC_HIDDEN;
extern char *get_alternate_wineloader( WORD machine ) DECLSPEC_HIDDEN;
extern NTSTATUS exec_wineloader( char **argv, int socketfd, const pe_image_info_t *pe_info ) DECLSPEC_HIDDEN;
extern NTSTATUS load_builtin( const pe_image_info_t *image_info, WCHAR *filename,
extern NTSTATUS load_builtin( const pe_image_info_t *image_info, WCHAR *filename, USHORT machine,
void **addr_ptr, SIZE_T *size_ptr, ULONG_PTR limit ) DECLSPEC_HIDDEN;
extern BOOL is_builtin_path( const UNICODE_STRING *path, WORD *machine ) DECLSPEC_HIDDEN;
extern NTSTATUS load_main_exe( const WCHAR *name, const char *unix_name, const WCHAR *curdir, WCHAR **image,
......
......@@ -592,7 +592,8 @@ typedef union
file_pos_t offset;
mem_size_t limit;
unsigned int alloc_type;
unsigned int prot;
unsigned short prot;
unsigned short machine;
} map_view_ex;
struct
{
......@@ -6393,7 +6394,7 @@ union generic_reply
/* ### protocol_version begin ### */
#define SERVER_PROTOCOL_VERSION 766
#define SERVER_PROTOCOL_VERSION 767
/* ### protocol_version end ### */
......
......@@ -608,7 +608,8 @@ typedef union
file_pos_t offset; /* file offset */
mem_size_t limit; /* allocation address limit */
unsigned int alloc_type; /* allocation type */
unsigned int prot; /* memory protection flags */
unsigned short prot; /* memory protection flags */
unsigned short machine; /* requested machine for image mappings */
} map_view_ex;
struct
{
......
......@@ -237,7 +237,8 @@ static void dump_apc_call( const char *prefix, const apc_call_t *call )
dump_uint64( ",size=", &call->map_view_ex.size );
dump_uint64( ",offset=", &call->map_view_ex.offset );
dump_uint64( ",limit=", &call->map_view_ex.limit );
fprintf( stderr, ",alloc_type=%x,prot=%x", call->map_view_ex.alloc_type, call->map_view_ex.prot );
fprintf( stderr, ",alloc_type=%x,prot=%x,machine=%04x",
call->map_view_ex.alloc_type, call->map_view_ex.prot, call->map_view_ex.machine );
break;
case APC_UNMAP_VIEW:
dump_uint64( "APC_UNMAP_VIEW,addr=", &call->unmap_view.addr );
......
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