Alexandre Julliard : ntdll: Implement NtWow64Read/WriteVirtualMemory64().

Alexandre Julliard julliard at winehq.org
Tue Jun 29 15:58:26 CDT 2021


Module: wine
Branch: master
Commit: bfd2d1d77d8efd7dfc0613140e6281c924c3a1c7
URL:    https://source.winehq.org/git/wine.git/?a=commit;h=bfd2d1d77d8efd7dfc0613140e6281c924c3a1c7

Author: Alexandre Julliard <julliard at winehq.org>
Date:   Mon Jun 28 20:24:56 2021 +0200

ntdll: Implement NtWow64Read/WriteVirtualMemory64().

Signed-off-by: Alexandre Julliard <julliard at winehq.org>

---

 dlls/ntdll/ntdll.spec     |  4 +++
 dlls/ntdll/tests/wow64.c  | 42 +++++++++++++++++++++++++++++
 dlls/ntdll/unix/virtual.c | 67 +++++++++++++++++++++++++++++++++++++++++++++++
 include/winternl.h        | 16 +++++------
 4 files changed, 121 insertions(+), 8 deletions(-)

diff --git a/dlls/ntdll/ntdll.spec b/dlls/ntdll/ntdll.spec
index bd72f50b864..70e752eb43b 100644
--- a/dlls/ntdll/ntdll.spec
+++ b/dlls/ntdll/ntdll.spec
@@ -430,6 +430,8 @@
 @ stdcall -syscall NtWaitForSingleObject(long long ptr)
 @ stub NtWaitHighEventPair
 @ stub NtWaitLowEventPair
+@ stdcall -syscall -arch=win32 NtWow64ReadVirtualMemory64(long int64 ptr int64 ptr)
+@ stdcall -syscall -arch=win32 NtWow64WriteVirtualMemory64(long int64 ptr int64 ptr)
 @ stdcall -syscall NtWriteFile(long long ptr ptr ptr ptr long ptr ptr)
 @ stdcall -syscall NtWriteFileGather(long long ptr ptr ptr ptr long ptr ptr)
 @ stub NtWriteRequestData
@@ -1444,6 +1446,8 @@
 @ stdcall -private -syscall ZwWaitForSingleObject(long long ptr) NtWaitForSingleObject
 @ stub ZwWaitHighEventPair
 @ stub ZwWaitLowEventPair
+@ stdcall -syscall -arch=win32 ZwWow64ReadVirtualMemory64(long int64 ptr int64 ptr) NtWow64ReadVirtualMemory64
+@ stdcall -syscall -arch=win32 ZwWow64WriteVirtualMemory64(long int64 ptr int64 ptr) NtWow64WriteVirtualMemory64
 @ stdcall -private -syscall ZwWriteFile(long long ptr ptr ptr ptr long ptr ptr) NtWriteFile
 @ stdcall -private -syscall ZwWriteFileGather(long long ptr ptr ptr ptr long ptr ptr) NtWriteFileGather
 @ stub ZwWriteRequestData
diff --git a/dlls/ntdll/tests/wow64.c b/dlls/ntdll/tests/wow64.c
index 17082d2d329..8146ab0363e 100644
--- a/dlls/ntdll/tests/wow64.c
+++ b/dlls/ntdll/tests/wow64.c
@@ -27,6 +27,9 @@ static NTSTATUS (WINAPI *pRtlWow64GetProcessMachines)(HANDLE,WORD*,WORD*);
 static NTSTATUS (WINAPI *pRtlWow64IsWowGuestMachineSupported)(USHORT,BOOLEAN*);
 #ifdef _WIN64
 static NTSTATUS (WINAPI *pRtlWow64GetCpuAreaInfo)(WOW64_CPURESERVED*,ULONG,WOW64_CPU_AREA_INFO*);
+#else
+static NTSTATUS (WINAPI *pNtWow64ReadVirtualMemory64)(HANDLE,ULONG64,void*,ULONG64,ULONG64*);
+static NTSTATUS (WINAPI *pNtWow64WriteVirtualMemory64)(HANDLE,ULONG64,const void *,ULONG64,ULONG64*);
 #endif
 
 static BOOL is_wow64;
