1 /* 2 * Unit test suite for PSAPI 3 * 4 * Copyright (C) 2005 Felix Nawothnig 5 * Copyright (C) 2012 Dmitry Timoshkov 6 * 7 * This library is free software; you can redistribute it and/or 8 * modify it under the terms of the GNU Lesser General Public 9 * License as published by the Free Software Foundation; either 10 * version 2.1 of the License, or (at your option) any later version. 11 * 12 * This library is distributed in the hope that it will be useful, 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 * Lesser General Public License for more details. 16 * 17 * You should have received a copy of the GNU Lesser General Public 18 * License along with this library; if not, write to the Free Software 19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA 20 */ 21 22 /* 0x0600 makes PROCESS_ALL_ACCESS not compatible with pre-Vista versions */ 23 #ifndef __REACTOS__ 24 #define _WIN32_WINNT 0x0500 25 #endif 26 27 #include <stdarg.h> 28 29 #include "ntstatus.h" 30 #define WIN32_NO_STATUS 31 32 #include "windef.h" 33 #include "winbase.h" 34 #include "winreg.h" 35 #include "winnt.h" 36 #include "wine/winternl.h" 37 #include "winnls.h" 38 #include "winuser.h" 39 #define PSAPI_VERSION 1 40 #include "psapi.h" 41 #include "wine/test.h" 42 43 static NTSTATUS (WINAPI *pNtQuerySystemInformation)(SYSTEM_INFORMATION_CLASS, PVOID, ULONG, PULONG); 44 static NTSTATUS (WINAPI *pNtQueryVirtualMemory)(HANDLE, LPCVOID, ULONG, PVOID, SIZE_T, SIZE_T *); 45 static BOOL (WINAPI *pIsWow64Process)(HANDLE, BOOL *); 46 static BOOL (WINAPI *pWow64DisableWow64FsRedirection)(void **); 47 static BOOL (WINAPI *pWow64RevertWow64FsRedirection)(void *); 48 49 static BOOL wow64; 50 51 static BOOL init_func_ptrs(void) 52 { 53 pNtQuerySystemInformation = (void *)GetProcAddress(GetModuleHandleA("ntdll.dll"), "NtQuerySystemInformation"); 54 pNtQueryVirtualMemory = (void *)GetProcAddress(GetModuleHandleA("ntdll.dll"), "NtQueryVirtualMemory"); 55 pIsWow64Process = (void *)GetProcAddress(GetModuleHandleA("kernel32.dll"), "IsWow64Process"); 56 pWow64DisableWow64FsRedirection = (void *)GetProcAddress(GetModuleHandleA("kernel32.dll"), "Wow64DisableWow64FsRedirection"); 57 pWow64RevertWow64FsRedirection = (void *)GetProcAddress(GetModuleHandleA("kernel32.dll"), "Wow64RevertWow64FsRedirection"); 58 return TRUE; 59 } 60 61 static HANDLE hpSR, hpQI, hpVR, hpQV; 62 static const HANDLE hBad = (HANDLE)0xdeadbeef; 63 64 static void test_EnumProcesses(void) 65 { 66 DWORD pid, ret, cbUsed = 0xdeadbeef; 67 68 SetLastError(0xdeadbeef); 69 ret = EnumProcesses(NULL, 0, &cbUsed); 70 ok(ret == 1, "failed with %d\n", GetLastError()); 71 ok(cbUsed == 0, "cbUsed=%d\n", cbUsed); 72 73 SetLastError(0xdeadbeef); 74 ret = EnumProcesses(&pid, 4, &cbUsed); 75 ok(ret == 1, "failed with %d\n", GetLastError()); 76 ok(cbUsed == 4, "cbUsed=%d\n", cbUsed); 77 } 78 79 static void test_EnumProcessModules(void) 80 { 81 char buffer[200] = "C:\\windows\\system32\\notepad.exe"; 82 PROCESS_INFORMATION pi = {0}; 83 STARTUPINFOA si = {0}; 84 void *cookie; 85 HMODULE hMod; 86 DWORD ret, cbNeeded = 0xdeadbeef; 87 88 SetLastError(0xdeadbeef); 89 EnumProcessModules(NULL, NULL, 0, &cbNeeded); 90 ok(GetLastError() == ERROR_INVALID_HANDLE, "expected error=ERROR_INVALID_HANDLE but got %d\n", GetLastError()); 91 92 SetLastError(0xdeadbeef); 93 EnumProcessModules(hpQI, NULL, 0, &cbNeeded); 94 ok(GetLastError() == ERROR_ACCESS_DENIED, "expected error=ERROR_ACCESS_DENIED but got %d\n", GetLastError()); 95 96 SetLastError(0xdeadbeef); 97 hMod = (void *)0xdeadbeef; 98 ret = EnumProcessModules(hpQI, &hMod, sizeof(HMODULE), NULL); 99 ok(!ret, "succeeded\n"); 100 ok(GetLastError() == ERROR_ACCESS_DENIED, "expected error=ERROR_ACCESS_DENIED but got %d\n", GetLastError()); 101 102 SetLastError(0xdeadbeef); 103 hMod = (void *)0xdeadbeef; 104 ret = EnumProcessModules(hpQV, &hMod, sizeof(HMODULE), NULL); 105 ok(!ret, "succeeded\n"); 106 ok(GetLastError() == ERROR_NOACCESS, "expected error=ERROR_NOACCESS but got %d\n", GetLastError()); 107 ok(hMod == GetModuleHandleA(NULL), 108 "hMod=%p GetModuleHandleA(NULL)=%p\n", hMod, GetModuleHandleA(NULL)); 109 110 SetLastError(0xdeadbeef); 111 ret = EnumProcessModules(hpQV, NULL, 0, &cbNeeded); 112 ok(ret == 1, "failed with %d\n", GetLastError()); 113 114 SetLastError(0xdeadbeef); 115 ret = EnumProcessModules(hpQV, NULL, sizeof(HMODULE), &cbNeeded); 116 ok(!ret, "succeeded\n"); 117 ok(GetLastError() == ERROR_NOACCESS, "expected error=ERROR_NOACCESS but got %d\n", GetLastError()); 118 119 SetLastError(0xdeadbeef); 120 hMod = (void *)0xdeadbeef; 121 ret = EnumProcessModules(hpQV, &hMod, sizeof(HMODULE), &cbNeeded); 122 ok(ret == 1, "got %d, failed with %d\n", ret, GetLastError()); 123 ok(hMod == GetModuleHandleA(NULL), 124 "hMod=%p GetModuleHandleA(NULL)=%p\n", hMod, GetModuleHandleA(NULL)); 125 ok(cbNeeded % sizeof(hMod) == 0, "not a multiple of sizeof(HMODULE) cbNeeded=%d\n", cbNeeded); 126 127 ret = CreateProcessA(NULL, buffer, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi); 128 ok(ret, "CreateProcess failed: %u\n", GetLastError()); 129 130 ret = WaitForInputIdle(pi.hProcess, 1000); 131 ok(!ret, "wait timed out\n"); 132 133 SetLastError(0xdeadbeef); 134 hMod = NULL; 135 ret = EnumProcessModules(pi.hProcess, &hMod, sizeof(HMODULE), &cbNeeded); 136 ok(ret == 1, "got %d, error %u\n", ret, GetLastError()); 137 ok(!!hMod, "expected non-NULL module\n"); 138 ok(cbNeeded % sizeof(hMod) == 0, "got %u\n", cbNeeded); 139 140 TerminateProcess(pi.hProcess, 0); 141 142 if (sizeof(void *) == 8) 143 { 144 MODULEINFO info; 145 char name[40]; 146 147 strcpy(buffer, "C:\\windows\\syswow64\\notepad.exe"); 148 ret = CreateProcessA(NULL, buffer, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi); 149 ok(ret, "CreateProcess failed: %u\n", GetLastError()); 150 151 ret = WaitForInputIdle(pi.hProcess, 1000); 152 ok(!ret, "wait timed out\n"); 153 154 SetLastError(0xdeadbeef); 155 hMod = NULL; 156 ret = EnumProcessModules(pi.hProcess, &hMod, sizeof(HMODULE), &cbNeeded); 157 ok(ret == 1, "got %d, error %u\n", ret, GetLastError()); 158 ok(!!hMod, "expected non-NULL module\n"); 159 ok(cbNeeded % sizeof(hMod) == 0, "got %u\n", cbNeeded); 160 161 ret = GetModuleBaseNameA(pi.hProcess, hMod, name, sizeof(name)); 162 ok(ret, "got error %u\n", GetLastError()); 163 ok(!strcmp(name, "notepad.exe"), "got %s\n", name); 164 165 ret = GetModuleFileNameExA(pi.hProcess, hMod, name, sizeof(name)); 166 ok(ret, "got error %u\n", GetLastError()); 167 todo_wine 168 ok(!strcmp(name, buffer), "got %s\n", name); 169 170 ret = GetModuleInformation(pi.hProcess, hMod, &info, sizeof(info)); 171 ok(ret, "got error %u\n", GetLastError()); 172 ok(info.lpBaseOfDll == hMod, "expected %p, got %p\n", hMod, info.lpBaseOfDll); 173 ok(info.SizeOfImage, "image size was 0\n"); 174 ok(info.EntryPoint >= info.lpBaseOfDll, "got entry point %p\n", info.EntryPoint); 175 176 TerminateProcess(pi.hProcess, 0); 177 } 178 else if (wow64) 179 { 180 pWow64DisableWow64FsRedirection(&cookie); 181 ret = CreateProcessA(NULL, buffer, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi); 182 pWow64RevertWow64FsRedirection(cookie); 183 ok(ret, "CreateProcess failed: %u\n", GetLastError()); 184 185 ret = WaitForInputIdle(pi.hProcess, 1000); 186 ok(!ret, "wait timed out\n"); 187 188 SetLastError(0xdeadbeef); 189 ret = EnumProcessModules(pi.hProcess, &hMod, sizeof(HMODULE), &cbNeeded); 190 ok(!ret, "got %d\n", ret); 191 todo_wine 192 ok(GetLastError() == ERROR_PARTIAL_COPY, "got error %u\n", GetLastError()); 193 194 TerminateProcess(pi.hProcess, 0); 195 } 196 } 197 198 static void test_GetModuleInformation(void) 199 { 200 HMODULE hMod = GetModuleHandleA(NULL); 201 DWORD *tmp, counter = 0; 202 MODULEINFO info; 203 DWORD ret; 204 205 SetLastError(0xdeadbeef); 206 GetModuleInformation(NULL, hMod, &info, sizeof(info)); 207 ok(GetLastError() == ERROR_INVALID_HANDLE, "expected error=ERROR_INVALID_HANDLE but got %d\n", GetLastError()); 208 209 SetLastError(0xdeadbeef); 210 GetModuleInformation(hpQI, hMod, &info, sizeof(info)); 211 ok(GetLastError() == ERROR_ACCESS_DENIED, "expected error=ERROR_ACCESS_DENIED but got %d\n", GetLastError()); 212 213 SetLastError(0xdeadbeef); 214 GetModuleInformation(hpQV, hBad, &info, sizeof(info)); 215 ok(GetLastError() == ERROR_INVALID_HANDLE, "expected error=ERROR_INVALID_HANDLE but got %d\n", GetLastError()); 216 217 SetLastError(0xdeadbeef); 218 GetModuleInformation(hpQV, hMod, &info, sizeof(info)-1); 219 ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER, "expected error=ERROR_INSUFFICIENT_BUFFER but got %d\n", GetLastError()); 220 221 ret = GetModuleInformation(hpQV, hMod, &info, sizeof(info)); 222 ok(ret == 1, "failed with %d\n", GetLastError()); 223 ok(info.lpBaseOfDll == hMod, "lpBaseOfDll=%p hMod=%p\n", info.lpBaseOfDll, hMod); 224 225 hMod = LoadLibraryA("shell32.dll"); 226 ok(hMod != NULL, "Failed to load shell32.dll, error: %u\n", GetLastError()); 227 228 ret = GetModuleInformation(hpQV, hMod, &info, sizeof(info)); 229 ok(ret == 1, "failed with %d\n", GetLastError()); 230 info.SizeOfImage /= sizeof(DWORD); 231 for (tmp = (DWORD *)hMod; info.SizeOfImage; info.SizeOfImage--) 232 counter ^= *tmp++; 233 trace("xor of shell32: %08x\n", counter); 234 235 FreeLibrary(hMod); 236 } 237 238 static BOOL check_with_margin(SIZE_T perf, SIZE_T sysperf, int margin) 239 { 240 return (perf >= max(sysperf, margin) - margin && perf <= sysperf + margin); 241 } 242 243 static void test_GetPerformanceInfo(void) 244 { 245 PERFORMANCE_INFORMATION info; 246 NTSTATUS status; 247 DWORD size; 248 BOOL ret; 249 250 SetLastError(0xdeadbeef); 251 ret = GetPerformanceInfo(&info, sizeof(info)-1); 252 ok(!ret, "GetPerformanceInfo unexpectedly succeeded\n"); 253 ok(GetLastError() == ERROR_BAD_LENGTH, "expected error=ERROR_BAD_LENGTH but got %d\n", GetLastError()); 254 255 if (!pNtQuerySystemInformation) 256 win_skip("NtQuerySystemInformation not found, skipping tests\n"); 257 else 258 { 259 char performance_buffer[sizeof(SYSTEM_PERFORMANCE_INFORMATION) + 16]; /* larger on w2k8/win7 */ 260 SYSTEM_PERFORMANCE_INFORMATION *sys_performance_info = (SYSTEM_PERFORMANCE_INFORMATION *)performance_buffer; 261 SYSTEM_PROCESS_INFORMATION *sys_process_info = NULL, *spi; 262 SYSTEM_BASIC_INFORMATION sys_basic_info; 263 DWORD process_count, handle_count, thread_count; 264 265 /* compare with values from SYSTEM_PERFORMANCE_INFORMATION */ 266 size = 0; 267 status = pNtQuerySystemInformation(SystemPerformanceInformation, sys_performance_info, sizeof(performance_buffer), &size); 268 ok(status == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %08x\n", status); 269 ok(size >= sizeof(SYSTEM_PERFORMANCE_INFORMATION), "incorrect length %d\n", size); 270 271 SetLastError(0xdeadbeef); 272 ret = GetPerformanceInfo(&info, sizeof(info)); 273 ok(ret, "GetPerformanceInfo failed with %d\n", GetLastError()); 274 ok(info.cb == sizeof(PERFORMANCE_INFORMATION), "got %d\n", info.cb); 275 276 ok(check_with_margin(info.CommitTotal, sys_performance_info->TotalCommittedPages, 288), 277 "expected approximately %ld but got %d\n", info.CommitTotal, sys_performance_info->TotalCommittedPages); 278 279 ok(check_with_margin(info.CommitLimit, sys_performance_info->TotalCommitLimit, 32), 280 "expected approximately %ld but got %d\n", info.CommitLimit, sys_performance_info->TotalCommitLimit); 281 282 ok(check_with_margin(info.CommitPeak, sys_performance_info->PeakCommitment, 32), 283 "expected approximately %ld but got %d\n", info.CommitPeak, sys_performance_info->PeakCommitment); 284 285 ok(check_with_margin(info.PhysicalAvailable, sys_performance_info->AvailablePages, 512), 286 "expected approximately %ld but got %d\n", info.PhysicalAvailable, sys_performance_info->AvailablePages); 287 288 /* TODO: info.SystemCache not checked yet - to which field(s) does this value correspond to? */ 289 290 ok(check_with_margin(info.KernelTotal, sys_performance_info->PagedPoolUsage + sys_performance_info->NonPagedPoolUsage, 256), 291 "expected approximately %ld but got %d\n", info.KernelTotal, 292 sys_performance_info->PagedPoolUsage + sys_performance_info->NonPagedPoolUsage); 293 294 ok(check_with_margin(info.KernelPaged, sys_performance_info->PagedPoolUsage, 256), 295 "expected approximately %ld but got %d\n", info.KernelPaged, sys_performance_info->PagedPoolUsage); 296 297 ok(check_with_margin(info.KernelNonpaged, sys_performance_info->NonPagedPoolUsage, 16), 298 "expected approximately %ld but got %d\n", info.KernelNonpaged, sys_performance_info->NonPagedPoolUsage); 299 300 /* compare with values from SYSTEM_BASIC_INFORMATION */ 301 size = 0; 302 status = pNtQuerySystemInformation(SystemBasicInformation, &sys_basic_info, sizeof(sys_basic_info), &size); 303 ok(status == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %08x\n", status); 304 ok(size >= sizeof(SYSTEM_BASIC_INFORMATION), "incorrect length %d\n", size); 305 306 ok(info.PhysicalTotal == sys_basic_info.MmNumberOfPhysicalPages, 307 "expected info.PhysicalTotal=%u but got %u\n", 308 sys_basic_info.MmNumberOfPhysicalPages, (ULONG)info.PhysicalTotal); 309 310 ok(info.PageSize == sys_basic_info.PageSize, 311 "expected info.PageSize=%u but got %u\n", 312 sys_basic_info.PageSize, (ULONG)info.PageSize); 313 314 /* compare with values from SYSTEM_PROCESS_INFORMATION */ 315 size = 0; 316 status = pNtQuerySystemInformation(SystemProcessInformation, NULL, 0, &size); 317 ok(status == STATUS_INFO_LENGTH_MISMATCH, "expected STATUS_INFO_LENGTH_MISMATCH, got %08x\n", status); 318 ok(size > 0, "incorrect length %d\n", size); 319 while (status == STATUS_INFO_LENGTH_MISMATCH) 320 { 321 sys_process_info = HeapAlloc(GetProcessHeap(), 0, size); 322 ok(sys_process_info != NULL, "failed to allocate memory\n"); 323 status = pNtQuerySystemInformation(SystemProcessInformation, sys_process_info, size, &size); 324 if (status == STATUS_SUCCESS) break; 325 HeapFree(GetProcessHeap(), 0, sys_process_info); 326 } 327 ok(status == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %08x\n", status); 328 329 process_count = handle_count = thread_count = 0; 330 for (spi = sys_process_info;; spi = (SYSTEM_PROCESS_INFORMATION *)(((char *)spi) + spi->NextEntryOffset)) 331 { 332 process_count++; 333 handle_count += spi->HandleCount; 334 thread_count += spi->dwThreadCount; 335 if (spi->NextEntryOffset == 0) break; 336 } 337 HeapFree(GetProcessHeap(), 0, sys_process_info); 338 339 ok(check_with_margin(info.HandleCount, handle_count, 256), 340 "expected approximately %d but got %d\n", info.HandleCount, handle_count); 341 342 ok(check_with_margin(info.ProcessCount, process_count, 4), 343 "expected approximately %d but got %d\n", info.ProcessCount, process_count); 344 345 ok(check_with_margin(info.ThreadCount, thread_count, 4), 346 "expected approximately %d but got %d\n", info.ThreadCount, thread_count); 347 } 348 } 349 350 351 static void test_GetProcessMemoryInfo(void) 352 { 353 PROCESS_MEMORY_COUNTERS pmc; 354 DWORD ret; 355 356 SetLastError(0xdeadbeef); 357 ret = GetProcessMemoryInfo(NULL, &pmc, sizeof(pmc)); 358 ok(!ret, "GetProcessMemoryInfo should fail\n"); 359 ok(GetLastError() == ERROR_INVALID_HANDLE, "expected error=ERROR_INVALID_HANDLE but got %d\n", GetLastError()); 360 361 SetLastError(0xdeadbeef); 362 ret = GetProcessMemoryInfo(hpSR, &pmc, sizeof(pmc)); 363 ok(!ret, "GetProcessMemoryInfo should fail\n"); 364 ok(GetLastError() == ERROR_ACCESS_DENIED, "expected error=ERROR_ACCESS_DENIED but got %d\n", GetLastError()); 365 366 SetLastError(0xdeadbeef); 367 ret = GetProcessMemoryInfo(hpQI, &pmc, sizeof(pmc)-1); 368 ok(!ret, "GetProcessMemoryInfo should fail\n"); 369 ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER, "expected error=ERROR_INSUFFICIENT_BUFFER but got %d\n", GetLastError()); 370 371 SetLastError(0xdeadbeef); 372 ret = GetProcessMemoryInfo(hpQI, &pmc, sizeof(pmc)); 373 ok(ret == 1, "failed with %d\n", GetLastError()); 374 } 375 376 static BOOL nt_get_mapped_file_name(HANDLE process, LPVOID addr, LPWSTR name, DWORD len) 377 { 378 MEMORY_SECTION_NAME *section_name; 379 WCHAR *buf; 380 SIZE_T buf_len, ret_len; 381 NTSTATUS status; 382 383 if (!pNtQueryVirtualMemory) return FALSE; 384 385 buf_len = len * sizeof(WCHAR) + sizeof(MEMORY_SECTION_NAME); 386 buf = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, buf_len); 387 388 ret_len = 0xdeadbeef; 389 status = pNtQueryVirtualMemory(process, addr, MemorySectionName, buf, buf_len, &ret_len); 390 ok(!status, "NtQueryVirtualMemory error %x\n", status); 391 392 section_name = (MEMORY_SECTION_NAME *)buf; 393 ok(ret_len == section_name->SectionFileName.MaximumLength + sizeof(*section_name), "got %lu, %u\n", 394 ret_len, section_name->SectionFileName.MaximumLength); 395 ok((char *)section_name->SectionFileName.Buffer == (char *)section_name + sizeof(*section_name), "got %p, %p\n", 396 section_name, section_name->SectionFileName.Buffer); 397 ok(section_name->SectionFileName.MaximumLength == section_name->SectionFileName.Length + sizeof(WCHAR), "got %u, %u\n", 398 section_name->SectionFileName.MaximumLength, section_name->SectionFileName.Length); 399 ok(section_name->SectionFileName.Length == lstrlenW(section_name->SectionFileName.Buffer) * sizeof(WCHAR), "got %u, %u\n", 400 section_name->SectionFileName.Length, lstrlenW(section_name->SectionFileName.Buffer)); 401 402 memcpy(name, section_name->SectionFileName.Buffer, section_name->SectionFileName.MaximumLength); 403 HeapFree(GetProcessHeap(), 0, buf); 404 return TRUE; 405 } 406 407 static void test_GetMappedFileName(void) 408 { 409 HMODULE hMod = GetModuleHandleA(NULL); 410 char szMapPath[MAX_PATH], szModPath[MAX_PATH], *szMapBaseName; 411 DWORD ret; 412 char *base; 413 char temp_path[MAX_PATH], file_name[MAX_PATH], map_name[MAX_PATH], device_name[MAX_PATH], drive[3]; 414 WCHAR map_nameW[MAX_PATH], nt_map_name[MAX_PATH]; 415 HANDLE hfile, hmap; 416 HANDLE current_process; 417 418 DuplicateHandle( GetCurrentProcess(), GetCurrentProcess(), 419 GetCurrentProcess(), ¤t_process, 0, 0, DUPLICATE_SAME_ACCESS ); 420 421 SetLastError(0xdeadbeef); 422 ret = GetMappedFileNameA(NULL, hMod, szMapPath, sizeof(szMapPath)); 423 ok(!ret, "GetMappedFileName should fail\n"); 424 ok(GetLastError() == ERROR_INVALID_HANDLE, "expected error=ERROR_INVALID_HANDLE but got %d\n", GetLastError()); 425 426 SetLastError(0xdeadbeef); 427 ret = GetMappedFileNameA(hpSR, hMod, szMapPath, sizeof(szMapPath)); 428 ok(!ret, "GetMappedFileName should fail\n"); 429 ok(GetLastError() == ERROR_ACCESS_DENIED, "expected error=ERROR_ACCESS_DENIED but got %d\n", GetLastError()); 430 431 SetLastError( 0xdeadbeef ); 432 ret = GetMappedFileNameA(hpQI, hMod, szMapPath, sizeof(szMapPath)); 433 ok( ret || broken(GetLastError() == ERROR_UNEXP_NET_ERR), /* win2k */ 434 "GetMappedFileNameA failed with error %u\n", GetLastError() ); 435 if (ret) 436 { 437 ok(ret == strlen(szMapPath), "szMapPath=\"%s\" ret=%d\n", szMapPath, ret); 438 ok(szMapPath[0] == '\\', "szMapPath=\"%s\"\n", szMapPath); 439 szMapBaseName = strrchr(szMapPath, '\\'); /* That's close enough for us */ 440 ok(szMapBaseName && *szMapBaseName, "szMapPath=\"%s\"\n", szMapPath); 441 if (szMapBaseName) 442 { 443 GetModuleFileNameA(NULL, szModPath, sizeof(szModPath)); 444 ok(!strcmp(strrchr(szModPath, '\\'), szMapBaseName), 445 "szModPath=\"%s\" szMapBaseName=\"%s\"\n", szModPath, szMapBaseName); 446 } 447 } 448 449 GetTempPathA(MAX_PATH, temp_path); 450 GetTempFileNameA(temp_path, "map", 0, file_name); 451 452 drive[0] = file_name[0]; 453 drive[1] = ':'; 454 drive[2] = 0; 455 SetLastError(0xdeadbeef); 456 ret = QueryDosDeviceA(drive, device_name, sizeof(device_name)); 457 ok(ret, "QueryDosDeviceA error %d\n", GetLastError()); 458 trace("%s -> %s\n", drive, device_name); 459 460 SetLastError(0xdeadbeef); 461 hfile = CreateFileA(file_name, GENERIC_READ | GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, 0); 462 ok(hfile != INVALID_HANDLE_VALUE, "CreateFileA(%s) error %d\n", file_name, GetLastError()); 463 SetFilePointer(hfile, 0x4000, NULL, FILE_BEGIN); 464 SetEndOfFile(hfile); 465 466 SetLastError(0xdeadbeef); 467 hmap = CreateFileMappingA(hfile, NULL, PAGE_READONLY | SEC_COMMIT, 0, 0, NULL); 468 ok(hmap != 0, "CreateFileMappingA error %d\n", GetLastError()); 469 470 SetLastError(0xdeadbeef); 471 base = MapViewOfFile(hmap, FILE_MAP_READ, 0, 0, 0); 472 ok(base != NULL, "MapViewOfFile error %d\n", GetLastError()); 473 474 SetLastError(0xdeadbeef); 475 ret = GetMappedFileNameA(GetCurrentProcess(), base, map_name, 0); 476 ok(!ret, "GetMappedFileName should fail\n"); 477 ok(GetLastError() == ERROR_INVALID_PARAMETER || GetLastError() == ERROR_INSUFFICIENT_BUFFER, 478 "wrong error %d\n", GetLastError()); 479 480 SetLastError(0xdeadbeef); 481 ret = GetMappedFileNameA(GetCurrentProcess(), base, 0, sizeof(map_name)); 482 ok(!ret, "GetMappedFileName should fail\n"); 483 ok(GetLastError() == ERROR_INVALID_PARAMETER, "expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError()); 484 485 SetLastError(0xdeadbeef); 486 ret = GetMappedFileNameA(GetCurrentProcess(), base, map_name, 1); 487 ok(ret == 1, "GetMappedFileName error %d\n", GetLastError()); 488 ok(!map_name[0] || broken(map_name[0] == device_name[0]) /* before win2k */, "expected 0, got %c\n", map_name[0]); 489 490 SetLastError(0xdeadbeef); 491 ret = GetMappedFileNameA(GetCurrentProcess(), base, map_name, sizeof(map_name)); 492 ok(ret, "GetMappedFileName error %d\n", GetLastError()); 493 ok(ret > strlen(device_name), "map_name should be longer than device_name\n"); 494 ok(memcmp(map_name, device_name, strlen(device_name)) == 0, "map name does not start with a device name: %s\n", map_name); 495 496 SetLastError(0xdeadbeef); 497 ret = GetMappedFileNameW(GetCurrentProcess(), base, map_nameW, ARRAY_SIZE(map_nameW)); 498 todo_wine { 499 ok(ret, "GetMappedFileNameW error %d\n", GetLastError()); 500 ok(ret > strlen(device_name), "map_name should be longer than device_name\n"); 501 } 502 if (nt_get_mapped_file_name(GetCurrentProcess(), base, nt_map_name, ARRAY_SIZE(nt_map_name))) 503 { 504 ok(memcmp(map_nameW, nt_map_name, lstrlenW(map_nameW)) == 0, "map name does not start with a device name: %s\n", map_name); 505 WideCharToMultiByte(CP_ACP, 0, map_nameW, -1, map_name, MAX_PATH, NULL, NULL); 506 ok(memcmp(map_name, device_name, strlen(device_name)) == 0, "map name does not start with a device name: %s\n", map_name); 507 } 508 509 SetLastError(0xdeadbeef); 510 ret = GetMappedFileNameW(current_process, base, map_nameW, sizeof(map_nameW)/sizeof(map_nameW[0])); 511 ok(ret, "GetMappedFileNameW error %d\n", GetLastError()); 512 ok(ret > strlen(device_name), "map_name should be longer than device_name\n"); 513 514 if (nt_get_mapped_file_name(current_process, base, nt_map_name, sizeof(nt_map_name)/sizeof(nt_map_name[0]))) 515 { 516 ok(memcmp(map_nameW, nt_map_name, lstrlenW(map_nameW)) == 0, "map name does not start with a device name: %s\n", map_name); 517 WideCharToMultiByte(CP_ACP, 0, map_nameW, -1, map_name, MAX_PATH, NULL, NULL); 518 ok(memcmp(map_name, device_name, strlen(device_name)) == 0, "map name does not start with a device name: %s\n", map_name); 519 } 520 521 SetLastError(0xdeadbeef); 522 ret = GetMappedFileNameA(GetCurrentProcess(), base + 0x2000, map_name, sizeof(map_name)); 523 ok(ret, "GetMappedFileName error %d\n", GetLastError()); 524 ok(ret > strlen(device_name), "map_name should be longer than device_name\n"); 525 ok(memcmp(map_name, device_name, strlen(device_name)) == 0, "map name does not start with a device name: %s\n", map_name); 526 527 SetLastError(0xdeadbeef); 528 ret = GetMappedFileNameA(GetCurrentProcess(), base + 0x4000, map_name, sizeof(map_name)); 529 ok(!ret, "GetMappedFileName should fail\n"); 530 ok(GetLastError() == ERROR_UNEXP_NET_ERR, "expected ERROR_UNEXP_NET_ERR, got %d\n", GetLastError()); 531 532 SetLastError(0xdeadbeef); 533 ret = GetMappedFileNameA(GetCurrentProcess(), NULL, map_name, sizeof(map_name)); 534 ok(!ret, "GetMappedFileName should fail\n"); 535 todo_wine 536 ok(GetLastError() == ERROR_UNEXP_NET_ERR, "expected ERROR_UNEXP_NET_ERR, got %d\n", GetLastError()); 537 538 SetLastError(0xdeadbeef); 539 ret = GetMappedFileNameA(0, base, map_name, sizeof(map_name)); 540 ok(!ret, "GetMappedFileName should fail\n"); 541 ok(GetLastError() == ERROR_INVALID_HANDLE, "expected ERROR_INVALID_HANDLE, got %d\n", GetLastError()); 542 543 UnmapViewOfFile(base); 544 CloseHandle(hmap); 545 CloseHandle(hfile); 546 DeleteFileA(file_name); 547 548 SetLastError(0xdeadbeef); 549 hmap = CreateFileMappingA(INVALID_HANDLE_VALUE, NULL, PAGE_READONLY | SEC_COMMIT, 0, 4096, NULL); 550 ok(hmap != 0, "CreateFileMappingA error %d\n", GetLastError()); 551 552 SetLastError(0xdeadbeef); 553 base = MapViewOfFile(hmap, FILE_MAP_READ, 0, 0, 0); 554 ok(base != NULL, "MapViewOfFile error %d\n", GetLastError()); 555 556 SetLastError(0xdeadbeef); 557 ret = GetMappedFileNameA(GetCurrentProcess(), base, map_name, sizeof(map_name)); 558 ok(!ret, "GetMappedFileName should fail\n"); 559 ok(GetLastError() == ERROR_FILE_INVALID, "expected ERROR_FILE_INVALID, got %d\n", GetLastError()); 560 561 CloseHandle(current_process); 562 UnmapViewOfFile(base); 563 CloseHandle(hmap); 564 } 565 566 static void test_GetProcessImageFileName(void) 567 { 568 HMODULE hMod = GetModuleHandleA(NULL); 569 char szImgPath[MAX_PATH], szMapPath[MAX_PATH]; 570 WCHAR szImgPathW[MAX_PATH]; 571 DWORD ret, ret1; 572 573 /* This function is available on WinXP+ only */ 574 SetLastError(0xdeadbeef); 575 if(!GetProcessImageFileNameA(hpQI, szImgPath, sizeof(szImgPath))) 576 { 577 if(GetLastError() == ERROR_INVALID_FUNCTION) { 578 win_skip("GetProcessImageFileName not implemented\n"); 579 return; 580 } 581 582 if(GetLastError() == 0xdeadbeef) 583 todo_wine ok(0, "failed without error code\n"); 584 else 585 todo_wine ok(0, "failed with %d\n", GetLastError()); 586 } 587 588 SetLastError(0xdeadbeef); 589 GetProcessImageFileNameA(NULL, szImgPath, sizeof(szImgPath)); 590 ok(GetLastError() == ERROR_INVALID_HANDLE, "expected error=ERROR_INVALID_HANDLE but got %d\n", GetLastError()); 591 592 SetLastError(0xdeadbeef); 593 GetProcessImageFileNameA(hpSR, szImgPath, sizeof(szImgPath)); 594 ok(GetLastError() == ERROR_ACCESS_DENIED, "expected error=ERROR_ACCESS_DENIED but got %d\n", GetLastError()); 595 596 SetLastError(0xdeadbeef); 597 GetProcessImageFileNameA(hpQI, szImgPath, 0); 598 ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER, "expected error=ERROR_INSUFFICIENT_BUFFER but got %d\n", GetLastError()); 599 600 ret = GetProcessImageFileNameA(hpQI, szImgPath, sizeof(szImgPath)); 601 ret1 = GetMappedFileNameA(hpQV, hMod, szMapPath, sizeof(szMapPath)); 602 if(ret && ret1) 603 { 604 /* Windows returns 2*strlen-1 */ 605 ok(ret >= strlen(szImgPath), "szImgPath=\"%s\" ret=%d\n", szImgPath, ret); 606 ok(!strcmp(szImgPath, szMapPath), "szImgPath=\"%s\" szMapPath=\"%s\"\n", szImgPath, szMapPath); 607 } 608 609 SetLastError(0xdeadbeef); 610 GetProcessImageFileNameW(NULL, szImgPathW, ARRAY_SIZE(szImgPathW)); 611 ok(GetLastError() == ERROR_INVALID_HANDLE, "expected error=ERROR_INVALID_HANDLE but got %d\n", GetLastError()); 612 613 /* no information about correct buffer size returned: */ 614 SetLastError(0xdeadbeef); 615 GetProcessImageFileNameW(hpQI, szImgPathW, 0); 616 ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER, "expected error=ERROR_INSUFFICIENT_BUFFER but got %d\n", GetLastError()); 617 618 SetLastError(0xdeadbeef); 619 GetProcessImageFileNameW(hpQI, NULL, 0); 620 ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER, "expected error=ERROR_INSUFFICIENT_BUFFER but got %d\n", GetLastError()); 621 622 /* correct call */ 623 memset(szImgPathW, 0xff, sizeof(szImgPathW)); 624 ret = GetProcessImageFileNameW(hpQI, szImgPathW, ARRAY_SIZE(szImgPathW)); 625 ok(ret > 0, "GetProcessImageFileNameW should have succeeded.\n"); 626 ok(szImgPathW[0] == '\\', "GetProcessImageFileNameW should have returned an NT path.\n"); 627 ok(lstrlenW(szImgPathW) == ret, "Expected length to be %d, got %d\n", ret, lstrlenW(szImgPathW)); 628 629 /* boundary values of 'size' */ 630 SetLastError(0xdeadbeef); 631 GetProcessImageFileNameW(hpQI, szImgPathW, ret); 632 ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER, "expected error=ERROR_INSUFFICIENT_BUFFER but got %d\n", GetLastError()); 633 634 memset(szImgPathW, 0xff, sizeof(szImgPathW)); 635 ret = GetProcessImageFileNameW(hpQI, szImgPathW, ret + 1); 636 ok(ret > 0, "GetProcessImageFileNameW should have succeeded.\n"); 637 ok(szImgPathW[0] == '\\', "GetProcessImageFileNameW should have returned an NT path.\n"); 638 ok(lstrlenW(szImgPathW) == ret, "Expected length to be %d, got %d\n", ret, lstrlenW(szImgPathW)); 639 } 640 641 static void test_GetModuleFileNameEx(void) 642 { 643 HMODULE hMod = GetModuleHandleA(NULL); 644 char szModExPath[MAX_PATH+1], szModPath[MAX_PATH+1]; 645 WCHAR buffer[MAX_PATH]; 646 DWORD ret; 647 648 SetLastError(0xdeadbeef); 649 ret = GetModuleFileNameExA(NULL, hMod, szModExPath, sizeof(szModExPath)); 650 ok( !ret, "GetModuleFileNameExA succeeded\n" ); 651 ok(GetLastError() == ERROR_INVALID_HANDLE, "expected error=ERROR_INVALID_HANDLE but got %d\n", GetLastError()); 652 653 SetLastError(0xdeadbeef); 654 ret = GetModuleFileNameExA(hpQI, hMod, szModExPath, sizeof(szModExPath)); 655 ok( !ret, "GetModuleFileNameExA succeeded\n" ); 656 ok(GetLastError() == ERROR_ACCESS_DENIED, "expected error=ERROR_ACCESS_DENIED but got %d\n", GetLastError()); 657 658 SetLastError(0xdeadbeef); 659 ret = GetModuleFileNameExA(hpQV, hBad, szModExPath, sizeof(szModExPath)); 660 ok( !ret, "GetModuleFileNameExA succeeded\n" ); 661 ok(GetLastError() == ERROR_INVALID_HANDLE, "expected error=ERROR_INVALID_HANDLE but got %d\n", GetLastError()); 662 663 ret = GetModuleFileNameExA(hpQV, NULL, szModExPath, sizeof(szModExPath)); 664 if(!ret) 665 return; 666 ok(ret == strlen(szModExPath), "szModExPath=\"%s\" ret=%d\n", szModExPath, ret); 667 GetModuleFileNameA(NULL, szModPath, sizeof(szModPath)); 668 ok(!strncmp(szModExPath, szModPath, MAX_PATH), 669 "szModExPath=\"%s\" szModPath=\"%s\"\n", szModExPath, szModPath); 670 671 SetLastError(0xdeadbeef); 672 memset( szModExPath, 0xcc, sizeof(szModExPath) ); 673 ret = GetModuleFileNameExA(hpQV, NULL, szModExPath, 4 ); 674 ok( ret == 4 || ret == strlen(szModExPath), "wrong length %u\n", ret ); 675 ok( broken(szModExPath[3]) /*w2kpro*/ || strlen(szModExPath) == 3, 676 "szModExPath=\"%s\" ret=%d\n", szModExPath, ret ); 677 ok(GetLastError() == 0xdeadbeef, "got error %d\n", GetLastError()); 678 679 if (0) /* crashes on Windows 10 */ 680 { 681 SetLastError(0xdeadbeef); 682 ret = GetModuleFileNameExA(hpQV, NULL, szModExPath, 0 ); 683 ok( ret == 0, "wrong length %u\n", ret ); 684 ok(GetLastError() == ERROR_INVALID_PARAMETER, "got error %d\n", GetLastError()); 685 } 686 687 SetLastError(0xdeadbeef); 688 memset( buffer, 0xcc, sizeof(buffer) ); 689 ret = GetModuleFileNameExW(hpQV, NULL, buffer, 4 ); 690 ok( ret == 4 || ret == lstrlenW(buffer), "wrong length %u\n", ret ); 691 ok( broken(buffer[3]) /*w2kpro*/ || lstrlenW(buffer) == 3, 692 "buffer=%s ret=%d\n", wine_dbgstr_w(buffer), ret ); 693 ok(GetLastError() == 0xdeadbeef, "got error %d\n", GetLastError()); 694 695 if (0) /* crashes on Windows 10 */ 696 { 697 SetLastError(0xdeadbeef); 698 buffer[0] = 0xcc; 699 ret = GetModuleFileNameExW(hpQV, NULL, buffer, 0 ); 700 ok( ret == 0, "wrong length %u\n", ret ); 701 ok(GetLastError() == 0xdeadbeef, "got error %d\n", GetLastError()); 702 ok( buffer[0] == 0xcc, "buffer modified %s\n", wine_dbgstr_w(buffer) ); 703 } 704 } 705 706 static void test_GetModuleBaseName(void) 707 { 708 HMODULE hMod = GetModuleHandleA(NULL); 709 char szModPath[MAX_PATH], szModBaseName[MAX_PATH]; 710 DWORD ret; 711 712 SetLastError(0xdeadbeef); 713 GetModuleBaseNameA(NULL, hMod, szModBaseName, sizeof(szModBaseName)); 714 ok(GetLastError() == ERROR_INVALID_HANDLE, "expected error=ERROR_INVALID_HANDLE but got %d\n", GetLastError()); 715 716 SetLastError(0xdeadbeef); 717 GetModuleBaseNameA(hpQI, hMod, szModBaseName, sizeof(szModBaseName)); 718 ok(GetLastError() == ERROR_ACCESS_DENIED, "expected error=ERROR_ACCESS_DENIED but got %d\n", GetLastError()); 719 720 SetLastError(0xdeadbeef); 721 GetModuleBaseNameA(hpQV, hBad, szModBaseName, sizeof(szModBaseName)); 722 ok(GetLastError() == ERROR_INVALID_HANDLE, "expected error=ERROR_INVALID_HANDLE but got %d\n", GetLastError()); 723 724 ret = GetModuleBaseNameA(hpQV, NULL, szModBaseName, sizeof(szModBaseName)); 725 if(!ret) 726 return; 727 ok(ret == strlen(szModBaseName), "szModBaseName=\"%s\" ret=%d\n", szModBaseName, ret); 728 GetModuleFileNameA(NULL, szModPath, sizeof(szModPath)); 729 ok(!strcmp(strrchr(szModPath, '\\') + 1, szModBaseName), 730 "szModPath=\"%s\" szModBaseName=\"%s\"\n", szModPath, szModBaseName); 731 } 732 733 static void test_ws_functions(void) 734 { 735 PSAPI_WS_WATCH_INFORMATION wswi[4096]; 736 ULONG_PTR pages[4096]; 737 HANDLE ws_handle; 738 char *addr; 739 unsigned int i; 740 BOOL ret; 741 742 ws_handle = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_SET_QUOTA | 743 PROCESS_SET_INFORMATION, FALSE, GetCurrentProcessId()); 744 ok(!!ws_handle, "got error %u\n", GetLastError()); 745 746 SetLastError(0xdeadbeef); 747 EmptyWorkingSet(NULL); 748 todo_wine ok(GetLastError() == ERROR_INVALID_HANDLE, "expected error=ERROR_INVALID_HANDLE but got %d\n", GetLastError()); 749 750 SetLastError(0xdeadbeef); 751 EmptyWorkingSet(hpSR); 752 todo_wine ok(GetLastError() == ERROR_ACCESS_DENIED, "expected error=ERROR_ACCESS_DENIED but got %d\n", GetLastError()); 753 754 SetLastError(0xdeadbeef); 755 ret = EmptyWorkingSet(ws_handle); 756 ok(ret == 1, "failed with %d\n", GetLastError()); 757 758 SetLastError( 0xdeadbeef ); 759 ret = InitializeProcessForWsWatch( NULL ); 760 todo_wine ok( !ret, "InitializeProcessForWsWatch succeeded\n" ); 761 if (!ret) 762 { 763 if (GetLastError() == ERROR_INVALID_FUNCTION) /* not supported on xp in wow64 mode */ 764 { 765 trace( "InitializeProcessForWsWatch not supported\n" ); 766 return; 767 } 768 ok( GetLastError() == ERROR_INVALID_HANDLE, "wrong error %u\n", GetLastError() ); 769 } 770 SetLastError(0xdeadbeef); 771 ret = InitializeProcessForWsWatch(ws_handle); 772 ok(ret == 1, "failed with %d\n", GetLastError()); 773 774 addr = VirtualAlloc(NULL, 1, MEM_COMMIT, PAGE_READWRITE); 775 if(!addr) 776 return; 777 778 *addr = 0; /* make sure it's paged in (needed on wow64) */ 779 if(!VirtualLock(addr, 1)) 780 { 781 trace("locking failed (error=%d) - skipping test\n", GetLastError()); 782 goto free_page; 783 } 784 785 SetLastError(0xdeadbeef); 786 ret = QueryWorkingSet(hpQI, pages, 4096 * sizeof(ULONG_PTR)); 787 todo_wine ok(ret == 1, "failed with %d\n", GetLastError()); 788 if(ret == 1) 789 { 790 for(i = 0; i < pages[0]; i++) 791 if((pages[i+1] & ~0xfffL) == (ULONG_PTR)addr) 792 { 793 todo_wine ok(ret == 1, "QueryWorkingSet found our page\n"); 794 goto test_gwsc; 795 } 796 797 todo_wine ok(0, "QueryWorkingSet didn't find our page\n"); 798 } 799 800 test_gwsc: 801 SetLastError(0xdeadbeef); 802 ret = GetWsChanges(hpQI, wswi, sizeof(wswi)); 803 todo_wine ok(ret == 1, "failed with %d\n", GetLastError()); 804 if(ret == 1) 805 { 806 for(i = 0; wswi[i].FaultingVa; i++) 807 if(((ULONG_PTR)wswi[i].FaultingVa & ~0xfffL) == (ULONG_PTR)addr) 808 { 809 todo_wine ok(ret == 1, "GetWsChanges found our page\n"); 810 goto free_page; 811 } 812 813 todo_wine ok(0, "GetWsChanges didn't find our page\n"); 814 } 815 816 free_page: 817 VirtualFree(addr, 0, MEM_RELEASE); 818 } 819 820 START_TEST(psapi_main) 821 { 822 DWORD pid = GetCurrentProcessId(); 823 824 init_func_ptrs(); 825 826 if (pIsWow64Process) 827 IsWow64Process(GetCurrentProcess(), &wow64); 828 829 hpSR = OpenProcess(STANDARD_RIGHTS_REQUIRED, FALSE, pid); 830 ok(!!hpSR, "got error %u\n", GetLastError()); 831 hpQI = OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, pid); 832 ok(!!hpQI, "got error %u\n", GetLastError()); 833 hpVR = OpenProcess(PROCESS_VM_READ, FALSE, pid); 834 ok(!!hpVR, "got error %u\n", GetLastError()); 835 hpQV = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, pid); 836 ok(!!hpQV, "got error %u\n", GetLastError()); 837 838 test_EnumProcesses(); 839 test_EnumProcessModules(); 840 test_GetModuleInformation(); 841 test_GetPerformanceInfo(); 842 test_GetProcessMemoryInfo(); 843 test_GetMappedFileName(); 844 test_GetProcessImageFileName(); 845 test_GetModuleFileNameEx(); 846 test_GetModuleBaseName(); 847 test_ws_functions(); 848 849 CloseHandle(hpSR); 850 CloseHandle(hpQI); 851 CloseHandle(hpVR); 852 CloseHandle(hpQV); 853 } 854