ntdll: Support the lower memory limit in MEM_ADDRESS_REQUIREMENTS.

This commit is contained in:
Alexandre Julliard 2023-06-13 11:17:03 +02:00
parent 2705e6c319
commit 11cd51139d
11 changed files with 199 additions and 99 deletions

View file

@ -906,6 +906,68 @@ static void test_NtAllocateVirtualMemoryEx_address_requirements(void)
status = pNtAllocateVirtualMemoryEx(NtCurrentProcess(), &addr, &size, MEM_RESERVE,
PAGE_EXECUTE_READWRITE, ext, 1);
ok(status == STATUS_INVALID_PARAMETER, "Unexpected status %08lx.\n", status);
a.LowestStartingAddress = (void *)0x20001000;
a.Alignment = 0;
size = 0x1000;
addr = NULL;
status = pNtAllocateVirtualMemoryEx(NtCurrentProcess(), &addr, &size, MEM_RESERVE,
PAGE_EXECUTE_READWRITE, ext, 1);
ok(status == STATUS_INVALID_PARAMETER, "Unexpected status %08lx.\n", status);
a.LowestStartingAddress = (void *)(0x20001000 - 1);
size = 0x1000;
addr = NULL;
status = pNtAllocateVirtualMemoryEx(NtCurrentProcess(), &addr, &size, MEM_RESERVE,
PAGE_EXECUTE_READWRITE, ext, 1);
ok(status == STATUS_INVALID_PARAMETER, "Unexpected status %08lx.\n", status);
a.LowestStartingAddress = (void *)(0x20001000 + 1);
size = 0x1000;
addr = NULL;
status = pNtAllocateVirtualMemoryEx(NtCurrentProcess(), &addr, &size, MEM_RESERVE,
PAGE_EXECUTE_READWRITE, ext, 1);
ok(status == STATUS_INVALID_PARAMETER, "Unexpected status %08lx.\n", status);
a.LowestStartingAddress = (void *)0x30000000;
a.HighestEndingAddress = (void *)0x20000000;
size = 0x1000;
addr = NULL;
status = pNtAllocateVirtualMemoryEx(NtCurrentProcess(), &addr, &size, MEM_RESERVE,
PAGE_EXECUTE_READWRITE, ext, 1);
ok(status == STATUS_INVALID_PARAMETER, "Unexpected status %08lx.\n", status);
a.LowestStartingAddress = (void *)0x20000000;
a.HighestEndingAddress = 0;
size = 0x1000;
addr = NULL;
status = pNtAllocateVirtualMemoryEx(NtCurrentProcess(), &addr, &size, MEM_RESERVE,
PAGE_EXECUTE_READWRITE, ext, 1);
ok(!status, "Unexpected status %08lx.\n", status);
ok(addr >= (void *)0x20000000, "Unexpected addr %p.\n", addr);
size = 0;
status = NtFreeVirtualMemory(NtCurrentProcess(), &addr, &size, MEM_RELEASE);
ok(!status, "Unexpected status %08lx.\n", status);
a.LowestStartingAddress = (void *)0x20000000;
a.HighestEndingAddress = (void *)0x2fffffff;
size = 0x1000;
addr = NULL;
status = pNtAllocateVirtualMemoryEx(NtCurrentProcess(), &addr, &size, MEM_RESERVE,
PAGE_EXECUTE_READWRITE, ext, 1);
ok(!status, "Unexpected status %08lx.\n", status);
ok(addr >= (void *)0x20000000 && addr < (void *)0x30000000, "Unexpected addr %p.\n", addr);
size = 0;
status = NtFreeVirtualMemory(NtCurrentProcess(), &addr, &size, MEM_RELEASE);
ok(!status, "Unexpected status %08lx.\n", status);
a.LowestStartingAddress = (char *)si.lpMaximumApplicationAddress + 1;
a.HighestEndingAddress = 0;
size = 0x10000;
addr = NULL;
status = pNtAllocateVirtualMemoryEx(NtCurrentProcess(), &addr, &size, MEM_RESERVE,
PAGE_EXECUTE_READWRITE, ext, 1);
ok(status == STATUS_INVALID_PARAMETER, "Unexpected status %08lx.\n", status);
}
struct test_stack_size_thread_args

View file

