From: James Eder Subject: [PATCH] kernel32: Actually return a PERFORMANCE_INFORMATION structure in K32GetPerformanceInfo (try 3) Message-Id: <1366826507-4946-1-git-send-email-jimportal@gmail.com> Date: Wed, 24 Apr 2013 12:01:47 -0600 try 2: Try harder to get a proc address and alow for skipping in tests. try 3: Improved FIXME and TRACE. --- dlls/kernel32/cpu.c | 30 ++++++++++++++++++++++++------ dlls/psapi/tests/psapi_main.c | 36 ++++++++++++++++++++++++++++++++++++ 2 files changed, 60 insertions(+), 6 deletions(-) diff --git a/dlls/kernel32/cpu.c b/dlls/kernel32/cpu.c index 0ebf8f3..ff2b047 100644 --- a/dlls/kernel32/cpu.c +++ b/dlls/kernel32/cpu.c @@ -216,16 +216,34 @@ BOOL WINAPI IsProcessorFeaturePresent ( */ BOOL WINAPI K32GetPerformanceInfo(PPERFORMANCE_INFORMATION info, DWORD size) { - NTSTATUS status; + MEMORYSTATUSEX mem_status; - TRACE( "(%p, %d)\n", info, size ); + FIXME("semi-stub (%p, %d)\n", info, size ); - status = NtQuerySystemInformation( SystemPerformanceInformation, info, size, NULL ); - - if (status) + if(size < sizeof(PERFORMANCE_INFORMATION)) { - SetLastError( RtlNtStatusToDosError( status ) ); + SetLastError(ERROR_BAD_LENGTH); return FALSE; } + + mem_status.dwLength = sizeof(mem_status); + if (!GlobalMemoryStatusEx( &mem_status )) + return FALSE; + + memset(info, 0, sizeof(PERFORMANCE_INFORMATION)); + + info->cb = sizeof(PERFORMANCE_INFORMATION); + info->CommitLimit = min((mem_status.ullTotalPageFile / system_info.PageSize), MAXDWORD); + info->PhysicalTotal = min((mem_status.ullTotalPhys / system_info.PageSize), MAXDWORD); + info->PhysicalAvailable = min((mem_status.ullAvailPhys / system_info.PageSize), MAXDWORD); + info->PageSize = system_info.PageSize; + + TRACE("cb=%d, CommitTotal=0x%lx, CommitLimit=0x%lx, CommitPeak=0x%lx, PhysicalTotal=0x%lx, " + "PhysicalAvailable=0x%lx, SystemCache=0x%lx, KernelTotal=0x%lx, KernelPaged=0x%lx, " + "KernelNonpaged=0x%lx, PageSize=0x%lx, HandleCount=%d, ProcessCount=%d, ThreadCount=%d\n", + info->cb, info->CommitTotal, info->CommitLimit, info->CommitPeak, info->PhysicalTotal, + info->PhysicalAvailable, info->SystemCache, info->KernelTotal, info->KernelPaged, + info->KernelNonpaged, info->PageSize, info->HandleCount, info->ProcessCount, info->ThreadCount); + return TRUE; } diff --git a/dlls/psapi/tests/psapi_main.c b/dlls/psapi/tests/psapi_main.c index b91add6..8fdebc4 100644 --- a/dlls/psapi/tests/psapi_main.c +++ b/dlls/psapi/tests/psapi_main.c @@ -53,6 +53,7 @@ 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); @@ -82,6 +83,12 @@ static BOOL InitFunctionPtrs(HMODULE hpsapi) pGetProcessImageFileNameW = (void *)GetProcAddress(hpsapi, "GetProcessImageFileNameW"); pNtQueryVirtualMemory = (void *)GetProcAddress(GetModuleHandle("ntdll.dll"), "NtQueryVirtualMemory"); + + /* GetPerformanceInfo can be found in psapi.dll, kernel32.dll (as K32GetPerformanceInfo), both, or nowhere */ + pGetPerformanceInfo = (void*)GetProcAddress(hpsapi, "GetPerformanceInfo"); + if(!pGetPerformanceInfo) + pGetPerformanceInfo = (void*)GetProcAddress(GetModuleHandle("kernel32.dll"), "K32GetPerformanceInfo"); + return TRUE; } @@ -648,6 +655,33 @@ free_page: VirtualFree(addr, 0, MEM_RELEASE); } +static void test_GetPerformanceInfo(void) +{ + PERFORMANCE_INFORMATION info; + BOOL ret; + + if(!pGetPerformanceInfo) + { + win_skip("GetPerformanceInfo not implemented.\n"); + return; + } + + SetLastError(0xdeadbeef); + ret = pGetPerformanceInfo(&info, sizeof(info) - 1); + ok(!ret, "GetPerformanceInfo should fail.\n"); + ok(GetLastError() == ERROR_BAD_LENGTH, "expected error=ERROR_BAD_LENGTH but got %d\n", GetLastError()); + + /* At least XP and 7 crash if a NULL pointer is passed to + * GetPerformanceInfo. It's probably unlikely any software depends on + * crashing so we don't test it */ + + SetLastError(0xdeadbeef); + ret = pGetPerformanceInfo(&info, sizeof(info)); + ok(ret, "GetPerformanceInfo should have succeeded but failed with %d\n", GetLastError()); + if(ret) + ok(info.cb >= sizeof(info), "expected cb >= %d but got %d\n", sizeof(info), info.cb); +} + START_TEST(psapi_main) { HMODULE hpsapi = LoadLibraryA("psapi.dll"); @@ -685,6 +719,8 @@ START_TEST(psapi_main) CloseHandle(hpVR); CloseHandle(hpQV); CloseHandle(hpAA); + + test_GetPerformanceInfo(); } FreeLibrary(hpsapi); -- 1.8.2.1