Signed-off-by: Jinoh Kang jinoh.kang.kr@gmail.com --- include/winbase.h | 6 ++++++ include/winnt.h | 4 ++-- 2 files changed, 8 insertions(+), 2 deletions(-)
diff --git a/include/winbase.h b/include/winbase.h index 2928385bde6..3f987c05fde 100644 --- a/include/winbase.h +++ b/include/winbase.h @@ -1757,6 +1757,12 @@ typedef struct _WIN32_FIND_STREAM_DATA { WCHAR cStreamName[MAX_PATH + 36]; } WIN32_FIND_STREAM_DATA,*PWIN32_FIND_STREAM_DATA;
+typedef struct _WIN32_MEMORY_RANGE_ENTRY +{ + PVOID VirtualAddress; + SIZE_T NumberOfBytes; +} WIN32_MEMORY_RANGE_ENTRY, *PWIN32_MEMORY_RANGE_ENTRY; + WINBASEAPI BOOL WINAPI ActivateActCtx(HANDLE,ULONG_PTR *); WINADVAPI BOOL WINAPI AddAccessAllowedAce(PACL,DWORD,DWORD,PSID); WINADVAPI BOOL WINAPI AddAccessAllowedAceEx(PACL,DWORD,DWORD,DWORD,PSID); diff --git a/include/winnt.h b/include/winnt.h index 2ab74ab123c..3a2e93675a3 100644 --- a/include/winnt.h +++ b/include/winnt.h @@ -776,11 +776,11 @@ typedef struct DECLSPEC_ALIGN(8) MEM_EXTENDED_PARAMETER { } DUMMYUNIONNAME; } MEM_EXTENDED_PARAMETER, *PMEM_EXTENDED_PARAMETER;
-typedef struct _WIN32_MEMORY_RANGE_ENTRY +typedef struct _MEMORY_RANGE_ENTRY { PVOID VirtualAddress; SIZE_T NumberOfBytes; -} WIN32_MEMORY_RANGE_ENTRY, *PWIN32_MEMORY_RANGE_ENTRY; +} MEMORY_RANGE_ENTRY, *PMEMORY_RANGE_ENTRY;
#define PAGE_NOACCESS 0x01 #define PAGE_READONLY 0x02
Signed-off-by: Jinoh Kang jinoh.kang.kr@gmail.com --- include/winternl.h | 8 ++++++++ tools/winapi/win32.api | 1 + 2 files changed, 9 insertions(+)
diff --git a/include/winternl.h b/include/winternl.h index cfd83f16337..b276fc836d3 100644 --- a/include/winternl.h +++ b/include/winternl.h @@ -1969,6 +1969,13 @@ typedef struct _TIMER_BASIC_INFORMATION BOOLEAN TimerState; } TIMER_BASIC_INFORMATION, *PTIMER_BASIC_INFORMATION;
+typedef enum +{ + VmPrefetchInformation, + VmPagePriorityInformation, + VmCfgCallTargetInformation +} VIRTUAL_MEMORY_INFORMATION_CLASS, *PVIRTUAL_MEMORY_INFORMATION_CLASS; +
/* return type of RtlDetermineDosPathNameType_U (FIXME: not the correct names) */ typedef enum @@ -4063,6 +4070,7 @@ NTSYSAPI NTSTATUS WINAPI NtSetInformationObject(HANDLE, OBJECT_INFORMATION_CLAS NTSYSAPI NTSTATUS WINAPI NtSetInformationProcess(HANDLE,PROCESS_INFORMATION_CLASS,PVOID,ULONG); NTSYSAPI NTSTATUS WINAPI NtSetInformationThread(HANDLE,THREADINFOCLASS,LPCVOID,ULONG); NTSYSAPI NTSTATUS WINAPI NtSetInformationToken(HANDLE,TOKEN_INFORMATION_CLASS,PVOID,ULONG); +NTSYSAPI NTSTATUS WINAPI NtSetInformationVirtualMemory(HANDLE,VIRTUAL_MEMORY_INFORMATION_CLASS,ULONG_PTR,PMEMORY_RANGE_ENTRY,PVOID,ULONG); NTSYSAPI NTSTATUS WINAPI NtSetIntervalProfile(ULONG,KPROFILE_SOURCE); NTSYSAPI NTSTATUS WINAPI NtSetIoCompletion(HANDLE,ULONG_PTR,ULONG_PTR,NTSTATUS,SIZE_T); NTSYSAPI NTSTATUS WINAPI NtSetLdtEntries(ULONG,LDT_ENTRY,ULONG,LDT_ENTRY); diff --git a/tools/winapi/win32.api b/tools/winapi/win32.api index d9b77dbce39..6e0c5da6f26 100644 --- a/tools/winapi/win32.api +++ b/tools/winapi/win32.api @@ -3245,6 +3245,7 @@ TOKEN_TYPE UCHAR UINT ULONG +VIRTUAL_MEMORY_INFORMATION_CLASS WCHAR WORD int
Signed-off-by: Jinoh Kang jinoh.kang.kr@gmail.com --- dlls/ntdll/tests/virtual.c | 117 +++++++++++++++++++++++++++++++++++++ 1 file changed, 117 insertions(+)
diff --git a/dlls/ntdll/tests/virtual.c b/dlls/ntdll/tests/virtual.c index adc9b1ae6dc..93be6a1006b 100644 --- a/dlls/ntdll/tests/virtual.c +++ b/dlls/ntdll/tests/virtual.c @@ -39,6 +39,9 @@ static void * (WINAPI *pRtlFindExportedRoutineByName)(HMODULE,const char*); static BOOL (WINAPI *pIsWow64Process)(HANDLE, PBOOL); static NTSTATUS (WINAPI *pNtAllocateVirtualMemoryEx)(HANDLE, PVOID *, SIZE_T *, ULONG, ULONG, MEM_EXTENDED_PARAMETER *, ULONG); +static NTSTATUS (WINAPI *pNtSetInformationVirtualMemory)(HANDLE, VIRTUAL_MEMORY_INFORMATION_CLASS, + ULONG_PTR, PMEMORY_RANGE_ENTRY, + PVOID, ULONG); static const BOOL is_win64 = sizeof(void*) != sizeof(int); static BOOL is_wow64;
@@ -1132,6 +1135,118 @@ static void test_syscalls(void) UnmapViewOfFile( ptr ); }
+static void test_prefetch(void) +{ + NTSTATUS status; + MEMORY_RANGE_ENTRY entries[2] = {{ 0 }}; + ULONG reservedarg = 0; + char stackmem[] = "Test stack mem"; + static char testmem[] = "Test memory range data"; + + if (!pNtSetInformationVirtualMemory) + { + skip("no NtSetInformationVirtualMemory in ntdll"); + return; + } + + status = pNtSetInformationVirtualMemory( NtCurrentProcess(), -1UL, 0, NULL, NULL, 0); + ok( status == STATUS_INVALID_PARAMETER_2, + "NtSetInformationVirtualMemory unexpected status on invalid info class (1): %08x\n", status); + + status = pNtSetInformationVirtualMemory( NtCurrentProcess(), -1UL, 1, NULL, NULL, 32); + ok( status == STATUS_INVALID_PARAMETER_2, + "NtSetInformationVirtualMemory unexpected status on invalid info class (2): %08x\n", status); + + status = pNtSetInformationVirtualMemory( NtCurrentProcess(), VmPrefetchInformation, + 1, entries, NULL, 0 ); + ok( status == STATUS_INVALID_PARAMETER_5, + "NtSetInformationVirtualMemory unexpected status on NULL info data (1): %08x\n", status); + + status = pNtSetInformationVirtualMemory( NtCurrentProcess(), VmPrefetchInformation, + 1, NULL, NULL, 0 ); + ok( status == STATUS_INVALID_PARAMETER_5, + "NtSetInformationVirtualMemory unexpected status on NULL info data (2): %08x\n", status); + + status = pNtSetInformationVirtualMemory( NtCurrentProcess(), VmPrefetchInformation, + 0, NULL, NULL, 0 ); + ok( status == STATUS_INVALID_PARAMETER_5, + "NtSetInformationVirtualMemory unexpected status on NULL info data (3): %08x\n", status); + + status = pNtSetInformationVirtualMemory( NtCurrentProcess(), VmPrefetchInformation, + 1, entries, &reservedarg, sizeof(reservedarg) * 2 ); + ok( status == STATUS_INVALID_PARAMETER_6, + "NtSetInformationVirtualMemory unexpected status on extended info data (1): %08x\n", status); + + status = pNtSetInformationVirtualMemory( NtCurrentProcess(), VmPrefetchInformation, + 0, NULL, &reservedarg, sizeof(reservedarg) * 2 ); + ok( status == STATUS_INVALID_PARAMETER_6, + "NtSetInformationVirtualMemory unexpected status on extended info data (2): %08x\n", status); + + status = pNtSetInformationVirtualMemory( NtCurrentProcess(), VmPrefetchInformation, + 1, entries, &reservedarg, sizeof(reservedarg) / 2 ); + ok( status == STATUS_INVALID_PARAMETER_6, + "NtSetInformationVirtualMemory unexpected status on shrunk info data (1): %08x\n", status); + + status = pNtSetInformationVirtualMemory( NtCurrentProcess(), VmPrefetchInformation, + 0, NULL, &reservedarg, sizeof(reservedarg) / 2 ); + ok( status == STATUS_INVALID_PARAMETER_6, + "NtSetInformationVirtualMemory unexpected status on shrunk info data (2): %08x\n", status); + + status = pNtSetInformationVirtualMemory( NtCurrentProcess(), VmPrefetchInformation, + 0, NULL, &reservedarg, sizeof(reservedarg) ); + ok( status == STATUS_INVALID_PARAMETER_3, + "NtSetInformationVirtualMemory unexpected status on 0 entries: %08x\n", status); + + status = pNtSetInformationVirtualMemory( NtCurrentProcess(), VmPrefetchInformation, + 1, NULL, &reservedarg, sizeof(reservedarg) ); + ok( status == STATUS_ACCESS_VIOLATION, + "NtSetInformationVirtualMemory unexpected status on NULL entries: %08x\n", status); + + entries[0].VirtualAddress = NULL; + entries[0].NumberOfBytes = 0; + status = pNtSetInformationVirtualMemory( NtCurrentProcess(), VmPrefetchInformation, + 1, entries, &reservedarg, sizeof(reservedarg) ); + ok( status == STATUS_INVALID_PARAMETER_4, + "NtSetInformationVirtualMemory unexpected status on 1 empty entry: %08x\n", status); + + entries[0].VirtualAddress = NULL; + entries[0].NumberOfBytes = page_size; + status = pNtSetInformationVirtualMemory( NtCurrentProcess(), VmPrefetchInformation, + 1, entries, &reservedarg, sizeof(reservedarg) ); + ok( status == STATUS_SUCCESS, + "NtSetInformationVirtualMemory unexpected status on 1 NULL address entry: %08x\n", status); + + entries[0].VirtualAddress = (PVOID)((ULONG_PTR)testmem & -(ULONG_PTR)page_size); + entries[0].NumberOfBytes = page_size; + status = pNtSetInformationVirtualMemory( NtCurrentProcess(), VmPrefetchInformation, + 1, entries, &reservedarg, sizeof(reservedarg) ); + ok( status == STATUS_SUCCESS, + "NtSetInformationVirtualMemory unexpected status on 1 page-aligned entry: %08x\n", status); + + entries[0].VirtualAddress = testmem; + entries[0].NumberOfBytes = sizeof(testmem); + status = pNtSetInformationVirtualMemory( NtCurrentProcess(), VmPrefetchInformation, + 1, entries, &reservedarg, sizeof(reservedarg) ); + ok( status == STATUS_SUCCESS, + "NtSetInformationVirtualMemory unexpected status on 1 entry: %08x\n", status); + + entries[0].VirtualAddress = NULL; + entries[0].NumberOfBytes = page_size; + status = pNtSetInformationVirtualMemory( NtCurrentProcess(), VmPrefetchInformation, + 1, entries, &reservedarg, sizeof(reservedarg) ); + ok( status == STATUS_SUCCESS, + "NtSetInformationVirtualMemory unexpected status on 1 unmapped entry: %08x\n", status); + + entries[0].VirtualAddress = (PVOID)((ULONG_PTR)testmem & -(ULONG_PTR)page_size); + entries[0].NumberOfBytes = page_size; + entries[1].VirtualAddress = (PVOID)((ULONG_PTR)stackmem & -(ULONG_PTR)page_size); + entries[1].NumberOfBytes = page_size; + status = pNtSetInformationVirtualMemory( NtCurrentProcess(), VmPrefetchInformation, + 2, entries, &reservedarg, sizeof(reservedarg) ); + ok( status == STATUS_SUCCESS, + "NtSetInformationVirtualMemory unexpected status on 2 page-aligned entries: %08x\n", status); +} + START_TEST(virtual) { HMODULE mod; @@ -1160,6 +1275,7 @@ START_TEST(virtual) pRtlFindExportedRoutineByName = (void *)GetProcAddress(mod, "RtlFindExportedRoutineByName"); pRtlGetEnabledExtendedFeatures = (void *)GetProcAddress(mod, "RtlGetEnabledExtendedFeatures"); pNtAllocateVirtualMemoryEx = (void *)GetProcAddress(mod, "NtAllocateVirtualMemoryEx"); + pNtSetInformationVirtualMemory = (void *)GetProcAddress(mod, "NtSetInformationVirtualMemory");
NtQuerySystemInformation(SystemBasicInformation, &sbi, sizeof(sbi), NULL); trace("system page size %#x\n", sbi.PageSize); @@ -1171,4 +1287,5 @@ START_TEST(virtual) test_NtMapViewOfSection(); test_user_shared_data(); test_syscalls(); + test_prefetch(); }
Hi,
While running your changed tests, I think I found new failures. Being a bot and all I'm not very good at pattern recognition, so I might be wrong, but could you please double-check?
Full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=102747
Your paranoid android.
=== w7u_2qxl (32 bit report) ===
Report validation errors: ntdll:virtual has no test summary line (early exit of the main process?) ntdll:virtual has unaccounted for skip messages
=== w7u_adm (32 bit report) ===
Report validation errors: ntdll:virtual has no test summary line (early exit of the main process?) ntdll:virtual has unaccounted for skip messages
=== w7u_el (32 bit report) ===
Report validation errors: ntdll:virtual has no test summary line (early exit of the main process?) ntdll:virtual has unaccounted for skip messages
=== w864 (32 bit report) ===
ntdll: virtual.c:1153: Test failed: NtSetInformationVirtualMemory unexpected status on invalid info class (1): c00000f1 virtual.c:1157: Test failed: NtSetInformationVirtualMemory unexpected status on invalid info class (2): c0000005 virtual.c:1167: Test failed: NtSetInformationVirtualMemory unexpected status on NULL info data (2): c0000005 virtual.c:1172: Test failed: NtSetInformationVirtualMemory unexpected status on NULL info data (3): c00000f1 virtual.c:1182: Test failed: NtSetInformationVirtualMemory unexpected status on extended info data (2): c00000f1 virtual.c:1192: Test failed: NtSetInformationVirtualMemory unexpected status on shrunk info data (2): c00000f1
=== w1064v1507 (32 bit report) ===
ntdll: virtual.c:1153: Test failed: NtSetInformationVirtualMemory unexpected status on invalid info class (1): c00000f1 virtual.c:1157: Test failed: NtSetInformationVirtualMemory unexpected status on invalid info class (2): c0000005 virtual.c:1162: Test failed: NtSetInformationVirtualMemory unexpected status on NULL info data (1): c00000f4 virtual.c:1167: Test failed: NtSetInformationVirtualMemory unexpected status on NULL info data (2): c0000005 virtual.c:1172: Test failed: NtSetInformationVirtualMemory unexpected status on NULL info data (3): c00000f1 virtual.c:1182: Test failed: NtSetInformationVirtualMemory unexpected status on extended info data (2): c00000f1 virtual.c:1192: Test failed: NtSetInformationVirtualMemory unexpected status on shrunk info data (2): c00000f1 virtual.c:1209: Test failed: NtSetInformationVirtualMemory unexpected status on 1 empty entry: c00000f4 virtual.c:1216: Test failed: NtSetInformationVirtualMemory unexpected status on 1 NULL address entry: c00000f4 virtual.c:1223: Test failed: NtSetInformationVirtualMemory unexpected status on 1 page-aligned entry: c00000f4 virtual.c:1230: Test failed: NtSetInformationVirtualMemory unexpected status on 1 entry: c00000f4 virtual.c:1237: Test failed: NtSetInformationVirtualMemory unexpected status on 1 unmapped entry: c00000f4 virtual.c:1246: Test failed: NtSetInformationVirtualMemory unexpected status on 2 page-aligned entries: c00000f4
=== w1064v1809 (32 bit report) ===
ntdll: virtual.c:1153: Test failed: NtSetInformationVirtualMemory unexpected status on invalid info class (1): c00000f1 virtual.c:1157: Test failed: NtSetInformationVirtualMemory unexpected status on invalid info class (2): c0000005 virtual.c:1167: Test failed: NtSetInformationVirtualMemory unexpected status on NULL info data (2): c0000005 virtual.c:1172: Test failed: NtSetInformationVirtualMemory unexpected status on NULL info data (3): c00000f1 virtual.c:1182: Test failed: NtSetInformationVirtualMemory unexpected status on extended info data (2): c00000f1 virtual.c:1192: Test failed: NtSetInformationVirtualMemory unexpected status on shrunk info data (2): c00000f1
=== w1064 (32 bit report) ===
ntdll: virtual.c:1153: Test failed: NtSetInformationVirtualMemory unexpected status on invalid info class (1): c00000f1 virtual.c:1157: Test failed: NtSetInformationVirtualMemory unexpected status on invalid info class (2): c0000005 virtual.c:1167: Test failed: NtSetInformationVirtualMemory unexpected status on NULL info data (2): c0000005 virtual.c:1172: Test failed: NtSetInformationVirtualMemory unexpected status on NULL info data (3): c00000f1 virtual.c:1182: Test failed: NtSetInformationVirtualMemory unexpected status on extended info data (2): c00000f1 virtual.c:1192: Test failed: NtSetInformationVirtualMemory unexpected status on shrunk info data (2): c00000f1
=== w1064_tsign (32 bit report) ===
ntdll: virtual.c:1153: Test failed: NtSetInformationVirtualMemory unexpected status on invalid info class (1): c00000f1 virtual.c:1157: Test failed: NtSetInformationVirtualMemory unexpected status on invalid info class (2): c0000005 virtual.c:1167: Test failed: NtSetInformationVirtualMemory unexpected status on NULL info data (2): c0000005 virtual.c:1172: Test failed: NtSetInformationVirtualMemory unexpected status on NULL info data (3): c00000f1 virtual.c:1182: Test failed: NtSetInformationVirtualMemory unexpected status on extended info data (2): c00000f1 virtual.c:1192: Test failed: NtSetInformationVirtualMemory unexpected status on shrunk info data (2): c00000f1
=== w10pro64 (32 bit report) ===
ntdll: virtual.c:1153: Test failed: NtSetInformationVirtualMemory unexpected status on invalid info class (1): c00000f1 virtual.c:1157: Test failed: NtSetInformationVirtualMemory unexpected status on invalid info class (2): c0000005 virtual.c:1167: Test failed: NtSetInformationVirtualMemory unexpected status on NULL info data (2): c0000005 virtual.c:1172: Test failed: NtSetInformationVirtualMemory unexpected status on NULL info data (3): c00000f1 virtual.c:1182: Test failed: NtSetInformationVirtualMemory unexpected status on extended info data (2): c00000f1 virtual.c:1192: Test failed: NtSetInformationVirtualMemory unexpected status on shrunk info data (2): c00000f1
=== debiant2 (32 bit report) ===
Report validation errors: ntdll:virtual has no test summary line (early exit of the main process?) ntdll:virtual has unaccounted for todo messages ntdll:virtual has unaccounted for skip messages
=== debiant2 (32 bit Arabic:Morocco report) ===
Report validation errors: ntdll:virtual has no test summary line (early exit of the main process?) ntdll:virtual has unaccounted for todo messages ntdll:virtual has unaccounted for skip messages
=== debiant2 (32 bit German report) ===
Report validation errors: ntdll:virtual has no test summary line (early exit of the main process?) ntdll:virtual has unaccounted for todo messages ntdll:virtual has unaccounted for skip messages
=== debiant2 (32 bit French report) ===
Report validation errors: ntdll:virtual has no test summary line (early exit of the main process?) ntdll:virtual has unaccounted for todo messages ntdll:virtual has unaccounted for skip messages
=== debiant2 (32 bit Hebrew:Israel report) ===
Report validation errors: ntdll:virtual has no test summary line (early exit of the main process?) ntdll:virtual has unaccounted for todo messages ntdll:virtual has unaccounted for skip messages
=== debiant2 (32 bit Hindi:India report) ===
Report validation errors: ntdll:virtual has no test summary line (early exit of the main process?) ntdll:virtual has unaccounted for todo messages ntdll:virtual has unaccounted for skip messages
=== debiant2 (32 bit Japanese:Japan report) ===
Report validation errors: ntdll:virtual has no test summary line (early exit of the main process?) ntdll:virtual has unaccounted for todo messages ntdll:virtual has unaccounted for skip messages
=== debiant2 (32 bit Chinese:China report) ===
Report validation errors: ntdll:virtual has no test summary line (early exit of the main process?) ntdll:virtual has unaccounted for todo messages ntdll:virtual has unaccounted for skip messages
=== debiant2 (32 bit WoW report) ===
Report validation errors: ntdll:virtual has no test summary line (early exit of the main process?) ntdll:virtual has unaccounted for todo messages ntdll:virtual has unaccounted for skip messages
=== debiant2 (64 bit WoW report) ===
Report validation errors: ntdll:virtual has no test summary line (early exit of the main process?) ntdll:virtual has unaccounted for todo messages ntdll:virtual has unaccounted for skip messages
Signed-off-by: Jinoh Kang jinoh.kang.kr@gmail.com --- configure | 6 ++++ configure.ac | 1 + dlls/ntdll/ntdll.spec | 2 ++ dlls/ntdll/unix/loader.c | 1 + dlls/ntdll/unix/virtual.c | 65 +++++++++++++++++++++++++++++++++++++++ include/config.h.in | 3 ++ 6 files changed, 78 insertions(+)
diff --git a/configure b/configure index ded6e71b815..d99e385120b 100755 --- a/configure +++ b/configure @@ -19000,6 +19000,12 @@ if test "x$ac_cv_func_mach_continuous_time" = xyes then : printf "%s\n" "#define HAVE_MACH_CONTINUOUS_TIME 1" >>confdefs.h
+fi +ac_fn_c_check_func "$LINENO" "madvise" "ac_cv_func_madvise" +if test "x$ac_cv_func_madvise" = xyes +then : + printf "%s\n" "#define HAVE_MADVISE 1" >>confdefs.h + fi ac_fn_c_check_func "$LINENO" "pipe2" "ac_cv_func_pipe2" if test "x$ac_cv_func_pipe2" = xyes diff --git a/configure.ac b/configure.ac index 4f7c7209da9..85a6f78d427 100644 --- a/configure.ac +++ b/configure.ac @@ -1942,6 +1942,7 @@ AC_CHECK_FUNCS(\ getrandom \ kqueue \ mach_continuous_time \ + madvise \ pipe2 \ port_create \ posix_fadvise \ diff --git a/dlls/ntdll/ntdll.spec b/dlls/ntdll/ntdll.spec index e5a49ba1a1f..f85af7acebc 100644 --- a/dlls/ntdll/ntdll.spec +++ b/dlls/ntdll/ntdll.spec @@ -384,6 +384,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) @@ -1405,6 +1406,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 f19d1d68dc7..d34f0b15d35 100644 --- a/dlls/ntdll/unix/loader.c +++ b/dlls/ntdll/unix/loader.c @@ -309,6 +309,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 5873a3e2335..e348e2a77e7 100644 --- a/dlls/ntdll/unix/virtual.c +++ b/dlls/ntdll/unix/virtual.c @@ -4968,6 +4968,71 @@ 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 int once; + + if (!once++) FIXME( "(process=%p,flags=%u) VmPrefetchInformation partial stub\n", process, flags ); + + if (process != NtCurrentProcess()) return STATUS_SUCCESS; + + for (i = 0; i < count; i++) + { + if (!addresses[i].NumberOfBytes) return STATUS_INVALID_PARAMETER_4; + } + + for (i = 0; i < count; i++) + { + MEMORY_RANGE_ENTRY entry; + memcpy(&entry, &addresses[i], sizeof(MEMORY_RANGE_ENTRY)); + + base = ROUND_ADDR( entry.VirtualAddress, page_mask ); + size = ROUND_SIZE( entry.VirtualAddress, entry.NumberOfBytes ); + +#ifdef HAVE_MADVISE + madvise(base, size, MADV_WILLNEED); +#else + (void)base; + (void)size; +#endif + } + + 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; + if (!addresses) return STATUS_ACCESS_VIOLATION; + 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/include/config.h.in b/include/config.h.in index 0fe50e8ce7c..234c3e1c8b5 100644 --- a/include/config.h.in +++ b/include/config.h.in @@ -293,6 +293,9 @@ /* Define to 1 if you have the <mach-o/loader.h> header file. */ #undef HAVE_MACH_O_LOADER_H
+/* Define to 1 if you have the `madvise' function. */ +#undef HAVE_MADVISE + /* Define to 1 if you have the <Metal/Metal.h> header file. */ #undef HAVE_METAL_METAL_H
Signed-off-by: Jinoh Kang jinoh.kang.kr@gmail.com --- dlls/kernel32/tests/virtual.c | 43 +++++++++++++++++++++++++++++++++++ 1 file changed, 43 insertions(+)
diff --git a/dlls/kernel32/tests/virtual.c b/dlls/kernel32/tests/virtual.c index a3b2d365c33..7a8fcab1fd8 100644 --- a/dlls/kernel32/tests/virtual.c +++ b/dlls/kernel32/tests/virtual.c @@ -51,6 +51,7 @@ static BOOL (WINAPI *pGetProcessDEPPolicy)(HANDLE, LPDWORD, PBOOL); static BOOL (WINAPI *pIsWow64Process)(HANDLE, PBOOL); static NTSTATUS (WINAPI *pNtProtectVirtualMemory)(HANDLE, PVOID *, SIZE_T *, ULONG, ULONG *); static PVOID (WINAPI *pVirtualAllocFromApp)(PVOID, SIZE_T, DWORD, DWORD); +static BOOL (WINAPI *pPrefetchVirtualMemory)(HANDLE, ULONG_PTR, PWIN32_MEMORY_RANGE_ENTRY, ULONG);
/* ############################### */
@@ -4240,6 +4241,46 @@ static void test_shared_memory_ro(BOOL is_child, DWORD child_access) CloseHandle(mapping); }
+static void test_PrefetchVirtualMemory(void) +{ + WIN32_MEMORY_RANGE_ENTRY entries[2]; + char stackmem[] = "Test stack mem"; + static char testmem[] = "Test memory range data"; + unsigned int page_size = si.dwPageSize; + + if (!pPrefetchVirtualMemory) + { + skip("no PrefetchVirtualMemory in kernelbase"); + return; + } + + todo_wine + ok( !pPrefetchVirtualMemory( GetCurrentProcess(), 0, NULL, 0 ), + "PrefetchVirtualMemory unexpected success on 0 entries\n" ); + + entries[0].VirtualAddress = (PVOID)((ULONG_PTR)testmem & -(ULONG_PTR)page_size); + entries[0].NumberOfBytes = page_size; + ok( pPrefetchVirtualMemory( GetCurrentProcess(), 1, entries, 0 ), + "PrefetchVirtualMemory unexpected status on 1 page-aligned entry: %d\n", GetLastError() ); + + entries[0].VirtualAddress = testmem; + entries[0].NumberOfBytes = sizeof(testmem); + ok( pPrefetchVirtualMemory( GetCurrentProcess(), 1, entries, 0 ), + "PrefetchVirtualMemory unexpected status on 1 entry: %d\n", GetLastError() ); + + entries[0].VirtualAddress = NULL; + entries[0].NumberOfBytes = page_size; + ok( pPrefetchVirtualMemory( GetCurrentProcess(), 1, entries, 0 ), + "PrefetchVirtualMemory unexpected status on 1 unmapped entry: %d\n", GetLastError() ); + + entries[0].VirtualAddress = (PVOID)((ULONG_PTR)testmem & -(ULONG_PTR)page_size); + entries[0].NumberOfBytes = page_size; + entries[1].VirtualAddress = (PVOID)((ULONG_PTR)stackmem & -(ULONG_PTR)page_size); + entries[1].NumberOfBytes = page_size; + ok( pPrefetchVirtualMemory( GetCurrentProcess(), 2, entries, 0 ), + "PrefetchVirtualMemory unexpected status on 2 page-aligned entries: %d\n", GetLastError() ); +} + START_TEST(virtual) { int argc; @@ -4295,6 +4336,7 @@ START_TEST(virtual) pRtlRemoveVectoredExceptionHandler = (void *)GetProcAddress( hntdll, "RtlRemoveVectoredExceptionHandler" ); pNtProtectVirtualMemory = (void *)GetProcAddress( hntdll, "NtProtectVirtualMemory" ); pVirtualAllocFromApp = (void *)GetProcAddress( hkernelbase, "VirtualAllocFromApp" ); + pPrefetchVirtualMemory = (void *)GetProcAddress( hkernelbase, "PrefetchVirtualMemory" );
GetSystemInfo(&si); trace("system page size %#x\n", si.dwPageSize); @@ -4317,6 +4359,7 @@ START_TEST(virtual) test_IsBadWritePtr(); test_IsBadCodePtr(); test_write_watch(); + test_PrefetchVirtualMemory(); #if defined(__i386__) || defined(__x86_64__) test_stack_commit(); #endif
Hi,
While running your changed tests, I think I found new failures. Being a bot and all I'm not very good at pattern recognition, so I might be wrong, but could you please double-check?
Full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=102749
Your paranoid android.
=== w1064v1507 (32 bit report) ===
kernel32: virtual.c:4263: Test failed: PrefetchVirtualMemory unexpected status on 1 page-aligned entry: 87 virtual.c:4268: Test failed: PrefetchVirtualMemory unexpected status on 1 entry: 87 virtual.c:4273: Test failed: PrefetchVirtualMemory unexpected status on 1 unmapped entry: 87 virtual.c:4280: Test failed: PrefetchVirtualMemory unexpected status on 2 page-aligned entries: 87
Signed-off-by: Jinoh Kang jinoh.kang.kr@gmail.com --- dlls/kernel32/tests/virtual.c | 1 - dlls/kernelbase/memory.c | 9 +++++---- 2 files changed, 5 insertions(+), 5 deletions(-)
diff --git a/dlls/kernel32/tests/virtual.c b/dlls/kernel32/tests/virtual.c index 7a8fcab1fd8..a3303f6f9db 100644 --- a/dlls/kernel32/tests/virtual.c +++ b/dlls/kernel32/tests/virtual.c @@ -4254,7 +4254,6 @@ static void test_PrefetchVirtualMemory(void) return; }
- todo_wine ok( !pPrefetchVirtualMemory( GetCurrentProcess(), 0, NULL, 0 ), "PrefetchVirtualMemory unexpected success on 0 entries\n" );
diff --git a/dlls/kernelbase/memory.c b/dlls/kernelbase/memory.c index 7844b571e51..9dd396fc273 100644 --- a/dlls/kernelbase/memory.c +++ b/dlls/kernelbase/memory.c @@ -346,11 +346,12 @@ LPVOID WINAPI DECLSPEC_HOTPATCH VirtualAllocFromApp( void *addr, SIZE_T size, /*********************************************************************** * PrefetchVirtualMemory (kernelbase.@) */ -BOOL WINAPI /* DECLSPEC_HOTPATCH */ PrefetchVirtualMemory( HANDLE process, ULONG_PTR count, - WIN32_MEMORY_RANGE_ENTRY *addresses, ULONG flags ) +BOOL WINAPI DECLSPEC_HOTPATCH PrefetchVirtualMemory( HANDLE process, ULONG_PTR count, + WIN32_MEMORY_RANGE_ENTRY *addresses, ULONG flags ) { - FIXME( "process %p, count %p, addresses %p, flags %#x stub.\n", process, (void *)count, addresses, flags ); - return TRUE; + return set_ntstatus( NtSetInformationVirtualMemory( process, VmPrefetchInformation, + count, (PMEMORY_RANGE_ENTRY)addresses, + &flags, sizeof(flags) )); }
Hi,
While running your changed tests, I think I found new failures. Being a bot and all I'm not very good at pattern recognition, so I might be wrong, but could you please double-check?
Full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=102750
Your paranoid android.
=== w1064v1507 (32 bit report) ===
kernel32: virtual.c:4262: Test failed: PrefetchVirtualMemory unexpected status on 1 page-aligned entry: 87 virtual.c:4267: Test failed: PrefetchVirtualMemory unexpected status on 1 entry: 87 virtual.c:4272: Test failed: PrefetchVirtualMemory unexpected status on 1 unmapped entry: 87 virtual.c:4279: Test failed: PrefetchVirtualMemory unexpected status on 2 page-aligned entries: 87