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(id,name,args) wow64_ ## name,
52 static BYTE syscall_args
[ARRAY_SIZE(syscall_thunks
)] =
54 #define SYSCALL_ENTRY(id,name,args) args,
59 static SYSTEM_SERVICE_TABLE syscall_tables
[4] =
61 { (ULONG_PTR
*)syscall_thunks
, NULL
, ARRAY_SIZE(syscall_thunks
), syscall_args
}
64 /* header for Wow64AllocTemp blocks; probably not the right layout */
67 struct mem_header
*next
;
72 /* stack frame for user callbacks */
73 struct user_callback_frame
75 struct user_callback_frame
*prev_frame
;
76 struct mem_header
*temp_list
;
80 __wine_jmp_buf jmpbuf
;
83 /* stack frame for user APCs */
86 struct user_apc_frame
*prev_frame
;
91 SYSTEM_DLL_INIT_BLOCK
*pLdrSystemDllInitBlock
= NULL
;
93 static WOW64INFO
*wow64info
;
95 /* cpu backend dll functions */
96 /* the function prototypes most likely differ from Windows */
97 static void * (WINAPI
*pBTCpuGetBopCode
)(void);
98 static NTSTATUS (WINAPI
*pBTCpuGetContext
)(HANDLE
,HANDLE
,void *,void *);
99 static BOOLEAN (WINAPI
*pBTCpuIsProcessorFeaturePresent
)(UINT
);
100 static void (WINAPI
*pBTCpuProcessInit
)(void);
101 static NTSTATUS (WINAPI
*pBTCpuSetContext
)(HANDLE
,HANDLE
,void *,void *);
102 static void (WINAPI
*pBTCpuThreadInit
)(void);
103 static void (WINAPI
*pBTCpuSimulate
)(void);
104 static NTSTATUS (WINAPI
*pBTCpuResetToConsistentState
)( EXCEPTION_POINTERS
* );
105 static void * (WINAPI
*p__wine_get_unix_opcode
)(void);
106 static void * (WINAPI
*pKiRaiseUserExceptionDispatcher
)(void);
107 void (WINAPI
*pBTCpuNotifyFlushInstructionCache2
)( const void *, SIZE_T
) = NULL
;
108 void (WINAPI
*pBTCpuNotifyMapViewOfSection
)( void * ) = NULL
;
109 void (WINAPI
*pBTCpuNotifyMemoryAlloc
)( void *, SIZE_T
, ULONG
, ULONG
) = NULL
;
110 void (WINAPI
*pBTCpuNotifyMemoryDirty
)( void *, SIZE_T
) = NULL
;
111 void (WINAPI
*pBTCpuNotifyMemoryFree
)( void *, SIZE_T
, ULONG
) = NULL
;
112 void (WINAPI
*pBTCpuNotifyMemoryProtect
)( void *, SIZE_T
, ULONG
) = NULL
;
113 void (WINAPI
*pBTCpuNotifyUnmapViewOfSection
)( void * ) = NULL
;
114 void (WINAPI
*pBTCpuUpdateProcessorInformation
)( SYSTEM_CPU_INFORMATION
* ) = NULL
;
115 void (WINAPI
*pBTCpuThreadTerm
)( HANDLE
) = NULL
;
117 void *dummy
= RtlUnwind
;
119 BOOL WINAPI
DllMain( HINSTANCE inst
, DWORD reason
, void *reserved
)
121 if (reason
== DLL_PROCESS_ATTACH
) LdrDisableThreadCalloutsForDll( inst
);
125 void __cdecl
__wine_spec_unimplemented_stub( const char *module
, const char *function
)
127 EXCEPTION_RECORD record
;
129 record
.ExceptionCode
= EXCEPTION_WINE_STUB
;
130 record
.ExceptionFlags
= EH_NONCONTINUABLE
;
131 record
.ExceptionRecord
= NULL
;
132 record
.ExceptionAddress
= __wine_spec_unimplemented_stub
;
133 record
.NumberParameters
= 2;
134 record
.ExceptionInformation
[0] = (ULONG_PTR
)module
;
135 record
.ExceptionInformation
[1] = (ULONG_PTR
)function
;
136 for (;;) RtlRaiseException( &record
);
140 static EXCEPTION_RECORD
*exception_record_32to64( const EXCEPTION_RECORD32
*rec32
)
142 EXCEPTION_RECORD
*rec
;
145 rec
= Wow64AllocateTemp( sizeof(*rec
) );
146 rec
->ExceptionCode
= rec32
->ExceptionCode
;
147 rec
->ExceptionFlags
= rec32
->ExceptionFlags
;
148 rec
->ExceptionRecord
= rec32
->ExceptionRecord
? exception_record_32to64( ULongToPtr(rec32
->ExceptionRecord
) ) : NULL
;
149 rec
->ExceptionAddress
= ULongToPtr( rec32
->ExceptionAddress
);
150 rec
->NumberParameters
= rec32
->NumberParameters
;
151 for (i
= 0; i
< EXCEPTION_MAXIMUM_PARAMETERS
; i
++)
152 rec
->ExceptionInformation
[i
] = rec32
->ExceptionInformation
[i
];
157 static void exception_record_64to32( EXCEPTION_RECORD32
*rec32
, const EXCEPTION_RECORD
*rec
)
161 rec32
->ExceptionCode
= rec
->ExceptionCode
;
162 rec32
->ExceptionFlags
= rec
->ExceptionFlags
;
163 rec32
->ExceptionRecord
= PtrToUlong( rec
->ExceptionRecord
);
164 rec32
->ExceptionAddress
= PtrToUlong( rec
->ExceptionAddress
);
165 rec32
->NumberParameters
= rec
->NumberParameters
;
166 for (i
= 0; i
< rec
->NumberParameters
; i
++)
167 rec32
->ExceptionInformation
[i
] = rec
->ExceptionInformation
[i
];
171 static NTSTATUS
get_context_return_value( void *wow_context
)
173 switch (current_machine
)
175 case IMAGE_FILE_MACHINE_I386
:
176 return ((I386_CONTEXT
*)wow_context
)->Eax
;
177 case IMAGE_FILE_MACHINE_ARMNT
:
178 return ((ARM_CONTEXT
*)wow_context
)->R0
;
184 /**********************************************************************
185 * call_user_exception_dispatcher
187 static void call_user_exception_dispatcher( EXCEPTION_RECORD32
*rec
, void *ctx32_ptr
, void *ctx64_ptr
)
189 switch (current_machine
)
191 case IMAGE_FILE_MACHINE_I386
:
195 ULONG rec_ptr
; /* first arg for KiUserExceptionDispatcher */
196 ULONG context_ptr
; /* second arg for KiUserExceptionDispatcher */
197 EXCEPTION_RECORD32 rec
;
198 I386_CONTEXT context
;
200 I386_CONTEXT
*context
, ctx
= { CONTEXT_I386_ALL
};
201 CONTEXT_EX
*context_ex
, *src_ex
= NULL
;
204 pBTCpuGetContext( GetCurrentThread(), GetCurrentProcess(), NULL
, &ctx
);
208 I386_CONTEXT
*ctx32
= ctx32_ptr
;
210 if ((ctx32
->ContextFlags
& CONTEXT_I386_XSTATE
) == CONTEXT_I386_XSTATE
)
211 src_ex
= (CONTEXT_EX
*)(ctx32
+ 1);
213 else if (native_machine
== IMAGE_FILE_MACHINE_AMD64
)
215 AMD64_CONTEXT
*ctx64
= ctx64_ptr
;
217 if ((ctx64
->ContextFlags
& CONTEXT_AMD64_FLOATING_POINT
) == CONTEXT_AMD64_FLOATING_POINT
)
218 memcpy( ctx
.ExtendedRegisters
, &ctx64
->FltSave
, sizeof(ctx
.ExtendedRegisters
) );
219 if ((ctx64
->ContextFlags
& CONTEXT_AMD64_XSTATE
) == CONTEXT_AMD64_XSTATE
)
220 src_ex
= (CONTEXT_EX
*)(ctx64
+ 1);
223 flags
= ctx
.ContextFlags
;
224 if (src_ex
) flags
|= CONTEXT_I386_XSTATE
;
225 RtlGetExtendedContextLength( flags
, &size
);
226 size
= ((size
+ 15) & ~15) + offsetof(struct stack_layout
,context
);
228 stack
= (struct stack_layout
*)(ULONG_PTR
)(ctx
.Esp
- size
);
229 stack
->rec_ptr
= PtrToUlong( &stack
->rec
);
231 RtlInitializeExtendedContext( &stack
->context
, flags
, &context_ex
);
232 context
= RtlLocateLegacyContext( context_ex
, NULL
);
234 context
->ContextFlags
= flags
;
235 /* adjust Eip for breakpoints in software emulation (hardware exceptions already adjust Rip) */
236 if (rec
->ExceptionCode
== EXCEPTION_BREAKPOINT
&& (wow64info
->CpuFlags
& WOW64_CPUFLAGS_SOFTWARE
))
238 stack
->context_ptr
= PtrToUlong( context
);
242 XSTATE
*src_xs
= (XSTATE
*)((char *)src_ex
+ src_ex
->XState
.Offset
);
243 XSTATE
*dst_xs
= (XSTATE
*)((char *)context_ex
+ context_ex
->XState
.Offset
);
245 dst_xs
->Mask
= src_xs
->Mask
& ~(ULONG64
)3;
246 dst_xs
->CompactionMask
= src_xs
->CompactionMask
;
247 if ((dst_xs
->Mask
& 4) &&
248 src_ex
->XState
.Length
>= sizeof(XSTATE
) &&
249 context_ex
->XState
.Length
>= sizeof(XSTATE
))
250 memcpy( &dst_xs
->YmmContext
, &src_xs
->YmmContext
, sizeof(dst_xs
->YmmContext
) );
253 ctx
.Esp
= PtrToUlong( stack
);
254 ctx
.Eip
= pLdrSystemDllInitBlock
->pKiUserExceptionDispatcher
;
255 ctx
.EFlags
&= ~(0x100|0x400|0x40000);
256 pBTCpuSetContext( GetCurrentThread(), GetCurrentProcess(), NULL
, &ctx
);
258 TRACE( "exception %08lx dispatcher %08lx stack %08lx eip %08lx\n",
259 rec
->ExceptionCode
, ctx
.Eip
, ctx
.Esp
, stack
->context
.Eip
);
263 case IMAGE_FILE_MACHINE_ARMNT
:
268 EXCEPTION_RECORD32 rec
;
270 ARM_CONTEXT ctx
= { CONTEXT_ARM_ALL
};
272 pBTCpuGetContext( GetCurrentThread(), GetCurrentProcess(), NULL
, &ctx
);
273 stack
= (struct stack_layout
*)(ULONG_PTR
)(ctx
.Sp
& ~3) - 1;
275 stack
->context
= ctx
;
277 ctx
.R0
= PtrToUlong( &stack
->rec
); /* first arg for KiUserExceptionDispatcher */
278 ctx
.R1
= PtrToUlong( &stack
->context
); /* second arg for KiUserExceptionDispatcher */
279 ctx
.Sp
= PtrToUlong( stack
);
280 ctx
.Pc
= pLdrSystemDllInitBlock
->pKiUserExceptionDispatcher
;
281 if (ctx
.Pc
& 1) ctx
.Cpsr
|= 0x20;
282 else ctx
.Cpsr
&= ~0x20;
283 pBTCpuSetContext( GetCurrentThread(), GetCurrentProcess(), NULL
, &ctx
);
285 TRACE( "exception %08lx dispatcher %08lx stack %08lx pc %08lx\n",
286 rec
->ExceptionCode
, ctx
.Pc
, ctx
.Sp
, stack
->context
.Sp
);
293 /**********************************************************************
294 * call_raise_user_exception_dispatcher
296 static void call_raise_user_exception_dispatcher( ULONG code
)
298 TEB32
*teb32
= (TEB32
*)((char *)NtCurrentTeb() + NtCurrentTeb()->WowTebOffset
);
300 teb32
->ExceptionCode
= code
;
302 switch (current_machine
)
304 case IMAGE_FILE_MACHINE_I386
:
306 I386_CONTEXT ctx
= { CONTEXT_I386_ALL
};
308 pBTCpuGetContext( GetCurrentThread(), GetCurrentProcess(), NULL
, &ctx
);
309 ctx
.Esp
-= sizeof(ULONG
);
310 *(ULONG
*)ULongToPtr( ctx
.Esp
) = ctx
.Eip
;
311 ctx
.Eip
= (ULONG_PTR
)pKiRaiseUserExceptionDispatcher
;
312 pBTCpuSetContext( GetCurrentThread(), GetCurrentProcess(), NULL
, &ctx
);
316 case IMAGE_FILE_MACHINE_ARMNT
:
318 ARM_CONTEXT ctx
= { CONTEXT_ARM_ALL
};
320 pBTCpuGetContext( GetCurrentThread(), GetCurrentProcess(), NULL
, &ctx
);
321 ctx
.Pc
= (ULONG_PTR
)pKiRaiseUserExceptionDispatcher
;
322 pBTCpuSetContext( GetCurrentThread(), GetCurrentProcess(), NULL
, &ctx
);
329 /* based on RtlRaiseException: call NtRaiseException with context setup to return to caller */
330 void WINAPI
raise_exception( EXCEPTION_RECORD
*rec
, CONTEXT
*context
, BOOL first_chance
);
332 __ASM_GLOBAL_FUNC( raise_exception
,
334 __ASM_SEH(".seh_stackalloc 0x28\n\t")
335 __ASM_SEH(".seh_endprologue\n\t")
336 __ASM_CFI(".cfi_adjust_cfa_offset 0x28\n\t")
337 "movq %rcx,(%rsp)\n\t"
339 "call " __ASM_NAME("RtlCaptureContext") "\n\t"
340 "leaq 0x30(%rsp),%rax\n\t" /* orig stack pointer */
341 "movq %rax,0x98(%rdx)\n\t" /* context->Rsp */
342 "movq (%rsp),%rcx\n\t" /* original first parameter */
343 "movq 0x28(%rsp),%rax\n\t" /* return address */
344 "movq %rax,0xf8(%rdx)\n\t" /* context->Rip */
345 "call " __ASM_NAME("NtRaiseException") )
346 #elif defined(__aarch64__)
347 __ASM_GLOBAL_FUNC( raise_exception
,
348 "stp x29, x30, [sp, #-32]!\n\t"
349 __ASM_SEH(".seh_save_fplr_x 32\n\t")
350 __ASM_SEH(".seh_endprologue\n\t")
351 __ASM_CFI(".cfi_def_cfa x29, 32\n\t")
352 __ASM_CFI(".cfi_offset x30, -24\n\t")
353 __ASM_CFI(".cfi_offset x29, -32\n\t")
355 "stp x0, x1, [sp, #16]\n\t"
357 "bl " __ASM_NAME("RtlCaptureContext") "\n\t"
358 "ldp x0, x1, [sp, #16]\n\t" /* orig parameters */
359 "ldp x4, x5, [sp]\n\t" /* frame pointer, return address */
360 "stp x4, x5, [x1, #0xf0]\n\t" /* context->Fp, Lr */
361 "add x4, sp, #32\n\t" /* orig stack pointer */
362 "stp x4, x5, [x1, #0x100]\n\t" /* context->Sp, Pc */
363 "bl " __ASM_NAME("NtRaiseException") )
367 /**********************************************************************
370 NTSTATUS WINAPI
wow64_NtAddAtom( UINT
*args
)
372 const WCHAR
*name
= get_ptr( &args
);
373 ULONG len
= get_ulong( &args
);
374 RTL_ATOM
*atom
= get_ptr( &args
);
376 return NtAddAtom( name
, len
, atom
);
380 /**********************************************************************
381 * wow64_NtAllocateLocallyUniqueId
383 NTSTATUS WINAPI
wow64_NtAllocateLocallyUniqueId( UINT
*args
)
385 LUID
*luid
= get_ptr( &args
);
387 return NtAllocateLocallyUniqueId( luid
);
391 /**********************************************************************
392 * wow64_NtAllocateUuids
394 NTSTATUS WINAPI
wow64_NtAllocateUuids( UINT
*args
)
396 ULARGE_INTEGER
*time
= get_ptr( &args
);
397 ULONG
*delta
= get_ptr( &args
);
398 ULONG
*sequence
= get_ptr( &args
);
399 UCHAR
*seed
= get_ptr( &args
);
401 return NtAllocateUuids( time
, delta
, sequence
, seed
);
405 /***********************************************************************
406 * wow64_NtCallbackReturn
408 NTSTATUS WINAPI
wow64_NtCallbackReturn( UINT
*args
)
410 void *ret_ptr
= get_ptr( &args
);
411 ULONG ret_len
= get_ulong( &args
);
412 NTSTATUS status
= get_ulong( &args
);
414 struct user_callback_frame
*frame
= NtCurrentTeb()->TlsSlots
[WOW64_TLS_USERCALLBACKDATA
];
416 if (!frame
) return STATUS_NO_CALLBACK_ACTIVE
;
418 *frame
->ret_ptr
= ret_ptr
;
419 *frame
->ret_len
= ret_len
;
420 frame
->status
= status
;
421 __wine_longjmp( &frame
->jmpbuf
, 1 );
425 /**********************************************************************
428 NTSTATUS WINAPI
wow64_NtClose( UINT
*args
)
430 HANDLE handle
= get_handle( &args
);
432 return NtClose( handle
);
436 /**********************************************************************
439 NTSTATUS WINAPI
wow64_NtContinue( UINT
*args
)
441 void *context
= get_ptr( &args
);
442 BOOLEAN alertable
= get_ulong( &args
);
444 NTSTATUS status
= get_context_return_value( context
);
445 struct user_apc_frame
*frame
= NtCurrentTeb()->TlsSlots
[WOW64_TLS_APCLIST
];
447 pBTCpuSetContext( GetCurrentThread(), GetCurrentProcess(), NULL
, context
);
449 while (frame
&& frame
->wow_context
!= context
) frame
= frame
->prev_frame
;
450 NtCurrentTeb()->TlsSlots
[WOW64_TLS_APCLIST
] = frame
? frame
->prev_frame
: NULL
;
451 if (frame
) NtContinue( frame
->context
, alertable
);
453 if (alertable
) NtTestAlert();
458 /**********************************************************************
461 NTSTATUS WINAPI
wow64_NtDeleteAtom( UINT
*args
)
463 RTL_ATOM atom
= get_ulong( &args
);
465 return NtDeleteAtom( atom
);
469 /**********************************************************************
472 NTSTATUS WINAPI
wow64_NtFindAtom( UINT
*args
)
474 const WCHAR
*name
= get_ptr( &args
);
475 ULONG len
= get_ulong( &args
);
476 RTL_ATOM
*atom
= get_ptr( &args
);
478 return NtFindAtom( name
, len
, atom
);
482 /**********************************************************************
483 * wow64_NtGetContextThread
485 NTSTATUS WINAPI
wow64_NtGetContextThread( UINT
*args
)
487 HANDLE handle
= get_handle( &args
);
488 WOW64_CONTEXT
*context
= get_ptr( &args
);
490 return RtlWow64GetThreadContext( handle
, context
);
494 /**********************************************************************
495 * wow64_NtGetCurrentProcessorNumber
497 NTSTATUS WINAPI
wow64_NtGetCurrentProcessorNumber( UINT
*args
)
499 return NtGetCurrentProcessorNumber();
503 /**********************************************************************
504 * wow64_NtQueryDefaultLocale
506 NTSTATUS WINAPI
wow64_NtQueryDefaultLocale( UINT
*args
)
508 BOOLEAN user
= get_ulong( &args
);
509 LCID
*lcid
= get_ptr( &args
);
511 return NtQueryDefaultLocale( user
, lcid
);
515 /**********************************************************************
516 * wow64_NtQueryDefaultUILanguage
518 NTSTATUS WINAPI
wow64_NtQueryDefaultUILanguage( UINT
*args
)
520 LANGID
*lang
= get_ptr( &args
);
522 return NtQueryDefaultUILanguage( lang
);
526 /**********************************************************************
527 * wow64_NtQueryInformationAtom
529 NTSTATUS WINAPI
wow64_NtQueryInformationAtom( UINT
*args
)
531 RTL_ATOM atom
= get_ulong( &args
);
532 ATOM_INFORMATION_CLASS
class = get_ulong( &args
);
533 void *info
= get_ptr( &args
);
534 ULONG len
= get_ulong( &args
);
535 ULONG
*retlen
= get_ptr( &args
);
537 if (class != AtomBasicInformation
) FIXME( "class %u not supported\n", class );
538 return NtQueryInformationAtom( atom
, class, info
, len
, retlen
);
542 /**********************************************************************
543 * wow64_NtQueryInstallUILanguage
545 NTSTATUS WINAPI
wow64_NtQueryInstallUILanguage( UINT
*args
)
547 LANGID
*lang
= get_ptr( &args
);
549 return NtQueryInstallUILanguage( lang
);
553 /**********************************************************************
554 * wow64_NtRaiseException
556 NTSTATUS WINAPI
wow64_NtRaiseException( UINT
*args
)
558 EXCEPTION_RECORD32
*rec32
= get_ptr( &args
);
559 void *context32
= get_ptr( &args
);
560 BOOL first_chance
= get_ulong( &args
);
562 EXCEPTION_RECORD
*rec
= exception_record_32to64( rec32
);
565 pBTCpuSetContext( GetCurrentThread(), GetCurrentProcess(), NULL
, context32
);
569 raise_exception( rec
, &context
, first_chance
);
573 call_user_exception_dispatcher( rec32
, context32
, &context
);
576 return STATUS_SUCCESS
;
580 /**********************************************************************
581 * wow64_NtSetContextThread
583 NTSTATUS WINAPI
wow64_NtSetContextThread( UINT
*args
)
585 HANDLE handle
= get_handle( &args
);
586 WOW64_CONTEXT
*context
= get_ptr( &args
);
588 return RtlWow64SetThreadContext( handle
, context
);
592 /**********************************************************************
593 * wow64_NtSetDebugFilterState
595 NTSTATUS WINAPI
wow64_NtSetDebugFilterState( UINT
*args
)
597 ULONG component_id
= get_ulong( &args
);
598 ULONG level
= get_ulong( &args
);
599 BOOLEAN state
= get_ulong( &args
);
601 return NtSetDebugFilterState( component_id
, level
, state
);
605 /**********************************************************************
606 * wow64_NtSetDefaultLocale
608 NTSTATUS WINAPI
wow64_NtSetDefaultLocale( UINT
*args
)
610 BOOLEAN user
= get_ulong( &args
);
611 LCID lcid
= get_ulong( &args
);
613 return NtSetDefaultLocale( user
, lcid
);
617 /**********************************************************************
618 * wow64_NtSetDefaultUILanguage
620 NTSTATUS WINAPI
wow64_NtSetDefaultUILanguage( UINT
*args
)
622 LANGID lang
= get_ulong( &args
);
624 return NtSetDefaultUILanguage( lang
);
628 /**********************************************************************
629 * wow64_NtWow64IsProcessorFeaturePresent
631 NTSTATUS WINAPI
wow64_NtWow64IsProcessorFeaturePresent( UINT
*args
)
633 UINT feature
= get_ulong( &args
);
635 return pBTCpuIsProcessorFeaturePresent
&& pBTCpuIsProcessorFeaturePresent( feature
);
639 /**********************************************************************
642 void init_image_mapping( HMODULE module
)
644 ULONG
*ptr
= RtlFindExportedRoutineByName( module
, "Wow64Transition" );
646 if (ptr
) *ptr
= PtrToUlong( pBTCpuGetBopCode() );
650 /**********************************************************************
653 static HMODULE
load_64bit_module( const WCHAR
*name
)
658 WCHAR path
[MAX_PATH
];
659 const WCHAR
*dir
= get_machine_wow64_dir( IMAGE_FILE_MACHINE_TARGET_HOST
);
661 swprintf( path
, MAX_PATH
, L
"%s\\%s", dir
, name
);
662 RtlInitUnicodeString( &str
, path
);
663 if ((status
= LdrLoadDll( dir
, 0, &str
, &module
)))
665 ERR( "failed to load dll %lx\n", status
);
666 NtTerminateProcess( GetCurrentProcess(), status
);
672 /**********************************************************************
675 static const WCHAR
*get_cpu_dll_name(void)
677 static ULONG buffer
[32];
678 KEY_VALUE_PARTIAL_INFORMATION
*info
= (KEY_VALUE_PARTIAL_INFORMATION
*)buffer
;
679 OBJECT_ATTRIBUTES attr
;
680 UNICODE_STRING nameW
;
685 switch (current_machine
)
687 case IMAGE_FILE_MACHINE_I386
:
688 RtlInitUnicodeString( &nameW
, L
"\\Registry\\Machine\\Software\\Microsoft\\Wow64\\x86" );
689 ret
= (native_machine
== IMAGE_FILE_MACHINE_ARM64
? L
"xtajit.dll" : L
"wow64cpu.dll");
691 case IMAGE_FILE_MACHINE_ARMNT
:
692 RtlInitUnicodeString( &nameW
, L
"\\Registry\\Machine\\Software\\Microsoft\\Wow64\\arm" );
693 ret
= L
"wowarmhw.dll";
696 ERR( "unsupported machine %04x\n", current_machine
);
697 RtlExitUserProcess( 1 );
699 InitializeObjectAttributes( &attr
, &nameW
, OBJ_CASE_INSENSITIVE
, 0, NULL
);
700 if (NtOpenKey( &key
, KEY_READ
| KEY_WOW64_64KEY
, &attr
)) return ret
;
701 RtlInitUnicodeString( &nameW
, L
"" );
702 size
= sizeof(buffer
) - sizeof(WCHAR
);
703 if (!NtQueryValueKey( key
, &nameW
, KeyValuePartialInformation
, buffer
, size
, &size
) && info
->Type
== REG_SZ
)
705 ((WCHAR
*)info
->Data
)[info
->DataLength
/ sizeof(WCHAR
)] = 0;
706 ret
= (WCHAR
*)info
->Data
;
713 /**********************************************************************
714 * create_cross_process_work_list
716 static NTSTATUS
create_cross_process_work_list( WOW64INFO
*wow64info
)
718 SIZE_T map_size
= 0x4000;
722 CROSS_PROCESS_WORK_LIST
*list
= NULL
;
723 CROSS_PROCESS_WORK_ENTRY
*end
;
726 size
.QuadPart
= map_size
;
727 status
= NtCreateSection( §ion
, SECTION_ALL_ACCESS
, NULL
, &size
, PAGE_READWRITE
, SEC_COMMIT
, 0 );
728 if (status
) return status
;
729 status
= NtMapViewOfSection( section
, GetCurrentProcess(), (void **)&list
, default_zero_bits
, 0, NULL
,
730 &map_size
, ViewShare
, MEM_TOP_DOWN
, PAGE_READWRITE
);
737 end
= (CROSS_PROCESS_WORK_ENTRY
*)((char *)list
+ map_size
);
738 for (i
= 0; list
->entries
+ i
+ 1 <= end
; i
++)
739 RtlWow64PushCrossProcessWorkOntoFreeList( &list
->free_list
, &list
->entries
[i
] );
741 wow64info
->SectionHandle
= (ULONG_PTR
)section
;
742 wow64info
->CrossProcessWorkList
= (ULONG_PTR
)list
;
743 return STATUS_SUCCESS
;
747 /**********************************************************************
750 static DWORD WINAPI
process_init( RTL_RUN_ONCE
*once
, void *param
, void **context
)
754 UNICODE_STRING str
= RTL_CONSTANT_STRING( L
"ntdll.dll" );
755 SYSTEM_BASIC_INFORMATION info
;
756 ULONG
*p__wine_syscall_dispatcher
, *p__wine_unix_call_dispatcher
;
757 const SYSTEM_SERVICE_TABLE
*psdwhwin32
;
759 RtlWow64GetProcessMachines( GetCurrentProcess(), ¤t_machine
, &native_machine
);
760 if (!current_machine
) current_machine
= native_machine
;
761 args_alignment
= (current_machine
== IMAGE_FILE_MACHINE_I386
) ? sizeof(ULONG
) : sizeof(ULONG64
);
762 NtQuerySystemInformation( SystemEmulationBasicInformation
, &info
, sizeof(info
), NULL
);
763 highest_user_address
= (ULONG_PTR
)info
.HighestUserAddress
;
764 default_zero_bits
= (ULONG_PTR
)info
.HighestUserAddress
| 0x7fffffff;
765 NtQueryInformationProcess( GetCurrentProcess(), ProcessWow64Information
, &peb32
, sizeof(peb32
), NULL
);
766 wow64info
= (WOW64INFO
*)(peb32
+ 1);
767 wow64info
->NativeSystemPageSize
= 0x1000;
768 wow64info
->NativeMachineType
= native_machine
;
769 wow64info
->EmulatedMachineType
= current_machine
;
770 NtCurrentTeb()->TlsSlots
[WOW64_TLS_WOW64INFO
] = wow64info
;
772 #define GET_PTR(name) p ## name = RtlFindExportedRoutineByName( module, #name )
774 LdrGetDllHandle( NULL
, 0, &str
, &module
);
775 GET_PTR( LdrSystemDllInitBlock
);
777 module
= load_64bit_module( get_cpu_dll_name() );
778 GET_PTR( BTCpuGetBopCode
);
779 GET_PTR( BTCpuGetContext
);
780 GET_PTR( BTCpuIsProcessorFeaturePresent
);
781 GET_PTR( BTCpuProcessInit
);
782 GET_PTR( BTCpuThreadInit
);
783 GET_PTR( BTCpuResetToConsistentState
);
784 GET_PTR( BTCpuSetContext
);
785 GET_PTR( BTCpuSimulate
);
786 GET_PTR( BTCpuNotifyFlushInstructionCache2
);
787 GET_PTR( BTCpuNotifyMapViewOfSection
);
788 GET_PTR( BTCpuNotifyMemoryAlloc
);
789 GET_PTR( BTCpuNotifyMemoryDirty
);
790 GET_PTR( BTCpuNotifyMemoryFree
);
791 GET_PTR( BTCpuNotifyMemoryProtect
);
792 GET_PTR( BTCpuNotifyUnmapViewOfSection
);
793 GET_PTR( BTCpuUpdateProcessorInformation
);
794 GET_PTR( BTCpuThreadTerm
);
795 GET_PTR( __wine_get_unix_opcode
);
797 module
= load_64bit_module( L
"wow64win.dll" );
798 GET_PTR( sdwhwin32
);
799 syscall_tables
[1] = *psdwhwin32
;
803 module
= (HMODULE
)(ULONG_PTR
)pLdrSystemDllInitBlock
->ntdll_handle
;
804 init_image_mapping( module
);
805 GET_PTR( KiRaiseUserExceptionDispatcher
);
806 GET_PTR( __wine_syscall_dispatcher
);
807 GET_PTR( __wine_unix_call_dispatcher
);
809 *p__wine_syscall_dispatcher
= PtrToUlong( pBTCpuGetBopCode() );
810 *p__wine_unix_call_dispatcher
= PtrToUlong( p__wine_get_unix_opcode() );
812 if (wow64info
->CpuFlags
& WOW64_CPUFLAGS_SOFTWARE
) create_cross_process_work_list( wow64info
);
814 init_file_redirects();
821 /**********************************************************************
824 static void thread_init(void)
828 RtlWow64GetCurrentCpuArea( NULL
, &cpu_area_ctx
, NULL
);
829 NtCurrentTeb()->TlsSlots
[WOW64_TLS_WOW64INFO
] = wow64info
;
830 if (pBTCpuThreadInit
) pBTCpuThreadInit();
832 /* update initial context to jump to 32-bit LdrInitializeThunk (cf. 32-bit call_init_thunk) */
833 switch (current_machine
)
835 case IMAGE_FILE_MACHINE_I386
:
837 I386_CONTEXT
*ctx_ptr
, *ctx
= cpu_area_ctx
;
840 ctx_ptr
= (I386_CONTEXT
*)ULongToPtr( ctx
->Esp
) - 1;
843 stack
= (ULONG
*)ctx_ptr
;
847 *(--stack
) = PtrToUlong( ctx_ptr
);
848 *(--stack
) = 0xdeadbabe;
849 ctx
->Esp
= PtrToUlong( stack
);
850 ctx
->Eip
= pLdrSystemDllInitBlock
->pLdrInitializeThunk
;
851 pBTCpuSetContext( GetCurrentThread(), GetCurrentProcess(), NULL
, ctx
);
855 case IMAGE_FILE_MACHINE_ARMNT
:
857 ARM_CONTEXT
*ctx_ptr
, *ctx
= cpu_area_ctx
;
859 ctx_ptr
= (ARM_CONTEXT
*)ULongToPtr( ctx
->Sp
& ~15 ) - 1;
862 ctx
->R0
= PtrToUlong( ctx_ptr
);
863 ctx
->Sp
= PtrToUlong( ctx_ptr
);
864 ctx
->Pc
= pLdrSystemDllInitBlock
->pLdrInitializeThunk
;
865 pBTCpuSetContext( GetCurrentThread(), GetCurrentProcess(), NULL
, ctx
);
870 ERR( "not supported machine %x\n", current_machine
);
871 NtTerminateProcess( GetCurrentProcess(), STATUS_INVALID_IMAGE_FORMAT
);
876 /**********************************************************************
879 static void free_temp_data(void)
881 struct mem_header
*next
, *mem
;
883 for (mem
= NtCurrentTeb()->TlsSlots
[WOW64_TLS_TEMPLIST
]; mem
; mem
= next
)
886 RtlFreeHeap( GetProcessHeap(), 0, mem
);
888 NtCurrentTeb()->TlsSlots
[WOW64_TLS_TEMPLIST
] = NULL
;
892 /**********************************************************************
895 static LONG CALLBACK
syscall_filter( EXCEPTION_POINTERS
*ptrs
)
897 switch (ptrs
->ExceptionRecord
->ExceptionCode
)
899 case STATUS_INVALID_HANDLE
:
900 call_raise_user_exception_dispatcher( ptrs
->ExceptionRecord
->ExceptionCode
);
903 return EXCEPTION_EXECUTE_HANDLER
;
907 /**********************************************************************
908 * Wow64SystemServiceEx (wow64.@)
910 NTSTATUS WINAPI
Wow64SystemServiceEx( UINT num
, UINT
*args
)
913 UINT id
= num
& 0xfff;
914 const SYSTEM_SERVICE_TABLE
*table
= &syscall_tables
[(num
>> 12) & 3];
916 if (id
>= table
->ServiceLimit
|| !table
->ServiceTable
[id
])
918 ERR( "unsupported syscall %04x\n", num
);
919 return STATUS_INVALID_SYSTEM_SERVICE
;
923 syscall_thunk thunk
= (syscall_thunk
)table
->ServiceTable
[id
];
924 status
= thunk( args
);
926 __EXCEPT( syscall_filter
)
928 status
= GetExceptionCode();
936 /**********************************************************************
939 static LONG CALLBACK
simulate_filter( EXCEPTION_POINTERS
*ptrs
)
941 Wow64PassExceptionToGuest( ptrs
);
942 return EXCEPTION_EXECUTE_HANDLER
;
946 /**********************************************************************
949 static void cpu_simulate(void)
957 __EXCEPT( simulate_filter
)
959 /* restart simulation loop */
966 /**********************************************************************
967 * Wow64AllocateTemp (wow64.@)
969 * FIXME: probably not 100% compatible.
971 void * WINAPI
Wow64AllocateTemp( SIZE_T size
)
973 struct mem_header
*mem
;
975 if (!(mem
= RtlAllocateHeap( GetProcessHeap(), 0, offsetof( struct mem_header
, data
[size
] ))))
977 mem
->next
= NtCurrentTeb()->TlsSlots
[WOW64_TLS_TEMPLIST
];
978 NtCurrentTeb()->TlsSlots
[WOW64_TLS_TEMPLIST
] = mem
;
983 /**********************************************************************
984 * Wow64ApcRoutine (wow64.@)
986 void WINAPI
Wow64ApcRoutine( ULONG_PTR arg1
, ULONG_PTR arg2
, ULONG_PTR arg3
, CONTEXT
*context
)
988 struct user_apc_frame frame
;
990 frame
.prev_frame
= NtCurrentTeb()->TlsSlots
[WOW64_TLS_APCLIST
];
991 frame
.context
= context
;
992 NtCurrentTeb()->TlsSlots
[WOW64_TLS_APCLIST
] = &frame
;
994 /* cf. 32-bit call_user_apc_dispatcher */
995 switch (current_machine
)
997 case IMAGE_FILE_MACHINE_I386
:
999 struct apc_stack_layout
1007 I386_CONTEXT context
;
1009 I386_CONTEXT ctx
= { CONTEXT_I386_FULL
};
1011 pBTCpuGetContext( GetCurrentThread(), GetCurrentProcess(), NULL
, &ctx
);
1012 stack
= (struct apc_stack_layout
*)ULongToPtr( ctx
.Esp
& ~3 ) - 1;
1013 stack
->context_ptr
= PtrToUlong( &stack
->context
);
1014 stack
->func
= arg1
>> 32;
1018 stack
->context
= ctx
;
1019 ctx
.Esp
= PtrToUlong( stack
);
1020 ctx
.Eip
= pLdrSystemDllInitBlock
->pKiUserApcDispatcher
;
1021 frame
.wow_context
= &stack
->context
;
1022 pBTCpuSetContext( GetCurrentThread(), GetCurrentProcess(), NULL
, &ctx
);
1027 case IMAGE_FILE_MACHINE_ARMNT
:
1029 struct apc_stack_layout
1033 ARM_CONTEXT context
;
1035 ARM_CONTEXT ctx
= { CONTEXT_ARM_FULL
};
1037 pBTCpuGetContext( GetCurrentThread(), GetCurrentProcess(), NULL
, &ctx
);
1038 stack
= (struct apc_stack_layout
*)ULongToPtr( ctx
.Sp
& ~15 ) - 1;
1039 stack
->func
= arg1
>> 32;
1040 stack
->context
= ctx
;
1041 ctx
.Sp
= PtrToUlong( stack
);
1042 ctx
.Pc
= pLdrSystemDllInitBlock
->pKiUserApcDispatcher
;
1043 ctx
.R0
= PtrToUlong( &stack
->context
);
1047 frame
.wow_context
= &stack
->context
;
1048 pBTCpuSetContext( GetCurrentThread(), GetCurrentProcess(), NULL
, &ctx
);
1056 /**********************************************************************
1057 * Wow64KiUserCallbackDispatcher (wow64.@)
1059 NTSTATUS WINAPI
Wow64KiUserCallbackDispatcher( ULONG id
, void *args
, ULONG len
,
1060 void **ret_ptr
, ULONG
*ret_len
)
1062 WOW64_CPURESERVED
*cpu
= NtCurrentTeb()->TlsSlots
[WOW64_TLS_CPURESERVED
];
1063 TEB32
*teb32
= (TEB32
*)((char *)NtCurrentTeb() + NtCurrentTeb()->WowTebOffset
);
1064 ULONG teb_frame
= teb32
->Tib
.ExceptionList
;
1065 struct user_callback_frame frame
;
1066 USHORT flags
= cpu
->Flags
;
1068 frame
.prev_frame
= NtCurrentTeb()->TlsSlots
[WOW64_TLS_USERCALLBACKDATA
];
1069 frame
.temp_list
= NtCurrentTeb()->TlsSlots
[WOW64_TLS_TEMPLIST
];
1070 frame
.ret_ptr
= ret_ptr
;
1071 frame
.ret_len
= ret_len
;
1073 NtCurrentTeb()->TlsSlots
[WOW64_TLS_USERCALLBACKDATA
] = &frame
;
1074 NtCurrentTeb()->TlsSlots
[WOW64_TLS_TEMPLIST
] = NULL
;
1076 /* cf. 32-bit KeUserModeCallback */
1077 switch (current_machine
)
1079 case IMAGE_FILE_MACHINE_I386
:
1081 I386_CONTEXT orig_ctx
, ctx
= { CONTEXT_I386_FULL
};
1085 pBTCpuGetContext( GetCurrentThread(), GetCurrentProcess(), NULL
, &ctx
);
1088 stack
= args_data
= ULongToPtr( (ctx
.Esp
- len
) & ~15 );
1089 memcpy( args_data
, args
, len
);
1092 *(--stack
) = PtrToUlong( args_data
);
1094 *(--stack
) = 0xdeadbabe;
1096 ctx
.Esp
= PtrToUlong( stack
);
1097 ctx
.Eip
= pLdrSystemDllInitBlock
->pKiUserCallbackDispatcher
;
1098 pBTCpuSetContext( GetCurrentThread(), GetCurrentProcess(), NULL
, &ctx
);
1100 if (!__wine_setjmpex( &frame
.jmpbuf
, NULL
))
1103 pBTCpuSetContext( GetCurrentThread(), GetCurrentProcess(), NULL
, &orig_ctx
);
1107 case IMAGE_FILE_MACHINE_ARMNT
:
1109 ARM_CONTEXT orig_ctx
, ctx
= { CONTEXT_ARM_FULL
};
1112 pBTCpuGetContext( GetCurrentThread(), GetCurrentProcess(), NULL
, &ctx
);
1115 args_data
= ULongToPtr( (ctx
.Sp
- len
) & ~15 );
1116 memcpy( args_data
, args
, len
);
1119 ctx
.R1
= PtrToUlong( args_data
);
1121 ctx
.Sp
= PtrToUlong( args_data
);
1122 ctx
.Pc
= pLdrSystemDllInitBlock
->pKiUserCallbackDispatcher
;
1123 pBTCpuSetContext( GetCurrentThread(), GetCurrentProcess(), NULL
, &ctx
);
1125 if (!__wine_setjmpex( &frame
.jmpbuf
, NULL
))
1128 pBTCpuSetContext( GetCurrentThread(), GetCurrentProcess(), NULL
, &orig_ctx
);
1133 teb32
->Tib
.ExceptionList
= teb_frame
;
1134 NtCurrentTeb()->TlsSlots
[WOW64_TLS_USERCALLBACKDATA
] = frame
.prev_frame
;
1135 NtCurrentTeb()->TlsSlots
[WOW64_TLS_TEMPLIST
] = frame
.temp_list
;
1137 return frame
.status
;
1141 /**********************************************************************
1142 * Wow64LdrpInitialize (wow64.@)
1144 void WINAPI
Wow64LdrpInitialize( CONTEXT
*context
)
1146 static RTL_RUN_ONCE init_done
;
1148 RtlRunOnceExecuteOnce( &init_done
, process_init
, NULL
, NULL
);
1154 /**********************************************************************
1155 * Wow64PrepareForException (wow64.@)
1157 void WINAPI
Wow64PrepareForException( EXCEPTION_RECORD
*rec
, CONTEXT
*context
)
1159 EXCEPTION_POINTERS ptrs
= { rec
, context
};
1161 pBTCpuResetToConsistentState( &ptrs
);
1165 /**********************************************************************
1166 * Wow64PassExceptionToGuest (wow64.@)
1168 void WINAPI
Wow64PassExceptionToGuest( EXCEPTION_POINTERS
*ptrs
)
1170 EXCEPTION_RECORD32 rec32
;
1172 exception_record_64to32( &rec32
, ptrs
->ExceptionRecord
);
1173 call_user_exception_dispatcher( &rec32
, NULL
, ptrs
->ContextRecord
);
1177 /**********************************************************************
1178 * Wow64ProcessPendingCrossProcessItems (wow64.@)
1180 void WINAPI
Wow64ProcessPendingCrossProcessItems(void)
1182 CROSS_PROCESS_WORK_LIST
*list
= (void *)wow64info
->CrossProcessWorkList
;
1183 CROSS_PROCESS_WORK_ENTRY
*entry
;
1184 BOOLEAN flush
= FALSE
;
1188 entry
= RtlWow64PopAllCrossProcessWorkFromWorkList( &list
->work_list
, &flush
);
1192 if (pBTCpuNotifyFlushInstructionCache2
) pBTCpuNotifyFlushInstructionCache2( NULL
, ~0ull );
1196 RtlWow64PushCrossProcessWorkOntoFreeList( &list
->free_list
, entry
);
1197 entry
= CROSS_PROCESS_LIST_ENTRY( &list
->work_list
, next
);
1206 case CrossProcessPreVirtualAlloc
:
1209 case CrossProcessPostVirtualAlloc
:
1210 if (!pBTCpuNotifyMemoryAlloc
) break;
1211 if (entry
->args
[2]) break;
1212 pBTCpuNotifyMemoryAlloc( (void *)entry
->addr
, entry
->size
, entry
->args
[0], entry
->args
[1] );
1214 case CrossProcessPreVirtualFree
:
1215 if (!pBTCpuNotifyMemoryFree
) break;
1216 pBTCpuNotifyMemoryFree( (void *)entry
->addr
, entry
->size
, entry
->args
[0] );
1218 case CrossProcessPostVirtualFree
:
1221 case CrossProcessPreVirtualProtect
:
1222 if (!pBTCpuNotifyMemoryProtect
) break;
1223 pBTCpuNotifyMemoryProtect( (void *)entry
->addr
, entry
->size
, entry
->args
[0] );
1225 case CrossProcessPostVirtualProtect
:
1228 case CrossProcessFlushCache
:
1229 if (!pBTCpuNotifyFlushInstructionCache2
) break;
1230 pBTCpuNotifyFlushInstructionCache2( (void *)entry
->addr
, entry
->size
);
1234 RtlWow64PushCrossProcessWorkOntoFreeList( &list
->free_list
, entry
);
1235 entry
= CROSS_PROCESS_LIST_ENTRY( &list
->work_list
, next
);
1240 /**********************************************************************
1241 * Wow64RaiseException (wow64.@)
1243 NTSTATUS WINAPI
Wow64RaiseException( int code
, EXCEPTION_RECORD
*rec
)
1245 EXCEPTION_RECORD32 rec32
;
1247 BOOL first_chance
= TRUE
;
1254 switch (current_machine
)
1256 case IMAGE_FILE_MACHINE_I386
:
1258 EXCEPTION_RECORD int_rec
= { 0 };
1260 ctx32
.i386
.ContextFlags
= CONTEXT_I386_ALL
;
1261 pBTCpuGetContext( GetCurrentThread(), GetCurrentProcess(), NULL
, &ctx32
.i386
);
1262 if (code
== -1) break;
1263 int_rec
.ExceptionAddress
= (void *)(ULONG_PTR
)ctx32
.i386
.Eip
;
1266 case 0x00: /* division by zero */
1267 int_rec
.ExceptionCode
= EXCEPTION_INT_DIVIDE_BY_ZERO
;
1269 case 0x01: /* single-step */
1270 int_rec
.ExceptionCode
= EXCEPTION_SINGLE_STEP
;
1272 case 0x03: /* breakpoint */
1273 int_rec
.ExceptionCode
= EXCEPTION_BREAKPOINT
;
1274 int_rec
.ExceptionAddress
= (void *)(ULONG_PTR
)(ctx32
.i386
.Eip
+ 1);
1275 int_rec
.NumberParameters
= 1;
1277 case 0x04: /* overflow */
1278 int_rec
.ExceptionCode
= EXCEPTION_INT_OVERFLOW
;
1280 case 0x05: /* array bounds */
1281 int_rec
.ExceptionCode
= EXCEPTION_ARRAY_BOUNDS_EXCEEDED
;
1283 case 0x06: /* invalid opcode */
1284 int_rec
.ExceptionCode
= EXCEPTION_ILLEGAL_INSTRUCTION
;
1286 case 0x09: /* coprocessor segment overrun */
1287 int_rec
.ExceptionCode
= EXCEPTION_FLT_INVALID_OPERATION
;
1289 case 0x0c: /* stack fault */
1290 int_rec
.ExceptionCode
= EXCEPTION_STACK_OVERFLOW
;
1292 case 0x29: /* __fastfail */
1293 int_rec
.ExceptionCode
= STATUS_STACK_BUFFER_OVERRUN
;
1294 int_rec
.ExceptionFlags
= EH_NONCONTINUABLE
;
1295 int_rec
.NumberParameters
= 1;
1296 int_rec
.ExceptionInformation
[0] = ctx32
.i386
.Ecx
;
1297 first_chance
= FALSE
;
1299 case 0x2d: /* debug service */
1301 pBTCpuSetContext( GetCurrentThread(), GetCurrentProcess(), NULL
, &ctx32
.i386
);
1302 int_rec
.ExceptionCode
= EXCEPTION_BREAKPOINT
;
1303 int_rec
.ExceptionAddress
= (void *)(ULONG_PTR
)ctx32
.i386
.Eip
;
1304 int_rec
.NumberParameters
= 1;
1305 int_rec
.ExceptionInformation
[0] = ctx32
.i386
.Eax
;
1308 ctx32
.i386
.Eip
-= 2;
1309 pBTCpuSetContext( GetCurrentThread(), GetCurrentProcess(), NULL
, &ctx32
.i386
);
1310 int_rec
.ExceptionCode
= EXCEPTION_ACCESS_VIOLATION
;
1311 int_rec
.ExceptionAddress
= (void *)(ULONG_PTR
)ctx32
.i386
.Eip
;
1312 int_rec
.NumberParameters
= 2;
1313 int_rec
.ExceptionInformation
[1] = 0xffffffff;
1320 case IMAGE_FILE_MACHINE_ARMNT
:
1321 ctx32
.arm
.ContextFlags
= CONTEXT_ARM_ALL
;
1322 pBTCpuGetContext( GetCurrentThread(), GetCurrentProcess(), NULL
, &ctx32
.arm
);
1326 exception_record_64to32( &rec32
, rec
);
1329 raise_exception( rec
, &context
, first_chance
);
1333 call_user_exception_dispatcher( &rec32
, &ctx32
, NULL
);
1336 return STATUS_SUCCESS
;