@@ -44,6 +47,9 @@ static void init(void)
     GET_PROC( RtlWow64IsWowGuestMachineSupported );
 #ifdef _WIN64
     GET_PROC( RtlWow64GetCpuAreaInfo );
+#else
+    GET_PROC( NtWow64ReadVirtualMemory64 );
+    GET_PROC( NtWow64WriteVirtualMemory64 );
 #endif
 #undef GET_PROC
 }
@@ -453,6 +459,40 @@ static void test_cpu_area(void)
     else win_skip( "RtlWow64GetCpuAreaInfo not supported\n" );
 }
 
+#else  /* _WIN64 */
+
+static void test_nt_wow64(void)
+{
+    const char str[] = "hello wow64";
+    char buffer[100];
+    NTSTATUS status;
+    ULONG64 res;
+    HANDLE process = OpenProcess( PROCESS_ALL_ACCESS, FALSE, GetCurrentProcessId() );
+
+    ok( process != 0, "failed to open current process %u\n", GetLastError() );
+    if (pNtWow64ReadVirtualMemory64)
+    {
+        status = pNtWow64ReadVirtualMemory64( process, (ULONG_PTR)str, buffer, sizeof(str), &res );
+        ok( !status, "NtWow64ReadVirtualMemory64 failed %x\n", status );
+        ok( res == sizeof(str), "wrong size %s\n", wine_dbgstr_longlong(res) );
+        ok( !strcmp( buffer, str ), "wrong data %s\n", debugstr_a(buffer) );
+        status = pNtWow64WriteVirtualMemory64( process, (ULONG_PTR)buffer, " bye ", 5, &res );
+        ok( !status, "NtWow64WriteVirtualMemory64 failed %x\n", status );
+        ok( res == 5, "wrong size %s\n", wine_dbgstr_longlong(res) );
+        ok( !strcmp( buffer, " bye  wow64" ), "wrong data %s\n", debugstr_a(buffer) );
+        /* current process pseudo-handle is broken on some Windows versions */
+        status = pNtWow64ReadVirtualMemory64( GetCurrentProcess(), (ULONG_PTR)str, buffer, sizeof(str), &res );
+        ok( !status || broken( status == STATUS_INVALID_HANDLE ),
+            "NtWow64ReadVirtualMemory64 failed %x\n", status );
+        status = pNtWow64WriteVirtualMemory64( GetCurrentProcess(), (ULONG_PTR)buffer, " bye ", 5, &res );
+        ok( !status || broken( status == STATUS_INVALID_HANDLE ),
+            "NtWow64WriteVirtualMemory64 failed %x\n", status );
+    }
+    else win_skip( "NtWow64ReadVirtualMemory64 not supported\n" );
+
+    NtClose( process );
+}
+
 #endif  /* _WIN64 */
 
 
@@ -463,5 +503,7 @@ START_TEST(wow64)
     test_peb_teb();
 #ifdef _WIN64
     test_cpu_area();
+#else
+    test_nt_wow64();
 #endif
 }
diff --git a/dlls/ntdll/unix/virtual.c b/dlls/ntdll/unix/virtual.c
index 52af195aa56..d42cf74208a 100644
--- a/dlls/ntdll/unix/virtual.c
+++ b/dlls/ntdll/unix/virtual.c
@@ -4833,3 +4833,70 @@ NTSTATUS WINAPI NtCreatePagingFile( UNICODE_STRING *name, LARGE_INTEGER *min_siz
     FIXME( "(%s %p %p %p) stub\n", debugstr_us(name), min_size, max_size, actual_size );
     return STATUS_SUCCESS;
 }
