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