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);