[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