NtMapViewOfSection also accepts the MEM_TOP_DOWN parameter that can be used in combination with zero_bits to map memory on the highest possible address.
This is useful for the next patches so we can consistently fail zero_bits tests.
Signed-off-by: Rémi Bernon rbernon@codeweavers.com --- dlls/ntdll/loader.c | 2 +- dlls/ntdll/ntdll_misc.h | 4 ++-- dlls/ntdll/virtual.c | 19 ++++++++++--------- 3 files changed, 13 insertions(+), 12 deletions(-)
diff --git a/dlls/ntdll/loader.c b/dlls/ntdll/loader.c index 67efcafdaec..c1358c67cdd 100644 --- a/dlls/ntdll/loader.c +++ b/dlls/ntdll/loader.c @@ -2135,7 +2135,7 @@ static NTSTATUS open_dll_file( UNICODE_STRING *nt_name, WINE_MODREF **pwm, *module = NULL; } status = virtual_map_section( mapping, module, 0, 0, NULL, &len, - PAGE_EXECUTE_READ, image_info ); + 0, PAGE_EXECUTE_READ, image_info ); if (status == STATUS_IMAGE_NOT_AT_BASE) status = STATUS_SUCCESS; NtClose( mapping ); } diff --git a/dlls/ntdll/ntdll_misc.h b/dlls/ntdll/ntdll_misc.h index e8db1ca07d2..1950d8c1c7e 100644 --- a/dlls/ntdll/ntdll_misc.h +++ b/dlls/ntdll/ntdll_misc.h @@ -166,8 +166,8 @@ extern NTSTATUS nt_to_unix_file_name_attr( const OBJECT_ATTRIBUTES *attr, ANSI_S extern NTSTATUS virtual_alloc_aligned( PVOID *ret, ULONG zero_bits, SIZE_T *size_ptr, ULONG type, ULONG protect, ULONG alignment ) DECLSPEC_HIDDEN; extern NTSTATUS virtual_map_section( HANDLE handle, PVOID *addr_ptr, ULONG zero_bits, SIZE_T commit_size, - const LARGE_INTEGER *offset_ptr, SIZE_T *size_ptr, ULONG protect, - pe_image_info_t *image_info ) DECLSPEC_HIDDEN; + const LARGE_INTEGER *offset_ptr, SIZE_T *size_ptr, ULONG alloc_type, + ULONG protect, pe_image_info_t *image_info ) DECLSPEC_HIDDEN; extern void virtual_get_system_info( SYSTEM_BASIC_INFORMATION *info ) DECLSPEC_HIDDEN; extern NTSTATUS virtual_create_builtin_view( void *base ) DECLSPEC_HIDDEN; extern NTSTATUS virtual_alloc_thread_stack( INITIAL_TEB *stack, SIZE_T reserve_size, diff --git a/dlls/ntdll/virtual.c b/dlls/ntdll/virtual.c index 6196a4e3ee1..292d4b97258 100644 --- a/dlls/ntdll/virtual.c +++ b/dlls/ntdll/virtual.c @@ -1361,7 +1361,7 @@ static NTSTATUS map_pe_header( void *ptr, size_t size, int fd, BOOL *removable ) * * Map an executable (PE format) image into memory. */ -static NTSTATUS map_image( HANDLE hmapping, ACCESS_MASK access, int fd, SIZE_T zero_bits, +static NTSTATUS map_image( HANDLE hmapping, ACCESS_MASK access, int fd, int top_down, SIZE_T zero_bits, pe_image_info_t *image_info, int shared_fd, BOOL removable, PVOID *addr_ptr ) { IMAGE_DOS_HEADER *dos; @@ -1391,11 +1391,11 @@ static NTSTATUS map_image( HANDLE hmapping, ACCESS_MASK access, int fd, SIZE_T z server_enter_uninterrupted_section( &csVirtual, &sigset );
if (base >= (char *)address_space_start) /* make sure the DOS area remains free */ - status = map_view( &view, base, total_size, 0, FALSE, SEC_IMAGE | SEC_FILE | + status = map_view( &view, base, total_size, 0, top_down, SEC_IMAGE | SEC_FILE | VPROT_COMMITTED | VPROT_READ | VPROT_EXEC | VPROT_WRITECOPY, zero_bits );
if (status != STATUS_SUCCESS) - status = map_view( &view, NULL, total_size, 0, FALSE, SEC_IMAGE | SEC_FILE | + status = map_view( &view, NULL, total_size, 0, top_down, SEC_IMAGE | SEC_FILE | VPROT_COMMITTED | VPROT_READ | VPROT_EXEC | VPROT_WRITECOPY, zero_bits );
if (status != STATUS_SUCCESS) goto error; @@ -1612,8 +1612,8 @@ static NTSTATUS map_image( HANDLE hmapping, ACCESS_MASK access, int fd, SIZE_T z * Map a file section into memory. */ NTSTATUS virtual_map_section( HANDLE handle, PVOID *addr_ptr, ULONG zero_bits, SIZE_T commit_size, - const LARGE_INTEGER *offset_ptr, SIZE_T *size_ptr, ULONG protect, - pe_image_info_t *image_info ) + const LARGE_INTEGER *offset_ptr, SIZE_T *size_ptr, ULONG alloc_type, + ULONG protect, pe_image_info_t *image_info ) { NTSTATUS res; mem_size_t full_size; @@ -1673,14 +1673,14 @@ NTSTATUS virtual_map_section( HANDLE handle, PVOID *addr_ptr, ULONG zero_bits, S
if ((res = server_get_unix_fd( shared_file, FILE_READ_DATA|FILE_WRITE_DATA, &shared_fd, &shared_needs_close, NULL, NULL ))) goto done; - res = map_image( handle, access, unix_handle, zero_bits, image_info, + res = map_image( handle, access, unix_handle, alloc_type & MEM_TOP_DOWN, zero_bits, image_info, shared_fd, needs_close, addr_ptr ); if (shared_needs_close) close( shared_fd ); close_handle( shared_file ); } else { - res = map_image( handle, access, unix_handle, zero_bits, image_info, + res = map_image( handle, access, unix_handle, alloc_type & MEM_TOP_DOWN, zero_bits, image_info, -1, needs_close, addr_ptr ); } if (needs_close) close( unix_handle ); @@ -1718,7 +1718,7 @@ NTSTATUS virtual_map_section( HANDLE handle, PVOID *addr_ptr, ULONG zero_bits, S get_vprot_flags( protect, &vprot, sec_flags & SEC_IMAGE ); vprot |= sec_flags; if (!(sec_flags & SEC_RESERVE)) vprot |= VPROT_COMMITTED; - res = map_view( &view, *addr_ptr, size, 0, FALSE, vprot, zero_bits ); + res = map_view( &view, *addr_ptr, size, 0, alloc_type & MEM_TOP_DOWN, vprot, zero_bits ); if (res) { server_leave_uninterrupted_section( &csVirtual, &sigset ); @@ -3198,7 +3198,8 @@ NTSTATUS WINAPI NtMapViewOfSection( HANDLE handle, HANDLE process, PVOID *addr_p }
return virtual_map_section( handle, addr_ptr, zero_bits, commit_size, - offset_ptr, size_ptr, protect, &image_info ); + offset_ptr, size_ptr, alloc_type, protect, + &image_info ); }
This is in preparation for the following patches that are changing the internal zero_bits format. Also, parameter validation has already been done before queueing the APC.
Signed-off-by: Rémi Bernon rbernon@codeweavers.com --- dlls/ntdll/server.c | 21 ++++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-)
diff --git a/dlls/ntdll/server.c b/dlls/ntdll/server.c index b82fbc56584..16e73d497c4 100644 --- a/dlls/ntdll/server.c +++ b/dlls/ntdll/server.c @@ -391,6 +391,7 @@ BOOL invoke_apc( const apc_call_t *call, apc_result_t *result ) BOOL user_apc = FALSE; SIZE_T size; void *addr; + pe_image_info_t image_info;
memset( result, 0, sizeof(*result) );
@@ -429,10 +430,11 @@ BOOL invoke_apc( const apc_call_t *call, apc_result_t *result ) size = call->virtual_alloc.size; if ((ULONG_PTR)addr == call->virtual_alloc.addr && size == call->virtual_alloc.size) { - result->virtual_alloc.status = NtAllocateVirtualMemory( NtCurrentProcess(), &addr, - call->virtual_alloc.zero_bits, &size, - call->virtual_alloc.op_type, - call->virtual_alloc.prot ); + result->virtual_alloc.status = virtual_alloc_aligned( &addr, + call->virtual_alloc.zero_bits, &size, + call->virtual_alloc.op_type, + call->virtual_alloc.prot, + 0 ); result->virtual_alloc.addr = wine_server_client_ptr( addr ); result->virtual_alloc.size = size; } @@ -534,11 +536,12 @@ BOOL invoke_apc( const apc_call_t *call, apc_result_t *result ) { LARGE_INTEGER offset; offset.QuadPart = call->map_view.offset; - result->map_view.status = NtMapViewOfSection( wine_server_ptr_handle(call->map_view.handle), - NtCurrentProcess(), &addr, - call->map_view.zero_bits, 0, - &offset, &size, ViewShare, - call->map_view.alloc_type, call->map_view.prot ); + result->map_view.status = virtual_map_section( wine_server_ptr_handle(call->map_view.handle), + &addr, + call->map_view.zero_bits, 0, + &offset, &size, + call->map_view.alloc_type, call->map_view.prot, + &image_info ); result->map_view.addr = wine_server_client_ptr( addr ); result->map_view.size = size; }
Signed-off-by: Huw Davies huw@codeweavers.com
It can be a pointer mask, eventually 64bit, and ULONG_PTR is what can be found in several documentation of these functions.
Signed-off-by: Rémi Bernon rbernon@codeweavers.com --- dlls/kernel32/tests/loader.c | 4 ++-- dlls/kernel32/tests/sync.c | 2 +- dlls/kernel32/tests/virtual.c | 2 +- dlls/ntdll/tests/info.c | 2 +- dlls/ntdll/tests/virtual.c | 12 ++++++------ dlls/ntdll/virtual.c | 4 ++-- include/winternl.h | 4 ++-- 7 files changed, 15 insertions(+), 15 deletions(-)
diff --git a/dlls/kernel32/tests/loader.c b/dlls/kernel32/tests/loader.c index eb02e95efca..65184887b8e 100644 --- a/dlls/kernel32/tests/loader.c +++ b/dlls/kernel32/tests/loader.c @@ -57,14 +57,14 @@ static BOOL is_wow64; static NTSTATUS (WINAPI *pNtCreateSection)(HANDLE *, ACCESS_MASK, const OBJECT_ATTRIBUTES *, const LARGE_INTEGER *, ULONG, ULONG, HANDLE ); static NTSTATUS (WINAPI *pNtQuerySection)(HANDLE, SECTION_INFORMATION_CLASS, void *, SIZE_T, SIZE_T *); -static NTSTATUS (WINAPI *pNtMapViewOfSection)(HANDLE, HANDLE, PVOID *, ULONG, SIZE_T, const LARGE_INTEGER *, SIZE_T *, ULONG, ULONG, ULONG); +static NTSTATUS (WINAPI *pNtMapViewOfSection)(HANDLE, HANDLE, PVOID *, ULONG_PTR, SIZE_T, const LARGE_INTEGER *, SIZE_T *, ULONG, ULONG, ULONG); static NTSTATUS (WINAPI *pNtUnmapViewOfSection)(HANDLE, PVOID); static NTSTATUS (WINAPI *pNtQueryInformationProcess)(HANDLE, PROCESSINFOCLASS, PVOID, ULONG, PULONG); static NTSTATUS (WINAPI *pNtSetInformationProcess)(HANDLE, PROCESSINFOCLASS, PVOID, ULONG); static NTSTATUS (WINAPI *pNtTerminateProcess)(HANDLE, DWORD); static void (WINAPI *pLdrShutdownProcess)(void); static BOOLEAN (WINAPI *pRtlDllShutdownInProgress)(void); -static NTSTATUS (WINAPI *pNtAllocateVirtualMemory)(HANDLE, PVOID *, ULONG, SIZE_T *, ULONG, ULONG); +static NTSTATUS (WINAPI *pNtAllocateVirtualMemory)(HANDLE, PVOID *, ULONG_PTR, SIZE_T *, ULONG, ULONG); static NTSTATUS (WINAPI *pNtFreeVirtualMemory)(HANDLE, PVOID *, SIZE_T *, ULONG); static NTSTATUS (WINAPI *pLdrLockLoaderLock)(ULONG, ULONG *, ULONG_PTR *); static NTSTATUS (WINAPI *pLdrUnlockLoaderLock)(ULONG, ULONG_PTR); diff --git a/dlls/kernel32/tests/sync.c b/dlls/kernel32/tests/sync.c index 97566f1d84b..40cad1c4c50 100644 --- a/dlls/kernel32/tests/sync.c +++ b/dlls/kernel32/tests/sync.c @@ -53,7 +53,7 @@ static VOID (WINAPI *pReleaseSRWLockShared)(PSRWLOCK); static BOOLEAN (WINAPI *pTryAcquireSRWLockExclusive)(PSRWLOCK); static BOOLEAN (WINAPI *pTryAcquireSRWLockShared)(PSRWLOCK);
-static NTSTATUS (WINAPI *pNtAllocateVirtualMemory)(HANDLE, PVOID *, ULONG, SIZE_T *, ULONG, ULONG); +static NTSTATUS (WINAPI *pNtAllocateVirtualMemory)(HANDLE, PVOID *, ULONG_PTR, SIZE_T *, ULONG, ULONG); static NTSTATUS (WINAPI *pNtFreeVirtualMemory)(HANDLE, PVOID *, SIZE_T *, ULONG); static NTSTATUS (WINAPI *pNtWaitForSingleObject)(HANDLE, BOOLEAN, const LARGE_INTEGER *); static NTSTATUS (WINAPI *pNtWaitForMultipleObjects)(ULONG,const HANDLE*,BOOLEAN,BOOLEAN,const LARGE_INTEGER*); diff --git a/dlls/kernel32/tests/virtual.c b/dlls/kernel32/tests/virtual.c index 402ab6b0b58..bde71b9c648 100644 --- a/dlls/kernel32/tests/virtual.c +++ b/dlls/kernel32/tests/virtual.c @@ -44,7 +44,7 @@ static UINT (WINAPI *pResetWriteWatch)(LPVOID,SIZE_T); static NTSTATUS (WINAPI *pNtAreMappedFilesTheSame)(PVOID,PVOID); static NTSTATUS (WINAPI *pNtCreateSection)(HANDLE *, ACCESS_MASK, const OBJECT_ATTRIBUTES *, const LARGE_INTEGER *, ULONG, ULONG, HANDLE ); -static NTSTATUS (WINAPI *pNtMapViewOfSection)(HANDLE, HANDLE, PVOID *, ULONG, SIZE_T, const LARGE_INTEGER *, SIZE_T *, ULONG, ULONG, ULONG); +static NTSTATUS (WINAPI *pNtMapViewOfSection)(HANDLE, HANDLE, PVOID *, ULONG_PTR, SIZE_T, const LARGE_INTEGER *, SIZE_T *, ULONG, ULONG, ULONG); static DWORD (WINAPI *pNtUnmapViewOfSection)(HANDLE, PVOID); static NTSTATUS (WINAPI *pNtQuerySection)(HANDLE, SECTION_INFORMATION_CLASS, void *, SIZE_T, SIZE_T *); static PVOID (WINAPI *pRtlAddVectoredExceptionHandler)(ULONG, PVECTORED_EXCEPTION_HANDLER); diff --git a/dlls/ntdll/tests/info.c b/dlls/ntdll/tests/info.c index 262d2f421fc..25c379929b0 100644 --- a/dlls/ntdll/tests/info.c +++ b/dlls/ntdll/tests/info.c @@ -32,7 +32,7 @@ static NTSTATUS (WINAPI * pNtSetInformationThread)(HANDLE, THREADINFOCLASS, PVOI static NTSTATUS (WINAPI * pNtReadVirtualMemory)(HANDLE, const void*, void*, SIZE_T, SIZE_T*); static NTSTATUS (WINAPI * pNtQueryVirtualMemory)(HANDLE, LPCVOID, MEMORY_INFORMATION_CLASS , PVOID , SIZE_T , SIZE_T *); static NTSTATUS (WINAPI * pNtCreateSection)(HANDLE*,ACCESS_MASK,const OBJECT_ATTRIBUTES*,const LARGE_INTEGER*,ULONG,ULONG,HANDLE); -static NTSTATUS (WINAPI * pNtMapViewOfSection)(HANDLE,HANDLE,PVOID*,ULONG,SIZE_T,const LARGE_INTEGER*,SIZE_T*,SECTION_INHERIT,ULONG,ULONG); +static NTSTATUS (WINAPI * pNtMapViewOfSection)(HANDLE,HANDLE,PVOID*,ULONG_PTR,SIZE_T,const LARGE_INTEGER*,SIZE_T*,SECTION_INHERIT,ULONG,ULONG); static NTSTATUS (WINAPI * pNtUnmapViewOfSection)(HANDLE,PVOID); static NTSTATUS (WINAPI * pNtClose)(HANDLE); static ULONG (WINAPI * pNtGetCurrentProcessorNumber)(void); diff --git a/dlls/ntdll/tests/virtual.c b/dlls/ntdll/tests/virtual.c index bb110f15681..5c3a0b341ff 100644 --- a/dlls/ntdll/tests/virtual.c +++ b/dlls/ntdll/tests/virtual.c @@ -69,7 +69,7 @@ static void test_NtAllocateVirtualMemory(void) void *addr1, *addr2; NTSTATUS status; SIZE_T size; - ULONG zero_bits; + ULONG_PTR zero_bits; BOOL is_wow64;
/* simple allocation should success */ @@ -120,12 +120,12 @@ static void test_NtAllocateVirtualMemory(void) MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE); ok(status == STATUS_SUCCESS || status == STATUS_NO_MEMORY || broken(zero_bits == 20 && status == STATUS_CONFLICTING_ADDRESSES) /* w1064v1809 */, - "NtAllocateVirtualMemory with %d zero_bits returned %08x\n", zero_bits, status); + "NtAllocateVirtualMemory with %d zero_bits returned %08x\n", (int)zero_bits, status); if (status == STATUS_SUCCESS) { todo_wine_if((UINT_PTR)addr2 >> (32 - zero_bits)) ok(((UINT_PTR)addr2 >> (32 - zero_bits)) == 0, - "NtAllocateVirtualMemory with %d zero_bits returned address %p\n", zero_bits, addr2); + "NtAllocateVirtualMemory with %d zero_bits returned address %p\n", (int)zero_bits, addr2);
size = 0; status = NtFreeVirtualMemory(NtCurrentProcess(), &addr2, &size, MEM_RELEASE); @@ -271,7 +271,7 @@ static void test_NtMapViewOfSection(void) DWORD status, written; SIZE_T size, result; LARGE_INTEGER offset; - ULONG zero_bits; + ULONG_PTR zero_bits;
file = CreateFileA(testfile, GENERIC_READ|GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, 0); ok(file != INVALID_HANDLE_VALUE, "Failed to create test file\n"); @@ -324,12 +324,12 @@ static void test_NtMapViewOfSection(void) offset.QuadPart = 0; status = NtMapViewOfSection(mapping, process, &ptr2, zero_bits, 0, &offset, &size, 1, 0, PAGE_READWRITE); ok(status == STATUS_SUCCESS || status == STATUS_NO_MEMORY, - "NtMapViewOfSection with %d zero_bits returned %08x\n", zero_bits, status); + "NtMapViewOfSection with %d zero_bits returned %08x\n", (int)zero_bits, status); if (status == STATUS_SUCCESS) { todo_wine_if((UINT_PTR)ptr2 >> (32 - zero_bits)) ok(((UINT_PTR)ptr2 >> (32 - zero_bits)) == 0, - "NtMapViewOfSection with %d zero_bits returned address %p\n", zero_bits, ptr2); + "NtMapViewOfSection with %d zero_bits returned address %p\n", (int)zero_bits, ptr2);
status = NtUnmapViewOfSection(process, ptr2); ok(status == STATUS_SUCCESS, "NtUnmapViewOfSection returned %08x\n", status); diff --git a/dlls/ntdll/virtual.c b/dlls/ntdll/virtual.c index 292d4b97258..57536eb6295 100644 --- a/dlls/ntdll/virtual.c +++ b/dlls/ntdll/virtual.c @@ -2501,7 +2501,7 @@ void virtual_set_large_address_space(void) * NtAllocateVirtualMemory (NTDLL.@) * ZwAllocateVirtualMemory (NTDLL.@) */ -NTSTATUS WINAPI NtAllocateVirtualMemory( HANDLE process, PVOID *ret, ULONG zero_bits, +NTSTATUS WINAPI NtAllocateVirtualMemory( HANDLE process, PVOID *ret, ULONG_PTR zero_bits, SIZE_T *size_ptr, ULONG type, ULONG protect ) { SIZE_T size = *size_ptr; @@ -3132,7 +3132,7 @@ NTSTATUS WINAPI NtOpenSection( HANDLE *handle, ACCESS_MASK access, const OBJECT_ * NtMapViewOfSection (NTDLL.@) * ZwMapViewOfSection (NTDLL.@) */ -NTSTATUS WINAPI NtMapViewOfSection( HANDLE handle, HANDLE process, PVOID *addr_ptr, ULONG zero_bits, +NTSTATUS WINAPI NtMapViewOfSection( HANDLE handle, HANDLE process, PVOID *addr_ptr, ULONG_PTR zero_bits, SIZE_T commit_size, const LARGE_INTEGER *offset_ptr, SIZE_T *size_ptr, SECTION_INHERIT inherit, ULONG alloc_type, ULONG protect ) { diff --git a/include/winternl.h b/include/winternl.h index 49eedaf1f98..3d31f8b462a 100644 --- a/include/winternl.h +++ b/include/winternl.h @@ -2318,7 +2318,7 @@ NTSYSAPI NTSTATUS WINAPI NtAlertResumeThread(HANDLE,PULONG); NTSYSAPI NTSTATUS WINAPI NtAlertThread(HANDLE ThreadHandle); NTSYSAPI NTSTATUS WINAPI NtAllocateLocallyUniqueId(PLUID lpLuid); NTSYSAPI NTSTATUS WINAPI NtAllocateUuids(PULARGE_INTEGER,PULONG,PULONG,PUCHAR); -NTSYSAPI NTSTATUS WINAPI NtAllocateVirtualMemory(HANDLE,PVOID*,ULONG,SIZE_T*,ULONG,ULONG); +NTSYSAPI NTSTATUS WINAPI NtAllocateVirtualMemory(HANDLE,PVOID*,ULONG_PTR,SIZE_T*,ULONG,ULONG); NTSYSAPI NTSTATUS WINAPI NtAreMappedFilesTheSame(PVOID,PVOID); NTSYSAPI NTSTATUS WINAPI NtAssignProcessToJobObject(HANDLE,HANDLE); NTSYSAPI NTSTATUS WINAPI NtCallbackReturn(PVOID,ULONG,NTSTATUS); @@ -2390,7 +2390,7 @@ NTSYSAPI NTSTATUS WINAPI NtLoadKey(const OBJECT_ATTRIBUTES *,OBJECT_ATTRIBUTES NTSYSAPI NTSTATUS WINAPI NtLockFile(HANDLE,HANDLE,PIO_APC_ROUTINE,void*,PIO_STATUS_BLOCK,PLARGE_INTEGER,PLARGE_INTEGER,ULONG*,BOOLEAN,BOOLEAN); NTSYSAPI NTSTATUS WINAPI NtLockVirtualMemory(HANDLE,PVOID*,SIZE_T*,ULONG); NTSYSAPI NTSTATUS WINAPI NtMakeTemporaryObject(HANDLE); -NTSYSAPI NTSTATUS WINAPI NtMapViewOfSection(HANDLE,HANDLE,PVOID*,ULONG,SIZE_T,const LARGE_INTEGER*,SIZE_T*,SECTION_INHERIT,ULONG,ULONG); +NTSYSAPI NTSTATUS WINAPI NtMapViewOfSection(HANDLE,HANDLE,PVOID*,ULONG_PTR,SIZE_T,const LARGE_INTEGER*,SIZE_T*,SECTION_INHERIT,ULONG,ULONG); NTSYSAPI NTSTATUS WINAPI NtNotifyChangeDirectoryFile(HANDLE,HANDLE,PIO_APC_ROUTINE,PVOID,PIO_STATUS_BLOCK,PVOID,ULONG,ULONG,BOOLEAN); NTSYSAPI NTSTATUS WINAPI NtNotifyChangeKey(HANDLE,HANDLE,PIO_APC_ROUTINE,PVOID,PIO_STATUS_BLOCK,ULONG,BOOLEAN,PVOID,ULONG,BOOLEAN); NTSYSAPI NTSTATUS WINAPI NtNotifyChangeMultipleKeys(HANDLE,ULONG,OBJECT_ATTRIBUTES*,HANDLE,PIO_APC_ROUTINE,PVOID,PIO_STATUS_BLOCK,ULONG,BOOLEAN,PVOID,ULONG,BOOLEAN);
Hi,
While running your changed tests, I think I found new failures. Being a bot and all I'm not very good at pattern recognition, so I might be wrong, but could you please double-check?
Full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=55000
Your paranoid android.
=== wvistau64_fr (32 bit report) ===
kernel32: loader.c:3305: Test failed: WaitForSingleObject failed: 102 loader.c:3307: Test failed: expected exit code 199, got 259 loader.c:3316: Test failed: WaitForSingleObject failed: 102 loader.c:3326: Test failed: expected 198, got 259 loader.c:3329: Test failed: expected STATUS_PROCESS_IS_TERMINATING, got 0
=== wvistau64_he (32 bit report) ===
kernel32: loader.c:3075: Test failed: child process failed to terminate loader.c:3078: Test failed: expected exit code 195, got 259
=== wvistau64 (32 bit report) ===
kernel32: virtual.c:2548: Test failed: NtSetInformationProcess failed with status c0000022 virtual.c:2586: Test failed: expected policy flags 0, got 3 virtual.c:2587: Test failed: expected policy permanent FALSE, got 1 virtual.c:2642: Test failed: expected no STATUS_ACCESS_VIOLATION exception, got 1 exceptions virtual.c:2656: Test failed: expected no STATUS_ACCESS_VIOLATION exception, got 1 exceptions virtual.c:2685: Test failed: expected no STATUS_ACCESS_VIOLATION exception, got 1 exceptions virtual.c:2700: Test failed: expected no STATUS_ACCESS_VIOLATION exception, got 1 exceptions virtual.c:2748: Test failed: expected no STATUS_ACCESS_VIOLATION exception, got 1 exceptions virtual.c:2763: Test failed: expected no STATUS_ACCESS_VIOLATION exception, got 1 exceptions virtual.c:2781: Test failed: expected no STATUS_ACCESS_VIOLATION exception, got 1 exceptions virtual.c:2799: Test failed: expected no STATUS_ACCESS_VIOLATION exception, got 1 exceptions virtual.c:2880: Test failed: expected no STATUS_ACCESS_VIOLATION exception, got 1 exceptions virtual.c:2904: Test failed: expected no STATUS_ACCESS_VIOLATION exception, got 1 exceptions virtual.c:2944: Test failed: expected no STATUS_ACCESS_VIOLATION exception, got 1 exceptions virtual.c:2969: Test failed: expected no STATUS_ACCESS_VIOLATION exception, got 1 exceptions virtual.c:3006: Test failed: NtSetInformationProcess failed with status c0000022 virtual.c:2548: Test failed: NtSetInformationProcess failed with status c0000022 virtual.c:2586: Test failed: expected policy flags 1, got 3 virtual.c:2587: Test failed: expected policy permanent FALSE, got 1 virtual.c:2685: Test failed: expected no STATUS_ACCESS_VIOLATION exception, got 1 exceptions virtual.c:2700: Test failed: expected no STATUS_ACCESS_VIOLATION exception, got 1 exceptions virtual.c:2748: Test failed: expected no STATUS_ACCESS_VIOLATION exception, got 1 exceptions virtual.c:2763: Test failed: expected no STATUS_ACCESS_VIOLATION exception, got 1 exceptions virtual.c:2944: Test failed: expected no STATUS_ACCESS_VIOLATION exception, got 1 exceptions virtual.c:2969: Test failed: expected no STATUS_ACCESS_VIOLATION exception, got 1 exceptions virtual.c:3006: Test failed: NtSetInformationProcess failed with status c0000022 virtual.c:2548: Test failed: NtSetInformationProcess failed with status c0000022 virtual.c:2587: Test failed: expected policy permanent FALSE, got 1 virtual.c:3006: Test failed: NtSetInformationProcess failed with status c0000022
=== w864 (32 bit report) ===
kernel32: virtual.c:2548: Test failed: NtSetInformationProcess failed with status c0000022 virtual.c:2586: Test failed: expected policy flags 0, got 3 virtual.c:2587: Test failed: expected policy permanent FALSE, got 1 virtual.c:2642: Test failed: expected no STATUS_ACCESS_VIOLATION exception, got 1 exceptions virtual.c:2656: Test failed: expected no STATUS_ACCESS_VIOLATION exception, got 1 exceptions virtual.c:2685: Test failed: expected no STATUS_ACCESS_VIOLATION exception, got 1 exceptions virtual.c:2700: Test failed: expected no STATUS_ACCESS_VIOLATION exception, got 1 exceptions virtual.c:2748: Test failed: expected no STATUS_ACCESS_VIOLATION exception, got 1 exceptions virtual.c:2763: Test failed: expected no STATUS_ACCESS_VIOLATION exception, got 1 exceptions virtual.c:2781: Test failed: expected no STATUS_ACCESS_VIOLATION exception, got 1 exceptions virtual.c:2799: Test failed: expected no STATUS_ACCESS_VIOLATION exception, got 1 exceptions virtual.c:2880: Test failed: expected no STATUS_ACCESS_VIOLATION exception, got 1 exceptions virtual.c:2904: Test failed: expected no STATUS_ACCESS_VIOLATION exception, got 1 exceptions virtual.c:2944: Test failed: expected no STATUS_ACCESS_VIOLATION exception, got 1 exceptions virtual.c:2969: Test failed: expected no STATUS_ACCESS_VIOLATION exception, got 1 exceptions virtual.c:3006: Test failed: NtSetInformationProcess failed with status c0000022 virtual.c:2548: Test failed: NtSetInformationProcess failed with status c0000022 virtual.c:2586: Test failed: expected policy flags 1, got 3 virtual.c:2587: Test failed: expected policy permanent FALSE, got 1 virtual.c:2685: Test failed: expected no STATUS_ACCESS_VIOLATION exception, got 1 exceptions virtual.c:2700: Test failed: expected no STATUS_ACCESS_VIOLATION exception, got 1 exceptions virtual.c:2748: Test failed: expected no STATUS_ACCESS_VIOLATION exception, got 1 exceptions virtual.c:2763: Test failed: expected no STATUS_ACCESS_VIOLATION exception, got 1 exceptions virtual.c:2944: Test failed: expected no STATUS_ACCESS_VIOLATION exception, got 1 exceptions virtual.c:2969: Test failed: expected no STATUS_ACCESS_VIOLATION exception, got 1 exceptions virtual.c:3006: Test failed: NtSetInformationProcess failed with status c0000022 virtual.c:2548: Test failed: NtSetInformationProcess failed with status c0000022 virtual.c:2587: Test failed: expected policy permanent FALSE, got 1 virtual.c:3006: Test failed: NtSetInformationProcess failed with status c0000022
=== debian10 (32 bit report) ===
Report errors: kernel32:virtual prints too much data (91052 bytes)
=== debian10 (32 bit French report) ===
Report errors: kernel32:virtual prints too much data (91052 bytes)
=== debian10 (32 bit Japanese:Japan report) ===
Report errors: kernel32:virtual prints too much data (91052 bytes)
=== debian10 (32 bit Chinese:China report) ===
Report errors: kernel32:virtual prints too much data (91052 bytes)
=== debian10 (32 bit WoW report) ===
Report errors: kernel32:virtual prints too much data (91052 bytes)
=== debian10 (64 bit WoW report) ===
Report errors: kernel32:virtual prints too much data (91052 bytes)
Signed-off-by: Huw Davies huw@codeweavers.com
This is in order to use todo_wine_if(is_win64) in next patch.
Signed-off-by: Rémi Bernon rbernon@codeweavers.com --- dlls/ntdll/tests/virtual.c | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-)
diff --git a/dlls/ntdll/tests/virtual.c b/dlls/ntdll/tests/virtual.c index 5c3a0b341ff..d45df72a741 100644 --- a/dlls/ntdll/tests/virtual.c +++ b/dlls/ntdll/tests/virtual.c @@ -31,6 +31,7 @@ static unsigned int page_size; static NTSTATUS (WINAPI *pRtlCreateUserStack)(SIZE_T, SIZE_T, ULONG, SIZE_T, SIZE_T, INITIAL_TEB *); static NTSTATUS (WINAPI *pRtlFreeUserStack)(void *); static BOOL (WINAPI *pIsWow64Process)(HANDLE, PBOOL); +static const BOOL is_win64 = sizeof(void*) != sizeof(int);
static HANDLE create_target_process(const char *arg) { @@ -72,6 +73,8 @@ static void test_NtAllocateVirtualMemory(void) ULONG_PTR zero_bits; BOOL is_wow64;
+ if (!pIsWow64Process || !pIsWow64Process(NtCurrentProcess(), &is_wow64)) is_wow64 = FALSE; + /* simple allocation should success */ size = 0x1000; addr1 = NULL; @@ -163,8 +166,7 @@ static void test_NtAllocateVirtualMemory(void) status = NtAllocateVirtualMemory(NtCurrentProcess(), &addr2, zero_bits, &size, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE);
- if (sizeof(void *) == sizeof(int) && (!pIsWow64Process || - !pIsWow64Process(NtCurrentProcess(), &is_wow64) || !is_wow64)) + if (!is_win64 && !is_wow64) { ok(status == STATUS_INVALID_PARAMETER_3, "NtAllocateVirtualMemory returned %08x\n", status); } @@ -273,6 +275,8 @@ static void test_NtMapViewOfSection(void) LARGE_INTEGER offset; ULONG_PTR zero_bits;
+ if (!pIsWow64Process || !pIsWow64Process(NtCurrentProcess(), &is_wow64)) is_wow64 = FALSE; + file = CreateFileA(testfile, GENERIC_READ|GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, 0); ok(file != INVALID_HANDLE_VALUE, "Failed to create test file\n"); WriteFile(file, data, sizeof(data), &written, NULL); @@ -360,8 +364,7 @@ static void test_NtMapViewOfSection(void) offset.QuadPart = 0; status = NtMapViewOfSection(mapping, process, &ptr2, zero_bits, 0, &offset, &size, 1, 0, PAGE_READWRITE);
- if (sizeof(void *) == sizeof(int) && (!pIsWow64Process || - !pIsWow64Process(NtCurrentProcess(), &is_wow64) || !is_wow64)) + if (!is_win64 && !is_wow64) { ok(status == STATUS_INVALID_PARAMETER_4, "NtMapViewOfSection returned %08x\n", status); } @@ -424,8 +427,7 @@ static void test_NtMapViewOfSection(void) status = NtMapViewOfSection(mapping, process, &ptr2, zero_bits, 0, &offset, &size, 1, 0, PAGE_READWRITE); ok(status == STATUS_MAPPED_ALIGNMENT, "NtMapViewOfSection returned %08x\n", status);
- if (sizeof(void *) == sizeof(int) && (!pIsWow64Process || - !pIsWow64Process(NtCurrentProcess(), &is_wow64) || !is_wow64)) + if (!is_win64 && !is_wow64) { /* new memory region conflicts with previous mapping */ ptr2 = ptr;
Signed-off-by: Huw Davies huw@codeweavers.com
The todo_wine_if made the tests not really test anything, and one test was succeeding when it shouldn't. Now we can actually remove the todo when 1 zero_bits handling is implemented.
Signed-off-by: Rémi Bernon rbernon@codeweavers.com --- dlls/ntdll/tests/virtual.c | 26 +++++++++++++++----------- 1 file changed, 15 insertions(+), 11 deletions(-)
diff --git a/dlls/ntdll/tests/virtual.c b/dlls/ntdll/tests/virtual.c index d45df72a741..8a53562cc7f 100644 --- a/dlls/ntdll/tests/virtual.c +++ b/dlls/ntdll/tests/virtual.c @@ -101,12 +101,14 @@ static void test_NtAllocateVirtualMemory(void) addr2 = NULL; zero_bits = 1; status = NtAllocateVirtualMemory(NtCurrentProcess(), &addr2, zero_bits, &size, - MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE); + MEM_RESERVE | MEM_COMMIT | MEM_TOP_DOWN, + PAGE_READWRITE); ok(status == STATUS_SUCCESS || status == STATUS_NO_MEMORY || broken(status == STATUS_INVALID_PARAMETER_3) /* winxp */, "NtAllocateVirtualMemory returned %08x\n", status); if (status == STATUS_SUCCESS) { + todo_wine_if(is_win64) ok(((UINT_PTR)addr2 >> (32 - zero_bits)) == 0, "NtAllocateVirtualMemory returned address: %p\n", addr2);
@@ -120,13 +122,14 @@ static void test_NtAllocateVirtualMemory(void) size = 0x1000; addr2 = NULL; status = NtAllocateVirtualMemory(NtCurrentProcess(), &addr2, zero_bits, &size, - MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE); + MEM_RESERVE | MEM_COMMIT | MEM_TOP_DOWN, + PAGE_READWRITE); ok(status == STATUS_SUCCESS || status == STATUS_NO_MEMORY || broken(zero_bits == 20 && status == STATUS_CONFLICTING_ADDRESSES) /* w1064v1809 */, "NtAllocateVirtualMemory with %d zero_bits returned %08x\n", (int)zero_bits, status); if (status == STATUS_SUCCESS) { - todo_wine_if((UINT_PTR)addr2 >> (32 - zero_bits)) + todo_wine ok(((UINT_PTR)addr2 >> (32 - zero_bits)) == 0, "NtAllocateVirtualMemory with %d zero_bits returned address %p\n", (int)zero_bits, addr2);
@@ -164,7 +167,8 @@ static void test_NtAllocateVirtualMemory(void) addr2 = NULL; zero_bits = 0x1fffffff; status = NtAllocateVirtualMemory(NtCurrentProcess(), &addr2, zero_bits, &size, - MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE); + MEM_RESERVE | MEM_COMMIT | MEM_TOP_DOWN, + PAGE_READWRITE);
if (!is_win64 && !is_wow64) { @@ -176,7 +180,7 @@ static void test_NtAllocateVirtualMemory(void) "NtAllocateVirtualMemory returned %08x\n", status); if (status == STATUS_SUCCESS) { - todo_wine_if((UINT_PTR)addr2 & ~zero_bits) + todo_wine ok(((UINT_PTR)addr2 & ~zero_bits) == 0, "NtAllocateVirtualMemory returned address %p\n", addr2);
@@ -308,12 +312,12 @@ static void test_NtMapViewOfSection(void) size = 0; zero_bits = 1; offset.QuadPart = 0; - status = NtMapViewOfSection(mapping, process, &ptr2, zero_bits, 0, &offset, &size, 1, 0, PAGE_READWRITE); + status = NtMapViewOfSection(mapping, process, &ptr2, zero_bits, 0, &offset, &size, 1, MEM_TOP_DOWN, PAGE_READWRITE); ok(status == STATUS_SUCCESS || status == STATUS_NO_MEMORY, "NtMapViewOfSection returned %08x\n", status); if (status == STATUS_SUCCESS) { - todo_wine_if((UINT_PTR)ptr2 >> (32 - zero_bits)) + todo_wine_if(is_win64) ok(((UINT_PTR)ptr2 >> (32 - zero_bits)) == 0, "NtMapViewOfSection returned address: %p\n", ptr2);
@@ -326,12 +330,12 @@ static void test_NtMapViewOfSection(void) ptr2 = NULL; size = 0; offset.QuadPart = 0; - status = NtMapViewOfSection(mapping, process, &ptr2, zero_bits, 0, &offset, &size, 1, 0, PAGE_READWRITE); + status = NtMapViewOfSection(mapping, process, &ptr2, zero_bits, 0, &offset, &size, 1, MEM_TOP_DOWN, PAGE_READWRITE); ok(status == STATUS_SUCCESS || status == STATUS_NO_MEMORY, "NtMapViewOfSection with %d zero_bits returned %08x\n", (int)zero_bits, status); if (status == STATUS_SUCCESS) { - todo_wine_if((UINT_PTR)ptr2 >> (32 - zero_bits)) + todo_wine ok(((UINT_PTR)ptr2 >> (32 - zero_bits)) == 0, "NtMapViewOfSection with %d zero_bits returned address %p\n", (int)zero_bits, ptr2);
@@ -362,7 +366,7 @@ static void test_NtMapViewOfSection(void) size = 0; zero_bits = 0x1fffffff; offset.QuadPart = 0; - status = NtMapViewOfSection(mapping, process, &ptr2, zero_bits, 0, &offset, &size, 1, 0, PAGE_READWRITE); + status = NtMapViewOfSection(mapping, process, &ptr2, zero_bits, 0, &offset, &size, 1, MEM_TOP_DOWN, PAGE_READWRITE);
if (!is_win64 && !is_wow64) { @@ -374,7 +378,7 @@ static void test_NtMapViewOfSection(void) "NtMapViewOfSection returned %08x\n", status); if (status == STATUS_SUCCESS) { - todo_wine_if((UINT_PTR)ptr2 & ~zero_bits) + todo_wine ok(((UINT_PTR)ptr2 & ~zero_bits) == 0, "NtMapViewOfSection returned address %p\n", ptr2);
Signed-off-by: Huw Davies huw@codeweavers.com
Only the leading zeroes are taken into account, so 0x1aaaaaaa zero_bits behaves as 0x1fffffff
Signed-off-by: Rémi Bernon rbernon@codeweavers.com --- dlls/ntdll/tests/virtual.c | 28 +++++++++++++++++++++------- 1 file changed, 21 insertions(+), 7 deletions(-)
diff --git a/dlls/ntdll/tests/virtual.c b/dlls/ntdll/tests/virtual.c index 8a53562cc7f..9eec912e24b 100644 --- a/dlls/ntdll/tests/virtual.c +++ b/dlls/ntdll/tests/virtual.c @@ -60,11 +60,23 @@ static UINT_PTR get_zero_bits(UINT_PTR p) return (~(UINT_PTR)0) >> get_zero_bits(p >> 32); #endif
- if (p == 0) return 32; + if (p == 0) return 0; while ((p >> (31 - z)) != 1) z++; return z; }
+static UINT_PTR get_zero_bits_mask(ULONG_PTR z) +{ + if (z >= 32) + { + z = get_zero_bits(z); +#ifdef _WIN64 + if (z >= 32) return z; +#endif + } + return (~(UINT32)0) >> z; +} + static void test_NtAllocateVirtualMemory(void) { void *addr1, *addr2; @@ -162,10 +174,10 @@ static void test_NtAllocateVirtualMemory(void) ok(status == STATUS_INVALID_PARAMETER_3 || status == STATUS_INVALID_PARAMETER, "NtAllocateVirtualMemory returned %08x\n", status);
- /* zero bits > 31 should be considered as bitmask on 64bit and WoW64 */ + /* zero bits > 31 should be considered as a leading zeroes bitmask on 64bit and WoW64 */ size = 0x1000; addr2 = NULL; - zero_bits = 0x1fffffff; + zero_bits = 0x1aaaaaaa; status = NtAllocateVirtualMemory(NtCurrentProcess(), &addr2, zero_bits, &size, MEM_RESERVE | MEM_COMMIT | MEM_TOP_DOWN, PAGE_READWRITE); @@ -181,7 +193,8 @@ static void test_NtAllocateVirtualMemory(void) if (status == STATUS_SUCCESS) { todo_wine - ok(((UINT_PTR)addr2 & ~zero_bits) == 0, + ok(((UINT_PTR)addr2 & ~get_zero_bits_mask(zero_bits)) == 0 && + ((UINT_PTR)addr2 & ~zero_bits) != 0, /* only the leading zeroes matter */ "NtAllocateVirtualMemory returned address %p\n", addr2);
size = 0; @@ -361,10 +374,10 @@ static void test_NtMapViewOfSection(void) ok(status == STATUS_INVALID_PARAMETER_4 || status == STATUS_INVALID_PARAMETER, "NtMapViewOfSection returned %08x\n", status);
- /* zero bits > 31 should be considered as bitmask on 64bit and WoW64 */ + /* zero bits > 31 should be considered as a leading zeroes bitmask on 64bit and WoW64 */ ptr2 = NULL; size = 0; - zero_bits = 0x1fffffff; + zero_bits = 0x1aaaaaaa; offset.QuadPart = 0; status = NtMapViewOfSection(mapping, process, &ptr2, zero_bits, 0, &offset, &size, 1, MEM_TOP_DOWN, PAGE_READWRITE);
@@ -379,7 +392,8 @@ static void test_NtMapViewOfSection(void) if (status == STATUS_SUCCESS) { todo_wine - ok(((UINT_PTR)ptr2 & ~zero_bits) == 0, + ok(((UINT_PTR)ptr2 & ~get_zero_bits_mask(zero_bits)) == 0 && + ((UINT_PTR)ptr2 & ~zero_bits) != 0, /* only the leading zeroes matter */ "NtMapViewOfSection returned address %p\n", ptr2);
status = NtUnmapViewOfSection(process, ptr2);
Hi,
While running your changed tests, I think I found new failures. Being a bot and all I'm not very good at pattern recognition, so I might be wrong, but could you please double-check?
Full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=55003
Your paranoid android.
=== debian10 (64 bit WoW report) ===
ntdll: pipe.c:1557: Test failed: pipe is not signaled pipe.c:1576: Test failed: pipe is not signaled
Signed-off-by: Huw Davies huw@codeweavers.com
The zero_bits parameter can be a pointer mask on Win64 and WoW64 and it was incorrectly truncated to 16bits in APCs. Testing shows that only the leading zeroes are used in the mask, so we can safely use the 64 based number of leading zeroes everywhere instead.
Signed-off-by: Rémi Bernon rbernon@codeweavers.com --- configure.ac | 9 +++++ dlls/ntdll/ntdll_misc.h | 4 +- dlls/ntdll/server.c | 4 +- dlls/ntdll/virtual.c | 88 ++++++++++++++++++++++++++++------------- server/protocol.def | 28 ++++++------- server/trace.c | 8 ++-- 6 files changed, 92 insertions(+), 49 deletions(-)
diff --git a/configure.ac b/configure.ac index 0fe26022b7d..1684400cd17 100644 --- a/configure.ac +++ b/configure.ac @@ -2693,6 +2693,15 @@ then AC_DEFINE(HAVE___BUILTIN_CLZ, 1, [Define to 1 if you have the `__builtin_clz' built-in function.]) fi
+dnl Check for __builtin_clzll +AC_CACHE_CHECK([for __builtin_clzll], ac_cv_have___builtin_clzll, + AC_LINK_IFELSE([AC_LANG_PROGRAM(,[[return __builtin_clzll(1)]])], + [ac_cv_have___builtin_clzll="yes"], [ac_cv_have___builtin_clzll="no"])) +if test "$ac_cv_have___builtin_clzll" = "yes" +then + AC_DEFINE(HAVE___BUILTIN_CLZLL, 1, [Define to 1 if you have the `__builtin_clzll' built-in function.]) +fi + dnl Check for __builtin_popcount AC_CACHE_CHECK([for __builtin_popcount], ac_cv_have___builtin_popcount, AC_LINK_IFELSE([AC_LANG_PROGRAM(,[[return __builtin_popcount(1)]])], diff --git a/dlls/ntdll/ntdll_misc.h b/dlls/ntdll/ntdll_misc.h index 1950d8c1c7e..5ddce437cfb 100644 --- a/dlls/ntdll/ntdll_misc.h +++ b/dlls/ntdll/ntdll_misc.h @@ -163,9 +163,9 @@ extern NTSTATUS nt_to_unix_file_name_attr( const OBJECT_ATTRIBUTES *attr, ANSI_S UINT disposition ) DECLSPEC_HIDDEN;
/* virtual memory */ -extern NTSTATUS virtual_alloc_aligned( PVOID *ret, ULONG zero_bits, SIZE_T *size_ptr, +extern NTSTATUS virtual_alloc_aligned( PVOID *ret, unsigned short zero_bits_64, SIZE_T *size_ptr, ULONG type, ULONG protect, ULONG alignment ) DECLSPEC_HIDDEN; -extern NTSTATUS virtual_map_section( HANDLE handle, PVOID *addr_ptr, ULONG zero_bits, SIZE_T commit_size, +extern NTSTATUS virtual_map_section( HANDLE handle, PVOID *addr_ptr, unsigned short zero_bits_64, SIZE_T commit_size, const LARGE_INTEGER *offset_ptr, SIZE_T *size_ptr, ULONG alloc_type, ULONG protect, pe_image_info_t *image_info ) DECLSPEC_HIDDEN; extern void virtual_get_system_info( SYSTEM_BASIC_INFORMATION *info ) DECLSPEC_HIDDEN; diff --git a/dlls/ntdll/server.c b/dlls/ntdll/server.c index 16e73d497c4..204370a1b77 100644 --- a/dlls/ntdll/server.c +++ b/dlls/ntdll/server.c @@ -431,7 +431,7 @@ BOOL invoke_apc( const apc_call_t *call, apc_result_t *result ) if ((ULONG_PTR)addr == call->virtual_alloc.addr && size == call->virtual_alloc.size) { result->virtual_alloc.status = virtual_alloc_aligned( &addr, - call->virtual_alloc.zero_bits, &size, + call->virtual_alloc.zero_bits_64, &size, call->virtual_alloc.op_type, call->virtual_alloc.prot, 0 ); @@ -538,7 +538,7 @@ BOOL invoke_apc( const apc_call_t *call, apc_result_t *result ) offset.QuadPart = call->map_view.offset; result->map_view.status = virtual_map_section( wine_server_ptr_handle(call->map_view.handle), &addr, - call->map_view.zero_bits, 0, + call->map_view.zero_bits_64, 0, &offset, &size, call->map_view.alloc_type, call->map_view.prot, &image_info ); diff --git a/dlls/ntdll/virtual.c b/dlls/ntdll/virtual.c index 57536eb6295..965b4a55ce8 100644 --- a/dlls/ntdll/virtual.c +++ b/dlls/ntdll/virtual.c @@ -418,6 +418,38 @@ static inline UINT_PTR get_mask( ULONG alignment ) }
+/*********************************************************************** + * zero_bits_win_to_64 + * + * Convert from Windows hybrid 32bit-based / bitmask to 64bit-based format + */ +static inline unsigned short zero_bits_win_to_64( ULONG_PTR zero_bits ) +{ + UINT_PTR mask; + unsigned short zero_bits_64; + + if (zero_bits == 0) return 0; + if (zero_bits < 32) return 32 + zero_bits; + mask = zero_bits; + +#ifdef HAVE___BUILTIN_CLZLL + zero_bits_64 = __builtin_clzll( mask ); +#else + zero_bits_64 = 63; +#ifdef _WIN64 + if (mask >> 32) { zero_bits_64 -= 32; mask >>= 32; } +#endif + if (mask >> 16) { zero_bits_64 -= 16; mask >>= 16; } + if (mask >> 8) { zero_bits_64 -= 8; mask >>= 8; } + if (mask >> 4) { zero_bits_64 -= 4; mask >>= 4; } + if (mask >> 2) { zero_bits_64 -= 2; mask >>= 2; } + if (mask >> 1) { zero_bits_64 -= 1; } +#endif + + return zero_bits_64; +} + + /*********************************************************************** * is_write_watch_range */ @@ -1083,7 +1115,7 @@ static NTSTATUS map_fixed_area( void *base, size_t size, unsigned int vprot ) * The csVirtual section must be held by caller. */ static NTSTATUS map_view( struct file_view **view_ret, void *base, size_t size, size_t alignment, - int top_down, unsigned int vprot, size_t zero_bits ) + int top_down, unsigned int vprot, unsigned short zero_bits_64 ) { void *ptr; NTSTATUS status; @@ -1102,7 +1134,7 @@ static NTSTATUS map_view( struct file_view **view_ret, void *base, size_t size, size_t view_size = size + mask + 1; struct alloc_area alloc;
- if (zero_bits) + if (zero_bits_64) FIXME("Unimplemented zero_bits parameter value\n");
alloc.size = size; @@ -1361,7 +1393,7 @@ static NTSTATUS map_pe_header( void *ptr, size_t size, int fd, BOOL *removable ) * * Map an executable (PE format) image into memory. */ -static NTSTATUS map_image( HANDLE hmapping, ACCESS_MASK access, int fd, int top_down, SIZE_T zero_bits, +static NTSTATUS map_image( HANDLE hmapping, ACCESS_MASK access, int fd, int top_down, unsigned short zero_bits_64, pe_image_info_t *image_info, int shared_fd, BOOL removable, PVOID *addr_ptr ) { IMAGE_DOS_HEADER *dos; @@ -1392,11 +1424,11 @@ static NTSTATUS map_image( HANDLE hmapping, ACCESS_MASK access, int fd, int top_
if (base >= (char *)address_space_start) /* make sure the DOS area remains free */ status = map_view( &view, base, total_size, 0, top_down, SEC_IMAGE | SEC_FILE | - VPROT_COMMITTED | VPROT_READ | VPROT_EXEC | VPROT_WRITECOPY, zero_bits ); + VPROT_COMMITTED | VPROT_READ | VPROT_EXEC | VPROT_WRITECOPY, zero_bits_64 );
if (status != STATUS_SUCCESS) status = map_view( &view, NULL, total_size, 0, top_down, SEC_IMAGE | SEC_FILE | - VPROT_COMMITTED | VPROT_READ | VPROT_EXEC | VPROT_WRITECOPY, zero_bits ); + VPROT_COMMITTED | VPROT_READ | VPROT_EXEC | VPROT_WRITECOPY, zero_bits_64 );
if (status != STATUS_SUCCESS) goto error;
@@ -1611,7 +1643,7 @@ static NTSTATUS map_image( HANDLE hmapping, ACCESS_MASK access, int fd, int top_ * * Map a file section into memory. */ -NTSTATUS virtual_map_section( HANDLE handle, PVOID *addr_ptr, ULONG zero_bits, SIZE_T commit_size, +NTSTATUS virtual_map_section( HANDLE handle, PVOID *addr_ptr, unsigned short zero_bits_64, SIZE_T commit_size, const LARGE_INTEGER *offset_ptr, SIZE_T *size_ptr, ULONG alloc_type, ULONG protect, pe_image_info_t *image_info ) { @@ -1673,14 +1705,14 @@ NTSTATUS virtual_map_section( HANDLE handle, PVOID *addr_ptr, ULONG zero_bits, S
if ((res = server_get_unix_fd( shared_file, FILE_READ_DATA|FILE_WRITE_DATA, &shared_fd, &shared_needs_close, NULL, NULL ))) goto done; - res = map_image( handle, access, unix_handle, alloc_type & MEM_TOP_DOWN, zero_bits, image_info, + res = map_image( handle, access, unix_handle, alloc_type & MEM_TOP_DOWN, zero_bits_64, image_info, shared_fd, needs_close, addr_ptr ); if (shared_needs_close) close( shared_fd ); close_handle( shared_file ); } else { - res = map_image( handle, access, unix_handle, alloc_type & MEM_TOP_DOWN, zero_bits, image_info, + res = map_image( handle, access, unix_handle, alloc_type & MEM_TOP_DOWN, zero_bits_64, image_info, -1, needs_close, addr_ptr ); } if (needs_close) close( unix_handle ); @@ -1718,7 +1750,7 @@ NTSTATUS virtual_map_section( HANDLE handle, PVOID *addr_ptr, ULONG zero_bits, S get_vprot_flags( protect, &vprot, sec_flags & SEC_IMAGE ); vprot |= sec_flags; if (!(sec_flags & SEC_RESERVE)) vprot |= VPROT_COMMITTED; - res = map_view( &view, *addr_ptr, size, 0, alloc_type & MEM_TOP_DOWN, vprot, zero_bits ); + res = map_view( &view, *addr_ptr, size, 0, alloc_type & MEM_TOP_DOWN, vprot, zero_bits_64 ); if (res) { server_leave_uninterrupted_section( &csVirtual, &sigset ); @@ -2506,6 +2538,7 @@ NTSTATUS WINAPI NtAllocateVirtualMemory( HANDLE process, PVOID *ret, ULONG_PTR z { SIZE_T size = *size_ptr; NTSTATUS status = STATUS_SUCCESS; + unsigned short zero_bits_64 = zero_bits_win_to_64( zero_bits );
TRACE("%p %p %08lx %x %08x\n", process, *ret, size, type, protect );
@@ -2520,12 +2553,12 @@ NTSTATUS WINAPI NtAllocateVirtualMemory( HANDLE process, PVOID *ret, ULONG_PTR z
memset( &call, 0, sizeof(call) );
- call.virtual_alloc.type = APC_VIRTUAL_ALLOC; - call.virtual_alloc.addr = wine_server_client_ptr( *ret ); - call.virtual_alloc.size = *size_ptr; - call.virtual_alloc.zero_bits = zero_bits; - call.virtual_alloc.op_type = type; - call.virtual_alloc.prot = protect; + call.virtual_alloc.type = APC_VIRTUAL_ALLOC; + call.virtual_alloc.addr = wine_server_client_ptr( *ret ); + call.virtual_alloc.size = *size_ptr; + call.virtual_alloc.zero_bits_64 = zero_bits_64; + call.virtual_alloc.op_type = type; + call.virtual_alloc.prot = protect; status = server_queue_process_apc( process, &call, &result ); if (status != STATUS_SUCCESS) return status;
@@ -2537,7 +2570,7 @@ NTSTATUS WINAPI NtAllocateVirtualMemory( HANDLE process, PVOID *ret, ULONG_PTR z return result.virtual_alloc.status; }
- return virtual_alloc_aligned( ret, zero_bits, size_ptr, type, protect, 0 ); + return virtual_alloc_aligned( ret, zero_bits_64, size_ptr, type, protect, 0 ); }
@@ -2546,7 +2579,7 @@ NTSTATUS WINAPI NtAllocateVirtualMemory( HANDLE process, PVOID *ret, ULONG_PTR z * * Same as NtAllocateVirtualMemory but with an alignment parameter */ -NTSTATUS virtual_alloc_aligned( PVOID *ret, ULONG zero_bits, SIZE_T *size_ptr, +NTSTATUS virtual_alloc_aligned( PVOID *ret, unsigned short zero_bits_64, SIZE_T *size_ptr, ULONG type, ULONG protect, ULONG alignment ) { void *base; @@ -2608,7 +2641,7 @@ NTSTATUS virtual_alloc_aligned( PVOID *ret, ULONG zero_bits, SIZE_T *size_ptr,
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, alignment, type & MEM_TOP_DOWN, vprot, zero_bits ); + else status = map_view( &view, base, size, alignment, type & MEM_TOP_DOWN, vprot, zero_bits_64 );
if (status == STATUS_SUCCESS) base = view->base; } @@ -3140,6 +3173,7 @@ NTSTATUS WINAPI NtMapViewOfSection( HANDLE handle, HANDLE process, PVOID *addr_p SIZE_T mask = get_mask( 0 ); pe_image_info_t image_info; LARGE_INTEGER offset; + unsigned short zero_bits_64 = zero_bits_win_to_64( zero_bits );
offset.QuadPart = offset_ptr ? offset_ptr->QuadPart : 0;
@@ -3178,14 +3212,14 @@ NTSTATUS WINAPI NtMapViewOfSection( HANDLE handle, HANDLE process, PVOID *addr_p
memset( &call, 0, sizeof(call) );
- call.map_view.type = APC_MAP_VIEW; - call.map_view.handle = wine_server_obj_handle( handle ); - call.map_view.addr = wine_server_client_ptr( *addr_ptr ); - call.map_view.size = *size_ptr; - call.map_view.offset = offset.QuadPart; - call.map_view.zero_bits = zero_bits; - call.map_view.alloc_type = alloc_type; - call.map_view.prot = protect; + call.map_view.type = APC_MAP_VIEW; + call.map_view.handle = wine_server_obj_handle( handle ); + call.map_view.addr = wine_server_client_ptr( *addr_ptr ); + call.map_view.size = *size_ptr; + call.map_view.offset = offset.QuadPart; + call.map_view.zero_bits_64 = zero_bits_64; + call.map_view.alloc_type = alloc_type; + call.map_view.prot = protect; res = server_queue_process_apc( process, &call, &result ); if (res != STATUS_SUCCESS) return res;
@@ -3197,7 +3231,7 @@ NTSTATUS WINAPI NtMapViewOfSection( HANDLE handle, HANDLE process, PVOID *addr_p return result.map_view.status; }
- return virtual_map_section( handle, addr_ptr, zero_bits, commit_size, + return virtual_map_section( handle, addr_ptr, zero_bits_64, commit_size, offset_ptr, size_ptr, alloc_type, protect, &image_info ); } diff --git a/server/protocol.def b/server/protocol.def index 8157199f2fa..6af0ae0cff8 100644 --- a/server/protocol.def +++ b/server/protocol.def @@ -496,12 +496,12 @@ typedef union } async_io; struct { - enum apc_type type; /* APC_VIRTUAL_ALLOC */ - unsigned int op_type; /* type of operation */ - client_ptr_t addr; /* requested address */ - mem_size_t size; /* allocation size */ - unsigned int zero_bits; /* allocation alignment */ - unsigned int prot; /* memory protection flags */ + enum apc_type type; /* APC_VIRTUAL_ALLOC */ + unsigned int op_type; /* type of operation */ + client_ptr_t addr; /* requested address */ + mem_size_t size; /* allocation size */ + unsigned int zero_bits_64; /* number of zero high bits */ + unsigned int prot; /* memory protection flags */ } virtual_alloc; struct { @@ -546,14 +546,14 @@ typedef union } virtual_unlock; struct { - enum apc_type type; /* APC_MAP_VIEW */ - obj_handle_t handle; /* mapping handle */ - client_ptr_t addr; /* requested address */ - mem_size_t size; /* allocation size */ - file_pos_t offset; /* file offset */ - unsigned int alloc_type;/* allocation type */ - unsigned short zero_bits; /* allocation alignment */ - unsigned short prot; /* memory protection flags */ + enum apc_type type; /* APC_MAP_VIEW */ + obj_handle_t handle; /* mapping handle */ + client_ptr_t addr; /* requested address */ + mem_size_t size; /* allocation size */ + file_pos_t offset; /* file offset */ + unsigned int alloc_type; /* allocation type */ + unsigned short zero_bits_64; /* number of zero high bits */ + unsigned short prot; /* memory protection flags */ } map_view; struct { diff --git a/server/trace.c b/server/trace.c index 0df649ea295..615542cff52 100644 --- a/server/trace.c +++ b/server/trace.c @@ -171,8 +171,8 @@ static void dump_apc_call( const char *prefix, const apc_call_t *call ) case APC_VIRTUAL_ALLOC: dump_uint64( "APC_VIRTUAL_ALLOC,addr==", &call->virtual_alloc.addr ); dump_uint64( ",size=", &call->virtual_alloc.size ); - fprintf( stderr, ",zero_bits=%u,op_type=%x,prot=%x", - call->virtual_alloc.zero_bits, call->virtual_alloc.op_type, + fprintf( stderr, ",zero_bits_64=%u,op_type=%x,prot=%x", + call->virtual_alloc.zero_bits_64, call->virtual_alloc.op_type, call->virtual_alloc.prot ); break; case APC_VIRTUAL_FREE: @@ -205,8 +205,8 @@ static void dump_apc_call( const char *prefix, const apc_call_t *call ) dump_uint64( ",addr=", &call->map_view.addr ); dump_uint64( ",size=", &call->map_view.size ); dump_uint64( ",offset=", &call->map_view.offset ); - fprintf( stderr, ",zero_bits=%u,alloc_type=%x,prot=%x", - call->map_view.zero_bits, call->map_view.alloc_type, call->map_view.prot ); + fprintf( stderr, ",zero_bits_64=%u,alloc_type=%x,prot=%x", + call->map_view.zero_bits_64, call->map_view.alloc_type, call->map_view.prot ); break; case APC_UNMAP_VIEW: dump_uint64( "APC_UNMAP_VIEW,addr=", &call->unmap_view.addr );
Signed-off-by: Huw Davies huw@codeweavers.com
Use alloc_area.limit field to limit the search in reserved areas to the desired memory range, or call find_free_area to get a pointer to a free memory region which matches the zero_bits constraint, then mmap it with MAP_FIXED flag.
Signed-off-by: Rémi Bernon rbernon@codeweavers.com --- dlls/ntdll/tests/virtual.c | 8 -------- dlls/ntdll/virtual.c | 22 +++++++++++++++++----- 2 files changed, 17 insertions(+), 13 deletions(-)
diff --git a/dlls/ntdll/tests/virtual.c b/dlls/ntdll/tests/virtual.c index 9eec912e24b..31eb66c1439 100644 --- a/dlls/ntdll/tests/virtual.c +++ b/dlls/ntdll/tests/virtual.c @@ -120,7 +120,6 @@ static void test_NtAllocateVirtualMemory(void) "NtAllocateVirtualMemory returned %08x\n", status); if (status == STATUS_SUCCESS) { - todo_wine_if(is_win64) ok(((UINT_PTR)addr2 >> (32 - zero_bits)) == 0, "NtAllocateVirtualMemory returned address: %p\n", addr2);
@@ -141,7 +140,6 @@ static void test_NtAllocateVirtualMemory(void) "NtAllocateVirtualMemory with %d zero_bits returned %08x\n", (int)zero_bits, status); if (status == STATUS_SUCCESS) { - todo_wine ok(((UINT_PTR)addr2 >> (32 - zero_bits)) == 0, "NtAllocateVirtualMemory with %d zero_bits returned address %p\n", (int)zero_bits, addr2);
@@ -156,7 +154,6 @@ static void test_NtAllocateVirtualMemory(void) addr2 = NULL; status = NtAllocateVirtualMemory(NtCurrentProcess(), &addr2, 21, &size, MEM_RESERVE | MEM_COMMIT, PAGE_EXECUTE_READWRITE); - todo_wine ok(status == STATUS_NO_MEMORY || status == STATUS_INVALID_PARAMETER, "NtAllocateVirtualMemory returned %08x\n", status); if (status == STATUS_SUCCESS) @@ -192,7 +189,6 @@ static void test_NtAllocateVirtualMemory(void) "NtAllocateVirtualMemory returned %08x\n", status); if (status == STATUS_SUCCESS) { - todo_wine ok(((UINT_PTR)addr2 & ~get_zero_bits_mask(zero_bits)) == 0 && ((UINT_PTR)addr2 & ~zero_bits) != 0, /* only the leading zeroes matter */ "NtAllocateVirtualMemory returned address %p\n", addr2); @@ -330,7 +326,6 @@ static void test_NtMapViewOfSection(void) "NtMapViewOfSection returned %08x\n", status); if (status == STATUS_SUCCESS) { - todo_wine_if(is_win64) ok(((UINT_PTR)ptr2 >> (32 - zero_bits)) == 0, "NtMapViewOfSection returned address: %p\n", ptr2);
@@ -348,7 +343,6 @@ static void test_NtMapViewOfSection(void) "NtMapViewOfSection with %d zero_bits returned %08x\n", (int)zero_bits, status); if (status == STATUS_SUCCESS) { - todo_wine ok(((UINT_PTR)ptr2 >> (32 - zero_bits)) == 0, "NtMapViewOfSection with %d zero_bits returned address %p\n", (int)zero_bits, ptr2);
@@ -362,7 +356,6 @@ static void test_NtMapViewOfSection(void) size = 0; offset.QuadPart = 0; status = NtMapViewOfSection(mapping, process, &ptr2, 21, 0, &offset, &size, 1, 0, PAGE_READWRITE); - todo_wine ok(status == STATUS_NO_MEMORY || status == STATUS_INVALID_PARAMETER, "NtMapViewOfSection returned %08x\n", status);
@@ -391,7 +384,6 @@ static void test_NtMapViewOfSection(void) "NtMapViewOfSection returned %08x\n", status); if (status == STATUS_SUCCESS) { - todo_wine ok(((UINT_PTR)ptr2 & ~get_zero_bits_mask(zero_bits)) == 0 && ((UINT_PTR)ptr2 & ~zero_bits) != 0, /* only the leading zeroes matter */ "NtMapViewOfSection returned address %p\n", ptr2); diff --git a/dlls/ntdll/virtual.c b/dlls/ntdll/virtual.c index 965b4a55ce8..116d8c5df30 100644 --- a/dlls/ntdll/virtual.c +++ b/dlls/ntdll/virtual.c @@ -450,6 +450,15 @@ static inline unsigned short zero_bits_win_to_64( ULONG_PTR zero_bits ) }
+/*********************************************************************** + * get_zero_bits_64_mask + */ +static inline UINT_PTR get_zero_bits_64_mask( USHORT zero_bits_64 ) +{ + return (UINT_PTR)((~(UINT64)0) >> zero_bits_64); +} + + /*********************************************************************** * is_write_watch_range */ @@ -1134,13 +1143,11 @@ static NTSTATUS map_view( struct file_view **view_ret, void *base, size_t size, size_t view_size = size + mask + 1; struct alloc_area alloc;
- if (zero_bits_64) - FIXME("Unimplemented zero_bits parameter value\n"); - alloc.size = size; alloc.mask = mask; alloc.top_down = top_down; - alloc.limit = user_space_limit; + alloc.limit = (void*)(get_zero_bits_64_mask( zero_bits_64 ) & (UINT_PTR)user_space_limit); + if (wine_mmap_enum_reserved_areas( alloc_reserved_area_callback, &alloc, top_down )) { ptr = alloc.result; @@ -1152,7 +1159,12 @@ static NTSTATUS map_view( struct file_view **view_ret, void *base, size_t size,
for (;;) { - if ((ptr = wine_anon_mmap( NULL, view_size, VIRTUAL_GetUnixProt(vprot), 0 )) == (void *)-1) + if (!zero_bits_64) + ptr = NULL; + else if (!(ptr = find_free_area( (void*)0, alloc.limit, view_size, mask, top_down ))) + return STATUS_NO_MEMORY; + + if ((ptr = wine_anon_mmap( ptr, view_size, VIRTUAL_GetUnixProt(vprot), ptr ? MAP_FIXED : 0 )) == (void *)-1) { if (errno == ENOMEM) return STATUS_NO_MEMORY; return STATUS_INVALID_PARAMETER;
Signed-off-by: Huw Davies huw@codeweavers.com