1 /*
2  * PROJECT:         ReactOS API Tests
3  * LICENSE:         GPLv2+ - See COPYING in the top level directory
4  * PURPOSE:         Test for the NtProtectVirtualMemory API
5  * PROGRAMMERS:     Jérôme Gardou <jerome.gardou@reactos.org>
6  *                  Thomas Faber <thomas.faber@reactos.org>
7  */
8 
9 #include "precomp.h"
10 
11 static
12 void
TestReadWrite(void)13 TestReadWrite(void)
14 {
15     ULONG* allocationStart = NULL;
16     NTSTATUS status;
17     SIZE_T allocationSize;
18     ULONG oldProtection;
19 
20     /* Reserve a page */
21     allocationSize = PAGE_SIZE;
22     status = NtAllocateVirtualMemory(NtCurrentProcess(),
23         (void**)&allocationStart,
24         0,
25         &allocationSize,
26         MEM_RESERVE,
27         PAGE_NOACCESS);
28     ok(NT_SUCCESS(status), "Reserving memory failed\n");
29 
30     /* Commit the page (RW) */
31     status = NtAllocateVirtualMemory(NtCurrentProcess(),
32         (void**)&allocationStart,
33         0,
34         &allocationSize,
35         MEM_COMMIT,
36         PAGE_READWRITE);
37     ok(NT_SUCCESS(status), "Commiting memory failed\n");
38 
39     /* Try writing it */
40     StartSeh()
41     {
42         *allocationStart = 0xFF;
43     } EndSeh(STATUS_SUCCESS);
44 
45     /* Try reading it */
46     StartSeh()
47     {
48         ok(*allocationStart == 0xFF, "Memory was not written\n");
49     } EndSeh(STATUS_SUCCESS);
50 
51     /* Set it as read only */
52     status = NtProtectVirtualMemory(NtCurrentProcess(),
53         (void**)&allocationStart,
54         &allocationSize,
55         PAGE_READONLY,
56         &oldProtection);
57     ok(NT_SUCCESS(status), "NtProtectVirtualMemory failed.\n");
58     ok(oldProtection == PAGE_READWRITE, "Expected PAGE_READWRITE, got %08lx.\n", oldProtection);
59 
60     /* Try writing it */
61     StartSeh()
62     {
63         *allocationStart = 0xAA;
64     } EndSeh(STATUS_ACCESS_VIOLATION);
65 
66     /* Try reading it */
67     StartSeh()
68     {
69         ok(*allocationStart == 0xFF, "read-only memory were changed.\n");
70     } EndSeh(STATUS_SUCCESS);
71 
72     /* Set it as no access */
73     status = NtProtectVirtualMemory(NtCurrentProcess(),
74         (void**)&allocationStart,
75         &allocationSize,
76         PAGE_NOACCESS,
77         &oldProtection);
78     ok(NT_SUCCESS(status), "NtProtectVirtualMemory failed.\n");
79     ok(oldProtection == PAGE_READONLY, "Expected PAGE_READONLY, got %08lx.\n", oldProtection);
80 
81     /* Try writing it */
82     StartSeh()
83     {
84         *allocationStart = 0xAA;
85     } EndSeh(STATUS_ACCESS_VIOLATION);
86 
87     /* Try reading it */
88     StartSeh()
89     {
90         ok(*allocationStart == 0, "Test should not go as far as this.\n");
91     } EndSeh(STATUS_ACCESS_VIOLATION);
92 
93     /* Set it as readable again */
94     status = NtProtectVirtualMemory(NtCurrentProcess(),
95         (void**)&allocationStart,
96         &allocationSize,
97         PAGE_READONLY,
98         &oldProtection);
99     ok(NT_SUCCESS(status), "NtProtectVirtualMemory failed.\n");
100     ok(oldProtection == PAGE_NOACCESS, "Expected PAGE_READONLY, got %08lx.\n", oldProtection);
101 
102     /* Try writing it */
103     StartSeh()
104     {
105         *allocationStart = 0xAA;
106     } EndSeh(STATUS_ACCESS_VIOLATION);
107 
108     /* Try reading it */
109     StartSeh()
110     {
111         ok(*allocationStart == 0xFF, "Memory content was not preserved.\n");
112     } EndSeh(STATUS_SUCCESS);
113 
114     /* Free memory */
115     status = NtFreeVirtualMemory(NtCurrentProcess(),
116         (void**)&allocationStart,
117         &allocationSize,
118         MEM_RELEASE);
119     ok(NT_SUCCESS(status), "Failed freeing memory.\n");
120 }
121 
122 /* Regression test for CORE-13311 */
123 static
124 void
TestFreeNoAccess(void)125 TestFreeNoAccess(void)
126 {
127     PVOID Mem;
128     SIZE_T Size;
129     NTSTATUS Status;
130     ULONG Iteration, PageNumber;
131     PUCHAR Page;
132     ULONG OldProtection;
133 
134     for (Iteration = 0; Iteration < 50000; Iteration++)
135     {
136         Mem = NULL;
137         Size = 16 * PAGE_SIZE;
138         Status = NtAllocateVirtualMemory(NtCurrentProcess(),
139                                          &Mem,
140                                          0,
141                                          &Size,
142                                          MEM_COMMIT,
143                                          PAGE_READWRITE);
144         ok_ntstatus(Status, STATUS_SUCCESS);
145         if (!NT_SUCCESS(Status))
146         {
147             break;
148         }
149 
150         for (PageNumber = 0; PageNumber < 16; PageNumber++)
151         {
152             Page = Mem;
153             Page += PageNumber * PAGE_SIZE;
154             ok(*Page == 0,
155                "[%lu, %lu] Got non-zero memory. %x at %p\n",
156                Iteration, PageNumber, *Page, Page);
157             *Page = 123;
158         }
159 
160         Status = NtProtectVirtualMemory(NtCurrentProcess(),
161                                         &Mem,
162                                         &Size,
163                                         PAGE_NOACCESS,
164                                         &OldProtection);
165         ok_ntstatus(Status, STATUS_SUCCESS);
166         ok_hex(OldProtection, PAGE_READWRITE);
167 
168         Size = 0;
169         Status = NtFreeVirtualMemory(NtCurrentProcess(),
170                                      &Mem,
171                                      &Size,
172                                      MEM_RELEASE);
173         ok_ntstatus(Status, STATUS_SUCCESS);
174     }
175 }
176 
START_TEST(NtProtectVirtualMemory)177 START_TEST(NtProtectVirtualMemory)
178 {
179     TestReadWrite();
180     TestFreeNoAccess();
181 }
182