2 * WoW64 syscall wrapping
4 * Copyright 2021 Alexandre Julliard
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.
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.
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
24 #define WIN32_NO_STATUS
29 #include "wine/exception.h"
30 #include "wine/unixlib.h"
32 #include "wow64_private.h"
33 #include "wine/debug.h"
35 WINE_DEFAULT_DEBUG_CHANNEL(wow
);
37 USHORT native_machine
= 0;
38 USHORT current_machine
= 0;
39 ULONG_PTR args_alignment
= 0;
40 ULONG_PTR highest_user_address
= 0x7ffeffff;
41 ULONG_PTR default_zero_bits
= 0x7fffffff;
43 typedef NTSTATUS (WINAPI
*syscall_thunk
)( UINT
*args
);
45 static const syscall_thunk syscall_thunks
[] =
47 #define SYSCALL_ENTRY(func) wow64_ ## func,
52 static const char *syscall_names
[] =
54 #define SYSCALL_ENTRY(func) #func,
59 static const SYSTEM_SERVICE_TABLE ntdll_syscall_table
=
61 (ULONG_PTR
*)syscall_thunks
,
62 (ULONG_PTR
*)syscall_names
,
63 ARRAY_SIZE(syscall_thunks
)
66 static SYSTEM_SERVICE_TABLE syscall_tables
[4];
68 /* header for Wow64AllocTemp blocks; probably not the right layout */
71 struct mem_header
*next
;
76 /* stack frame for user callbacks */
77 struct user_callback_frame
79 struct user_callback_frame
*prev_frame
;
80 struct mem_header
*temp_list
;
84 __wine_jmp_buf jmpbuf
;
87 /* stack frame for user APCs */
90 struct user_apc_frame
*prev_frame
;
95 SYSTEM_DLL_INIT_BLOCK
*pLdrSystemDllInitBlock
= NULL
;
97 /* wow64win syscall table */
98 static const SYSTEM_SERVICE_TABLE
*psdwhwin32
;
99 static HMODULE win32u_module
;
100 static WOW64INFO
*wow64info
;
102 /* cpu backend dll functions */
103 /* the function prototypes most likely differ from Windows */
104 static void * (WINAPI
*pBTCpuGetBopCode
)(void);
105 static NTSTATUS (WINAPI
*pBTCpuGetContext
)(HANDLE
,HANDLE
,void *,void *);
106 static BOOLEAN (WINAPI
*pBTCpuIsProcessorFeaturePresent
)(UINT
);
107 static void (WINAPI
*pBTCpuProcessInit
)(void);
108 static NTSTATUS (WINAPI
*pBTCpuSetContext
)(HANDLE
,HANDLE
,void *,void *);
109 static void (WINAPI
*pBTCpuThreadInit
)(void);
110 static void (WINAPI
*pBTCpuSimulate
)(void);
111 static NTSTATUS (WINAPI
*pBTCpuResetToConsistentState
)( EXCEPTION_POINTERS
* );
112 static void * (WINAPI
*p__wine_get_unix_opcode
)(void);
113 static void * (WINAPI
*pKiRaiseUserExceptionDispatcher
)(void);
114 void (WINAPI
*pBTCpuNotifyFlushInstructionCache2
)( const void *, SIZE_T
) = NULL
;
115 void (WINAPI
*pBTCpuNotifyMapViewOfSection
)( void * ) = NULL
;
116 void (WINAPI
*pBTCpuNotifyMemoryAlloc
)( void *, SIZE_T
, ULONG
, ULONG
) = NULL
;
117 void (WINAPI
*pBTCpuNotifyMemoryDirty
)( void *, SIZE_T
) = NULL
;
118 void (WINAPI
*pBTCpuNotifyMemoryFree
)( void *, SIZE_T
) = NULL
;
119 void (WINAPI
*pBTCpuNotifyMemoryProtect
)( void *, SIZE_T
, ULONG
) = NULL
;
120 void (WINAPI
*pBTCpuNotifyUnmapViewOfSection
)( void * ) = NULL
;
121 void (WINAPI
*pBTCpuUpdateProcessorInformation
)( SYSTEM_CPU_INFORMATION
* ) = NULL
;
122 void (WINAPI
*pBTCpuThreadTerm
)( HANDLE
) = NULL
;
124 void *dummy
= RtlUnwind
;
126 BOOL WINAPI
DllMain( HINSTANCE inst
, DWORD reason
, void *reserved
)
128 if (reason
== DLL_PROCESS_ATTACH
) LdrDisableThreadCalloutsForDll( inst
);
132 void __cdecl
__wine_spec_unimplemented_stub( const char *module
, const char *function
)
134 EXCEPTION_RECORD record
;
136 record
.ExceptionCode
= EXCEPTION_WINE_STUB
;
137 record
.ExceptionFlags
= EH_NONCONTINUABLE
;
138 record
.ExceptionRecord
= NULL
;
139 record
.ExceptionAddress
= __wine_spec_unimplemented_stub
;
140 record
.NumberParameters
= 2;
141 record
.ExceptionInformation
[0] = (ULONG_PTR
)module
;
142 record
.ExceptionInformation
[1] = (ULONG_PTR
)function
;
143 for (;;) RtlRaiseException( &record
);
147 static EXCEPTION_RECORD
*exception_record_32to64( const EXCEPTION_RECORD32
*rec32
)
149 EXCEPTION_RECORD
*rec
;
152 rec
= Wow64AllocateTemp( sizeof(*rec
) );
153 rec
->ExceptionCode
= rec32
->ExceptionCode
;
154 rec
->ExceptionFlags
= rec32
->ExceptionFlags
;
155 rec
->ExceptionRecord
= rec32
->ExceptionRecord
? exception_record_32to64( ULongToPtr(rec32
->ExceptionRecord
) ) : NULL
;
156 rec
->ExceptionAddress
= ULongToPtr( rec32
->ExceptionAddress
);
157 rec
->NumberParameters
= rec32
->NumberParameters
;
158 for (i
= 0; i
< EXCEPTION_MAXIMUM_PARAMETERS
; i
++)
159 rec
->ExceptionInformation
[i
] = rec32
->ExceptionInformation
[i
];
164 static void exception_record_64to32( EXCEPTION_RECORD32
*rec32
, const EXCEPTION_RECORD
*rec
)
168 rec32
->ExceptionCode
= rec
->ExceptionCode
;
169 rec32
->ExceptionFlags
= rec
->ExceptionFlags
;
170 rec32
->ExceptionRecord
= PtrToUlong( rec
->ExceptionRecord
);
171 rec32
->ExceptionAddress
= PtrToUlong( rec
->ExceptionAddress
);
172 rec32
->NumberParameters
= rec
->NumberParameters
;
173 for (i
= 0; i
< rec
->NumberParameters
; i
++)
174 rec32
->ExceptionInformation
[i
] = rec
->ExceptionInformation
[i
];
178 static NTSTATUS
get_context_return_value( void *wow_context
)
180 switch (current_machine
)
182 case IMAGE_FILE_MACHINE_I386
:
183 return ((I386_CONTEXT
*)wow_context
)->Eax
;
184 case IMAGE_FILE_MACHINE_ARMNT
:
185 return ((ARM_CONTEXT
*)wow_context
)->R0
;
191 /**********************************************************************
192 * call_user_exception_dispatcher
194 static void call_user_exception_dispatcher( EXCEPTION_RECORD32
*rec
, void *ctx32_ptr
, void *ctx64_ptr
)
196 switch (current_machine
)
198 case IMAGE_FILE_MACHINE_I386
:
202 ULONG rec_ptr
; /* first arg for KiUserExceptionDispatcher */
203 ULONG context_ptr
; /* second arg for KiUserExceptionDispatcher */
204 EXCEPTION_RECORD32 rec
;
205 I386_CONTEXT context
;
207 I386_CONTEXT
*context
, ctx
= { CONTEXT_I386_ALL
};
208 CONTEXT_EX
*context_ex
, *src_ex
= NULL
;
211 pBTCpuGetContext( GetCurrentThread(), GetCurrentProcess(), NULL
, &ctx
);
215 I386_CONTEXT
*ctx32
= ctx32_ptr
;
217 if ((ctx32
->ContextFlags
& CONTEXT_I386_XSTATE
) == CONTEXT_I386_XSTATE
)
218 src_ex
= (CONTEXT_EX
*)(ctx32
+ 1);
220 else if (native_machine
== IMAGE_FILE_MACHINE_AMD64
)
222 AMD64_CONTEXT
*ctx64
= ctx64_ptr
;
224 if ((ctx64
->ContextFlags
& CONTEXT_AMD64_FLOATING_POINT
) == CONTEXT_AMD64_FLOATING_POINT
)
225 memcpy( ctx
.ExtendedRegisters
, &ctx64
->FltSave
, sizeof(ctx
.ExtendedRegisters
) );
226 if ((ctx64
->ContextFlags
& CONTEXT_AMD64_XSTATE
) == CONTEXT_AMD64_XSTATE
)
227 src_ex
= (CONTEXT_EX
*)(ctx64
+ 1);
230 flags
= ctx
.ContextFlags
;
231 if (src_ex
) flags
|= CONTEXT_I386_XSTATE
;
232 RtlGetExtendedContextLength( flags
, &size
);
233 size
= ((size
+ 15) & ~15) + offsetof(struct stack_layout
,context
);
235 stack
= (struct stack_layout
*)(ULONG_PTR
)(ctx
.Esp
- size
);
236 stack
->rec_ptr
= PtrToUlong( &stack
->rec
);
238 RtlInitializeExtendedContext( &stack
->context
, flags
, &context_ex
);
239 context
= RtlLocateLegacyContext( context_ex
, NULL
);
241 context
->ContextFlags
= flags
;
242 /* adjust Eip for breakpoints in software emulation (hardware exceptions already adjust Rip) */
243 if (rec
->ExceptionCode
== EXCEPTION_BREAKPOINT
&& (wow64info
->CpuFlags
& WOW64_CPUFLAGS_SOFTWARE
))
245 stack
->context_ptr
= PtrToUlong( context
);
249 XSTATE
*src_xs
= (XSTATE
*)((char *)src_ex
+ src_ex
->XState
.Offset
);
250 XSTATE
*dst_xs
= (XSTATE
*)((char *)context_ex
+ context_ex
->XState
.Offset
);
252 dst_xs
->Mask
= src_xs
->Mask
& ~(ULONG64
)3;
253 dst_xs
->CompactionMask
= src_xs
->CompactionMask
;
254 if ((dst_xs
->Mask
& 4) &&
255 src_ex
->XState
.Length
>= sizeof(XSTATE
) &&
256 context_ex
->XState
.Length
>= sizeof(XSTATE
))
257 memcpy( &dst_xs
->YmmContext
, &src_xs
->YmmContext
, sizeof(dst_xs
->YmmContext
) );
260 ctx
.Esp
= PtrToUlong( stack
);
261 ctx
.Eip
= pLdrSystemDllInitBlock
->pKiUserExceptionDispatcher
;
262 ctx
.EFlags
&= ~(0x100|0x400|0x40000);
263 pBTCpuSetContext( GetCurrentThread(), GetCurrentProcess(), NULL
, &ctx
);
265 TRACE( "exception %08lx dispatcher %08lx stack %08lx eip %08lx\n",
266 rec
->ExceptionCode
, ctx
.Eip
, ctx
.Esp
, stack
->context
.Eip
);
270 case IMAGE_FILE_MACHINE_ARMNT
:
275 EXCEPTION_RECORD32 rec
;
277 ARM_CONTEXT ctx
= { CONTEXT_ARM_ALL
};
279 pBTCpuGetContext( GetCurrentThread(), GetCurrentProcess(), NULL
, &ctx
);
280 stack
= (struct stack_layout
*)(ULONG_PTR
)(ctx
.Sp
& ~3) - 1;
282 stack
->context
= ctx
;
284 ctx
.R0
= PtrToUlong( &stack
->rec
); /* first arg for KiUserExceptionDispatcher */
285 ctx
.R1
= PtrToUlong( &stack
->context
); /* second arg for KiUserExceptionDispatcher */
286 ctx
.Sp
= PtrToUlong( stack
);
287 ctx
.Pc
= pLdrSystemDllInitBlock
->pKiUserExceptionDispatcher
;
288 if (ctx
.Pc
& 1) ctx
.Cpsr
|= 0x20;
289 else ctx
.Cpsr
&= ~0x20;
290 pBTCpuSetContext( GetCurrentThread(), GetCurrentProcess(), NULL
, &ctx
);
292 TRACE( "exception %08lx dispatcher %08lx stack %08lx pc %08lx\n",
293 rec
->ExceptionCode
, ctx
.Pc
, ctx
.Sp
, stack
->context
.Sp
);
300 /**********************************************************************
301 * call_raise_user_exception_dispatcher
303 static void call_raise_user_exception_dispatcher( ULONG code
)
305 TEB32
*teb32
= (TEB32
*)((char *)NtCurrentTeb() + NtCurrentTeb()->WowTebOffset
);
307 teb32
->ExceptionCode
= code
;
309 switch (current_machine
)
311 case IMAGE_FILE_MACHINE_I386
:
313 I386_CONTEXT ctx
= { CONTEXT_I386_ALL
};
315 pBTCpuGetContext( GetCurrentThread(), GetCurrentProcess(), NULL
, &ctx
);
316 ctx
.Esp
-= sizeof(ULONG
);
317 *(ULONG
*)ULongToPtr( ctx
.Esp
) = ctx
.Eip
;
318 ctx
.Eip
= (ULONG_PTR
)pKiRaiseUserExceptionDispatcher
;
319 pBTCpuSetContext( GetCurrentThread(), GetCurrentProcess(), NULL
, &ctx
);
323 case IMAGE_FILE_MACHINE_ARMNT
:
325 ARM_CONTEXT ctx
= { CONTEXT_ARM_ALL
};
327 pBTCpuGetContext( GetCurrentThread(), GetCurrentProcess(), NULL
, &ctx
);
328 ctx
.Pc
= (ULONG_PTR
)pKiRaiseUserExceptionDispatcher
;
329 pBTCpuSetContext( GetCurrentThread(), GetCurrentProcess(), NULL
, &ctx
);
336 /* based on RtlRaiseException: call NtRaiseException with context setup to return to caller */
337 void WINAPI
raise_exception( EXCEPTION_RECORD
*rec
, CONTEXT
*context
, BOOL first_chance
) DECLSPEC_HIDDEN
;
339 __ASM_GLOBAL_FUNC( raise_exception
,
341 __ASM_SEH(".seh_stackalloc 0x28\n\t")
342 __ASM_SEH(".seh_endprologue\n\t")
343 __ASM_CFI(".cfi_adjust_cfa_offset 0x28\n\t")
344 "movq %rcx,(%rsp)\n\t"
346 "call " __ASM_NAME("RtlCaptureContext") "\n\t"
347 "leaq 0x30(%rsp),%rax\n\t" /* orig stack pointer */
348 "movq %rax,0x98(%rdx)\n\t" /* context->Rsp */
349 "movq (%rsp),%rcx\n\t" /* original first parameter */
350 "movq 0x28(%rsp),%rax\n\t" /* return address */
351 "movq %rax,0xf8(%rdx)\n\t" /* context->Rip */
352 "call " __ASM_NAME("NtRaiseException") )
353 #elif defined(__aarch64__)
354 __ASM_GLOBAL_FUNC( raise_exception
,
355 "stp x29, x30, [sp, #-32]!\n\t"
356 __ASM_SEH(".seh_save_fplr_x 32\n\t")
357 __ASM_SEH(".seh_endprologue\n\t")
358 __ASM_CFI(".cfi_def_cfa x29, 32\n\t")
359 __ASM_CFI(".cfi_offset x30, -24\n\t")
360 __ASM_CFI(".cfi_offset x29, -32\n\t")
362 "stp x0, x1, [sp, #16]\n\t"
364 "bl " __ASM_NAME("RtlCaptureContext") "\n\t"
365 "ldp x0, x1, [sp, #16]\n\t" /* orig parameters */
366 "ldp x4, x5, [sp]\n\t" /* frame pointer, return address */
367 "stp x4, x5, [x1, #0xf0]\n\t" /* context->Fp, Lr */
368 "add x4, sp, #32\n\t" /* orig stack pointer */
369 "stp x4, x5, [x1, #0x100]\n\t" /* context->Sp, Pc */
370 "bl " __ASM_NAME("NtRaiseException") )
374 /**********************************************************************
377 NTSTATUS WINAPI
wow64_NtAddAtom( UINT
*args
)
379 const WCHAR
*name
= get_ptr( &args
);
380 ULONG len
= get_ulong( &args
);
381 RTL_ATOM
*atom
= get_ptr( &args
);
383 return NtAddAtom( name
, len
, atom
);
387 /**********************************************************************
388 * wow64_NtAllocateLocallyUniqueId
390 NTSTATUS WINAPI
wow64_NtAllocateLocallyUniqueId( UINT
*args
)
392 LUID
*luid
= get_ptr( &args
);
394 return NtAllocateLocallyUniqueId( luid
);
398 /**********************************************************************
399 * wow64_NtAllocateUuids
401 NTSTATUS WINAPI
wow64_NtAllocateUuids( UINT
*args
)
403 ULARGE_INTEGER
*time
= get_ptr( &args
);
404 ULONG
*delta
= get_ptr( &args
);
405 ULONG
*sequence
= get_ptr( &args
);
406 UCHAR
*seed
= get_ptr( &args
);
408 return NtAllocateUuids( time
, delta
, sequence
, seed
);
412 /***********************************************************************
413 * wow64_NtCallbackReturn
415 NTSTATUS WINAPI
wow64_NtCallbackReturn( UINT
*args
)
417 void *ret_ptr
= get_ptr( &args
);
418 ULONG ret_len
= get_ulong( &args
);
419 NTSTATUS status
= get_ulong( &args
);
421 struct user_callback_frame
*frame
= NtCurrentTeb()->TlsSlots
[WOW64_TLS_USERCALLBACKDATA
];
423 if (!frame
) return STATUS_NO_CALLBACK_ACTIVE
;
425 *frame
->ret_ptr
= ret_ptr
;
426 *frame
->ret_len
= ret_len
;
427 frame
->status
= status
;
428 __wine_longjmp( &frame
->jmpbuf
, 1 );
432 /**********************************************************************
435 NTSTATUS WINAPI
wow64_NtClose( UINT
*args
)
437 HANDLE handle
= get_handle( &args
);
439 return NtClose( handle
);
443 /**********************************************************************
446 NTSTATUS WINAPI
wow64_NtContinue( UINT
*args
)
448 void *context
= get_ptr( &args
);
449 BOOLEAN alertable
= get_ulong( &args
);
451 NTSTATUS status
= get_context_return_value( context
);
452 struct user_apc_frame
*frame
= NtCurrentTeb()->TlsSlots
[WOW64_TLS_APCLIST
];
454 pBTCpuSetContext( GetCurrentThread(), GetCurrentProcess(), NULL
, context
);
456 while (frame
&& frame
->wow_context
!= context
) frame
= frame
->prev_frame
;
457 NtCurrentTeb()->TlsSlots
[WOW64_TLS_APCLIST
] = frame
? frame
->prev_frame
: NULL
;
458 if (frame
) NtContinue( frame
->context
, alertable
);
460 if (alertable
) NtTestAlert();
465 /**********************************************************************
468 NTSTATUS WINAPI
wow64_NtDeleteAtom( UINT
*args
)
470 RTL_ATOM atom
= get_ulong( &args
);
472 return NtDeleteAtom( atom
);
476 /**********************************************************************
479 NTSTATUS WINAPI
wow64_NtFindAtom( UINT
*args
)
481 const WCHAR
*name
= get_ptr( &args
);
482 ULONG len
= get_ulong( &args
);
483 RTL_ATOM
*atom
= get_ptr( &args
);
485 return NtFindAtom( name
, len
, atom
);
489 /**********************************************************************
490 * wow64_NtGetContextThread
492 NTSTATUS WINAPI
wow64_NtGetContextThread( UINT
*args
)
494 HANDLE handle
= get_handle( &args
);
495 WOW64_CONTEXT
*context
= get_ptr( &args
);
497 return RtlWow64GetThreadContext( handle
, context
);
501 /**********************************************************************
502 * wow64_NtGetCurrentProcessorNumber
504 NTSTATUS WINAPI
wow64_NtGetCurrentProcessorNumber( UINT
*args
)
506 return NtGetCurrentProcessorNumber();
510 /**********************************************************************
511 * wow64_NtQueryDefaultLocale
513 NTSTATUS WINAPI
wow64_NtQueryDefaultLocale( UINT
*args
)
515 BOOLEAN user
= get_ulong( &args
);
516 LCID
*lcid
= get_ptr( &args
);
518 return NtQueryDefaultLocale( user
, lcid
);
522 /**********************************************************************
523 * wow64_NtQueryDefaultUILanguage
525 NTSTATUS WINAPI
wow64_NtQueryDefaultUILanguage( UINT
*args
)
527 LANGID
*lang
= get_ptr( &args
);
529 return NtQueryDefaultUILanguage( lang
);
533 /**********************************************************************
534 * wow64_NtQueryInformationAtom
536 NTSTATUS WINAPI
wow64_NtQueryInformationAtom( UINT
*args
)
538 RTL_ATOM atom
= get_ulong( &args
);
539 ATOM_INFORMATION_CLASS
class = get_ulong( &args
);
540 void *info
= get_ptr( &args
);
541 ULONG len
= get_ulong( &args
);
542 ULONG
*retlen
= get_ptr( &args
);
544 if (class != AtomBasicInformation
) FIXME( "class %u not supported\n", class );
545 return NtQueryInformationAtom( atom
, class, info
, len
, retlen
);
549 /**********************************************************************
550 * wow64_NtQueryInstallUILanguage
552 NTSTATUS WINAPI
wow64_NtQueryInstallUILanguage( UINT
*args
)
554 LANGID
*lang
= get_ptr( &args
);
556 return NtQueryInstallUILanguage( lang
);
560 /**********************************************************************
561 * wow64_NtRaiseException
563 NTSTATUS WINAPI
wow64_NtRaiseException( UINT
*args
)
565 EXCEPTION_RECORD32
*rec32
= get_ptr( &args
);
566 void *context32
= get_ptr( &args
);
567 BOOL first_chance
= get_ulong( &args
);
569 EXCEPTION_RECORD
*rec
= exception_record_32to64( rec32
);
572 pBTCpuSetContext( GetCurrentThread(), GetCurrentProcess(), NULL
, context32
);
576 raise_exception( rec
, &context
, first_chance
);
580 call_user_exception_dispatcher( rec32
, context32
, &context
);
583 return STATUS_SUCCESS
;
587 /**********************************************************************
588 * wow64_NtSetContextThread
590 NTSTATUS WINAPI
wow64_NtSetContextThread( UINT
*args
)
592 HANDLE handle
= get_handle( &args
);
593 WOW64_CONTEXT
*context
= get_ptr( &args
);
595 return RtlWow64SetThreadContext( handle
, context
);
599 /**********************************************************************
600 * wow64_NtSetDebugFilterState
602 NTSTATUS WINAPI
wow64_NtSetDebugFilterState( UINT
*args
)
604 ULONG component_id
= get_ulong( &args
);
605 ULONG level
= get_ulong( &args
);
606 BOOLEAN state
= get_ulong( &args
);
608 return NtSetDebugFilterState( component_id
, level
, state
);
612 /**********************************************************************
613 * wow64_NtSetDefaultLocale
615 NTSTATUS WINAPI
wow64_NtSetDefaultLocale( UINT
*args
)
617 BOOLEAN user
= get_ulong( &args
);
618 LCID lcid
= get_ulong( &args
);
620 return NtSetDefaultLocale( user
, lcid
);
624 /**********************************************************************
625 * wow64_NtSetDefaultUILanguage
627 NTSTATUS WINAPI
wow64_NtSetDefaultUILanguage( UINT
*args
)
629 LANGID lang
= get_ulong( &args
);
631 return NtSetDefaultUILanguage( lang
);
635 /**********************************************************************
636 * wow64_NtWow64IsProcessorFeaturePresent
638 NTSTATUS WINAPI
wow64_NtWow64IsProcessorFeaturePresent( UINT
*args
)
640 UINT feature
= get_ulong( &args
);
642 return pBTCpuIsProcessorFeaturePresent
&& pBTCpuIsProcessorFeaturePresent( feature
);
646 /**********************************************************************
649 static DWORD
get_syscall_num( const BYTE
*syscall
)
651 WORD
*arm_syscall
= (WORD
*)((ULONG_PTR
)syscall
& ~1);
654 if (!syscall
) return id
;
655 switch (current_machine
)
657 case IMAGE_FILE_MACHINE_I386
:
658 if (syscall
[0] == 0xb8 && syscall
[5] == 0xba && syscall
[10] == 0xff && syscall
[11] == 0xd2)
659 id
= *(DWORD
*)(syscall
+ 1);
662 case IMAGE_FILE_MACHINE_ARMNT
:
663 if (*arm_syscall
== 0xb40f)
665 DWORD inst
= *(DWORD
*)(arm_syscall
+ 1);
666 id
= ((inst
<< 1) & 0x0800) + ((inst
<< 12) & 0xf000) +
667 ((inst
>> 20) & 0x0700) + ((inst
>> 16) & 0x00ff);
675 /**********************************************************************
678 static void *get_rva( const IMAGE_NT_HEADERS
*nt
, HMODULE module
, DWORD rva
,
679 IMAGE_SECTION_HEADER
**section
, BOOL image
)
681 if (image
) return (void *)((char *)module
+ rva
);
682 return RtlImageRvaToVa( nt
, module
, rva
, section
);
686 /**********************************************************************
689 static void init_syscall_table( HMODULE module
, ULONG idx
, const SYSTEM_SERVICE_TABLE
*orig_table
, BOOL image
)
691 static syscall_thunk thunks
[2048];
692 static ULONG start_pos
;
694 const IMAGE_NT_HEADERS
*nt
= RtlImageNtHeader( module
);
695 IMAGE_SECTION_HEADER
*section
= NULL
;
696 const IMAGE_EXPORT_DIRECTORY
*exports
;
697 const ULONG
*functions
, *names
;
698 const USHORT
*ordinals
;
699 ULONG id
, exp_size
, exp_pos
, wrap_pos
, max_pos
= 0;
700 const char **syscall_names
= (const char **)orig_table
->CounterTable
;
702 exports
= RtlImageDirectoryEntryToData( module
, image
, IMAGE_DIRECTORY_ENTRY_EXPORT
, &exp_size
);
703 ordinals
= get_rva( nt
, module
, exports
->AddressOfNameOrdinals
, §ion
, image
);
704 functions
= get_rva( nt
, module
, exports
->AddressOfFunctions
, §ion
, image
);
705 names
= get_rva( nt
, module
, exports
->AddressOfNames
, §ion
, image
);
707 for (exp_pos
= wrap_pos
= 0; exp_pos
< exports
->NumberOfNames
; exp_pos
++)
709 char *name
= get_rva( nt
, module
, names
[exp_pos
], §ion
, image
);
712 if (strncmp( name
, "Nt", 2 ) && strncmp( name
, "wine", 4 ) && strncmp( name
, "__wine", 6 ))
713 continue; /* not a syscall */
715 id
= get_syscall_num( get_rva( nt
, module
, functions
[ordinals
[exp_pos
]], §ion
, image
));
716 if (id
== ~0u) continue; /* not a syscall */
718 if (wrap_pos
< orig_table
->ServiceLimit
) res
= strcmp( name
, syscall_names
[wrap_pos
] );
720 if (!res
) /* got a match */
722 ULONG table_idx
= (id
>> 12) & 3, table_pos
= id
& 0xfff;
723 if (table_idx
== idx
)
725 if (start_pos
+ table_pos
< ARRAY_SIZE(thunks
))
727 thunks
[start_pos
+ table_pos
] = (syscall_thunk
)orig_table
->ServiceTable
[wrap_pos
++];
728 max_pos
= max( table_pos
, max_pos
);
730 else ERR( "invalid syscall id %04lx for %s\n", id
, name
);
732 else ERR( "wrong syscall table id %04lx for %s\n", id
, name
);
736 FIXME( "no export for syscall %s\n", syscall_names
[wrap_pos
] );
738 exp_pos
--; /* try again */
740 else FIXME( "missing wrapper for syscall %04lx %s\n", id
, name
);
743 for ( ; wrap_pos
< orig_table
->ServiceLimit
; wrap_pos
++)
744 FIXME( "no export for syscall %s\n", syscall_names
[wrap_pos
] );
746 syscall_tables
[idx
].ServiceTable
= (ULONG_PTR
*)(thunks
+ start_pos
);
747 syscall_tables
[idx
].ServiceLimit
= max_pos
+ 1;
748 start_pos
+= max_pos
+ 1;
752 /**********************************************************************
755 void init_image_mapping( HMODULE module
)
757 void **ptr
= RtlFindExportedRoutineByName( module
, "Wow64Transition" );
760 *ptr
= pBTCpuGetBopCode();
761 if (!win32u_module
&& RtlFindExportedRoutineByName( module
, "NtUserInitializeClientPfnArrays" ))
763 win32u_module
= module
;
764 init_syscall_table( win32u_module
, 1, psdwhwin32
, TRUE
);
769 /**********************************************************************
772 static HMODULE
load_32bit_module( const WCHAR
*name
, WORD machine
, BOOL image
)
775 OBJECT_ATTRIBUTES attr
;
781 HANDLE handle
, mapping
;
782 WCHAR path
[MAX_PATH
];
783 const WCHAR
*dir
= get_machine_wow64_dir( machine
);
785 swprintf( path
, MAX_PATH
, L
"%s\\%s", dir
, name
);
786 RtlInitUnicodeString( &str
, path
);
787 InitializeObjectAttributes( &attr
, &str
, OBJ_CASE_INSENSITIVE
, 0, NULL
);
789 status
= NtOpenFile( &handle
, GENERIC_READ
| SYNCHRONIZE
, &attr
, &io
,
790 FILE_SHARE_READ
| FILE_SHARE_DELETE
,
791 FILE_SYNCHRONOUS_IO_NONALERT
| FILE_NON_DIRECTORY_FILE
);
792 if (status
) return NULL
;
795 status
= NtCreateSection( &mapping
, STANDARD_RIGHTS_REQUIRED
| SECTION_QUERY
|
796 SECTION_MAP_READ
| SECTION_MAP_EXECUTE
, NULL
,
797 &size
, PAGE_EXECUTE_READ
, image
? SEC_IMAGE
: SEC_COMMIT
, handle
);
799 if (status
) return NULL
;
801 status
= NtMapViewOfSection( mapping
, NtCurrentProcess(), &ptr
, 0, 0, NULL
, &len
,
802 ViewShare
, 0, PAGE_EXECUTE_READ
);
804 if (!NT_SUCCESS( status
)) ptr
= NULL
;
809 /**********************************************************************
812 static HMODULE
load_64bit_module( const WCHAR
*name
)
817 WCHAR path
[MAX_PATH
];
818 const WCHAR
*dir
= get_machine_wow64_dir( IMAGE_FILE_MACHINE_TARGET_HOST
);
820 swprintf( path
, MAX_PATH
, L
"%s\\%s", dir
, name
);
821 RtlInitUnicodeString( &str
, path
);
822 if ((status
= LdrLoadDll( dir
, 0, &str
, &module
)))
824 ERR( "failed to load dll %lx\n", status
);
825 NtTerminateProcess( GetCurrentProcess(), status
);
831 /**********************************************************************
834 static const WCHAR
*get_cpu_dll_name(void)
836 static ULONG buffer
[32];
837 KEY_VALUE_PARTIAL_INFORMATION
*info
= (KEY_VALUE_PARTIAL_INFORMATION
*)buffer
;
838 OBJECT_ATTRIBUTES attr
;
839 UNICODE_STRING nameW
;
844 switch (current_machine
)
846 case IMAGE_FILE_MACHINE_I386
:
847 RtlInitUnicodeString( &nameW
, L
"\\Registry\\Machine\\Software\\Microsoft\\Wow64\\x86" );
848 ret
= (native_machine
== IMAGE_FILE_MACHINE_ARM64
? L
"xtajit.dll" : L
"wow64cpu.dll");
850 case IMAGE_FILE_MACHINE_ARMNT
:
851 RtlInitUnicodeString( &nameW
, L
"\\Registry\\Machine\\Software\\Microsoft\\Wow64\\arm" );
852 ret
= L
"wowarmhw.dll";
855 ERR( "unsupported machine %04x\n", current_machine
);
856 RtlExitUserProcess( 1 );
858 InitializeObjectAttributes( &attr
, &nameW
, OBJ_CASE_INSENSITIVE
, 0, NULL
);
859 if (NtOpenKey( &key
, KEY_READ
| KEY_WOW64_64KEY
, &attr
)) return ret
;
860 RtlInitUnicodeString( &nameW
, L
"" );
861 size
= sizeof(buffer
) - sizeof(WCHAR
);
862 if (!NtQueryValueKey( key
, &nameW
, KeyValuePartialInformation
, buffer
, size
, &size
) && info
->Type
== REG_SZ
)
864 ((WCHAR
*)info
->Data
)[info
->DataLength
/ sizeof(WCHAR
)] = 0;
865 ret
= (WCHAR
*)info
->Data
;
872 /**********************************************************************
875 static DWORD WINAPI
process_init( RTL_RUN_ONCE
*once
, void *param
, void **context
)
878 HMODULE module
, ntdll
;
879 UNICODE_STRING str
= RTL_CONSTANT_STRING( L
"ntdll.dll" );
880 SYSTEM_BASIC_INFORMATION info
;
882 RtlWow64GetProcessMachines( GetCurrentProcess(), ¤t_machine
, &native_machine
);
883 if (!current_machine
) current_machine
= native_machine
;
884 args_alignment
= (current_machine
== IMAGE_FILE_MACHINE_I386
) ? sizeof(ULONG
) : sizeof(ULONG64
);
885 NtQuerySystemInformation( SystemEmulationBasicInformation
, &info
, sizeof(info
), NULL
);
886 highest_user_address
= (ULONG_PTR
)info
.HighestUserAddress
;
887 default_zero_bits
= (ULONG_PTR
)info
.HighestUserAddress
| 0x7fffffff;
888 NtQueryInformationProcess( GetCurrentProcess(), ProcessWow64Information
, &peb32
, sizeof(peb32
), NULL
);
889 wow64info
= (WOW64INFO
*)(peb32
+ 1);
890 wow64info
->NativeSystemPageSize
= 0x1000;
891 wow64info
->NativeMachineType
= native_machine
;
892 wow64info
->EmulatedMachineType
= current_machine
;
893 NtCurrentTeb()->TlsSlots
[WOW64_TLS_WOW64INFO
] = wow64info
;
895 #define GET_PTR(name) p ## name = RtlFindExportedRoutineByName( module, #name )
897 LdrGetDllHandle( NULL
, 0, &str
, &module
);
898 GET_PTR( LdrSystemDllInitBlock
);
900 module
= load_64bit_module( get_cpu_dll_name() );
901 GET_PTR( BTCpuGetBopCode
);
902 GET_PTR( BTCpuGetContext
);
903 GET_PTR( BTCpuIsProcessorFeaturePresent
);
904 GET_PTR( BTCpuProcessInit
);
905 GET_PTR( BTCpuThreadInit
);
906 GET_PTR( BTCpuResetToConsistentState
);
907 GET_PTR( BTCpuSetContext
);
908 GET_PTR( BTCpuSimulate
);
909 GET_PTR( BTCpuNotifyFlushInstructionCache2
);
910 GET_PTR( BTCpuNotifyMapViewOfSection
);
911 GET_PTR( BTCpuNotifyMemoryAlloc
);
912 GET_PTR( BTCpuNotifyMemoryDirty
);
913 GET_PTR( BTCpuNotifyMemoryFree
);
914 GET_PTR( BTCpuNotifyMemoryProtect
);
915 GET_PTR( BTCpuNotifyUnmapViewOfSection
);
916 GET_PTR( BTCpuUpdateProcessorInformation
);
917 GET_PTR( BTCpuThreadTerm
);
918 GET_PTR( __wine_get_unix_opcode
);
920 module
= load_64bit_module( L
"wow64win.dll" );
921 GET_PTR( sdwhwin32
);
925 module
= (HMODULE
)(ULONG_PTR
)pLdrSystemDllInitBlock
->ntdll_handle
;
926 init_image_mapping( module
);
927 *(void **)RtlFindExportedRoutineByName( module
, "__wine_syscall_dispatcher" ) = pBTCpuGetBopCode();
928 *(void **)RtlFindExportedRoutineByName( module
, "__wine_unix_call_dispatcher" ) = p__wine_get_unix_opcode();
929 GET_PTR( KiRaiseUserExceptionDispatcher
);
931 if ((ntdll
= load_32bit_module( L
"ntdll.dll", current_machine
, FALSE
)))
933 init_syscall_table( ntdll
, 0, &ntdll_syscall_table
, FALSE
);
934 NtUnmapViewOfSection( NtCurrentProcess(), ntdll
);
936 else init_syscall_table( module
, 0, &ntdll_syscall_table
, TRUE
);
938 init_file_redirects();
945 /**********************************************************************
948 static void thread_init(void)
952 RtlWow64GetCurrentCpuArea( NULL
, &cpu_area_ctx
, NULL
);
953 NtCurrentTeb()->TlsSlots
[WOW64_TLS_WOW64INFO
] = wow64info
;
954 if (pBTCpuThreadInit
) pBTCpuThreadInit();
956 /* update initial context to jump to 32-bit LdrInitializeThunk (cf. 32-bit call_init_thunk) */
957 switch (current_machine
)
959 case IMAGE_FILE_MACHINE_I386
:
961 I386_CONTEXT
*ctx_ptr
, *ctx
= cpu_area_ctx
;
964 ctx_ptr
= (I386_CONTEXT
*)ULongToPtr( ctx
->Esp
) - 1;
967 stack
= (ULONG
*)ctx_ptr
;
971 *(--stack
) = PtrToUlong( ctx_ptr
);
972 *(--stack
) = 0xdeadbabe;
973 ctx
->Esp
= PtrToUlong( stack
);
974 ctx
->Eip
= pLdrSystemDllInitBlock
->pLdrInitializeThunk
;
975 pBTCpuSetContext( GetCurrentThread(), GetCurrentProcess(), NULL
, ctx
);
979 case IMAGE_FILE_MACHINE_ARMNT
:
981 ARM_CONTEXT
*ctx_ptr
, *ctx
= cpu_area_ctx
;
983 ctx_ptr
= (ARM_CONTEXT
*)ULongToPtr( ctx
->Sp
& ~15 ) - 1;
986 ctx
->R0
= PtrToUlong( ctx_ptr
);
987 ctx
->Sp
= PtrToUlong( ctx_ptr
);
988 ctx
->Pc
= pLdrSystemDllInitBlock
->pLdrInitializeThunk
;
989 pBTCpuSetContext( GetCurrentThread(), GetCurrentProcess(), NULL
, ctx
);
994 ERR( "not supported machine %x\n", current_machine
);
995 NtTerminateProcess( GetCurrentProcess(), STATUS_INVALID_IMAGE_FORMAT
);
1000 /**********************************************************************
1003 static void free_temp_data(void)
1005 struct mem_header
*next
, *mem
;
1007 for (mem
= NtCurrentTeb()->TlsSlots
[WOW64_TLS_TEMPLIST
]; mem
; mem
= next
)
1010 RtlFreeHeap( GetProcessHeap(), 0, mem
);
1012 NtCurrentTeb()->TlsSlots
[WOW64_TLS_TEMPLIST
] = NULL
;
1016 /**********************************************************************
1019 static LONG CALLBACK
syscall_filter( EXCEPTION_POINTERS
*ptrs
)
1021 switch (ptrs
->ExceptionRecord
->ExceptionCode
)
1023 case STATUS_INVALID_HANDLE
:
1024 call_raise_user_exception_dispatcher( ptrs
->ExceptionRecord
->ExceptionCode
);
1027 return EXCEPTION_EXECUTE_HANDLER
;
1031 /**********************************************************************
1032 * Wow64SystemServiceEx (wow64.@)
1034 NTSTATUS WINAPI
Wow64SystemServiceEx( UINT num
, UINT
*args
)
1037 UINT id
= num
& 0xfff;
1038 const SYSTEM_SERVICE_TABLE
*table
= &syscall_tables
[(num
>> 12) & 3];
1040 if (id
>= table
->ServiceLimit
|| !table
->ServiceTable
[id
])
1042 ERR( "unsupported syscall %04x\n", num
);
1043 return STATUS_INVALID_SYSTEM_SERVICE
;
1047 syscall_thunk thunk
= (syscall_thunk
)table
->ServiceTable
[id
];
1048 status
= thunk( args
);
1050 __EXCEPT( syscall_filter
)
1052 status
= GetExceptionCode();
1060 /**********************************************************************
1063 static LONG CALLBACK
simulate_filter( EXCEPTION_POINTERS
*ptrs
)
1065 Wow64PassExceptionToGuest( ptrs
);
1066 return EXCEPTION_EXECUTE_HANDLER
;
1070 /**********************************************************************
1073 static void cpu_simulate(void)
1081 __EXCEPT( simulate_filter
)
1083 /* restart simulation loop */
1090 /**********************************************************************
1091 * Wow64AllocateTemp (wow64.@)
1093 * FIXME: probably not 100% compatible.
1095 void * WINAPI
Wow64AllocateTemp( SIZE_T size
)
1097 struct mem_header
*mem
;
1099 if (!(mem
= RtlAllocateHeap( GetProcessHeap(), 0, offsetof( struct mem_header
, data
[size
] ))))
1101 mem
->next
= NtCurrentTeb()->TlsSlots
[WOW64_TLS_TEMPLIST
];
1102 NtCurrentTeb()->TlsSlots
[WOW64_TLS_TEMPLIST
] = mem
;
1107 /**********************************************************************
1108 * Wow64ApcRoutine (wow64.@)
1110 void WINAPI
Wow64ApcRoutine( ULONG_PTR arg1
, ULONG_PTR arg2
, ULONG_PTR arg3
, CONTEXT
*context
)
1112 struct user_apc_frame frame
;
1114 frame
.prev_frame
= NtCurrentTeb()->TlsSlots
[WOW64_TLS_APCLIST
];
1115 frame
.context
= context
;
1116 NtCurrentTeb()->TlsSlots
[WOW64_TLS_APCLIST
] = &frame
;
1118 /* cf. 32-bit call_user_apc_dispatcher */
1119 switch (current_machine
)
1121 case IMAGE_FILE_MACHINE_I386
:
1123 struct apc_stack_layout
1131 I386_CONTEXT context
;
1133 I386_CONTEXT ctx
= { CONTEXT_I386_FULL
};
1135 pBTCpuGetContext( GetCurrentThread(), GetCurrentProcess(), NULL
, &ctx
);
1136 stack
= (struct apc_stack_layout
*)ULongToPtr( ctx
.Esp
& ~3 ) - 1;
1137 stack
->context_ptr
= PtrToUlong( &stack
->context
);
1138 stack
->func
= arg1
>> 32;
1142 stack
->context
= ctx
;
1143 ctx
.Esp
= PtrToUlong( stack
);
1144 ctx
.Eip
= pLdrSystemDllInitBlock
->pKiUserApcDispatcher
;
1145 frame
.wow_context
= &stack
->context
;
1146 pBTCpuSetContext( GetCurrentThread(), GetCurrentProcess(), NULL
, &ctx
);
1151 case IMAGE_FILE_MACHINE_ARMNT
:
1153 struct apc_stack_layout
1157 ARM_CONTEXT context
;
1159 ARM_CONTEXT ctx
= { CONTEXT_ARM_FULL
};
1161 pBTCpuGetContext( GetCurrentThread(), GetCurrentProcess(), NULL
, &ctx
);
1162 stack
= (struct apc_stack_layout
*)ULongToPtr( ctx
.Sp
& ~15 ) - 1;
1163 stack
->func
= arg1
>> 32;
1164 stack
->context
= ctx
;
1165 ctx
.Sp
= PtrToUlong( stack
);
1166 ctx
.Pc
= pLdrSystemDllInitBlock
->pKiUserApcDispatcher
;
1167 ctx
.R0
= PtrToUlong( &stack
->context
);
1171 frame
.wow_context
= &stack
->context
;
1172 pBTCpuSetContext( GetCurrentThread(), GetCurrentProcess(), NULL
, &ctx
);
1180 /**********************************************************************
1181 * Wow64KiUserCallbackDispatcher (wow64.@)
1183 NTSTATUS WINAPI
Wow64KiUserCallbackDispatcher( ULONG id
, void *args
, ULONG len
,
1184 void **ret_ptr
, ULONG
*ret_len
)
1186 WOW64_CPURESERVED
*cpu
= NtCurrentTeb()->TlsSlots
[WOW64_TLS_CPURESERVED
];
1187 TEB32
*teb32
= (TEB32
*)((char *)NtCurrentTeb() + NtCurrentTeb()->WowTebOffset
);
1188 ULONG teb_frame
= teb32
->Tib
.ExceptionList
;
1189 struct user_callback_frame frame
;
1190 USHORT flags
= cpu
->Flags
;
1192 frame
.prev_frame
= NtCurrentTeb()->TlsSlots
[WOW64_TLS_USERCALLBACKDATA
];
1193 frame
.temp_list
= NtCurrentTeb()->TlsSlots
[WOW64_TLS_TEMPLIST
];
1194 frame
.ret_ptr
= ret_ptr
;
1195 frame
.ret_len
= ret_len
;
1197 NtCurrentTeb()->TlsSlots
[WOW64_TLS_USERCALLBACKDATA
] = &frame
;
1198 NtCurrentTeb()->TlsSlots
[WOW64_TLS_TEMPLIST
] = NULL
;
1200 /* cf. 32-bit KeUserModeCallback */
1201 switch (current_machine
)
1203 case IMAGE_FILE_MACHINE_I386
:
1205 I386_CONTEXT orig_ctx
, ctx
= { CONTEXT_I386_FULL
};
1209 pBTCpuGetContext( GetCurrentThread(), GetCurrentProcess(), NULL
, &ctx
);
1212 stack
= args_data
= ULongToPtr( (ctx
.Esp
- len
) & ~15 );
1213 memcpy( args_data
, args
, len
);
1216 *(--stack
) = PtrToUlong( args_data
);
1218 *(--stack
) = 0xdeadbabe;
1220 ctx
.Esp
= PtrToUlong( stack
);
1221 ctx
.Eip
= pLdrSystemDllInitBlock
->pKiUserCallbackDispatcher
;
1222 pBTCpuSetContext( GetCurrentThread(), GetCurrentProcess(), NULL
, &ctx
);
1224 if (!__wine_setjmpex( &frame
.jmpbuf
, NULL
))
1227 pBTCpuSetContext( GetCurrentThread(), GetCurrentProcess(), NULL
, &orig_ctx
);
1231 case IMAGE_FILE_MACHINE_ARMNT
:
1233 ARM_CONTEXT orig_ctx
, ctx
= { CONTEXT_ARM_FULL
};
1236 pBTCpuGetContext( GetCurrentThread(), GetCurrentProcess(), NULL
, &ctx
);
1239 args_data
= ULongToPtr( (ctx
.Sp
- len
) & ~15 );
1240 memcpy( args_data
, args
, len
);
1243 ctx
.R1
= PtrToUlong( args_data
);
1245 ctx
.Sp
= PtrToUlong( args_data
);
1246 ctx
.Pc
= pLdrSystemDllInitBlock
->pKiUserCallbackDispatcher
;
1247 pBTCpuSetContext( GetCurrentThread(), GetCurrentProcess(), NULL
, &ctx
);
1249 if (!__wine_setjmpex( &frame
.jmpbuf
, NULL
))
1252 pBTCpuSetContext( GetCurrentThread(), GetCurrentProcess(), NULL
, &orig_ctx
);
1257 teb32
->Tib
.ExceptionList
= teb_frame
;
1258 NtCurrentTeb()->TlsSlots
[WOW64_TLS_USERCALLBACKDATA
] = frame
.prev_frame
;
1259 NtCurrentTeb()->TlsSlots
[WOW64_TLS_TEMPLIST
] = frame
.temp_list
;
1261 return frame
.status
;
1265 /**********************************************************************
1266 * Wow64LdrpInitialize (wow64.@)
1268 void WINAPI
Wow64LdrpInitialize( CONTEXT
*context
)
1270 static RTL_RUN_ONCE init_done
;
1272 RtlRunOnceExecuteOnce( &init_done
, process_init
, NULL
, NULL
);
1278 /**********************************************************************
1279 * Wow64PrepareForException (wow64.@)
1281 void WINAPI
Wow64PrepareForException( EXCEPTION_RECORD
*rec
, CONTEXT
*context
)
1283 EXCEPTION_POINTERS ptrs
= { rec
, context
};
1285 pBTCpuResetToConsistentState( &ptrs
);
1289 /**********************************************************************
1290 * Wow64PassExceptionToGuest (wow64.@)
1292 void WINAPI
Wow64PassExceptionToGuest( EXCEPTION_POINTERS
*ptrs
)
1294 EXCEPTION_RECORD32 rec32
;
1296 exception_record_64to32( &rec32
, ptrs
->ExceptionRecord
);
1297 call_user_exception_dispatcher( &rec32
, NULL
, ptrs
->ContextRecord
);
1301 /**********************************************************************
1302 * Wow64RaiseException (wow64.@)
1304 NTSTATUS WINAPI
Wow64RaiseException( int code
, EXCEPTION_RECORD
*rec
)
1306 EXCEPTION_RECORD32 rec32
;
1308 BOOL first_chance
= TRUE
;
1315 switch (current_machine
)
1317 case IMAGE_FILE_MACHINE_I386
:
1319 EXCEPTION_RECORD int_rec
= { 0 };
1321 ctx32
.i386
.ContextFlags
= CONTEXT_I386_ALL
;
1322 pBTCpuGetContext( GetCurrentThread(), GetCurrentProcess(), NULL
, &ctx32
.i386
);
1323 if (code
== -1) break;
1324 int_rec
.ExceptionAddress
= (void *)(ULONG_PTR
)ctx32
.i386
.Eip
;
1327 case 0x00: /* division by zero */
1328 int_rec
.ExceptionCode
= EXCEPTION_INT_DIVIDE_BY_ZERO
;
1330 case 0x01: /* single-step */
1331 int_rec
.ExceptionCode
= EXCEPTION_SINGLE_STEP
;
1333 case 0x03: /* breakpoint */
1334 int_rec
.ExceptionCode
= EXCEPTION_BREAKPOINT
;
1335 int_rec
.ExceptionAddress
= (void *)(ULONG_PTR
)(ctx32
.i386
.Eip
+ 1);
1336 int_rec
.NumberParameters
= 1;
1338 case 0x04: /* overflow */
1339 int_rec
.ExceptionCode
= EXCEPTION_INT_OVERFLOW
;
1341 case 0x05: /* array bounds */
1342 int_rec
.ExceptionCode
= EXCEPTION_ARRAY_BOUNDS_EXCEEDED
;
1344 case 0x06: /* invalid opcode */
1345 int_rec
.ExceptionCode
= EXCEPTION_ILLEGAL_INSTRUCTION
;
1347 case 0x09: /* coprocessor segment overrun */
1348 int_rec
.ExceptionCode
= EXCEPTION_FLT_INVALID_OPERATION
;
1350 case 0x0c: /* stack fault */
1351 int_rec
.ExceptionCode
= EXCEPTION_STACK_OVERFLOW
;
1353 case 0x29: /* __fastfail */
1354 int_rec
.ExceptionCode
= STATUS_STACK_BUFFER_OVERRUN
;
1355 int_rec
.ExceptionFlags
= EH_NONCONTINUABLE
;
1356 int_rec
.NumberParameters
= 1;
1357 int_rec
.ExceptionInformation
[0] = ctx32
.i386
.Ecx
;
1358 first_chance
= FALSE
;
1360 case 0x2d: /* debug service */
1362 pBTCpuSetContext( GetCurrentThread(), GetCurrentProcess(), NULL
, &ctx32
.i386
);
1363 int_rec
.ExceptionCode
= EXCEPTION_BREAKPOINT
;
1364 int_rec
.ExceptionAddress
= (void *)(ULONG_PTR
)ctx32
.i386
.Eip
;
1365 int_rec
.NumberParameters
= 1;
1366 int_rec
.ExceptionInformation
[0] = ctx32
.i386
.Eax
;
1369 ctx32
.i386
.Eip
-= 2;
1370 pBTCpuSetContext( GetCurrentThread(), GetCurrentProcess(), NULL
, &ctx32
.i386
);
1371 int_rec
.ExceptionCode
= EXCEPTION_ACCESS_VIOLATION
;
1372 int_rec
.ExceptionAddress
= (void *)(ULONG_PTR
)ctx32
.i386
.Eip
;
1373 int_rec
.NumberParameters
= 2;
1374 int_rec
.ExceptionInformation
[1] = 0xffffffff;
1381 case IMAGE_FILE_MACHINE_ARMNT
:
1382 ctx32
.arm
.ContextFlags
= CONTEXT_ARM_ALL
;
1383 pBTCpuGetContext( GetCurrentThread(), GetCurrentProcess(), NULL
, &ctx32
.arm
);
1387 exception_record_64to32( &rec32
, rec
);
1390 raise_exception( rec
, &context
, first_chance
);
1394 call_user_exception_dispatcher( &rec32
, &ctx32
, NULL
);
1397 return STATUS_SUCCESS
;