@ -1396,7 +1396,8 @@ static NTSTATUS open_dll_file( const char *name, OBJECT_ATTRIBUTES *attr, HANDLE
*/
static NTSTATUS open_builtin_pe_file( const char *name, OBJECT_ATTRIBUTES *attr, void **module,
SIZE_T *size, SECTION_IMAGE_INFORMATION *image_info,
ULONG_PTR limit, WORD machine, BOOL prefer_native )
ULONG_PTR limit_low, ULONG_PTR limit_high,
WORD machine, BOOL prefer_native )
{
NTSTATUS status;
HANDLE mapping;
@ -1405,7 +1406,8 @@ static NTSTATUS open_builtin_pe_file( const char *name, OBJECT_ATTRIBUTES *attr,
status = open_dll_file( name, attr, &mapping );
if (!status)
{
status = virtual_map_builtin_module( mapping, module, size, image_info, limit, machine, prefer_native );
status = virtual_map_builtin_module( mapping, module, size, image_info,
limit_low, limit_high, machine, prefer_native );
NtClose( mapping );
}
return status;
@ -1447,8 +1449,9 @@ 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,
USHORT search_machine, USHORT load_machine, BOOL prefer_native )
SECTION_IMAGE_INFORMATION *image_info, ULONG_PTR limit_low,
ULONG_PTR limit_high, USHORT search_machine,
USHORT load_machine, BOOL prefer_native )
{
unsigned int i, pos, namepos, maxlen = 0;
unsigned int len = nt_name->Length / sizeof(WCHAR);
@ -1487,7 +1490,7 @@ static NTSTATUS find_builtin_dll( UNICODE_STRING *nt_name, void **module, SIZE_T
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, load_machine, prefer_native );
limit_low, limit_high, load_machine, prefer_native );
ptr = prepend_build_dir_path( file + pos, ".dll", "", "/dlls" );
if (status != STATUS_DLL_NOT_FOUND) goto done;
if (try_so)
@ -1501,7 +1504,7 @@ static NTSTATUS find_builtin_dll( UNICODE_STRING *nt_name, void **module, SIZE_T
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, load_machine, prefer_native );
limit_low, limit_high, load_machine, prefer_native );
ptr = prepend_build_dir_path( file + pos, ".exe", "", "/programs" );
if (status != STATUS_DLL_NOT_FOUND) goto done;
if (try_so)
@ -1518,7 +1521,7 @@ 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,
status = open_builtin_pe_file( ptr, &attr, module, size_ptr, image_info, limit_low, limit_high,
load_machine, prefer_native );
/* use so dir for unix lib */
ptr = file + pos;
@ -1533,7 +1536,7 @@ static NTSTATUS find_builtin_dll( UNICODE_STRING *nt_name, void **module, SIZE_T
}
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,
status = open_builtin_pe_file( ptr, &attr, module, size_ptr, image_info, limit_low, limit_high,
load_machine, prefer_native );
if (status == STATUS_NOT_SUPPORTED)
{
@ -1568,7 +1571,7 @@ done:
* 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, USHORT machine,
void **module, SIZE_T *size, ULONG_PTR limit )
void **module, SIZE_T *size, ULONG_PTR limit_low, ULONG_PTR limit_high )
{
NTSTATUS status;
UNICODE_STRING nt_name;
@ -1598,10 +1601,10 @@ NTSTATUS load_builtin( const pe_image_info_t *image_info, WCHAR *filename, USHOR
case LO_NATIVE_BUILTIN:
return STATUS_IMAGE_ALREADY_LOADED;
case LO_BUILTIN:
return find_builtin_dll( &nt_name, module, size, &info, limit,
return find_builtin_dll( &nt_name, module, size, &info, limit_low, limit_high,
image_info->machine, machine, FALSE );
default:
status = find_builtin_dll( &nt_name, module, size, &info, limit,
status = find_builtin_dll( &nt_name, module, size, &info, limit_low, limit_high,
image_info->machine, machine, (loadorder == LO_DEFAULT) );
if (status == STATUS_DLL_NOT_FOUND || status == STATUS_NOT_SUPPORTED)
return STATUS_IMAGE_ALREADY_LOADED;
@ -1691,7 +1694,7 @@ static NTSTATUS open_main_image( WCHAR *image, void **module, SECTION_IMAGE_INFO
status = open_dll_file( unix_name, &attr, &mapping );
if (!status)
{
status = virtual_map_module( mapping, module, &size, info, 0, machine );
status = virtual_map_module( mapping, module, &size, info, 0, 0, machine );
if (status == STATUS_IMAGE_MACHINE_TYPE_MISMATCH && info->ComPlusNativeReady)
{
info->Machine = native_machine;
@ -1763,7 +1766,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, &search_machine ))
{
status = find_builtin_dll( &nt_name, module, &size, &main_image_info, 0,
status = find_builtin_dll( &nt_name, module, &size, &main_image_info, 0, 0,
search_machine, load_machine, FALSE );
if (status != STATUS_DLL_NOT_FOUND) return status;
}
@ -1793,7 +1796,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, 0, FALSE );
status = find_builtin_dll( &nt_name, module, &size, &main_image_info, 0, 0, current_machine, 0, FALSE );
if (status)
{
MESSAGE( "wine: failed to load start.exe: %x\n", status );
@ -1897,7 +1900,7 @@ static void load_ntdll(void)
name = malloc( strlen( ntdll_dir ) + strlen( pe_dir ) + sizeof("/ntdll.dll.so") );
if (build_dir) sprintf( name, "%s%s/ntdll.dll", ntdll_dir, pe_dir );
else sprintf( name, "%s%s/ntdll.dll", dll_dir, pe_dir );
status = open_builtin_pe_file( name, &attr, &module, &size, &info, 0, current_machine, FALSE );
status = open_builtin_pe_file( name, &attr, &module, &size, &info, 0, 0, current_machine, FALSE );
if (status == STATUS_DLL_NOT_FOUND)
{
sprintf( name, "%s/ntdll.dll.so", ntdll_dir );
@ -1997,7 +2000,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, 0, FALSE );
status = find_builtin_dll( &nt_name, &module, &size, &info, 0, 0, machine, 0, FALSE );
switch (status)
{
case STATUS_IMAGE_NOT_AT_BASE:

View file

@ -423,21 +423,22 @@ static void invoke_system_apc( const apc_call_t *call, apc_result_t *result, BOO
result->virtual_alloc_ex.status = STATUS_WORKING_SET_LIMIT_RANGE;
break;
}
if (call->virtual_alloc_ex.limit || call->virtual_alloc_ex.align)
if (call->virtual_alloc_ex.limit_low || call->virtual_alloc_ex.limit_high || call->virtual_alloc_ex.align)
{
SYSTEM_BASIC_INFORMATION sbi;
SIZE_T limit, align;
SIZE_T limit_low, limit_high, align;
virtual_get_system_info( &sbi, is_wow64() );
limit = min( (ULONG_PTR)sbi.HighestUserAddress, call->virtual_alloc_ex.limit );
limit_low = call->virtual_alloc_ex.limit_low;
limit_high = min( (ULONG_PTR)sbi.HighestUserAddress, call->virtual_alloc_ex.limit_high );
align = call->virtual_alloc_ex.align;
if (align != call->virtual_alloc_ex.align)
if (limit_low != call->virtual_alloc_ex.limit_low || align != call->virtual_alloc_ex.align)
{
result->virtual_alloc_ex.status = STATUS_WORKING_SET_LIMIT_RANGE;
break;
}
r.LowestStartingAddress = NULL;
r.HighestEndingAddress = (void *)limit;
r.LowestStartingAddress = (void *)limit_low;
r.HighestEndingAddress = (void *)limit_high;
r.Alignment = align;
ext[count].Type = MemExtendedParameterAddressRequirements;
ext[count].Pointer = &r;
@ -572,25 +573,27 @@ static void invoke_system_apc( const apc_call_t *call, apc_result_t *result, BOO
MEM_EXTENDED_PARAMETER ext[2];
ULONG count = 0;
LARGE_INTEGER offset;
ULONG_PTR limit_low, limit_high;
result->type = call->type;
addr = wine_server_get_ptr( call->map_view_ex.addr );
size = call->map_view_ex.size;
offset.QuadPart = call->map_view_ex.offset;
if ((ULONG_PTR)addr != call->map_view_ex.addr || size != call->map_view_ex.size)
limit_low = call->map_view_ex.limit_low;
if ((ULONG_PTR)addr != call->map_view_ex.addr || size != call->map_view_ex.size ||
limit_low != call->map_view_ex.limit_low)
{
result->map_view_ex.status = STATUS_WORKING_SET_LIMIT_RANGE;
break;
}
if (call->map_view_ex.limit)
if (call->map_view_ex.limit_low || call->map_view_ex.limit_high)
{
SYSTEM_BASIC_INFORMATION sbi;
ULONG_PTR limit;
virtual_get_system_info( &sbi, is_wow64() );
limit = min( (ULONG_PTR)sbi.HighestUserAddress, call->map_view_ex.limit );
addr_req.LowestStartingAddress = NULL;
addr_req.HighestEndingAddress = (void *)limit;
limit_high = min( (ULONG_PTR)sbi.HighestUserAddress, call->map_view_ex.limit_high );
addr_req.LowestStartingAddress = (void *)limit_low;
addr_req.HighestEndingAddress = (void *)limit_high;
addr_req.Alignment = 0;
ext[count].Type = MemExtendedParameterAddressRequirements;
ext[count].Pointer = &addr_req;

View file

@ -1180,7 +1180,7 @@ NTSTATUS init_thread_stack( TEB *teb, ULONG_PTR limit, SIZE_T reserve_size, SIZE
NTSTATUS status;
/* kernel stack */
if ((status = virtual_alloc_thread_stack( &stack, 0, kernel_stack_size, kernel_stack_size, FALSE )))
if ((status = virtual_alloc_thread_stack( &stack, 0, 0, kernel_stack_size, kernel_stack_size, FALSE )))
return status;
thread_data->kernel_stack = stack.DeallocationStack;
@ -1191,7 +1191,7 @@ NTSTATUS init_thread_stack( TEB *teb, ULONG_PTR limit, SIZE_T reserve_size, SIZE
((get_machine_context_size( main_image_info.Machine ) + 7) & ~7) + sizeof(ULONG64);
/* 64-bit stack */
if ((status = virtual_alloc_thread_stack( &stack, 0, 0x40000, 0x40000, TRUE ))) return status;
if ((status = virtual_alloc_thread_stack( &stack, 0, 0, 0x40000, 0x40000, TRUE ))) return status;
cpu = (WOW64_CPURESERVED *)(((ULONG_PTR)stack.StackBase - cpusize) & ~15);
cpu->Machine = main_image_info.Machine;
@ -1201,7 +1201,7 @@ NTSTATUS init_thread_stack( TEB *teb, ULONG_PTR limit, SIZE_T reserve_size, SIZE
teb->DeallocationStack = stack.DeallocationStack;
/* 32-bit stack */
if ((status = virtual_alloc_thread_stack( &stack, limit ? limit : 0x7fffffff,
if ((status = virtual_alloc_thread_stack( &stack, 0, limit ? limit : 0x7fffffff,
reserve_size, commit_size, TRUE )))
return status;
wow_teb->Tib.StackBase = PtrToUlong( stack.StackBase );
@ -1216,7 +1216,7 @@ NTSTATUS init_thread_stack( TEB *teb, ULONG_PTR limit, SIZE_T reserve_size, SIZE
}
/* native stack */
if ((status = virtual_alloc_thread_stack( &stack, limit, reserve_size, commit_size, TRUE )))
if ((status = virtual_alloc_thread_stack( &stack, 0, limit, reserve_size, commit_size, TRUE )))
return status;
teb->Tib.StackBase = stack.StackBase;
teb->Tib.StackLimit = stack.StackLimit;

View file

@ -174,7 +174,7 @@ 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, USHORT machine,
void **addr_ptr, SIZE_T *size_ptr, ULONG_PTR limit ) DECLSPEC_HIDDEN;
void **addr_ptr, SIZE_T *size_ptr, ULONG_PTR limit_low, ULONG_PTR limit_high ) 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,
USHORT load_machine, WCHAR **image, void **module ) DECLSPEC_HIDDEN;
@ -220,18 +220,20 @@ extern void *anon_mmap_alloc( size_t size, int prot ) DECLSPEC_HIDDEN;
extern void virtual_init(void) DECLSPEC_HIDDEN;
extern ULONG_PTR get_system_affinity_mask(void) DECLSPEC_HIDDEN;
extern void virtual_get_system_info( SYSTEM_BASIC_INFORMATION *info, BOOL wow64 ) DECLSPEC_HIDDEN;
extern NTSTATUS virtual_map_builtin_module( HANDLE mapping, void **module, SIZE_T *size, SECTION_IMAGE_INFORMATION *info,
ULONG_PTR limit, WORD machine, BOOL prefer_native ) DECLSPEC_HIDDEN;
extern NTSTATUS virtual_map_module( HANDLE mapping, void **module, SIZE_T *size, SECTION_IMAGE_INFORMATION *info,
ULONG_PTR limit, USHORT machine ) DECLSPEC_HIDDEN;
extern NTSTATUS virtual_map_builtin_module( HANDLE mapping, void **module, SIZE_T *size,
SECTION_IMAGE_INFORMATION *info, ULONG_PTR limit_low,
ULONG_PTR limit_high, WORD machine, BOOL prefer_native ) DECLSPEC_HIDDEN;
extern NTSTATUS virtual_map_module( HANDLE mapping, void **module, SIZE_T *size,
SECTION_IMAGE_INFORMATION *info, ULONG_PTR limit_low,
ULONG_PTR limit_high, USHORT machine ) DECLSPEC_HIDDEN;
extern NTSTATUS virtual_create_builtin_view( void *module, const UNICODE_STRING *nt_name,
pe_image_info_t *info, void *so_handle ) DECLSPEC_HIDDEN;
extern TEB *virtual_alloc_first_teb(void) DECLSPEC_HIDDEN;
extern NTSTATUS virtual_alloc_teb( TEB **ret_teb ) DECLSPEC_HIDDEN;
extern void virtual_free_teb( TEB *teb ) DECLSPEC_HIDDEN;
extern NTSTATUS virtual_clear_tls_index( ULONG index ) DECLSPEC_HIDDEN;
extern NTSTATUS virtual_alloc_thread_stack( INITIAL_TEB *stack, ULONG_PTR limit, SIZE_T reserve_size,
SIZE_T commit_size, BOOL guard_page ) DECLSPEC_HIDDEN;
extern NTSTATUS virtual_alloc_thread_stack( INITIAL_TEB *stack, ULONG_PTR limit_low, ULONG_PTR limit_high,
SIZE_T reserve_size, SIZE_T commit_size, BOOL guard_page ) DECLSPEC_HIDDEN;
extern void virtual_map_user_shared_data(void) DECLSPEC_HIDDEN;
extern NTSTATUS virtual_handle_fault( void *addr, DWORD err, void *stack ) DECLSPEC_HIDDEN;
extern unsigned int virtual_locked_server_call( void *req_ptr ) DECLSPEC_HIDDEN;

View file

@ -1942,7 +1942,8 @@ failed:
* virtual_mutex must be held by caller.
*/
static NTSTATUS map_view( struct file_view **view_ret, void *base, size_t size,
unsigned int alloc_type, unsigned int vprot, ULONG_PTR limit, size_t align_mask )
unsigned int alloc_type, unsigned int vprot,
ULONG_PTR limit_low, ULONG_PTR limit_high, size_t align_mask )
{
int top_down = alloc_type & MEM_TOP_DOWN;
void *ptr;
@ -1965,10 +1966,13 @@ static NTSTATUS map_view( struct file_view **view_ret, void *base, size_t size,
return STATUS_SUCCESS;
}
if (limit_high && limit_low >= limit_high) return STATUS_INVALID_PARAMETER;
if (base)
{
if (is_beyond_limit( base, size, address_space_limit )) return STATUS_WORKING_SET_LIMIT_RANGE;
if (limit && is_beyond_limit( base, size, (void *)limit )) return STATUS_CONFLICTING_ADDRESSES;
if (limit_low && base < (void *)limit_low) return STATUS_CONFLICTING_ADDRESSES;
if (limit_high && is_beyond_limit( base, size, (void *)limit_high )) return STATUS_CONFLICTING_ADDRESSES;
if ((status = map_fixed_area( base, size, vprot ))) return status;
if (is_beyond_limit( base, size, working_set_limit )) working_set_limit = address_space_limit;
ptr = base;
@ -1982,7 +1986,8 @@ static NTSTATUS map_view( struct file_view **view_ret, void *base, size_t size,
if (!align_mask) align_mask = granularity_mask;
view_size = size + align_mask + 1;
if (limit && (void *)limit < end) end = (char *)limit + 1;
if (limit_low && (void *)limit_low > start) start = (void *)limit_low;
if (limit_high && (void *)limit_high < end) end = (char *)limit_high + 1;
if ((ptr = map_reserved_area( start, end, size, top_down, get_unix_prot(vprot), align_mask )))
{
@ -1990,7 +1995,7 @@ static NTSTATUS map_view( struct file_view **view_ret, void *base, size_t size,
goto done;
}
if (limit)
if (limit_low || limit_high)
{
if (!(ptr = map_free_area( start, end, size, top_down, get_unix_prot(vprot), align_mask )))
return STATUS_NO_MEMORY;
@ -2324,7 +2329,7 @@ static NTSTATUS allocate_dos_memory( struct file_view **view, unsigned int vprot
if (mmap_is_in_reserved_area( low_64k, dosmem_size - 0x10000 ) != 1)
{
addr = anon_mmap_tryfixed( low_64k, dosmem_size - 0x10000, unix_prot, 0 );
if (addr == MAP_FAILED) return map_view( view, NULL, dosmem_size, 0, vprot, 0, 0 );
if (addr == MAP_FAILED) return map_view( view, NULL, dosmem_size, 0, vprot, 0, 0, 0 );
}
/* now try to allocate the low 64K too */
@ -2795,8 +2800,9 @@ static unsigned int get_mapping_info( HANDLE handle, ACCESS_MASK access, unsigne
* Map a PE image section into memory.
*/
static NTSTATUS virtual_map_image( HANDLE mapping, void **addr_ptr, SIZE_T *size_ptr, HANDLE shared_file,
ULONG_PTR limit, ULONG alloc_type, USHORT machine,
pe_image_info_t *image_info, WCHAR *filename, BOOL is_builtin )
ULONG_PTR limit_low, ULONG_PTR limit_high, ULONG alloc_type,
USHORT machine, pe_image_info_t *image_info,
WCHAR *filename, BOOL is_builtin )
{
unsigned int vprot = SEC_IMAGE | SEC_FILE | VPROT_COMMITTED | VPROT_READ | VPROT_EXEC | VPROT_WRITECOPY;
int unix_fd = -1, needs_close;
@ -2824,9 +2830,9 @@ static NTSTATUS virtual_map_image( HANDLE mapping, void **addr_ptr, SIZE_T *size
if ((ULONG_PTR)base != image_info->base) base = NULL;
if ((char *)base >= (char *)address_space_start) /* make sure the DOS area remains free */
status = map_view( &view, base, size, alloc_type, vprot, limit, 0 );
status = map_view( &view, base, size, alloc_type, vprot, limit_low, limit_high, 0 );
if (status) status = map_view( &view, NULL, size, alloc_type, vprot, limit, 0 );
if (status) status = map_view( &view, NULL, size, alloc_type, vprot, limit_low, limit_high, 0 );
if (status) goto done;
status = map_image_into_view( view, filename, unix_fd, base, image_info,
@ -2866,10 +2872,10 @@ done:
*
* Map a file section into memory.
*/
static unsigned int virtual_map_section( HANDLE handle, PVOID *addr_ptr, ULONG_PTR limit,
SIZE_T commit_size, const LARGE_INTEGER *offset_ptr,
SIZE_T *size_ptr, ULONG alloc_type, ULONG protect,
USHORT machine )
static unsigned int virtual_map_section( HANDLE handle, PVOID *addr_ptr, ULONG_PTR limit_low,
ULONG_PTR limit_high, SIZE_T commit_size,
const LARGE_INTEGER *offset_ptr, SIZE_T *size_ptr,
ULONG alloc_type, ULONG protect, USHORT machine )
{
unsigned int res;
mem_size_t full_size;
@ -2914,9 +2920,9 @@ static unsigned int virtual_map_section( HANDLE handle, PVOID *addr_ptr, ULONG_P
{
filename = (WCHAR *)(image_info + 1);
/* check if we can replace that mapping with the builtin */
res = load_builtin( image_info, filename, machine, addr_ptr, size_ptr, limit );
res = load_builtin( image_info, filename, machine, addr_ptr, size_ptr, limit_low, limit_high );
if (res == STATUS_IMAGE_ALREADY_LOADED)
res = virtual_map_image( handle, addr_ptr, size_ptr, shared_file, limit,
res = virtual_map_image( handle, addr_ptr, size_ptr, shared_file, limit_low, limit_high,
alloc_type, machine, image_info, filename, FALSE );
if (shared_file) NtClose( shared_file );
free( image_info );
@ -2951,7 +2957,7 @@ static unsigned int virtual_map_section( HANDLE handle, PVOID *addr_ptr, ULONG_P
server_enter_uninterrupted_section( &virtual_mutex, &sigset );
res = map_view( &view, base, size, alloc_type, vprot, limit, 0 );
res = map_view( &view, base, size, alloc_type, vprot, limit_low, limit_high, 0 );
if (res) goto done;
TRACE( "handle=%p size=%lx offset=%s\n", handle, size, wine_dbgstr_longlong(offset.QuadPart) );
@ -3128,8 +3134,9 @@ void virtual_get_system_info( SYSTEM_BASIC_INFORMATION *info, BOOL wow64 )
/***********************************************************************
* virtual_map_builtin_module
*/
NTSTATUS virtual_map_builtin_module( HANDLE mapping, void **module, SIZE_T *size, SECTION_IMAGE_INFORMATION *info,
ULONG_PTR limit, WORD machine, BOOL prefer_native )
NTSTATUS virtual_map_builtin_module( HANDLE mapping, void **module, SIZE_T *size,
SECTION_IMAGE_INFORMATION *info, ULONG_PTR limit_low,
ULONG_PTR limit_high, WORD machine, BOOL prefer_native )
{
mem_size_t full_size;
unsigned int sec_flags;
@ -3160,7 +3167,7 @@ NTSTATUS virtual_map_builtin_module( HANDLE mapping, void **module, SIZE_T *size
}
else
{
status = virtual_map_image( mapping, module, size, shared_file, limit, 0,
status = virtual_map_image( mapping, module, size, shared_file, limit_low, limit_high, 0,
machine, image_info, filename, TRUE );
virtual_fill_image_information( image_info, info );
}
@ -3175,7 +3182,7 @@ NTSTATUS virtual_map_builtin_module( HANDLE mapping, void **module, SIZE_T *size
* virtual_map_module
*/
NTSTATUS virtual_map_module( HANDLE mapping, void **module, SIZE_T *size, SECTION_IMAGE_INFORMATION *info,
ULONG_PTR limit, USHORT machine )
ULONG_PTR limit_low, ULONG_PTR limit_high, USHORT machine )
{
unsigned int status;
mem_size_t full_size;
@ -3195,9 +3202,9 @@ NTSTATUS virtual_map_module( HANDLE mapping, void **module, SIZE_T *size, SECTIO
filename = (WCHAR *)(image_info + 1);
/* check if we can replace that mapping with the builtin */
status = load_builtin( image_info, filename, machine, module, size, limit );
status = load_builtin( image_info, filename, machine, module, size, limit_low, limit_high );
if (status == STATUS_IMAGE_ALREADY_LOADED)
status = virtual_map_image( mapping, module, size, shared_file, limit, 0,
status = virtual_map_image( mapping, module, size, shared_file, limit_low, limit_high, 0,
machine, image_info, filename, FALSE );
virtual_fill_image_information( image_info, info );
@ -3500,8 +3507,8 @@ NTSTATUS virtual_clear_tls_index( ULONG index )
/***********************************************************************
* virtual_alloc_thread_stack
*/
NTSTATUS virtual_alloc_thread_stack( INITIAL_TEB *stack, ULONG_PTR limit, SIZE_T reserve_size,
SIZE_T commit_size, BOOL guard_page )
NTSTATUS virtual_alloc_thread_stack( INITIAL_TEB *stack, ULONG_PTR limit_low, ULONG_PTR limit_high,
SIZE_T reserve_size, SIZE_T commit_size, BOOL guard_page )
{
struct file_view *view;
NTSTATUS status;
@ -3517,7 +3524,8 @@ NTSTATUS virtual_alloc_thread_stack( INITIAL_TEB *stack, ULONG_PTR limit, SIZE_T
server_enter_uninterrupted_section( &virtual_mutex, &sigset );
status = map_view( &view, NULL, size, 0, VPROT_READ | VPROT_WRITE | VPROT_COMMITTED, limit, 0 );
status = map_view( &view, NULL, size, 0, VPROT_READ | VPROT_WRITE | VPROT_COMMITTED,
limit_low, limit_high, 0 );
if (status != STATUS_SUCCESS) goto done;
#ifdef VALGRIND_STACK_REGISTER
@ -4115,7 +4123,8 @@ void virtual_set_large_address_space(void)
* NtAllocateVirtualMemory[Ex] implementation.
*/
static NTSTATUS allocate_virtual_memory( void **ret, SIZE_T *size_ptr, ULONG type, ULONG protect,
ULONG_PTR limit, ULONG_PTR align, ULONG attributes )
ULONG_PTR limit_low, ULONG_PTR limit_high,
ULONG_PTR align, ULONG attributes )
{
void *base;
unsigned int vprot;
@ -4180,7 +4189,7 @@ static NTSTATUS allocate_virtual_memory( void **ret, SIZE_T *size_ptr, ULONG typ
if (vprot & VPROT_WRITECOPY) status = STATUS_INVALID_PAGE_PROTECTION;
else if (is_dos_memory) status = allocate_dos_memory( &view, vprot );
else status = map_view( &view, base, size, type, vprot, limit,
else status = map_view( &view, base, size, type, vprot, limit_low, limit_high,
align ? align - 1 : granularity_mask );
if (status == STATUS_SUCCESS) base = view->base;
@ -4274,13 +4283,13 @@ NTSTATUS WINAPI NtAllocateVirtualMemory( HANDLE process, PVOID *ret, ULONG_PTR z
else
limit = 0;
return allocate_virtual_memory( ret, size_ptr, type, protect, limit, 0, 0 );
return allocate_virtual_memory( ret, size_ptr, type, protect, 0, limit, 0, 0 );
}
static NTSTATUS get_extended_params( const MEM_EXTENDED_PARAMETER *parameters, ULONG count,
ULONG_PTR *limit, ULONG_PTR *align, ULONG *attributes,
USHORT *machine )
ULONG_PTR *limit_low, ULONG_PTR *limit_high, ULONG_PTR *align,
ULONG *attributes, USHORT *machine )
{
ULONG i, present = 0;
@ -4298,10 +4307,6 @@ static NTSTATUS get_extended_params( const MEM_EXTENDED_PARAMETER *parameters, U
{
MEM_ADDRESS_REQUIREMENTS *r = parameters[i].Pointer;
if (r->LowestStartingAddress)
FIXME( "Not supported requirements LowestStartingAddress %p, Alignment %p.\n",
r->LowestStartingAddress, (void *)r->Alignment );
if (r->Alignment)
{
if ((r->Alignment & (r->Alignment - 1)) || r->Alignment - 1 < granularity_mask)
@ -4311,10 +4316,21 @@ static NTSTATUS get_extended_params( const MEM_EXTENDED_PARAMETER *parameters, U
}
*align = r->Alignment;
}
if (r->LowestStartingAddress)
{
*limit_low = (ULONG_PTR)r->LowestStartingAddress;
if (*limit_low >= (ULONG_PTR)user_space_limit || (*limit_low & granularity_mask))
{
WARN( "Invalid limit %p.\n", r->LowestStartingAddress );
return STATUS_INVALID_PARAMETER;
}
}
if (r->HighestEndingAddress)
{
*limit = (ULONG_PTR)r->HighestEndingAddress;
if (*limit > (ULONG_PTR)user_space_limit || ((*limit + 1) & (page_mask - 1)))
*limit_high = (ULONG_PTR)r->HighestEndingAddress;
if (*limit_high > (ULONG_PTR)user_space_limit ||
*limit_high <= *limit_low ||
((*limit_high + 1) & (page_mask - 1)))
{
WARN( "Invalid limit %p.\n", r->HighestEndingAddress );
return STATUS_INVALID_PARAMETER;
@ -4356,7 +4372,8 @@ NTSTATUS WINAPI NtAllocateVirtualMemoryEx( HANDLE process, PVOID *ret, SIZE_T *s
{
static const ULONG type_mask = MEM_COMMIT | MEM_RESERVE | MEM_TOP_DOWN | MEM_WRITE_WATCH
| MEM_RESET | MEM_RESERVE_PLACEHOLDER | MEM_REPLACE_PLACEHOLDER;
ULONG_PTR limit = 0;
ULONG_PTR limit_low = 0;
ULONG_PTR limit_high = 0;
ULONG_PTR align = 0;
ULONG attributes = 0;
USHORT machine = 0;
@ -4365,11 +4382,12 @@ NTSTATUS WINAPI NtAllocateVirtualMemoryEx( HANDLE process, PVOID *ret, SIZE_T *s
TRACE( "%p %p %08lx %x %08x %p %u\n",
process, *ret, *size_ptr, (int)type, (int)protect, parameters, (int)count );
status = get_extended_params( parameters, count, &limit, &align, &attributes, &machine );
status = get_extended_params( parameters, count, &limit_low, &limit_high,
&align, &attributes, &machine );
if (status) return status;
if (type & ~type_mask) return STATUS_INVALID_PARAMETER;
if (*ret && (align || limit)) return STATUS_INVALID_PARAMETER;
if (*ret && (align || limit_low || limit_high)) return STATUS_INVALID_PARAMETER;
if (!*size_ptr) return STATUS_INVALID_PARAMETER;
if (process != NtCurrentProcess())
@ -4382,7 +4400,8 @@ NTSTATUS WINAPI NtAllocateVirtualMemoryEx( HANDLE process, PVOID *ret, SIZE_T *s
call.virtual_alloc_ex.type = APC_VIRTUAL_ALLOC_EX;
call.virtual_alloc_ex.addr = wine_server_client_ptr( *ret );
call.virtual_alloc_ex.size = *size_ptr;
call.virtual_alloc_ex.limit = limit;
call.virtual_alloc_ex.limit_low = limit_low;
call.virtual_alloc_ex.limit_high = limit_high;
call.virtual_alloc_ex.align = align;
call.virtual_alloc_ex.op_type = type;
call.virtual_alloc_ex.prot = protect;
@ -4398,7 +4417,8 @@ NTSTATUS WINAPI NtAllocateVirtualMemoryEx( HANDLE process, PVOID *ret, SIZE_T *s
return result.virtual_alloc_ex.status;
}
return allocate_virtual_memory( ret, size_ptr, type, protect, limit, align, attributes );
return allocate_virtual_memory( ret, size_ptr, type, protect,
limit_low, limit_high, align, attributes );
}
@ -5094,7 +5114,7 @@ NTSTATUS WINAPI NtMapViewOfSection( HANDLE handle, HANDLE process, PVOID *addr_p
return result.map_view.status;
}
return virtual_map_section( handle, addr_ptr, get_zero_bits_limit( zero_bits ), commit_size,
return virtual_map_section( handle, addr_ptr, 0, get_zero_bits_limit( zero_bits ), commit_size,
offset_ptr, size_ptr, alloc_type, protect, 0 );
}
@ -5107,7 +5127,7 @@ NTSTATUS WINAPI NtMapViewOfSectionEx( HANDLE handle, HANDLE process, PVOID *addr
ULONG alloc_type, ULONG protect,
MEM_EXTENDED_PARAMETER *parameters, ULONG count )
{
ULONG_PTR limit = 0, align = 0;
ULONG_PTR limit_low = 0, limit_high = 0, align = 0;
ULONG attributes = 0;
USHORT machine = 0;
unsigned int status;
@ -5119,11 +5139,12 @@ NTSTATUS WINAPI NtMapViewOfSectionEx( HANDLE handle, HANDLE process, PVOID *addr
TRACE( "handle=%p process=%p addr=%p off=%s size=%lx access=%x\n",
handle, process, *addr_ptr, wine_dbgstr_longlong(offset.QuadPart), *size_ptr, (int)protect );
status = get_extended_params( parameters, count, &limit, &align, &attributes, &machine );
status = get_extended_params( parameters, count, &limit_low, &limit_high,
&align, &attributes, &machine );
if (status) return status;
if (align) return STATUS_INVALID_PARAMETER;
if (*addr_ptr && limit) return STATUS_INVALID_PARAMETER;
if (*addr_ptr && (limit_low || limit_high)) return STATUS_INVALID_PARAMETER;
#ifndef _WIN64
if (!is_old_wow64() && (alloc_type & AT_ROUND_TO_PAGE))
@ -5148,11 +5169,11 @@ NTSTATUS WINAPI NtMapViewOfSectionEx( HANDLE handle, HANDLE process, PVOID *addr
call.map_view_ex.addr = wine_server_client_ptr( *addr_ptr );
call.map_view_ex.size = *size_ptr;
call.map_view_ex.offset = offset.QuadPart;
call.map_view_ex.limit = limit;
call.map_view_ex.limit_low = limit_low;
call.map_view_ex.limit_high = limit_high;
call.map_view_ex.alloc_type = alloc_type;
call.map_view_ex.prot = protect;
call.map_view_ex.machine = machine;
if (call.map_view_ex.prot != protect) return STATUS_INVALID_PARAMETER;
status = server_queue_process_apc( process, &call, &result );
if (status != STATUS_SUCCESS) return status;
@ -5164,8 +5185,8 @@ NTSTATUS WINAPI NtMapViewOfSectionEx( HANDLE handle, HANDLE process, PVOID *addr
return result.map_view_ex.status;
}
return virtual_map_section( handle, addr_ptr, limit, 0, offset_ptr, size_ptr,
alloc_type, protect, machine );
return virtual_map_section( handle, addr_ptr, limit_low, limit_high, 0,
offset_ptr, size_ptr, alloc_type, protect, machine );
}

View file

@ -527,7 +527,8 @@ typedef union
unsigned int op_type;
client_ptr_t addr;
mem_size_t size;
mem_size_t limit;
mem_size_t limit_low;
mem_size_t limit_high;
mem_size_t align;
unsigned int prot;
unsigned int attributes;
@ -591,10 +592,12 @@ typedef union
client_ptr_t addr;
mem_size_t size;
file_pos_t offset;
mem_size_t limit;
mem_size_t limit_low;
mem_size_t limit_high;
unsigned int alloc_type;
unsigned short prot;
unsigned int prot;
unsigned short machine;
unsigned short __pad[3];
} map_view_ex;
struct
{
@ -6414,7 +6417,7 @@ union generic_reply
/* ### protocol_version begin ### */
#define SERVER_PROTOCOL_VERSION 775
#define SERVER_PROTOCOL_VERSION 776
/* ### protocol_version end ### */

View file

@ -543,7 +543,8 @@ typedef union
unsigned int op_type; /* type of operation */
client_ptr_t addr; /* requested address */
mem_size_t size; /* allocation size */
mem_size_t limit; /* allocation address limit */
mem_size_t limit_low; /* allocation address limits */
mem_size_t limit_high;
mem_size_t align; /* allocation alignment */
unsigned int prot; /* memory protection flags */
unsigned int attributes; /* memory extended attributes */
@ -607,10 +608,12 @@ typedef union
client_ptr_t addr; /* requested address */
mem_size_t size; /* allocation size */
file_pos_t offset; /* file offset */
mem_size_t limit; /* allocation address limit */
mem_size_t limit_low; /* allocation address limits */
mem_size_t limit_high;
unsigned int alloc_type; /* allocation type */
unsigned short prot; /* memory protection flags */
unsigned int prot; /* memory protection flags */
unsigned short machine; /* requested machine for image mappings */
unsigned short __pad[3];
} map_view_ex;
struct
{

View file

@ -689,7 +689,7 @@ static const req_handler req_handlers[REQ_NB_REQUESTS] =
C_ASSERT( sizeof(abstime_t) == 8 );
C_ASSERT( sizeof(affinity_t) == 8 );
C_ASSERT( sizeof(apc_call_t) == 48 );
C_ASSERT( sizeof(apc_call_t) == 64 );
C_ASSERT( sizeof(apc_param_t) == 8 );
C_ASSERT( sizeof(apc_result_t) == 40 );
C_ASSERT( sizeof(async_data_t) == 40 );

View file

@ -192,7 +192,8 @@ static void dump_apc_call( const char *prefix, const apc_call_t *call )
case APC_VIRTUAL_ALLOC_EX:
dump_uint64( "APC_VIRTUAL_ALLOC_EX,addr=", &call->virtual_alloc_ex.addr );
dump_uint64( ",size=", &call->virtual_alloc_ex.size );
dump_uint64( ",limit=", &call->virtual_alloc_ex.limit );
dump_uint64( ",limit_low=", &call->virtual_alloc_ex.limit_low );
dump_uint64( ",limit_high=", &call->virtual_alloc_ex.limit_high );
dump_uint64( ",align=", &call->virtual_alloc_ex.align );
fprintf( stderr, ",op_type=%x,prot=%x,attributes=%x",
call->virtual_alloc_ex.op_type, call->virtual_alloc_ex.prot,
@ -236,7 +237,8 @@ static void dump_apc_call( const char *prefix, const apc_call_t *call )
dump_uint64( ",addr=", &call->map_view_ex.addr );
dump_uint64( ",size=", &call->map_view_ex.size );
dump_uint64( ",offset=", &call->map_view_ex.offset );
dump_uint64( ",limit=", &call->map_view_ex.limit );
dump_uint64( ",limit_low=", &call->map_view_ex.limit_low );
dump_uint64( ",limit_high=", &call->map_view_ex.limit_high );
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;
@ -549,6 +551,7 @@ static void dump_varargs_apc_call( const char *prefix, data_size_t size )
dump_apc_call( prefix, call );
size = sizeof(*call);
}
else fprintf( stderr, "%s{}", prefix );
remove_data( size );
}

View file

@ -53,7 +53,7 @@ my %formats =
"ioctl_code_t" => [ 4, 4, "&dump_ioctl_code" ],
"hw_input_t" => [ 40, 8, "&dump_hw_input" ],
# varargs-only structures
"apc_call_t" => [ 48, 8 ],
"apc_call_t" => [ 64, 8 ],
"context_t" => [ 1720, 8 ],
"cursor_pos_t" => [ 24, 8 ],
"debug_event_t" => [ 160, 8 ],