Module: wine Branch: master Commit: 37628a77324f4393e92e8fbd007e5a2e132a9bbe URL: https://gitlab.winehq.org/wine/wine/-/commit/37628a77324f4393e92e8fbd007e5a2...
Author: Alexandre Julliard julliard@winehq.org Date: Thu Mar 9 17:28:12 2023 +0100
wow64: Implement Wow64RaiseException().
---
dlls/wow64/syscall.c | 125 ++++++++++++++++++++++++++++++++++++++++++++++---- dlls/wow64/wow64.spec | 2 +- include/winternl.h | 1 + 3 files changed, 117 insertions(+), 11 deletions(-)
diff --git a/dlls/wow64/syscall.c b/dlls/wow64/syscall.c index b6b3c0c2830..d1c7421fabd 100644 --- a/dlls/wow64/syscall.c +++ b/dlls/wow64/syscall.c @@ -151,6 +151,20 @@ static EXCEPTION_RECORD *exception_record_32to64( const EXCEPTION_RECORD32 *rec3 }
+static void exception_record_64to32( EXCEPTION_RECORD32 *rec32, const EXCEPTION_RECORD *rec ) +{ + unsigned int i; + + rec32->ExceptionCode = rec->ExceptionCode; + rec32->ExceptionFlags = rec->ExceptionFlags; + rec32->ExceptionRecord = PtrToUlong( rec->ExceptionRecord ); + rec32->ExceptionAddress = PtrToUlong( rec->ExceptionAddress ); + rec32->NumberParameters = rec->NumberParameters; + for (i = 0; i < rec->NumberParameters; i++) + rec32->ExceptionInformation[i] = rec->ExceptionInformation[i]; +} + + static NTSTATUS get_context_return_value( void *wow_context ) { switch (current_machine) @@ -1185,17 +1199,108 @@ void WINAPI Wow64PrepareForException( EXCEPTION_RECORD *rec, CONTEXT *context ) */ void WINAPI Wow64PassExceptionToGuest( EXCEPTION_POINTERS *ptrs ) { - EXCEPTION_RECORD *rec = ptrs->ExceptionRecord; EXCEPTION_RECORD32 rec32; - ULONG i; - - rec32.ExceptionCode = rec->ExceptionCode; - rec32.ExceptionFlags = rec->ExceptionFlags; - rec32.ExceptionRecord = PtrToUlong( rec->ExceptionRecord ); - rec32.ExceptionAddress = PtrToUlong( rec->ExceptionAddress ); - rec32.NumberParameters = rec->NumberParameters; - for (i = 0; i < rec->NumberParameters; i++) - rec32.ExceptionInformation[i] = rec->ExceptionInformation[i];
+ exception_record_64to32( &rec32, ptrs->ExceptionRecord ); call_user_exception_dispatcher( &rec32, NULL, ptrs->ContextRecord ); } + + +/********************************************************************** + * Wow64RaiseException (wow64.@) + */ +NTSTATUS WINAPI Wow64RaiseException( int code, EXCEPTION_RECORD *rec ) +{ + EXCEPTION_RECORD32 rec32; + CONTEXT context; + BOOL first_chance = TRUE; + union + { + I386_CONTEXT i386; + ARM_CONTEXT arm; + } ctx32 = { 0 }; + + switch (current_machine) + { + case IMAGE_FILE_MACHINE_I386: + { + EXCEPTION_RECORD int_rec = { 0 }; + + ctx32.i386.ContextFlags = CONTEXT_I386_ALL; + pBTCpuGetContext( GetCurrentThread(), GetCurrentProcess(), NULL, &ctx32.i386 ); + if (code == -1) break; + int_rec.ExceptionAddress = (void *)(ULONG_PTR)ctx32.i386.Eip; + switch (code) + { + case 0x00: /* division by zero */ + int_rec.ExceptionCode = EXCEPTION_INT_DIVIDE_BY_ZERO; + break; + case 0x01: /* single-step */ + int_rec.ExceptionCode = EXCEPTION_SINGLE_STEP; + break; + case 0x03: /* breakpoint */ + int_rec.ExceptionCode = EXCEPTION_BREAKPOINT; + int_rec.ExceptionAddress = (void *)(ULONG_PTR)(ctx32.i386.Eip + 1); + int_rec.NumberParameters = 1; + break; + case 0x04: /* overflow */ + int_rec.ExceptionCode = EXCEPTION_INT_OVERFLOW; + break; + case 0x05: /* array bounds */ + int_rec.ExceptionCode = EXCEPTION_ARRAY_BOUNDS_EXCEEDED; + break; + case 0x06: /* invalid opcode */ + int_rec.ExceptionCode = EXCEPTION_ILLEGAL_INSTRUCTION; + break; + case 0x09: /* coprocessor segment overrun */ + int_rec.ExceptionCode = EXCEPTION_FLT_INVALID_OPERATION; + break; + case 0x0c: /* stack fault */ + int_rec.ExceptionCode = EXCEPTION_STACK_OVERFLOW; + break; + case 0x29: /* __fastfail */ + int_rec.ExceptionCode = STATUS_STACK_BUFFER_OVERRUN; + int_rec.ExceptionFlags = EH_NONCONTINUABLE; + int_rec.NumberParameters = 1; + int_rec.ExceptionInformation[0] = ctx32.i386.Ecx; + first_chance = FALSE; + break; + case 0x2d: /* debug service */ + ctx32.i386.Eip++; + pBTCpuSetContext( GetCurrentThread(), GetCurrentProcess(), NULL, &ctx32.i386 ); + int_rec.ExceptionCode = EXCEPTION_BREAKPOINT; + int_rec.ExceptionAddress = (void *)(ULONG_PTR)ctx32.i386.Eip; + int_rec.NumberParameters = 1; + int_rec.ExceptionInformation[0] = ctx32.i386.Eax; + break; + default: + ctx32.i386.Eip -= 2; + pBTCpuSetContext( GetCurrentThread(), GetCurrentProcess(), NULL, &ctx32.i386 ); + int_rec.ExceptionCode = EXCEPTION_ACCESS_VIOLATION; + int_rec.ExceptionAddress = (void *)(ULONG_PTR)ctx32.i386.Eip; + int_rec.NumberParameters = 2; + int_rec.ExceptionInformation[1] = 0xffffffff; + break; + } + *rec = int_rec; + break; + } + + case IMAGE_FILE_MACHINE_ARMNT: + ctx32.arm.ContextFlags = CONTEXT_ARM_ALL; + pBTCpuGetContext( GetCurrentThread(), GetCurrentProcess(), NULL, &ctx32.arm ); + break; + } + + exception_record_64to32( &rec32, rec ); + __TRY + { + raise_exception( rec, &context, first_chance ); + } + __EXCEPT_ALL + { + call_user_exception_dispatcher( &rec32, &ctx32, NULL ); + } + __ENDTRY + return STATUS_SUCCESS; +} diff --git a/dlls/wow64/wow64.spec b/dlls/wow64/wow64.spec index e05a608d319..1f09e1411bb 100644 --- a/dlls/wow64/wow64.spec +++ b/dlls/wow64/wow64.spec @@ -16,7 +16,7 @@ @ stdcall Wow64PassExceptionToGuest(ptr) @ stub Wow64PrepareForDebuggerAttach @ stdcall Wow64PrepareForException(ptr ptr) -@ stub Wow64RaiseException +@ stdcall Wow64RaiseException(long ptr) @ stub Wow64ShallowThunkAllocObjectAttributes32TO64_FNC @ stub Wow64ShallowThunkAllocSecurityQualityOfService32TO64_FNC @ stub Wow64ShallowThunkSIZE_T32TO64 diff --git a/include/winternl.h b/include/winternl.h index 6fd0694b4ce..f59fcec05dd 100644 --- a/include/winternl.h +++ b/include/winternl.h @@ -3875,6 +3875,7 @@ void WINAPI Wow64ApcRoutine(ULONG_PTR,ULONG_PTR,ULONG_PTR,CONTEXT*); NTSTATUS WINAPI Wow64KiUserCallbackDispatcher(ULONG,void*,ULONG,void**,ULONG*); void WINAPI Wow64PassExceptionToGuest(EXCEPTION_POINTERS*); void WINAPI Wow64PrepareForException(EXCEPTION_RECORD*,CONTEXT*); +NTSTATUS WINAPI Wow64RaiseException(int,EXCEPTION_RECORD*); NTSTATUS WINAPI Wow64SystemServiceEx(UINT,UINT*);
#ifdef __WINESRC__