Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- dlls/ntdll/tests/virtual.c | 43 +++++++++++++++++++++++++++++++++++--- 1 file changed, 40 insertions(+), 3 deletions(-)
diff --git a/dlls/ntdll/tests/virtual.c b/dlls/ntdll/tests/virtual.c index aeef2ed8fb9..74e3facca13 100644 --- a/dlls/ntdll/tests/virtual.c +++ b/dlls/ntdll/tests/virtual.c @@ -264,6 +264,13 @@ static void test_NtAllocateVirtualMemory(void) ok(status == STATUS_SUCCESS, "NtFreeVirtualMemory failed %lx\n", status); ok( size == 0x10000, "wrong size %Ix\n", size ); ok( addr2 == addr1, "wrong addr %p\n", addr2 ); +} + +static void test_NtAllocateVirtualMemoryEx(void) +{ + void *addr1, *addr2; + NTSTATUS status; + SIZE_T size;
if (!pNtAllocateVirtualMemoryEx) { @@ -271,17 +278,26 @@ static void test_NtAllocateVirtualMemory(void) return; }
- /* simple allocation should succeed */ size = 0x1000; addr1 = NULL; status = pNtAllocateVirtualMemoryEx(NtCurrentProcess(), &addr1, &size, MEM_RESERVE | MEM_COMMIT, PAGE_EXECUTE_READWRITE, NULL, 0); - ok(status == STATUS_SUCCESS, "NtAllocateVirtualMemoryEx returned %08lx\n", status); + ok(status == STATUS_SUCCESS, "Unexpected status %08lx.\n", status); + + size = 0; + status = NtFreeVirtualMemory(NtCurrentProcess(), &addr2, &size, MEM_RELEASE); + ok(status == STATUS_SUCCESS, "Unexpected status %08lx.\n", status);
/* specifying a count of >0 with NULL parameters should fail */ status = pNtAllocateVirtualMemoryEx(NtCurrentProcess(), &addr1, &size, MEM_RESERVE | MEM_COMMIT, PAGE_EXECUTE_READWRITE, NULL, 1); - ok(status == STATUS_INVALID_PARAMETER, "NtAllocateVirtualMemoryEx returned %08lx\n", status); + ok(status == STATUS_INVALID_PARAMETER, "Unexpected status %08lx.\n", status); + + /* NULL process handle */ + size = 0x1000; + addr1 = NULL; + status = pNtAllocateVirtualMemoryEx(NULL, &addr1, &size, MEM_RESERVE | MEM_COMMIT, PAGE_EXECUTE_READWRITE, NULL, 0); + ok(status == STATUS_INVALID_HANDLE, "Unexpected status %08lx.\n", status); }
struct test_stack_size_thread_args @@ -1279,6 +1295,25 @@ static void test_syscalls(void) UnmapViewOfFile( ptr ); }
+static void test_NtFreeVirtualMemory(void) +{ + NTSTATUS status; + void *addr1; + SIZE_T size; + + size = 0x10000; + addr1 = NULL; + status = NtAllocateVirtualMemory(NtCurrentProcess(), &addr1, 0, &size, MEM_RESERVE, PAGE_READWRITE); + ok(status == STATUS_SUCCESS, "Unexpected status %08lx.\n", status); + + size = 0; + status = NtFreeVirtualMemory(NULL, &addr1, &size, MEM_RELEASE); + ok(status == STATUS_INVALID_HANDLE, "Unexpected status %08lx.\n", status); + + status = NtFreeVirtualMemory(NtCurrentProcess(), &addr1, &size, MEM_RELEASE); + ok(status == STATUS_SUCCESS, "Unexpected status %08lx.\n", status); +} + START_TEST(virtual) { HMODULE mod; @@ -1315,6 +1350,8 @@ START_TEST(virtual) if (!pIsWow64Process || !pIsWow64Process(NtCurrentProcess(), &is_wow64)) is_wow64 = FALSE;
test_NtAllocateVirtualMemory(); + test_NtAllocateVirtualMemoryEx(); + test_NtFreeVirtualMemory(); test_RtlCreateUserStack(); test_NtMapViewOfSection(); test_NtMapViewOfSectionEx();
Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- dlls/kernel32/tests/virtual.c | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-)
diff --git a/dlls/kernel32/tests/virtual.c b/dlls/kernel32/tests/virtual.c index 365194b9065..6d4d34e2e81 100644 --- a/dlls/kernel32/tests/virtual.c +++ b/dlls/kernel32/tests/virtual.c @@ -78,11 +78,21 @@ static void test_VirtualAllocEx(void) char *src, *dst; SIZE_T bytes_written = 0, bytes_read = 0, i; void *addr1, *addr2; - BOOL b; + BOOL b, ret; DWORD old_prot; MEMORY_BASIC_INFORMATION info; HANDLE hProcess;
+ /* Same process */ + addr1 = VirtualAllocEx(GetCurrentProcess(), NULL, alloc_size, MEM_COMMIT, PAGE_EXECUTE_READWRITE); + ok(!!addr1, "Failed to allocated, error %lu.\n", GetLastError()); + ret = VirtualFreeEx(NULL, addr1, 0, MEM_RELEASE); + ok(!ret && GetLastError() == ERROR_INVALID_HANDLE, "Unexpected value %d, error %lu.\n", ret, GetLastError()); + addr2 = VirtualAllocEx(NULL, NULL, alloc_size, MEM_COMMIT, PAGE_EXECUTE_READWRITE); + ok(!addr2 && GetLastError() == ERROR_INVALID_HANDLE, "Unexpected value %p, error %lu.\n", addr2, GetLastError()); + ret = VirtualFreeEx(GetCurrentProcess(), addr1, 0, MEM_RELEASE); + ok(ret, "Unexpected value %d, error %lu.\n", ret, GetLastError()); + hProcess = create_target_process("sleep"); ok(hProcess != NULL, "Can't start process\n");
Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- dlls/kernelbase/tests/process.c | 73 +++++++++++++++++++++++++++++++++ include/winnt.h | 23 +++++++---- 2 files changed, 88 insertions(+), 8 deletions(-)
diff --git a/dlls/kernelbase/tests/process.c b/dlls/kernelbase/tests/process.c index bacf9057836..52c481a59e8 100644 --- a/dlls/kernelbase/tests/process.c +++ b/dlls/kernelbase/tests/process.c @@ -33,6 +33,7 @@ static BOOL (WINAPI *pCompareObjectHandles)(HANDLE, HANDLE); static LPVOID (WINAPI *pMapViewOfFile3)(HANDLE, HANDLE, PVOID, ULONG64 offset, SIZE_T size, ULONG, ULONG, MEM_EXTENDED_PARAMETER *, ULONG); +static LPVOID (WINAPI *pVirtualAlloc2)(HANDLE, void *, SIZE_T, DWORD, DWORD, MEM_EXTENDED_PARAMETER *, ULONG);
static void test_CompareObjectHandles(void) { @@ -125,6 +126,76 @@ static void test_MapViewOfFile3(void) ok(ret, "Failed to delete a test file.\n"); }
+static void test_VirtualAlloc2(void) +{ + void *placeholder1, *placeholder2, *view1, *view2, *addr; + MEMORY_BASIC_INFORMATION info; + HANDLE section; + SIZE_T size; + BOOL ret; + + if (!pVirtualAlloc2) + { + win_skip("VirtualAlloc2() is not supported.\n"); + return; + } + + size = 0x80000; + addr = pVirtualAlloc2(NULL, NULL, size, MEM_COMMIT, PAGE_EXECUTE_READWRITE, NULL, 0); + todo_wine + ok(!!addr, "Failed to allocate, error %lu.\n", GetLastError()); + ret = VirtualFree(addr, 0, MEM_RELEASE); + todo_wine + ok(ret, "Unexpected return value %d, error %lu.\n", ret, GetLastError()); + + /* Placeholder splitting functionality */ + placeholder1 = pVirtualAlloc2(NULL, NULL, 2 * size, MEM_RESERVE_PLACEHOLDER | MEM_RESERVE, PAGE_NOACCESS, NULL, 0); + todo_wine + ok(!!placeholder1, "Failed to create a placeholder range.\n"); + if (!placeholder1) return; + + memset(&info, 0, sizeof(info)); + VirtualQuery(placeholder1, &info, sizeof(info)); + ok(info.AllocationProtect == PAGE_NOACCESS, "Unexpected protection %#lx.\n", info.AllocationProtect); + ok(info.State == MEM_RESERVE, "Unexpected state %#lx.\n", info.State); + ok(info.Type == MEM_PRIVATE, "Unexpected type %#lx.\n", info.Type); + ok(info.RegionSize == 2 * size, "Unexpected size.\n"); + + ret = VirtualFree(placeholder1, size, MEM_RELEASE | MEM_PRESERVE_PLACEHOLDER); + ok(ret, "Failed to split placeholder.\n"); + + memset(&info, 0, sizeof(info)); + VirtualQuery(placeholder1, &info, sizeof(info)); + ok(info.AllocationProtect == PAGE_NOACCESS, "Unexpected protection %#lx.\n", info.AllocationProtect); + ok(info.State == MEM_RESERVE, "Unexpected state %#lx.\n", info.State); + ok(info.Type == MEM_PRIVATE, "Unexpected type %#lx.\n", info.Type); + ok(info.RegionSize == size, "Unexpected size.\n"); + + placeholder2 = (void *)((BYTE *)placeholder1 + size); + memset(&info, 0, sizeof(info)); + VirtualQuery(placeholder2, &info, sizeof(info)); + ok(info.AllocationProtect == PAGE_NOACCESS, "Unexpected protection %#lx.\n", info.AllocationProtect); + ok(info.State == MEM_RESERVE, "Unexpected state %#lx.\n", info.State); + ok(info.Type == MEM_PRIVATE, "Unexpected type %#lx.\n", info.Type); + ok(info.RegionSize == size, "Unexpected size.\n"); + + section = CreateFileMappingW(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0, size, NULL); + ok(!!section, "Failed to create a section.\n"); + + view1 = pMapViewOfFile3(section, NULL, placeholder1, 0, size, MEM_REPLACE_PLACEHOLDER, PAGE_READWRITE, NULL, 0); + ok(!!view1, "Failed to map a section.\n"); + + view2 = pMapViewOfFile3(section, NULL, placeholder2, 0, size, MEM_REPLACE_PLACEHOLDER, PAGE_READWRITE, NULL, 0); + ok(!!view2, "Failed to map a section.\n"); + + CloseHandle(section); + UnmapViewOfFile(view1); + UnmapViewOfFile(view2); + + VirtualFree(placeholder1, 0, MEM_RELEASE); + VirtualFree(placeholder2, 0, MEM_RELEASE); +} + START_TEST(process) { HMODULE hmod; @@ -136,7 +207,9 @@ START_TEST(process) hmod = GetModuleHandleA("kernelbase.dll"); pCompareObjectHandles = (void *)GetProcAddress(hmod, "CompareObjectHandles"); pMapViewOfFile3 = (void *)GetProcAddress(hmod, "MapViewOfFile3"); + pVirtualAlloc2 = (void *)GetProcAddress(hmod, "VirtualAlloc2");
test_CompareObjectHandles(); test_MapViewOfFile3(); + test_VirtualAlloc2(); } diff --git a/include/winnt.h b/include/winnt.h index 5ca106d1031..7aafbcf0cfe 100644 --- a/include/winnt.h +++ b/include/winnt.h @@ -806,18 +806,25 @@ typedef struct _WIN32_MEMORY_RANGE_ENTRY #define PAGE_NOCACHE 0x200 #define PAGE_WRITECOMBINE 0x400
-#define MEM_COMMIT 0x00001000 -#define MEM_RESERVE 0x00002000 -#define MEM_DECOMMIT 0x00004000 -#define MEM_RELEASE 0x00008000 +#define MEM_COMMIT 0x00001000 +#define MEM_RESERVE 0x00002000 +#define MEM_REPLACE_PLACEHOLDER 0x00004000 +#define MEM_RESERVE_PLACEHOLDER 0x00040000 +#define MEM_RESET 0x00080000 +#define MEM_TOP_DOWN 0x00100000 +#define MEM_PHYSICAL 0x00400000 +#define MEM_RESET_UNDO 0x10000000 +#define MEM_LARGE_PAGES 0x20000000 + +#define MEM_COALESCE_PLACEHOLDERS 0x00000001 +#define MEM_PRESERVE_PLACEHOLDER 0x00000002 +#define MEM_DECOMMIT 0x00004000 +#define MEM_RELEASE 0x00008000 + #define MEM_FREE 0x00010000 #define MEM_PRIVATE 0x00020000 #define MEM_MAPPED 0x00040000 -#define MEM_RESET 0x00080000 -#define MEM_TOP_DOWN 0x00100000 #define MEM_WRITE_WATCH 0x00200000 -#define MEM_PHYSICAL 0x00400000 -#define MEM_LARGE_PAGES 0x20000000 #define MEM_4MB_PAGES 0x80000000
#define SEC_FILE 0x00800000
Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- dlls/kernelbase/memory.c | 1 + dlls/kernelbase/tests/process.c | 2 -- 2 files changed, 1 insertion(+), 2 deletions(-)
diff --git a/dlls/kernelbase/memory.c b/dlls/kernelbase/memory.c index 656569220fa..416d7b52a16 100644 --- a/dlls/kernelbase/memory.c +++ b/dlls/kernelbase/memory.c @@ -352,6 +352,7 @@ LPVOID WINAPI DECLSPEC_HOTPATCH VirtualAlloc2( HANDLE process, void *addr, SIZE_ { LPVOID ret = addr;
+ if (!process) process = GetCurrentProcess(); if (!set_ntstatus( NtAllocateVirtualMemoryEx( process, &ret, &size, type, protect, parameters, count ))) return NULL; return ret; diff --git a/dlls/kernelbase/tests/process.c b/dlls/kernelbase/tests/process.c index 52c481a59e8..b83a25015b2 100644 --- a/dlls/kernelbase/tests/process.c +++ b/dlls/kernelbase/tests/process.c @@ -142,10 +142,8 @@ static void test_VirtualAlloc2(void)
size = 0x80000; addr = pVirtualAlloc2(NULL, NULL, size, MEM_COMMIT, PAGE_EXECUTE_READWRITE, NULL, 0); - todo_wine ok(!!addr, "Failed to allocate, error %lu.\n", GetLastError()); ret = VirtualFree(addr, 0, MEM_RELEASE); - todo_wine ok(ret, "Unexpected return value %d, error %lu.\n", ret, GetLastError());
/* Placeholder splitting functionality */
Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- dlls/ntdll/tests/virtual.c | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+)
diff --git a/dlls/ntdll/tests/virtual.c b/dlls/ntdll/tests/virtual.c index 74e3facca13..136d5a6fd4e 100644 --- a/dlls/ntdll/tests/virtual.c +++ b/dlls/ntdll/tests/virtual.c @@ -264,6 +264,12 @@ static void test_NtAllocateVirtualMemory(void) ok(status == STATUS_SUCCESS, "NtFreeVirtualMemory failed %lx\n", status); ok( size == 0x10000, "wrong size %Ix\n", size ); ok( addr2 == addr1, "wrong addr %p\n", addr2 ); + + /* Placeholder functionality */ + size = 0x10000; + addr1 = NULL; + status = NtAllocateVirtualMemory(NtCurrentProcess(), &addr1, 0, &size, MEM_RESERVE | MEM_RESERVE_PLACEHOLDER, PAGE_NOACCESS); + ok(status == STATUS_INVALID_PARAMETER, "Unexpected status %08lx.\n", status); }
static void test_NtAllocateVirtualMemoryEx(void) @@ -298,6 +304,24 @@ static void test_NtAllocateVirtualMemoryEx(void) addr1 = NULL; status = pNtAllocateVirtualMemoryEx(NULL, &addr1, &size, MEM_RESERVE | MEM_COMMIT, PAGE_EXECUTE_READWRITE, NULL, 0); ok(status == STATUS_INVALID_HANDLE, "Unexpected status %08lx.\n", status); + + /* Placeholder functionality */ + size = 0x10000; + addr1 = NULL; + status = NtAllocateVirtualMemory(NtCurrentProcess(), &addr1, 0, &size, MEM_RESERVE | MEM_RESERVE_PLACEHOLDER, PAGE_NOACCESS); + ok(status == STATUS_INVALID_PARAMETER, "Unexpected status %08lx.\n", status); + + status = pNtAllocateVirtualMemoryEx(NtCurrentProcess(), &addr1, &size, MEM_RESERVE | MEM_RESERVE_PLACEHOLDER, + PAGE_NOACCESS, NULL, 0); + todo_wine + ok(status == STATUS_SUCCESS, "Unexpected status %08lx.\n", status); + + if (addr1) + { + size = 0; + status = NtFreeVirtualMemory(NtCurrentProcess(), &addr1, &size, MEM_RELEASE); + ok(status == STATUS_SUCCESS, "Unexpected status %08lx.\n", status); + } }
struct test_stack_size_thread_args
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=115153
Your paranoid android.
=== w7u_2qxl (32 bit report) ===
ntdll: virtual.c:272: Test failed: Unexpected status c00000f3.
=== w7u_adm (32 bit report) ===
ntdll: virtual.c:272: Test failed: Unexpected status c00000f3.
=== w7u_el (32 bit report) ===
ntdll: virtual.c:272: Test failed: Unexpected status c00000f3.
=== w8 (32 bit report) ===
ntdll: virtual.c:272: Test failed: Unexpected status c00000f3.
=== w8adm (32 bit report) ===
ntdll: virtual.c:272: Test failed: Unexpected status c00000f3.
=== w864 (32 bit report) ===
ntdll: virtual.c:272: Test failed: Unexpected status c00000f3.
=== w1064v1507 (32 bit report) ===
ntdll: virtual.c:272: Test failed: Unexpected status c00000f3.
=== w864 (64 bit report) ===
ntdll: virtual.c:272: Test failed: Unexpected status c00000f3.
=== w1064v1507 (64 bit report) ===
ntdll: virtual.c:272: Test failed: Unexpected status c00000f3.