Also add some tests for three different ways of splitting the region.
From: Nikolay Sivov nsivov@codeweavers.com
Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- dlls/kernel32/tests/virtual.c | 36 ---------------------- dlls/kernelbase/tests/process.c | 54 +++++++++++++++++++++++++++------ 2 files changed, 45 insertions(+), 45 deletions(-)
diff --git a/dlls/kernel32/tests/virtual.c b/dlls/kernel32/tests/virtual.c index 6d4d34e2e81..9b3c8228a3f 100644 --- a/dlls/kernel32/tests/virtual.c +++ b/dlls/kernel32/tests/virtual.c @@ -50,7 +50,6 @@ static ULONG (WINAPI *pRtlRemoveVectoredExceptionHandler)(PVOID); static BOOL (WINAPI *pGetProcessDEPPolicy)(HANDLE, LPDWORD, PBOOL); static BOOL (WINAPI *pIsWow64Process)(HANDLE, PBOOL); static NTSTATUS (WINAPI *pNtProtectVirtualMemory)(HANDLE, PVOID *, SIZE_T *, ULONG, ULONG *); -static PVOID (WINAPI *pVirtualAllocFromApp)(PVOID, SIZE_T, DWORD, DWORD);
/* ############################### */
@@ -454,39 +453,6 @@ static void test_VirtualAlloc(void) ok(VirtualFree(addr1, 0, MEM_RELEASE), "VirtualFree failed\n"); }
-static void test_VirtualAllocFromApp(void) -{ - void *p; - BOOL ret; - if (!pVirtualAllocFromApp) - { - win_skip("VirtualAllocFromApp is not available.\n"); - return; - } - - p = GetProcAddress(hkernel32, "VirtualAllocFromApp"); - ok(!p, "Found VirtualAllocFromApp in kernel32.dll.\n"); - - SetLastError(0xdeadbeef); - p = pVirtualAllocFromApp(NULL, 0x1000, MEM_RESERVE, PAGE_READWRITE); - ok(p && GetLastError() == 0xdeadbeef, "Got unexpected mem %p, GetLastError() %lu.\n", p, GetLastError()); - ret = VirtualFree(p, 0, MEM_RELEASE); - ok(ret, "Got unexpected ret %#x, GetLastError() %lu.\n", ret, GetLastError()); - - SetLastError(0xdeadbeef); - p = pVirtualAllocFromApp(NULL, 0x1000, MEM_RESERVE, PAGE_EXECUTE); - ok(!p && GetLastError() == ERROR_INVALID_PARAMETER, "Got unexpected mem %p, GetLastError() %lu.\n", - p, GetLastError()); - SetLastError(0xdeadbeef); - p = pVirtualAllocFromApp(NULL, 0x1000, MEM_RESERVE, PAGE_EXECUTE_READ); - ok(!p && GetLastError() == ERROR_INVALID_PARAMETER, "Got unexpected mem %p, GetLastError() %lu.\n", - p, GetLastError()); - SetLastError(0xdeadbeef); - p = pVirtualAllocFromApp(NULL, 0x1000, MEM_RESERVE, PAGE_EXECUTE_READWRITE); - ok(!p && GetLastError() == ERROR_INVALID_PARAMETER, "Got unexpected mem %p, GetLastError() %lu.\n", - p, GetLastError()); -} - static void test_MapViewOfFile(void) { static const char testfile[] = "testfile.xxx"; @@ -4304,7 +4270,6 @@ START_TEST(virtual) pRtlAddVectoredExceptionHandler = (void *)GetProcAddress( hntdll, "RtlAddVectoredExceptionHandler" ); pRtlRemoveVectoredExceptionHandler = (void *)GetProcAddress( hntdll, "RtlRemoveVectoredExceptionHandler" ); pNtProtectVirtualMemory = (void *)GetProcAddress( hntdll, "NtProtectVirtualMemory" ); - pVirtualAllocFromApp = (void *)GetProcAddress( hkernelbase, "VirtualAllocFromApp" );
GetSystemInfo(&si); trace("system page size %#lx\n", si.dwPageSize); @@ -4319,7 +4284,6 @@ START_TEST(virtual) test_VirtualProtect(); test_VirtualAllocEx(); test_VirtualAlloc(); - test_VirtualAllocFromApp(); test_MapViewOfFile(); test_NtAreMappedFilesTheSame(); test_CreateFileMapping(); diff --git a/dlls/kernelbase/tests/process.c b/dlls/kernelbase/tests/process.c index b83a25015b2..90c4c4c26e1 100644 --- a/dlls/kernelbase/tests/process.c +++ b/dlls/kernelbase/tests/process.c @@ -34,6 +34,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 PVOID (WINAPI *pVirtualAllocFromApp)(PVOID, SIZE_T, DWORD, DWORD);
static void test_CompareObjectHandles(void) { @@ -194,20 +195,55 @@ static void test_VirtualAlloc2(void) VirtualFree(placeholder2, 0, MEM_RELEASE); }
-START_TEST(process) +static void test_VirtualAllocFromApp(void) { - HMODULE hmod; + BOOL ret; + void *p;
- hmod = GetModuleHandleA("kernel32.dll"); - pCompareObjectHandles = (void *)GetProcAddress(hmod, "CompareObjectHandles"); - ok(!pCompareObjectHandles, "expected CompareObjectHandles only in kernelbase.dll\n"); + if (!pVirtualAllocFromApp) + { + win_skip("VirtualAllocFromApp is not available.\n"); + return; + }
- hmod = GetModuleHandleA("kernelbase.dll"); - pCompareObjectHandles = (void *)GetProcAddress(hmod, "CompareObjectHandles"); - pMapViewOfFile3 = (void *)GetProcAddress(hmod, "MapViewOfFile3"); - pVirtualAlloc2 = (void *)GetProcAddress(hmod, "VirtualAlloc2"); + SetLastError(0xdeadbeef); + p = pVirtualAllocFromApp(NULL, 0x1000, MEM_RESERVE, PAGE_READWRITE); + ok(p && GetLastError() == 0xdeadbeef, "Got unexpected mem %p, GetLastError() %lu.\n", p, GetLastError()); + ret = VirtualFree(p, 0, MEM_RELEASE); + ok(ret, "Got unexpected ret %#x, GetLastError() %lu.\n", ret, GetLastError()); + + SetLastError(0xdeadbeef); + p = pVirtualAllocFromApp(NULL, 0x1000, MEM_RESERVE, PAGE_EXECUTE); + ok(!p && GetLastError() == ERROR_INVALID_PARAMETER, "Got unexpected mem %p, GetLastError() %lu.\n", + p, GetLastError()); + SetLastError(0xdeadbeef); + p = pVirtualAllocFromApp(NULL, 0x1000, MEM_RESERVE, PAGE_EXECUTE_READ); + ok(!p && GetLastError() == ERROR_INVALID_PARAMETER, "Got unexpected mem %p, GetLastError() %lu.\n", + p, GetLastError()); + SetLastError(0xdeadbeef); + p = pVirtualAllocFromApp(NULL, 0x1000, MEM_RESERVE, PAGE_EXECUTE_READWRITE); + ok(!p && GetLastError() == ERROR_INVALID_PARAMETER, "Got unexpected mem %p, GetLastError() %lu.\n", + p, GetLastError()); +} + +static void init_funcs(void) +{ + HMODULE hmod = GetModuleHandleA("kernelbase.dll"); + +#define X(f) { p##f = (void*)GetProcAddress(hmod, #f); } + X(CompareObjectHandles); + X(MapViewOfFile3); + X(VirtualAlloc2); + X(VirtualAllocFromApp); +#undef X +} + +START_TEST(process) +{ + init_funcs();
test_CompareObjectHandles(); test_MapViewOfFile3(); test_VirtualAlloc2(); + test_VirtualAllocFromApp(); }
From: Nikolay Sivov nsivov@codeweavers.com
Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- dlls/kernelbase/kernelbase.spec | 1 + dlls/kernelbase/memory.c | 32 +++++++++++++++-- dlls/kernelbase/tests/process.c | 63 ++++++++++++++++++++++++++------- include/winbase.h | 1 + 4 files changed, 83 insertions(+), 14 deletions(-)
diff --git a/dlls/kernelbase/kernelbase.spec b/dlls/kernelbase/kernelbase.spec index 7109628a678..d4b5b5d3eb8 100644 --- a/dlls/kernelbase/kernelbase.spec +++ b/dlls/kernelbase/kernelbase.spec @@ -1707,6 +1707,7 @@ # @ stub VerifyPackageRelativeApplicationId # @ stub VerifyScripts @ stdcall VirtualAlloc2(long ptr long long long ptr long) +@ stdcall VirtualAlloc2FromApp(long ptr long long long ptr long) @ stdcall VirtualAlloc(ptr long long long) @ stdcall VirtualAllocEx(long ptr long long long) @ stdcall VirtualAllocExNuma(long ptr long long long long) diff --git a/dlls/kernelbase/memory.c b/dlls/kernelbase/memory.c index cac456d01be..736d3642995 100644 --- a/dlls/kernelbase/memory.c +++ b/dlls/kernelbase/memory.c @@ -358,6 +358,35 @@ LPVOID WINAPI DECLSPEC_HOTPATCH VirtualAlloc2( HANDLE process, void *addr, SIZE_ return ret; }
+static BOOL is_exec_prot( DWORD protect ) +{ + return protect == PAGE_EXECUTE || protect == PAGE_EXECUTE_READ || protect == PAGE_EXECUTE_READWRITE + || protect == PAGE_EXECUTE_WRITECOPY; +} + +/*********************************************************************** + * VirtualAlloc2FromApp (kernelbase.@) + */ +LPVOID WINAPI DECLSPEC_HOTPATCH VirtualAlloc2FromApp( HANDLE process, void *addr, SIZE_T size, + DWORD type, DWORD protect, MEM_EXTENDED_PARAMETER *parameters, ULONG count ) +{ + LPVOID ret = addr; + + TRACE_(virtual)( "addr %p, size %p, type %#lx, protect %#lx, params %p, count %lu.\n", addr, (void *)size, type, protect, + parameters, count ); + + if (is_exec_prot( protect )) + { + SetLastError( ERROR_INVALID_PARAMETER ); + return NULL; + } + + if (!process) process = GetCurrentProcess(); + if (!set_ntstatus( NtAllocateVirtualMemoryEx( process, &ret, &size, type, protect, parameters, count ))) + return NULL; + return ret; +} +
/*********************************************************************** * VirtualAllocFromApp (kernelbase.@) @@ -369,8 +398,7 @@ LPVOID WINAPI DECLSPEC_HOTPATCH VirtualAllocFromApp( void *addr, SIZE_T size,
TRACE_(virtual)( "addr %p, size %p, type %#lx, protect %#lx.\n", addr, (void *)size, type, protect );
- if (protect == PAGE_EXECUTE || protect == PAGE_EXECUTE_READ || protect == PAGE_EXECUTE_READWRITE - || protect == PAGE_EXECUTE_WRITECOPY) + if (is_exec_prot( protect )) { SetLastError( ERROR_INVALID_PARAMETER ); return NULL; diff --git a/dlls/kernelbase/tests/process.c b/dlls/kernelbase/tests/process.c index 90c4c4c26e1..bb1de49049d 100644 --- a/dlls/kernelbase/tests/process.c +++ b/dlls/kernelbase/tests/process.c @@ -34,6 +34,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 LPVOID (WINAPI *pVirtualAlloc2FromApp)(HANDLE, void *, SIZE_T, DWORD, DWORD, MEM_EXTENDED_PARAMETER *, ULONG); static PVOID (WINAPI *pVirtualAllocFromApp)(PVOID, SIZE_T, DWORD, DWORD);
static void test_CompareObjectHandles(void) @@ -197,6 +198,14 @@ static void test_VirtualAlloc2(void)
static void test_VirtualAllocFromApp(void) { + static const DWORD prot[] = + { + PAGE_EXECUTE, + PAGE_EXECUTE_READ, + PAGE_EXECUTE_READWRITE, + PAGE_EXECUTE_WRITECOPY, + }; + unsigned int i; BOOL ret; void *p;
@@ -212,18 +221,46 @@ static void test_VirtualAllocFromApp(void) ret = VirtualFree(p, 0, MEM_RELEASE); ok(ret, "Got unexpected ret %#x, GetLastError() %lu.\n", ret, GetLastError());
- SetLastError(0xdeadbeef); - p = pVirtualAllocFromApp(NULL, 0x1000, MEM_RESERVE, PAGE_EXECUTE); - ok(!p && GetLastError() == ERROR_INVALID_PARAMETER, "Got unexpected mem %p, GetLastError() %lu.\n", - p, GetLastError()); - SetLastError(0xdeadbeef); - p = pVirtualAllocFromApp(NULL, 0x1000, MEM_RESERVE, PAGE_EXECUTE_READ); - ok(!p && GetLastError() == ERROR_INVALID_PARAMETER, "Got unexpected mem %p, GetLastError() %lu.\n", - p, GetLastError()); - SetLastError(0xdeadbeef); - p = pVirtualAllocFromApp(NULL, 0x1000, MEM_RESERVE, PAGE_EXECUTE_READWRITE); - ok(!p && GetLastError() == ERROR_INVALID_PARAMETER, "Got unexpected mem %p, GetLastError() %lu.\n", - p, GetLastError()); + for (i = 0; i < ARRAY_SIZE(prot); ++i) + { + SetLastError(0xdeadbeef); + p = pVirtualAllocFromApp(NULL, 0x1000, MEM_RESERVE, prot[i]); + ok(!p && GetLastError() == ERROR_INVALID_PARAMETER, "Got unexpected mem %p, GetLastError() %lu.\n", + p, GetLastError()); + } +} + +static void test_VirtualAlloc2FromApp(void) +{ + static const DWORD prot[] = + { + PAGE_EXECUTE, + PAGE_EXECUTE_READ, + PAGE_EXECUTE_READWRITE, + PAGE_EXECUTE_WRITECOPY, + }; + unsigned int i; + void *addr; + BOOL ret; + + if (!pVirtualAlloc2FromApp) + { + win_skip("VirtualAlloc2FromApp is not available.\n"); + return; + } + + addr = pVirtualAlloc2FromApp(NULL, NULL, 0x1000, MEM_COMMIT, PAGE_READWRITE, NULL, 0); + ok(!!addr, "Failed to allocate, error %lu.\n", GetLastError()); + ret = VirtualFree(addr, 0, MEM_RELEASE); + ok(ret, "Unexpected return value %d, error %lu.\n", ret, GetLastError()); + + for (i = 0; i < ARRAY_SIZE(prot); ++i) + { + SetLastError(0xdeadbeef); + addr = pVirtualAlloc2FromApp(NULL, NULL, 0x1000, MEM_COMMIT, prot[i], NULL, 0); + ok(!addr && GetLastError() == ERROR_INVALID_PARAMETER, "Got unexpected mem %p, GetLastError() %lu.\n", + addr, GetLastError()); + } }
static void init_funcs(void) @@ -234,6 +271,7 @@ static void init_funcs(void) X(CompareObjectHandles); X(MapViewOfFile3); X(VirtualAlloc2); + X(VirtualAlloc2FromApp); X(VirtualAllocFromApp); #undef X } @@ -246,4 +284,5 @@ START_TEST(process) test_MapViewOfFile3(); test_VirtualAlloc2(); test_VirtualAllocFromApp(); + test_VirtualAlloc2FromApp(); } diff --git a/include/winbase.h b/include/winbase.h index a400816c4d3..bf191153ddc 100644 --- a/include/winbase.h +++ b/include/winbase.h @@ -2756,6 +2756,7 @@ WINBASEAPI BOOL WINAPI VerifyVersionInfoW(LPOSVERSIONINFOEXW,DWORD,DWORDL #define VerifyVersionInfo WINELIB_NAME_AW(VerifyVersionInfo) WINBASEAPI LPVOID WINAPI VirtualAlloc(LPVOID,SIZE_T,DWORD,DWORD); WINBASEAPI LPVOID WINAPI VirtualAlloc2(HANDLE,LPVOID,SIZE_T,DWORD,DWORD,MEM_EXTENDED_PARAMETER*,ULONG); +WINBASEAPI LPVOID WINAPI VirtualAlloc2FromApp(HANDLE,LPVOID,SIZE_T,DWORD,DWORD,MEM_EXTENDED_PARAMETER*,ULONG); WINBASEAPI LPVOID WINAPI VirtualAllocEx(HANDLE,LPVOID,SIZE_T,DWORD,DWORD); WINBASEAPI LPVOID WINAPI VirtualAllocExNuma(HANDLE,void*,SIZE_T,DWORD,DWORD,DWORD); WINBASEAPI LPVOID WINAPI VirtualAllocFromApp(LPVOID,SIZE_T,DWORD,DWORD);
From: Nikolay Sivov nsivov@codeweavers.com
Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- dlls/kernelbase/tests/process.c | 61 +++++++++++++++++++++++++++++++++ 1 file changed, 61 insertions(+)
diff --git a/dlls/kernelbase/tests/process.c b/dlls/kernelbase/tests/process.c index bb1de49049d..62debfb9861 100644 --- a/dlls/kernelbase/tests/process.c +++ b/dlls/kernelbase/tests/process.c @@ -128,10 +128,23 @@ static void test_MapViewOfFile3(void) ok(ret, "Failed to delete a test file.\n"); }
+#define check_region_size(p, s) check_region_size_(p, s, __LINE__) +static void check_region_size_(void *p, SIZE_T s, unsigned int line) +{ + MEMORY_BASIC_INFORMATION info; + SIZE_T ret; + + memset(&info, 0, sizeof(info)); + ret = VirtualQuery(p, &info, sizeof(info)); + ok_(__FILE__,line)(ret == sizeof(info), "Unexpected return value.\n"); + ok_(__FILE__,line)(info.RegionSize == s, "Unexpected size %Iu, expected %Iu.\n", info.RegionSize, s); +} + static void test_VirtualAlloc2(void) { void *placeholder1, *placeholder2, *view1, *view2, *addr; MEMORY_BASIC_INFORMATION info; + char *p, *p1, *p2; HANDLE section; SIZE_T size; BOOL ret; @@ -194,6 +207,54 @@ static void test_VirtualAlloc2(void)
VirtualFree(placeholder1, 0, MEM_RELEASE); VirtualFree(placeholder2, 0, MEM_RELEASE); + + /* Split in three regions. */ + p = pVirtualAlloc2(NULL, NULL, 2 * size, MEM_RESERVE_PLACEHOLDER | MEM_RESERVE, PAGE_NOACCESS, NULL, 0); + ok(!!p, "Failed to create a placeholder range.\n"); + + p1 = p + size / 2; + p2 = p1 + size / 4; + ret = VirtualFree(p1, size / 4, MEM_RELEASE | MEM_PRESERVE_PLACEHOLDER); + ok(ret, "Failed to split a placeholder.\n"); + check_region_size(p, size / 2); + check_region_size(p1, size / 4); + check_region_size(p2, 2 * size - size / 2 - size / 4); + ret = VirtualFree(p, 0, MEM_RELEASE); + ok(ret, "Failed to release a region.\n"); + ret = VirtualFree(p1, 0, MEM_RELEASE); + ok(ret, "Failed to release a region.\n"); + ret = VirtualFree(p2, 0, MEM_RELEASE); + ok(ret, "Failed to release a region.\n"); + + /* Split in two regions, specifying lower part. */ + p = pVirtualAlloc2(NULL, NULL, 2 * size, MEM_RESERVE_PLACEHOLDER | MEM_RESERVE, PAGE_NOACCESS, NULL, 0); + ok(!!p, "Failed to create a placeholder range.\n"); + + p1 = p; + p2 = p + size / 2; + ret = VirtualFree(p1, size / 2, MEM_RELEASE | MEM_PRESERVE_PLACEHOLDER); + ok(ret, "Failed to split a placeholder.\n"); + check_region_size(p1, size / 2); + check_region_size(p2, 2 * size - size / 2); + ret = VirtualFree(p1, 0, MEM_RELEASE); + ok(ret, "Failed to release a region.\n"); + ret = VirtualFree(p2, 0, MEM_RELEASE); + ok(ret, "Failed to release a region.\n"); + + /* Split in two regions, specifying second half. */ + p = pVirtualAlloc2(NULL, NULL, 2 * size, MEM_RESERVE_PLACEHOLDER | MEM_RESERVE, PAGE_NOACCESS, NULL, 0); + ok(!!p, "Failed to create a placeholder range.\n"); + + p1 = p; + p2 = p + size; + ret = VirtualFree(p2, size, MEM_RELEASE | MEM_PRESERVE_PLACEHOLDER); + ok(ret, "Failed to split a placeholder.\n"); + check_region_size(p1, size); + check_region_size(p2, size); + ret = VirtualFree(p1, 0, MEM_RELEASE); + ok(ret, "Failed to release a region.\n"); + ret = VirtualFree(p2, 0, MEM_RELEASE); + ok(ret, "Failed to release a region.\n"); }
static void test_VirtualAllocFromApp(void)
From: Nikolay Sivov nsivov@codeweavers.com
Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- dlls/ntdll/tests/virtual.c | 102 +++++++++++++++++++++++++++++++++++-- 1 file changed, 99 insertions(+), 3 deletions(-)
diff --git a/dlls/ntdll/tests/virtual.c b/dlls/ntdll/tests/virtual.c index f8bb3e97c86..24c87c46d26 100644 --- a/dlls/ntdll/tests/virtual.c +++ b/dlls/ntdll/tests/virtual.c @@ -272,12 +272,27 @@ static void test_NtAllocateVirtualMemory(void) ok(!!status, "Unexpected status %08lx.\n", status); }
-static void test_NtAllocateVirtualMemoryEx(void) +#define check_region_size(p, s) check_region_size_(p, s, __LINE__) +static void check_region_size_(void *p, SIZE_T s, unsigned int line) { - void *addr1, *addr2; + MEMORY_BASIC_INFORMATION mbi; NTSTATUS status; SIZE_T size;
+ memset(&mbi, 0, sizeof(mbi)); + status = NtQueryVirtualMemory( NtCurrentProcess(), p, MemoryBasicInformation, &mbi, sizeof(mbi), &size ); + ok_(__FILE__,line)( !status, "Unexpected return value %08lx\n", status ); + ok_(__FILE__,line)( size == sizeof(mbi), "Unexpected return value.\n"); + ok_(__FILE__,line)( mbi.RegionSize == s, "Unexpected size %Iu, expected %Iu.\n", mbi.RegionSize, s); +} + +static void test_NtAllocateVirtualMemoryEx(void) +{ + SIZE_T size, size2; + char *p, *p1, *p2; + NTSTATUS status; + void *addr1; + if (!pNtAllocateVirtualMemoryEx) { win_skip("NtAllocateVirtualMemoryEx() is missing\n"); @@ -291,7 +306,7 @@ static void test_NtAllocateVirtualMemoryEx(void) ok(status == STATUS_SUCCESS, "Unexpected status %08lx.\n", status);
size = 0; - status = NtFreeVirtualMemory(NtCurrentProcess(), &addr2, &size, MEM_RELEASE); + status = NtFreeVirtualMemory(NtCurrentProcess(), &addr1, &size, MEM_RELEASE); ok(status == STATUS_SUCCESS, "Unexpected status %08lx.\n", status);
/* specifying a count of >0 with NULL parameters should fail */ @@ -322,6 +337,87 @@ static void test_NtAllocateVirtualMemoryEx(void) status = NtFreeVirtualMemory(NtCurrentProcess(), &addr1, &size, MEM_RELEASE); ok(status == STATUS_SUCCESS, "Unexpected status %08lx.\n", status); } + + /* Placeholder region splitting. */ + + /* Split in three regions. */ + addr1 = NULL; + size = 0x10000; + 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 (status == STATUS_SUCCESS) + { + p = addr1; + p1 = p + size / 2; + p2 = p1 + size / 4; + size2 = size / 4; + status = NtFreeVirtualMemory(NtCurrentProcess(), (void **)&p1, &size2, MEM_RELEASE | MEM_PRESERVE_PLACEHOLDER); + ok(status == STATUS_SUCCESS, "Unexpected status %08lx.\n", status); + + check_region_size(p, size / 2); + check_region_size(p1, size / 4); + check_region_size(p2, size - size / 2 - size / 4); + + status = NtFreeVirtualMemory(NtCurrentProcess(), (void **)&p, &size2, MEM_RELEASE); + ok(status == STATUS_SUCCESS, "Unexpected status %08lx.\n", status); + status = NtFreeVirtualMemory(NtCurrentProcess(), (void **)&p1, &size2, MEM_RELEASE); + ok(status == STATUS_SUCCESS, "Unexpected status %08lx.\n", status); + status = NtFreeVirtualMemory(NtCurrentProcess(), (void **)&p2, &size2, MEM_RELEASE); + ok(status == STATUS_SUCCESS, "Unexpected status %08lx.\n", status); + } + + /* Split in two regions, specifying lower part. */ + addr1 = NULL; + size = 0x10000; + 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 (status == STATUS_SUCCESS) + { + p1 = addr1; + p2 = p1 + size / 4; + size2 = size / 4; + status = NtFreeVirtualMemory(NtCurrentProcess(), (void **)&p1, &size2, MEM_RELEASE | MEM_PRESERVE_PLACEHOLDER); + ok(status == STATUS_SUCCESS, "Unexpected status %08lx.\n", status); + ok(p1 == addr1, "Unexpected address.\n"); + + check_region_size(p1, size / 4); + check_region_size(p2, size - size / 4); + status = NtFreeVirtualMemory(NtCurrentProcess(), (void **)&p1, &size2, MEM_RELEASE); + ok(status == STATUS_SUCCESS, "Unexpected status %08lx.\n", status); + status = NtFreeVirtualMemory(NtCurrentProcess(), (void **)&p2, &size2, MEM_RELEASE); + ok(status == STATUS_SUCCESS, "Unexpected status %08lx.\n", status); + } + + /* Split in two regions, specifying second half. */ + addr1 = NULL; + size = 0x10000; + 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 (status == STATUS_SUCCESS) + { + p1 = addr1; + p2 = p1 + size / 2; + + size2 = size / 2; + status = NtFreeVirtualMemory(NtCurrentProcess(), (void **)&p2, &size2, MEM_RELEASE | MEM_PRESERVE_PLACEHOLDER); + ok(status == STATUS_SUCCESS, "Unexpected status %08lx.\n", status); + ok(p2 == p1 + size / 2, "Unexpected address.\n"); + check_region_size(p1, size / 2); + check_region_size(p2, size / 2); + status = NtFreeVirtualMemory(NtCurrentProcess(), (void **)&p1, &size2, MEM_RELEASE); + ok(status == STATUS_SUCCESS, "Unexpected status %08lx.\n", status); + status = NtFreeVirtualMemory(NtCurrentProcess(), (void **)&p2, &size2, MEM_RELEASE); + ok(status == STATUS_SUCCESS, "Unexpected status %08lx.\n", status); + } }
struct test_stack_size_thread_args