From: Jinoh Kang jinoh.kang.kr@gmail.com
Signed-off-by: Jinoh Kang jinoh.kang.kr@gmail.com --- dlls/ntdll/ntdll.spec | 2 ++ dlls/ntdll/unix/loader.c | 1 + dlls/ntdll/unix/virtual.c | 59 +++++++++++++++++++++++++++++++++++++++ dlls/wow64/struct32.h | 6 ++++ dlls/wow64/syscall.h | 1 + dlls/wow64/virtual.c | 46 ++++++++++++++++++++++++++++++ 6 files changed, 115 insertions(+)
diff --git a/dlls/ntdll/ntdll.spec b/dlls/ntdll/ntdll.spec index 89b05728951..299d2195800 100644 --- a/dlls/ntdll/ntdll.spec +++ b/dlls/ntdll/ntdll.spec @@ -388,6 +388,7 @@ @ stdcall -syscall NtSetInformationProcess(long long ptr long) @ stdcall -syscall NtSetInformationThread(long long ptr long) @ stdcall -syscall NtSetInformationToken(long long ptr long) +@ stdcall -syscall NtSetInformationVirtualMemory(long long ptr ptr ptr long) @ stdcall -syscall NtSetIntervalProfile(long long) @ stdcall -syscall NtSetIoCompletion(ptr long long long long) @ stdcall -syscall NtSetLdtEntries(long int64 long int64) @@ -1416,6 +1417,7 @@ @ stdcall -private -syscall ZwSetInformationProcess(long long ptr long) NtSetInformationProcess @ stdcall -private -syscall ZwSetInformationThread(long long ptr long) NtSetInformationThread @ stdcall -private -syscall ZwSetInformationToken(long long ptr long) NtSetInformationToken +@ stdcall -private -syscall ZwSetInformationVirtualMemory(long long ptr ptr ptr long) NtSetInformationVirtualMemory @ stdcall -private -syscall ZwSetIntervalProfile(long long) NtSetIntervalProfile @ stdcall -private -syscall ZwSetIoCompletion(ptr long long long long) NtSetIoCompletion @ stdcall -private -syscall ZwSetLdtEntries(long int64 long int64) NtSetLdtEntries diff --git a/dlls/ntdll/unix/loader.c b/dlls/ntdll/unix/loader.c index 2fd4acc06b9..f58a716d08c 100644 --- a/dlls/ntdll/unix/loader.c +++ b/dlls/ntdll/unix/loader.c @@ -310,6 +310,7 @@ static void * const syscalls[] = NtSetInformationProcess, NtSetInformationThread, NtSetInformationToken, + NtSetInformationVirtualMemory, NtSetIntervalProfile, NtSetIoCompletion, NtSetLdtEntries, diff --git a/dlls/ntdll/unix/virtual.c b/dlls/ntdll/unix/virtual.c index a93d5b4174a..96a5e095d16 100644 --- a/dlls/ntdll/unix/virtual.c +++ b/dlls/ntdll/unix/virtual.c @@ -4931,6 +4931,65 @@ NTSTATUS WINAPI NtAreMappedFilesTheSame(PVOID addr1, PVOID addr2) }
+static NTSTATUS prefetch_memory( HANDLE process, ULONG_PTR count, + PMEMORY_RANGE_ENTRY addresses, ULONG flags ) +{ + ULONG_PTR i; + PVOID base; + SIZE_T size; + static unsigned int once; + + if (!once++) + { + FIXME( "(process=%p,flags=%u) NtSetInformationVirtualMemory(VmPrefetchInformation) partial stub\n", + process, flags ); + } + + for (i = 0; i < count; i++) + { + if (!addresses[i].NumberOfBytes) return STATUS_INVALID_PARAMETER_4; + } + + if (process != NtCurrentProcess()) return STATUS_SUCCESS; + + for (i = 0; i < count; i++) + { + base = ROUND_ADDR( addresses[i].VirtualAddress, page_mask ); + size = ROUND_SIZE( addresses[i].VirtualAddress, addresses[i].NumberOfBytes ); + madvise( base, size, MADV_WILLNEED ); + } + + return STATUS_SUCCESS; +} + +/*********************************************************************** + * NtSetInformationVirtualMemory (NTDLL.@) + * ZwSetInformationVirtualMemory (NTDLL.@) + */ +NTSTATUS WINAPI NtSetInformationVirtualMemory( HANDLE process, + VIRTUAL_MEMORY_INFORMATION_CLASS info_class, + ULONG_PTR count, PMEMORY_RANGE_ENTRY addresses, + PVOID ptr, ULONG size ) +{ + TRACE("(%p, info_class=%d, %lu, %p, %p, %u)\n", + process, info_class, count, addresses, ptr, size); + + switch (info_class) + { + case VmPrefetchInformation: + if (!ptr) return STATUS_INVALID_PARAMETER_5; + if (size != sizeof(ULONG)) return STATUS_INVALID_PARAMETER_6; + if (!count) return STATUS_INVALID_PARAMETER_3; + return prefetch_memory( process, count, addresses, *(ULONG *)ptr ); + + default: + FIXME("(%p,info_class=%d,%lu,%p,%p,%u) Unknown information class\n", + process, info_class, count, addresses, ptr, size); + return STATUS_INVALID_PARAMETER_2; + } +} + + /********************************************************************** * NtFlushInstructionCache (NTDLL.@) */ diff --git a/dlls/wow64/struct32.h b/dlls/wow64/struct32.h index b096c8d587b..91acc26436f 100644 --- a/dlls/wow64/struct32.h +++ b/dlls/wow64/struct32.h @@ -650,6 +650,12 @@ typedef struct ULONG Reserved4; } SYSTEM_EXTENDED_THREAD_INFORMATION32;
+typedef struct +{ + ULONG VirtualAddress; + ULONG NumberOfBytes; +} MEMORY_RANGE_ENTRY32; + struct __server_iovec32 { ULONG ptr; diff --git a/dlls/wow64/syscall.h b/dlls/wow64/syscall.h index bd107ce0ef5..65fbca89f4f 100644 --- a/dlls/wow64/syscall.h +++ b/dlls/wow64/syscall.h @@ -211,6 +211,7 @@ SYSCALL_ENTRY( NtSetInformationProcess ) \ SYSCALL_ENTRY( NtSetInformationThread ) \ SYSCALL_ENTRY( NtSetInformationToken ) \ + SYSCALL_ENTRY( NtSetInformationVirtualMemory ) \ SYSCALL_ENTRY( NtSetIntervalProfile ) \ SYSCALL_ENTRY( NtSetIoCompletion ) \ SYSCALL_ENTRY( NtSetLdtEntries ) \ diff --git a/dlls/wow64/virtual.c b/dlls/wow64/virtual.c index c21464857fa..8b69432829d 100644 --- a/dlls/wow64/virtual.c +++ b/dlls/wow64/virtual.c @@ -33,6 +33,21 @@ WINE_DEFAULT_DEBUG_CHANNEL(wow);
+static MEMORY_RANGE_ENTRY *memory_range_entry_array_32to64( const MEMORY_RANGE_ENTRY32 *addresses32, + ULONG count ) +{ + MEMORY_RANGE_ENTRY *addresses = Wow64AllocateTemp( sizeof(MEMORY_RANGE_ENTRY) * count ); + ULONG i; + + for (i = 0; i < count; i++) + { + addresses[i].VirtualAddress = ULongToPtr( addresses32[i].VirtualAddress ); + addresses[i].NumberOfBytes = addresses32[i].NumberOfBytes; + } + + return addresses; +} + /********************************************************************** * wow64_NtAllocateVirtualMemory */ @@ -470,6 +485,37 @@ NTSTATUS WINAPI wow64_NtResetWriteWatch( UINT *args ) }
+/********************************************************************** + * wow64_NtSetInformationVirtualMemory + */ +NTSTATUS WINAPI wow64_NtSetInformationVirtualMemory( UINT *args ) +{ + HANDLE process = get_handle( &args ); + VIRTUAL_MEMORY_INFORMATION_CLASS info_class = get_ulong( &args ); + ULONG count = get_ulong( &args ); + MEMORY_RANGE_ENTRY32 *addresses32 = get_ptr( &args ); + PVOID ptr = get_ptr( &args ); + ULONG len = get_ulong( &args ); + + MEMORY_RANGE_ENTRY *addresses; + + if (!count) return STATUS_INVALID_PARAMETER_3; + addresses = memory_range_entry_array_32to64( addresses32, count ); + + switch (info_class) + { + case VmPrefetchInformation: + break; + default: + FIXME( "(%p,info_class=%u,%lu,%p,%p,%lu): not implemented\n", + process, info_class, count, addresses32, ptr, len ); + return STATUS_INVALID_PARAMETER_2; + } + + return NtSetInformationVirtualMemory( process, info_class, count, addresses, ptr, len ); +} + + /********************************************************************** * wow64_NtSetLdtEntries */