+
+#ifndef _WIN64
+
+/***********************************************************************
+ *             NtWow64ReadVirtualMemory64   (NTDLL.@)
+ *             ZwWow64ReadVirtualMemory64   (NTDLL.@)
+ */
+NTSTATUS WINAPI NtWow64ReadVirtualMemory64( HANDLE process, ULONG64 addr, void *buffer,
+                                            ULONG64 size, ULONG64 *bytes_read )
+{
+    NTSTATUS status;
+
+    if (size > MAXLONG) size = MAXLONG;
+
+    if (virtual_check_buffer_for_write( buffer, size ))
+    {
+        SERVER_START_REQ( read_process_memory )
+        {
+            req->handle = wine_server_obj_handle( process );
+            req->addr   = addr;
+            wine_server_set_reply( req, buffer, size );
+            if ((status = wine_server_call( req ))) size = 0;
+        }
+        SERVER_END_REQ;
+    }
+    else
+    {
+        status = STATUS_ACCESS_VIOLATION;
+        size = 0;
+    }
+    if (bytes_read) *bytes_read = size;
+    return status;
+}
+
+
+/***********************************************************************
+ *             NtWow64WriteVirtualMemory64   (NTDLL.@)
+ *             ZwWow64WriteVirtualMemory64   (NTDLL.@)
+ */
+NTSTATUS WINAPI NtWow64WriteVirtualMemory64( HANDLE process, ULONG64 addr, const void *buffer,
+                                             ULONG64 size, ULONG64 *bytes_written )
+{
+    NTSTATUS status;
+
+    if (size > MAXLONG) size = MAXLONG;
+
+    if (virtual_check_buffer_for_read( buffer, size ))
+    {
+        SERVER_START_REQ( write_process_memory )
+        {
+            req->handle     = wine_server_obj_handle( process );
+            req->addr       = addr;
+            wine_server_add_data( req, buffer, size );
+            if ((status = wine_server_call( req ))) size = 0;
+        }
+        SERVER_END_REQ;
+    }
+    else
+    {
+        status = STATUS_PARTIAL_COPY;
+        size = 0;
+    }
+    if (bytes_written) *bytes_written = size;
+    return status;
+}
+
+#endif  /* _WIN64 */
diff --git a/include/winternl.h b/include/winternl.h
index 7221c0632b0..042936f4a7f 100644
--- a/include/winternl.h
+++ b/include/winternl.h
@@ -4396,19 +4396,19 @@ NTSYSAPI NTSTATUS  WINAPI RtlpUnWaitCriticalSection(RTL_CRITICAL_SECTION *);
 NTSYSAPI NTSTATUS  WINAPI vDbgPrintEx(ULONG,ULONG,LPCSTR,__ms_va_list);
 NTSYSAPI NTSTATUS  WINAPI vDbgPrintExWithPrefix(LPCSTR,ULONG,ULONG,LPCSTR,__ms_va_list);
 
-#ifdef _WIN64
-NTSYSAPI NTSTATUS  WINAPI RtlWow64GetCpuAreaInfo(WOW64_CPURESERVED*,ULONG,WOW64_CPU_AREA_INFO*);
-NTSYSAPI NTSTATUS  WINAPI RtlWow64GetThreadContext(HANDLE,WOW64_CONTEXT*);
-NTSYSAPI NTSTATUS  WINAPI RtlWow64SetThreadContext(HANDLE,const WOW64_CONTEXT*);
-#endif
-
 #ifndef __WINE_USE_MSVCRT
 NTSYSAPI int __cdecl _strnicmp(LPCSTR,LPCSTR,size_t);
 #endif
 
-/* 32-bit only functions */
+/* 32-bit or 64-bit only functions */
 
-#ifndef _WIN64
+#ifdef _WIN64
+NTSYSAPI NTSTATUS  WINAPI RtlWow64GetCpuAreaInfo(WOW64_CPURESERVED*,ULONG,WOW64_CPU_AREA_INFO*);
+NTSYSAPI NTSTATUS  WINAPI RtlWow64GetThreadContext(HANDLE,WOW64_CONTEXT*);
+NTSYSAPI NTSTATUS  WINAPI RtlWow64SetThreadContext(HANDLE,const WOW64_CONTEXT*);
+#else
+NTSYSAPI NTSTATUS  WINAPI NtWow64ReadVirtualMemory64(HANDLE,ULONG64,void*,ULONG64,ULONG64*);
+NTSYSAPI NTSTATUS  WINAPI NtWow64WriteVirtualMemory64(HANDLE,ULONG64,const void*,ULONG64,ULONG64*);
 NTSYSAPI LONGLONG  WINAPI RtlConvertLongToLargeInteger(LONG);
 NTSYSAPI ULONGLONG WINAPI RtlConvertUlongToLargeInteger(ULONG);
 NTSYSAPI LONGLONG  WINAPI RtlEnlargedIntegerMultiply(INT,INT);




More information about the wine-cvs mailing list