diff --git a/README.md b/README.md index 0ce6ac27..f9262378 100644 --- a/README.md +++ b/README.md @@ -39,7 +39,7 @@ Wine. All those differences are also documented on the Included bug fixes and improvements =================================== -**Bugfixes and features included in the next upcoming release [18]:** +**Bugfixes and features included in the next upcoming release [19]:** * Add stub for NtSetLdtEntries/ZwSetLdtEntries ([Wine Bug #26268](https://bugs.winehq.org/show_bug.cgi?id=26268)) * Allow NULL pointer for optional arguments of D3DXIntersectTri ([Wine Bug #35133](https://bugs.winehq.org/show_bug.cgi?id=35133)) @@ -53,6 +53,7 @@ Included bug fixes and improvements * Fix crash of Trine Demo on start ([Wine Bug #19231](https://bugs.winehq.org/show_bug.cgi?id=19231)) * Fix crash of winedevice when relocation entry crosses page boundary ([Wine Bug #28254](https://bugs.winehq.org/show_bug.cgi?id=28254)) * Fix handling of invert_y in DrawTextExW ([Wine Bug #22109](https://bugs.winehq.org/show_bug.cgi?id=22109)) +* Fix implementation of K32GetPerformanceInfo ([Wine Bug #37512](https://bugs.winehq.org/show_bug.cgi?id=37512)) * Fix texture corruption in CSI: Fatal Conspiracy ([Wine Bug #33768](https://bugs.winehq.org/show_bug.cgi?id=33768)) * MSVCRT crashes when NULL is passed as string to atof or strtod ([Wine Bug #32550](https://bugs.winehq.org/show_bug.cgi?id=32550)) * Return correct values for GetThreadTimes function ([Wine Bug #20230](https://bugs.winehq.org/show_bug.cgi?id=20230)) diff --git a/debian/changelog b/debian/changelog index 348bf158..e51fa33d 100644 --- a/debian/changelog +++ b/debian/changelog @@ -22,6 +22,7 @@ wine-compholio (1.7.31) UNRELEASED; urgency=low * Added patch to avoid crashing when broken app tries to release surface although refcount is zero. * Added patch to avoid sending window messages in FindWindowExW. * Added patch to fix handling of invert_y in DrawTextExW. + * Added patch to fix implementation of K32GetPerformanceInfo. * Removed patch for iphlpapi stub functions (accepted upstream). * Removed patches for FindFirstFileExW (accepted upstream). * Removed patches for TLB dependencies lookup in resources (accepted upstream). diff --git a/patches/Makefile b/patches/Makefile index bb840165..59c3a32c 100644 --- a/patches/Makefile +++ b/patches/Makefile @@ -47,6 +47,7 @@ PATCHLIST := \ kernel32-GetNumaProcessorNode.ok \ kernel32-GetSystemTimes.ok \ kernel32-GetVolumePathName.ok \ + kernel32-K32GetPerformanceInfo.ok \ kernel32-Named_Pipe.ok \ kernel32-UTF7_Support.ok \ libs-Unicode_Collation.ok \ @@ -697,6 +698,24 @@ kernel32-GetVolumePathName.ok: echo '+ { "kernel32-GetVolumePathName", "Erich E. Hoover", "Implement GetVolumePathName." },'; \ ) > kernel32-GetVolumePathName.ok +# Patchset kernel32-K32GetPerformanceInfo +# | +# | Included patches: +# | * Fix implementation of K32GetPerformanceInfo. [by Sebastian Lackner] +# | +# | This patchset fixes the following Wine bugs: +# | * [#37512] Fix implementation of K32GetPerformanceInfo +# | +# | Modified files: +# | * dlls/kernel32/cpu.c, dlls/psapi/tests/psapi_main.c +# | +.INTERMEDIATE: kernel32-K32GetPerformanceInfo.ok +kernel32-K32GetPerformanceInfo.ok: + $(call APPLY_FILE,kernel32-K32GetPerformanceInfo/0001-kernel32-Fix-implementation-of-K32GetPerformanceInfo.patch) + @( \ + echo '+ { "kernel32-K32GetPerformanceInfo", "Sebastian Lackner", "Fix implementation of K32GetPerformanceInfo." },'; \ + ) > kernel32-K32GetPerformanceInfo.ok + # Patchset kernel32-Named_Pipe # | # | Included patches: diff --git a/patches/kernel32-GetNumaProcessorNode/0001-kernel32-Implement-GetNumaProcessorNode.patch b/patches/kernel32-GetNumaProcessorNode/0001-kernel32-Implement-GetNumaProcessorNode.patch index 77ff9cdb..8887dd5c 100644 --- a/patches/kernel32-GetNumaProcessorNode/0001-kernel32-Implement-GetNumaProcessorNode.patch +++ b/patches/kernel32-GetNumaProcessorNode/0001-kernel32-Implement-GetNumaProcessorNode.patch @@ -13,8 +13,7 @@ diff --git a/dlls/kernel32/cpu.c b/dlls/kernel32/cpu.c index 0ebf8f3..c389898 100644 --- a/dlls/kernel32/cpu.c +++ b/dlls/kernel32/cpu.c -@@ -229,3 +229,31 @@ BOOL WINAPI K32GetPerformanceInfo(PPERFORMANCE_INFORMATION info, DWORD size) - } +@@ -230,2 +230,30 @@ BOOL WINAPI K32GetPerformanceInfo(PPERFORMANCE_INFORMATION info, DWORD size) return TRUE; } + diff --git a/patches/kernel32-K32GetPerformanceInfo/0001-kernel32-Fix-implementation-of-K32GetPerformanceInfo.patch b/patches/kernel32-K32GetPerformanceInfo/0001-kernel32-Fix-implementation-of-K32GetPerformanceInfo.patch new file mode 100644 index 00000000..4adbbab7 --- /dev/null +++ b/patches/kernel32-K32GetPerformanceInfo/0001-kernel32-Fix-implementation-of-K32GetPerformanceInfo.patch @@ -0,0 +1,284 @@ +From 6d0a5dfb47d6f38a7eec61f54b6e95214df3083d Mon Sep 17 00:00:00 2001 +From: Sebastian Lackner +Date: Thu, 13 Nov 2014 23:06:15 +0100 +Subject: kernel32: Fix implementation of K32GetPerformanceInfo. + +--- + dlls/kernel32/cpu.c | 72 +++++++++++++++++++++- + dlls/psapi/tests/psapi_main.c | 137 +++++++++++++++++++++++++++++++++++++++++- + 2 files changed, 207 insertions(+), 2 deletions(-) + +diff --git a/dlls/kernel32/cpu.c b/dlls/kernel32/cpu.c +index 0ebf8f3..56cbfd2 100644 +--- a/dlls/kernel32/cpu.c ++++ b/dlls/kernel32/cpu.c +@@ -217,10 +217,63 @@ BOOL WINAPI IsProcessorFeaturePresent ( + BOOL WINAPI K32GetPerformanceInfo(PPERFORMANCE_INFORMATION info, DWORD size) + { ++ union ++ { ++ SYSTEM_PERFORMANCE_INFORMATION performance; ++ SYSTEM_BASIC_INFORMATION basic; ++ } sysinfo; ++ SYSTEM_PROCESS_INFORMATION *process_info = NULL, *spi; ++ DWORD process_info_size; + NTSTATUS status; + + TRACE( "(%p, %d)\n", info, size ); + +- status = NtQuerySystemInformation( SystemPerformanceInformation, info, size, NULL ); ++ if (size < sizeof(*info)) ++ { ++ SetLastError( ERROR_BAD_LENGTH ); ++ return FALSE; ++ } ++ ++ info->cb = sizeof(*info); ++ ++ /* SYSTEM_PERFORMANCE_INFORMATION */ ++ status = NtQuerySystemInformation( SystemPerformanceInformation, &sysinfo.performance, sizeof(sysinfo.performance), NULL ); ++ if (status) ++ { ++ SetLastError( RtlNtStatusToDosError( status ) ); ++ return FALSE; ++ } ++ info->CommitTotal = sysinfo.performance.TotalCommittedPages; ++ info->CommitLimit = sysinfo.performance.TotalCommitLimit; ++ info->CommitPeak = sysinfo.performance.PeakCommitment; ++ info->PhysicalAvailable = sysinfo.performance.AvailablePages; ++ info->SystemCache = 0; /* FIXME */ ++ info->KernelTotal = sysinfo.performance.PagedPoolUsage + sysinfo.performance.NonPagedPoolUsage; ++ info->KernelPaged = sysinfo.performance.PagedPoolUsage; ++ info->KernelNonpaged = sysinfo.performance.NonPagedPoolUsage; ++ ++ /* SYSTEM_BASIC_INFORMATION */ ++ status = NtQuerySystemInformation( SystemBasicInformation, &sysinfo.basic, sizeof(sysinfo.basic), NULL ); ++ if (status) ++ { ++ SetLastError( RtlNtStatusToDosError( status ) ); ++ return FALSE; ++ } ++ info->PhysicalTotal = sysinfo.basic.MmNumberOfPhysicalPages; ++ info->PageSize = sysinfo.basic.PageSize; + ++ /* SYSTEM_PROCESS_INFORMATION */ ++ status = NtQuerySystemInformation( SystemProcessInformation, NULL, 0, &process_info_size ); ++ while (status == STATUS_INFO_LENGTH_MISMATCH) ++ { ++ process_info = HeapAlloc( GetProcessHeap(), 0, process_info_size ); ++ if (!process_info) ++ { ++ SetLastError( ERROR_OUTOFMEMORY ); ++ return FALSE; ++ } ++ status = NtQuerySystemInformation( SystemProcessInformation, process_info, process_info_size, &process_info_size ); ++ if (!status) break; ++ HeapFree( GetProcessHeap(), 0, process_info ); ++ } + if (status) + { +@@ -228,4 +281,21 @@ BOOL WINAPI K32GetPerformanceInfo(PPERFORMANCE_INFORMATION info, DWORD size) + return FALSE; + } ++ ++ info->HandleCount = 0; ++ info->ProcessCount = 0; ++ info->ThreadCount = 0; ++ ++ if (process_info) ++ { ++ for (spi = process_info;; spi = (SYSTEM_PROCESS_INFORMATION *)(((PCHAR)spi) + spi->NextEntryOffset)) ++ { ++ info->ProcessCount++; ++ info->HandleCount += spi->HandleCount; ++ info->ThreadCount += spi->dwThreadCount; ++ if (spi->NextEntryOffset == 0) break; ++ } ++ } ++ ++ HeapFree( GetProcessHeap(), 0, process_info ); + return TRUE; + } +diff --git a/dlls/psapi/tests/psapi_main.c b/dlls/psapi/tests/psapi_main.c +index 62d4f5c..7fa5d26 100644 +--- a/dlls/psapi/tests/psapi_main.c ++++ b/dlls/psapi/tests/psapi_main.c +@@ -53,14 +53,16 @@ static DWORD (WINAPI *pGetModuleFileNameExW)(HANDLE, HMODULE, LPWSTR, DWORD); + static BOOL (WINAPI *pGetModuleInformation)(HANDLE, HMODULE, LPMODULEINFO, DWORD); + static DWORD (WINAPI *pGetMappedFileNameA)(HANDLE, LPVOID, LPSTR, DWORD); + static DWORD (WINAPI *pGetMappedFileNameW)(HANDLE, LPVOID, LPWSTR, DWORD); ++static BOOL (WINAPI *pGetPerformanceInfo)(PPERFORMANCE_INFORMATION, DWORD); + static DWORD (WINAPI *pGetProcessImageFileNameA)(HANDLE, LPSTR, DWORD); + static DWORD (WINAPI *pGetProcessImageFileNameW)(HANDLE, LPWSTR, DWORD); + static BOOL (WINAPI *pGetProcessMemoryInfo)(HANDLE, PPROCESS_MEMORY_COUNTERS, DWORD); + static BOOL (WINAPI *pGetWsChanges)(HANDLE, PPSAPI_WS_WATCH_INFORMATION, DWORD); + static BOOL (WINAPI *pInitializeProcessForWsWatch)(HANDLE); + static BOOL (WINAPI *pQueryWorkingSet)(HANDLE, PVOID, DWORD); ++static NTSTATUS (WINAPI *pNtQuerySystemInformation)(SYSTEM_INFORMATION_CLASS, PVOID, ULONG, PULONG); + static NTSTATUS (WINAPI *pNtQueryVirtualMemory)(HANDLE, LPCVOID, ULONG, PVOID, SIZE_T, SIZE_T *); +- ++ + static BOOL InitFunctionPtrs(HMODULE hpsapi) + { + PSAPI_GET_PROC(EmptyWorkingSet); +@@ -77,10 +79,13 @@ static BOOL InitFunctionPtrs(HMODULE hpsapi) + PSAPI_GET_PROC(InitializeProcessForWsWatch); + PSAPI_GET_PROC(QueryWorkingSet); + /* GetProcessImageFileName is not exported on NT4 */ ++ pGetPerformanceInfo = ++ (void *)GetProcAddress(hpsapi, "GetPerformanceInfo"); + pGetProcessImageFileNameA = + (void *)GetProcAddress(hpsapi, "GetProcessImageFileNameA"); + pGetProcessImageFileNameW = + (void *)GetProcAddress(hpsapi, "GetProcessImageFileNameW"); ++ pNtQuerySystemInformation = (void *)GetProcAddress(GetModuleHandleA("ntdll.dll"), "NtQuerySystemInformation"); + pNtQueryVirtualMemory = (void *)GetProcAddress(GetModuleHandleA("ntdll.dll"), "NtQueryVirtualMemory"); + return TRUE; + } +@@ -184,6 +189,135 @@ static void test_GetModuleInformation(void) + ok(info.lpBaseOfDll == hMod, "lpBaseOfDll=%p hMod=%p\n", info.lpBaseOfDll, hMod); + } + ++static void test_GetPerformanceInfo(void) ++{ ++ PERFORMANCE_INFORMATION info; ++ NTSTATUS status; ++ DWORD size; ++ BOOL ret; ++ ++ if (!pGetPerformanceInfo) ++ { ++ win_skip("GetPerformanceInfo not available, skipping tests\n"); ++ return; ++ } ++ ++ SetLastError(0xdeadbeef); ++ ret = pGetPerformanceInfo(&info, sizeof(info)-1); ++ ok(!ret, "GetPerformanceInfo unexpectedly succeeded\n"); ++ ok(GetLastError() == ERROR_BAD_LENGTH, "expected error=ERROR_BAD_LENGTH but got %d\n", GetLastError()); ++ ++ SetLastError(0xdeadbeef); ++ ret = pGetPerformanceInfo(&info, sizeof(info)); ++ ok(ret, "GetPerformanceInfo failed with %d\n", GetLastError()); ++ ok(info.cb == sizeof(PERFORMANCE_INFORMATION), "expected info.cb=%d but got %d\n", sizeof(PERFORMANCE_INFORMATION), info.cb); ++ ++ /* verify content of the structure */ ++ if (!pNtQuerySystemInformation) ++ win_skip("NtQuerySystemInformation not found, unable to verify results\n"); ++ else ++ { ++ char performance_buffer[sizeof(SYSTEM_PERFORMANCE_INFORMATION) + 16]; /* larger on w2k8/win7 */ ++ SYSTEM_PERFORMANCE_INFORMATION *sys_performance_info = (SYSTEM_PERFORMANCE_INFORMATION *)performance_buffer; ++ SYSTEM_BASIC_INFORMATION sys_basic_info; ++ SYSTEM_PROCESS_INFORMATION *sys_process_info, *spi; ++ DWORD process_count, handle_count, thread_count; ++ ++ /* SYSTEM_PERFORMANCE_INFORMATION */ ++ size = 0; ++ status = pNtQuerySystemInformation(SystemPerformanceInformation, sys_performance_info, sizeof(performance_buffer), &size); ++ ok(status == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %08x\n", status); ++ ok(size >= sizeof(SYSTEM_PERFORMANCE_INFORMATION), "incorrect length %d\n", size); ++ ++ /* SYSTEM_BASIC_INFORMATION */ ++ size = 0; ++ status = pNtQuerySystemInformation(SystemBasicInformation, &sys_basic_info, sizeof(sys_basic_info), &size); ++ ok(status == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %08x\n", status); ++ ok(size >= sizeof(SYSTEM_BASIC_INFORMATION), "incorrect length %d\n", size); ++ ++ /* SYSTEM_PROCESS_INFORMATION */ ++ size = 0; ++ status = pNtQuerySystemInformation(SystemProcessInformation, NULL, 0, &size); ++ ok(status == STATUS_INFO_LENGTH_MISMATCH, "expected STATUS_LENGTH_MISMATCH, got %08x\n", status); ++ ok(size > 0, "incorrect length %d\n", size); ++ ++ while (status == STATUS_INFO_LENGTH_MISMATCH) ++ { ++ sys_process_info = HeapAlloc(GetProcessHeap(), 0, size); ++ ok(sys_process_info != NULL, "failed to allocate memory\n"); ++ status = pNtQuerySystemInformation(SystemProcessInformation, sys_process_info, size, &size); ++ if (!status) break; ++ HeapFree(GetProcessHeap(), 0, sys_process_info); ++ } ++ ok(status == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %08x\n", status); ++ ++ process_count = handle_count = thread_count = 0; ++ for (spi = sys_process_info;; spi = (SYSTEM_PROCESS_INFORMATION *)(((PCHAR)spi) + spi->NextEntryOffset)) ++ { ++ process_count++; ++ handle_count += spi->HandleCount; ++ thread_count += spi->dwThreadCount; ++ if (spi->NextEntryOffset == 0) break; ++ } ++ ++ ok(info.CommitTotal == sys_performance_info->TotalCommittedPages, ++ "expected info.CommitTotal=%u but got %u\n", ++ sys_performance_info->TotalCommittedPages, (ULONG)info.CommitTotal); ++ ++ ok(info.CommitLimit == sys_performance_info->TotalCommitLimit, ++ "expected info.CommitLimit=%u but got %u\n", ++ sys_performance_info->TotalCommitLimit, (ULONG)info.CommitLimit); ++ ++ ok(info.CommitPeak == sys_performance_info->PeakCommitment, ++ "expected info.CommitPeak=%u but got %u\n", ++ sys_performance_info->PeakCommitment, (ULONG)info.CommitPeak); ++ ++ ok(info.PhysicalTotal == sys_basic_info.MmNumberOfPhysicalPages, ++ "expected info.PhysicalTotal=%u but got %u\n", ++ sys_basic_info.MmNumberOfPhysicalPages, (ULONG)info.PhysicalTotal); ++ ++ ok(info.PhysicalAvailable >= max(sys_performance_info->AvailablePages, 25) - 25 && ++ info.PhysicalAvailable <= sys_performance_info->AvailablePages + 25, ++ "expected approximately info.PhysicalAvailable=%u but got %u\n", ++ sys_performance_info->AvailablePages, (ULONG)info.PhysicalAvailable); ++ ++ /* ok(info.SystemCache == sys_performance_info->MmSystemCachePage, ++ "expected info.SystemCache=%u but got %u\n", ++ sys_performance_info->MmSystemCachePage, (ULONG)info.SystemCache); */ ++ ++ ok(info.KernelTotal == sys_performance_info->PagedPoolUsage + sys_performance_info->NonPagedPoolUsage, ++ "expected info.KernelTotal=%u but got %u\n", ++ sys_performance_info->PagedPoolUsage + sys_performance_info->NonPagedPoolUsage, (ULONG)info.KernelTotal); ++ ++ ok(info.KernelPaged == sys_performance_info->PagedPoolUsage, ++ "expected info.KernelPaged=%u but got %u\n", ++ sys_performance_info->PagedPoolUsage, (ULONG)info.KernelPaged); ++ ++ ok(info.KernelNonpaged == sys_performance_info->NonPagedPoolUsage, ++ "expected info.KernelNonpaged=%u but got %u\n", ++ sys_performance_info->NonPagedPoolUsage, (ULONG)info.KernelNonpaged); ++ ++ ok(info.PageSize == sys_basic_info.PageSize, ++ "expected info.PageSize=%u but got %u\n", ++ sys_basic_info.PageSize, (ULONG)info.PageSize); ++ ++ ok(info.HandleCount == handle_count, ++ "expected info.HandleCount=%u but got %u\n", ++ handle_count, info.HandleCount); ++ ++ ok(info.ProcessCount == process_count, ++ "expected info.ProcessCount=%u but got %u\n", ++ process_count, info.ProcessCount); ++ ++ ok(info.ThreadCount == thread_count, ++ "expected info.ThreadCount=%u but got %u\n", ++ thread_count, info.ThreadCount); ++ ++ HeapFree(GetProcessHeap(), 0, sys_process_info); ++ } ++} ++ ++ + static void test_GetProcessMemoryInfo(void) + { + PROCESS_MEMORY_COUNTERS pmc; +@@ -677,6 +811,7 @@ START_TEST(psapi_main) + test_EnumProcesses(); + test_EnumProcessModules(); + test_GetModuleInformation(); ++ test_GetPerformanceInfo(); + test_GetProcessMemoryInfo(); + test_GetMappedFileName(); + test_GetProcessImageFileName(); +-- +2.1.3 + diff --git a/patches/kernel32-K32GetPerformanceInfo/definition b/patches/kernel32-K32GetPerformanceInfo/definition new file mode 100644 index 00000000..df0f1b09 --- /dev/null +++ b/patches/kernel32-K32GetPerformanceInfo/definition @@ -0,0 +1,4 @@ +Author: Sebastian Lackner +Subject: Fix implementation of K32GetPerformanceInfo. +Revision: 1 +Fixes: [37512] Fix implementation of K32GetPerformanceInfo