--- /dev/null
+#define WIN32_NO_STATUS
+#include <stdio.h>
+#include <wine/test.h>
+#include <ndk/ntndk.h>
+
+static void Test_NtFreeVirtualMemory(void)
+{
+ PVOID Buffer = NULL, Buffer2;
+ SIZE_T Length = PAGE_SIZE;
+ NTSTATUS Status;
+
+ Status = NtAllocateVirtualMemory(NtCurrentProcess(),
+ &Buffer,
+ 0,
+ &Length,
+ MEM_RESERVE,
+ PAGE_READWRITE);
+ ok(NT_SUCCESS(Status), "NtAllocateVirtualMemory failed : 0x%08x\n", Status);
+ ok(Length == PAGE_SIZE, "Length mismatch : 0x08x\n", Length);
+ ok(((ULONG_PTR)Buffer % PAGE_SIZE) == 0, "The buffer is not aligned to PAGE_SIZE.\n");
+
+ Status = NtFreeVirtualMemory(NtCurrentProcess(),
+ &Buffer,
+ &Length,
+ MEM_DECOMMIT);
+ ok(Status == STATUS_SUCCESS, "NtFreeVirtualMemory failed : 0x%08x\n", Status);
+
+ /* Now try to free more than we got */
+ Length++;
+ Status = NtFreeVirtualMemory(NtCurrentProcess(),
+ &Buffer,
+ &Length,
+ MEM_DECOMMIT);
+ ok(Status == STATUS_UNABLE_TO_FREE_VM, "NtFreeVirtualMemory returned status : 0x%08x\n", Status);
+
+ Status = NtFreeVirtualMemory(NtCurrentProcess(),
+ &Buffer,
+ &Length,
+ MEM_RELEASE);
+ ok(Status == STATUS_UNABLE_TO_FREE_VM, "NtFreeVirtualMemory returned status : 0x%08x\n", Status);
+
+ /* Free out of bounds from the wrong origin */
+ Length = PAGE_SIZE;
+ Buffer2 = (PVOID)((ULONG_PTR)Buffer+1);
+
+ Status = NtFreeVirtualMemory(NtCurrentProcess(),
+ &Buffer2,
+ &Length,
+ MEM_DECOMMIT);
+ ok(Status == STATUS_UNABLE_TO_FREE_VM, "NtFreeVirtualMemory returned status : 0x%08x\n", Status);
+
+ Buffer2 = (PVOID)((ULONG_PTR)Buffer+1);
+ Length = PAGE_SIZE;
+ Status = NtFreeVirtualMemory(NtCurrentProcess(),
+ &Buffer2,
+ &Length,
+ MEM_RELEASE);
+ ok(Status == STATUS_UNABLE_TO_FREE_VM, "NtFreeVirtualMemory returned status : 0x%08x\n", Status);
+
+ /* Same but in bounds */
+ Length = PAGE_SIZE - 1;
+ Buffer2 = (PVOID)((ULONG_PTR)Buffer+1);
+
+ Status = NtFreeVirtualMemory(NtCurrentProcess(),
+ &Buffer2,
+ &Length,
+ MEM_DECOMMIT);
+ ok(Status == STATUS_SUCCESS, "NtFreeVirtualMemory returned status : 0x%08x\n", Status);
+ ok(Buffer2 == Buffer, "NtFreeVirtualMemory set wrong buffer.\n");
+ ok(Length == PAGE_SIZE, "NtFreeVirtualMemory did not round Length to PAGE_SIZE.\n");
+
+ Buffer2 = (PVOID)((ULONG_PTR)Buffer+1);
+ Length = PAGE_SIZE-1;
+ Status = NtFreeVirtualMemory(NtCurrentProcess(),
+ &Buffer2,
+ &Length,
+ MEM_RELEASE);
+ ok(Status == STATUS_SUCCESS, "NtFreeVirtualMemory returned status : 0x%08x\n", Status);
+ ok(Buffer2 == Buffer, "NtFreeVirtualMemory set wrong buffer.\n");
+ ok(Length == PAGE_SIZE, "NtFreeVirtualMemory did not round Length to PAGE_SIZE.\n");
+
+ /* Now allocate two pages and try to free them one after the other */
+ Length = 2*PAGE_SIZE;
+ Status = NtAllocateVirtualMemory(NtCurrentProcess(),
+ &Buffer,
+ 0,
+ &Length,
+ MEM_RESERVE,
+ PAGE_READWRITE);
+ ok(NT_SUCCESS(Status), "NtAllocateVirtualMemory failed : 0x%08x\n", Status);
+ ok(Length == 2*PAGE_SIZE, "Length mismatch : 0x08x\n", Length);
+ ok(((ULONG_PTR)Buffer % PAGE_SIZE) == 0, "The buffer is not aligned to PAGE_SIZE.\n");
+
+ Buffer2 = Buffer;
+ Length = PAGE_SIZE;
+ Status = NtFreeVirtualMemory(NtCurrentProcess(),
+ &Buffer2,
+ &Length,
+ MEM_RELEASE);
+ ok(NT_SUCCESS(Status), "NtAllocateVirtualMemory failed : 0x%08x\n", Status);
+ ok(Length == PAGE_SIZE, "Length mismatch : 0x08x\n", Length);
+ ok(Buffer2 == Buffer, "The buffer is not aligned to PAGE_SIZE.\n");
+
+ Buffer2 = (PVOID)((ULONG_PTR)Buffer+PAGE_SIZE);
+ Length = PAGE_SIZE;
+ Status = NtFreeVirtualMemory(NtCurrentProcess(),
+ &Buffer2,
+ &Length,
+ MEM_RELEASE);
+ ok(NT_SUCCESS(Status), "NtFreeVirtualMemory failed : 0x%08x\n", Status);
+ ok(Length == PAGE_SIZE, "Length mismatch : 0x08x\n", Length);
+ ok(Buffer2 == (PVOID)((ULONG_PTR)Buffer+PAGE_SIZE), "The buffer is not aligned to PAGE_SIZE.\n");
+}
+
+START_TEST(NtFreeVirtualMemory)
+{
+ Test_NtFreeVirtualMemory();
+}
\ No newline at end of file