winealsa: Fix AudioRenderClient Get/ReleaseBuffer protocol.
[wine] / dlls / kernel32 / tests / virtual.c
1 /*
2  * Unit test suite for Virtual* family of APIs.
3  *
4  * Copyright 2004 Dmitry Timoshkov
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19  */
20
21 #include <stdarg.h>
22 #include <stdio.h>
23
24 #include "ntstatus.h"
25 #define WIN32_NO_STATUS
26 #include "windef.h"
27 #include "winbase.h"
28 #include "winternl.h"
29 #include "winerror.h"
30 #include "wine/test.h"
31
32 #define NUM_THREADS 4
33 #define MAPPING_SIZE 0x100000
34
35 static HINSTANCE hkernel32;
36 static LPVOID (WINAPI *pVirtualAllocEx)(HANDLE, LPVOID, SIZE_T, DWORD, DWORD);
37 static BOOL   (WINAPI *pVirtualFreeEx)(HANDLE, LPVOID, SIZE_T, DWORD);
38 static UINT   (WINAPI *pGetWriteWatch)(DWORD,LPVOID,SIZE_T,LPVOID*,ULONG_PTR*,ULONG*);
39 static UINT   (WINAPI *pResetWriteWatch)(LPVOID,SIZE_T);
40 static NTSTATUS (WINAPI *pNtAreMappedFilesTheSame)(PVOID,PVOID);
41
42 /* ############################### */
43
44 static HANDLE create_target_process(const char *arg)
45 {
46     char **argv;
47     char cmdline[MAX_PATH];
48     PROCESS_INFORMATION pi;
49     BOOL ret;
50     STARTUPINFO si = { 0 };
51     si.cb = sizeof(si);
52
53     winetest_get_mainargs( &argv );
54     sprintf(cmdline, "%s %s %s", argv[0], argv[1], arg);
55     ret = CreateProcess(NULL, cmdline, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi);
56     ok(ret, "error: %u\n", GetLastError());
57     ret = CloseHandle(pi.hThread);
58     ok(ret, "error %u\n", GetLastError());
59     return pi.hProcess;
60 }
61
62 static void test_VirtualAllocEx(void)
63 {
64     const unsigned int alloc_size = 1<<15;
65     char *src, *dst;
66     SIZE_T bytes_written = 0, bytes_read = 0, i;
67     void *addr1, *addr2;
68     BOOL b;
69     DWORD old_prot;
70     MEMORY_BASIC_INFORMATION info;
71     HANDLE hProcess;
72
73     /* not exported in all windows-versions  */
74     if ((!pVirtualAllocEx) || (!pVirtualFreeEx)) {
75         win_skip("Virtual{Alloc,Free}Ex not available\n");
76         return;
77     }
78
79     hProcess = create_target_process("sleep");
80     ok(hProcess != NULL, "Can't start process\n");
81
82     SetLastError(0xdeadbeef);
83     addr1 = pVirtualAllocEx(hProcess, NULL, alloc_size, MEM_COMMIT,
84                            PAGE_EXECUTE_READWRITE);
85     if (!addr1 && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
86     {   /* Win9x */
87         win_skip("VirtualAllocEx not implemented\n");
88         TerminateProcess(hProcess, 0);
89         CloseHandle(hProcess);
90         return;
91     }
92
93     src = VirtualAlloc( NULL, alloc_size, MEM_COMMIT, PAGE_READWRITE );
94     dst = VirtualAlloc( NULL, alloc_size, MEM_COMMIT, PAGE_READWRITE );
95     for (i = 0; i < alloc_size; i++)
96         src[i] = i & 0xff;
97
98     ok(addr1 != NULL, "VirtualAllocEx error %u\n", GetLastError());
99     b = WriteProcessMemory(hProcess, addr1, src, alloc_size, &bytes_written);
100     ok(b && (bytes_written == alloc_size), "%lu bytes written\n",
101        bytes_written);
102     b = ReadProcessMemory(hProcess, addr1, dst, alloc_size, &bytes_read);
103     ok(b && (bytes_read == alloc_size), "%lu bytes read\n", bytes_read);
104     ok(!memcmp(src, dst, alloc_size), "Data from remote process differs\n");
105
106     /* test invalid source buffers */
107
108     b = VirtualProtect( src + 0x2000, 0x2000, PAGE_NOACCESS, &old_prot );
109     ok( b, "VirtualProtect failed error %u\n", GetLastError() );
110     b = WriteProcessMemory(hProcess, addr1, src, alloc_size, &bytes_written);
111     ok( !b, "WriteProcessMemory succeeded\n" );
112     ok( GetLastError() == ERROR_NOACCESS ||
113         GetLastError() == ERROR_PARTIAL_COPY, /* vista */
114         "wrong error %u\n", GetLastError() );
115     ok( bytes_written == 0, "%lu bytes written\n", bytes_written );
116     b = ReadProcessMemory(hProcess, addr1, src, alloc_size, &bytes_read);
117     ok( !b, "ReadProcessMemory succeeded\n" );
118     ok( GetLastError() == ERROR_NOACCESS, "wrong error %u\n", GetLastError() );
119     ok( bytes_read == 0, "%lu bytes written\n", bytes_read );
120
121     b = VirtualProtect( src, 0x2000, PAGE_NOACCESS, &old_prot );
122     ok( b, "VirtualProtect failed error %u\n", GetLastError() );
123     b = WriteProcessMemory(hProcess, addr1, src, alloc_size, &bytes_written);
124     ok( !b, "WriteProcessMemory succeeded\n" );
125     ok( GetLastError() == ERROR_NOACCESS ||
126         GetLastError() == ERROR_PARTIAL_COPY, /* vista */
127         "wrong error %u\n", GetLastError() );
128     ok( bytes_written == 0, "%lu bytes written\n", bytes_written );
129     b = ReadProcessMemory(hProcess, addr1, src, alloc_size, &bytes_read);
130     ok( !b, "ReadProcessMemory succeeded\n" );
131     ok( GetLastError() == ERROR_NOACCESS, "wrong error %u\n", GetLastError() );
132     ok( bytes_read == 0, "%lu bytes written\n", bytes_read );
133
134     b = pVirtualFreeEx(hProcess, addr1, 0, MEM_RELEASE);
135     ok(b != 0, "VirtualFreeEx, error %u\n", GetLastError());
136
137     VirtualFree( src, 0, MEM_FREE );
138     VirtualFree( dst, 0, MEM_FREE );
139
140     /*
141      * The following tests parallel those in test_VirtualAlloc()
142      */
143
144     SetLastError(0xdeadbeef);
145     addr1 = pVirtualAllocEx(hProcess, 0, 0, MEM_RESERVE, PAGE_NOACCESS);
146     ok(addr1 == NULL, "VirtualAllocEx should fail on zero-sized allocation\n");
147     ok(GetLastError() == ERROR_INVALID_PARAMETER /* NT */ ||
148        GetLastError() == ERROR_NOT_ENOUGH_MEMORY, /* Win9x */
149         "got %u, expected ERROR_INVALID_PARAMETER\n", GetLastError());
150
151     addr1 = pVirtualAllocEx(hProcess, 0, 0xFFFC, MEM_RESERVE, PAGE_NOACCESS);
152     ok(addr1 != NULL, "VirtualAllocEx failed\n");
153
154     /* test a not committed memory */
155     memset(&info, 'q', sizeof(info));
156     ok(VirtualQueryEx(hProcess, addr1, &info, sizeof(info)) == sizeof(info), "VirtualQueryEx failed\n");
157     ok(info.BaseAddress == addr1, "%p != %p\n", info.BaseAddress, addr1);
158     ok(info.AllocationBase == addr1, "%p != %p\n", info.AllocationBase, addr1);
159     ok(info.AllocationProtect == PAGE_NOACCESS, "%x != PAGE_NOACCESS\n", info.AllocationProtect);
160     ok(info.RegionSize == 0x10000, "%lx != 0x10000\n", info.RegionSize);
161     ok(info.State == MEM_RESERVE, "%x != MEM_RESERVE\n", info.State);
162     /* NT reports Protect == 0 for a not committed memory block */
163     ok(info.Protect == 0 /* NT */ ||
164        info.Protect == PAGE_NOACCESS, /* Win9x */
165         "%x != PAGE_NOACCESS\n", info.Protect);
166     ok(info.Type == MEM_PRIVATE, "%x != MEM_PRIVATE\n", info.Type);
167
168     SetLastError(0xdeadbeef);
169     ok(!VirtualProtectEx(hProcess, addr1, 0xFFFC, PAGE_READONLY, &old_prot),
170        "VirtualProtectEx should fail on a not committed memory\n");
171     ok(GetLastError() == ERROR_INVALID_ADDRESS /* NT */ ||
172        GetLastError() == ERROR_INVALID_PARAMETER, /* Win9x */
173         "got %u, expected ERROR_INVALID_ADDRESS\n", GetLastError());
174
175     addr2 = pVirtualAllocEx(hProcess, addr1, 0x1000, MEM_COMMIT, PAGE_NOACCESS);
176     ok(addr1 == addr2, "VirtualAllocEx failed\n");
177
178     /* test a committed memory */
179     ok(VirtualQueryEx(hProcess, addr1, &info, sizeof(info)) == sizeof(info),
180         "VirtualQueryEx failed\n");
181     ok(info.BaseAddress == addr1, "%p != %p\n", info.BaseAddress, addr1);
182     ok(info.AllocationBase == addr1, "%p != %p\n", info.AllocationBase, addr1);
183     ok(info.AllocationProtect == PAGE_NOACCESS, "%x != PAGE_NOACCESS\n", info.AllocationProtect);
184     ok(info.RegionSize == 0x1000, "%lx != 0x1000\n", info.RegionSize);
185     ok(info.State == MEM_COMMIT, "%x != MEM_COMMIT\n", info.State);
186     /* this time NT reports PAGE_NOACCESS as well */
187     ok(info.Protect == PAGE_NOACCESS, "%x != PAGE_NOACCESS\n", info.Protect);
188     ok(info.Type == MEM_PRIVATE, "%x != MEM_PRIVATE\n", info.Type);
189
190     /* this should fail, since not the whole range is committed yet */
191     SetLastError(0xdeadbeef);
192     ok(!VirtualProtectEx(hProcess, addr1, 0xFFFC, PAGE_READONLY, &old_prot),
193         "VirtualProtectEx should fail on a not committed memory\n");
194     ok(GetLastError() == ERROR_INVALID_ADDRESS /* NT */ ||
195        GetLastError() == ERROR_INVALID_PARAMETER, /* Win9x */
196         "got %u, expected ERROR_INVALID_ADDRESS\n", GetLastError());
197
198     old_prot = 0;
199     ok(VirtualProtectEx(hProcess, addr1, 0x1000, PAGE_READONLY, &old_prot), "VirtualProtectEx failed\n");
200     ok(old_prot == PAGE_NOACCESS, "wrong old protection: got %04x instead of PAGE_NOACCESS\n", old_prot);
201
202     old_prot = 0;
203     ok(VirtualProtectEx(hProcess, addr1, 0x1000, PAGE_READWRITE, &old_prot), "VirtualProtectEx failed\n");
204     ok(old_prot == PAGE_READONLY, "wrong old protection: got %04x instead of PAGE_READONLY\n", old_prot);
205
206     ok(!pVirtualFreeEx(hProcess, addr1, 0x10000, 0),
207        "VirtualFreeEx should fail with type 0\n");
208     ok(GetLastError() == ERROR_INVALID_PARAMETER,
209         "got %u, expected ERROR_INVALID_PARAMETER\n", GetLastError());
210
211     ok(pVirtualFreeEx(hProcess, addr1, 0x10000, MEM_DECOMMIT), "VirtualFreeEx failed\n");
212
213     /* if the type is MEM_RELEASE, size must be 0 */
214     ok(!pVirtualFreeEx(hProcess, addr1, 1, MEM_RELEASE),
215        "VirtualFreeEx should fail\n");
216     ok(GetLastError() == ERROR_INVALID_PARAMETER,
217         "got %u, expected ERROR_INVALID_PARAMETER\n", GetLastError());
218
219     ok(pVirtualFreeEx(hProcess, addr1, 0, MEM_RELEASE), "VirtualFreeEx failed\n");
220
221     TerminateProcess(hProcess, 0);
222     CloseHandle(hProcess);
223 }
224
225 static void test_VirtualAlloc(void)
226 {
227     void *addr1, *addr2;
228     DWORD old_prot;
229     MEMORY_BASIC_INFORMATION info;
230
231     SetLastError(0xdeadbeef);
232     addr1 = VirtualAlloc(0, 0, MEM_RESERVE, PAGE_NOACCESS);
233     ok(addr1 == NULL, "VirtualAlloc should fail on zero-sized allocation\n");
234     ok(GetLastError() == ERROR_INVALID_PARAMETER /* NT */ ||
235        GetLastError() == ERROR_NOT_ENOUGH_MEMORY, /* Win9x */
236         "got %d, expected ERROR_INVALID_PARAMETER\n", GetLastError());
237
238     addr1 = VirtualAlloc(0, 0xFFFC, MEM_RESERVE, PAGE_NOACCESS);
239     ok(addr1 != NULL, "VirtualAlloc failed\n");
240
241     /* test a not committed memory */
242     ok(VirtualQuery(addr1, &info, sizeof(info)) == sizeof(info),
243         "VirtualQuery failed\n");
244     ok(info.BaseAddress == addr1, "%p != %p\n", info.BaseAddress, addr1);
245     ok(info.AllocationBase == addr1, "%p != %p\n", info.AllocationBase, addr1);
246     ok(info.AllocationProtect == PAGE_NOACCESS, "%x != PAGE_NOACCESS\n", info.AllocationProtect);
247     ok(info.RegionSize == 0x10000, "%lx != 0x10000\n", info.RegionSize);
248     ok(info.State == MEM_RESERVE, "%x != MEM_RESERVE\n", info.State);
249     /* NT reports Protect == 0 for a not committed memory block */
250     ok(info.Protect == 0 /* NT */ ||
251        info.Protect == PAGE_NOACCESS, /* Win9x */
252         "%x != PAGE_NOACCESS\n", info.Protect);
253     ok(info.Type == MEM_PRIVATE, "%x != MEM_PRIVATE\n", info.Type);
254
255     SetLastError(0xdeadbeef);
256     ok(!VirtualProtect(addr1, 0xFFFC, PAGE_READONLY, &old_prot),
257        "VirtualProtect should fail on a not committed memory\n");
258     ok(GetLastError() == ERROR_INVALID_ADDRESS /* NT */ ||
259        GetLastError() == ERROR_INVALID_PARAMETER, /* Win9x */
260         "got %d, expected ERROR_INVALID_ADDRESS\n", GetLastError());
261
262     addr2 = VirtualAlloc(addr1, 0x1000, MEM_COMMIT, PAGE_NOACCESS);
263     ok(addr1 == addr2, "VirtualAlloc failed\n");
264
265     /* test a committed memory */
266     ok(VirtualQuery(addr1, &info, sizeof(info)) == sizeof(info),
267         "VirtualQuery failed\n");
268     ok(info.BaseAddress == addr1, "%p != %p\n", info.BaseAddress, addr1);
269     ok(info.AllocationBase == addr1, "%p != %p\n", info.AllocationBase, addr1);
270     ok(info.AllocationProtect == PAGE_NOACCESS, "%x != PAGE_NOACCESS\n", info.AllocationProtect);
271     ok(info.RegionSize == 0x1000, "%lx != 0x1000\n", info.RegionSize);
272     ok(info.State == MEM_COMMIT, "%x != MEM_COMMIT\n", info.State);
273     /* this time NT reports PAGE_NOACCESS as well */
274     ok(info.Protect == PAGE_NOACCESS, "%x != PAGE_NOACCESS\n", info.Protect);
275     ok(info.Type == MEM_PRIVATE, "%x != MEM_PRIVATE\n", info.Type);
276
277     /* this should fail, since not the whole range is committed yet */
278     SetLastError(0xdeadbeef);
279     ok(!VirtualProtect(addr1, 0xFFFC, PAGE_READONLY, &old_prot),
280         "VirtualProtect should fail on a not committed memory\n");
281     ok(GetLastError() == ERROR_INVALID_ADDRESS /* NT */ ||
282        GetLastError() == ERROR_INVALID_PARAMETER, /* Win9x */
283         "got %d, expected ERROR_INVALID_ADDRESS\n", GetLastError());
284
285     ok(VirtualProtect(addr1, 0x1000, PAGE_READONLY, &old_prot), "VirtualProtect failed\n");
286     ok(old_prot == PAGE_NOACCESS,
287         "wrong old protection: got %04x instead of PAGE_NOACCESS\n", old_prot);
288
289     ok(VirtualProtect(addr1, 0x1000, PAGE_READWRITE, &old_prot), "VirtualProtect failed\n");
290     ok(old_prot == PAGE_READONLY,
291         "wrong old protection: got %04x instead of PAGE_READONLY\n", old_prot);
292
293     ok(VirtualQuery(addr1, &info, sizeof(info)) == sizeof(info),
294         "VirtualQuery failed\n");
295     ok(info.RegionSize == 0x1000, "%lx != 0x1000\n", info.RegionSize);
296     ok(info.State == MEM_COMMIT, "%x != MEM_COMMIT\n", info.State);
297     ok(info.Protect == PAGE_READWRITE, "%x != PAGE_READWRITE\n", info.Protect);
298     memset( addr1, 0x55, 20 );
299     ok( *(DWORD *)addr1 == 0x55555555, "wrong data %x\n", *(DWORD *)addr1 );
300
301     addr2 = VirtualAlloc( addr1, 0x1000, MEM_RESET, PAGE_NOACCESS );
302     ok( addr2 == addr1 || broken( !addr2 && GetLastError() == ERROR_INVALID_PARAMETER), /* win9x */
303         "VirtualAlloc failed err %u\n", GetLastError() );
304     ok( *(DWORD *)addr1 == 0x55555555 || *(DWORD *)addr1 == 0, "wrong data %x\n", *(DWORD *)addr1 );
305     if (addr2)
306     {
307         ok(VirtualQuery(addr1, &info, sizeof(info)) == sizeof(info),
308            "VirtualQuery failed\n");
309         ok(info.RegionSize == 0x1000, "%lx != 0x1000\n", info.RegionSize);
310         ok(info.State == MEM_COMMIT, "%x != MEM_COMMIT\n", info.State);
311         ok(info.Protect == PAGE_READWRITE, "%x != PAGE_READWRITE\n", info.Protect);
312
313         addr2 = VirtualAlloc( (char *)addr1 + 0x1000, 0x1000, MEM_RESET, PAGE_NOACCESS );
314         ok( (char *)addr2 == (char *)addr1 + 0x1000, "VirtualAlloc failed\n" );
315
316         ok(VirtualQuery(addr2, &info, sizeof(info)) == sizeof(info),
317            "VirtualQuery failed\n");
318         ok(info.RegionSize == 0xf000, "%lx != 0xf000\n", info.RegionSize);
319         ok(info.State == MEM_RESERVE, "%x != MEM_RESERVE\n", info.State);
320         ok(info.Protect == 0, "%x != 0\n", info.Protect);
321
322         addr2 = VirtualAlloc( (char *)addr1 + 0xf000, 0x2000, MEM_RESET, PAGE_NOACCESS );
323         ok( !addr2, "VirtualAlloc failed\n" );
324         ok( GetLastError() == ERROR_INVALID_ADDRESS, "wrong error %u\n", GetLastError() );
325     }
326
327     /* invalid protection values */
328     SetLastError(0xdeadbeef);
329     addr2 = VirtualAlloc(NULL, 0x1000, MEM_RESERVE, 0);
330     ok(!addr2, "VirtualAlloc succeeded\n");
331     ok(GetLastError() == ERROR_INVALID_PARAMETER, "wrong error %u\n", GetLastError());
332
333     SetLastError(0xdeadbeef);
334     addr2 = VirtualAlloc(NULL, 0x1000, MEM_COMMIT, 0);
335     ok(!addr2, "VirtualAlloc succeeded\n");
336     ok(GetLastError() == ERROR_INVALID_PARAMETER, "wrong error %u\n", GetLastError());
337
338     SetLastError(0xdeadbeef);
339     addr2 = VirtualAlloc(addr1, 0x1000, MEM_COMMIT, PAGE_READONLY | PAGE_EXECUTE);
340     ok(!addr2, "VirtualAlloc succeeded\n");
341     ok(GetLastError() == ERROR_INVALID_PARAMETER, "wrong error %u\n", GetLastError());
342
343     SetLastError(0xdeadbeef);
344     ok(!VirtualProtect(addr1, 0x1000, PAGE_READWRITE | PAGE_EXECUTE_WRITECOPY, &old_prot),
345        "VirtualProtect succeeded\n");
346     ok(GetLastError() == ERROR_INVALID_PARAMETER, "wrong error %u\n", GetLastError());
347
348     SetLastError(0xdeadbeef);
349     ok(!VirtualProtect(addr1, 0x1000, 0, &old_prot), "VirtualProtect succeeded\n");
350     ok(GetLastError() == ERROR_INVALID_PARAMETER, "wrong error %u\n", GetLastError());
351
352     SetLastError(0xdeadbeef);
353     ok(!VirtualFree(addr1, 0x10000, 0), "VirtualFree should fail with type 0\n");
354     ok(GetLastError() == ERROR_INVALID_PARAMETER,
355         "got %d, expected ERROR_INVALID_PARAMETER\n", GetLastError());
356
357     ok(VirtualFree(addr1, 0x10000, MEM_DECOMMIT), "VirtualFree failed\n");
358
359     /* if the type is MEM_RELEASE, size must be 0 */
360     ok(!VirtualFree(addr1, 1, MEM_RELEASE), "VirtualFree should fail\n");
361     ok(GetLastError() == ERROR_INVALID_PARAMETER,
362         "got %d, expected ERROR_INVALID_PARAMETER\n", GetLastError());
363
364     ok(VirtualFree(addr1, 0, MEM_RELEASE), "VirtualFree failed\n");
365 }
366
367 static void test_MapViewOfFile(void)
368 {
369     static const char testfile[] = "testfile.xxx";
370     const char *name;
371     HANDLE file, mapping, map2;
372     void *ptr, *ptr2, *addr;
373     MEMORY_BASIC_INFORMATION info;
374     BOOL ret;
375
376     SetLastError(0xdeadbeef);
377     file = CreateFileA( testfile, GENERIC_READ|GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, 0 );
378     ok( file != INVALID_HANDLE_VALUE, "CreateFile error %u\n", GetLastError() );
379     SetFilePointer( file, 4096, NULL, FILE_BEGIN );
380     SetEndOfFile( file );
381
382     /* read/write mapping */
383
384     SetLastError(0xdeadbeef);
385     mapping = CreateFileMappingA( file, NULL, PAGE_READWRITE, 0, 4096, NULL );
386     ok( mapping != 0, "CreateFileMapping error %u\n", GetLastError() );
387
388     SetLastError(0xdeadbeef);
389     ptr = MapViewOfFile( mapping, FILE_MAP_READ, 0, 0, 4096 );
390     ok( ptr != NULL, "MapViewOfFile FILE_MAPE_READ error %u\n", GetLastError() );
391     UnmapViewOfFile( ptr );
392
393     /* this fails on win9x but succeeds on NT */
394     SetLastError(0xdeadbeef);
395     ptr = MapViewOfFile( mapping, FILE_MAP_COPY, 0, 0, 4096 );
396     if (ptr) UnmapViewOfFile( ptr );
397     else ok( GetLastError() == ERROR_INVALID_PARAMETER, "Wrong error %d\n", GetLastError() );
398
399     SetLastError(0xdeadbeef);
400     ptr = MapViewOfFile( mapping, 0, 0, 0, 4096 );
401     ok( ptr != NULL, "MapViewOfFile 0 error %u\n", GetLastError() );
402     UnmapViewOfFile( ptr );
403
404     SetLastError(0xdeadbeef);
405     ptr = MapViewOfFile( mapping, FILE_MAP_WRITE, 0, 0, 4096 );
406     ok( ptr != NULL, "MapViewOfFile FILE_MAP_WRITE error %u\n", GetLastError() );
407     UnmapViewOfFile( ptr );
408
409     ret = DuplicateHandle( GetCurrentProcess(), mapping, GetCurrentProcess(), &map2,
410                            FILE_MAP_READ|FILE_MAP_WRITE, FALSE, 0 );
411     ok( ret, "DuplicateHandle failed error %u\n", GetLastError());
412     ptr = MapViewOfFile( map2, FILE_MAP_WRITE, 0, 0, 4096 );
413     ok( ptr != NULL, "MapViewOfFile FILE_MAP_WRITE error %u\n", GetLastError() );
414     UnmapViewOfFile( ptr );
415     CloseHandle( map2 );
416
417     ret = DuplicateHandle( GetCurrentProcess(), mapping, GetCurrentProcess(), &map2,
418                            FILE_MAP_READ, FALSE, 0 );
419     ok( ret, "DuplicateHandle failed error %u\n", GetLastError());
420     ptr = MapViewOfFile( map2, FILE_MAP_WRITE, 0, 0, 4096 );
421     if (!ptr)
422     {
423         ok( GetLastError() == ERROR_ACCESS_DENIED, "Wrong error %d\n", GetLastError() );
424         CloseHandle( map2 );
425         ret = DuplicateHandle( GetCurrentProcess(), mapping, GetCurrentProcess(), &map2, 0, FALSE, 0 );
426         ok( ret, "DuplicateHandle failed error %u\n", GetLastError());
427         ptr = MapViewOfFile( map2, 0, 0, 0, 4096 );
428         ok( !ptr, "MapViewOfFile succeeded\n" );
429         ok( GetLastError() == ERROR_ACCESS_DENIED, "Wrong error %d\n", GetLastError() );
430         CloseHandle( map2 );
431         ret = DuplicateHandle( GetCurrentProcess(), mapping, GetCurrentProcess(), &map2,
432                                FILE_MAP_READ, FALSE, 0 );
433         ok( ret, "DuplicateHandle failed error %u\n", GetLastError());
434         ptr = MapViewOfFile( map2, 0, 0, 0, 4096 );
435         ok( ptr != NULL, "MapViewOfFile NO_ACCESS error %u\n", GetLastError() );
436     }
437     else win_skip( "no access checks on win9x\n" );
438
439     UnmapViewOfFile( ptr );
440     CloseHandle( map2 );
441     CloseHandle( mapping );
442
443     /* read-only mapping */
444
445     SetLastError(0xdeadbeef);
446     mapping = CreateFileMappingA( file, NULL, PAGE_READONLY, 0, 4096, NULL );
447     ok( mapping != 0, "CreateFileMapping error %u\n", GetLastError() );
448
449     SetLastError(0xdeadbeef);
450     ptr = MapViewOfFile( mapping, FILE_MAP_READ, 0, 0, 4096 );
451     ok( ptr != NULL, "MapViewOfFile FILE_MAP_READ error %u\n", GetLastError() );
452     UnmapViewOfFile( ptr );
453
454     /* this fails on win9x but succeeds on NT */
455     SetLastError(0xdeadbeef);
456     ptr = MapViewOfFile( mapping, FILE_MAP_COPY, 0, 0, 4096 );
457     if (ptr) UnmapViewOfFile( ptr );
458     else ok( GetLastError() == ERROR_INVALID_PARAMETER, "Wrong error %d\n", GetLastError() );
459
460     SetLastError(0xdeadbeef);
461     ptr = MapViewOfFile( mapping, 0, 0, 0, 4096 );
462     ok( ptr != NULL, "MapViewOfFile 0 error %u\n", GetLastError() );
463     UnmapViewOfFile( ptr );
464
465     SetLastError(0xdeadbeef);
466     ptr = MapViewOfFile( mapping, FILE_MAP_WRITE, 0, 0, 4096 );
467     ok( !ptr, "MapViewOfFile FILE_MAP_WRITE succeeded\n" );
468     ok( GetLastError() == ERROR_INVALID_PARAMETER ||
469         GetLastError() == ERROR_ACCESS_DENIED, "Wrong error %d\n", GetLastError() );
470     CloseHandle( mapping );
471
472     /* copy-on-write mapping */
473
474     SetLastError(0xdeadbeef);
475     mapping = CreateFileMappingA( file, NULL, PAGE_WRITECOPY, 0, 4096, NULL );
476     ok( mapping != 0, "CreateFileMapping error %u\n", GetLastError() );
477
478     SetLastError(0xdeadbeef);
479     ptr = MapViewOfFile( mapping, FILE_MAP_READ, 0, 0, 4096 );
480     ok( ptr != NULL, "MapViewOfFile FILE_MAP_READ error %u\n", GetLastError() );
481     UnmapViewOfFile( ptr );
482
483     SetLastError(0xdeadbeef);
484     ptr = MapViewOfFile( mapping, FILE_MAP_COPY, 0, 0, 4096 );
485     ok( ptr != NULL, "MapViewOfFile FILE_MAP_COPY error %u\n", GetLastError() );
486     UnmapViewOfFile( ptr );
487
488     SetLastError(0xdeadbeef);
489     ptr = MapViewOfFile( mapping, 0, 0, 0, 4096 );
490     ok( ptr != NULL, "MapViewOfFile 0 error %u\n", GetLastError() );
491     UnmapViewOfFile( ptr );
492
493     SetLastError(0xdeadbeef);
494     ptr = MapViewOfFile( mapping, FILE_MAP_WRITE, 0, 0, 4096 );
495     ok( !ptr, "MapViewOfFile FILE_MAP_WRITE succeeded\n" );
496     ok( GetLastError() == ERROR_INVALID_PARAMETER ||
497         GetLastError() == ERROR_ACCESS_DENIED, "Wrong error %d\n", GetLastError() );
498     CloseHandle( mapping );
499
500     /* no access mapping */
501
502     SetLastError(0xdeadbeef);
503     mapping = CreateFileMappingA( file, NULL, PAGE_NOACCESS, 0, 4096, NULL );
504     /* fails on NT but succeeds on win9x */
505     if (!mapping) ok( GetLastError() == ERROR_INVALID_PARAMETER, "Wrong error %d\n", GetLastError() );
506     else
507     {
508         SetLastError(0xdeadbeef);
509         ptr = MapViewOfFile( mapping, FILE_MAP_READ, 0, 0, 4096 );
510         ok( ptr != NULL, "MapViewOfFile FILE_MAP_READ error %u\n", GetLastError() );
511         UnmapViewOfFile( ptr );
512
513         SetLastError(0xdeadbeef);
514         ptr = MapViewOfFile( mapping, FILE_MAP_COPY, 0, 0, 4096 );
515         ok( !ptr, "MapViewOfFile FILE_MAP_COPY succeeded\n" );
516         ok( GetLastError() == ERROR_INVALID_PARAMETER, "Wrong error %d\n", GetLastError() );
517
518         SetLastError(0xdeadbeef);
519         ptr = MapViewOfFile( mapping, 0, 0, 0, 4096 );
520         ok( ptr != NULL, "MapViewOfFile 0 error %u\n", GetLastError() );
521         UnmapViewOfFile( ptr );
522
523         SetLastError(0xdeadbeef);
524         ptr = MapViewOfFile( mapping, FILE_MAP_WRITE, 0, 0, 4096 );
525         ok( !ptr, "MapViewOfFile FILE_MAP_WRITE succeeded\n" );
526         ok( GetLastError() == ERROR_INVALID_PARAMETER, "Wrong error %d\n", GetLastError() );
527
528         CloseHandle( mapping );
529     }
530
531     CloseHandle( file );
532
533     /* now try read-only file */
534
535     SetLastError(0xdeadbeef);
536     file = CreateFileA( testfile, GENERIC_READ, 0, NULL, OPEN_EXISTING, 0, 0 );
537     ok( file != INVALID_HANDLE_VALUE, "CreateFile error %u\n", GetLastError() );
538
539     SetLastError(0xdeadbeef);
540     mapping = CreateFileMappingA( file, NULL, PAGE_READWRITE, 0, 4096, NULL );
541     ok( !mapping, "CreateFileMapping PAGE_READWRITE succeeded\n" );
542     ok( GetLastError() == ERROR_INVALID_PARAMETER ||
543         GetLastError() == ERROR_ACCESS_DENIED, "Wrong error %d\n", GetLastError() );
544
545     SetLastError(0xdeadbeef);
546     mapping = CreateFileMappingA( file, NULL, PAGE_WRITECOPY, 0, 4096, NULL );
547     ok( mapping != 0, "CreateFileMapping PAGE_WRITECOPY error %u\n", GetLastError() );
548     CloseHandle( mapping );
549
550     SetLastError(0xdeadbeef);
551     mapping = CreateFileMappingA( file, NULL, PAGE_READONLY, 0, 4096, NULL );
552     ok( mapping != 0, "CreateFileMapping PAGE_READONLY error %u\n", GetLastError() );
553     CloseHandle( mapping );
554     CloseHandle( file );
555
556     /* now try no access file */
557
558     SetLastError(0xdeadbeef);
559     file = CreateFileA( testfile, 0, 0, NULL, OPEN_EXISTING, 0, 0 );
560     ok( file != INVALID_HANDLE_VALUE, "CreateFile error %u\n", GetLastError() );
561
562     SetLastError(0xdeadbeef);
563     mapping = CreateFileMappingA( file, NULL, PAGE_READWRITE, 0, 4096, NULL );
564     ok( !mapping, "CreateFileMapping PAGE_READWRITE succeeded\n" );
565     ok( GetLastError() == ERROR_INVALID_PARAMETER ||
566         GetLastError() == ERROR_ACCESS_DENIED, "Wrong error %d\n", GetLastError() );
567
568     SetLastError(0xdeadbeef);
569     mapping = CreateFileMappingA( file, NULL, PAGE_WRITECOPY, 0, 4096, NULL );
570     ok( !mapping, "CreateFileMapping PAGE_WRITECOPY succeeded\n" );
571     ok( GetLastError() == ERROR_INVALID_PARAMETER ||
572         GetLastError() == ERROR_ACCESS_DENIED, "Wrong error %d\n", GetLastError() );
573
574     SetLastError(0xdeadbeef);
575     mapping = CreateFileMappingA( file, NULL, PAGE_READONLY, 0, 4096, NULL );
576     ok( !mapping, "CreateFileMapping PAGE_READONLY succeeded\n" );
577     ok( GetLastError() == ERROR_INVALID_PARAMETER ||
578         GetLastError() == ERROR_ACCESS_DENIED, "Wrong error %d\n", GetLastError() );
579
580     CloseHandle( file );
581     DeleteFileA( testfile );
582
583     SetLastError(0xdeadbeef);
584     name = "Local\\Foo";
585     file = CreateFileMapping( INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0, 4096, name );
586     /* nt4 doesn't have Local\\ */
587     if (!file && GetLastError() == ERROR_PATH_NOT_FOUND)
588     {
589         name = "Foo";
590         file = CreateFileMapping( INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0, 4096, name );
591     }
592     ok( file != 0, "CreateFileMapping PAGE_READWRITE error %u\n", GetLastError() );
593
594     SetLastError(0xdeadbeef);
595     mapping = OpenFileMapping( FILE_MAP_READ, FALSE, name );
596     ok( mapping != 0, "OpenFileMapping FILE_MAP_READ error %u\n", GetLastError() );
597     SetLastError(0xdeadbeef);
598     ptr = MapViewOfFile( mapping, FILE_MAP_WRITE, 0, 0, 0 );
599     if (!ptr)
600     {
601         SIZE_T size;
602         ok( GetLastError() == ERROR_ACCESS_DENIED, "Wrong error %d\n", GetLastError() );
603         SetLastError(0xdeadbeef);
604         ptr = MapViewOfFile( mapping, FILE_MAP_READ, 0, 0, 0 );
605         ok( ptr != NULL, "MapViewOfFile FILE_MAP_READ error %u\n", GetLastError() );
606         SetLastError(0xdeadbeef);
607         size = VirtualQuery( ptr, &info, sizeof(info) );
608         ok( size == sizeof(info),
609             "VirtualQuery error %u\n", GetLastError() );
610         ok( info.BaseAddress == ptr, "%p != %p\n", info.BaseAddress, ptr );
611         ok( info.AllocationBase == ptr, "%p != %p\n", info.AllocationBase, ptr );
612         ok( info.AllocationProtect == PAGE_READONLY, "%x != PAGE_READONLY\n", info.AllocationProtect );
613         ok( info.RegionSize == 4096, "%lx != 4096\n", info.RegionSize );
614         ok( info.State == MEM_COMMIT, "%x != MEM_COMMIT\n", info.State );
615         ok( info.Protect == PAGE_READONLY, "%x != PAGE_READONLY\n", info.Protect );
616     }
617     else win_skip( "no access checks on win9x\n" );
618     UnmapViewOfFile( ptr );
619     CloseHandle( mapping );
620
621     SetLastError(0xdeadbeef);
622     mapping = OpenFileMapping( FILE_MAP_WRITE, FALSE, name );
623     ok( mapping != 0, "OpenFileMapping FILE_MAP_WRITE error %u\n", GetLastError() );
624     SetLastError(0xdeadbeef);
625     ptr = MapViewOfFile( mapping, FILE_MAP_READ, 0, 0, 0 );
626     if (!ptr)
627     {
628         SIZE_T size;
629         ok( GetLastError() == ERROR_ACCESS_DENIED, "Wrong error %d\n", GetLastError() );
630         SetLastError(0xdeadbeef);
631         ptr = MapViewOfFile( mapping, FILE_MAP_WRITE, 0, 0, 0 );
632         ok( ptr != NULL, "MapViewOfFile FILE_MAP_WRITE error %u\n", GetLastError() );
633         SetLastError(0xdeadbeef);
634         size = VirtualQuery( ptr, &info, sizeof(info) );
635         ok( size == sizeof(info),
636             "VirtualQuery error %u\n", GetLastError() );
637         ok( info.BaseAddress == ptr, "%p != %p\n", info.BaseAddress, ptr );
638         ok( info.AllocationBase == ptr, "%p != %p\n", info.AllocationBase, ptr );
639         ok( info.AllocationProtect == PAGE_READWRITE, "%x != PAGE_READWRITE\n", info.AllocationProtect );
640         ok( info.RegionSize == 4096, "%lx != 4096\n", info.RegionSize );
641         ok( info.State == MEM_COMMIT, "%x != MEM_COMMIT\n", info.State );
642         ok( info.Protect == PAGE_READWRITE, "%x != PAGE_READWRITE\n", info.Protect );
643     }
644     else win_skip( "no access checks on win9x\n" );
645     UnmapViewOfFile( ptr );
646     CloseHandle( mapping );
647
648     CloseHandle( file );
649
650     /* read/write mapping with SEC_RESERVE */
651     mapping = CreateFileMappingA(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE | SEC_RESERVE, 0, MAPPING_SIZE, NULL);
652     ok(mapping != INVALID_HANDLE_VALUE, "CreateFileMappingA failed with error %d\n", GetLastError());
653
654     ptr = MapViewOfFile(mapping, FILE_MAP_WRITE, 0, 0, 0);
655     ok(ptr != NULL, "MapViewOfFile failed with error %d\n", GetLastError());
656
657     ptr2 = MapViewOfFile(mapping, FILE_MAP_WRITE, 0, 0, 0);
658     /* on NT ptr != ptr2 but on Win9x ptr == ptr2 */
659     ok(ptr2 != NULL, "MapViewOfFile failed with error %d\n", GetLastError());
660     trace("mapping same section resulted in views %p and %p\n", ptr, ptr2);
661
662     ret = VirtualQuery(ptr, &info, sizeof(info));
663     ok(ret, "VirtualQuery failed with error %d\n", GetLastError());
664     ok(info.BaseAddress == ptr, "BaseAddress should have been %p but was %p instead\n", ptr, info.BaseAddress);
665     ok(info.AllocationBase == ptr, "AllocationBase should have been %p but was %p instead\n", ptr, info.AllocationBase);
666     ok(info.RegionSize == MAPPING_SIZE, "RegionSize should have been 0x%x but was 0x%x\n", MAPPING_SIZE, (unsigned int)info.RegionSize);
667     ok(info.State == MEM_RESERVE, "State should have been MEM_RESERVE instead of 0x%x\n", info.State);
668     if (info.Type == MEM_PRIVATE)  /* win9x is different for uncommitted mappings */
669     {
670         ok(info.AllocationProtect == PAGE_NOACCESS,
671            "AllocationProtect should have been PAGE_NOACCESS but was 0x%x\n", info.AllocationProtect);
672         ok(info.Protect == PAGE_NOACCESS,
673            "Protect should have been PAGE_NOACCESS instead of 0x%x\n", info.Protect);
674     }
675     else
676     {
677         ok(info.AllocationProtect == PAGE_READWRITE,
678            "AllocationProtect should have been PAGE_READWRITE but was 0x%x\n", info.AllocationProtect);
679         ok(info.Protect == 0, "Protect should have been 0 instead of 0x%x\n", info.Protect);
680         ok(info.Type == MEM_MAPPED, "Type should have been MEM_MAPPED instead of 0x%x\n", info.Type);
681     }
682
683     if (ptr != ptr2)
684     {
685         ret = VirtualQuery(ptr2, &info, sizeof(info));
686         ok(ret, "VirtualQuery failed with error %d\n", GetLastError());
687         ok(info.BaseAddress == ptr2,
688            "BaseAddress should have been %p but was %p instead\n", ptr2, info.BaseAddress);
689         ok(info.AllocationBase == ptr2,
690            "AllocationBase should have been %p but was %p instead\n", ptr2, info.AllocationBase);
691         ok(info.AllocationProtect == PAGE_READWRITE,
692            "AllocationProtect should have been PAGE_READWRITE but was 0x%x\n", info.AllocationProtect);
693         ok(info.RegionSize == MAPPING_SIZE,
694            "RegionSize should have been 0x%x but was 0x%x\n", MAPPING_SIZE, (unsigned int)info.RegionSize);
695         ok(info.State == MEM_RESERVE,
696            "State should have been MEM_RESERVE instead of 0x%x\n", info.State);
697         ok(info.Protect == 0,
698            "Protect should have been 0 instead of 0x%x\n", info.Protect);
699         ok(info.Type == MEM_MAPPED,
700            "Type should have been MEM_MAPPED instead of 0x%x\n", info.Type);
701     }
702
703     ptr = VirtualAlloc(ptr, 0x10000, MEM_COMMIT, PAGE_READONLY);
704     ok(ptr != NULL, "VirtualAlloc failed with error %d\n", GetLastError());
705
706     ret = VirtualQuery(ptr, &info, sizeof(info));
707     ok(ret, "VirtualQuery failed with error %d\n", GetLastError());
708     ok(info.BaseAddress == ptr, "BaseAddress should have been %p but was %p instead\n", ptr, info.BaseAddress);
709     ok(info.AllocationBase == ptr, "AllocationBase should have been %p but was %p instead\n", ptr, info.AllocationBase);
710     ok(info.RegionSize == 0x10000, "RegionSize should have been 0x10000 but was 0x%x\n", (unsigned int)info.RegionSize);
711     ok(info.State == MEM_COMMIT, "State should have been MEM_RESERVE instead of 0x%x\n", info.State);
712     ok(info.Protect == PAGE_READONLY, "Protect should have been 0 instead of 0x%x\n", info.Protect);
713     if (info.Type == MEM_PRIVATE)  /* win9x is different for uncommitted mappings */
714     {
715         ok(info.AllocationProtect == PAGE_NOACCESS,
716            "AllocationProtect should have been PAGE_NOACCESS but was 0x%x\n", info.AllocationProtect);
717     }
718     else
719     {
720         ok(info.AllocationProtect == PAGE_READWRITE,
721            "AllocationProtect should have been PAGE_READWRITE but was 0x%x\n", info.AllocationProtect);
722         ok(info.Type == MEM_MAPPED, "Type should have been MEM_MAPPED instead of 0x%x\n", info.Type);
723     }
724
725     /* shows that the VirtualAlloc above affects the mapping, not just the
726      * virtual memory in this process - it also affects all other processes
727      * with a view of the mapping, but that isn't tested here */
728     if (ptr != ptr2)
729     {
730         ret = VirtualQuery(ptr2, &info, sizeof(info));
731         ok(ret, "VirtualQuery failed with error %d\n", GetLastError());
732         ok(info.BaseAddress == ptr2,
733            "BaseAddress should have been %p but was %p instead\n", ptr2, info.BaseAddress);
734         ok(info.AllocationBase == ptr2,
735            "AllocationBase should have been %p but was %p instead\n", ptr2, info.AllocationBase);
736         ok(info.AllocationProtect == PAGE_READWRITE,
737            "AllocationProtect should have been PAGE_READWRITE but was 0x%x\n", info.AllocationProtect);
738         ok(info.RegionSize == 0x10000,
739            "RegionSize should have been 0x10000 but was 0x%x\n", (unsigned int)info.RegionSize);
740         ok(info.State == MEM_COMMIT,
741            "State should have been MEM_RESERVE instead of 0x%x\n", info.State);
742         ok(info.Protect == PAGE_READWRITE,
743            "Protect should have been 0 instead of 0x%x\n", info.Protect);
744         ok(info.Type == MEM_MAPPED, "Type should have been MEM_MAPPED instead of 0x%x\n", info.Type);
745     }
746
747     addr = VirtualAlloc( ptr, MAPPING_SIZE, MEM_RESET, PAGE_READONLY );
748     ok( addr == ptr || broken(!addr && GetLastError() == ERROR_INVALID_PARAMETER), /* win9x */
749         "VirtualAlloc failed with error %u\n", GetLastError() );
750
751     ret = VirtualFree( ptr, 0x10000, MEM_DECOMMIT );
752     ok( !ret || broken(ret) /* win9x */, "VirtualFree succeeded\n" );
753     if (!ret)
754         ok( GetLastError() == ERROR_INVALID_PARAMETER, "VirtualFree failed with %u\n", GetLastError() );
755
756     ret = UnmapViewOfFile(ptr2);
757     ok(ret, "UnmapViewOfFile failed with error %d\n", GetLastError());
758     ret = UnmapViewOfFile(ptr);
759     ok(ret, "UnmapViewOfFile failed with error %d\n", GetLastError());
760     CloseHandle(mapping);
761
762     addr = VirtualAlloc(NULL, 0x10000, MEM_COMMIT, PAGE_READONLY );
763     ok( addr != NULL, "VirtualAlloc failed with error %u\n", GetLastError() );
764
765     SetLastError(0xdeadbeef);
766     ok( !UnmapViewOfFile(addr), "UnmapViewOfFile should fail on VirtualAlloc mem\n" );
767     ok( GetLastError() == ERROR_INVALID_ADDRESS,
768         "got %u, expected ERROR_INVALID_ADDRESS\n", GetLastError());
769     SetLastError(0xdeadbeef);
770     ok( !UnmapViewOfFile((char *)addr + 0x3000), "UnmapViewOfFile should fail on VirtualAlloc mem\n" );
771     ok( GetLastError() == ERROR_INVALID_ADDRESS,
772         "got %u, expected ERROR_INVALID_ADDRESS\n", GetLastError());
773     SetLastError(0xdeadbeef);
774     ok( !UnmapViewOfFile((void *)0xdeadbeef), "UnmapViewOfFile should fail on VirtualAlloc mem\n" );
775     ok( GetLastError() == ERROR_INVALID_ADDRESS,
776        "got %u, expected ERROR_INVALID_ADDRESS\n", GetLastError());
777
778     ok( VirtualFree(addr, 0, MEM_RELEASE), "VirtualFree failed\n" );
779 }
780
781 static DWORD (WINAPI *pNtMapViewOfSection)( HANDLE handle, HANDLE process, PVOID *addr_ptr,
782                                             ULONG zero_bits, SIZE_T commit_size,
783                                             const LARGE_INTEGER *offset_ptr, SIZE_T *size_ptr,
784                                             ULONG inherit, ULONG alloc_type, ULONG protect );
785 static DWORD (WINAPI *pNtUnmapViewOfSection)( HANDLE process, PVOID addr );
786
787 static void test_NtMapViewOfSection(void)
788 {
789     HANDLE hProcess;
790
791     static const char testfile[] = "testfile.xxx";
792     static const char data[] = "test data for NtMapViewOfSection";
793     char buffer[sizeof(data)];
794     HANDLE file, mapping;
795     void *ptr;
796     BOOL ret;
797     DWORD status, written;
798     SIZE_T size, result;
799     LARGE_INTEGER offset;
800
801     pNtMapViewOfSection = (void *)GetProcAddress( GetModuleHandle("ntdll.dll"), "NtMapViewOfSection" );
802     pNtUnmapViewOfSection = (void *)GetProcAddress( GetModuleHandle("ntdll.dll"), "NtUnmapViewOfSection" );
803     if (!pNtMapViewOfSection || !pNtUnmapViewOfSection)
804     {
805         win_skip( "NtMapViewOfSection not available\n" );
806         return;
807     }
808
809     file = CreateFileA( testfile, GENERIC_READ|GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, 0 );
810     ok( file != INVALID_HANDLE_VALUE, "Failed to create test file\n" );
811     WriteFile( file, data, sizeof(data), &written, NULL );
812     SetFilePointer( file, 4096, NULL, FILE_BEGIN );
813     SetEndOfFile( file );
814
815     /* read/write mapping */
816
817     mapping = CreateFileMappingA( file, NULL, PAGE_READWRITE, 0, 4096, NULL );
818     ok( mapping != 0, "CreateFileMapping failed\n" );
819
820     hProcess = create_target_process("sleep");
821     ok(hProcess != NULL, "Can't start process\n");
822
823     ptr = NULL;
824     size = 0;
825     offset.QuadPart = 0;
826     status = pNtMapViewOfSection( mapping, hProcess, &ptr, 0, 0, &offset, &size, 1, 0, PAGE_READWRITE );
827     ok( !status, "NtMapViewOfSection failed status %x\n", status );
828
829     ret = ReadProcessMemory( hProcess, ptr, buffer, sizeof(buffer), &result );
830     ok( ret, "ReadProcessMemory failed\n" );
831     ok( result == sizeof(buffer), "ReadProcessMemory didn't read all data (%lx)\n", result );
832     ok( !memcmp( buffer, data, sizeof(buffer) ), "Wrong data read\n" );
833
834     status = pNtUnmapViewOfSection( hProcess, ptr );
835     ok( !status, "NtUnmapViewOfSection failed status %x\n", status );
836
837     CloseHandle( mapping );
838     CloseHandle( file );
839     DeleteFileA( testfile );
840
841     TerminateProcess(hProcess, 0);
842     CloseHandle(hProcess);
843 }
844
845 static void test_NtAreMappedFilesTheSame(void)
846 {
847     static const char testfile[] = "testfile.xxx";
848     HANDLE file, file2, mapping, map2;
849     void *ptr, *ptr2;
850     NTSTATUS status;
851     char path[MAX_PATH];
852
853     if (!pNtAreMappedFilesTheSame)
854     {
855         win_skip( "NtAreMappedFilesTheSame not available\n" );
856         return;
857     }
858
859     file = CreateFileA( testfile, GENERIC_READ|GENERIC_WRITE, FILE_SHARE_READ|FILE_SHARE_WRITE,
860                         NULL, CREATE_ALWAYS, 0, 0 );
861     ok( file != INVALID_HANDLE_VALUE, "CreateFile error %u\n", GetLastError() );
862     SetFilePointer( file, 4096, NULL, FILE_BEGIN );
863     SetEndOfFile( file );
864
865     mapping = CreateFileMappingA( file, NULL, PAGE_READWRITE, 0, 4096, NULL );
866     ok( mapping != 0, "CreateFileMapping error %u\n", GetLastError() );
867
868     ptr = MapViewOfFile( mapping, FILE_MAP_READ, 0, 0, 4096 );
869     ok( ptr != NULL, "MapViewOfFile FILE_MAP_READ error %u\n", GetLastError() );
870
871     file2 = CreateFileA( testfile, GENERIC_READ, FILE_SHARE_READ|FILE_SHARE_WRITE,
872                          NULL, OPEN_EXISTING, 0, 0 );
873     ok( file2 != INVALID_HANDLE_VALUE, "CreateFile error %u\n", GetLastError() );
874
875     map2 = CreateFileMappingA( file2, NULL, PAGE_READONLY, 0, 4096, NULL );
876     ok( map2 != 0, "CreateFileMapping error %u\n", GetLastError() );
877     ptr2 = MapViewOfFile( map2, FILE_MAP_READ, 0, 0, 4096 );
878     ok( ptr2 != NULL, "MapViewOfFile FILE_MAP_READ error %u\n", GetLastError() );
879     status = pNtAreMappedFilesTheSame( ptr, ptr2 );
880     ok( status == STATUS_NOT_SAME_DEVICE, "NtAreMappedFilesTheSame returned %x\n", status );
881     UnmapViewOfFile( ptr2 );
882
883     ptr2 = MapViewOfFile( mapping, FILE_MAP_READ, 0, 0, 4096 );
884     ok( ptr2 != NULL, "MapViewOfFile FILE_MAP_READ error %u\n", GetLastError() );
885     status = pNtAreMappedFilesTheSame( ptr, ptr2 );
886     ok( status == STATUS_NOT_SAME_DEVICE, "NtAreMappedFilesTheSame returned %x\n", status );
887     UnmapViewOfFile( ptr2 );
888     CloseHandle( map2 );
889
890     map2 = CreateFileMappingA( file, NULL, PAGE_READONLY, 0, 4096, NULL );
891     ok( map2 != 0, "CreateFileMapping error %u\n", GetLastError() );
892     ptr2 = MapViewOfFile( map2, FILE_MAP_READ, 0, 0, 4096 );
893     ok( ptr2 != NULL, "MapViewOfFile FILE_MAP_READ error %u\n", GetLastError() );
894     status = pNtAreMappedFilesTheSame( ptr, ptr2 );
895     ok( status == STATUS_NOT_SAME_DEVICE, "NtAreMappedFilesTheSame returned %x\n", status );
896     UnmapViewOfFile( ptr2 );
897     CloseHandle( map2 );
898     CloseHandle( file2 );
899
900     status = pNtAreMappedFilesTheSame( ptr, ptr );
901     ok( status == STATUS_NOT_SAME_DEVICE, "NtAreMappedFilesTheSame returned %x\n", status );
902
903     status = pNtAreMappedFilesTheSame( ptr, (char *)ptr + 30 );
904     ok( status == STATUS_NOT_SAME_DEVICE, "NtAreMappedFilesTheSame returned %x\n", status );
905
906     status = pNtAreMappedFilesTheSame( ptr, GetModuleHandleA("kernel32.dll") );
907     ok( status == STATUS_NOT_SAME_DEVICE, "NtAreMappedFilesTheSame returned %x\n", status );
908
909     status = pNtAreMappedFilesTheSame( ptr, (void *)0xdeadbeef );
910     ok( status == STATUS_CONFLICTING_ADDRESSES || status == STATUS_INVALID_ADDRESS,
911         "NtAreMappedFilesTheSame returned %x\n", status );
912
913     status = pNtAreMappedFilesTheSame( ptr, NULL );
914     ok( status == STATUS_INVALID_ADDRESS, "NtAreMappedFilesTheSame returned %x\n", status );
915
916     status = pNtAreMappedFilesTheSame( ptr, (void *)GetProcessHeap() );
917     ok( status == STATUS_CONFLICTING_ADDRESSES, "NtAreMappedFilesTheSame returned %x\n", status );
918
919     status = pNtAreMappedFilesTheSame( NULL, NULL );
920     ok( status == STATUS_INVALID_ADDRESS, "NtAreMappedFilesTheSame returned %x\n", status );
921
922     ptr2 = VirtualAlloc( NULL, 0x10000, MEM_COMMIT, PAGE_READWRITE );
923     ok( ptr2 != NULL, "VirtualAlloc error %u\n", GetLastError() );
924     status = pNtAreMappedFilesTheSame( ptr, ptr2 );
925     ok( status == STATUS_CONFLICTING_ADDRESSES, "NtAreMappedFilesTheSame returned %x\n", status );
926     VirtualFree( ptr2, 0, MEM_RELEASE );
927
928     UnmapViewOfFile( ptr );
929     CloseHandle( mapping );
930     CloseHandle( file );
931
932     status = pNtAreMappedFilesTheSame( GetModuleHandleA("ntdll.dll"),
933                                        GetModuleHandleA("kernel32.dll") );
934     ok( status == STATUS_NOT_SAME_DEVICE, "NtAreMappedFilesTheSame returned %x\n", status );
935     status = pNtAreMappedFilesTheSame( GetModuleHandleA("kernel32.dll"),
936                                        GetModuleHandleA("kernel32.dll") );
937     ok( status == STATUS_SUCCESS, "NtAreMappedFilesTheSame returned %x\n", status );
938     status = pNtAreMappedFilesTheSame( GetModuleHandleA("kernel32.dll"),
939                                        (char *)GetModuleHandleA("kernel32.dll") + 4096 );
940     ok( status == STATUS_SUCCESS, "NtAreMappedFilesTheSame returned %x\n", status );
941
942     GetSystemDirectoryA( path, MAX_PATH );
943     strcat( path, "\\kernel32.dll" );
944     file = CreateFileA( path, GENERIC_READ, FILE_SHARE_READ|FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, 0 );
945     ok( file != INVALID_HANDLE_VALUE, "CreateFile error %u\n", GetLastError() );
946
947     mapping = CreateFileMappingA( file, NULL, PAGE_READONLY, 0, 4096, NULL );
948     ok( mapping != 0, "CreateFileMapping error %u\n", GetLastError() );
949     ptr = MapViewOfFile( mapping, FILE_MAP_READ, 0, 0, 4096 );
950     ok( ptr != NULL, "MapViewOfFile FILE_MAP_READ error %u\n", GetLastError() );
951     status = pNtAreMappedFilesTheSame( ptr, GetModuleHandleA("kernel32.dll") );
952     ok( status == STATUS_NOT_SAME_DEVICE, "NtAreMappedFilesTheSame returned %x\n", status );
953     UnmapViewOfFile( ptr );
954     CloseHandle( mapping );
955
956     mapping = CreateFileMappingA( file, NULL, PAGE_READONLY | SEC_IMAGE, 0, 0, NULL );
957     ok( mapping != 0, "CreateFileMapping error %u\n", GetLastError() );
958     ptr = MapViewOfFile( mapping, FILE_MAP_READ, 0, 0, 0 );
959     ok( ptr != NULL, "MapViewOfFile FILE_MAP_READ error %u\n", GetLastError() );
960     status = pNtAreMappedFilesTheSame( ptr, GetModuleHandleA("kernel32.dll") );
961     todo_wine
962     ok( status == STATUS_SUCCESS, "NtAreMappedFilesTheSame returned %x\n", status );
963
964     file2 = CreateFileA( path, GENERIC_READ, FILE_SHARE_READ|FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, 0 );
965     ok( file2 != INVALID_HANDLE_VALUE, "CreateFile error %u\n", GetLastError() );
966     map2 = CreateFileMappingA( file2, NULL, PAGE_READONLY | SEC_IMAGE, 0, 0, NULL );
967     ok( map2 != 0, "CreateFileMapping error %u\n", GetLastError() );
968     ptr2 = MapViewOfFile( map2, FILE_MAP_READ, 0, 0, 0 );
969     ok( ptr2 != NULL, "MapViewOfFile FILE_MAP_READ error %u\n", GetLastError() );
970     status = pNtAreMappedFilesTheSame( ptr, ptr2 );
971     ok( status == STATUS_SUCCESS, "NtAreMappedFilesTheSame returned %x\n", status );
972     UnmapViewOfFile( ptr2 );
973     CloseHandle( map2 );
974     CloseHandle( file2 );
975
976     UnmapViewOfFile( ptr );
977     CloseHandle( mapping );
978
979     CloseHandle( file );
980     DeleteFileA( testfile );
981 }
982
983 static void test_CreateFileMapping(void)
984 {
985     HANDLE handle, handle2;
986
987     /* test case sensitivity */
988
989     SetLastError(0xdeadbeef);
990     handle = CreateFileMappingA( INVALID_HANDLE_VALUE, NULL, SEC_COMMIT | PAGE_READWRITE, 0, 0x1000,
991                                  "Wine Test Mapping");
992     ok( handle != NULL, "CreateFileMapping failed with error %u\n", GetLastError());
993     ok( GetLastError() == 0, "wrong error %u\n", GetLastError());
994
995     SetLastError(0xdeadbeef);
996     handle2 = CreateFileMappingA( INVALID_HANDLE_VALUE, NULL, SEC_COMMIT | PAGE_READWRITE, 0, 0x1000,
997                                   "Wine Test Mapping");
998     ok( handle2 != NULL, "CreateFileMapping failed with error %d\n", GetLastError());
999     ok( GetLastError() == ERROR_ALREADY_EXISTS, "wrong error %u\n", GetLastError());
1000     CloseHandle( handle2 );
1001
1002     SetLastError(0xdeadbeef);
1003     handle2 = CreateFileMappingA( INVALID_HANDLE_VALUE, NULL, SEC_COMMIT | PAGE_READWRITE, 0, 0x1000,
1004                                  "WINE TEST MAPPING");
1005     ok( handle2 != NULL, "CreateFileMapping failed with error %d\n", GetLastError());
1006     ok( GetLastError() == 0, "wrong error %u\n", GetLastError());
1007     CloseHandle( handle2 );
1008
1009     SetLastError(0xdeadbeef);
1010     handle2 = OpenFileMappingA( FILE_MAP_ALL_ACCESS, FALSE, "Wine Test Mapping");
1011     ok( handle2 != NULL, "OpenFileMapping failed with error %d\n", GetLastError());
1012     CloseHandle( handle2 );
1013
1014     SetLastError(0xdeadbeef);
1015     handle2 = OpenFileMappingA( FILE_MAP_ALL_ACCESS, FALSE, "WINE TEST MAPPING");
1016     ok( !handle2, "OpenFileMapping succeeded\n");
1017     ok( GetLastError() == ERROR_FILE_NOT_FOUND || GetLastError() == ERROR_INVALID_NAME /* win9x */,
1018         "wrong error %u\n", GetLastError());
1019
1020     CloseHandle( handle );
1021 }
1022
1023 static void test_IsBadReadPtr(void)
1024 {
1025     BOOL ret;
1026     void *ptr = (void *)0xdeadbeef;
1027     char stackvar;
1028
1029     ret = IsBadReadPtr(NULL, 0);
1030     ok(ret == FALSE, "Expected IsBadReadPtr to return FALSE, got %d\n", ret);
1031
1032     ret = IsBadReadPtr(NULL, 1);
1033     ok(ret == TRUE, "Expected IsBadReadPtr to return TRUE, got %d\n", ret);
1034
1035     ret = IsBadReadPtr(ptr, 0);
1036     ok(ret == FALSE, "Expected IsBadReadPtr to return FALSE, got %d\n", ret);
1037
1038     ret = IsBadReadPtr(ptr, 1);
1039     ok(ret == TRUE, "Expected IsBadReadPtr to return TRUE, got %d\n", ret);
1040
1041     ret = IsBadReadPtr(&stackvar, 0);
1042     ok(ret == FALSE, "Expected IsBadReadPtr to return FALSE, got %d\n", ret);
1043
1044     ret = IsBadReadPtr(&stackvar, sizeof(char));
1045     ok(ret == FALSE, "Expected IsBadReadPtr to return FALSE, got %d\n", ret);
1046 }
1047
1048 static void test_IsBadWritePtr(void)
1049 {
1050     BOOL ret;
1051     void *ptr = (void *)0xdeadbeef;
1052     char stackval;
1053
1054     ret = IsBadWritePtr(NULL, 0);
1055     ok(ret == FALSE, "Expected IsBadWritePtr to return FALSE, got %d\n", ret);
1056
1057     ret = IsBadWritePtr(NULL, 1);
1058     ok(ret == TRUE, "Expected IsBadWritePtr to return TRUE, got %d\n", ret);
1059
1060     ret = IsBadWritePtr(ptr, 0);
1061     ok(ret == FALSE, "Expected IsBadWritePtr to return FALSE, got %d\n", ret);
1062
1063     ret = IsBadWritePtr(ptr, 1);
1064     ok(ret == TRUE, "Expected IsBadWritePtr to return TRUE, got %d\n", ret);
1065
1066     ret = IsBadWritePtr(&stackval, 0);
1067     ok(ret == FALSE, "Expected IsBadWritePtr to return FALSE, got %d\n", ret);
1068
1069     ret = IsBadWritePtr(&stackval, sizeof(char));
1070     ok(ret == FALSE, "Expected IsBadWritePtr to return FALSE, got %d\n", ret);
1071 }
1072
1073 static void test_IsBadCodePtr(void)
1074 {
1075     BOOL ret;
1076     void *ptr = (void *)0xdeadbeef;
1077     char stackval;
1078
1079     ret = IsBadCodePtr(NULL);
1080     ok(ret == TRUE, "Expected IsBadCodePtr to return TRUE, got %d\n", ret);
1081
1082     ret = IsBadCodePtr(ptr);
1083     ok(ret == TRUE, "Expected IsBadCodePtr to return TRUE, got %d\n", ret);
1084
1085     ret = IsBadCodePtr((void *)&stackval);
1086     ok(ret == FALSE, "Expected IsBadCodePtr to return FALSE, got %d\n", ret);
1087 }
1088
1089 static void test_write_watch(void)
1090 {
1091     char *base;
1092     DWORD ret, size, old_prot;
1093     MEMORY_BASIC_INFORMATION info;
1094     void *results[64];
1095     ULONG_PTR count;
1096     ULONG pagesize;
1097
1098     if (!pGetWriteWatch || !pResetWriteWatch)
1099     {
1100         win_skip( "GetWriteWatch not supported\n" );
1101         return;
1102     }
1103
1104     size = 0x10000;
1105     base = VirtualAlloc( 0, size, MEM_RESERVE | MEM_COMMIT | MEM_WRITE_WATCH, PAGE_READWRITE );
1106     if (!base &&
1107         (GetLastError() == ERROR_INVALID_PARAMETER || GetLastError() == ERROR_NOT_SUPPORTED))
1108     {
1109         win_skip( "MEM_WRITE_WATCH not supported\n" );
1110         return;
1111     }
1112     ok( base != NULL, "VirtualAlloc failed %u\n", GetLastError() );
1113     ret = VirtualQuery( base, &info, sizeof(info) );
1114     ok(ret, "VirtualQuery failed %u\n", GetLastError());
1115     ok( info.BaseAddress == base, "BaseAddress %p instead of %p\n", info.BaseAddress, base );
1116     ok( info.AllocationProtect == PAGE_READWRITE, "wrong AllocationProtect %x\n", info.AllocationProtect );
1117     ok( info.RegionSize == size, "wrong RegionSize 0x%lx\n", info.RegionSize );
1118     ok( info.State == MEM_COMMIT, "wrong State 0x%x\n", info.State );
1119     ok( info.Protect == PAGE_READWRITE, "wrong Protect 0x%x\n", info.Protect );
1120     ok( info.Type == MEM_PRIVATE, "wrong Type 0x%x\n", info.Type );
1121
1122     count = 64;
1123     SetLastError( 0xdeadbeef );
1124     ret = pGetWriteWatch( 0, NULL, size, results, &count, &pagesize );
1125     ok( ret == ~0u, "GetWriteWatch succeeded %u\n", ret );
1126     ok( GetLastError() == ERROR_INVALID_PARAMETER ||
1127         broken( GetLastError() == 0xdeadbeef ), /* win98 */
1128         "wrong error %u\n", GetLastError() );
1129
1130     SetLastError( 0xdeadbeef );
1131     ret = pGetWriteWatch( 0, GetModuleHandle(0), size, results, &count, &pagesize );
1132     if (ret)
1133     {
1134         ok( ret == ~0u, "GetWriteWatch succeeded %u\n", ret );
1135         ok( GetLastError() == ERROR_INVALID_PARAMETER, "wrong error %u\n", GetLastError() );
1136     }
1137     else  /* win98 */
1138     {
1139         ok( count == 0, "wrong count %lu\n", count );
1140     }
1141
1142     ret = pGetWriteWatch( 0, base, size, results, &count, &pagesize );
1143     ok( !ret, "GetWriteWatch failed %u\n", GetLastError() );
1144     ok( count == 0, "wrong count %lu\n", count );
1145
1146     base[pagesize + 1] = 0x44;
1147
1148     count = 64;
1149     ret = pGetWriteWatch( 0, base, size, results, &count, &pagesize );
1150     ok( !ret, "GetWriteWatch failed %u\n", GetLastError() );
1151     ok( count == 1, "wrong count %lu\n", count );
1152     ok( results[0] == base + pagesize, "wrong result %p\n", results[0] );
1153
1154     count = 64;
1155     ret = pGetWriteWatch( WRITE_WATCH_FLAG_RESET, base, size, results, &count, &pagesize );
1156     ok( !ret, "GetWriteWatch failed %u\n", GetLastError() );
1157     ok( count == 1, "wrong count %lu\n", count );
1158     ok( results[0] == base + pagesize, "wrong result %p\n", results[0] );
1159
1160     count = 64;
1161     ret = pGetWriteWatch( 0, base, size, results, &count, &pagesize );
1162     ok( !ret, "GetWriteWatch failed %u\n", GetLastError() );
1163     ok( count == 0, "wrong count %lu\n", count );
1164
1165     base[2*pagesize + 3] = 0x11;
1166     base[4*pagesize + 8] = 0x11;
1167
1168     count = 64;
1169     ret = pGetWriteWatch( 0, base, size, results, &count, &pagesize );
1170     ok( !ret, "GetWriteWatch failed %u\n", GetLastError() );
1171     ok( count == 2, "wrong count %lu\n", count );
1172     ok( results[0] == base + 2*pagesize, "wrong result %p\n", results[0] );
1173     ok( results[1] == base + 4*pagesize, "wrong result %p\n", results[1] );
1174
1175     count = 64;
1176     ret = pGetWriteWatch( 0, base + 3*pagesize, 2*pagesize, results, &count, &pagesize );
1177     ok( !ret, "GetWriteWatch failed %u\n", GetLastError() );
1178     ok( count == 1, "wrong count %lu\n", count );
1179     ok( results[0] == base + 4*pagesize, "wrong result %p\n", results[0] );
1180
1181     ret = pResetWriteWatch( base, 3*pagesize );
1182     ok( !ret, "pResetWriteWatch failed %u\n", GetLastError() );
1183
1184     count = 64;
1185     ret = pGetWriteWatch( 0, base, size, results, &count, &pagesize );
1186     ok( !ret, "GetWriteWatch failed %u\n", GetLastError() );
1187     ok( count == 1, "wrong count %lu\n", count );
1188     ok( results[0] == base + 4*pagesize, "wrong result %p\n", results[0] );
1189
1190     *(DWORD *)(base + 2*pagesize - 2) = 0xdeadbeef;
1191
1192     count = 64;
1193     ret = pGetWriteWatch( 0, base, size, results, &count, &pagesize );
1194     ok( !ret, "GetWriteWatch failed %u\n", GetLastError() );
1195     ok( count == 3, "wrong count %lu\n", count );
1196     ok( results[0] == base + pagesize, "wrong result %p\n", results[0] );
1197     ok( results[1] == base + 2*pagesize, "wrong result %p\n", results[1] );
1198     ok( results[2] == base + 4*pagesize, "wrong result %p\n", results[2] );
1199
1200     count = 1;
1201     ret = pGetWriteWatch( WRITE_WATCH_FLAG_RESET, base, size, results, &count, &pagesize );
1202     ok( !ret, "GetWriteWatch failed %u\n", GetLastError() );
1203     ok( count == 1, "wrong count %lu\n", count );
1204     ok( results[0] == base + pagesize, "wrong result %p\n", results[0] );
1205
1206     count = 64;
1207     ret = pGetWriteWatch( 0, base, size, results, &count, &pagesize );
1208     ok( !ret, "GetWriteWatch failed %u\n", GetLastError() );
1209     ok( count == 2, "wrong count %lu\n", count );
1210     ok( results[0] == base + 2*pagesize, "wrong result %p\n", results[0] );
1211     ok( results[1] == base + 4*pagesize, "wrong result %p\n", results[1] );
1212
1213     /* changing protections doesn't affect watches */
1214
1215     ret = VirtualProtect( base, 3*pagesize, PAGE_READONLY, &old_prot );
1216     ok( ret, "VirtualProtect failed error %u\n", GetLastError() );
1217     ok( old_prot == PAGE_READWRITE, "wrong old prot %x\n", old_prot );
1218
1219     ret = VirtualQuery( base, &info, sizeof(info) );
1220     ok(ret, "VirtualQuery failed %u\n", GetLastError());
1221     ok( info.BaseAddress == base, "BaseAddress %p instead of %p\n", info.BaseAddress, base );
1222     ok( info.RegionSize == 3*pagesize, "wrong RegionSize 0x%lx\n", info.RegionSize );
1223     ok( info.State == MEM_COMMIT, "wrong State 0x%x\n", info.State );
1224     ok( info.Protect == PAGE_READONLY, "wrong Protect 0x%x\n", info.Protect );
1225
1226     ret = VirtualProtect( base, 3*pagesize, PAGE_READWRITE, &old_prot );
1227     ok( ret, "VirtualProtect failed error %u\n", GetLastError() );
1228     ok( old_prot == PAGE_READONLY, "wrong old prot %x\n", old_prot );
1229
1230     count = 64;
1231     ret = pGetWriteWatch( 0, base, size, results, &count, &pagesize );
1232     ok( !ret, "GetWriteWatch failed %u\n", GetLastError() );
1233     ok( count == 2, "wrong count %lu\n", count );
1234     ok( results[0] == base + 2*pagesize, "wrong result %p\n", results[0] );
1235     ok( results[1] == base + 4*pagesize, "wrong result %p\n", results[1] );
1236
1237     ret = VirtualQuery( base, &info, sizeof(info) );
1238     ok(ret, "VirtualQuery failed %u\n", GetLastError());
1239     ok( info.BaseAddress == base, "BaseAddress %p instead of %p\n", info.BaseAddress, base );
1240     ok( info.RegionSize == size, "wrong RegionSize 0x%lx\n", info.RegionSize );
1241     ok( info.State == MEM_COMMIT, "wrong State 0x%x\n", info.State );
1242     ok( info.Protect == PAGE_READWRITE, "wrong Protect 0x%x\n", info.Protect );
1243
1244     /* some invalid parameter tests */
1245
1246     SetLastError( 0xdeadbeef );
1247     count = 0;
1248     ret = pGetWriteWatch( 0, base, size, results, &count, &pagesize );
1249     if (ret)
1250     {
1251         ok( ret == ~0u, "GetWriteWatch succeeded %u\n", ret );
1252         ok( GetLastError() == ERROR_INVALID_PARAMETER, "wrong error %u\n", GetLastError() );
1253
1254         SetLastError( 0xdeadbeef );
1255         ret = pGetWriteWatch( 0, base, size, results, NULL, &pagesize );
1256         ok( ret == ~0u, "GetWriteWatch succeeded %u\n", ret );
1257         ok( GetLastError() == ERROR_NOACCESS, "wrong error %u\n", GetLastError() );
1258
1259         SetLastError( 0xdeadbeef );
1260         count = 64;
1261         ret = pGetWriteWatch( 0, base, size, results, &count, NULL );
1262         ok( ret == ~0u, "GetWriteWatch succeeded %u\n", ret );
1263         ok( GetLastError() == ERROR_NOACCESS, "wrong error %u\n", GetLastError() );
1264
1265         SetLastError( 0xdeadbeef );
1266         count = 64;
1267         ret = pGetWriteWatch( 0, base, size, NULL, &count, &pagesize );
1268         ok( ret == ~0u, "GetWriteWatch succeeded %u\n", ret );
1269         ok( GetLastError() == ERROR_NOACCESS, "wrong error %u\n", GetLastError() );
1270
1271         SetLastError( 0xdeadbeef );
1272         count = 0;
1273         ret = pGetWriteWatch( 0, base, size, NULL, &count, &pagesize );
1274         ok( ret == ~0u, "GetWriteWatch succeeded %u\n", ret );
1275         ok( GetLastError() == ERROR_INVALID_PARAMETER, "wrong error %u\n", GetLastError() );
1276
1277         SetLastError( 0xdeadbeef );
1278         count = 64;
1279         ret = pGetWriteWatch( 0xdeadbeef, base, size, results, &count, &pagesize );
1280         ok( ret == ~0u, "GetWriteWatch succeeded %u\n", ret );
1281         ok( GetLastError() == ERROR_INVALID_PARAMETER, "wrong error %u\n", GetLastError() );
1282
1283         SetLastError( 0xdeadbeef );
1284         count = 64;
1285         ret = pGetWriteWatch( 0, base, 0, results, &count, &pagesize );
1286         ok( ret == ~0u, "GetWriteWatch succeeded %u\n", ret );
1287         ok( GetLastError() == ERROR_INVALID_PARAMETER, "wrong error %u\n", GetLastError() );
1288
1289         SetLastError( 0xdeadbeef );
1290         count = 64;
1291         ret = pGetWriteWatch( 0, base, size * 2, results, &count, &pagesize );
1292         ok( ret == ~0u, "GetWriteWatch succeeded %u\n", ret );
1293         ok( GetLastError() == ERROR_INVALID_PARAMETER, "wrong error %u\n", GetLastError() );
1294
1295         SetLastError( 0xdeadbeef );
1296         count = 64;
1297         ret = pGetWriteWatch( 0, base + size - pagesize, pagesize + 1, results, &count, &pagesize );
1298         ok( ret == ~0u, "GetWriteWatch succeeded %u\n", ret );
1299         ok( GetLastError() == ERROR_INVALID_PARAMETER, "wrong error %u\n", GetLastError() );
1300
1301         SetLastError( 0xdeadbeef );
1302         ret = pResetWriteWatch( base, 0 );
1303         ok( ret == ~0u, "ResetWriteWatch succeeded %u\n", ret );
1304         ok( GetLastError() == ERROR_INVALID_PARAMETER, "wrong error %u\n", GetLastError() );
1305
1306         SetLastError( 0xdeadbeef );
1307         ret = pResetWriteWatch( GetModuleHandle(0), size );
1308         ok( ret == ~0u, "ResetWriteWatch succeeded %u\n", ret );
1309         ok( GetLastError() == ERROR_INVALID_PARAMETER, "wrong error %u\n", GetLastError() );
1310     }
1311     else  /* win98 is completely different */
1312     {
1313         SetLastError( 0xdeadbeef );
1314         count = 64;
1315         ret = pGetWriteWatch( 0, base, size, NULL, &count, &pagesize );
1316         ok( ret == ERROR_INVALID_PARAMETER, "GetWriteWatch succeeded %u\n", ret );
1317         ok( GetLastError() == 0xdeadbeef, "wrong error %u\n", GetLastError() );
1318
1319         count = 0;
1320         ret = pGetWriteWatch( 0, base, size, NULL, &count, &pagesize );
1321         ok( !ret, "GetWriteWatch failed %u\n", ret );
1322
1323         count = 64;
1324         ret = pGetWriteWatch( 0xdeadbeef, base, size, results, &count, &pagesize );
1325         ok( !ret, "GetWriteWatch failed %u\n", ret );
1326
1327         count = 64;
1328         ret = pGetWriteWatch( 0, base, 0, results, &count, &pagesize );
1329         ok( !ret, "GetWriteWatch failed %u\n", ret );
1330
1331         ret = pResetWriteWatch( base, 0 );
1332         ok( !ret, "ResetWriteWatch failed %u\n", ret );
1333
1334         ret = pResetWriteWatch( GetModuleHandle(0), size );
1335         ok( !ret, "ResetWriteWatch failed %u\n", ret );
1336     }
1337
1338     VirtualFree( base, 0, MEM_FREE );
1339
1340     base = VirtualAlloc( 0, size, MEM_RESERVE | MEM_WRITE_WATCH, PAGE_READWRITE );
1341     ok( base != NULL, "VirtualAlloc failed %u\n", GetLastError() );
1342     VirtualFree( base, 0, MEM_FREE );
1343
1344     base = VirtualAlloc( 0, size, MEM_WRITE_WATCH, PAGE_READWRITE );
1345     ok( !base, "VirtualAlloc succeeded\n" );
1346     ok( GetLastError() == ERROR_INVALID_PARAMETER, "wrong error %u\n", GetLastError() );
1347
1348     /* initial protect doesn't matter */
1349
1350     base = VirtualAlloc( 0, size, MEM_RESERVE | MEM_WRITE_WATCH, PAGE_NOACCESS );
1351     ok( base != NULL, "VirtualAlloc failed %u\n", GetLastError() );
1352     base = VirtualAlloc( base, size, MEM_COMMIT, PAGE_NOACCESS );
1353     ok( base != NULL, "VirtualAlloc failed %u\n", GetLastError() );
1354
1355     count = 64;
1356     ret = pGetWriteWatch( 0, base, size, results, &count, &pagesize );
1357     ok( !ret, "GetWriteWatch failed %u\n", GetLastError() );
1358     ok( count == 0, "wrong count %lu\n", count );
1359
1360     ret = VirtualProtect( base, 6*pagesize, PAGE_READWRITE, &old_prot );
1361     ok( ret, "VirtualProtect failed error %u\n", GetLastError() );
1362     ok( old_prot == PAGE_NOACCESS, "wrong old prot %x\n", old_prot );
1363
1364     base[5*pagesize + 200] = 3;
1365
1366     ret = VirtualProtect( base, 6*pagesize, PAGE_NOACCESS, &old_prot );
1367     ok( ret, "VirtualProtect failed error %u\n", GetLastError() );
1368     ok( old_prot == PAGE_READWRITE, "wrong old prot %x\n", old_prot );
1369
1370     count = 64;
1371     ret = pGetWriteWatch( 0, base, size, results, &count, &pagesize );
1372     ok( !ret, "GetWriteWatch failed %u\n", GetLastError() );
1373     ok( count == 1, "wrong count %lu\n", count );
1374     ok( results[0] == base + 5*pagesize, "wrong result %p\n", results[0] );
1375
1376     ret = VirtualFree( base, size, MEM_DECOMMIT );
1377     ok( ret, "VirtualFree failed %u\n", GetLastError() );
1378
1379     count = 64;
1380     ret = pGetWriteWatch( 0, base, size, results, &count, &pagesize );
1381     ok( !ret, "GetWriteWatch failed %u\n", GetLastError() );
1382     ok( count == 1 || broken(count == 0), /* win98 */
1383         "wrong count %lu\n", count );
1384     if (count) ok( results[0] == base + 5*pagesize, "wrong result %p\n", results[0] );
1385
1386     VirtualFree( base, 0, MEM_FREE );
1387 }
1388
1389 static void test_VirtualProtect(void)
1390 {
1391     static const struct test_data
1392     {
1393         DWORD prot_set, prot_get;
1394     } td[] =
1395     {
1396         { 0, 0 }, /* 0x00 */
1397         { PAGE_NOACCESS, PAGE_NOACCESS }, /* 0x01 */
1398         { PAGE_READONLY, PAGE_READONLY }, /* 0x02 */
1399         { PAGE_READONLY | PAGE_NOACCESS, 0 }, /* 0x03 */
1400         { PAGE_READWRITE, PAGE_READWRITE }, /* 0x04 */
1401         { PAGE_READWRITE | PAGE_NOACCESS, 0 }, /* 0x05 */
1402         { PAGE_READWRITE | PAGE_READONLY, 0 }, /* 0x06 */
1403         { PAGE_READWRITE | PAGE_READONLY | PAGE_NOACCESS, 0 }, /* 0x07 */
1404         { PAGE_WRITECOPY, 0 }, /* 0x08 */
1405         { PAGE_WRITECOPY | PAGE_NOACCESS, 0 }, /* 0x09 */
1406         { PAGE_WRITECOPY | PAGE_READONLY, 0 }, /* 0x0a */
1407         { PAGE_WRITECOPY | PAGE_NOACCESS | PAGE_READONLY, 0 }, /* 0x0b */
1408         { PAGE_WRITECOPY | PAGE_READWRITE, 0 }, /* 0x0c */
1409         { PAGE_WRITECOPY | PAGE_READWRITE | PAGE_NOACCESS, 0 }, /* 0x0d */
1410         { PAGE_WRITECOPY | PAGE_READWRITE | PAGE_READONLY, 0 }, /* 0x0e */
1411         { PAGE_WRITECOPY | PAGE_READWRITE | PAGE_READONLY | PAGE_NOACCESS, 0 }, /* 0x0f */
1412
1413         { PAGE_EXECUTE, PAGE_EXECUTE }, /* 0x10 */
1414         { PAGE_EXECUTE_READ, PAGE_EXECUTE_READ }, /* 0x20 */
1415         { PAGE_EXECUTE_READ | PAGE_EXECUTE, 0 }, /* 0x30 */
1416         { PAGE_EXECUTE_READWRITE, PAGE_EXECUTE_READWRITE }, /* 0x40 */
1417         { PAGE_EXECUTE_READWRITE | PAGE_EXECUTE, 0 }, /* 0x50 */
1418         { PAGE_EXECUTE_READWRITE | PAGE_EXECUTE_READ, 0 }, /* 0x60 */
1419         { PAGE_EXECUTE_READWRITE | PAGE_EXECUTE_READ | PAGE_EXECUTE, 0 }, /* 0x70 */
1420         { PAGE_EXECUTE_WRITECOPY, 0 }, /* 0x80 */
1421         { PAGE_EXECUTE_WRITECOPY | PAGE_EXECUTE, 0 }, /* 0x90 */
1422         { PAGE_EXECUTE_WRITECOPY | PAGE_EXECUTE_READ, 0 }, /* 0xa0 */
1423         { PAGE_EXECUTE_WRITECOPY | PAGE_EXECUTE_READ | PAGE_EXECUTE, 0 }, /* 0xb0 */
1424         { PAGE_EXECUTE_WRITECOPY | PAGE_EXECUTE_READWRITE, 0 }, /* 0xc0 */
1425         { PAGE_EXECUTE_WRITECOPY | PAGE_EXECUTE_READWRITE | PAGE_EXECUTE, 0 }, /* 0xd0 */
1426         { PAGE_EXECUTE_WRITECOPY | PAGE_EXECUTE_READWRITE | PAGE_EXECUTE_READ, 0 }, /* 0xe0 */
1427         { PAGE_EXECUTE_WRITECOPY | PAGE_EXECUTE_READWRITE | PAGE_EXECUTE_READ | PAGE_EXECUTE, 0 } /* 0xf0 */
1428     };
1429     char *base;
1430     DWORD ret, old_prot, rw_prot, exec_prot, i, j;
1431     MEMORY_BASIC_INFORMATION info;
1432     SYSTEM_INFO si;
1433
1434     GetSystemInfo(&si);
1435     trace("system page size %#x\n", si.dwPageSize);
1436
1437     SetLastError(0xdeadbeef);
1438     base = VirtualAlloc(0, si.dwPageSize, MEM_RESERVE | MEM_COMMIT, PAGE_NOACCESS);
1439     ok(base != NULL, "VirtualAlloc failed %d\n", GetLastError());
1440
1441     for (i = 0; i < sizeof(td)/sizeof(td[0]); i++)
1442     {
1443         SetLastError(0xdeadbeef);
1444         ret = VirtualQuery(base, &info, sizeof(info));
1445         ok(ret, "VirtualQuery failed %d\n", GetLastError());
1446         ok(info.BaseAddress == base, "%d: got %p != expected %p\n", i, info.BaseAddress, base);
1447         ok(info.RegionSize == si.dwPageSize, "%d: got %#lx != expected %#x\n", i, info.RegionSize, si.dwPageSize);
1448         ok(info.Protect == PAGE_NOACCESS, "%d: got %#x != expected PAGE_NOACCESS\n", i, info.Protect);
1449         ok(info.AllocationBase == base, "%d: %p != %p\n", i, info.AllocationBase, base);
1450         ok(info.AllocationProtect == PAGE_NOACCESS, "%d: %#x != PAGE_NOACCESS\n", i, info.AllocationProtect);
1451         ok(info.State == MEM_COMMIT, "%d: %#x != MEM_COMMIT\n", i, info.State);
1452         ok(info.Type == MEM_PRIVATE, "%d: %#x != MEM_PRIVATE\n", i, info.Type);
1453
1454         old_prot = 0xdeadbeef;
1455         SetLastError(0xdeadbeef);
1456         ret = VirtualProtect(base, si.dwPageSize, td[i].prot_set, &old_prot);
1457         if (td[i].prot_get)
1458         {
1459             ok(ret, "%d: VirtualProtect error %d\n", i, GetLastError());
1460             ok(old_prot == PAGE_NOACCESS, "%d: got %#x != expected PAGE_NOACCESS\n", i, old_prot);
1461
1462             SetLastError(0xdeadbeef);
1463             ret = VirtualQuery(base, &info, sizeof(info));
1464             ok(ret, "VirtualQuery failed %d\n", GetLastError());
1465             ok(info.BaseAddress == base, "%d: got %p != expected %p\n", i, info.BaseAddress, base);
1466             ok(info.RegionSize == si.dwPageSize, "%d: got %#lx != expected %#x\n", i, info.RegionSize, si.dwPageSize);
1467             ok(info.Protect == td[i].prot_get, "%d: got %#x != expected %#x\n", i, info.Protect, td[i].prot_get);
1468             ok(info.AllocationBase == base, "%d: %p != %p\n", i, info.AllocationBase, base);
1469             ok(info.AllocationProtect == PAGE_NOACCESS, "%d: %#x != PAGE_NOACCESS\n", i, info.AllocationProtect);
1470             ok(info.State == MEM_COMMIT, "%d: %#x != MEM_COMMIT\n", i, info.State);
1471             ok(info.Type == MEM_PRIVATE, "%d: %#x != MEM_PRIVATE\n", i, info.Type);
1472         }
1473         else
1474         {
1475             ok(!ret, "%d: VirtualProtect should fail\n", i);
1476             ok(GetLastError() == ERROR_INVALID_PARAMETER, "%d: expected ERROR_INVALID_PARAMETER, got %d\n", i, GetLastError());
1477         }
1478
1479         old_prot = 0xdeadbeef;
1480         SetLastError(0xdeadbeef);
1481         ret = VirtualProtect(base, si.dwPageSize, PAGE_NOACCESS, &old_prot);
1482         ok(ret, "%d: VirtualProtect error %d\n", i, GetLastError());
1483         if (td[i].prot_get)
1484             ok(old_prot == td[i].prot_get, "%d: got %#x != expected %#x\n", i, old_prot, td[i].prot_get);
1485         else
1486             ok(old_prot == PAGE_NOACCESS, "%d: got %#x != expected PAGE_NOACCESS\n", i, old_prot);
1487     }
1488
1489     exec_prot = 0;
1490
1491     for (i = 0; i <= 4; i++)
1492     {
1493         rw_prot = 0;
1494
1495         for (j = 0; j <= 4; j++)
1496         {
1497             DWORD prot = exec_prot | rw_prot;
1498
1499             SetLastError(0xdeadbeef);
1500             ret = VirtualProtect(base, si.dwPageSize, prot, &old_prot);
1501             if ((rw_prot && exec_prot) || (!rw_prot && !exec_prot))
1502             {
1503                 ok(!ret, "VirtualProtect(%02x) should fail\n", prot);
1504                 ok(GetLastError() == ERROR_INVALID_PARAMETER, "expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
1505             }
1506             else
1507             {
1508                 if (prot & (PAGE_WRITECOPY | PAGE_EXECUTE_WRITECOPY))
1509                 {
1510                     ok(!ret, "VirtualProtect(%02x) should fail\n", prot);
1511                     ok(GetLastError() == ERROR_INVALID_PARAMETER, "expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
1512                 }
1513                 else
1514                     ok(ret, "VirtualProtect(%02x) error %d\n", prot, GetLastError());
1515             }
1516
1517             rw_prot = 1 << j;
1518         }
1519
1520         exec_prot = 1 << (i + 4);
1521     }
1522
1523     VirtualFree(base, 0, MEM_FREE);
1524 }
1525
1526 static BOOL is_mem_writable(DWORD prot)
1527 {
1528     switch (prot & 0xff)
1529     {
1530         case PAGE_READWRITE:
1531         case PAGE_WRITECOPY:
1532         case PAGE_EXECUTE_READWRITE:
1533         case PAGE_EXECUTE_WRITECOPY:
1534             return TRUE;
1535
1536         default:
1537             return FALSE;
1538     }
1539 }
1540
1541 static void test_VirtualAlloc_protection(void)
1542 {
1543     static const struct test_data
1544     {
1545         DWORD prot;
1546         BOOL success;
1547     } td[] =
1548     {
1549         { 0, FALSE }, /* 0x00 */
1550         { PAGE_NOACCESS, TRUE }, /* 0x01 */
1551         { PAGE_READONLY, TRUE }, /* 0x02 */
1552         { PAGE_READONLY | PAGE_NOACCESS, FALSE }, /* 0x03 */
1553         { PAGE_READWRITE, TRUE }, /* 0x04 */
1554         { PAGE_READWRITE | PAGE_NOACCESS, FALSE }, /* 0x05 */
1555         { PAGE_READWRITE | PAGE_READONLY, FALSE }, /* 0x06 */
1556         { PAGE_READWRITE | PAGE_READONLY | PAGE_NOACCESS, FALSE }, /* 0x07 */
1557         { PAGE_WRITECOPY, FALSE }, /* 0x08 */
1558         { PAGE_WRITECOPY | PAGE_NOACCESS, FALSE }, /* 0x09 */
1559         { PAGE_WRITECOPY | PAGE_READONLY, FALSE }, /* 0x0a */
1560         { PAGE_WRITECOPY | PAGE_NOACCESS | PAGE_READONLY, FALSE }, /* 0x0b */
1561         { PAGE_WRITECOPY | PAGE_READWRITE, FALSE }, /* 0x0c */
1562         { PAGE_WRITECOPY | PAGE_READWRITE | PAGE_NOACCESS, FALSE }, /* 0x0d */
1563         { PAGE_WRITECOPY | PAGE_READWRITE | PAGE_READONLY, FALSE }, /* 0x0e */
1564         { PAGE_WRITECOPY | PAGE_READWRITE | PAGE_READONLY | PAGE_NOACCESS, FALSE }, /* 0x0f */
1565
1566         { PAGE_EXECUTE, TRUE }, /* 0x10 */
1567         { PAGE_EXECUTE_READ, TRUE }, /* 0x20 */
1568         { PAGE_EXECUTE_READ | PAGE_EXECUTE, FALSE }, /* 0x30 */
1569         { PAGE_EXECUTE_READWRITE, TRUE }, /* 0x40 */
1570         { PAGE_EXECUTE_READWRITE | PAGE_EXECUTE, FALSE }, /* 0x50 */
1571         { PAGE_EXECUTE_READWRITE | PAGE_EXECUTE_READ, FALSE }, /* 0x60 */
1572         { PAGE_EXECUTE_READWRITE | PAGE_EXECUTE_READ | PAGE_EXECUTE, FALSE }, /* 0x70 */
1573         { PAGE_EXECUTE_WRITECOPY, FALSE }, /* 0x80 */
1574         { PAGE_EXECUTE_WRITECOPY | PAGE_EXECUTE, FALSE }, /* 0x90 */
1575         { PAGE_EXECUTE_WRITECOPY | PAGE_EXECUTE_READ, FALSE }, /* 0xa0 */
1576         { PAGE_EXECUTE_WRITECOPY | PAGE_EXECUTE_READ | PAGE_EXECUTE, FALSE }, /* 0xb0 */
1577         { PAGE_EXECUTE_WRITECOPY | PAGE_EXECUTE_READWRITE, FALSE }, /* 0xc0 */
1578         { PAGE_EXECUTE_WRITECOPY | PAGE_EXECUTE_READWRITE | PAGE_EXECUTE, FALSE }, /* 0xd0 */
1579         { PAGE_EXECUTE_WRITECOPY | PAGE_EXECUTE_READWRITE | PAGE_EXECUTE_READ, FALSE }, /* 0xe0 */
1580         { PAGE_EXECUTE_WRITECOPY | PAGE_EXECUTE_READWRITE | PAGE_EXECUTE_READ | PAGE_EXECUTE, FALSE } /* 0xf0 */
1581     };
1582     char *base;
1583     DWORD ret, i;
1584     MEMORY_BASIC_INFORMATION info;
1585     SYSTEM_INFO si;
1586
1587     GetSystemInfo(&si);
1588     trace("system page size %#x\n", si.dwPageSize);
1589
1590     for (i = 0; i < sizeof(td)/sizeof(td[0]); i++)
1591     {
1592         SetLastError(0xdeadbeef);
1593         base = VirtualAlloc(0, si.dwPageSize, MEM_COMMIT, td[i].prot);
1594
1595         if (td[i].success)
1596         {
1597             ok(base != NULL, "%d: VirtualAlloc failed %d\n", i, GetLastError());
1598
1599             SetLastError(0xdeadbeef);
1600             ret = VirtualQuery(base, &info, sizeof(info));
1601             ok(ret, "VirtualQuery failed %d\n", GetLastError());
1602             ok(info.BaseAddress == base, "%d: got %p != expected %p\n", i, info.BaseAddress, base);
1603             ok(info.RegionSize == si.dwPageSize, "%d: got %#lx != expected %#x\n", i, info.RegionSize, si.dwPageSize);
1604             ok(info.Protect == td[i].prot, "%d: got %#x != expected %#x\n", i, info.Protect, td[i].prot);
1605             ok(info.AllocationBase == base, "%d: %p != %p\n", i, info.AllocationBase, base);
1606             ok(info.AllocationProtect == td[i].prot, "%d: %#x != %#x\n", i, info.AllocationProtect, td[i].prot);
1607             ok(info.State == MEM_COMMIT, "%d: %#x != MEM_COMMIT\n", i, info.State);
1608             ok(info.Type == MEM_PRIVATE, "%d: %#x != MEM_PRIVATE\n", i, info.Type);
1609
1610             if (is_mem_writable(info.Protect))
1611             {
1612                 base[0] = 0xfe;
1613
1614                 SetLastError(0xdeadbeef);
1615                 ret = VirtualQuery(base, &info, sizeof(info));
1616                 ok(ret, "VirtualQuery failed %d\n", GetLastError());
1617                 ok(info.Protect == td[i].prot, "%d: got %#x != expected %#x\n", i, info.Protect, td[i].prot);
1618             }
1619
1620             VirtualFree(base, 0, MEM_FREE);
1621         }
1622         else
1623         {
1624             ok(!base, "%d: VirtualAlloc should fail\n", i);
1625             ok(GetLastError() == ERROR_INVALID_PARAMETER, "%d: expected ERROR_INVALID_PARAMETER, got %d\n", i, GetLastError());
1626         }
1627     }
1628 }
1629
1630 static void test_CreateFileMapping_protection(void)
1631 {
1632     static const struct test_data
1633     {
1634         DWORD prot;
1635         BOOL success;
1636         DWORD prot_after_write;
1637     } td[] =
1638     {
1639         { 0, FALSE, 0 }, /* 0x00 */
1640         { PAGE_NOACCESS, FALSE, PAGE_NOACCESS }, /* 0x01 */
1641         { PAGE_READONLY, TRUE, PAGE_READONLY }, /* 0x02 */
1642         { PAGE_READONLY | PAGE_NOACCESS, FALSE, PAGE_NOACCESS }, /* 0x03 */
1643         { PAGE_READWRITE, TRUE, PAGE_READWRITE }, /* 0x04 */
1644         { PAGE_READWRITE | PAGE_NOACCESS, FALSE, PAGE_NOACCESS }, /* 0x05 */
1645         { PAGE_READWRITE | PAGE_READONLY, FALSE, PAGE_NOACCESS }, /* 0x06 */
1646         { PAGE_READWRITE | PAGE_READONLY | PAGE_NOACCESS, FALSE, PAGE_NOACCESS }, /* 0x07 */
1647         { PAGE_WRITECOPY, TRUE, PAGE_READWRITE }, /* 0x08 */
1648         { PAGE_WRITECOPY | PAGE_NOACCESS, FALSE, PAGE_NOACCESS }, /* 0x09 */
1649         { PAGE_WRITECOPY | PAGE_READONLY, FALSE, PAGE_NOACCESS }, /* 0x0a */
1650         { PAGE_WRITECOPY | PAGE_NOACCESS | PAGE_READONLY, FALSE, PAGE_NOACCESS }, /* 0x0b */
1651         { PAGE_WRITECOPY | PAGE_READWRITE, FALSE, PAGE_NOACCESS }, /* 0x0c */
1652         { PAGE_WRITECOPY | PAGE_READWRITE | PAGE_NOACCESS, FALSE, PAGE_NOACCESS }, /* 0x0d */
1653         { PAGE_WRITECOPY | PAGE_READWRITE | PAGE_READONLY, FALSE, PAGE_NOACCESS }, /* 0x0e */
1654         { PAGE_WRITECOPY | PAGE_READWRITE | PAGE_READONLY | PAGE_NOACCESS, FALSE, PAGE_NOACCESS }, /* 0x0f */
1655
1656         { PAGE_EXECUTE, FALSE, PAGE_EXECUTE }, /* 0x10 */
1657         { PAGE_EXECUTE_READ, TRUE, PAGE_EXECUTE_READ }, /* 0x20 */
1658         { PAGE_EXECUTE_READ | PAGE_EXECUTE, FALSE, PAGE_EXECUTE_READ }, /* 0x30 */
1659         { PAGE_EXECUTE_READWRITE, TRUE, PAGE_EXECUTE_READWRITE }, /* 0x40 */
1660         { PAGE_EXECUTE_READWRITE | PAGE_EXECUTE, FALSE, PAGE_NOACCESS }, /* 0x50 */
1661         { PAGE_EXECUTE_READWRITE | PAGE_EXECUTE_READ, FALSE, PAGE_NOACCESS }, /* 0x60 */
1662         { PAGE_EXECUTE_READWRITE | PAGE_EXECUTE_READ | PAGE_EXECUTE, FALSE, PAGE_NOACCESS }, /* 0x70 */
1663         { PAGE_EXECUTE_WRITECOPY, TRUE, PAGE_EXECUTE_READWRITE }, /* 0x80 */
1664         { PAGE_EXECUTE_WRITECOPY | PAGE_EXECUTE, FALSE, PAGE_NOACCESS }, /* 0x90 */
1665         { PAGE_EXECUTE_WRITECOPY | PAGE_EXECUTE_READ, FALSE, PAGE_NOACCESS }, /* 0xa0 */
1666         { PAGE_EXECUTE_WRITECOPY | PAGE_EXECUTE_READ | PAGE_EXECUTE, FALSE, PAGE_NOACCESS }, /* 0xb0 */
1667         { PAGE_EXECUTE_WRITECOPY | PAGE_EXECUTE_READWRITE, FALSE, PAGE_NOACCESS }, /* 0xc0 */
1668         { PAGE_EXECUTE_WRITECOPY | PAGE_EXECUTE_READWRITE | PAGE_EXECUTE, FALSE, PAGE_NOACCESS }, /* 0xd0 */
1669         { PAGE_EXECUTE_WRITECOPY | PAGE_EXECUTE_READWRITE | PAGE_EXECUTE_READ, FALSE, PAGE_NOACCESS }, /* 0xe0 */
1670         { PAGE_EXECUTE_WRITECOPY | PAGE_EXECUTE_READWRITE | PAGE_EXECUTE_READ | PAGE_EXECUTE, FALSE, PAGE_NOACCESS } /* 0xf0 */
1671     };
1672     char *base;
1673     DWORD ret, i, alloc_prot, prot, old_prot;
1674     MEMORY_BASIC_INFORMATION info;
1675     SYSTEM_INFO si;
1676     char temp_path[MAX_PATH];
1677     char file_name[MAX_PATH];
1678     HANDLE hfile, hmap;
1679     BOOL page_exec_supported = TRUE;
1680
1681     GetSystemInfo(&si);
1682     trace("system page size %#x\n", si.dwPageSize);
1683
1684     GetTempPath(MAX_PATH, temp_path);
1685     GetTempFileName(temp_path, "map", 0, file_name);
1686
1687     SetLastError(0xdeadbeef);
1688     hfile = CreateFile(file_name, GENERIC_READ|GENERIC_WRITE|GENERIC_EXECUTE, 0, NULL, CREATE_ALWAYS, 0, 0);
1689     ok(hfile != INVALID_HANDLE_VALUE, "CreateFile(%s) error %d\n", file_name, GetLastError());
1690     SetFilePointer(hfile, si.dwPageSize, NULL, FILE_BEGIN);
1691     SetEndOfFile(hfile);
1692
1693     for (i = 0; i < sizeof(td)/sizeof(td[0]); i++)
1694     {
1695         SetLastError(0xdeadbeef);
1696         hmap = CreateFileMapping(hfile, NULL, td[i].prot | SEC_COMMIT, 0, si.dwPageSize, NULL);
1697
1698         if (td[i].success)
1699         {
1700             if (!hmap)
1701             {
1702                 trace("%d: CreateFileMapping(%04x) failed: %d\n", i, td[i].prot, GetLastError());
1703                 /* NT4 and win2k don't support EXEC on file mappings */
1704                 if (td[i].prot == PAGE_EXECUTE_READ || td[i].prot == PAGE_EXECUTE_READWRITE)
1705                 {
1706                     page_exec_supported = FALSE;
1707                     ok(broken(!hmap), "%d: CreateFileMapping doesn't support PAGE_EXECUTE\n", i);
1708                     continue;
1709                 }
1710                 /* Vista+ supports PAGE_EXECUTE_WRITECOPY, earlier versions don't */
1711                 if (td[i].prot == PAGE_EXECUTE_WRITECOPY)
1712                 {
1713                     page_exec_supported = FALSE;
1714                     ok(broken(!hmap), "%d: CreateFileMapping doesn't support PAGE_EXECUTE_WRITECOPY\n", i);
1715                     continue;
1716                 }
1717             }
1718             ok(hmap != 0, "%d: CreateFileMapping(%04x) error %d\n", i, td[i].prot, GetLastError());
1719
1720             base = MapViewOfFile(hmap, FILE_MAP_READ, 0, 0, 0);
1721             ok(base != NULL, "%d: MapViewOfFile failed %d\n", i, GetLastError());
1722
1723             SetLastError(0xdeadbeef);
1724             ret = VirtualQuery(base, &info, sizeof(info));
1725             ok(ret, "VirtualQuery failed %d\n", GetLastError());
1726             ok(info.BaseAddress == base, "%d: got %p != expected %p\n", i, info.BaseAddress, base);
1727             ok(info.RegionSize == si.dwPageSize, "%d: got %#lx != expected %#x\n", i, info.RegionSize, si.dwPageSize);
1728             ok(info.Protect == PAGE_READONLY, "%d: got %#x != expected PAGE_READONLY\n", i, info.Protect);
1729             ok(info.AllocationBase == base, "%d: %p != %p\n", i, info.AllocationBase, base);
1730             ok(info.AllocationProtect == PAGE_READONLY, "%d: %#x != PAGE_READONLY\n", i, info.AllocationProtect);
1731             ok(info.State == MEM_COMMIT, "%d: %#x != MEM_COMMIT\n", i, info.State);
1732             ok(info.Type == MEM_MAPPED, "%d: %#x != MEM_MAPPED\n", i, info.Type);
1733
1734             if (is_mem_writable(info.Protect))
1735             {
1736                 base[0] = 0xfe;
1737
1738                 SetLastError(0xdeadbeef);
1739                 ret = VirtualQuery(base, &info, sizeof(info));
1740                 ok(ret, "VirtualQuery failed %d\n", GetLastError());
1741                 ok(info.Protect == td[i].prot, "%d: got %#x != expected %#x\n", i, info.Protect, td[i].prot);
1742             }
1743
1744             UnmapViewOfFile(base);
1745             CloseHandle(hmap);
1746         }
1747         else
1748         {
1749             ok(!hmap, "%d: CreateFileMapping should fail\n", i);
1750             ok(GetLastError() == ERROR_INVALID_PARAMETER, "%d: expected ERROR_INVALID_PARAMETER, got %d\n", i, GetLastError());
1751         }
1752     }
1753
1754     if (page_exec_supported) alloc_prot = PAGE_EXECUTE_READWRITE;
1755     else alloc_prot = PAGE_READWRITE;
1756     SetLastError(0xdeadbeef);
1757     hmap = CreateFileMapping(hfile, NULL, alloc_prot, 0, si.dwPageSize, NULL);
1758     ok(hmap != 0, "%d: CreateFileMapping error %d\n", i, GetLastError());
1759
1760     SetLastError(0xdeadbeef);
1761     base = MapViewOfFile(hmap, FILE_MAP_READ | FILE_MAP_WRITE | (page_exec_supported ? FILE_MAP_EXECUTE : 0), 0, 0, 0);
1762     ok(base != NULL, "MapViewOfFile failed %d\n", GetLastError());
1763
1764     old_prot = 0xdeadbeef;
1765     SetLastError(0xdeadbeef);
1766     ret = VirtualProtect(base, si.dwPageSize, PAGE_NOACCESS, &old_prot);
1767     ok(ret, "VirtualProtect error %d\n", GetLastError());
1768     ok(old_prot == alloc_prot, "got %#x != expected %#x\n", old_prot, alloc_prot);
1769
1770     for (i = 0; i < sizeof(td)/sizeof(td[0]); i++)
1771     {
1772         SetLastError(0xdeadbeef);
1773         ret = VirtualQuery(base, &info, sizeof(info));
1774         ok(ret, "VirtualQuery failed %d\n", GetLastError());
1775         ok(info.BaseAddress == base, "%d: got %p != expected %p\n", i, info.BaseAddress, base);
1776         ok(info.RegionSize == si.dwPageSize, "%d: got %#lx != expected %#x\n", i, info.RegionSize, si.dwPageSize);
1777         ok(info.Protect == PAGE_NOACCESS, "%d: got %#x != expected PAGE_NOACCESS\n", i, info.Protect);
1778         ok(info.AllocationBase == base, "%d: %p != %p\n", i, info.AllocationBase, base);
1779         ok(info.AllocationProtect == alloc_prot, "%d: %#x != %#x\n", i, info.AllocationProtect, alloc_prot);
1780         ok(info.State == MEM_COMMIT, "%d: %#x != MEM_COMMIT\n", i, info.State);
1781         ok(info.Type == MEM_MAPPED, "%d: %#x != MEM_MAPPED\n", i, info.Type);
1782
1783         old_prot = 0xdeadbeef;
1784         SetLastError(0xdeadbeef);
1785         ret = VirtualProtect(base, si.dwPageSize, td[i].prot, &old_prot);
1786         if (td[i].success || td[i].prot == PAGE_NOACCESS || td[i].prot == PAGE_EXECUTE)
1787         {
1788             if (!ret)
1789             {
1790                 /* win2k and XP don't support EXEC on file mappings */
1791                 if (td[i].prot == PAGE_EXECUTE)
1792                 {
1793                     ok(broken(!ret), "%d: VirtualProtect doesn't support PAGE_EXECUTE\n", i);
1794                     continue;
1795                 }
1796                 /* NT4 and win2k don't support EXEC on file mappings */
1797                 if (td[i].prot == PAGE_EXECUTE_READ || td[i].prot == PAGE_EXECUTE_READWRITE)
1798                 {
1799                     ok(broken(!ret), "%d: VirtualProtect doesn't support PAGE_EXECUTE\n", i);
1800                     continue;
1801                 }
1802                 /* Vista+ supports PAGE_EXECUTE_WRITECOPY, earlier versions don't */
1803                 if (td[i].prot == PAGE_EXECUTE_WRITECOPY)
1804                 {
1805                     ok(broken(!ret), "%d: VirtualProtect doesn't support PAGE_EXECUTE_WRITECOPY\n", i);
1806                     continue;
1807                 }
1808             }
1809
1810             ok(ret, "%d: VirtualProtect error %d\n", i, GetLastError());
1811             ok(old_prot == PAGE_NOACCESS, "%d: got %#x != expected PAGE_NOACCESS\n", i, old_prot);
1812
1813             prot = td[i].prot;
1814             /* looks strange but Windows doesn't do this for PAGE_WRITECOPY */
1815             if (prot == PAGE_EXECUTE_WRITECOPY) prot = PAGE_EXECUTE_READWRITE;
1816
1817             SetLastError(0xdeadbeef);
1818             ret = VirtualQuery(base, &info, sizeof(info));
1819             ok(ret, "VirtualQuery failed %d\n", GetLastError());
1820             ok(info.BaseAddress == base, "%d: got %p != expected %p\n", i, info.BaseAddress, base);
1821             ok(info.RegionSize == si.dwPageSize, "%d: got %#lx != expected %#x\n", i, info.RegionSize, si.dwPageSize);
1822             /* FIXME: remove the condition below once Wine is fixed */
1823             if (td[i].prot == PAGE_EXECUTE_WRITECOPY)
1824                 todo_wine ok(info.Protect == prot, "%d: got %#x != expected %#x\n", i, info.Protect, prot);
1825             else
1826                 ok(info.Protect == prot, "%d: got %#x != expected %#x\n", i, info.Protect, prot);
1827             ok(info.AllocationBase == base, "%d: %p != %p\n", i, info.AllocationBase, base);
1828             ok(info.AllocationProtect == alloc_prot, "%d: %#x != %#x\n", i, info.AllocationProtect, alloc_prot);
1829             ok(info.State == MEM_COMMIT, "%d: %#x != MEM_COMMIT\n", i, info.State);
1830             ok(info.Type == MEM_MAPPED, "%d: %#x != MEM_MAPPED\n", i, info.Type);
1831
1832             if (is_mem_writable(info.Protect))
1833             {
1834                 base[0] = 0xfe;
1835
1836                 SetLastError(0xdeadbeef);
1837                 ret = VirtualQuery(base, &info, sizeof(info));
1838                 ok(ret, "VirtualQuery failed %d\n", GetLastError());
1839                 /* FIXME: remove the condition below once Wine is fixed */
1840                 if (td[i].prot == PAGE_WRITECOPY || td[i].prot == PAGE_EXECUTE_WRITECOPY)
1841                     todo_wine ok(info.Protect == td[i].prot_after_write, "%d: got %#x != expected %#x\n", i, info.Protect, td[i].prot_after_write);
1842                 else
1843                     ok(info.Protect == td[i].prot_after_write, "%d: got %#x != expected %#x\n", i, info.Protect, td[i].prot_after_write);
1844             }
1845         }
1846         else
1847         {
1848             ok(!ret, "%d: VirtualProtect should fail\n", i);
1849             ok(GetLastError() == ERROR_INVALID_PARAMETER, "%d: expected ERROR_INVALID_PARAMETER, got %d\n", i, GetLastError());
1850             continue;
1851         }
1852
1853         old_prot = 0xdeadbeef;
1854         SetLastError(0xdeadbeef);
1855         ret = VirtualProtect(base, si.dwPageSize, PAGE_NOACCESS, &old_prot);
1856         ok(ret, "%d: VirtualProtect error %d\n", i, GetLastError());
1857         /* FIXME: remove the condition below once Wine is fixed */
1858         if (td[i].prot == PAGE_WRITECOPY || td[i].prot == PAGE_EXECUTE_WRITECOPY)
1859             todo_wine ok(old_prot == td[i].prot_after_write, "%d: got %#x != expected %#x\n", i, old_prot, td[i].prot_after_write);
1860         else
1861             ok(old_prot == td[i].prot_after_write, "%d: got %#x != expected %#x\n", i, old_prot, td[i].prot_after_write);
1862     }
1863
1864     UnmapViewOfFile(base);
1865     CloseHandle(hmap);
1866
1867     CloseHandle(hfile);
1868     DeleteFile(file_name);
1869 }
1870
1871 #define ACCESS_READ      0x01
1872 #define ACCESS_WRITE     0x02
1873 #define ACCESS_EXECUTE   0x04
1874 #define ACCESS_WRITECOPY 0x08
1875
1876 static DWORD page_prot_to_access(DWORD prot)
1877 {
1878     switch (prot)
1879     {
1880     case PAGE_READWRITE:
1881         return ACCESS_READ | ACCESS_WRITE;
1882
1883     case PAGE_EXECUTE:
1884     case PAGE_EXECUTE_READ:
1885         return ACCESS_READ | ACCESS_EXECUTE;
1886
1887     case PAGE_EXECUTE_READWRITE:
1888         return ACCESS_READ | ACCESS_WRITE | ACCESS_WRITECOPY | ACCESS_EXECUTE;
1889
1890     case PAGE_EXECUTE_WRITECOPY:
1891         return ACCESS_READ | ACCESS_WRITECOPY | ACCESS_EXECUTE;
1892
1893     case PAGE_READONLY:
1894         return ACCESS_READ;
1895
1896     case PAGE_WRITECOPY:
1897         return ACCESS_READ;
1898
1899     default:
1900         return 0;
1901     }
1902 }
1903
1904 static BOOL is_compatible_protection(DWORD map_prot, DWORD view_prot, DWORD prot)
1905 {
1906     DWORD map_access, view_access, prot_access;
1907
1908     map_access = page_prot_to_access(map_prot);
1909     view_access = page_prot_to_access(view_prot);
1910     prot_access = page_prot_to_access(prot);
1911
1912     if (view_access == prot_access) return TRUE;
1913     if (!view_access) return FALSE;
1914
1915     if ((view_access & prot_access) != prot_access) return FALSE;
1916     if ((map_access & prot_access) == prot_access) return TRUE;
1917
1918     return FALSE;
1919 }
1920
1921 static DWORD map_prot_to_access(DWORD prot)
1922 {
1923     switch (prot)
1924     {
1925     case PAGE_READWRITE:
1926     case PAGE_EXECUTE_READWRITE:
1927         return SECTION_MAP_READ | SECTION_MAP_WRITE | SECTION_MAP_EXECUTE | SECTION_MAP_EXECUTE_EXPLICIT | SECTION_QUERY;
1928     case PAGE_READONLY:
1929     case PAGE_WRITECOPY:
1930     case PAGE_EXECUTE:
1931     case PAGE_EXECUTE_READ:
1932     case PAGE_EXECUTE_WRITECOPY:
1933         return SECTION_MAP_READ | SECTION_MAP_EXECUTE | SECTION_MAP_EXECUTE_EXPLICIT | SECTION_QUERY;
1934     default:
1935         return 0;
1936     }
1937 }
1938
1939 static BOOL is_compatible_access(DWORD map_prot, DWORD view_prot)
1940 {
1941     DWORD access = map_prot_to_access(map_prot);
1942     if (!access) return FALSE;
1943     return (view_prot & access) == view_prot;
1944 }
1945
1946 static void test_mapping(void)
1947 {
1948     static const DWORD page_prot[] =
1949     {
1950         PAGE_NOACCESS, PAGE_READONLY, PAGE_READWRITE, PAGE_WRITECOPY,
1951         PAGE_EXECUTE_READ, PAGE_EXECUTE_READWRITE, PAGE_EXECUTE_WRITECOPY
1952     };
1953     static const struct
1954     {
1955         DWORD access, prot;
1956     } view[] =
1957     {
1958         { 0, PAGE_NOACCESS }, /* 0x00 */
1959         { FILE_MAP_COPY, PAGE_WRITECOPY }, /* 0x01 */
1960         { FILE_MAP_WRITE, PAGE_READWRITE }, /* 0x02 */
1961         { FILE_MAP_WRITE | FILE_MAP_COPY, PAGE_READWRITE }, /* 0x03 */
1962         { FILE_MAP_READ, PAGE_READONLY }, /* 0x04 */
1963         { FILE_MAP_READ | FILE_MAP_COPY, PAGE_READONLY }, /* 0x05 */
1964         { FILE_MAP_READ | FILE_MAP_WRITE, PAGE_READWRITE }, /* 0x06 */
1965         { FILE_MAP_READ | FILE_MAP_WRITE | FILE_MAP_COPY, PAGE_READWRITE }, /* 0x07 */
1966         { SECTION_MAP_EXECUTE, PAGE_NOACCESS }, /* 0x08 */
1967         { SECTION_MAP_EXECUTE | FILE_MAP_COPY, PAGE_NOACCESS }, /* 0x09 */
1968         { SECTION_MAP_EXECUTE | FILE_MAP_WRITE, PAGE_READWRITE }, /* 0x0a */
1969         { SECTION_MAP_EXECUTE | FILE_MAP_WRITE | FILE_MAP_COPY, PAGE_READWRITE }, /* 0x0b */
1970         { SECTION_MAP_EXECUTE | FILE_MAP_READ, PAGE_READONLY }, /* 0x0c */
1971         { SECTION_MAP_EXECUTE | FILE_MAP_READ | FILE_MAP_COPY, PAGE_READONLY }, /* 0x0d */
1972         { SECTION_MAP_EXECUTE | FILE_MAP_READ | FILE_MAP_WRITE, PAGE_READWRITE }, /* 0x0e */
1973         { SECTION_MAP_EXECUTE | FILE_MAP_READ | FILE_MAP_WRITE | FILE_MAP_COPY, PAGE_READWRITE }, /* 0x0f */
1974         { FILE_MAP_EXECUTE, PAGE_NOACCESS }, /* 0x20 */
1975         { FILE_MAP_EXECUTE | FILE_MAP_COPY, PAGE_EXECUTE_WRITECOPY }, /* 0x21 */
1976         { FILE_MAP_EXECUTE | FILE_MAP_WRITE, PAGE_EXECUTE_READWRITE }, /* 0x22 */
1977         { FILE_MAP_EXECUTE | FILE_MAP_WRITE | FILE_MAP_COPY, PAGE_EXECUTE_READWRITE }, /* 0x23 */
1978         { FILE_MAP_EXECUTE | FILE_MAP_READ, PAGE_EXECUTE_READ }, /* 0x24 */
1979         { FILE_MAP_EXECUTE | FILE_MAP_READ | FILE_MAP_COPY, PAGE_EXECUTE_READ }, /* 0x25 */
1980         { FILE_MAP_EXECUTE | FILE_MAP_READ | FILE_MAP_WRITE, PAGE_EXECUTE_READWRITE }, /* 0x26 */
1981         { FILE_MAP_EXECUTE | FILE_MAP_READ | FILE_MAP_WRITE | FILE_MAP_COPY, PAGE_EXECUTE_READWRITE }, /* 0x27 */
1982         { FILE_MAP_EXECUTE | SECTION_MAP_EXECUTE, PAGE_NOACCESS }, /* 0x28 */
1983         { FILE_MAP_EXECUTE | SECTION_MAP_EXECUTE | FILE_MAP_COPY, PAGE_NOACCESS }, /* 0x29 */
1984         { FILE_MAP_EXECUTE | SECTION_MAP_EXECUTE | FILE_MAP_WRITE, PAGE_EXECUTE_READWRITE }, /* 0x2a */
1985         { FILE_MAP_EXECUTE | SECTION_MAP_EXECUTE | FILE_MAP_WRITE | FILE_MAP_COPY, PAGE_EXECUTE_READWRITE }, /* 0x2b */
1986         { FILE_MAP_EXECUTE | SECTION_MAP_EXECUTE | FILE_MAP_READ, PAGE_EXECUTE_READ }, /* 0x2c */
1987         { FILE_MAP_EXECUTE | SECTION_MAP_EXECUTE | FILE_MAP_READ | FILE_MAP_COPY, PAGE_EXECUTE_READ }, /* 0x2d */
1988         { FILE_MAP_EXECUTE | SECTION_MAP_EXECUTE | FILE_MAP_READ | FILE_MAP_WRITE, PAGE_EXECUTE_READWRITE }, /* 0x2e */
1989         { FILE_MAP_EXECUTE | SECTION_MAP_EXECUTE | FILE_MAP_READ | FILE_MAP_WRITE | FILE_MAP_COPY, PAGE_EXECUTE_READWRITE } /* 0x2f */
1990     };
1991     void *base;
1992     DWORD i, j, k, ret, old_prot, prev_prot;
1993     SYSTEM_INFO si;
1994     char temp_path[MAX_PATH];
1995     char file_name[MAX_PATH];
1996     HANDLE hfile, hmap;
1997     MEMORY_BASIC_INFORMATION info;
1998
1999     GetSystemInfo(&si);
2000     trace("system page size %#x\n", si.dwPageSize);
2001
2002     GetTempPath(MAX_PATH, temp_path);
2003     GetTempFileName(temp_path, "map", 0, file_name);
2004
2005     SetLastError(0xdeadbeef);
2006     hfile = CreateFile(file_name, GENERIC_READ|GENERIC_WRITE|GENERIC_EXECUTE, 0, NULL, CREATE_ALWAYS, 0, 0);
2007     ok(hfile != INVALID_HANDLE_VALUE, "CreateFile(%s) error %d\n", file_name, GetLastError());
2008     SetFilePointer(hfile, si.dwPageSize, NULL, FILE_BEGIN);
2009     SetEndOfFile(hfile);
2010
2011     for (i = 0; i < sizeof(page_prot)/sizeof(page_prot[0]); i++)
2012     {
2013         SetLastError(0xdeadbeef);
2014         hmap = CreateFileMapping(hfile, NULL, page_prot[i] | SEC_COMMIT, 0, si.dwPageSize, NULL);
2015
2016         if (page_prot[i] == PAGE_NOACCESS)
2017         {
2018             HANDLE hmap2;
2019
2020             ok(!hmap, "CreateFileMapping(PAGE_NOACCESS) should fail\n");
2021             ok(GetLastError() == ERROR_INVALID_PARAMETER, "expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
2022
2023             /* A trick to create a not accessible mapping */
2024             SetLastError(0xdeadbeef);
2025             hmap = CreateFileMapping(hfile, NULL, PAGE_READWRITE | SEC_COMMIT, 0, si.dwPageSize, NULL);
2026             ok(hmap != 0, "CreateFileMapping(PAGE_READWRITE) error %d\n", GetLastError());
2027             SetLastError(0xdeadbeef);
2028             ret = DuplicateHandle(GetCurrentProcess(), hmap, GetCurrentProcess(), &hmap2, 0, FALSE, 0);
2029             ok(ret, "DuplicateHandle error %d\n", GetLastError());
2030             CloseHandle(hmap);
2031             hmap = hmap2;
2032         }
2033
2034         if (!hmap)
2035         {
2036             trace("%d: CreateFileMapping(%04x) failed: %d\n", i, page_prot[i], GetLastError());
2037
2038             /* NT4 and win2k don't support EXEC on file mappings */
2039             if (page_prot[i] == PAGE_EXECUTE_READ || page_prot[i] == PAGE_EXECUTE_READWRITE)
2040             {
2041                 ok(broken(!hmap), "%d: CreateFileMapping doesn't support PAGE_EXECUTE\n", i);
2042                 continue;
2043             }
2044             /* Vista+ supports PAGE_EXECUTE_WRITECOPY, earlier versions don't */
2045             if (page_prot[i] == PAGE_EXECUTE_WRITECOPY)
2046             {
2047                 ok(broken(!hmap), "%d: CreateFileMapping doesn't support PAGE_EXECUTE_WRITECOPY\n", i);
2048                 continue;
2049             }
2050         }
2051
2052         ok(hmap != 0, "%d: CreateFileMapping(%04x) error %d\n", i, page_prot[i], GetLastError());
2053
2054         for (j = 0; j < sizeof(view)/sizeof(view[0]); j++)
2055         {
2056             SetLastError(0xdeadbeef);
2057             base = MapViewOfFile(hmap, view[j].access, 0, 0, 0);
2058
2059             if (!is_compatible_access(page_prot[i], view[j].access))
2060             {
2061                 ok(!base, "%d: MapViewOfFile(%04x/%04x) should fail\n", j, page_prot[i], view[j].access);
2062                 ok(GetLastError() == ERROR_ACCESS_DENIED, "wrong error %d\n", GetLastError());
2063                 continue;
2064             }
2065
2066             /* Vista+ properly supports FILE_MAP_EXECUTE, earlier versions don't */
2067             if (!base && (view[j].access & FILE_MAP_EXECUTE))
2068             {
2069                 ok(broken(!base), "%d: MapViewOfFile(%04x/%04x) failed %d\n", j, page_prot[i], view[j].access, GetLastError());
2070                 continue;
2071             }
2072
2073             ok(base != NULL, "%d: MapViewOfFile(%04x/%04x) failed %d\n", j, page_prot[i], view[j].access, GetLastError());
2074
2075             SetLastError(0xdeadbeef);
2076             ret = VirtualQuery(base, &info, sizeof(info));
2077             ok(ret, "%d: VirtualQuery failed %d\n", j, GetLastError());
2078             ok(info.BaseAddress == base, "%d: (%04x) got %p, expected %p\n", j, view[j].access, info.BaseAddress, base);
2079             ok(info.RegionSize == si.dwPageSize, "%d: (%04x) got %#lx != expected %#x\n", j, view[j].access, info.RegionSize, si.dwPageSize);
2080             /* FIXME: completely remove the condition below once Wine is fixed */
2081             if (info.Protect != view[j].prot)
2082             todo_wine
2083             ok(info.Protect == view[j].prot ||
2084                broken(view[j].prot == PAGE_EXECUTE_READ && info.Protect == PAGE_READONLY) || /* win2k */
2085                broken(view[j].prot == PAGE_EXECUTE_READWRITE && info.Protect == PAGE_READWRITE) || /* win2k */
2086                broken(view[j].prot == PAGE_EXECUTE_WRITECOPY && info.Protect == PAGE_NOACCESS), /* XP */
2087                "%d: (%04x) got %#x, expected %#x\n", j, view[j].access, info.Protect, view[j].prot);
2088             else
2089             ok(info.Protect == view[j].prot ||
2090                broken(view[j].prot == PAGE_EXECUTE_READ && info.Protect == PAGE_READONLY) || /* win2k */
2091                broken(view[j].prot == PAGE_EXECUTE_READWRITE && info.Protect == PAGE_READWRITE) || /* win2k */
2092                broken(view[j].prot == PAGE_EXECUTE_WRITECOPY && info.Protect == PAGE_NOACCESS), /* XP */
2093                "%d: (%04x) got %#x, expected %#x\n", j, view[j].access, info.Protect, view[j].prot);
2094             ok(info.AllocationBase == base, "%d: (%04x) got %p, expected %p\n", j, view[j].access, info.AllocationBase, base);
2095             ok(info.AllocationProtect == info.Protect, "%d: (%04x) got %#x, expected %#x\n", j, view[j].access, info.AllocationProtect, info.Protect);
2096             ok(info.State == MEM_COMMIT, "%d: (%04x) got %#x, expected MEM_COMMIT\n", j, view[j].access, info.State);
2097             ok(info.Type == MEM_MAPPED, "%d: (%04x) got %#x, expected MEM_MAPPED\n", j, view[j].access, info.Type);
2098
2099             prev_prot = info.Protect;
2100
2101             for (k = 0; k < sizeof(page_prot)/sizeof(page_prot[0]); k++)
2102             {
2103                 /*trace("map %#x, view %#x, requested prot %#x\n", page_prot[i], view[j].prot, page_prot[k]);*/
2104                 SetLastError(0xdeadbeef);
2105                 old_prot = 0xdeadbeef;
2106                 ret = VirtualProtect(base, si.dwPageSize, page_prot[k], &old_prot);
2107                 if (is_compatible_protection(page_prot[i], view[j].prot, page_prot[k]))
2108                 {
2109                     /* win2k and XP don't support EXEC on file mappings */
2110                     if (!ret && page_prot[k] == PAGE_EXECUTE)
2111                     {
2112                         ok(broken(!ret), "VirtualProtect doesn't support PAGE_EXECUTE\n");
2113                         continue;
2114                     }
2115                     /* NT4 and win2k don't support EXEC on file mappings */
2116                     if (!ret && (page_prot[k] == PAGE_EXECUTE_READ || page_prot[k] == PAGE_EXECUTE_READWRITE))
2117                     {
2118                         ok(broken(!ret), "VirtualProtect doesn't support PAGE_EXECUTE\n");
2119                         continue;
2120                     }
2121                     /* Vista+ supports PAGE_EXECUTE_WRITECOPY, earlier versions don't */
2122                     if (!ret && page_prot[k] == PAGE_EXECUTE_WRITECOPY)
2123                     {
2124                     todo_wine
2125                         ok(broken(!ret), "VirtualProtect doesn't support PAGE_EXECUTE_WRITECOPY\n");
2126                         continue;
2127                     }
2128                     /* win2k and XP don't support PAGE_EXECUTE_WRITECOPY views properly  */
2129                     if (!ret && view[j].prot == PAGE_EXECUTE_WRITECOPY)
2130                     {
2131                         ok(broken(!ret), "VirtualProtect doesn't support PAGE_EXECUTE_WRITECOPY view properly\n");
2132                         continue;
2133                     }
2134
2135                     ok(ret, "VirtualProtect error %d, map %#x, view %#x, requested prot %#x\n", GetLastError(), page_prot[i], view[j].prot, page_prot[k]);
2136                     ok(old_prot == prev_prot, "got %#x, expected %#x\n", old_prot, prev_prot);
2137                     prev_prot = page_prot[k];
2138                 }
2139                 else
2140                 {
2141                     /* NT4 doesn't fail on incompatible map and view */
2142                     if (ret)
2143                     {
2144                     todo_wine
2145                         ok(broken(ret), "VirtualProtect should fail, map %#x, view %#x, requested prot %#x\n", page_prot[i], view[j].prot, page_prot[k]);
2146                         skip("Incompatible map and view are not properly handled on this platform\n");
2147                         break; /* NT4 won't pass remaining tests */
2148                     }
2149
2150                     ok(!ret, "VirtualProtect should fail, map %#x, view %#x, requested prot %#x\n", page_prot[i], view[j].prot, page_prot[k]);
2151                     ok(GetLastError() == ERROR_INVALID_PARAMETER, "expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
2152                 }
2153             }
2154
2155             UnmapViewOfFile(base);
2156         }
2157
2158         CloseHandle(hmap);
2159     }
2160
2161     CloseHandle(hfile);
2162     DeleteFile(file_name);
2163 }
2164
2165 START_TEST(virtual)
2166 {
2167     int argc;
2168     char **argv;
2169     argc = winetest_get_mainargs( &argv );
2170
2171     if (argc >= 3)
2172     {
2173         if (!strcmp(argv[2], "sleep"))
2174         {
2175             Sleep(5000); /* spawned process runs for at most 5 seconds */
2176             return;
2177         }
2178         while (1)
2179         {
2180             void *mem;
2181             BOOL ret;
2182             mem = VirtualAlloc(NULL, 1<<20, MEM_COMMIT|MEM_RESERVE,
2183                                PAGE_EXECUTE_READWRITE);
2184             ok(mem != NULL, "VirtualAlloc failed %u\n", GetLastError());
2185             if (mem == NULL) break;
2186             ret = VirtualFree(mem, 0, MEM_RELEASE);
2187             ok(ret, "VirtualFree failed %u\n", GetLastError());
2188             if (!ret) break;
2189         }
2190         return;
2191     }
2192
2193     hkernel32 = GetModuleHandleA("kernel32.dll");
2194     pVirtualAllocEx = (void *) GetProcAddress(hkernel32, "VirtualAllocEx");
2195     pVirtualFreeEx = (void *) GetProcAddress(hkernel32, "VirtualFreeEx");
2196     pGetWriteWatch = (void *) GetProcAddress(hkernel32, "GetWriteWatch");
2197     pResetWriteWatch = (void *) GetProcAddress(hkernel32, "ResetWriteWatch");
2198     pNtAreMappedFilesTheSame = (void *)GetProcAddress( GetModuleHandle("ntdll.dll"),
2199                                                        "NtAreMappedFilesTheSame" );
2200     test_mapping();
2201     test_CreateFileMapping_protection();
2202     test_VirtualAlloc_protection();
2203     test_VirtualProtect();
2204     test_VirtualAllocEx();
2205     test_VirtualAlloc();
2206     test_MapViewOfFile();
2207     test_NtMapViewOfSection();
2208     test_NtAreMappedFilesTheSame();
2209     test_CreateFileMapping();
2210     test_IsBadReadPtr();
2211     test_IsBadWritePtr();
2212     test_IsBadCodePtr();
2213     test_write_watch();
2214 }