ReactOS 0.4.17-dev-37-g0bfb40d
wow64.c
Go to the documentation of this file.
1/*
2 * Unit test suite Wow64 functions
3 *
4 * Copyright 2021 Alexandre Julliard
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
22#include <stdarg.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 "winioctl.h"
30#include "winuser.h"
31#include "ddk/wdm.h"
32#include "wine/test.h"
33
34#ifdef __REACTOS__
35#define NT_SUCCESS(Status) (((NTSTATUS)(Status)) >= 0)
36#define wcsicmp _wcsicmp
37#if defined(_MSC_VER) && defined(_M_AMD64)
38USHORT __readsegfs(void);
39USHORT __readsegss(void);
40#endif // _M_AMD64
41#endif
42
43static NTSTATUS (WINAPI *pNtQuerySystemInformation)(SYSTEM_INFORMATION_CLASS,void*,ULONG,ULONG*);
44static NTSTATUS (WINAPI *pNtQuerySystemInformationEx)(SYSTEM_INFORMATION_CLASS,void*,ULONG,void*,ULONG,ULONG*);
45static NTSTATUS (WINAPI *pRtlGetNativeSystemInformation)(SYSTEM_INFORMATION_CLASS,void*,ULONG,ULONG*);
46static void (WINAPI *pRtlOpenCrossProcessEmulatorWorkConnection)(HANDLE,HANDLE*,void**);
47static void * (WINAPI *pRtlFindExportedRoutineByName)(HMODULE,const char *);
48static USHORT (WINAPI *pRtlWow64GetCurrentMachine)(void);
49static NTSTATUS (WINAPI *pRtlWow64GetProcessMachines)(HANDLE,WORD*,WORD*);
50static NTSTATUS (WINAPI *pRtlWow64GetSharedInfoProcess)(HANDLE,BOOLEAN*,WOW64INFO*);
51static NTSTATUS (WINAPI *pRtlWow64GetThreadContext)(HANDLE,WOW64_CONTEXT*);
52static NTSTATUS (WINAPI *pRtlWow64IsWowGuestMachineSupported)(USHORT,BOOLEAN*);
54#ifdef _WIN64
56static NTSTATUS (WINAPI *pRtlWow64GetCpuAreaInfo)(WOW64_CPURESERVED*,ULONG,WOW64_CPU_AREA_INFO*);
57static NTSTATUS (WINAPI *pRtlWow64GetThreadSelectorEntry)(HANDLE,THREAD_DESCRIPTOR_INFORMATION*,ULONG,ULONG*);
58static CROSS_PROCESS_WORK_ENTRY * (WINAPI *pRtlWow64PopAllCrossProcessWorkFromWorkList)(CROSS_PROCESS_WORK_HDR*,BOOLEAN*);
59static CROSS_PROCESS_WORK_ENTRY * (WINAPI *pRtlWow64PopCrossProcessWorkFromFreeList)(CROSS_PROCESS_WORK_HDR*);
60static BOOLEAN (WINAPI *pRtlWow64PushCrossProcessWorkOntoFreeList)(CROSS_PROCESS_WORK_HDR*,CROSS_PROCESS_WORK_ENTRY*);
61static BOOLEAN (WINAPI *pRtlWow64PushCrossProcessWorkOntoWorkList)(CROSS_PROCESS_WORK_HDR*,CROSS_PROCESS_WORK_ENTRY*,void**);
62static BOOLEAN (WINAPI *pRtlWow64RequestCrossProcessHeavyFlush)(CROSS_PROCESS_WORK_HDR*);
63static void (WINAPI *pProcessPendingCrossProcessEmulatorWork)(void);
64#else
65static NTSTATUS (WINAPI *pNtWow64AllocateVirtualMemory64)(HANDLE,ULONG64*,ULONG64,ULONG64*,ULONG,ULONG);
66static NTSTATUS (WINAPI *pNtWow64GetNativeSystemInformation)(SYSTEM_INFORMATION_CLASS,void*,ULONG,ULONG*);
67static NTSTATUS (WINAPI *pNtWow64IsProcessorFeaturePresent)(ULONG);
68static NTSTATUS (WINAPI *pNtWow64QueryInformationProcess64)(HANDLE,PROCESSINFOCLASS,void*,ULONG,ULONG*);
69static NTSTATUS (WINAPI *pNtWow64ReadVirtualMemory64)(HANDLE,ULONG64,void*,ULONG64,ULONG64*);
70static NTSTATUS (WINAPI *pNtWow64WriteVirtualMemory64)(HANDLE,ULONG64,const void *,ULONG64,ULONG64*);
71#endif
72
73static BOOL is_win64 = sizeof(void *) > sizeof(int);
75static BOOL old_wow64; /* Wine old-style wow64 */
76static void *code_mem;
77
78#ifdef __i386__
81#elif defined __x86_64__
84#elif defined __arm__
87#elif defined __aarch64__
90#else
93#endif
94
96{
103};
104
105#if !defined(__REACTOS__) || (DLL_EXPORT_VERSION >= 0x600)
107{
109}
110#endif // !defined(__REACTOS__) || (DLL_EXPORT_VERSION >= 0x600)
111
112static void init(void)
113{
114 HMODULE ntdll = GetModuleHandleA( "ntdll.dll" );
115
117
118 if (is_wow64)
119 {
120 TEB64 *teb64 = ULongToPtr( NtCurrentTeb()->GdiBatchCount );
121
122 if (teb64)
123 {
124 PEB64 *peb64 = ULongToPtr(teb64->Peb);
125 old_wow64 = !peb64->LdrData;
126 }
127 }
128
129#define GET_PROC(func) p##func = (void *)GetProcAddress( ntdll, #func )
134 GET_PROC( RtlOpenCrossProcessEmulatorWorkConnection );
139 GET_PROC( RtlWow64GetThreadContext );
141#ifdef _WIN64
143 GET_PROC( RtlWow64GetCpuAreaInfo );
144 GET_PROC( RtlWow64GetThreadSelectorEntry );
145 GET_PROC( RtlWow64PopAllCrossProcessWorkFromWorkList );
146 GET_PROC( RtlWow64PopCrossProcessWorkFromFreeList );
147 GET_PROC( RtlWow64PushCrossProcessWorkOntoFreeList );
148 GET_PROC( RtlWow64PushCrossProcessWorkOntoWorkList );
149 GET_PROC( RtlWow64RequestCrossProcessHeavyFlush );
150 GET_PROC( ProcessPendingCrossProcessEmulatorWork );
151#else
158#endif
159#undef GET_PROC
160
161 if (pNtQuerySystemInformationEx)
162 {
165 NTSTATUS status = pNtQuerySystemInformationEx( SystemSupportedProcessorArchitectures, &process,
166 sizeof(process), machines, sizeof(machines), NULL );
167 if (!status)
168 for (int i = 0; machines[i].Machine; i++)
169 trace( "machine %04x kernel %u user %u native %u process %u wow64 %u\n",
170 machines[i].Machine, machines[i].KernelMode, machines[i].UserMode,
171 machines[i].Native, machines[i].Process, machines[i].WoW64Container );
172 }
173
174 if (pRtlGetNativeSystemInformation)
175 {
177 ULONG len;
178
179 pRtlGetNativeSystemInformation( SystemCpuInformation, &info, sizeof(info), &len );
180 switch (info.ProcessorArchitecture)
181 {
184 break;
187 break;
188 }
189 }
190
191 trace( "current %04x native %04x\n", current_machine, native_machine );
192
195}
196
197#if !defined (__REACTOS__) || (DLL_EXPORT_VERSION >= 0x600)
199{
201 STARTUPINFOEXA si = {{ sizeof(si) }};
202 SIZE_T size = 1024;
203 BOOL ret;
204
205 si.lpAttributeList = list = malloc( size );
208 &machine, sizeof(machine), NULL, NULL );
210 EXTENDED_STARTUPINFO_PRESENT | flags, NULL, NULL, &si.StartupInfo, pi );
212 free( list );
213 return ret;
214}
215
216static void test_process_architecture( HANDLE process, USHORT expect_machine, USHORT expect_native )
217{
220 ULONG i, len;
221
222 len = 0xdead;
223 status = pNtQuerySystemInformationEx( SystemSupportedProcessorArchitectures, &process, sizeof(process),
224 machines, sizeof(machines), &len );
225 ok( !status, "failed %lx\n", status );
226 ok( !(len & 3), "wrong len %lx\n", len );
227 len /= sizeof(machines[0]);
228 for (i = 0; i < len - 1; i++)
229 {
230 if (machines[i].Process)
231 ok( machines[i].Machine == expect_machine, "wrong process machine %x\n", machines[i].Machine);
232 else
233 ok( machines[i].Machine != expect_machine, "wrong machine %x\n", machines[i].Machine);
234
235 if (machines[i].Native)
236 ok( machines[i].Machine == expect_native, "wrong native machine %x\n", machines[i].Machine);
237 else
238 ok( machines[i].Machine != expect_native, "wrong machine %x\n", machines[i].Machine);
239
240 if (machines[i].WoW64Container)
241 ok( is_machine_32bit( machines[i].Machine ) && !is_machine_32bit( native_machine ),
242 "wrong wow64 %x\n", machines[i].Machine);
243 }
244 ok( !*(DWORD *)&machines[i], "missing terminating null\n" );
245
246 len = i * sizeof(machines[0]);
247 status = pNtQuerySystemInformationEx( SystemSupportedProcessorArchitectures, &process, sizeof(process),
248 machines, len, &len );
249 ok( status == STATUS_BUFFER_TOO_SMALL, "failed %lx\n", status );
250 ok( len == (i + 1) * sizeof(machines[0]), "wrong len %lu\n", len );
251
252 if (pRtlWow64GetProcessMachines)
253 {
254 USHORT current = 0xdead, native = 0xbeef;
255 status = pRtlWow64GetProcessMachines( process, &current, &native );
256 ok( !status, "failed %lx\n", status );
257 if (expect_machine == expect_native)
258 ok( current == 0, "wrong current machine %x / %x\n", current, expect_machine );
259 else
260 ok( current == expect_machine, "wrong current machine %x / %x\n", current, expect_machine );
261 ok( native == expect_native, "wrong native machine %x / %x\n", native, expect_native );
262 }
263}
264
266 USHORT expect_machine, USHORT expect_image )
267{
272 PEB peb;
273 ULONG len;
274 SIZE_T size;
276 void *entry_point = NULL;
277 void *win32_entry = NULL;
278
280 ok( !status, "ProcessBasicInformation failed %lx\n", status );
281 if (ReadProcessMemory( process, basic.PebBaseAddress, &peb, sizeof(peb), &size ) &&
282 ReadProcessMemory( process, peb.ImageBaseAddress, &dos, sizeof(dos), &size ) &&
283 ReadProcessMemory( process, (char *)peb.ImageBaseAddress + dos.e_lfanew, &nt, sizeof(nt), &size ))
284 {
285 ok( nt.FileHeader.Machine == expect_machine, "wrong nt machine %x / %x\n",
286 nt.FileHeader.Machine, expect_machine );
287 entry_point = (char *)peb.ImageBaseAddress + nt.OptionalHeader.AddressOfEntryPoint;
288 }
289
291 ok( !status, "ProcessImageInformation failed %lx\n", status );
292 ok( image.Machine == expect_image, "wrong image info %x / %x\n", image.Machine, expect_image );
293
295 &win32_entry, sizeof(win32_entry), &len );
296 ok( !status, "ThreadQuerySetWin32StartAddress failed %lx\n", status );
297
298 if (!entry_point) return;
299
300 if (image.Machine == expect_machine)
301 {
302 ok( image.TransferAddress == entry_point, "wrong entry %p / %p\n",
303 image.TransferAddress, entry_point );
304 ok( win32_entry == entry_point, "wrong win32 entry %p / %p\n",
305 win32_entry, entry_point );
306 }
307 else
308 {
309 /* image.TransferAddress is the ARM64 entry, entry_point is the x86-64 one,
310 win32_entry is the redirected x86-64 -> ARM64EC one */
311 ok( image.TransferAddress != entry_point, "wrong entry %p\n", image.TransferAddress );
312 ok( image.TransferAddress != win32_entry, "wrong entry %p\n", image.TransferAddress );
313 ok( win32_entry != entry_point, "wrong win32 entry %p\n", win32_entry );
314 }
315}
316
318{
319 static char cmd_sysnative[] = "C:\\windows\\sysnative\\cmd.exe /c exit";
320 static char cmd_system32[] = "C:\\windows\\system32\\cmd.exe /c exit";
321 static char cmd_syswow64[] = "C:\\windows\\syswow64\\cmd.exe /c exit";
324 STARTUPINFOA si = { sizeof(si) };
327 ULONG i, len;
328#ifdef __arm64ec__
330#else
332#endif
333
334 if (!pNtQuerySystemInformationEx) return;
335
337 status = pNtQuerySystemInformationEx( SystemSupportedProcessorArchitectures, &process, sizeof(process),
338 machines, sizeof(machines), &len );
340 {
341 win_skip( "SystemSupportedProcessorArchitectures not supported\n" );
342 return;
343 }
344 ok( !status, "failed %lx\n", status );
345
346 process = (HANDLE)0xdeadbeef;
347 status = pNtQuerySystemInformationEx( SystemSupportedProcessorArchitectures, &process, sizeof(process),
348 machines, sizeof(machines), &len );
349 ok( status == STATUS_INVALID_HANDLE, "failed %lx\n", status );
350 process = (HANDLE)0xdeadbeef;
351 status = pNtQuerySystemInformationEx( SystemSupportedProcessorArchitectures, &process, 3,
352 machines, sizeof(machines), &len );
354 "failed %lx\n", status );
356 status = pNtQuerySystemInformationEx( SystemSupportedProcessorArchitectures, &process, 3,
357 machines, sizeof(machines), &len );
359 "failed %lx\n", status );
360 status = pNtQuerySystemInformationEx( SystemSupportedProcessorArchitectures, NULL, 0,
361 machines, sizeof(machines), &len );
362 ok( status == STATUS_INVALID_PARAMETER, "failed %lx\n", status );
363
364 winetest_push_context( "current" );
370
371 winetest_push_context( "zero" );
374
375 if (CreateProcessA( NULL, is_win64 ? cmd_system32 : cmd_sysnative, NULL, NULL,
377 {
378 winetest_push_context( "system32" );
386 }
387 if (CreateProcessA( NULL, is_win64 ? cmd_syswow64 : cmd_system32, NULL, NULL,
389 {
390 winetest_push_context( "syswow64" );
397 }
399 {
401
402 if (create_process_machine( cmd_system32, CREATE_SUSPENDED, machine, &pi ))
403 {
411 }
412 }
413
414 if (pRtlWow64GetCurrentMachine)
415 {
416 USHORT machine = pRtlWow64GetCurrentMachine();
417 ok( machine == current_machine, "wrong machine %x / %x\n", machine, current_machine );
418 }
419 if (pRtlWow64IsWowGuestMachineSupported)
420 {
421 static const WORD machines[] = { IMAGE_FILE_MACHINE_I386, IMAGE_FILE_MACHINE_ARMNT,
423
424 for (i = 0; i < ARRAY_SIZE(machines); i++)
425 {
426 BOOLEAN ret = 0xcc;
427 status = pRtlWow64IsWowGuestMachineSupported( machines[i], &ret );
428 ok( !status, "failed %lx\n", status );
429 if (is_machine_32bit( machines[i] ) && !is_machine_32bit( native_machine ))
430 ok( ret || machines[i] == IMAGE_FILE_MACHINE_ARMNT ||
431 broken(current_machine == IMAGE_FILE_MACHINE_I386), /* win10-1607 wow64 */
432 "%04x: got %u\n", machines[i], ret );
433 else
434 ok( !ret, "%04x: got %u\n", machines[i], ret );
435 }
436 }
437}
438#endif // !defined (__REACTOS__) || (DLL_EXPORT_VERSION >= 0x600)
439
441{
442#ifdef _WIN64
443 pRtlWow64PushCrossProcessWorkOntoFreeList( list, entry );
444#else
445 entry->next = list->first;
446 list->first = (char *)entry - (char *)list;
447#endif
448}
449
451{
452#ifdef _WIN64
453 void *ret;
454 pRtlWow64PushCrossProcessWorkOntoWorkList( list, entry, &ret );
455#else
456 entry->next = list->first;
457 list->first = (char *)entry - (char *)list;
458#endif
459}
460
462{
463#ifdef _WIN64
464 return pRtlWow64PopCrossProcessWorkFromFreeList( list );
465#else
467
468 if (!list->first) return NULL;
469 ret = (CROSS_PROCESS_WORK_ENTRY *)((char *)list + list->first);
470 list->first = ret->next;
471 ret->next = 0;
472 return ret;
473#endif
474}
475
477{
478#ifdef _WIN64
480
481 return pRtlWow64PopAllCrossProcessWorkFromWorkList( list, &flush );
482#else
483 UINT pos = list->first, prev_pos = 0;
484
485 list->first = 0;
486 if (!pos) return NULL;
487
488 for (;;) /* reverse the list */
489 {
491 UINT next = entry->next;
492 entry->next = prev_pos;
493 if (!next) return entry;
494 prev_pos = pos;
495 pos = next;
496 }
497#endif
498}
499
501{
502#ifdef _WIN64
503 pRtlWow64RequestCrossProcessHeavyFlush( list );
504#else
506#endif
507}
508
509#define expect_cross_work_entry(list,entry,id,addr,size,arg0,arg1,arg2,arg3) \
510 expect_cross_work_entry_(list,entry,id,addr,size,arg0,arg1,arg2,arg3,__LINE__)
513 UINT id, void *addr, SIZE_T size,
514 UINT arg0, UINT arg1, UINT arg2, UINT arg3,
515 int line )
516{
518
519 ok_(__FILE__,line)( entry != NULL, "no more entries in list\n" );
520 if (!entry) return NULL;
521 ok_(__FILE__,line)( entry->id == id, "wrong type %u / %u\n", entry->id, id );
522 ok_(__FILE__,line)( entry->addr == (ULONG_PTR)addr, "wrong address %s / %p\n",
524 ok_(__FILE__,line)( entry->size == size, "wrong size %s / %Ix\n",
526 ok_(__FILE__,line)( entry->args[0] == arg0, "wrong args[0] %x / %x\n", entry->args[0], arg0 );
527 ok_(__FILE__,line)( entry->args[1] == arg1, "wrong args[1] %x / %x\n", entry->args[1], arg1 );
528 ok_(__FILE__,line)( entry->args[2] == arg2, "wrong args[2] %x / %x\n", entry->args[2], arg2 );
529 ok_(__FILE__,line)( entry->args[3] == arg3, "wrong args[3] %x / %x\n", entry->args[3], arg3 );
530 next = entry->next ? CROSS_PROCESS_LIST_ENTRY( &list->work_list, entry->next ) : NULL;
531 memset( entry, 0xcc, sizeof(*entry) );
532 push_onto_free_list( &list->free_list, entry );
533 return next;
534}
535
537{
540 UINT pos;
541 void *addr = NULL, *addr2;
542 SIZE_T size = 0;
543 DWORD old_prot;
547 BOOL ret;
548 BYTE data[] = { 0xcc, 0xcc, 0xcc };
549
552 ok( ret, "DuplicateHandle failed %lu\n", GetLastError() );
555 ok( !status, "NtMapViewOfSection failed %lx\n", status );
556 ok( size == 0x4000, "unexpected size %Ix\n", size );
557 list = addr;
558 addr2 = malloc( size );
559 ret = ReadProcessMemory( process, (void *)ptr, addr2, size, &size );
560 ok( ret, "ReadProcessMemory failed %lu\n", GetLastError() );
561 ok( !memcmp( addr2, addr, size ), "wrong data\n" );
562 free( addr2 );
564
565 if (pRtlOpenCrossProcessEmulatorWorkConnection)
566 {
567 pRtlOpenCrossProcessEmulatorWorkConnection( process, &mapping, &addr2 );
568 ok( mapping != 0, "got 0 handle\n" );
569 ok( addr2 != NULL, "got NULL data\n" );
570 ok( !memcmp( addr2, addr, size ), "wrong data\n" );
571 UnmapViewOfFile( addr2 );
572 addr2 = NULL;
573 size = 0;
576 ok( !status, "NtMapViewOfSection failed %lx\n", status );
577 ok( !memcmp( addr2, addr, size ), "wrong data\n" );
578 ok( CloseHandle( mapping ), "invalid handle\n" );
579 UnmapViewOfFile( addr2 );
580
581 mapping = (HANDLE)0xdead;
582 addr2 = (void *)0xdeadbeef;
583 pRtlOpenCrossProcessEmulatorWorkConnection( GetCurrentProcess(), &mapping, &addr2 );
584 ok( !mapping, "got handle %p\n", mapping );
585 ok( !addr2, "got data %p\n", addr2 );
586 }
587 else skip( "RtlOpenCrossProcessEmulatorWorkConnection not supported\n" );
588
590
591 /* set argument values in free list to detect changes */
592 for (pos = list->free_list.first; pos; pos = entry->next )
593 {
594 entry = CROSS_PROCESS_LIST_ENTRY( &list->free_list, pos );
595 memset( entry->args, 0xcc, sizeof(entry->args) );
596 }
597
599 entry = pop_from_work_list( &list->work_list );
601 {
603 MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE, 0, 0xcccccccc );
605 MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE, 0, 0xcccccccc );
606 }
607 ok( !entry, "not at end of list\n" );
608
609 VirtualProtectEx( process, (char *)addr + 0x333, 17, PAGE_READONLY, &old_prot );
610 entry = pop_from_work_list( &list->work_list );
612 {
614 (char *)addr + 0x333, 17,
615 PAGE_READONLY, 0, 0xcccccccc, 0xcccccccc );
617 PAGE_READONLY, 0, 0xcccccccc, 0xcccccccc );
618 }
619 ok( !entry, "not at end of list\n" );
620
622 entry = pop_from_work_list( &list->work_list );
624 {
626 MEM_RELEASE, 0, 0xcccccccc, 0xcccccccc );
628 MEM_RELEASE, 0, 0xcccccccc, 0xcccccccc );
629 }
630 ok( !entry, "not at end of list\n" );
631
632 addr = (void *)0x123;
633 size = 0x321;
636 "NtAllocateVirtualMemory failed %lx\n", status );
637 entry = pop_from_work_list( &list->work_list );
639 {
641 MEM_COMMIT, PAGE_EXECUTE_READ, 0, 0xcccccccc );
643 MEM_COMMIT, PAGE_EXECUTE_READ, status, 0xcccccccc );
644 }
645 ok( !entry, "not at end of list\n" );
646
647 addr = NULL;
648 size = 0x321;
650 ok( status == STATUS_INVALID_PARAMETER, "NtAllocateVirtualMemory failed %lx\n", status );
651 entry = pop_from_work_list( &list->work_list );
653 {
655 0, PAGE_EXECUTE_READ, 0, 0xcccccccc );
657 0, PAGE_EXECUTE_READ, status, 0xcccccccc );
658 }
659 ok( !entry, "not at end of list\n" );
660
661 addr = NULL;
662 size = 0x4321;
664 ok( !status, "NtAllocateVirtualMemory failed %lx\n", status );
665 entry = pop_from_work_list( &list->work_list );
667 {
669 MEM_RESERVE, PAGE_EXECUTE_READWRITE, 0, 0xcccccccc );
671 MEM_RESERVE, PAGE_EXECUTE_READWRITE, 0, 0xcccccccc );
672 }
673 ok( !entry, "not at end of list\n" );
674
675 size = 0x4321;
677 ok( !status, "NtAllocateVirtualMemory failed %lx\n", status );
678 entry = pop_from_work_list( &list->work_list );
680 {
682 MEM_COMMIT, PAGE_READWRITE, 0, 0xcccccccc );
684 MEM_COMMIT, PAGE_READWRITE, 0, 0xcccccccc );
685 }
686 ok( !entry, "not at end of list\n" );
687
688 addr2 = (char *)addr + 0x111;
689 size = 23;
691 ok( !status, "NtProtectVirtualMemory failed %lx\n", status );
692 entry = pop_from_work_list( &list->work_list );
694 {
696 PAGE_EXECUTE_READWRITE, 0, 0xcccccccc, 0xcccccccc );
698 PAGE_EXECUTE_READWRITE, 0, 0xcccccccc, 0xcccccccc );
699 }
700 ok( !entry, "not at end of list\n" );
701
702 addr2 = (char *)addr + 0x222;
703 size = 34;
706 "NtProtectVirtualMemory failed %lx\n", status );
707 entry = pop_from_work_list( &list->work_list );
709 {
711 (char *)addr + 0x222, 34,
712 PAGE_EXECUTE_WRITECOPY, 0, 0xcccccccc, 0xcccccccc );
714 (char *)addr + 0x222, 34,
715 PAGE_EXECUTE_WRITECOPY, status, 0xcccccccc, 0xcccccccc );
716 }
717 ok( !entry, "not at end of list\n" );
718
719 status = NtWriteVirtualMemory( process, (char *)addr + 0x1111, data, sizeof(data), &size );
720 ok( !status, "NtWriteVirtualMemory failed %lx\n", status );
721 entry = pop_from_work_list( &list->work_list );
722 ok( !entry, "not at end of list\n" );
723
724 addr2 = (char *)addr + 0x1234;
725 size = 45;
727 ok( !status, "NtFreeVirtualMemory failed %lx\n", status );
728 entry = pop_from_work_list( &list->work_list );
730 {
732 MEM_DECOMMIT, 0, 0xcccccccc, 0xcccccccc );
734 MEM_DECOMMIT, 0, 0xcccccccc, 0xcccccccc );
735 }
736 ok( !entry, "not at end of list\n" );
737
738 size = 0;
740 ok( !status, "NtFreeVirtualMemory failed %lx\n", status );
741 entry = pop_from_work_list( &list->work_list );
743 {
745 MEM_RELEASE, 0, 0xcccccccc, 0xcccccccc );
747 MEM_RELEASE, 0, 0xcccccccc, 0xcccccccc );
748 }
749 ok( !entry, "not at end of list\n" );
750
751 addr = (void *)0x123;
752 size = 0;
755 "NtFreeVirtualMemory failed %lx\n", status );
756 entry = pop_from_work_list( &list->work_list );
758 {
760 MEM_RELEASE, 0, 0xcccccccc, 0xcccccccc );
762 MEM_RELEASE, status, 0xcccccccc, 0xcccccccc );
763 }
764 ok( !entry, "not at end of list\n" );
765
766 file = CreateFileA( "c:\\windows\\syswow64\\version.dll", GENERIC_READ | GENERIC_EXECUTE, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, 0 );
767 ok( file != INVALID_HANDLE_VALUE, "Failed to open version.dll\n" );
769 ok( mapping != 0, "CreateFileMapping failed\n" );
770 addr = NULL;
771 size = 0;
772 offset.QuadPart = 0;
774 ok( NT_SUCCESS(status), "NtMapViewOfSection failed %lx\n", status );
775 entry = pop_from_work_list( &list->work_list );
776 ok( !entry, "list not empty\n" );
777
779 entry = pop_from_work_list( &list->work_list );
781 0xcccccccc, 0xcccccccc, 0xcccccccc, 0xcccccccc );
782 ok( !entry, "not at end of list\n" );
783
785 entry = pop_from_work_list( &list->work_list );
787 {
789 0xcccccccc, 0xcccccccc, 0xcccccccc, 0xcccccccc );
790 }
791 ok( !entry, "not at end of list\n" );
792
793 WriteProcessMemory( process, (char *)addr + 0x1ffe, data, sizeof(data), &size );
794 entry = pop_from_work_list( &list->work_list );
796 (char *)addr + 0x1000, 0x2000, 0x60000000 | PAGE_EXECUTE_WRITECOPY,
797 (current_machine != IMAGE_FILE_MACHINE_ARM64) ? 0 : 0xcccccccc,
798 0xcccccccc, 0xcccccccc );
800 (char *)addr + 0x1000, 0x2000,
801 0x60000000 | PAGE_EXECUTE_WRITECOPY, 0, 0xcccccccc, 0xcccccccc );
803 (char *)addr + 0x1ffe, sizeof(data),
804 0xcccccccc, 0xcccccccc, 0xcccccccc, 0xcccccccc );
806 (char *)addr + 0x1000, 0x2000, 0x60000000 | PAGE_EXECUTE_READ,
807 (current_machine != IMAGE_FILE_MACHINE_ARM64) ? 0 : 0xcccccccc,
808 0xcccccccc, 0xcccccccc );
810 (char *)addr + 0x1000, 0x2000,
811 0x60000000 | PAGE_EXECUTE_READ, 0, 0xcccccccc, 0xcccccccc );
812 ok( !entry, "not at end of list\n" );
813
815 ok( !status, "NtUnmapViewOfSection failed %lx\n", status );
816 entry = pop_from_work_list( &list->work_list );
817 ok( !entry, "list not empty\n" );
818
820 CloseHandle( file );
822}
823
825{
826 ULONG i, peb_data[0x200], buffer[16];
828 ULONG_PTR peb_ptr;
830 SIZE_T res;
831 BOOLEAN wow64 = 0xcc;
832
833 NtQueryInformationProcess( process, ProcessWow64Information, &peb_ptr, sizeof(peb_ptr), NULL );
834 memset( buffer, 0xcc, sizeof(buffer) );
835 status = pRtlWow64GetSharedInfoProcess( process, &wow64, info );
836 ok( !status, "RtlWow64GetSharedInfoProcess failed %lx\n", status );
837 ok( wow64 == TRUE, "wrong wow64 %u\n", wow64 );
838 todo_wine_if (!info->NativeSystemPageSize) /* not set in old wow64 */
839 {
840 ok( info->NativeSystemPageSize == 0x1000, "wrong page size %lx\n",
841 info->NativeSystemPageSize );
843 "wrong flags %lx\n", info->CpuFlags );
844 ok( info->NativeMachineType == native_machine, "wrong machine %x / %x\n",
845 info->NativeMachineType, native_machine );
846 ok( info->EmulatedMachineType == IMAGE_FILE_MACHINE_I386, "wrong machine %x\n",
847 info->EmulatedMachineType );
848 }
849 ok( buffer[sizeof(*info) / sizeof(ULONG)] == 0xcccccccc, "buffer set %lx\n",
850 buffer[sizeof(*info) / sizeof(ULONG)] );
851 if (ReadProcessMemory( process, (void *)peb_ptr, peb_data, sizeof(peb_data), &res ))
852 {
853 ULONG limit = (sizeof(peb_data) - sizeof(info)) / sizeof(ULONG);
854 for (i = 0; i < limit; i++)
855 {
856 if (!memcmp( peb_data + i, info, sizeof(*info) ))
857 {
858 trace( "wow64info found at %lx\n", i * 4 );
859 break;
860 }
861 }
862 ok( i < limit, "wow64info not found in PEB\n" );
863 }
864 if (info->SectionHandle && info->CrossProcessWorkList)
865 test_cross_process_notifications( process, info->SectionHandle, info->CrossProcessWorkList );
866 else
867 trace( "no WOW64INFO section handle\n" );
868}
869
870#if !defined (__REACTOS__) || (DLL_EXPORT_VERSION >= 0x600)
872{
873 ULONG i, peb_data[0x200], buffer[16];
876 SIZE_T res;
877 BOOLEAN wow64 = 0xcc;
878 struct arm64ec_shared_info *info = NULL;
879
880 NtQueryInformationProcess( process, ProcessBasicInformation, &proc_info, sizeof(proc_info), NULL );
881
882 memset( buffer, 0xcc, sizeof(buffer) );
883 status = pRtlWow64GetSharedInfoProcess( process, &wow64, (WOW64INFO *)buffer );
884 ok( !status, "RtlWow64GetSharedInfoProcess failed %lx\n", status );
885 ok( !wow64, "wrong wow64 %u\n", wow64 );
886 ok( buffer[0] == 0xcccccccc, "buffer initialized %lx\n", buffer[0] );
887
888 if (ReadProcessMemory( process, (void *)proc_info.PebBaseAddress, peb_data, sizeof(peb_data), &res ))
889 {
890 ULONG limit = (sizeof(peb_data) - sizeof(*info)) / sizeof(ULONG);
891 for (i = 0; i < limit; i++)
892 {
893 info = (struct arm64ec_shared_info *)(peb_data + i);
894 if (info->NativeMachineType == IMAGE_FILE_MACHINE_ARM64 &&
895 info->EmulatedMachineType == IMAGE_FILE_MACHINE_AMD64)
896 {
897 trace( "shared info found at %lx\n", i * 4 );
898 break;
899 }
900 }
901 ok( i < limit, "shared info not found in PEB\n" );
902 }
903 if (info && info->SectionHandle && info->CrossProcessWorkList)
904 test_cross_process_notifications( process, info->SectionHandle, info->CrossProcessWorkList );
905 else
906 trace( "no shared info section handle\n" );
907}
908#endif // !defined (__REACTOS__) || (DLL_EXPORT_VERSION >= 0x600)
909
910static void test_peb_teb(void)
911{
915 STARTUPINFOA si = {0};
917 void *redir;
918 SIZE_T res;
919 BOOL ret;
920 TEB teb;
921 PEB peb;
922 TEB32 teb32;
923 PEB32 peb32;
926 ULONG_PTR peb_ptr;
927 ULONG buffer[16];
928 WOW64INFO *wow64info = (WOW64INFO *)buffer;
930
932
933 if (CreateProcessA( "C:\\windows\\syswow64\\msinfo32.exe", NULL, NULL, NULL,
935 {
936 memset( &info, 0xcc, sizeof(info) );
938 ok( !status, "ThreadBasicInformation failed %lx\n", status );
939 if (!ReadProcessMemory( pi.hProcess, info.TebBaseAddress, &teb, sizeof(teb), &res )) res = 0;
940 ok( res == sizeof(teb), "wrong len %Ix\n", res );
941 ok( teb.Tib.Self == info.TebBaseAddress, "wrong teb %p / %p\n", teb.Tib.Self, info.TebBaseAddress );
942 if (is_wow64)
943 {
944 ok( !!teb.GdiBatchCount, "GdiBatchCount not set\n" );
945 ok( (char *)info.TebBaseAddress + teb.WowTebOffset == ULongToPtr(teb.GdiBatchCount) ||
946 broken(!NtCurrentTeb()->WowTebOffset), /* pre-win10 */
947 "wrong teb offset %ld\n", teb.WowTebOffset );
948 }
949 else
950 {
951 ok( !teb.GdiBatchCount, "GdiBatchCount set\n" );
952 ok( teb.WowTebOffset == 0x2000 ||
953 broken( !teb.WowTebOffset || teb.WowTebOffset == 1 ), /* pre-win10 */
954 "wrong teb offset %ld\n", teb.WowTebOffset );
955 ok( (char *)teb.Tib.ExceptionList == (char *)info.TebBaseAddress + 0x2000,
956 "wrong Tib.ExceptionList %p / %p\n",
957 (char *)teb.Tib.ExceptionList, (char *)info.TebBaseAddress + 0x2000 );
958 if (!ReadProcessMemory( pi.hProcess, teb.Tib.ExceptionList, &teb32, sizeof(teb32), &res )) res = 0;
959 ok( res == sizeof(teb32), "wrong len %Ix\n", res );
960 ok( (char *)ULongToPtr(teb32.Peb) == (char *)teb.Peb + 0x1000 ||
961 broken( ULongToPtr(teb32.Peb) != teb.Peb ), /* vista */
962 "wrong peb %p / %p\n", ULongToPtr(teb32.Peb), teb.Peb );
963 }
964
966 &proc_info, sizeof(proc_info), NULL );
967 ok( !status, "ProcessBasicInformation failed %lx\n", status );
968 ok( proc_info.PebBaseAddress == teb.Peb, "wrong peb %p / %p\n", proc_info.PebBaseAddress, teb.Peb );
969
971 &peb_ptr, sizeof(peb_ptr), NULL );
972 ok( !status, "ProcessWow64Information failed %lx\n", status );
973 ok( (void *)peb_ptr == (is_wow64 ? teb.Peb : ULongToPtr(teb32.Peb)),
974 "wrong peb %p\n", (void *)peb_ptr );
975
976 if (!ReadProcessMemory( pi.hProcess, proc_info.PebBaseAddress, &peb, sizeof(peb), &res )) res = 0;
977 ok( res == sizeof(peb), "wrong len %Ix\n", res );
978 ok( !peb.BeingDebugged, "BeingDebugged is %u\n", peb.BeingDebugged );
979 if (!is_wow64)
980 {
981 if (!ReadProcessMemory( pi.hProcess, ULongToPtr(teb32.Peb), &peb32, sizeof(peb32), &res )) res = 0;
982 ok( res == sizeof(peb32), "wrong len %Ix\n", res );
983 ok( !peb32.BeingDebugged, "BeingDebugged is %u\n", peb32.BeingDebugged );
984 }
985
986 if (!ReadProcessMemory( pi.hProcess, peb.ProcessParameters, &params, sizeof(params), &res )) res = 0;
987 ok( res == sizeof(params), "wrong len %Ix\n", res );
988#define CHECK_STR(name) \
989 ok( (char *)params.name.Buffer >= (char *)peb.ProcessParameters && \
990 (char *)params.name.Buffer < (char *)peb.ProcessParameters + params.Size, \
991 "wrong " #name " ptr %p / %p-%p\n", params.name.Buffer, peb.ProcessParameters, \
992 (char *)peb.ProcessParameters + params.Size )
993 CHECK_STR( ImagePathName );
994 CHECK_STR( CommandLine );
995 CHECK_STR( WindowTitle );
997 CHECK_STR( ShellInfo );
998#undef CHECK_STR
999 if (!is_wow64)
1000 {
1002 "wrong ptr32 %p / %p\n", ULongToPtr(peb32.ProcessParameters), peb.ProcessParameters );
1003 if (!ReadProcessMemory( pi.hProcess, ULongToPtr(peb32.ProcessParameters), &params32, sizeof(params32), &res )) res = 0;
1004 ok( res == sizeof(params32), "wrong len %Ix\n", res );
1005#define CHECK_STR(name) \
1006 ok( ULongToPtr(params32.name.Buffer) >= ULongToPtr(peb32.ProcessParameters) && \
1007 ULongToPtr(params32.name.Buffer) < ULongToPtr(peb32.ProcessParameters + params32.Size), \
1008 "wrong " #name " ptr %lx / %lx-%lx\n", params32.name.Buffer, peb32.ProcessParameters, \
1009 peb32.ProcessParameters + params.Size ); \
1010 ok( params32.name.Length == params.name.Length, "wrong " #name "len %u / %u\n", \
1011 params32.name.Length, params.name.Length )
1012 CHECK_STR( ImagePathName );
1013 CHECK_STR( CommandLine );
1014 CHECK_STR( WindowTitle );
1015 CHECK_STR( Desktop );
1016 CHECK_STR( ShellInfo );
1017#undef CHECK_STR
1018 ok( params32.EnvironmentSize == params.EnvironmentSize, "wrong size %lu / %Iu\n",
1019 params32.EnvironmentSize, params.EnvironmentSize );
1020 }
1021
1023 WaitForInputIdle( pi.hProcess, 1000 );
1024
1025 if (pRtlWow64GetSharedInfoProcess) test_wow64_shared_info( pi.hProcess );
1026 else win_skip( "RtlWow64GetSharedInfoProcess not supported\n" );
1027
1029 ok( ret, "debugging failed\n" );
1030 if (!ReadProcessMemory( pi.hProcess, proc_info.PebBaseAddress, &peb, sizeof(peb), &res )) res = 0;
1031 ok( res == sizeof(peb), "wrong len %Ix\n", res );
1032 ok( peb.BeingDebugged == !!ret, "BeingDebugged is %u\n", peb.BeingDebugged );
1033 if (!is_wow64)
1034 {
1035 if (!ReadProcessMemory( pi.hProcess, ULongToPtr(teb32.Peb), &peb32, sizeof(peb32), &res )) res = 0;
1036 ok( res == sizeof(peb32), "wrong len %Ix\n", res );
1037 ok( peb32.BeingDebugged == !!ret, "BeingDebugged is %u\n", peb32.BeingDebugged );
1038 }
1039
1043 }
1044
1045#if !defined (__REACTOS__) || (DLL_EXPORT_VERSION >= 0x600)
1047 create_process_machine( (char *)"C:\\windows\\system32\\regsvr32.exe /?", CREATE_SUSPENDED,
1049 {
1050 memset( &info, 0xcc, sizeof(info) );
1052 ok( !status, "ThreadBasicInformation failed %lx\n", status );
1053 if (!ReadProcessMemory( pi.hProcess, info.TebBaseAddress, &teb, sizeof(teb), &res )) res = 0;
1054 ok( res == sizeof(teb), "wrong len %Ix\n", res );
1055 ok( teb.Tib.Self == info.TebBaseAddress, "wrong teb %p / %p\n", teb.Tib.Self, info.TebBaseAddress );
1056 ok( !teb.GdiBatchCount, "GdiBatchCount set\n" );
1057 ok( !teb.WowTebOffset, "wrong teb offset %ld\n", teb.WowTebOffset );
1058 ok( !teb.Tib.ExceptionList, "wrong Tib.ExceptionList %p\n", (char *)teb.Tib.ExceptionList );
1059
1061 &proc_info, sizeof(proc_info), NULL );
1062 ok( !status, "ProcessBasicInformation failed %lx\n", status );
1063 ok( proc_info.PebBaseAddress == teb.Peb, "wrong peb %p / %p\n", proc_info.PebBaseAddress, teb.Peb );
1064
1066 &peb_ptr, sizeof(peb_ptr), NULL );
1067 ok( !status, "ProcessWow64Information failed %lx\n", status );
1068 ok( !peb_ptr, "wrong peb %p\n", (void *)peb_ptr );
1069
1070 if (!ReadProcessMemory( pi.hProcess, proc_info.PebBaseAddress, &peb, sizeof(peb), &res )) res = 0;
1071 ok( res == sizeof(peb), "wrong len %Ix\n", res );
1072 ok( !peb.BeingDebugged, "BeingDebugged is %u\n", peb.BeingDebugged );
1073
1075 WaitForInputIdle( pi.hProcess, 1000 );
1076
1078
1082 }
1083#endif
1084
1085 if (CreateProcessA( "C:\\windows\\system32\\msinfo32.exe", NULL, NULL, NULL,
1087 {
1088 memset( &info, 0xcc, sizeof(info) );
1090 ok( !status, "ThreadBasicInformation failed %lx\n", status );
1091 if (!is_wow64)
1092 {
1093 if (!ReadProcessMemory( pi.hProcess, info.TebBaseAddress, &teb, sizeof(teb), &res )) res = 0;
1094 ok( res == sizeof(teb), "wrong len %Ix\n", res );
1095 ok( teb.Tib.Self == info.TebBaseAddress, "wrong teb %p / %p\n",
1096 teb.Tib.Self, info.TebBaseAddress );
1097 ok( !teb.GdiBatchCount, "GdiBatchCount set\n" );
1098 ok( !teb.WowTebOffset || broken( teb.WowTebOffset == 1 ), /* vista */
1099 "wrong teb offset %ld\n", teb.WowTebOffset );
1100 }
1101 else ok( !info.TebBaseAddress, "got teb %p\n", info.TebBaseAddress );
1102
1104 &proc_info, sizeof(proc_info), NULL );
1105 ok( !status, "ProcessBasicInformation failed %lx\n", status );
1106 if (is_wow64)
1107 ok( !proc_info.PebBaseAddress ||
1108 broken( (char *)proc_info.PebBaseAddress >= (char *)0x7f000000 ), /* vista */
1109 "wrong peb %p\n", proc_info.PebBaseAddress );
1110 else
1111 ok( proc_info.PebBaseAddress == teb.Peb, "wrong peb %p / %p\n",
1112 proc_info.PebBaseAddress, teb.Peb );
1113
1115 WaitForInputIdle( pi.hProcess, 1000 );
1116
1117 if (pRtlWow64GetSharedInfoProcess)
1118 {
1119 wow64 = 0xcc;
1120 memset( buffer, 0xcc, sizeof(buffer) );
1121 status = pRtlWow64GetSharedInfoProcess( pi.hProcess, &wow64, wow64info );
1122 ok( !status, "RtlWow64GetSharedInfoProcess failed %lx\n", status );
1123 ok( !wow64, "wrong wow64 %u\n", wow64 );
1124 ok( buffer[0] == 0xcccccccc, "buffer set %lx\n", buffer[0] );
1125 }
1126
1130 }
1131
1133
1134#ifndef _WIN64
1135 if (is_wow64)
1136 {
1137 PEB64 *peb64;
1138 TEB64 *teb64 = (TEB64 *)NtCurrentTeb()->GdiBatchCount;
1139
1140 ok( !!teb64, "GdiBatchCount not set\n" );
1141 ok( (char *)NtCurrentTeb() + NtCurrentTeb()->WowTebOffset == (char *)teb64 ||
1142 broken(!NtCurrentTeb()->WowTebOffset), /* pre-win10 */
1143 "wrong WowTebOffset %lx (%p/%p)\n", NtCurrentTeb()->WowTebOffset, teb64, NtCurrentTeb() );
1144 ok( (char *)teb64 + 0x2000 == (char *)NtCurrentTeb(), "unexpected diff %p / %p\n",
1145 teb64, NtCurrentTeb() );
1146 ok( (char *)teb64 + teb64->WowTebOffset == (char *)NtCurrentTeb() ||
1147 broken( !teb64->WowTebOffset || teb64->WowTebOffset == 1 ), /* pre-win10 */
1148 "wrong WowTebOffset %lx (%p/%p)\n", teb64->WowTebOffset, teb64, NtCurrentTeb() );
1149 ok( !teb64->GdiBatchCount, "GdiBatchCount set %lx\n", teb64->GdiBatchCount );
1150 ok( teb64->Tib.ExceptionList == PtrToUlong( NtCurrentTeb() ), "wrong Tib.ExceptionList %s / %p\n",
1152 ok( teb64->Tib.Self == PtrToUlong( teb64 ), "wrong Tib.Self %s / %p\n",
1153 wine_dbgstr_longlong(teb64->Tib.Self), teb64 );
1155 "wrong StaticUnicodeString %s / %p\n",
1157 ok( teb64->ClientId.UniqueProcess == GetCurrentProcessId(), "wrong pid %s / %lx\n",
1159 ok( teb64->ClientId.UniqueThread == GetCurrentThreadId(), "wrong tid %s / %lx\n",
1161 peb64 = ULongToPtr( teb64->Peb );
1163 "wrong ImageBaseAddress %s / %p\n",
1165 ok( peb64->OSBuildNumber == NtCurrentTeb()->Peb->OSBuildNumber, "wrong OSBuildNumber %lx / %lx\n",
1167 ok( peb64->OSPlatformId == NtCurrentTeb()->Peb->OSPlatformId, "wrong OSPlatformId %lx / %lx\n",
1170 "wrong AnsiCodePageData %I64x / %p\n",
1173 "wrong OemCodePageData %I64x / %p\n",
1176 "wrong UnicodeCaseTableData %I64x / %p\n",
1178 return;
1179 }
1180#endif
1181 ok( !NtCurrentTeb()->GdiBatchCount, "GdiBatchCount set to %lx\n", NtCurrentTeb()->GdiBatchCount );
1182 ok( !NtCurrentTeb()->WowTebOffset || broken( NtCurrentTeb()->WowTebOffset == 1 ), /* vista */
1183 "WowTebOffset set to %lx\n", NtCurrentTeb()->WowTebOffset );
1184}
1185
1186static void test_selectors(void)
1187{
1188#ifndef __arm__
1191 ULONG base, limit, sel, retlen;
1193
1194#ifdef _WIN64
1195 if (!pRtlWow64GetThreadSelectorEntry)
1196 {
1197 win_skip( "RtlWow64GetThreadSelectorEntry not supported\n" );
1198 return;
1199 }
1200 if (!pRtlWow64GetThreadContext || pRtlWow64GetThreadContext( GetCurrentThread(), &context ))
1201 {
1202 /* hardcoded values */
1203#ifdef __arm64ec__
1204 context.SegCs = 0x23;
1205 context.SegSs = 0x2b;
1206 context.SegFs = 0x53;
1207#elif defined __x86_64__
1208#ifdef _MSC_VER
1209 context.SegFs = __readsegfs();
1210 context.SegSs = __readsegss();
1211#else
1212 __asm__( "movw %%fs,%0" : "=m" (context.SegFs) );
1213 __asm__( "movw %%ss,%0" : "=m" (context.SegSs) );
1214#endif
1215#else
1216 context.SegCs = 0x1b;
1217 context.SegSs = 0x23;
1218 context.SegFs = 0x3b;
1219#endif
1220 }
1221#define GET_ENTRY(info,size,ret) \
1222 pRtlWow64GetThreadSelectorEntry( GetCurrentThread(), info, size, ret )
1223
1224#else
1226#define GET_ENTRY(info,size,ret) \
1227 NtQueryInformationThread( GetCurrentThread(), ThreadDescriptorTableEntry, info, size, ret )
1228#endif
1229
1230 trace( "cs %04lx ss %04lx fs %04lx\n", context.SegCs, context.SegSs, context.SegFs );
1231 retlen = 0xdeadbeef;
1232 info.Selector = 0;
1233 status = GET_ENTRY( &info, sizeof(info) - 1, &retlen );
1234 ok( status == STATUS_INFO_LENGTH_MISMATCH, "wrong status %lx\n", status );
1235 ok( retlen == 0xdeadbeef, "len set %lu\n", retlen );
1236
1237 retlen = 0xdeadbeef;
1238 status = GET_ENTRY( &info, sizeof(info) + 1, &retlen );
1239 ok( status == STATUS_INFO_LENGTH_MISMATCH, "wrong status %lx\n", status );
1240 ok( retlen == 0xdeadbeef, "len set %lu\n", retlen );
1241
1242 retlen = 0xdeadbeef;
1243 status = GET_ENTRY( NULL, 0, &retlen );
1244 ok( status == STATUS_INFO_LENGTH_MISMATCH, "wrong status %lx\n", status );
1245 ok( retlen == 0xdeadbeef, "len set %lu\n", retlen );
1246
1247 status = GET_ENTRY( &info, sizeof(info), NULL );
1248 ok( !status, "wrong status %lx\n", status );
1249
1250 for (info.Selector = 0; info.Selector < 0x100; info.Selector++)
1251 {
1252 retlen = 0xdeadbeef;
1253 status = GET_ENTRY( &info, sizeof(info), &retlen );
1254 base = (info.Entry.BaseLow |
1255 (info.Entry.HighWord.Bytes.BaseMid << 16) |
1256 (info.Entry.HighWord.Bytes.BaseHi << 24));
1257 limit = (info.Entry.LimitLow | info.Entry.HighWord.Bits.LimitHi << 16);
1258 sel = info.Selector | 3;
1259
1260 if (sel == 0x03) /* null selector */
1261 {
1262 ok( !status, "wrong status %lx\n", status );
1263 ok( retlen == sizeof(info.Entry), "len set %lu\n", retlen );
1264 ok( !base, "wrong base %lx\n", base );
1265 ok( !limit, "wrong limit %lx\n", limit );
1266 ok( !info.Entry.HighWord.Bytes.Flags1, "wrong flags1 %x\n", info.Entry.HighWord.Bytes.Flags1 );
1267 ok( !info.Entry.HighWord.Bytes.Flags2, "wrong flags2 %x\n", info.Entry.HighWord.Bytes.Flags2 );
1268 }
1269 else if (sel == context.SegCs) /* 32-bit code selector */
1270 {
1271 ok( !status, "wrong status %lx\n", status );
1272 ok( retlen == sizeof(info.Entry), "len set %lu\n", retlen );
1273 ok( !base, "wrong base %lx\n", base );
1274 ok( limit == 0xfffff, "wrong limit %lx\n", limit );
1275 ok( info.Entry.HighWord.Bits.Type == 0x1b, "wrong type %x\n", info.Entry.HighWord.Bits.Type );
1276 ok( info.Entry.HighWord.Bits.Dpl == 3, "wrong dpl %x\n", info.Entry.HighWord.Bits.Dpl );
1277 ok( info.Entry.HighWord.Bits.Pres, "wrong pres\n" );
1278 ok( !info.Entry.HighWord.Bits.Sys, "wrong sys\n" );
1279 ok( info.Entry.HighWord.Bits.Default_Big, "wrong big\n" );
1280 ok( info.Entry.HighWord.Bits.Granularity, "wrong granularity\n" );
1281 }
1282 else if (sel == context.SegSs) /* 32-bit data selector */
1283 {
1284 ok( !status, "wrong status %lx\n", status );
1285 ok( retlen == sizeof(info.Entry), "len set %lu\n", retlen );
1286 ok( !base, "wrong base %lx\n", base );
1287 ok( limit == 0xfffff, "wrong limit %lx\n", limit );
1288 ok( info.Entry.HighWord.Bits.Type == 0x13, "wrong type %x\n", info.Entry.HighWord.Bits.Type );
1289 ok( info.Entry.HighWord.Bits.Dpl == 3, "wrong dpl %x\n", info.Entry.HighWord.Bits.Dpl );
1290 ok( info.Entry.HighWord.Bits.Pres, "wrong pres\n" );
1291 ok( !info.Entry.HighWord.Bits.Sys, "wrong sys\n" );
1292 ok( info.Entry.HighWord.Bits.Default_Big, "wrong big\n" );
1293 ok( info.Entry.HighWord.Bits.Granularity, "wrong granularity\n" );
1294 }
1295 else if (sel == context.SegFs) /* TEB selector */
1296 {
1297 ok( !status, "wrong status %lx\n", status );
1298 ok( retlen == sizeof(info.Entry), "len set %lu\n", retlen );
1299#ifdef _WIN64
1300 if (NtCurrentTeb()->WowTebOffset == 0x2000)
1301 ok( base == (ULONG_PTR)NtCurrentTeb() + 0x2000, "wrong base %lx / %p\n",
1302 base, NtCurrentTeb() );
1303#else
1304 ok( base == (ULONG_PTR)NtCurrentTeb(), "wrong base %lx / %p\n", base, NtCurrentTeb() );
1305#endif
1306 ok( limit == 0xfff || broken(limit == 0x4000), /* <= win8 */
1307 "wrong limit %lx\n", limit );
1308 ok( info.Entry.HighWord.Bits.Type == 0x13, "wrong type %x\n", info.Entry.HighWord.Bits.Type );
1309 ok( info.Entry.HighWord.Bits.Dpl == 3, "wrong dpl %x\n", info.Entry.HighWord.Bits.Dpl );
1310 ok( info.Entry.HighWord.Bits.Pres, "wrong pres\n" );
1311 ok( !info.Entry.HighWord.Bits.Sys, "wrong sys\n" );
1312 ok( info.Entry.HighWord.Bits.Default_Big, "wrong big\n" );
1313 ok( !info.Entry.HighWord.Bits.Granularity, "wrong granularity\n" );
1314 }
1315 else if (!status)
1316 {
1317 ok( retlen == sizeof(info.Entry), "len set %lu\n", retlen );
1318 trace( "succeeded for %lx base %lx limit %lx type %x\n",
1319 sel, base, limit, info.Entry.HighWord.Bits.Type );
1320 }
1321 else
1322 {
1324 ((sel & 4) && (status == STATUS_NO_LDT)) ||
1325 broken( status == STATUS_ACCESS_VIOLATION), /* <= win8 */
1326 "%lx: wrong status %lx\n", info.Selector, status );
1327 ok( retlen == 0xdeadbeef, "len set %lu\n", retlen );
1328 }
1329 }
1330#undef GET_ENTRY
1331#endif /* __arm__ */
1332}
1333
1334static void test_image_mappings(void)
1335{
1339 SIZE_T size;
1341 void *ptr;
1342
1343 if (!pNtMapViewOfSectionEx)
1344 {
1345 win_skip( "NtMapViewOfSectionEx() not supported\n" );
1346 return;
1347 }
1348
1349 offset.QuadPart = 0;
1350 file = CreateFileA( "c:\\windows\\system32\\version.dll", GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, 0 );
1351 ok( file != INVALID_HANDLE_VALUE, "Failed to open version.dll\n" );
1353 ok( mapping != 0, "CreateFileMapping failed\n" );
1354 CloseHandle( file );
1355
1356 ptr = NULL;
1357 size = 0;
1359 status = pNtMapViewOfSectionEx( mapping, process, &ptr, &offset, &size, 0, PAGE_READONLY, &ext, 1 );
1361 {
1362 win_skip( "MemExtendedParameterImageMachine not supported\n" );
1363 NtClose( mapping );
1364 return;
1365 }
1367 {
1369 "NtMapViewOfSection returned %08lx\n", status );
1371 }
1373 {
1374 todo_wine
1375 ok( status == STATUS_IMAGE_MACHINE_TYPE_MISMATCH, "NtMapViewOfSection returned %08lx\n", status );
1377 }
1378 else ok( status == STATUS_NOT_SUPPORTED, "NtMapViewOfSection returned %08lx\n", status );
1379
1380 ptr = NULL;
1381 size = 0;
1383 status = pNtMapViewOfSectionEx( mapping, process, &ptr, &offset, &size, 0, PAGE_READONLY, &ext, 1 );
1385 {
1387 "NtMapViewOfSection returned %08lx\n", status );
1389 }
1390 else ok( status == STATUS_NOT_SUPPORTED, "NtMapViewOfSection returned %08lx\n", status );
1391
1392 ptr = NULL;
1393 size = 0;
1395 status = pNtMapViewOfSectionEx( mapping, process, &ptr, &offset, &size, 0, PAGE_READONLY, &ext, 1 );
1397 {
1398 switch (current_machine)
1399 {
1402 "NtMapViewOfSection returned %08lx\n", status );
1404 break;
1406 ok( status == STATUS_IMAGE_MACHINE_TYPE_MISMATCH, "NtMapViewOfSection returned %08lx\n", status );
1408 break;
1409 default:
1410 ok( status == STATUS_NOT_SUPPORTED, "NtMapViewOfSection returned %08lx\n", status );
1411 break;
1412 }
1413 }
1414 else ok( status == STATUS_NOT_SUPPORTED, "NtMapViewOfSection returned %08lx\n", status );
1415
1416 ptr = NULL;
1417 size = 0;
1419 status = pNtMapViewOfSectionEx( mapping, process, &ptr, &offset, &size, 0, PAGE_READONLY, &ext, 1 );
1420 ok( status == STATUS_NOT_SUPPORTED, "NtMapViewOfSection returned %08lx\n", status );
1421
1422 ptr = NULL;
1423 size = 0;
1424 ext.ULong = 0;
1425 status = pNtMapViewOfSectionEx( mapping, process, &ptr, &offset, &size, 0, PAGE_READONLY, &ext, 1 );
1427 "NtMapViewOfSection returned %08lx\n", status );
1429
1430 NtClose( mapping );
1431
1432 if (is_wow64)
1433 {
1434 file = CreateFileA( "c:\\windows\\sysnative\\version.dll", GENERIC_READ, 0, NULL, OPEN_EXISTING, 0, 0 );
1435 ok( file != INVALID_HANDLE_VALUE, "Failed to open version.dll\n" );
1436
1438 ok( mapping != 0, "CreateFileMapping failed\n" );
1439 CloseHandle( file );
1440
1441 ptr = NULL;
1442 size = 0;
1443 ext.ULong = native_machine;
1444 status = pNtMapViewOfSectionEx( mapping, process, &ptr, &offset, &size, 0, PAGE_READONLY, &ext, 1 );
1446 "NtMapViewOfSection returned %08lx\n", status );
1448
1449 ptr = NULL;
1450 size = 0;
1452 status = pNtMapViewOfSectionEx( mapping, process, &ptr, &offset, &size, 0, PAGE_READONLY, &ext, 1 );
1453 ok( status == STATUS_NOT_SUPPORTED, "NtMapViewOfSection returned %08lx\n", status );
1454 NtClose( mapping );
1455 }
1457 {
1458 file = CreateFileA( "c:\\windows\\syswow64\\version.dll", GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, 0 );
1459 ok( file != INVALID_HANDLE_VALUE, "Failed to open version.dll\n" );
1460
1462 ok( mapping != 0, "CreateFileMapping failed\n" );
1463 CloseHandle( file );
1464
1465 ptr = NULL;
1466 size = 0;
1467 ext.ULong = native_machine;
1468 status = pNtMapViewOfSectionEx( mapping, process, &ptr, &offset, &size, 0, PAGE_READONLY, &ext, 1 );
1469 ok( status == STATUS_NOT_SUPPORTED, "NtMapViewOfSection returned %08lx\n", status );
1470
1471 ptr = NULL;
1472 size = 0;
1474 status = pNtMapViewOfSectionEx( mapping, process, &ptr, &offset, &size, 0, PAGE_READONLY, &ext, 1 );
1475 ok( status == STATUS_IMAGE_MACHINE_TYPE_MISMATCH, "NtMapViewOfSection returned %08lx\n", status );
1477 NtClose( mapping );
1478 }
1479}
1480
1482{
1483 0x58000048, /* ldr x8, 1f */
1484 0xd61f0100, /* br x8 */
1485 0, 0 /* 1: .quad ptr */
1486};
1487
1488static const DWORD log_params_code[] =
1489{
1490 0x10008009, /* adr x9, .+0x1000 */
1491 0xf940012a, /* ldr x10, [x9] */
1492 0xa8810540, /* stp x0, x1, [x10], #0x10 */
1493 0xa8810d42, /* stp x2, x3, [x10], #0x10 */
1494 0xa8811544, /* stp x4, x5, [x10], #0x10 */
1495 0xa8811d46, /* stp x6, x7, [x10], #0x10 */
1496 0xf900012a, /* str x10, [x9] */
1497 0xf9400520, /* ldr x0, [x9, #0x8] */
1498 0xd65f03c0, /* ret */
1499};
1500
1502{
1503}
1504
1506{
1509};
1510
1512{
1513 memset( results + 1, 0xcc, 0x1000 - sizeof(*results) );
1514 results[0] = (ULONG_PTR)(results + 2);
1515}
1516
1517#define expect_notifications(results, count, expect, syscall) \
1518 expect_notifications_(results, count, expect, syscall, __LINE__)
1520 BOOL syscall, int line )
1521{
1522 ULONG64 *regs = results + 2;
1523 UINT i, j, len = (results[0] - (ULONG_PTR)regs) / 8 / sizeof(*regs);
1524
1525#ifdef _WIN64
1526 if (syscall)
1527 {
1528 CHPE_V2_CPU_AREA_INFO *cpu_area = NtCurrentTeb()->ChpeV2CpuAreaInfo;
1529 if (cpu_area && cpu_area->InSyscallCallback) count = 0;
1530 }
1531#endif
1532
1533 ok_(__FILE__,line)( count == len, "wrong notification count %u / %u\n", len, count );
1534 for (i = 0; i < min( count, len ); i++, expect++, regs += 8)
1535 for (j = 0; j < expect->nb_args; j++)
1536 ok_(__FILE__,line)( regs[j] == expect->args[j], "%u: wrong args[%u] %I64x / %I64x\n",
1537 i, j, regs[j], expect->args[j] );
1539}
1540
1542 UINT arg0, UINT arg1, UINT arg2, UINT arg3 )
1543{
1545
1546 entry->id = id;
1547 entry->addr = addr;
1548 entry->size = size;
1549 entry->args[0] = arg0;
1550 entry->args[1] = arg1;
1551 entry->args[2] = arg2;
1552 entry->args[3] = arg3;
1553 push_onto_work_list( &list->work_list, entry );
1554}
1555
1556static void process_work_items(void)
1557{
1558#ifdef _WIN64
1559 if (pProcessPendingCrossProcessEmulatorWork)
1560 {
1561 pProcessPendingCrossProcessEmulatorWork();
1562 return;
1563 }
1564#endif
1566 SleepEx( 1, TRUE );
1567}
1568
1569static BYTE old_code[sizeof(hook_code)];
1570
1571static void *hook_notification_function( HMODULE module, const char *win32_name, const char *win64_name )
1572{
1573 BYTE *ptr;
1574 BOOL ret;
1575
1577 {
1578 static const BYTE fast_forward[] = { 0x48, 0x8b, 0xc4, 0x48, 0x89, 0x58, 0x20, 0x55, 0x5d, 0xe9 };
1579
1580 if (!(ptr = pRtlFindExportedRoutineByName( module, win64_name )))
1581 {
1582 skip( "%s not exported\n", win64_name );
1583 return NULL;
1584 }
1585 if (memcmp( ptr, fast_forward, sizeof(fast_forward) ))
1586 {
1587 skip( "unrecognized x64 thunk for %s\n", win64_name );
1588 return NULL;
1589 }
1590 ptr += sizeof(fast_forward);
1591 ptr += sizeof(LONG) + *(LONG *)ptr;
1592 }
1593 else if (!(ptr = pRtlFindExportedRoutineByName( module, win32_name )))
1594 {
1595 skip( "%s not exported\n", win32_name );
1596 return NULL;
1597 }
1598
1599 memcpy( old_code, ptr, sizeof(old_code) );
1601 ok( ret, "hooking failed %p %lu\n", ptr, GetLastError() );
1602 return ptr;
1603}
1604
1606{
1607 void *code, *ptr, *addr = NULL;
1608 DWORD old_prot;
1609 SIZE_T size;
1613
1616 VirtualProtect( code, 0x1000, PAGE_EXECUTE_READ, &old_prot );
1617 *(void **)&hook_code[2] = code;
1618
1619 results = (ULONG64 *)((char *)code + 0x1000);
1621
1622 file = CreateFileA( "c:\\windows\\system32\\version.dll", GENERIC_READ | GENERIC_EXECUTE,
1624 ok( file != INVALID_HANDLE_VALUE, "Failed to open version.dll\n" );
1626 ok( mapping != 0, "CreateFileMapping failed\n" );
1627
1628 if ((ptr = hook_notification_function( module, "BTCpuNotifyMemoryAlloc", "NotifyMemoryAlloc" )))
1629 {
1630 struct expected_notification expect_cross[2] =
1631 {
1632 { 6, { 0x1234567890, 0x6543210000, MEM_COMMIT, PAGE_EXECUTE_READ, 0, 0 } },
1633 { 6, { 0x1234567890, 0x6543210000, MEM_COMMIT, PAGE_EXECUTE_READ, 1, 0xdeadbeef } }
1634 };
1635 struct expected_notification expect_alloc[2] =
1636 {
1637 { 6, { 0, 0x123456, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE, 0, 0 } },
1638 { 6, { 0, 0x124000, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE, 1, 0 } }
1639 };
1640
1641 add_work_item( list, CrossProcessPreVirtualAlloc, expect_cross[0].args[0], expect_cross[0].args[1],
1642 expect_cross[0].args[2], expect_cross[0].args[3], 0, 0 );
1643 add_work_item( list, CrossProcessPostVirtualAlloc, expect_cross[1].args[0], expect_cross[1].args[1],
1644 expect_cross[1].args[2], expect_cross[1].args[3], 0xdeadbeef, 0 );
1646 expect_notifications( results, 2, expect_cross, FALSE );
1647 ok( !list->work_list.first, "list not empty\n" );
1648
1649 size = expect_alloc[0].args[1];
1651 ok( !status, "NtAllocateVirtualMemory failed %lx\n", status );
1652 expect_alloc[1].args[0] = (ULONG_PTR)addr;
1653 expect_notifications( results, 2, expect_alloc, TRUE );
1655 }
1656
1657 if ((ptr = hook_notification_function( module, "BTCpuNotifyMemoryProtect", "NotifyMemoryProtect" )))
1658 {
1659 struct expected_notification expect_cross[2] =
1660 {
1661 { 5, { 0x1234567890, 0x6543210000, PAGE_READWRITE, 0, 0 } },
1662 { 5, { 0x1234567890, 0x6543210000, PAGE_READWRITE, 1, 0xdeadbeef } }
1663 };
1664 struct expected_notification expect_protect[2] =
1665 {
1666 { 5, { 0, 0x123456, PAGE_EXECUTE_READ, 0, 0 } },
1667 { 5, { 0, 0x124000, PAGE_EXECUTE_READ, 1, 0 } }
1668 };
1669
1672 expect_cross[0].args[1], expect_cross[0].args[2], 0, 0, 0 );
1674 expect_cross[1].args[1], expect_cross[1].args[2], 0xdeadbeef, 0, 0 );
1676 expect_notifications( results, 2, expect_cross, FALSE );
1677 ok( !list->work_list.first, "list not empty\n" );
1678
1679 expect_protect[1].args[0] = (ULONG_PTR)addr;
1680 addr = (char *)addr + 0x123;
1681 expect_protect[0].args[0] = (ULONG_PTR)addr;
1682 size = expect_protect[0].args[1];
1684 ok( !status, "NtProtectVirtualMemory failed %lx\n", status );
1685 expect_notifications( results, 2, expect_protect, TRUE );
1686
1689 }
1690
1691 if ((ptr = hook_notification_function( module, "BTCpuNotifyMemoryFree", "NotifyMemoryFree" )))
1692 {
1693 struct expected_notification expect_cross[2] =
1694 {
1695 { 5, { 0x1234567890, 0x6543210000, MEM_RELEASE, 0, 0 } },
1696 { 5, { 0x1234567890, 0x6543210000, MEM_RELEASE, 1, 0xdeadbeef } }
1697 };
1698 struct expected_notification expect_free[2] =
1699 {
1700 { 5, { 0, 0x123456, MEM_RELEASE, 0, 0 } },
1701 { 5, { 0, 0x124000, MEM_RELEASE, 1, 0 } }
1702 };
1703
1704 add_work_item( list, CrossProcessPreVirtualFree, expect_cross[0].args[0],
1705 expect_cross[0].args[1], expect_cross[0].args[2], 0, 0, 0 );
1706 add_work_item( list, CrossProcessPostVirtualFree, expect_cross[1].args[0],
1707 expect_cross[1].args[1], expect_cross[1].args[2], 0xdeadbeef, 0, 0 );
1709 expect_notifications( results, 2, expect_cross, FALSE );
1710 ok( !list->work_list.first, "list not empty\n" );
1711
1712 expect_free[0].args[0] = (ULONG_PTR)addr;
1713 expect_free[1].args[0] = (ULONG_PTR)addr;
1714 size = expect_free[0].args[1];
1716 ok( !status, "NtFreeVirtualMemory failed %lx\n", status );
1717 expect_notifications( results, 2, expect_free, TRUE );
1718
1720 }
1721
1722 if ((ptr = hook_notification_function( module, "BTCpuNotifyMemoryDirty", "BTCpu64NotifyMemoryDirty" )))
1723 {
1724 struct expected_notification expect = { 2, { 0x1234567890, 0x6543210000 } };
1725
1726 add_work_item( list, CrossProcessMemoryWrite, expect.args[0], expect.args[1], 0, 0, 0, 0 );
1729 ok( !list->work_list.first, "list not empty\n" );
1730
1732 }
1733
1734 if ((ptr = hook_notification_function( module, "BTCpuFlushInstructionCache2", "BTCpu64FlushInstructionCache" )))
1735 {
1736 struct expected_notification expect_cross = { 2, { 0x1234567890, 0x6543210000 } };
1737 struct expected_notification expect_flush = { 2, { 0, 0x1234 } };
1738
1741 expect_cross.args[1], 0, 0, 0, 0 );
1743 expect_notifications( results, 1, &expect_cross, FALSE );
1744 ok( !list->work_list.first, "list not empty\n" );
1745
1746 expect_flush.args[0] = (ULONG_PTR)ptr;
1747 NtFlushInstructionCache( GetCurrentProcess(), ptr, expect_flush.args[1] );
1748 expect_notifications( results, 1, &expect_flush, TRUE );
1749
1751 }
1752
1753 if ((ptr = hook_notification_function( module, "BTCpuFlushInstructionCacheHeavy", "FlushInstructionCacheHeavy" )))
1754 {
1755 struct expected_notification expect = { 2, { 0x1234567890, 0x6543210000 } };
1756 struct expected_notification expect2 = { 2 };
1757
1759 add_work_item( list, CrossProcessFlushCacheHeavy, expect.args[0], expect.args[1], 0, 0, 0, 0 );
1762 ok( !list->work_list.first, "list not empty\n" );
1763
1764 request_cross_process_flush( &list->work_list );
1767 ok( !list->work_list.first, "list not empty\n" );
1768
1770 }
1771
1772 if ((ptr = hook_notification_function( module, "BTCpuNotifyMapViewOfSection", "NotifyMapViewOfSection" )))
1773 {
1774 struct expected_notification expect = { 6 };
1776
1777 addr = NULL;
1778 size = 0;
1779 offset.QuadPart = 0;
1782 ok( NT_SUCCESS(status), "NtMapViewOfSection failed %lx\n", status );
1785
1786 /* only NtMapViewOfSection calls coming from the loader trigger a notification */
1787 NtCurrentTeb()->Tib.ArbitraryUserPointer = (WCHAR *)L"c:\\windows\\system32\\version.dll";
1788 addr = NULL;
1789 size = 0;
1793 ok( NT_SUCCESS(status), "NtMapViewOfSection failed %lx\n", status );
1794 expect.args[0] = results[2]; /* FIXME: first parameter unknown */
1795 expect.args[1] = (ULONG_PTR)addr;
1796 expect.args[3] = size;
1797 expect.args[5] = PAGE_READONLY;
1800
1801 results[1] = 0xdeadbeef;
1804#ifdef _WIN64
1805 if (NtCurrentTeb()->ChpeV2CpuAreaInfo->InSyscallCallback)
1806 {
1807 ok( status == STATUS_SUCCESS, "NtMapViewOfSection failed %lx\n", status );
1810 }
1811 else
1812#endif
1813 {
1814 ok( status == 0xdeadbeef, "NtMapViewOfSection failed %lx\n", status );
1815 expect.args[0] = results[2]; /* FIXME: first parameter unknown */
1816 expect.args[1] = (ULONG_PTR)addr;
1817 expect.args[3] = size;
1818 expect.args[5] = PAGE_READONLY;
1820 }
1821 NtCurrentTeb()->Tib.ArbitraryUserPointer = NULL;
1823 }
1824
1825 if ((ptr = hook_notification_function( module, "BTCpuNotifyUnmapViewOfSection", "NotifyUnmapViewOfSection" )))
1826 {
1827 struct expected_notification expect[2] = { { 3 }, { 3 } };
1829
1830 addr = NULL;
1831 size = 0;
1832 offset.QuadPart = 0;
1835 ok( NT_SUCCESS(status), "NtMapViewOfSection failed %lx\n", status );
1836 NtUnmapViewOfSection( GetCurrentProcess(), (char *)addr + 0x123 );
1837 expect[0].args[0] = expect[1].args[0] = (ULONG_PTR)addr + 0x123;
1838 expect[1].args[1] = 1;
1840
1841 NtUnmapViewOfSection( GetCurrentProcess(), (char *)0x1234 );
1842 expect[0].args[0] = expect[1].args[0] = 0x1234;
1843 expect[1].args[1] = 1;
1844 expect[1].args[2] = (ULONG)STATUS_NOT_MAPPED_VIEW;
1846
1848 }
1849
1850 if ((ptr = hook_notification_function( module, "BTCpuNotifyReadFile", "BTCpu64NotifyReadFile" )))
1851 {
1852 char buffer[0x123];
1854 struct expected_notification expect[2] =
1855 {
1856 { 5, { (ULONG_PTR)file, (ULONG_PTR)buffer, sizeof(buffer), 0, 0 } },
1857 { 5, { (ULONG_PTR)file, (ULONG_PTR)buffer, sizeof(buffer), 1, 0 } }
1858 };
1859
1861 status = NtReadFile( file, 0, NULL, NULL, &io, buffer, sizeof(buffer), NULL, NULL );
1862 ok( !status, "NtReadFile failed %lx\n", status );
1864
1865 status = NtReadFile( (HANDLE)0xdead, 0, NULL, NULL, &io, buffer, sizeof(buffer), NULL, NULL );
1866 ok( status == STATUS_INVALID_HANDLE, "NtReadFile failed %lx\n", status );
1867 expect[0].args[0] = expect[1].args[0] = 0xdead;
1868 expect[1].args[4] = (ULONG)STATUS_INVALID_HANDLE;
1870
1872 }
1873
1874 if ((ptr = hook_notification_function( module, "BTCpuThreadTerm", "ThreadTerm" )))
1875 {
1876 struct expected_notification expect = { 2, { 0xdead, 0xbeef } };
1877
1879 status = NtTerminateThread( (HANDLE)0xdead, 0xbeef );
1880 ok( status == STATUS_INVALID_HANDLE, "NtTerminateThread failed %lx\n", status );
1882
1884 }
1885
1886 if ((ptr = hook_notification_function( module, "BTCpuProcessTerm", "ProcessTerm" )))
1887 {
1888 struct expected_notification expect[2] =
1889 {
1890 { 3, { 0, 0, 0 } },
1891 { 3, { 0, 1, 0 } }
1892 };
1893
1895 status = NtTerminateProcess( (HANDLE)0xdead, 0xbeef );
1896 ok( status == STATUS_INVALID_HANDLE, "NtTerminateProcess failed %lx\n", status );
1898
1899 status = NtTerminateProcess( 0, 0xbeef );
1900 ok( !status, "NtTerminateProcess failed %lx\n", status );
1902
1904 }
1905
1906 NtClose( mapping );
1907 NtClose( file );
1909}
1910
1911
1912#ifdef _WIN64
1913
1914static void test_cross_process_work_list(void)
1915{
1916 UINT i, next, count = 10, size = offsetof( CROSS_PROCESS_WORK_LIST, entries[count] );
1917 BOOLEAN res, flush;
1920
1921 if (!pRtlWow64PopAllCrossProcessWorkFromWorkList)
1922 {
1923 win_skip( "cross process list not supported\n" );
1924 return;
1925 }
1926
1927 list = calloc( size, 1 );
1928 for (i = 0; i < count; i++)
1929 {
1930 res = pRtlWow64PushCrossProcessWorkOntoFreeList( &list->free_list, &list->entries[i] );
1931 ok( res == TRUE, "%u: RtlWow64PushCrossProcessWorkOntoFreeList failed\n", i );
1932 }
1933
1934 ok( list->free_list.counter == count, "wrong counter %u\n", list->free_list.counter );
1935 ok( CROSS_PROCESS_LIST_ENTRY( &list->free_list, list->free_list.first ) == &list->entries[count - 1],
1936 "wrong offset %u\n", list->free_list.first );
1937 for (i = count; i > 1; i--)
1938 ok( CROSS_PROCESS_LIST_ENTRY( &list->free_list, list->entries[i - 1].next ) == &list->entries[i - 2],
1939 "%u: wrong offset %x / %x\n", i, list->entries[i - 1].next,
1940 (UINT)((char *)&list->entries[i - 2] - (char *)&list->free_list) );
1941 ok( !list->entries[0].next, "wrong last offset %x\n", list->entries[0].next );
1942
1943 next = list->entries[count - 1].next;
1944 ptr = pRtlWow64PopCrossProcessWorkFromFreeList( &list->free_list );
1945 ok( ptr == (void *)&list->entries[count - 1], "wrong ptr %p (%p)\n", ptr, list );
1946 ok( !ptr->next, "next not reset %x\n", ptr->next );
1947 ok( list->free_list.first == next, "wrong offset %x / %x\n", list->free_list.first, next );
1948 ok( list->free_list.counter == count + 1, "wrong counter %u\n", list->free_list.counter );
1949
1950 ptr->next = 0xdead;
1951 ptr->id = 3;
1952 ptr->addr = 0xdeadbeef;
1953 ptr->size = 0x1000;
1954 ptr->args[0] = 7;
1955 ret = (void *)0xdeadbeef;
1956 res = pRtlWow64PushCrossProcessWorkOntoWorkList( &list->work_list, ptr, (void **)&ret );
1957 ok( res == TRUE, "RtlWow64PushCrossProcessWorkOntoWorkList failed\n" );
1958 ok( !ret, "got ret ptr %p\n", ret );
1959 ok( list->work_list.counter == 1, "wrong counter %u\n", list->work_list.counter );
1960 ok( ptr == CROSS_PROCESS_LIST_ENTRY( &list->work_list, list->work_list.first), "wrong ptr %p / %p\n",
1961 ptr, CROSS_PROCESS_LIST_ENTRY( &list->work_list, list->work_list.first ));
1962 ok( !ptr->next, "got next %x\n", ptr->next );
1963
1964 next = list->work_list.first;
1965 ptr = pRtlWow64PopCrossProcessWorkFromFreeList( &list->free_list );
1966 ok( list->free_list.counter == count + 2, "wrong counter %u\n", list->free_list.counter );
1967 ptr->id = 20;
1968 ptr->addr = 0x123456;
1969 ptr->size = 0x2345;
1970 res = pRtlWow64PushCrossProcessWorkOntoWorkList( &list->work_list, ptr, (void **)&ret );
1971 ok( res == TRUE, "RtlWow64PushCrossProcessWorkOntoWorkList failed\n" );
1972 ok( !ret, "got ret ptr %p\n", ret );
1973 ok( list->work_list.counter == 2, "wrong counter %u\n", list->work_list.counter );
1974 ok( list->work_list.first == (char *)ptr - (char *)&list->work_list, "wrong ptr %p / %p\n",
1975 ptr, (char *)list + list->work_list.first );
1976 ok( ptr->next == next, "got wrong next %x / %x\n", ptr->next, next );
1977
1978 flush = 0xcc;
1979 ptr = pRtlWow64PopAllCrossProcessWorkFromWorkList( &list->work_list, &flush );
1980 ok( !flush, "RtlWow64PopAllCrossProcessWorkFromWorkList flush is TRUE\n" );
1981 ok( list->work_list.counter == 3, "wrong counter %u\n", list->work_list.counter );
1982 ok( !list->work_list.first, "list not empty %x\n", list->work_list.first );
1983 ok( ptr->addr == 0xdeadbeef, "wrong addr %s\n", wine_dbgstr_longlong(ptr->addr) );
1984 ok( ptr->size == 0x1000, "wrong size %s\n", wine_dbgstr_longlong(ptr->size) );
1985 ok( ptr->next, "next not set\n" );
1986
1987 ptr = CROSS_PROCESS_LIST_ENTRY( &list->work_list, ptr->next );
1988 ok( ptr->addr == 0x123456, "wrong addr %s\n", wine_dbgstr_longlong(ptr->addr) );
1989 ok( ptr->size == 0x2345, "wrong size %s\n", wine_dbgstr_longlong(ptr->size) );
1990 ok( !ptr->next, "list not terminated\n" );
1991
1992 res = pRtlWow64PushCrossProcessWorkOntoWorkList( &list->work_list, ptr, (void **)&ret );
1993 ok( res == TRUE, "RtlWow64PushCrossProcessWorkOntoWorkList failed\n" );
1994 ok( !ret, "got ret ptr %p\n", ret );
1995 ok( list->work_list.counter == 4, "wrong counter %u\n", list->work_list.counter );
1996
1997 res = pRtlWow64RequestCrossProcessHeavyFlush( &list->work_list );
1998 ok( res == TRUE, "RtlWow64RequestCrossProcessHeavyFlush failed\n" );
1999 ok( list->work_list.counter == 5, "wrong counter %u\n", list->work_list.counter );
2000 ok( list->work_list.first & CROSS_PROCESS_LIST_FLUSH, "flush flag not set %x\n", list->work_list.first );
2001 ok( ptr == CROSS_PROCESS_LIST_ENTRY( &list->work_list, list->work_list.first), "wrong ptr %p / %p\n",
2002 ptr, CROSS_PROCESS_LIST_ENTRY( &list->work_list, list->work_list.first ));
2003
2004 flush = 0xcc;
2005 ptr = pRtlWow64PopAllCrossProcessWorkFromWorkList( &list->work_list, &flush );
2006 ok( flush == TRUE, "RtlWow64PopAllCrossProcessWorkFromWorkList flush not set\n" );
2007 ok( list->work_list.counter == 6, "wrong counter %u\n", list->work_list.counter );
2008 ok( !list->work_list.first, "list not empty %x\n", list->work_list.first );
2009 ok( ptr->addr == 0x123456, "wrong addr %s\n", wine_dbgstr_longlong(ptr->addr) );
2010 ok( ptr->size == 0x2345, "wrong size %s\n", wine_dbgstr_longlong(ptr->size) );
2011 ok( !ptr->next, "next not set\n" );
2012
2013 flush = 0xcc;
2014 ptr = pRtlWow64PopAllCrossProcessWorkFromWorkList( &list->work_list, &flush );
2015 ok( flush == FALSE, "RtlWow64PopAllCrossProcessWorkFromWorkList flush set\n" );
2016 ok( list->work_list.counter == 6, "wrong counter %u\n", list->work_list.counter );
2017 ok( !list->work_list.first, "list not empty %x\n", list->work_list.first );
2018 ok( !ptr, "got ptr %p\n", ptr );
2019
2020 res = pRtlWow64RequestCrossProcessHeavyFlush( &list->work_list );
2021 ok( res == TRUE, "RtlWow64RequestCrossProcessHeavyFlush failed\n" );
2022 ok( list->work_list.counter == 7, "wrong counter %u\n", list->work_list.counter );
2023 ok( list->work_list.first & CROSS_PROCESS_LIST_FLUSH, "flush flag not set %x\n", list->work_list.first );
2024
2025 res = pRtlWow64RequestCrossProcessHeavyFlush( &list->work_list );
2026 ok( res == TRUE, "RtlWow64RequestCrossProcessHeavyFlush failed\n" );
2027 ok( list->work_list.counter == 8, "wrong counter %u\n", list->work_list.counter );
2028 ok( list->work_list.first & CROSS_PROCESS_LIST_FLUSH, "flush flag not set %x\n", list->work_list.first );
2029
2030 flush = 0xcc;
2031 ptr = pRtlWow64PopAllCrossProcessWorkFromWorkList( &list->work_list, &flush );
2032 ok( flush == TRUE, "RtlWow64PopAllCrossProcessWorkFromWorkList flush set\n" );
2033 ok( list->work_list.counter == 9, "wrong counter %u\n", list->work_list.counter );
2034 ok( !list->work_list.first, "list not empty %x\n", list->work_list.first );
2035 ok( !ptr, "got ptr %p\n", ptr );
2036
2037 for (i = 0; i < count; i++)
2038 {
2039 ptr = pRtlWow64PopCrossProcessWorkFromFreeList( &list->free_list );
2040 if (!ptr) break;
2041 ok( list->free_list.counter == count + 3 + i, "wrong counter %u\n", list->free_list.counter );
2042 }
2043 ok( list->free_list.counter == count + 2 + i, "wrong counter %u\n", list->free_list.counter );
2044 ok( !list->free_list.first, "first still set %x\n", list->free_list.first );
2045
2046 free( list );
2047}
2048
2049
2050static void test_cpu_area(void)
2051{
2052 if (pRtlWow64GetCpuAreaInfo)
2053 {
2054 static const struct
2055 {
2059 } tests[] =
2060 {
2061 { IMAGE_FILE_MACHINE_I386, 0, 4, 0x2cc, 0x00, 0x00010000 },
2062 { IMAGE_FILE_MACHINE_AMD64, 0, 16, 0x4d0, 0x30, 0x00100000 },
2063 { IMAGE_FILE_MACHINE_ARMNT, 0, 8, 0x1a0, 0x00, 0x00200000 },
2064 { IMAGE_FILE_MACHINE_ARM64, 0, 16, 0x390, 0x00, 0x00400000 },
2067 };
2068 USHORT buffer[2048];
2071 ULONG i, j;
2073#define ALIGN(ptr,align) ((void *)(((ULONG_PTR)(ptr) + (align) - 1) & ~((align) - 1)))
2074
2075 for (i = 0; i < ARRAY_SIZE(tests); i++)
2076 {
2077 for (j = 0; j < 8; j++)
2078 {
2079 cpu = (WOW64_CPURESERVED *)(buffer + j);
2080 cpu->Flags = 0;
2081 cpu->Machine = tests[i].machine;
2082 status = pRtlWow64GetCpuAreaInfo( cpu, 0, &info );
2083 ok( status == tests[i].expect, "%lu:%lu: failed %lx\n", i, j, status );
2084 if (status) continue;
2085 ok( info.Context == ALIGN( cpu + 1, tests[i].align ) ||
2086 broken( (ULONG_PTR)info.Context == (ULONG)(ULONG_PTR)ALIGN( cpu + 1, tests[i].align ) ), /* win10 <= 1709 */
2087 "%lu:%lu: wrong offset %Iu cpu %p context %p\n",
2088 i, j, (ULONG_PTR)((char *)info.Context - (char *)cpu), cpu, info.Context );
2089 ok( info.ContextEx == ALIGN( (char *)info.Context + tests[i].size, sizeof(void*) ),
2090 "%lu:%lu: wrong ex offset %lu\n", i, j, (ULONG)((char *)info.ContextEx - (char *)cpu) );
2091 ok( info.ContextFlagsLocation == (char *)info.Context + tests[i].offset,
2092 "%lu:%lu: wrong flags offset %lu\n",
2093 i, j, (ULONG)((char *)info.ContextFlagsLocation - (char *)info.Context) );
2094 ok( info.CpuReserved == cpu, "%lu:%lu: wrong cpu %p / %p\n", i, j, info.CpuReserved, cpu );
2095 ok( info.ContextFlag == tests[i].flag, "%lu:%lu: wrong flag %08lx\n", i, j, info.ContextFlag );
2096 ok( info.Machine == tests[i].machine, "%lu:%lu: wrong machine %x\n", i, j, info.Machine );
2097 }
2098 }
2099#undef ALIGN
2100 }
2101 else win_skip( "RtlWow64GetCpuAreaInfo not supported\n" );
2102}
2103
2104static void test_exception_dispatcher(void)
2105{
2106#ifdef __x86_64__
2108 void **hook;
2109
2110 /* cld; mov xxx(%rip),%rax */
2111 ok( code[0] == 0xfc && code[1] == 0x48 && code[2] == 0x8b && code[3] == 0x05,
2112 "wrong opcodes %02x %02x %02x %02x\n", code[0], code[1], code[2], code[3] );
2113 hook = (void **)(code + 8 + *(int *)(code + 4));
2114 ok( !*hook, "hook %p set to %p\n", hook, *hook );
2115#endif
2116}
2117
2118#ifdef __arm64ec__
2119static DWORD CALLBACK simulation_thread( void *arg )
2120{
2121 BYTE code[] =
2122 {
2123 0x48, 0xc7, 0xc1, 0x34, 0x12, 0x00, 0x00, /* mov $0x1234,%rcx */
2124 0x48, 0xb8, 0, 0, 0, 0, 0, 0, 0, 0, /* movabs $RtlExitUserThread,%rax */
2125 0xff, 0xd0, /* call *%rax */
2126 0xc3, /* ret */
2127 };
2128 DWORD old_prot;
2130 void (WINAPI *pBeginSimulation)(void) = arg;
2131 void *addr = VirtualAlloc( NULL, 0x1000, MEM_COMMIT, PAGE_READWRITE );
2132
2133 *(void **)(code + 9) = GetProcAddress( GetModuleHandleA("ntdll.dll"), "RtlExitUserThread" );
2134 memcpy( addr, code, sizeof(code) );
2135 VirtualProtect( addr, 0x1000, PAGE_EXECUTE_READ, &old_prot );
2136
2137 context = &NtCurrentTeb()->ChpeV2CpuAreaInfo->ContextAmd64->AMD64_Context;
2138 context->Rsp = (ULONG_PTR)&context - 0x800;
2139 context->Rip = (ULONG_PTR)addr;
2140
2141 NtCurrentTeb()->ChpeV2CpuAreaInfo->InSimulation = 1; /* otherwise it crashes on recent Windows */
2142 pBeginSimulation();
2143 return 0x5678;
2144}
2145#endif
2146
2147static void test_xtajit64(void)
2148{
2149#ifdef __arm64ec__
2150 HMODULE module = GetModuleHandleA( "xtajit64.dll" );
2151 BOOLEAN (WINAPI *pBTCpu64IsProcessorFeaturePresent)( UINT feature );
2152 void (WINAPI *pUpdateProcessorInformation)( SYSTEM_CPU_INFORMATION *info );
2153 void (WINAPI *pBeginSimulation)(void);
2154 UINT i;
2155
2156 if (!module)
2157 {
2158 win_skip( "xtaji64.dll not loaded\n" );
2159 return;
2160 }
2161#define GET_PROC(func) p##func = pRtlFindExportedRoutineByName( module, #func )
2162 GET_PROC( BTCpu64IsProcessorFeaturePresent );
2163 GET_PROC( BeginSimulation );
2164 GET_PROC( UpdateProcessorInformation );
2165#undef GET_PROC
2166
2167 if (pBTCpu64IsProcessorFeaturePresent)
2168 {
2169 static const ULONGLONG expect_features =
2170 (1ull << PF_COMPARE_EXCHANGE_DOUBLE) |
2175 (1ull << PF_NX_ENABLED) |
2177 (1ull << PF_COMPARE_EXCHANGE128) |
2178 (1ull << PF_FASTFAIL_AVAILABLE) |
2183
2184 for (i = 0; i < 64; i++)
2185 {
2186 BOOLEAN ret = pBTCpu64IsProcessorFeaturePresent( i );
2187 if (expect_features & (1ull << i)) ok( ret, "missing feature %u\n", i );
2188 else if (ret) trace( "extra feature %u supported\n", i );
2189 }
2190 }
2191 else win_skip( "BTCpu64IsProcessorFeaturePresent missing\n" );
2192
2193 if (pUpdateProcessorInformation)
2194 {
2196
2197 memset( &info, 0xcc, sizeof(info) );
2198 info.ProcessorArchitecture = PROCESSOR_ARCHITECTURE_ARM64;
2199 pUpdateProcessorInformation( &info );
2200
2201 ok( info.ProcessorArchitecture == PROCESSOR_ARCHITECTURE_AMD64,
2202 "wrong architecture %u\n", info.ProcessorArchitecture );
2203 ok( info.ProcessorLevel == 21, "wrong level %u\n", info.ProcessorLevel );
2204 ok( info.ProcessorRevision == 1, "wrong revision %u\n", info.ProcessorRevision );
2205 ok( info.MaximumProcessors == 0xcccc, "wrong max proc %u\n", info.MaximumProcessors );
2206 ok( info.ProcessorFeatureBits == 0xcccccccc, "wrong features %lx\n", info.ProcessorFeatureBits );
2207 }
2208 else win_skip( "UpdateProcessorInformation missing\n" );
2209
2210 if (pBeginSimulation)
2211 {
2213 HANDLE thread = CreateThread( NULL, 0, simulation_thread, pBeginSimulation, 0, NULL );
2214
2215 ok( thread != 0, "thread creation failed\n" );
2216 ret = WaitForSingleObject( thread, 10000 );
2217 ok( !ret, "wait failed %lx\n", ret );
2219 ok( exit_code == 0x1234, "wrong exit code %lx\n", exit_code );
2221 }
2222 else win_skip( "BeginSimulation missing\n" );
2223#endif
2224}
2225
2226
2227static void test_memory_notifications(void)
2228{
2231
2233 if (!(module = GetModuleHandleA( "xtajit64.dll" ))) return;
2234 info = NtCurrentTeb()->Peb->ChpeV2ProcessInfo;
2235 if (info->NativeMachineType == native_machine &&
2236 info->EmulatedMachineType == IMAGE_FILE_MACHINE_AMD64)
2237 {
2238 test_notifications( module, (CROSS_PROCESS_WORK_LIST *)info->CrossProcessWorkList );
2239
2240 NtCurrentTeb()->ChpeV2CpuAreaInfo->InSyscallCallback++;
2241 test_notifications( module, (CROSS_PROCESS_WORK_LIST *)info->CrossProcessWorkList );
2242 NtCurrentTeb()->ChpeV2CpuAreaInfo->InSyscallCallback--;
2243 }
2244 skip( "arm64ec shared info not found\n" );
2245}
2246
2247
2248#else /* _WIN64 */
2249
2250static const BYTE call_func64_code[] =
2251{
2252 0x58, /* pop %eax */
2253 0x0e, /* push %cs */
2254 0x50, /* push %eax */
2255 0x6a, 0x33, /* push $0x33 */
2256 0xe8, 0x00, 0x00, 0x00, 0x00, /* call 1f */
2257 0x83, 0x04, 0x24, 0x05, /* 1: addl $0x5,(%esp) */
2258 0xcb, /* lret */
2259 /* in 64-bit mode: */
2260 0x4c, 0x87, 0xf4, /* xchg %r14,%rsp */
2261 0x55, /* push %rbp */
2262 0x48, 0x89, 0xe5, /* mov %rsp,%rbp */
2263 0x56, /* push %rsi */
2264 0x57, /* push %rdi */
2265 0x41, 0x8b, 0x4e, 0x10, /* mov 0x10(%r14),%ecx */
2266 0x41, 0x8b, 0x76, 0x14, /* mov 0x14(%r14),%esi */
2267 0x67, 0x8d, 0x04, 0xcd, 0, 0, 0, 0, /* lea 0x0(,%ecx,8),%eax */
2268 0x83, 0xf8, 0x20, /* cmp $0x20,%eax */
2269 0x7d, 0x05, /* jge 1f */
2270 0xb8, 0x20, 0x00, 0x00, 0x00, /* mov $0x20,%eax */
2271 0x48, 0x29, 0xc4, /* 1: sub %rax,%rsp */
2272 0x48, 0x83, 0xe4, 0xf0, /* and $~15,%rsp */
2273 0x48, 0x89, 0xe7, /* mov %rsp,%rdi */
2274 0xf3, 0x48, 0xa5, /* rep movsq */
2275 0x48, 0x8b, 0x0c, 0x24, /* mov (%rsp),%rcx */
2276 0x48, 0x8b, 0x54, 0x24, 0x08, /* mov 0x8(%rsp),%rdx */
2277 0x4c, 0x8b, 0x44, 0x24, 0x10, /* mov 0x10(%rsp),%r8 */
2278 0x4c, 0x8b, 0x4c, 0x24, 0x18, /* mov 0x18(%rsp),%r9 */
2279 0x41, 0xff, 0x56, 0x08, /* callq *0x8(%r14) */
2280 0x48, 0x8d, 0x65, 0xf0, /* lea -0x10(%rbp),%rsp */
2281 0x5f, /* pop %rdi */
2282 0x5e, /* pop %rsi */
2283 0x5d, /* pop %rbp */
2284 0x4c, 0x87, 0xf4, /* xchg %r14,%rsp */
2285 0xcb, /* lret */
2286};
2287
2289{
2290 NTSTATUS (WINAPI *func)( ULONG64 func64, int nb_args, ULONG64 *args ) = code_mem;
2291
2293 return func( func64, nb_args, args );
2294}
2295
2298
2299static void enum_modules64( void (*func)(ULONG64,const WCHAR *) )
2300{
2301 typedef struct
2302 {
2303 LIST_ENTRY64 InLoadOrderLinks;
2304 LIST_ENTRY64 InMemoryOrderLinks;
2305 LIST_ENTRY64 InInitializationOrderLinks;
2306 ULONG64 DllBase;
2307 ULONG64 EntryPoint;
2308 ULONG SizeOfImage;
2310 UNICODE_STRING64 BaseDllName;
2311 /* etc. */
2312 } LDR_DATA_TABLE_ENTRY64;
2313
2314 TEB64 *teb64 = (TEB64 *)NtCurrentTeb()->GdiBatchCount;
2315 PEB64 peb64;
2316 ULONG64 ptr;
2317 PEB_LDR_DATA64 ldr;
2318 LDR_DATA_TABLE_ENTRY64 entry;
2321
2323 ok( process != 0, "failed to open current process %lu\n", GetLastError() );
2324 status = pNtWow64ReadVirtualMemory64( process, teb64->Peb, &peb64, sizeof(peb64), NULL );
2325 ok( !status, "NtWow64ReadVirtualMemory64 failed %lx\n", status );
2327 ok( peb64.LdrData, "LdrData not initialized\n" );
2328 if (!peb64.LdrData) goto done;
2329 status = pNtWow64ReadVirtualMemory64( process, peb64.LdrData, &ldr, sizeof(ldr), NULL );
2330 ok( !status, "NtWow64ReadVirtualMemory64 failed %lx\n", status );
2332 for (;;)
2333 {
2334 WCHAR buffer[256];
2335 status = pNtWow64ReadVirtualMemory64( process, ptr, &entry, sizeof(entry), NULL );
2336 ok( !status, "NtWow64ReadVirtualMemory64 failed %lx\n", status );
2337 status = pNtWow64ReadVirtualMemory64( process, entry.BaseDllName.Buffer, buffer, sizeof(buffer), NULL );
2338 ok( !status, "NtWow64ReadVirtualMemory64 failed %lx\n", status );
2339 if (status) break;
2340 func( entry.DllBase, buffer );
2341 ptr = entry.InLoadOrderLinks.Flink;
2342 if (ptr == peb64.LdrData + offsetof( PEB_LDR_DATA64, InLoadOrderModuleList )) break;
2343 }
2344done:
2345 NtClose( process );
2346}
2347
2349{
2352 IMAGE_EXPORT_DIRECTORY exports;
2353 ULONG i, *names, *funcs;
2354 USHORT *ordinals;
2357 ULONG64 ret = 0;
2358 char buffer[64];
2359
2360 if (!module) return 0;
2362 ok( process != 0, "failed to open current process %lu\n", GetLastError() );
2363 status = pNtWow64ReadVirtualMemory64( process, module, &dos, sizeof(dos), NULL );
2364 ok( !status, "NtWow64ReadVirtualMemory64 failed %lx\n", status );
2365 status = pNtWow64ReadVirtualMemory64( process, module + dos.e_lfanew, &nt, sizeof(nt), NULL );
2366 ok( !status, "NtWow64ReadVirtualMemory64 failed %lx\n", status );
2368 &exports, sizeof(exports), NULL );
2369 ok( !status, "NtWow64ReadVirtualMemory64 failed %lx\n", status );
2370 names = calloc( exports.NumberOfNames, sizeof(*names) );
2371 ordinals = calloc( exports.NumberOfNames, sizeof(*ordinals) );
2372 funcs = calloc( exports.NumberOfFunctions, sizeof(*funcs) );
2373 status = pNtWow64ReadVirtualMemory64( process, module + exports.AddressOfNames,
2374 names, exports.NumberOfNames * sizeof(*names), NULL );
2375 ok( !status, "NtWow64ReadVirtualMemory64 failed %lx\n", status );
2376 status = pNtWow64ReadVirtualMemory64( process, module + exports.AddressOfNameOrdinals,
2377 ordinals, exports.NumberOfNames * sizeof(*ordinals), NULL );
2378 ok( !status, "NtWow64ReadVirtualMemory64 failed %lx\n", status );
2379 status = pNtWow64ReadVirtualMemory64( process, module + exports.AddressOfFunctions,
2380 funcs, exports.NumberOfFunctions * sizeof(*funcs), NULL );
2381 ok( !status, "NtWow64ReadVirtualMemory64 failed %lx\n", status );
2382 for (i = 0; i < exports.NumberOfNames && !ret; i++)
2383 {
2384 status = pNtWow64ReadVirtualMemory64( process, module + names[i], buffer, sizeof(buffer), NULL );
2385 ok( !status, "NtWow64ReadVirtualMemory64 failed %lx\n", status );
2386 if (!strcmp( buffer, name )) ret = module + funcs[ordinals[i]];
2387 }
2388 free( funcs );
2389 free( ordinals );
2390 free( names );
2391 NtClose( process );
2392 return ret;
2393}
2394
2395static void check_module( ULONG64 base, const WCHAR *name )
2396{
2397 if (base == (ULONG_PTR)GetModuleHandleW(0))
2398 {
2400
2402 if ((p = wcsrchr( module, '\\' ))) p++;
2403 else p = module;
2404 ok( !wcsicmp( name, p ), "wrong name %s / %s\n", debugstr_w(name), debugstr_w(module));
2405 main_module = base;
2406 return;
2407 }
2408#define CHECK_MODULE(mod) do { if (!wcsicmp( name, L"" #mod ".dll" )) { mod ## _module = base; return; } } while(0)
2411 CHECK_MODULE(wow64base);
2412 CHECK_MODULE(wow64con);
2413 CHECK_MODULE(wow64win);
2415 CHECK_MODULE(xtajit);
2416 else
2417 CHECK_MODULE(wow64cpu);
2418#undef CHECK_MODULE
2419 todo_wine_if( !wcscmp( name, L"win32u.dll" ))
2420 ok( 0, "unknown module %s %s found\n", wine_dbgstr_longlong(base), wine_dbgstr_w(name));
2421}
2422
2423static void test_modules(void)
2424{
2425 if (!is_wow64) return;
2426 if (!pNtWow64ReadVirtualMemory64) return;
2429 {
2430 ok( main_module, "main module not found\n" );
2431 ok( ntdll_module, "64-bit ntdll not found\n" );
2432 ok( wow64_module, "wow64.dll not found\n" );
2434 ok( xtajit_module, "xtajit.dll not found\n" );
2435 else
2436 ok( wow64cpu_module, "wow64cpu.dll not found\n" );
2437 ok( wow64win_module, "wow64win.dll not found\n" );
2438 }
2439}
2440
2441static void test_nt_wow64(void)
2442{
2443 const char str[] = "hello wow64";
2444 char buffer[100];
2446 ULONG64 res;
2448
2449 ok( process != 0, "failed to open current process %lu\n", GetLastError() );
2450 if (pNtWow64ReadVirtualMemory64)
2451 {
2452 status = pNtWow64ReadVirtualMemory64( process, (ULONG_PTR)str, buffer, sizeof(str), &res );
2453 ok( !status, "NtWow64ReadVirtualMemory64 failed %lx\n", status );
2454 ok( res == sizeof(str), "wrong size %s\n", wine_dbgstr_longlong(res) );
2455 ok( !strcmp( buffer, str ), "wrong data %s\n", debugstr_a(buffer) );
2456 status = pNtWow64WriteVirtualMemory64( process, (ULONG_PTR)buffer, " bye ", 5, &res );
2457 ok( !status, "NtWow64WriteVirtualMemory64 failed %lx\n", status );
2458 ok( res == 5, "wrong size %s\n", wine_dbgstr_longlong(res) );
2459 ok( !strcmp( buffer, " bye wow64" ), "wrong data %s\n", debugstr_a(buffer) );
2460 /* current process pseudo-handle is broken on some Windows versions */
2461 status = pNtWow64ReadVirtualMemory64( GetCurrentProcess(), (ULONG_PTR)str, buffer, sizeof(str), &res );
2463 "NtWow64ReadVirtualMemory64 failed %lx\n", status );
2464 status = pNtWow64WriteVirtualMemory64( GetCurrentProcess(), (ULONG_PTR)buffer, " bye ", 5, &res );
2466 "NtWow64WriteVirtualMemory64 failed %lx\n", status );
2467 }
2468 else win_skip( "NtWow64ReadVirtualMemory64 not supported\n" );
2469
2470 if (pNtWow64AllocateVirtualMemory64)
2471 {
2472 ULONG64 ptr = 0;
2473 ULONG64 size = 0x2345;
2474
2475 status = pNtWow64AllocateVirtualMemory64( process, &ptr, 0, &size,
2477 ok( !status, "NtWow64AllocateVirtualMemory64 failed %lx\n", status );
2478 ok( ptr, "ptr not set\n" );
2479 ok( size == 0x3000, "size not set %s\n", wine_dbgstr_longlong(size) );
2480 ptr += 0x1000;
2481 status = pNtWow64AllocateVirtualMemory64( process, &ptr, 0, &size,
2483 ok( status == STATUS_CONFLICTING_ADDRESSES, "NtWow64AllocateVirtualMemory64 failed %lx\n", status );
2484 ptr = 0;
2485 size = 0;
2486 status = pNtWow64AllocateVirtualMemory64( process, &ptr, 0, &size,
2489 "NtWow64AllocateVirtualMemory64 failed %lx\n", status );
2490 size = 0x1000;
2491 status = pNtWow64AllocateVirtualMemory64( process, &ptr, 22, &size,
2494 "NtWow64AllocateVirtualMemory64 failed %lx\n", status );
2495 status = pNtWow64AllocateVirtualMemory64( process, &ptr, 33, &size,
2498 "NtWow64AllocateVirtualMemory64 failed %lx\n", status );
2499 status = pNtWow64AllocateVirtualMemory64( process, &ptr, 0x3fffffff, &size,
2502 ok( !status, "NtWow64AllocateVirtualMemory64 failed %lx\n", status );
2503 ok( ptr < 0x40000000, "got wrong ptr %s\n", wine_dbgstr_longlong(ptr) );
2504 if (!status && pNtWow64WriteVirtualMemory64)
2505 {
2506 status = pNtWow64WriteVirtualMemory64( process, ptr, str, sizeof(str), &res );
2507 ok( !status, "NtWow64WriteVirtualMemory64 failed %lx\n", status );
2508 ok( res == sizeof(str), "wrong size %s\n", wine_dbgstr_longlong(res) );
2509 ok( !strcmp( (char *)(ULONG_PTR)ptr, str ), "wrong data %s\n",
2510 debugstr_a((char *)(ULONG_PTR)ptr) );
2511 ptr = 0;
2512 status = pNtWow64AllocateVirtualMemory64( process, &ptr, 0, &size,
2514 ok( !status, "NtWow64AllocateVirtualMemory64 failed %lx\n", status );
2515 status = pNtWow64WriteVirtualMemory64( process, ptr, str, sizeof(str), &res );
2516 todo_wine
2518 "NtWow64WriteVirtualMemory64 failed %lx\n", status );
2519 todo_wine
2520 ok( !res || broken(res) /* win10 1709 */, "wrong size %s\n", wine_dbgstr_longlong(res) );
2521 }
2522 ptr = 0x9876543210ull;
2523 status = pNtWow64AllocateVirtualMemory64( process, &ptr, 0, &size,
2527 "NtWow64AllocateVirtualMemory64 failed %lx\n", status );
2528 if (!status) ok( ptr == 0x9876540000ull || broken(ptr == 0x76540000), /* win 8.1 */
2529 "wrong ptr %s\n", wine_dbgstr_longlong(ptr) );
2530 ptr = 0;
2531 status = pNtWow64AllocateVirtualMemory64( GetCurrentProcess(), &ptr, 0, &size,
2534 "NtWow64AllocateVirtualMemory64 failed %lx\n", status );
2535 }
2536 else win_skip( "NtWow64AllocateVirtualMemory64 not supported\n" );
2537
2538 if (pNtWow64GetNativeSystemInformation)
2539 {
2540 ULONG i, len;
2541 SYSTEM_BASIC_INFORMATION sbi, sbi2, sbi3;
2542
2543 memset( &sbi, 0xcc, sizeof(sbi) );
2544 status = pNtQuerySystemInformation( SystemBasicInformation, &sbi, sizeof(sbi), &len );
2545 ok( status == STATUS_SUCCESS, "failed %lx\n", status );
2546 ok( len == sizeof(sbi), "wrong length %ld\n", len );
2547
2548 memset( &sbi2, 0xcc, sizeof(sbi2) );
2549 status = pRtlGetNativeSystemInformation( SystemBasicInformation, &sbi2, sizeof(sbi2), &len );
2550 ok( status == STATUS_SUCCESS, "failed %lx\n", status );
2551 ok( len == sizeof(sbi2), "wrong length %ld\n", len );
2552
2553 ok( sbi.HighestUserAddress == (void *)0x7ffeffff, "wrong limit %p\n", sbi.HighestUserAddress);
2555 ok( sbi2.HighestUserAddress == (is_wow64 ? (void *)0xfffeffff : (void *)0x7ffeffff),
2556 "wrong limit %p\n", sbi.HighestUserAddress);
2557
2558 memset( &sbi3, 0xcc, sizeof(sbi3) );
2559 status = pNtWow64GetNativeSystemInformation( SystemBasicInformation, &sbi3, sizeof(sbi3), &len );
2560 ok( status == STATUS_SUCCESS, "failed %lx\n", status );
2561 ok( len == sizeof(sbi3), "wrong length %ld\n", len );
2562 ok( !memcmp( &sbi2, &sbi3, offsetof(SYSTEM_BASIC_INFORMATION,NumberOfProcessors)+1 ),
2563 "info is different\n" );
2564
2565 memset( &sbi3, 0xcc, sizeof(sbi3) );
2566 status = pNtWow64GetNativeSystemInformation( SystemEmulationBasicInformation, &sbi3, sizeof(sbi3), &len );
2567 ok( status == STATUS_SUCCESS, "failed %lx\n", status );
2568 ok( len == sizeof(sbi3), "wrong length %ld\n", len );
2569 ok( !memcmp( &sbi, &sbi3, offsetof(SYSTEM_BASIC_INFORMATION,NumberOfProcessors)+1 ),
2570 "info is different\n" );
2571
2572 for (i = 0; i < 256; i++)
2573 {
2574 NTSTATUS expect = pNtQuerySystemInformation( i, NULL, 0, &len );
2575 status = pNtWow64GetNativeSystemInformation( i, NULL, 0, &len );
2576 switch (i)
2577 {
2580 broken(status == STATUS_NOT_IMPLEMENTED) /* vista */, "%lu: %lx / %lx\n", i, status, expect );
2581 break;
2586 ok( status == expect, "%lu: %lx / %lx\n", i, status, expect );
2587 break;
2588 default:
2589 if (is_wow64) /* only a few info classes are supported on Wow64 */
2591 broken(status == STATUS_NOT_IMPLEMENTED), /* vista */
2592 "%lu: %lx\n", i, status );
2593 else
2594 ok( status == expect, "%lu: %lx / %lx\n", i, status, expect );
2595 break;
2596 }
2597 }
2598 }
2599 else win_skip( "NtWow64GetNativeSystemInformation not supported\n" );
2600
2601 if (pNtWow64IsProcessorFeaturePresent)
2602 {
2603 ULONG i;
2604
2605 for (i = 0; i < 64; i++)
2606 ok( pNtWow64IsProcessorFeaturePresent( i ) == IsProcessorFeaturePresent( i ),
2607 "mismatch %lu wow64 returned %lx\n", i, pNtWow64IsProcessorFeaturePresent( i ));
2608
2610 {
2612
2613 ok( user_shared_data->ProcessorFeatures[PF_ARM_V8_INSTRUCTIONS_AVAILABLE], "no ARM_V8\n" );
2614 ok( user_shared_data->ProcessorFeatures[PF_MMX_INSTRUCTIONS_AVAILABLE], "no MMX\n" );
2615 ok( !pNtWow64IsProcessorFeaturePresent( PF_ARM_V8_INSTRUCTIONS_AVAILABLE ), "ARM_V8 present\n" );
2616 ok( pNtWow64IsProcessorFeaturePresent( PF_MMX_INSTRUCTIONS_AVAILABLE ), "MMX not present\n" );
2617 }
2618 }
2619 else win_skip( "NtWow64IsProcessorFeaturePresent not supported\n" );
2620
2621 if (pNtWow64QueryInformationProcess64)
2622 {
2625 ULONG expected_peb;
2626 ULONG class;
2627
2628 for (class = 0; class <= MaxProcessInfoClass; class++)
2629 {
2630 winetest_push_context( "Process information class %lu", class );
2631
2632 switch (class)
2633 {
2636 ok( !status, "NtQueryInformationProcess returned 0x%08lx\n", status );
2637
2638 status = pNtWow64QueryInformationProcess64( GetCurrentProcess(), ProcessBasicInformation, &pbi64, sizeof(pbi64), NULL );
2639 ok( !status, "NtWow64QueryInformationProcess64 returned 0x%08lx\n", status );
2640
2641 expected_peb = (ULONG)pbi32.PebBaseAddress;
2642 if (is_wow64) expected_peb -= 0x1000;
2643
2644 ok( pbi64.ExitStatus == pbi32.ExitStatus,
2645 "expected %lu got %lu\n", pbi32.ExitStatus, pbi64.ExitStatus );
2646 ok( pbi64.PebBaseAddress == expected_peb ||
2647 /* The 64-bit PEB is usually, but not always, 4096 bytes below the 32-bit PEB */
2648 broken( is_wow64 && llabs( (INT64)pbi64.PebBaseAddress - (INT64)expected_peb ) < 0x10000 ),
2649 "expected 0x%lx got 0x%I64x\n", expected_peb, pbi64.PebBaseAddress );
2650 ok( pbi64.AffinityMask == pbi32.AffinityMask,
2651 "expected 0x%Ix got 0x%I64x\n", pbi32.AffinityMask, pbi64.AffinityMask );
2652 ok( pbi64.UniqueProcessId == pbi32.UniqueProcessId,
2653 "expected %Ix got %I64x\n", pbi32.UniqueProcessId, pbi64.UniqueProcessId );
2655 "expected %Ix got %I64x\n", pbi32.UniqueProcessId, pbi64.UniqueProcessId );
2656 break;
2657 default:
2658 status = pNtWow64QueryInformationProcess64( GetCurrentProcess(), class, NULL, 0, NULL );
2659 ok( status == STATUS_NOT_IMPLEMENTED, "NtWow64QueryInformationProcess64 returned 0x%08lx\n", status );
2660 }
2661
2663 }
2664 }
2665 else win_skip( "NtWow64QueryInformationProcess64 not supported\n" );
2666
2667 NtClose( process );
2668}
2669
2670static void test_init_block(void)
2671{
2672 HMODULE ntdll = GetModuleHandleA( "ntdll.dll" );
2673 ULONG i, size = 0, *init_block;
2674 ULONG64 ptr64, *block64;
2675 void *ptr;
2676
2677 if (!is_wow64) return;
2678 if ((ptr = GetProcAddress( ntdll, "LdrSystemDllInitBlock" )))
2679 {
2680 init_block = ptr;
2681 trace( "got init block %08lx\n", init_block[0] );
2682#define CHECK_FUNC(val,func) \
2683 ok( (val) == (ULONG_PTR)GetProcAddress( ntdll, func ), \
2684 "got %p for %s %p\n", (void *)(ULONG_PTR)(val), func, GetProcAddress( ntdll, func ))
2685 switch (init_block[0])
2686 {
2687 case 0x44: /* vistau64 */
2688 CHECK_FUNC( init_block[1], "LdrInitializeThunk" );
2689 CHECK_FUNC( init_block[2], "KiUserExceptionDispatcher" );
2690 CHECK_FUNC( init_block[3], "KiUserApcDispatcher" );
2691 CHECK_FUNC( init_block[4], "KiUserCallbackDispatcher" );
2692 CHECK_FUNC( init_block[5], "LdrHotPatchRoutine" );
2693 CHECK_FUNC( init_block[6], "ExpInterlockedPopEntrySListFault" );
2694 CHECK_FUNC( init_block[7], "ExpInterlockedPopEntrySListResume" );
2695 CHECK_FUNC( init_block[8], "ExpInterlockedPopEntrySListEnd" );
2696 CHECK_FUNC( init_block[9], "RtlUserThreadStart" );
2697 CHECK_FUNC( init_block[10], "RtlpQueryProcessDebugInformationRemote" );
2698 CHECK_FUNC( init_block[11], "EtwpNotificationThread" );
2699 ok( init_block[12] == (ULONG_PTR)ntdll, "got %p for ntdll %p\n",
2700 (void *)(ULONG_PTR)init_block[12], ntdll );
2701 size = 13 * sizeof(*init_block);
2702 break;
2703 case 0x50: /* win7 */
2704 CHECK_FUNC( init_block[4], "LdrInitializeThunk" );
2705 CHECK_FUNC( init_block[5], "KiUserExceptionDispatcher" );
2706 CHECK_FUNC( init_block[6], "KiUserApcDispatcher" );
2707 CHECK_FUNC( init_block[7], "KiUserCallbackDispatcher" );
2708 CHECK_FUNC( init_block[8], "LdrHotPatchRoutine" );
2709 CHECK_FUNC( init_block[9], "ExpInterlockedPopEntrySListFault" );
2710 CHECK_FUNC( init_block[10], "ExpInterlockedPopEntrySListResume" );
2711 CHECK_FUNC( init_block[11], "ExpInterlockedPopEntrySListEnd" );
2712 CHECK_FUNC( init_block[12], "RtlUserThreadStart" );
2713 CHECK_FUNC( init_block[13], "RtlpQueryProcessDebugInformationRemote" );
2714 CHECK_FUNC( init_block[14], "EtwpNotificationThread" );
2715 ok( init_block[15] == (ULONG_PTR)ntdll, "got %p for ntdll %p\n",
2716 (void *)(ULONG_PTR)init_block[15], ntdll );
2717 /* CHECK_FUNC( init_block[16], "LdrSystemDllInitBlock" ); not always present */
2718 size = 17 * sizeof(*init_block);
2719 break;
2720 case 0x70: /* win8 */
2721 CHECK_FUNC( init_block[4], "LdrInitializeThunk" );
2722 CHECK_FUNC( init_block[5], "KiUserExceptionDispatcher" );
2723 CHECK_FUNC( init_block[6], "KiUserApcDispatcher" );
2724 CHECK_FUNC( init_block[7], "KiUserCallbackDispatcher" );
2725 CHECK_FUNC( init_block[8], "ExpInterlockedPopEntrySListFault" );
2726 CHECK_FUNC( init_block[9], "ExpInterlockedPopEntrySListResume" );
2727 CHECK_FUNC( init_block[10], "ExpInterlockedPopEntrySListEnd" );
2728 CHECK_FUNC( init_block[11], "RtlUserThreadStart" );
2729 CHECK_FUNC( init_block[12], "RtlpQueryProcessDebugInformationRemote" );
2730 ok( init_block[13] == (ULONG_PTR)ntdll, "got %p for ntdll %p\n",
2731 (void *)(ULONG_PTR)init_block[13], ntdll );
2732 CHECK_FUNC( init_block[14], "LdrSystemDllInitBlock" );
2733 size = 15 * sizeof(*init_block);
2734 break;
2735 case 0x80: /* win10 1507 */
2736 CHECK_FUNC( init_block[4], "LdrInitializeThunk" );
2737 CHECK_FUNC( init_block[5], "KiUserExceptionDispatcher" );
2738 CHECK_FUNC( init_block[6], "KiUserApcDispatcher" );
2739 CHECK_FUNC( init_block[7], "KiUserCallbackDispatcher" );
2740 if (GetProcAddress( ntdll, "ExpInterlockedPopEntrySListFault" ))
2741 {
2742 CHECK_FUNC( init_block[8], "ExpInterlockedPopEntrySListFault" );
2743 CHECK_FUNC( init_block[9], "ExpInterlockedPopEntrySListResume" );
2744 CHECK_FUNC( init_block[10], "ExpInterlockedPopEntrySListEnd" );
2745 CHECK_FUNC( init_block[11], "RtlUserThreadStart" );
2746 CHECK_FUNC( init_block[12], "RtlpQueryProcessDebugInformationRemote" );
2747 ok( init_block[13] == (ULONG_PTR)ntdll, "got %p for ntdll %p\n",
2748 (void *)(ULONG_PTR)init_block[13], ntdll );
2749 CHECK_FUNC( init_block[14], "LdrSystemDllInitBlock" );
2750 size = 15 * sizeof(*init_block);
2751 }
2752 else /* win10 1607 */
2753 {
2754 CHECK_FUNC( init_block[8], "RtlUserThreadStart" );
2755 CHECK_FUNC( init_block[9], "RtlpQueryProcessDebugInformationRemote" );
2756 ok( init_block[10] == (ULONG_PTR)ntdll, "got %p for ntdll %p\n",
2757 (void *)(ULONG_PTR)init_block[10], ntdll );
2758 CHECK_FUNC( init_block[11], "LdrSystemDllInitBlock" );
2759 size = 12 * sizeof(*init_block);
2760 }
2761 break;
2762 case 0xe0: /* win10 1809 */
2763 case 0xf0: /* win10 2004 */
2764 case 0x128: /* win11 24h2 */
2765 block64 = ptr;
2766 CHECK_FUNC( block64[3], "LdrInitializeThunk" );
2767 CHECK_FUNC( block64[4], "KiUserExceptionDispatcher" );
2768 CHECK_FUNC( block64[5], "KiUserApcDispatcher" );
2769 CHECK_FUNC( block64[6], "KiUserCallbackDispatcher" );
2770 CHECK_FUNC( block64[7], "RtlUserThreadStart" );
2771 CHECK_FUNC( block64[8], "RtlpQueryProcessDebugInformationRemote" );
2773 ok( block64[9] == (ULONG_PTR)ntdll, "got %p for ntdll %p\n",
2774 (void *)(ULONG_PTR)block64[9], ntdll );
2775 CHECK_FUNC( block64[10], "LdrSystemDllInitBlock" );
2776 CHECK_FUNC( block64[11], "RtlpFreezeTimeBias" );
2777 size = 12 * sizeof(*block64);
2778 break;
2779 default:
2780 ok( 0, "unknown init block %08lx\n", init_block[0] );
2781 for (i = 0; i < init_block[0] / sizeof(ULONG); i++) trace("%04lx: %08lx\n", i, init_block[i]);
2782 break;
2783 }
2784#undef CHECK_FUNC
2785
2786 if (size && (ptr64 = get_proc_address64( ntdll_module, "LdrSystemDllInitBlock" )))
2787 {
2788 DWORD buffer[64];
2790 NTSTATUS status = pNtWow64ReadVirtualMemory64( process, ptr64, buffer, size, NULL );
2791 ok( !status, "NtWow64ReadVirtualMemory64 failed %lx\n", status );
2792 ok( !memcmp( buffer, init_block, size ), "wrong 64-bit init block\n" );
2793 NtClose( process );
2794 }
2795 }
2796 else todo_wine win_skip( "LdrSystemDllInitBlock not supported\n" );
2797}
2798
2799
2801{
2803 WOW64INFO *info;
2804 DWORD i;
2805
2806 if (!xtajit_module)
2807 {
2808 skip( "xtajit.dll not loaded\n" );
2809 return;
2810 }
2812 {
2813 skip( "xtajit.dll loaded above 4G\n" );
2814 return;
2815 }
2816
2817 for (i = 0x400; i < 0x800; i += sizeof(ULONG))
2818 {
2819 info = (WOW64INFO *)((char *)NtCurrentTeb()->Peb + i);
2820 if (info->NativeMachineType == native_machine &&
2821 info->EmulatedMachineType == IMAGE_FILE_MACHINE_I386)
2822 {
2823 if (info->CrossProcessWorkList >> 32)
2824 skip( "cross-process work list above 4G (%I64x)\n", info->CrossProcessWorkList );
2825 else
2826 test_notifications( module, ULongToPtr( info->CrossProcessWorkList ));
2827 return;
2828 }
2829 }
2830 skip( "WOW64INFO not found\n" );
2831}
2832
2833
2835{
2836 HANDLE client = arg;
2837 DWORD size;
2838 BOOL ret;
2839
2840 Sleep(100);
2841
2842 ret = WriteFile( client, "data", sizeof("data"), &size, NULL );
2843 ok( ret == TRUE, "got error %lu\n", GetLastError() );
2844
2845 return 0;
2846}
2847
2848
2849static void test_iosb(void)
2850{
2851 static const char pipe_name[] = "\\\\.\\pipe\\wow64iosbnamedpipe";
2854 ULONG64 read_func, flush_func;
2855 IO_STATUS_BLOCK iosb32;
2856 char buffer[6];
2857 DWORD size;
2858 BOOL ret;
2859 struct
2860 {
2861 union
2862 {
2864 ULONG64 Pointer;
2865 };
2867 } iosb64;
2868 ULONG64 args[] = { 0, 0, 0, 0, (ULONG_PTR)&iosb64, (ULONG_PTR)buffer, sizeof(buffer), 0, 0 };
2869 ULONG64 flush_args[] = { 0, (ULONG_PTR)&iosb64 };
2870
2871 if (!is_wow64) return;
2872 if (!code_mem) return;
2873 if (!ntdll_module) return;
2874 read_func = get_proc_address64( ntdll_module, "NtReadFile" );
2875 flush_func = get_proc_address64( ntdll_module, "NtFlushBuffersFile" );
2876
2877 /* async calls set iosb32 but not iosb64 */
2878
2881 4, 1024, 1024, 1000, NULL );
2882 ok( server != INVALID_HANDLE_VALUE, "CreateNamedPipe failed: %lu\n", GetLastError() );
2883
2886 ok( client != INVALID_HANDLE_VALUE, "CreateFile failed: %lu\n", GetLastError() );
2887
2888 memset( buffer, 0xcc, sizeof(buffer) );
2889 memset( &iosb32, 0x55, sizeof(iosb32) );
2890 iosb64.Pointer = PtrToUlong( &iosb32 );
2891 iosb64.Information = 0xdeadbeef;
2892
2893 args[0] = (LONG_PTR)server;
2894 status = call_func64( read_func, ARRAY_SIZE(args), args );
2895 ok( status == STATUS_PENDING, "NtReadFile returned %lx\n", status );
2896 ok( iosb32.Status == 0x55555555, "status changed to %lx\n", iosb32.Status );
2897 ok( iosb64.Pointer == PtrToUlong(&iosb32), "pointer changed to %I64x\n", iosb64.Pointer );
2898 ok( iosb64.Information == 0xdeadbeef, "info changed to %Ix\n", (ULONG_PTR)iosb64.Information );
2899
2900 ret = WriteFile( client, "data", sizeof("data"), &size, NULL );
2901 ok( ret == TRUE, "got error %lu\n", GetLastError() );
2902
2903 ok( iosb32.Status == 0, "Wrong iostatus %lx\n", iosb32.Status );
2904 ok( iosb32.Information == sizeof("data"), "Wrong information %Ix\n", iosb32.Information );
2905 ok( iosb64.Pointer == PtrToUlong(&iosb32), "pointer changed to %I64x\n", iosb64.Pointer );
2906 ok( iosb64.Information == 0xdeadbeef, "info changed to %Ix\n", (ULONG_PTR)iosb64.Information );
2907 ok( !memcmp( buffer, "data", iosb32.Information ),
2908 "got wrong data %s\n", debugstr_an(buffer, iosb32.Information) );
2909
2910 memset( buffer, 0xcc, sizeof(buffer) );
2911 memset( &iosb32, 0x55, sizeof(iosb32) );
2912 iosb64.Pointer = PtrToUlong( &iosb32 );
2913 iosb64.Information = 0xdeadbeef;
2914
2915 ret = WriteFile( client, "data", sizeof("data"), &size, NULL );
2916 ok( ret == TRUE, "got error %lu\n", GetLastError() );
2917
2918 status = call_func64( read_func, ARRAY_SIZE(args), args );
2919 ok( status == STATUS_SUCCESS, "NtReadFile returned %lx\n", status );
2920 ok( iosb32.Status == STATUS_SUCCESS, "status changed to %lx\n", iosb32.Status );
2921 ok( iosb32.Information == sizeof("data"), "info changed to %Ix\n", iosb32.Information );
2922 ok( iosb64.Pointer == PtrToUlong(&iosb32), "pointer changed to %I64x\n", iosb64.Pointer );
2923 ok( iosb64.Information == 0xdeadbeef, "info changed to %Ix\n", (ULONG_PTR)iosb64.Information );
2924 ok( !memcmp( buffer, "data", iosb32.Information ),
2925 "got wrong data %s\n", debugstr_an(buffer, iosb32.Information) );
2926
2927 /* syscalls which are always synchronous set iosb64 but not iosb32 */
2928
2929 memset( &iosb32, 0x55, sizeof(iosb32) );
2930 iosb64.Pointer = PtrToUlong( &iosb32 );
2931 iosb64.Information = 0xdeadbeef;
2932
2933 flush_args[0] = (LONG_PTR)server;
2934 status = call_func64( flush_func, ARRAY_SIZE(flush_args), flush_args );
2935 ok( status == STATUS_SUCCESS, "NtFlushBuffersFile returned %lx\n", status );
2936 ok( iosb32.Status == 0x55555555, "status changed to %lx\n", iosb32.Status );
2937 ok( iosb32.Information == 0x55555555, "info changed to %Ix\n", iosb32.Information );
2938 ok( iosb64.Pointer == STATUS_SUCCESS, "pointer changed to %I64x\n", iosb64.Pointer );
2939 ok( iosb64.Information == 0, "info changed to %Ix\n", (ULONG_PTR)iosb64.Information );
2940
2943
2944 /* synchronous calls set iosb64 but not iosb32 */
2945
2948 4, 1024, 1024, 1000, NULL );
2949 ok( server != INVALID_HANDLE_VALUE, "CreateNamedPipe failed: %lu\n", GetLastError() );
2950
2953 ok( client != INVALID_HANDLE_VALUE, "CreateFile failed: %lu\n", GetLastError() );
2954
2955 ret = WriteFile( client, "data", sizeof("data"), &size, NULL );
2956 ok( ret == TRUE, "got error %lu\n", GetLastError() );
2957
2958 memset( buffer, 0xcc, sizeof(buffer) );
2959 memset( &iosb32, 0x55, sizeof(iosb32) );
2960 iosb64.Pointer = PtrToUlong( &iosb32 );
2961 iosb64.Information = 0xdeadbeef;
2962
2963 args[0] = (LONG_PTR)server;
2964 status = call_func64( read_func, ARRAY_SIZE(args), args );
2965 ok( status == STATUS_SUCCESS, "NtReadFile returned %lx\n", status );
2966 ok( iosb32.Status == 0x55555555, "status changed to %lx\n", iosb32.Status );
2967 ok( iosb32.Information == 0x55555555, "info changed to %Ix\n", iosb32.Information );
2968 ok( iosb64.Pointer == STATUS_SUCCESS, "pointer changed to %I64x\n", iosb64.Pointer );
2969 ok( iosb64.Information == sizeof("data"), "info changed to %Ix\n", (ULONG_PTR)iosb64.Information );
2970 ok( !memcmp( buffer, "data", iosb64.Information ),
2971 "got wrong data %s\n", debugstr_an(buffer, iosb64.Information) );
2972
2974
2975 memset( buffer, 0xcc, sizeof(buffer) );
2976 memset( &iosb32, 0x55, sizeof(iosb32) );
2977 iosb64.Pointer = PtrToUlong( &iosb32 );
2978 iosb64.Information = 0xdeadbeef;
2979
2980 args[0] = (LONG_PTR)server;
2981 status = call_func64( read_func, ARRAY_SIZE(args), args );
2982 ok( status == STATUS_SUCCESS, "NtReadFile returned %lx\n", status );
2983 todo_wine
2984 {
2985 ok( iosb32.Status == 0x55555555, "status changed to %lx\n", iosb32.Status );
2986 ok( iosb32.Information == 0x55555555, "info changed to %Ix\n", iosb32.Information );
2987 ok( iosb64.Pointer == STATUS_SUCCESS, "pointer changed to %I64x\n", iosb64.Pointer );
2988 ok( iosb64.Information == sizeof("data"), "info changed to %Ix\n", (ULONG_PTR)iosb64.Information );
2989 ok( !memcmp( buffer, "data", iosb64.Information ),
2990 "got wrong data %s\n", debugstr_an(buffer, iosb64.Information) );
2991 }
2992
2993 ret = WaitForSingleObject( thread, 1000 );
2994 ok(!ret, "got %d\n", ret );
2996
2997 memset( &iosb32, 0x55, sizeof(iosb32) );
2998 iosb64.Pointer = PtrToUlong( &iosb32 );
2999 iosb64.Information = 0xdeadbeef;
3000
3001 flush_args[0] = (LONG_PTR)server;
3002 status = call_func64( flush_func, ARRAY_SIZE(flush_args), flush_args );
3003 ok( status == STATUS_SUCCESS, "NtFlushBuffersFile returned %lx\n", status );
3004 ok( iosb32.Status == 0x55555555, "status changed to %lx\n", iosb32.Status );
3005 ok( iosb32.Information == 0x55555555, "info changed to %Ix\n", iosb32.Information );
3006 ok( iosb64.Pointer == STATUS_SUCCESS, "pointer changed to %I64x\n", iosb64.Pointer );
3007 ok( iosb64.Information == 0, "info changed to %Ix\n", (ULONG_PTR)iosb64.Information );
3008
3011}
3012
3013static NTSTATUS invoke_syscall( const char *name, ULONG args32[] )
3014{
3015 ULONG64 args64[] = { -1, PtrToUlong( args32 ) };
3016 ULONG64 func = get_proc_address64( wow64_module, "Wow64SystemServiceEx" );
3017 BYTE *syscall = (BYTE *)GetProcAddress( GetModuleHandleA("ntdll.dll"), name );
3018
3019 ok( syscall != NULL, "syscall %s not found\n", name );
3020 if (syscall[0] == 0xb8)
3021 args64[0] = *(DWORD *)(syscall + 1);
3022 else
3023 win_skip( "syscall thunk %s not recognized\n", name );
3024
3025 return call_func64( func, ARRAY_SIZE(args64), args64 );
3026}
3027
3028static void test_syscalls(void)
3029{
3030 ULONG64 func;
3031 ULONG args32[8];
3032 HANDLE event, event2;
3036
3037 if (!is_wow64) return;
3038 if (!code_mem) return;
3039 if (!ntdll_module) return;
3040
3041 func = get_proc_address64( wow64_module, "Wow64SystemServiceEx" );
3042 ok( func, "Wow64SystemServiceEx not found\n" );
3043
3044 event = CreateEventA( NULL, FALSE, FALSE, NULL );
3045
3047 ok( !status, "NtSetEvent failed %lx\n", status );
3048 args32[0] = HandleToLong( event );
3049 status = invoke_syscall( "NtClose", args32 );
3050 ok( !status, "syscall failed %lx\n", status );
3052 ok( status == STATUS_INVALID_HANDLE, "NtSetEvent failed %lx\n", status );
3053 status = invoke_syscall( "NtClose", args32 );
3054 ok( status == STATUS_INVALID_HANDLE, "syscall failed %lx\n", status );
3055 args32[0] = 0xdeadbeef;
3056 status = invoke_syscall( "NtClose", args32 );
3057 ok( status == STATUS_INVALID_HANDLE, "syscall failed %lx\n", status );
3058
3059 RtlInitUnicodeString( &name, L"\\BaseNamedObjects\\wow64-test");
3061 event = (HANDLE)0xdeadbeef;
3062 args32[0] = PtrToUlong(&event );
3063 args32[1] = EVENT_ALL_ACCESS;
3064 args32[2] = PtrToUlong( &attr );
3065 args32[3] = NotificationEvent;
3066 args32[4] = 0;
3067 status = invoke_syscall( "NtCreateEvent", args32 );
3068 ok( !status, "syscall failed %lx\n", status );
3070 ok( !status, "NtSetEvent failed %lx\n", status );
3071
3072 event2 = (HANDLE)0xdeadbeef;
3073 args32[0] = PtrToUlong( &event2 );
3074 status = invoke_syscall( "NtOpenEvent", args32 );
3075 ok( !status, "syscall failed %lx\n", status );
3076 status = NtSetEvent( event2, NULL );
3077 ok( !status, "NtSetEvent failed %lx\n", status );
3078 args32[0] = HandleToLong( event2 );
3079 status = invoke_syscall( "NtClose", args32 );
3080 ok( !status, "syscall failed %lx\n", status );
3081
3082 event2 = (HANDLE)0xdeadbeef;
3083 args32[0] = PtrToUlong( &event2 );
3084 status = invoke_syscall( "NtCreateEvent", args32 );
3085 ok( status == STATUS_OBJECT_NAME_EXISTS, "syscall failed %lx\n", status );
3086 status = NtSetEvent( event2, NULL );
3087 ok( !status, "NtSetEvent failed %lx\n", status );
3088 args32[0] = HandleToLong( event2 );
3089 status = invoke_syscall( "NtClose", args32 );
3090 ok( !status, "syscall failed %lx\n", status );
3091
3092 status = NtClose( event );
3093 ok( !status, "NtClose failed %lx\n", status );
3094
3095 if (pNtWow64ReadVirtualMemory64)
3096 {
3097 TEB64 *teb64 = (TEB64 *)NtCurrentTeb()->GdiBatchCount;
3098 PEB64 peb64, peb64_2;
3099 ULONG64 res, res2;
3101 ULONG args32[] = { HandleToLong( process ), (ULONG)teb64->Peb, teb64->Peb >> 32,
3102 PtrToUlong(&peb64_2), sizeof(peb64_2), 0, PtrToUlong(&res2) };
3103
3104 ok( process != 0, "failed to open current process %lu\n", GetLastError() );
3105 status = pNtWow64ReadVirtualMemory64( process, teb64->Peb, &peb64, sizeof(peb64), &res );
3106 ok( !status, "NtWow64ReadVirtualMemory64 failed %lx\n", status );
3107 status = invoke_syscall( "NtWow64ReadVirtualMemory64", args32 );
3108 ok( !status, "NtWow64ReadVirtualMemory64 failed %lx\n", status );
3109 ok( res2 == res, "wrong len %s / %s\n", wine_dbgstr_longlong(res), wine_dbgstr_longlong(res2) );
3110 ok( !memcmp( &peb64, &peb64_2, res ), "data is different\n" );
3111 NtClose( process );
3112 }
3113}
3114
3115static void test_cpu_area(void)
3116{
3117 TEB64 *teb64 = (TEB64 *)NtCurrentTeb()->GdiBatchCount;
3118 ULONG64 ptr;
3120
3121 if (!is_wow64) return;
3122 if (!code_mem) return;
3123 if (!ntdll_module) return;
3124
3125 if ((ptr = get_proc_address64( ntdll_module, "RtlWow64GetCurrentCpuArea" )))
3126 {
3127 USHORT machine = 0xdead;
3130
3132 ok( !status, "RtlWow64GetCpuAreaInfo failed %lx\n", status );
3133 ok( machine == IMAGE_FILE_MACHINE_I386, "wrong machine %x\n", machine );
3134 ok( context == teb64->TlsSlots[WOW64_TLS_CPURESERVED] + 4, "wrong context %s / %s\n",
3136 ok( !context_ex, "got context_ex %s\n", wine_dbgstr_longlong(context_ex) );
3137 args[0] = args[1] = args[2] = 0;
3139 ok( !status, "RtlWow64GetCpuAreaInfo failed %lx\n", status );
3140 }
3141 else win_skip( "RtlWow64GetCpuAreaInfo not supported\n" );
3142
3143}
3144
3146{
3147 ULONG64 ptr, hook_ptr, hook, expect, res;
3149 BYTE code[8];
3150
3151 if (!is_wow64) return;
3152 if (!code_mem) return;
3153 if (!ntdll_module) return;
3154
3155 ptr = get_proc_address64( ntdll_module, "KiUserExceptionDispatcher" );
3156 ok( ptr, "KiUserExceptionDispatcher not found\n" );
3157
3158 if (pNtWow64ReadVirtualMemory64)
3159 {
3161
3162 ok( process != 0, "failed to open current process %lu\n", GetLastError() );
3163 status = pNtWow64ReadVirtualMemory64( process, ptr, &code, sizeof(code), &res );
3164 ok( !status, "NtWow64ReadVirtualMemory64 failed %lx\n", status );
3165
3166 /* cld; mov xxx(%rip),%rax */
3167 ok( code[0] == 0xfc && code[1] == 0x48 && code[2] == 0x8b && code[3] == 0x05,
3168 "wrong opcodes %02x %02x %02x %02x\n", code[0], code[1], code[2], code[3] );
3169 hook_ptr = ptr + 8 + *(int *)(code + 4);
3170 status = pNtWow64ReadVirtualMemory64( process, hook_ptr, &hook, sizeof(hook), &res );
3171 ok( !status, "NtWow64ReadVirtualMemory64 failed %lx\n", status );
3172
3173 expect = get_proc_address64( wow64_module, "Wow64PrepareForException" );
3174 ok( hook == expect, "hook %I64x set to %I64x / %I64x\n", hook_ptr, hook, expect );
3175 NtClose( process );
3176 }
3177}
3178
3179#endif /* _WIN64 */
3180
3181static void test_arm64ec(void)
3182{
3183#ifdef __aarch64__
3185 char cmdline[MAX_PATH];
3186 char **argv;
3187
3188 trace( "restarting test as arm64ec\n" );
3189
3191 sprintf( cmdline, "%s %s", argv[0], argv[1] );
3193 {
3195 ok( ret == 0, "wait failed %lx\n", ret );
3197 ok( exit_code == 0xbeef, "wrong exit code %lx\n", exit_code );
3200 }
3201 else skip( "could not start arm64ec process: %lu\n", GetLastError() );
3202#endif
3203}
3204
3206{
3207 init();
3208#if !defined (__REACTOS__) || (DLL_EXPORT_VERSION >= 0x600)
3210#endif
3211 test_peb_teb();
3214#ifdef _WIN64
3215 test_xtajit64();
3216 test_cross_process_work_list();
3217#else
3218 test_nt_wow64();
3219 test_modules();
3221 test_iosb();
3222 test_syscalls();
3223#endif
3225 test_cpu_area();
3227 test_arm64ec();
3228}
NTSTATUS NTAPI NtUnmapViewOfSection(IN HANDLE ProcessHandle, IN PVOID BaseAddress)
Definition: section.c:3485
NTSTATUS NTAPI NtMapViewOfSection(IN HANDLE SectionHandle, IN HANDLE ProcessHandle, IN OUT PVOID *BaseAddress, IN ULONG_PTR ZeroBits, IN SIZE_T CommitSize, IN OUT PLARGE_INTEGER SectionOffset OPTIONAL, IN OUT PSIZE_T ViewSize, IN SECTION_INHERIT InheritDisposition, IN ULONG AllocationType, IN ULONG Protect)
Definition: section.c:3259
static struct _test_info results[8]
Definition: SetCursorPos.c:31
@ hook
Definition: SystemMenu.c:35
#define expect(EXPECTED, GOT)
Definition: SystemMenu.c:483
unsigned char BOOLEAN
Definition: actypes.h:127
COMPILER_DEPENDENT_INT64 INT64
Definition: actypes.h:132
#define trace
Definition: atltest.h:70
#define ok(value,...)
Definition: atltest.h:57
#define skip(...)
Definition: atltest.h:64
#define broken(x)
Definition: atltest.h:178
#define START_TEST(x)
Definition: atltest.h:75
#define ok_(x1, x2)
Definition: atltest.h:61
#define ALIGN(x)
Definition: avimux.c:40
LONG NTSTATUS
Definition: precomp.h:26
#define ARRAY_SIZE(A)
Definition: main.h:20
static HANDLE thread
Definition: service.c:33
#define HandleToLong(h)
Definition: basetsd.h:74
#define ULongToPtr(ul)
Definition: basetsd.h:86
@ ProcessBasicInformation
Definition: cicbase.cpp:63
@ ProcessWow64Information
Definition: cicbase.cpp:65
Definition: list.h:37
struct list * next
Definition: list.h:38
#define STATUS_INVALID_HANDLE
Definition: d3dkmdt.h:40
#define STATUS_NOT_SUPPORTED
Definition: d3dkmdt.h:48
#define STATUS_NOT_IMPLEMENTED
Definition: d3dkmdt.h:42
NTSTATUS WINAPI NtSuspendProcess(HANDLE handle)
#define free
Definition: debug_ros.c:5
#define malloc
Definition: debug_ros.c:4
PIMAGE_NT_HEADERS nt
Definition: delayimp.cpp:445
static CHAR Desktop[MAX_PATH]
Definition: dem.c:256
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:33
VOID NTAPI KiUserExceptionDispatcher(PEXCEPTION_RECORD ExceptionRecord, PCONTEXT Context)
Definition: dispatch.c:26
#define NTSTATUS
Definition: precomp.h:19
#define CloseHandle
Definition: compat.h:739
#define IMAGE_DIRECTORY_ENTRY_EXPORT
Definition: compat.h:151
#define ReadProcessMemory(a, b, c, d, e)
Definition: compat.h:758
#define IMAGE_FILE_MACHINE_ARMNT
Definition: compat.h:127
#define PAGE_READONLY
Definition: compat.h:138
#define UnmapViewOfFile
Definition: compat.h:746
#define wcsrchr
Definition: compat.h:16
#define OPEN_EXISTING
Definition: compat.h:775
#define GetProcAddress(x, y)
Definition: compat.h:753
#define INVALID_HANDLE_VALUE
Definition: compat.h:731
@ ThreadQuerySetWin32StartAddress
Definition: compat.h:944
@ ThreadBasicInformation
Definition: compat.h:935
#define CreateFileA(a, b, c, d, e, f, g)
Definition: compat.h:740
static __inline const char * debugstr_an(const char *s, int n)
Definition: compat.h:55
static __inline const char * wine_dbgstr_longlong(ULONGLONG ll)
Definition: compat.h:49
#define GetCurrentProcess()
Definition: compat.h:759
#define GENERIC_READ
Definition: compat.h:135
#define IsWow64Process
Definition: compat.h:760
#define MAX_PATH
Definition: compat.h:34
#define IMAGE_FILE_MACHINE_ARM64
Definition: compat.h:129
#define CALLBACK
Definition: compat.h:35
#define FILE_SHARE_READ
Definition: compat.h:136
#define wcsicmp
Definition: compat.h:15
static const WCHAR *const ext[]
Definition: module.c:53
BOOL WINAPI DebugActiveProcess(IN DWORD dwProcessId)
Definition: debugger.c:445
PPEB Peb
Definition: dllmain.c:27
BOOL WINAPI WriteFile(IN HANDLE hFile, IN LPCVOID lpBuffer, IN DWORD nNumberOfBytesToWrite OPTIONAL, OUT LPDWORD lpNumberOfBytesWritten, IN LPOVERLAPPED lpOverlapped OPTIONAL)
Definition: rw.c:24
BOOL WINAPI DuplicateHandle(IN HANDLE hSourceProcessHandle, IN HANDLE hSourceHandle, IN HANDLE hTargetProcessHandle, OUT LPHANDLE lpTargetHandle, IN DWORD dwDesiredAccess, IN BOOL bInheritHandle, IN DWORD dwOptions)
Definition: handle.c:149
DWORD WINAPI GetModuleFileNameW(HINSTANCE hModule, LPWSTR lpFilename, DWORD nSize)
Definition: loader.c:600
HMODULE WINAPI GetModuleHandleW(LPCWSTR lpModuleName)
Definition: loader.c:838
HMODULE WINAPI DECLSPEC_HOTPATCH GetModuleHandleA(LPCSTR lpModuleName)
Definition: loader.c:812
BOOL NTAPI WriteProcessMemory(IN HANDLE hProcess, IN LPVOID lpBaseAddress, IN LPCVOID lpBuffer, IN SIZE_T nSize, OUT SIZE_T *lpNumberOfBytesWritten)
Definition: proc.c:1906
BOOL WINAPI FlushInstructionCache(IN HANDLE hProcess, IN LPCVOID lpBaseAddress, IN SIZE_T nSize)
Definition: proc.c:1307
BOOL WINAPI GetExitCodeProcess(IN HANDLE hProcess, IN LPDWORD lpExitCode)
Definition: proc.c:1166
BOOL WINAPI TerminateProcess(IN HANDLE hProcess, IN UINT uExitCode)
Definition: proc.c:1376
HANDLE WINAPI OpenProcess(IN DWORD dwDesiredAccess, IN BOOL bInheritHandle, IN DWORD dwProcessId)
Definition: proc.c:1225
BOOL WINAPI IsProcessorFeaturePresent(IN DWORD ProcessorFeature)
Definition: sysinfo.c:169
DWORD WINAPI QueueUserAPC(IN PAPCFUNC pfnAPC, IN HANDLE hThread, IN ULONG_PTR dwData)
Definition: thread.c:959
DWORD WINAPI ResumeThread(IN HANDLE hThread)
Definition: thread.c:567
HANDLE WINAPI DECLSPEC_HOTPATCH CreateThread(IN LPSECURITY_ATTRIBUTES lpThreadAttributes, IN DWORD dwStackSize, IN LPTHREAD_START_ROUTINE lpStartAddress, IN LPVOID lpParameter, IN DWORD dwCreationFlags, OUT LPDWORD lpThreadId)
Definition: thread.c:137
BOOL WINAPI GetExitCodeThread(IN HANDLE hThread, OUT LPDWORD lpExitCode)
Definition: thread.c:541
BOOL WINAPI GetThreadContext(IN HANDLE hThread, OUT LPCONTEXT lpContext)
Definition: thread.c:501
BOOL WINAPI Wow64RevertWow64FsRedirection(IN PVOID OldValue)
Definition: utils.c:809
BOOL WINAPI Wow64DisableWow64FsRedirection(IN PVOID *OldValue)
Definition: utils.c:786
BOOL WINAPI DECLSPEC_HOTPATCH CreateProcessA(const char *app_name, char *cmd_line, SECURITY_ATTRIBUTES *process_attr, SECURITY_ATTRIBUTES *thread_attr, BOOL inherit, DWORD flags, void *env, const char *cur_dir, STARTUPINFOA *startup_info, PROCESS_INFORMATION *info)
Definition: process.c:686
void WINAPI DECLSPEC_HOTPATCH DeleteProcThreadAttributeList(struct _PROC_THREAD_ATTRIBUTE_LIST *list)
Definition: process.c:1860
BOOL WINAPI DECLSPEC_HOTPATCH UpdateProcThreadAttribute(struct _PROC_THREAD_ATTRIBUTE_LIST *list, DWORD flags, DWORD_PTR attr, void *value, SIZE_T size, void *prev_ret, SIZE_T *size_ret)
Definition: process.c:1820
BOOL WINAPI DECLSPEC_HOTPATCH InitializeProcThreadAttributeList(struct _PROC_THREAD_ATTRIBUTE_LIST *list, DWORD count, DWORD flags, SIZE_T *size)
Definition: process.c:1753
static const struct _KUSER_SHARED_DATA * user_shared_data
Definition: sync.c:43
_ACRTIMP int __cdecl wcscmp(const wchar_t *, const wchar_t *)
Definition: wcs.c:1972
_ACRTIMP int __cdecl memcmp(const void *, const void *, size_t)
Definition: string.c:2802
_ACRTIMP __int64 __cdecl llabs(__int64)
_ACRTIMP int __cdecl strcmp(const char *, const char *)
Definition: string.c:3319
return ret
Definition: mutex.c:146
#define L(x)
Definition: resources.c:13
#define ULONG_PTR
Definition: config.h:101
#define PtrToUlong(u)
Definition: config.h:107
int align(int length, int align)
Definition: dsound8.c:36
HANDLE NTAPI CreateFileMappingA(IN HANDLE hFile, IN LPSECURITY_ATTRIBUTES lpFileMappingAttributes, IN DWORD flProtect, IN DWORD dwMaximumSizeHigh, IN DWORD dwMaximumSizeLow, IN LPCSTR lpName)
Definition: filemap.c:23
unsigned short WORD
Definition: ntddk_ex.h:93
unsigned int BOOL
Definition: ntddk_ex.h:94
unsigned long DWORD
Definition: ntddk_ex.h:95
@ SystemBasicInformation
Definition: ntddk_ex.h:11
enum _SYSTEM_INFORMATION_CLASS SYSTEM_INFORMATION_CLASS
#define STATUS_ACCESS_VIOLATION
unsigned int Native
Definition: fpcontrol.c:84
_Must_inspect_result_ _In_ PLARGE_INTEGER _In_ PLARGE_INTEGER _In_ ULONG _In_ PFILE_OBJECT _In_ PVOID Process
Definition: fsrtlfuncs.h:223
Status
Definition: gdiplustypes.h:25
GLuint GLuint GLsizei count
Definition: gl.h:1545
GLeglImageOES image
Definition: gl.h:2204
GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * data
Definition: gl.h:1950
GLenum func
Definition: glext.h:6028
struct _cl_event * event
Definition: glext.h:7739
GLuint res
Definition: glext.h:9613
GLuint GLuint * names
Definition: glext.h:11545
GLuint buffer
Definition: glext.h:5915
GLsizeiptr size
Definition: glext.h:5919
GLintptr offset
Definition: glext.h:5920
GLuint GLuint GLuint GLuint arg1
Definition: glext.h:9513
GLuint GLuint GLuint GLuint GLuint GLuint GLuint GLuint GLuint GLuint arg3
Definition: glext.h:9515
GLuint GLuint GLuint GLuint GLuint GLuint GLuint arg2
Definition: glext.h:9514
GLint limit
Definition: glext.h:10326
GLenum const GLfloat * params
Definition: glext.h:5645
GLbitfield flags
Definition: glext.h:7161
GLenum const GLvoid * addr
Definition: glext.h:9621
GLenum GLenum GLenum GLenum mapping
Definition: glext.h:9031
GLfloat GLfloat p
Definition: glext.h:8902
GLenum GLsizei len
Definition: glext.h:6722
GLuint id
Definition: glext.h:5910
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean flag
Definition: glfuncs.h:52
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint GLint GLint j
Definition: glfuncs.h:250
#define NtCurrentTeb
uint32_t entry
Definition: isohybrid.c:63
#define EVENT_ALL_ACCESS
Definition: isotest.c:82
#define debugstr_a
Definition: kernel32.h:31
#define debugstr_w
Definition: kernel32.h:32
#define wine_dbgstr_w
Definition: kernel32.h:34
_In_ PCWSTR FullDllName
Definition: ldrtypes.h:264
if(dx< 0)
Definition: linetemp.h:194
#define win_skip
Definition: minitest.h:67
#define todo_wine_if(is_todo)
Definition: minitest.h:81
void __cdecl void __cdecl void __cdecl void __cdecl void __cdecl void winetest_pop_context(void)
void __cdecl void __cdecl void __cdecl void __cdecl void __cdecl winetest_push_context(const char *fmt,...) __WINE_PRINTF_ATTR(1
Definition: test.h:537
#define todo_wine
Definition: minitest.h:80
#define memcpy(s1, s2, n)
Definition: mkisofs.h:878
struct task_struct * current
Definition: linux.c:32
#define FILE_FLAG_OVERLAPPED
Definition: disk.h:46
#define FILE_FLAG_NO_BUFFERING
Definition: disk.h:45
unsigned __int64 ULONG64
Definition: imports.h:198
static PVOID ptr
Definition: dispmode.c:27
static struct test_info tests[]
#define sprintf
Definition: sprintf.c:45
#define expect2(expected1, expected2, got1, got2)
Definition: listview.c:50
static HMODULE ntdll
Definition: debugger.c:59
static PROCESS_INFORMATION pi
Definition: debugger.c:2303
IMAGE_DOS_HEADER dos
Definition: module.c:67
static HANDLE process
Definition: process.c:78
static UINT exit_code
Definition: process.c:80
static SYSTEM_INFO si
Definition: virtual.c:39
static const char machine[]
Definition: profile.c:104
static ULONG CONTEXT_EX ** context_ex
Definition: exception.c:71
static BOOL is_arm64ec
Definition: exception.c:53
static void * pKiUserExceptionDispatcher
Definition: exception.c:109
static HANDLE PIO_APC_ROUTINE PVOID PIO_STATUS_BLOCK io
Definition: file.c:72
#define InitializeObjectAttributes(p, n, a, r, s)
Definition: reg.c:115
static SYSTEM_BASIC_INFORMATION sbi
Definition: virtual.c:53
static void test_notifications(void)
Definition: txtsrv.c:1226
INTERNETFEATURELIST feature
Definition: misc.c:1719
#define min(a, b)
Definition: monoChain.cc:55
#define argv
Definition: mplay32.c:18
unsigned int UINT
Definition: ndis.h:50
@ SystemSupportedProcessorArchitectures
Definition: extypes.h:414
@ SystemEmulationBasicInformation
Definition: extypes.h:279
@ SystemEmulationProcessorInformation
Definition: extypes.h:280
@ SystemNativeBasicInformation
Definition: extypes.h:336
#define KernelMode
Definition: asm.h:38
#define UserMode
Definition: asm.h:39
#define PROCESSOR_ARCHITECTURE_AMD64
Definition: ketypes.h:114
#define SEC_IMAGE
Definition: mmtypes.h:97
HANDLE WINAPI CreateNamedPipeA(LPCSTR lpName, DWORD dwOpenMode, DWORD dwPipeMode, DWORD nMaxInstances, DWORD nOutBufferSize, DWORD nInBufferSize, DWORD nDefaultTimeOut, LPSECURITY_ATTRIBUTES lpSecurityAttributes)
Definition: npipe.c:220
#define MEM_DECOMMIT
Definition: nt_native.h:1318
#define PAGE_READWRITE
Definition: nt_native.h:1307
#define PAGE_EXECUTE_READ
Definition: nt_native.h:1310
NTSTATUS NtTerminateThread(IN HANDLE ThreadHandle OPTIONAL, IN NTSTATUS ExitStatus)
Definition: kill.c:1287
#define PROCESS_ALL_ACCESS
Definition: nt_native.h:1327
NTSYSAPI VOID NTAPI RtlInitUnicodeString(PUNICODE_STRING DestinationString, PCWSTR SourceString)
NTSTATUS NTAPI NtTerminateProcess(HANDLE ProcessHandle, LONG ExitStatus)
@ ViewShare
Definition: nt_native.h:1281
NTSTATUS NTAPI NtClose(IN HANDLE Handle)
Definition: obhandle.c:3402
#define PAGE_EXECUTE_WRITECOPY
Definition: nt_native.h:1312
#define MEM_RESERVE
Definition: nt_native.h:1317
#define MEM_RELEASE
Definition: nt_native.h:1319
#define GENERIC_WRITE
Definition: nt_native.h:90
#define MEM_COMMIT
Definition: nt_native.h:1316
#define GENERIC_EXECUTE
Definition: nt_native.h:91
#define PAGE_EXECUTE_READWRITE
Definition: nt_native.h:1311
@ NotificationEvent
#define IMAGE_FILE_MACHINE_THUMB
Definition: ntimage.h:35
#define IMAGE_FILE_MACHINE_ARM
Definition: ntimage.h:18
#define IMAGE_FILE_MACHINE_AMD64
Definition: ntimage.h:17
NTSTATUS NTAPI NtSetEvent(IN HANDLE EventHandle, OUT PLONG PreviousState OPTIONAL)
Definition: event.c:463
PVOID NTAPI RtlFindExportedRoutineByName(_In_ PVOID ImageBase, _In_ PCSTR ExportName)
Finds the address of a given named exported routine in a loaded image. Note that this function does n...
Definition: sysldr.c:401
NTSTATUS NTAPI NtFreeVirtualMemory(IN HANDLE ProcessHandle, IN PVOID *UBaseAddress, IN PSIZE_T URegionSize, IN ULONG FreeType)
Definition: virtual.c:5192
NTSTATUS NTAPI NtWriteVirtualMemory(IN HANDLE ProcessHandle, IN PVOID BaseAddress, IN PVOID Buffer, IN SIZE_T NumberOfBytesToWrite, OUT PSIZE_T NumberOfBytesWritten OPTIONAL)
Definition: virtual.c:2895
NTSTATUS NTAPI NtProtectVirtualMemory(IN HANDLE ProcessHandle, IN OUT PVOID *UnsafeBaseAddress, IN OUT SIZE_T *UnsafeNumberOfBytesToProtect, IN ULONG NewAccessProtection, OUT PULONG UnsafeOldAccessProtection)
Definition: virtual.c:3076
NTSTATUS NTAPI NtAllocateVirtualMemory(IN HANDLE ProcessHandle, IN OUT PVOID *UBaseAddress, IN ULONG_PTR ZeroBits, IN OUT PSIZE_T URegionSize, IN ULONG AllocationType, IN ULONG Protect)
Definition: virtual.c:4457
NTSTATUS NTAPI NtFlushInstructionCache(_In_ HANDLE ProcessHandle, _In_opt_ PVOID BaseAddress, _In_ SIZE_T FlushSize)
Definition: virtual.c:3009
NTSTATUS NTAPI NtQueryInformationThread(_In_ HANDLE ThreadHandle, _In_ THREADINFOCLASS ThreadInformationClass, _Out_writes_bytes_to_opt_(ThreadInformationLength, *ReturnLength) PVOID ThreadInformation, _In_ ULONG ThreadInformationLength, _Out_opt_ PULONG ReturnLength)
Definition: query.c:2985
NTSTATUS NTAPI NtQueryInformationProcess(_In_ HANDLE ProcessHandle, _In_ PROCESSINFOCLASS ProcessInformationClass, _Out_writes_bytes_to_opt_(ProcessInformationLength, *ReturnLength) PVOID ProcessInformation, _In_ ULONG ProcessInformationLength, _Out_opt_ PULONG ReturnLength)
Definition: query.c:211
#define STATUS_IMAGE_MACHINE_TYPE_MISMATCH
Definition: ntstatus.h:203
#define STATUS_MEMORY_NOT_ALLOCATED
Definition: ntstatus.h:490
#define STATUS_NOT_MAPPED_VIEW
Definition: ntstatus.h:355
#define STATUS_OBJECT_NAME_EXISTS
Definition: ntstatus.h:189
#define STATUS_INVALID_PARAMETER_4
Definition: ntstatus.h:572
#define STATUS_CONFLICTING_ADDRESSES
Definition: ntstatus.h:354
#define STATUS_INVALID_PAGE_PROTECTION
Definition: ntstatus.h:399
#define STATUS_NO_LDT
Definition: ntstatus.h:609
#define STATUS_INVALID_INFO_CLASS
Definition: ntstatus.h:333
#define STATUS_INVALID_PARAMETER_3
Definition: ntstatus.h:571
#define STATUS_IMAGE_NOT_AT_BASE
Definition: ntstatus.h:192
#define STATUS_PARTIAL_COPY
Definition: ntstatus.h:273
#define IMAGE_FILE_MACHINE_I386
Definition: pedump.c:174
short WCHAR
Definition: pedump.c:58
#define BOOLEAN
Definition: pedump.c:73
long LONG
Definition: pedump.c:60
unsigned short USHORT
Definition: pedump.c:61
#define IMAGE_FILE_MACHINE_R3000
Definition: pedump.c:175
static BOOL wow64
Definition: psapi_main.c:44
#define OBJ_OPENIF
Definition: winternl.h:229
__asm__(".p2align 4, 0x90\n" ".seh_proc __seh2_global_filter_func\n" "__seh2_global_filter_func:\n" "\tsub %rbp, %rax\n" "\tpush %rbp\n" "\t.seh_pushreg %rbp\n" "\tpush %rbx\n" "\t.seh_pushreg %rbx\n" "\tpush %rdi\n" "\t.seh_pushreg %rdi\n" "\tpush %rsi\n" "\t.seh_pushreg %rsi\n" "\tpush %r12\n" "\t.seh_pushreg %r12\n" "\tpush %r13\n" "\t.seh_pushreg %r13\n" "\tpush %r14\n" "\t.seh_pushreg %r14\n" "\tpush %r15\n" "\t.seh_pushreg %r15\n" "\tsub $40, %rsp\n" "\t.seh_stackalloc 40\n" "\t.seh_endprologue\n" "\tsub %rax, %rdx\n" "\tmov %rdx, %rbp\n" "\tjmp *%r8\n" "__seh2_global_filter_func_exit:\n" "\t.p2align 4\n" "\tadd $40, %rsp\n" "\tpop %r15\n" "\tpop %r14\n" "\tpop %r13\n" "\tpop %r12\n" "\tpop %rsi\n" "\tpop %rdi\n" "\tpop %rbx\n" "\tpop %rbp\n" "\tret\n" "\t.seh_endproc")
static unsigned __int64 next
Definition: rand_nt.c:6
#define calloc
Definition: rosglue.h:14
#define list
Definition: rosglue.h:35
const WCHAR * str
#define offsetof(TYPE, MEMBER)
int winetest_get_mainargs(char ***pargv)
int flush
Definition: zlib.h:309
static struct __wine_debug_functions funcs
Definition: debug.c:48
#define memset(x, y, z)
Definition: compat.h:39
#define args
Definition: format.c:66
static FILE * client
Definition: client.c:37
#define STATUS_SUCCESS
Definition: shellext.h:65
#define STATUS_BUFFER_TOO_SMALL
Definition: shellext.h:69
NTSTATUS NTAPI NtReadFile(HANDLE FileHandle, HANDLE Event, PIO_APC_ROUTINE ApcRoutine, PVOID ApcContext, PIO_STATUS_BLOCK IoStatusBlock, PVOID Buffer, ULONG Length, PLARGE_INTEGER ByteOffset, PULONG Key)
NTSYSAPI NTSTATUS NTAPI NtQuerySystemInformation(IN SYSTEM_INFORMATION_CLASS SystemInfoClass, OUT PVOID SystemInfoBuffer, IN ULONG SystemInfoBufferSize, OUT PULONG BytesReturned OPTIONAL)
TCHAR * cmdline
Definition: stretchblt.cpp:32
Definition: winternl.h:391
BOOLEAN InSyscallCallback
Definition: winternl.h:437
ULONG64 UniqueThread
Definition: pstypes.h:774
ULONG64 UniqueProcess
Definition: pstypes.h:773
DWORD AddressOfNameOrdinals
Definition: compat.h:167
IMAGE_OPTIONAL_HEADER32 OptionalHeader
Definition: ntddk_ex.h:184
IMAGE_FILE_HEADER FileHeader
Definition: ntddk_ex.h:183
IMAGE_DATA_DIRECTORY DataDirectory[IMAGE_NUMBEROF_DIRECTORY_ENTRIES]
Definition: ntddk_ex.h:178
ULONG64 Flink
Definition: winternl.h:757
ULONG64 ExceptionList
Definition: winternl.h:726
ULONG64 Self
Definition: winternl.h:732
struct _NT_TIB * Self
Definition: compat.h:720
struct _EXCEPTION_REGISTRATION_RECORD * ExceptionList
Definition: compat.h:711
ULONG ProcessParameters
Definition: winternl.h:938
BOOLEAN BeingDebugged
Definition: winternl.h:926
ULONG OSPlatformId
Definition: winternl.h:1093
ULONG64 OemCodePageData
Definition: winternl.h:1074
ULONG64 LdrData
Definition: winternl.h:1047
ULONG64 AnsiCodePageData
Definition: winternl.h:1073
ULONG OSBuildNumber
Definition: winternl.h:1092
ULONG64 UnicodeCaseTableData
Definition: winternl.h:1075
ULONG64 ImageBaseAddress
Definition: winternl.h:1046
LIST_ENTRY64 InLoadOrderModuleList
Definition: winternl.h:914
PVOID ImageBaseAddress
Definition: ntddk_ex.h:245
PRTL_USER_PROCESS_PARAMETERS ProcessParameters
Definition: btrfs_drv.h:1913
PVOID AnsiCodePageData
Definition: ntddk_ex.h:264
BYTE BeingDebugged
Definition: btrfs_drv.h:1909
ULONG OSBuildNumber
Definition: ntddk_ex.h:302
PVOID OemCodePageData
Definition: ntddk_ex.h:265
ULONG OSPlatformId
Definition: ntddk_ex.h:303
PVOID UnicodeCaseTableData
Definition: ntddk_ex.h:266
ULONG_PTR InheritedFromUniqueProcessId
Definition: pstypes.h:362
ULONG Peb
Definition: winternl.h:1153
ULONG64 TlsSlots[64]
Definition: winternl.h:1299
LONG WowTebOffset
Definition: winternl.h:1344
UNICODE_STRING64 StaticUnicodeString
Definition: winternl.h:1296
WCHAR StaticUnicodeBuffer[261]
Definition: winternl.h:1297
ULONG GdiBatchCount
Definition: winternl.h:1311
NT_TIB64 Tib
Definition: winternl.h:1249
ULONG64 Peb
Definition: winternl.h:1254
CLIENT_ID64 ClientId
Definition: winternl.h:1251
Definition: compat.h:836
LONG WowTebOffset
Definition: winternl.h:701
PVOID Peb
Definition: compat.h:842
ULONG GdiBatchCount
Definition: compat.h:887
NT_TIB Tib
Definition: compat.h:837
ULONG64 Buffer
Definition: winternl.h:773
Definition: match.c:390
ULONGLONG unknown
Definition: wow64.c:102
ULONG Wow64ExecuteFlags
Definition: wow64.c:97
USHORT EmulatedMachineType
Definition: wow64.c:99
USHORT NativeMachineType
Definition: wow64.c:98
ULONGLONG CrossProcessWorkList
Definition: wow64.c:101
ULONGLONG SectionHandle
Definition: wow64.c:100
Definition: cookie.c:202
Definition: inflate.c:139
Definition: http.c:7252
ULONG64 args[6]
Definition: wow64.c:1508
Definition: fci.c:127
Definition: parser.c:49
Definition: name.c:39
Definition: parser.c:56
Definition: ps.c:97
DWORD WINAPI SleepEx(IN DWORD dwMilliseconds, IN BOOL bAlertable)
Definition: synch.c:738
DWORD WINAPI WaitForSingleObject(IN HANDLE hHandle, IN DWORD dwMilliseconds)
Definition: synch.c:82
VOID WINAPI DECLSPEC_HOTPATCH Sleep(IN DWORD dwMilliseconds)
Definition: synch.c:726
HANDLE WINAPI DECLSPEC_HOTPATCH CreateEventA(IN LPSECURITY_ATTRIBUTES lpEventAttributes OPTIONAL, IN BOOL bManualReset, IN BOOL bInitialState, IN LPCSTR lpName OPTIONAL)
Definition: synch.c:573
#define STATUS_PENDING
Definition: telnetd.h:14
#define LONG_PTR
Definition: treelist.c:79
void init_block(deflate_state *s)
Definition: trees.c:407
ULONG_PTR SIZE_T
Definition: typedefs.h:80
uint64_t ULONGLONG
Definition: typedefs.h:67
uint32_t ULONG_PTR
Definition: typedefs.h:65
HANDLE HMODULE
Definition: typedefs.h:77
uint32_t ULONG
Definition: typedefs.h:59
#define STATUS_INVALID_PARAMETER
Definition: udferr_usr.h:135
#define STATUS_UNSUCCESSFUL
Definition: udferr_usr.h:132
#define STATUS_INFO_LENGTH_MISMATCH
Definition: udferr_usr.h:133
static rfbScreenInfoPtr server
Definition: vnc.c:74
_In_ WDFREQUEST _In_ NTSTATUS _In_ ULONG_PTR Information
Definition: wdfrequest.h:1049
LPVOID NTAPI VirtualAlloc(IN LPVOID lpAddress, IN SIZE_T dwSize, IN DWORD flAllocationType, IN DWORD flProtect)
Definition: virtmem.c:65
BOOL NTAPI VirtualProtect(IN LPVOID lpAddress, IN SIZE_T dwSize, IN DWORD flNewProtect, OUT PDWORD lpflOldProtect)
Definition: virtmem.c:135
LPVOID NTAPI VirtualAllocEx(IN HANDLE hProcess, IN LPVOID lpAddress, IN SIZE_T dwSize, IN DWORD flAllocationType, IN DWORD flProtect)
Definition: virtmem.c:23
BOOL NTAPI VirtualProtectEx(IN HANDLE hProcess, IN LPVOID lpAddress, IN SIZE_T dwSize, IN DWORD flNewProtect, OUT PDWORD lpflOldProtect)
Definition: virtmem.c:153
BOOL NTAPI VirtualFree(IN LPVOID lpAddress, IN SIZE_T dwSize, IN DWORD dwFreeType)
Definition: virtmem.c:119
BOOL NTAPI VirtualFreeEx(IN HANDLE hProcess, IN LPVOID lpAddress, IN SIZE_T dwSize, IN DWORD dwFreeType)
Definition: virtmem.c:83
DWORD WINAPI GetLastError(void)
Definition: except.c:1042
HANDLE WINAPI GetCurrentThread(void)
Definition: proc.c:1146
#define PIPE_ACCESS_DUPLEX
Definition: winbase.h:166
DWORD WINAPI GetCurrentThreadId(void)
Definition: thread.c:459
DWORD WINAPI GetCurrentProcessId(void)
Definition: proc.c:1156
#define PIPE_WAIT
Definition: winbase.h:173
#define CREATE_SUSPENDED
Definition: winbase.h:182
#define PIPE_READMODE_MESSAGE
Definition: winbase.h:172
#define PROC_THREAD_ATTRIBUTE_MACHINE_TYPE
Definition: winbase.h:1157
#define EXTENDED_STARTUPINFO_PRESENT
Definition: winbase.h:204
#define PIPE_TYPE_MESSAGE
Definition: winbase.h:170
void * arg
Definition: msvc.h:10
#define WINAPI
Definition: msvc.h:6
#define WOW64_TLS_CPURESERVED
Definition: winternl.h:1362
NTSYSAPI NTSTATUS WINAPI RtlWow64GetProcessMachines(HANDLE, USHORT *, USHORT *)
NTSYSAPI NTSTATUS WINAPI NtQuerySystemInformationEx(SYSTEM_INFORMATION_CLASS, void *, ULONG, void *, ULONG, ULONG *)
NTSYSAPI NTSTATUS WINAPI NtWow64AllocateVirtualMemory64(HANDLE, ULONG64 *, ULONG64, ULONG64 *, ULONG, ULONG)
@ CrossProcessPreVirtualProtect
Definition: winternl.h:423
@ CrossProcessFlushCacheHeavy
Definition: winternl.h:426
@ CrossProcessPreVirtualFree
Definition: winternl.h:421
@ CrossProcessPostVirtualFree
Definition: winternl.h:422
@ CrossProcessPreVirtualAlloc
Definition: winternl.h:419
@ CrossProcessFlushCache
Definition: winternl.h:425
@ CrossProcessPostVirtualAlloc
Definition: winternl.h:420
@ CrossProcessPostVirtualProtect
Definition: winternl.h:424
@ CrossProcessMemoryWrite
Definition: winternl.h:427
#define CROSS_PROCESS_LIST_ENTRY(list, pos)
Definition: winternl.h:431
NTSYSAPI NTSTATUS WINAPI NtWow64WriteVirtualMemory64(HANDLE, ULONG64, const void *, ULONG64, ULONG64 *)
NTSYSAPI NTSTATUS WINAPI NtMapViewOfSectionEx(HANDLE, HANDLE, PVOID *, const LARGE_INTEGER *, SIZE_T *, ULONG, ULONG, MEM_EXTENDED_PARAMETER *, ULONG)
NTSYSAPI USHORT WINAPI RtlWow64GetCurrentMachine(void)
NTSYSAPI NTSTATUS WINAPI RtlGetNativeSystemInformation(SYSTEM_INFORMATION_CLASS, void *, ULONG, ULONG *)
NTSYSAPI NTSTATUS WINAPI RtlWow64GetSharedInfoProcess(HANDLE, BOOLEAN *, WOW64INFO *)
#define WOW64_CPUFLAGS_SOFTWARE
Definition: winternl.h:4424
@ MaxProcessInfoClass
Definition: winternl.h:1994
@ ProcessImageInformation
Definition: winternl.h:1919
#define CROSS_PROCESS_LIST_FLUSH
Definition: winternl.h:430
NTSYSAPI NTSTATUS WINAPI NtWow64ReadVirtualMemory64(HANDLE, ULONG64, void *, ULONG64, ULONG64 *)
@ SystemCpuInformation
Definition: winternl.h:2014
#define WOW64_CPUFLAGS_MSFT64
Definition: winternl.h:4423
NTSYSAPI NTSTATUS WINAPI NtWow64GetNativeSystemInformation(SYSTEM_INFORMATION_CLASS, void *, ULONG, ULONG *)
NTSYSAPI NTSTATUS WINAPI NtWow64IsProcessorFeaturePresent(UINT)
NTSYSAPI NTSTATUS WINAPI RtlWow64IsWowGuestMachineSupported(USHORT, BOOLEAN *)
NTSYSAPI NTSTATUS WINAPI NtWow64QueryInformationProcess64(HANDLE, PROCESSINFOCLASS, void *, ULONG, ULONG *)
#define CONTEXT_I386_SEGMENTS
Definition: winnt.h:11
#define CONTEXT_I386_CONTROL
Definition: winnt.h:9
MEM_EXTENDED_PARAMETER
Definition: winnt_old.h:1265
#define PROCESSOR_ARCHITECTURE_ARM64
Definition: winnt_old.h:503
@ MemExtendedParameterImageMachine
Definition: winnt_old.h:1238
DWORD WINAPI WaitForInputIdle(_In_ HANDLE, _In_ DWORD)
static CROSS_PROCESS_WORK_ENTRY * pop_from_free_list(CROSS_PROCESS_WORK_HDR *list)
Definition: wow64.c:461
static BYTE old_code[sizeof(hook_code)]
Definition: wow64.c:1569
static NTSTATUS invoke_syscall(const char *name, ULONG args32[])
Definition: wow64.c:3013
static ULONG64 ntdll_module
Definition: wow64.c:2296
static ULONG64 wow64base_module
Definition: wow64.c:2296
static void test_init_block(void)
Definition: wow64.c:2670
static BOOL create_process_machine(char *cmdline, DWORD flags, USHORT machine, PROCESS_INFORMATION *pi)
Definition: wow64.c:198
static NTSTATUS call_func64(ULONG64 func64, int nb_args, ULONG64 *args)
Definition: wow64.c:2288
static void init(void)
Definition: wow64.c:112
static void test_modules(void)
Definition: wow64.c:2423
static BOOL is_machine_32bit(USHORT machine)
Definition: wow64.c:106
static void test_syscalls(void)
Definition: wow64.c:3028
static void test_arm64ec(void)
Definition: wow64.c:3181
static void test_memory_notifications(void)
Definition: wow64.c:2800
static void test_iosb(void)
Definition: wow64.c:2849
static DWORD WINAPI iosb_delayed_write_thread(void *arg)
Definition: wow64.c:2834
static WORD WORD *static BOOLEAN WOW64INFO *static WOW64_CONTEXT *static BOOLEAN *static HANDLE
Definition: wow64.c:53
static void * code_mem
Definition: wow64.c:76
static void test_exception_dispatcher(void)
Definition: wow64.c:3145
static void test_query_architectures(void)
Definition: wow64.c:317
#define CHECK_STR(name)
static ULONG64 wow64cpu_module
Definition: wow64.c:2297
static void check_module(ULONG64 base, const WCHAR *name)
Definition: wow64.c:2395
static ULONG64 xtajit_module
Definition: wow64.c:2297
#define GET_ENTRY(info, size, ret)
static CROSS_PROCESS_WORK_ENTRY * expect_cross_work_entry_(CROSS_PROCESS_WORK_LIST *list, CROSS_PROCESS_WORK_ENTRY *entry, UINT id, void *addr, SIZE_T size, UINT arg0, UINT arg1, UINT arg2, UINT arg3, int line)
Definition: wow64.c:511
static BOOL is_wow64
Definition: wow64.c:74
static ULONG64 get_proc_address64(ULONG64 module, const char *name)
Definition: wow64.c:2348
static DWORD hook_code[]
Definition: wow64.c:1481
static PROCESSINFOCLASS
Definition: wow64.c:68
static const BYTE call_func64_code[]
Definition: wow64.c:2250
static BOOL old_wow64
Definition: wow64.c:75
static void test_cross_process_notifications(HANDLE process, ULONG_PTR section, ULONG_PTR ptr)
Definition: wow64.c:536
static void CALLBACK dummy_apc(ULONG_PTR arg)
Definition: wow64.c:1501
static void test_process_architecture(HANDLE process, USHORT expect_machine, USHORT expect_native)
Definition: wow64.c:216
static USHORT current_machine
Definition: wow64.c:91
static void ULONG
Definition: wow64.c:43
static void request_cross_process_flush(CROSS_PROCESS_WORK_HDR *list)
Definition: wow64.c:500
static void push_onto_free_list(CROSS_PROCESS_WORK_HDR *list, CROSS_PROCESS_WORK_ENTRY *entry)
Definition: wow64.c:440
static void test_peb_teb(void)
Definition: wow64.c:910
static void ULONG *static void void ULONG *static void ULONG *static HANDLE void **static void *WINAPI * pRtlFindExportedRoutineByName(HMODULE, const char *)
static ULONG64 wow64_module
Definition: wow64.c:2296
static USHORT native_machine
Definition: wow64.c:92
static void test_wow64_shared_info(HANDLE process)
Definition: wow64.c:824
static void add_work_item(CROSS_PROCESS_WORK_LIST *list, UINT id, ULONG64 addr, ULONG64 size, UINT arg0, UINT arg1, UINT arg2, UINT arg3)
Definition: wow64.c:1541
#define CHECK_FUNC(val, func)
static void test_nt_wow64(void)
Definition: wow64.c:2441
#define GET_PROC(func)
#define CHECK_MODULE(mod)
static ULONG64 ULONG64
Definition: wow64.c:65
#define expect_cross_work_entry(list, entry, id, addr, size, arg0, arg1, arg2, arg3)
Definition: wow64.c:509
static void enum_modules64(void(*func)(ULONG64, const WCHAR *))
Definition: wow64.c:2299
static void expect_notifications_(ULONG64 *results, UINT count, const struct expected_notification *expect, BOOL syscall, int line)
Definition: wow64.c:1519
static void * hook_notification_function(HMODULE module, const char *win32_name, const char *win64_name)
Definition: wow64.c:1571
static ULONG64 wow64con_module
Definition: wow64.c:2296
static void test_cpu_area(void)
Definition: wow64.c:3115
static ULONG64 main_module
Definition: wow64.c:2296
static const DWORD log_params_code[]
Definition: wow64.c:1488
static void test_image_mappings(void)
Definition: wow64.c:1334
#define expect_notifications(results, count, expect, syscall)
Definition: wow64.c:1517
static ULONG64 wow64win_module
Definition: wow64.c:2297
static void push_onto_work_list(CROSS_PROCESS_WORK_HDR *list, CROSS_PROCESS_WORK_ENTRY *entry)
Definition: wow64.c:450
static void reset_results(ULONG64 *results)
Definition: wow64.c:1511
static void process_work_items(void)
Definition: wow64.c:1556
static CROSS_PROCESS_WORK_ENTRY * pop_from_work_list(CROSS_PROCESS_WORK_HDR *list)
Definition: wow64.c:476
static void test_amd64_shared_info(HANDLE process)
Definition: wow64.c:871
static void ULONG *static void ULONG64 *static const void ULONG64 *static BOOL is_win64
Definition: wow64.c:73
static void test_selectors(void)
Definition: wow64.c:1186
static void test_process_machine(HANDLE process, HANDLE thread, USHORT expect_machine, USHORT expect_image)
Definition: wow64.c:265
#define PF_SSE4_2_INSTRUCTIONS_AVAILABLE
Definition: ketypes.h:213
#define PF_MMX_INSTRUCTIONS_AVAILABLE
Definition: ketypes.h:179
#define PF_XMMI64_INSTRUCTIONS_AVAILABLE
Definition: ketypes.h:186
#define PF_ARM_V8_INSTRUCTIONS_AVAILABLE
Definition: ketypes.h:205
#define PF_XMMI_INSTRUCTIONS_AVAILABLE
Definition: ketypes.h:182
#define PF_SSSE3_INSTRUCTIONS_AVAILABLE
Definition: ketypes.h:211
#define PF_COMPARE_EXCHANGE_DOUBLE
Definition: ketypes.h:178
#define PF_FASTFAIL_AVAILABLE
Definition: ketypes.h:199
#define PF_SSE3_INSTRUCTIONS_AVAILABLE
Definition: ketypes.h:189
#define PF_RDTSC_INSTRUCTION_AVAILABLE
Definition: ketypes.h:184
#define PF_NX_ENABLED
Definition: ketypes.h:188
#define PF_COMPARE_EXCHANGE128
Definition: ketypes.h:190
#define PF_SSE4_1_INSTRUCTIONS_AVAILABLE
Definition: ketypes.h:212
#define PF_RDTSCP_INSTRUCTION_AVAILABLE
Definition: ketypes.h:208
#define DUPLICATE_SAME_ACCESS
unsigned char BYTE
Definition: xxhash.c:193