[PATCH 3/3] kernel32: Implement Wow64SetThreadContext().
Zebediah Figura
zfigura at codeweavers.com
Tue Jun 5 18:39:08 CDT 2018
Signed-off-by: Zebediah Figura <zfigura at codeweavers.com>
---
dlls/kernel32/kernel32.spec | 2 +-
dlls/kernel32/thread.c | 116 ++++++++++++++++++++++++++++++++++++++++++++
include/winbase.h | 1 +
3 files changed, 118 insertions(+), 1 deletion(-)
diff --git a/dlls/kernel32/kernel32.spec b/dlls/kernel32/kernel32.spec
index 1cb0b54..de6f007 100644
--- a/dlls/kernel32/kernel32.spec
+++ b/dlls/kernel32/kernel32.spec
@@ -1603,7 +1603,7 @@
@ stdcall Wow64GetThreadContext(long ptr)
# @ stub Wow64GetThreadSelectorEntry
@ stdcall Wow64RevertWow64FsRedirection(ptr)
-# @ stub Wow64SetThreadContext
+@ stdcall Wow64SetThreadContext(long ptr)
# @ stub Wow64SuspendThread
@ stdcall WriteConsoleA(long ptr long ptr ptr)
@ stdcall WriteConsoleInputA(long ptr long ptr)
diff --git a/dlls/kernel32/thread.c b/dlls/kernel32/thread.c
index caeec63..838cf0f 100644
--- a/dlls/kernel32/thread.c
+++ b/dlls/kernel32/thread.c
@@ -235,6 +235,122 @@ BOOL WINAPI SetThreadContext( HANDLE handle, /* [in] Handle to thread
}
+static NTSTATUS wow64_context_to_server( context_t *to, const WOW64_CONTEXT *from )
+{
+ DWORD flags = from->ContextFlags & ~WOW64_CONTEXT_i386; /* get rid of CPU id */
+
+ memset( to, 0, sizeof(*to) );
+ to->cpu = CPU_x86;
+
+ if (flags & WOW64_CONTEXT_CONTROL)
+ {
+ to->flags |= SERVER_CTX_CONTROL;
+ to->ctl.i386_regs.ebp = from->Ebp;
+ to->ctl.i386_regs.esp = from->Esp;
+ to->ctl.i386_regs.eip = from->Eip;
+ to->ctl.i386_regs.cs = from->SegCs;
+ to->ctl.i386_regs.ss = from->SegSs;
+ to->ctl.i386_regs.eflags = from->EFlags;
+ }
+ if (flags & WOW64_CONTEXT_INTEGER)
+ {
+ to->flags |= SERVER_CTX_INTEGER;
+ to->integer.i386_regs.eax = from->Eax;
+ to->integer.i386_regs.ebx = from->Ebx;
+ to->integer.i386_regs.ecx = from->Ecx;
+ to->integer.i386_regs.edx = from->Edx;
+ to->integer.i386_regs.esi = from->Esi;
+ to->integer.i386_regs.edi = from->Edi;
+ }
+ if (flags & WOW64_CONTEXT_SEGMENTS)
+ {
+ to->flags |= SERVER_CTX_SEGMENTS;
+ to->seg.i386_regs.ds = from->SegDs;
+ to->seg.i386_regs.es = from->SegEs;
+ to->seg.i386_regs.fs = from->SegFs;
+ to->seg.i386_regs.gs = from->SegGs;
+ }
+ if (flags & WOW64_CONTEXT_FLOATING_POINT)
+ {
+ to->flags |= SERVER_CTX_FLOATING_POINT;
+ to->fp.i386_regs.ctrl = from->FloatSave.ControlWord;
+ to->fp.i386_regs.status = from->FloatSave.StatusWord;
+ to->fp.i386_regs.tag = from->FloatSave.TagWord;
+ to->fp.i386_regs.err_off = from->FloatSave.ErrorOffset;
+ to->fp.i386_regs.err_sel = from->FloatSave.ErrorSelector;
+ to->fp.i386_regs.data_off = from->FloatSave.DataOffset;
+ to->fp.i386_regs.data_sel = from->FloatSave.DataSelector;
+ to->fp.i386_regs.cr0npx = from->FloatSave.Cr0NpxState;
+ memcpy( to->fp.i386_regs.regs, from->FloatSave.RegisterArea, sizeof(to->fp.i386_regs.regs) );
+ }
+ if (flags & WOW64_CONTEXT_DEBUG_REGISTERS)
+ {
+ to->flags |= SERVER_CTX_DEBUG_REGISTERS;
+ to->debug.i386_regs.dr0 = from->Dr0;
+ to->debug.i386_regs.dr1 = from->Dr1;
+ to->debug.i386_regs.dr2 = from->Dr2;
+ to->debug.i386_regs.dr3 = from->Dr3;
+ to->debug.i386_regs.dr6 = from->Dr6;
+ to->debug.i386_regs.dr7 = from->Dr7;
+ }
+ if (flags & WOW64_CONTEXT_EXTENDED_REGISTERS)
+ {
+ to->flags |= SERVER_CTX_EXTENDED_REGISTERS;
+ memcpy( to->ext.i386_regs, from->ExtendedRegisters, sizeof(to->ext.i386_regs) );
+ }
+ return STATUS_SUCCESS;
+}
+
+
+/***********************************************************************
+ * Wow64GetThreadContext [KERNEL32.@]
+ */
+BOOL WINAPI Wow64SetThreadContext( HANDLE handle, const WOW64_CONTEXT *context)
+{
+ NTSTATUS ret;
+ DWORD dummy, i;
+ context_t server_context;
+
+ wow64_context_to_server( &server_context, context );
+
+ SERVER_START_REQ( set_thread_context )
+ {
+ req->handle = wine_server_obj_handle( handle );
+ req->suspend = 1;
+ wine_server_add_data( req, &server_context, sizeof(server_context) );
+ ret = wine_server_call( req );
+ }
+ SERVER_END_REQ;
+
+ if (ret == STATUS_PENDING)
+ {
+ for (i = 0; i < 100; i++)
+ {
+ SERVER_START_REQ( set_thread_context )
+ {
+ req->handle = wine_server_obj_handle( handle );
+ req->suspend = 0;
+ wine_server_add_data( req, &server_context, sizeof(server_context) );
+ ret = wine_server_call( req );
+ }
+ SERVER_END_REQ;
+ if (ret == STATUS_PENDING)
+ {
+ LARGE_INTEGER timeout;
+ timeout.QuadPart = -10000;
+ NtDelayExecution( FALSE, &timeout );
+ }
+ else break;
+ }
+ NtResumeThread( handle, &dummy );
+ if (ret == STATUS_PENDING) ret = STATUS_ACCESS_DENIED;
+ }
+
+ if (ret) SetLastError( RtlNtStatusToDosError( ret ) );
+ return !ret;
+}
+
+
/***********************************************************************
* GetThreadContext [KERNEL32.@] Retrieves context of thread.
*
diff --git a/include/winbase.h b/include/winbase.h
index f7239b8..667df96 100644
--- a/include/winbase.h
+++ b/include/winbase.h
@@ -2708,6 +2708,7 @@ WINBASEAPI BOOL WINAPI Wow64DisableWow64FsRedirection(PVOID*);
WINBASEAPI BOOLEAN WINAPI Wow64EnableWow64FsRedirection(BOOLEAN);
WINBASEAPI BOOL WINAPI Wow64GetThreadContext(HANDLE, WOW64_CONTEXT *);
WINBASEAPI BOOL WINAPI Wow64RevertWow64FsRedirection(PVOID);
+WINBASEAPI BOOL WINAPI Wow64SetThreadContext(HANDLE, const WOW64_CONTEXT *);
WINADVAPI DWORD WINAPI WriteEncryptedFileRaw(PFE_IMPORT_FUNC,PVOID,PVOID);
WINBASEAPI BOOL WINAPI WriteFile(HANDLE,LPCVOID,DWORD,LPDWORD,LPOVERLAPPED);
WINBASEAPI BOOL WINAPI WriteFileEx(HANDLE,LPCVOID,DWORD,LPOVERLAPPED,LPOVERLAPPED_COMPLETION_ROUTINE);
--
2.7.4
More information about the wine-devel
mailing list