[PSAPI_WINETEST]
[reactos.git] / rostests / winetests / psapi / psapi_main.c
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 "winternl.h"
32 #include "winnls.h"
33 #include "psapi.h"
34 #include "wine/test.h"
35
36 #define PSAPI_GET_PROC(func) \
37 p ## func = (void*)GetProcAddress(hpsapi, #func); \
38 if(!p ## func) { \
39 ok(0, "GetProcAddress(%s) failed\n", #func); \
40 FreeLibrary(hpsapi); \
41 return FALSE; \
42 }
43
44 static BOOL (WINAPI *pEmptyWorkingSet)(HANDLE);
45 static BOOL (WINAPI *pEnumProcesses)(DWORD*, DWORD, DWORD*);
46 static BOOL (WINAPI *pEnumProcessModules)(HANDLE, HMODULE*, DWORD, LPDWORD);
47 static DWORD (WINAPI *pGetModuleBaseNameA)(HANDLE, HMODULE, LPSTR, DWORD);
48 static DWORD (WINAPI *pGetModuleFileNameExA)(HANDLE, HMODULE, LPSTR, DWORD);
49 static DWORD (WINAPI *pGetModuleFileNameExW)(HANDLE, HMODULE, LPWSTR, DWORD);
50 static BOOL (WINAPI *pGetModuleInformation)(HANDLE, HMODULE, LPMODULEINFO, DWORD);
51 static DWORD (WINAPI *pGetMappedFileNameA)(HANDLE, LPVOID, LPSTR, DWORD);
52 static DWORD (WINAPI *pGetMappedFileNameW)(HANDLE, LPVOID, LPWSTR, DWORD);
53 static DWORD (WINAPI *pGetProcessImageFileNameA)(HANDLE, LPSTR, DWORD);
54 static DWORD (WINAPI *pGetProcessImageFileNameW)(HANDLE, LPWSTR, DWORD);
55 static BOOL (WINAPI *pGetProcessMemoryInfo)(HANDLE, PPROCESS_MEMORY_COUNTERS, DWORD);
56 static BOOL (WINAPI *pGetWsChanges)(HANDLE, PPSAPI_WS_WATCH_INFORMATION, DWORD);
57 static BOOL (WINAPI *pInitializeProcessForWsWatch)(HANDLE);
58 static BOOL (WINAPI *pQueryWorkingSet)(HANDLE, PVOID, DWORD);
59 static NTSTATUS (WINAPI *pNtQueryVirtualMemory)(HANDLE, LPCVOID, ULONG, PVOID, SIZE_T, SIZE_T *);
60
61 static BOOL InitFunctionPtrs(HMODULE hpsapi)
62 {
63 PSAPI_GET_PROC(EmptyWorkingSet);
64 PSAPI_GET_PROC(EnumProcessModules);
65 PSAPI_GET_PROC(EnumProcesses);
66 PSAPI_GET_PROC(GetModuleBaseNameA);
67 PSAPI_GET_PROC(GetModuleFileNameExA);
68 PSAPI_GET_PROC(GetModuleFileNameExW);
69 PSAPI_GET_PROC(GetModuleInformation);
70 PSAPI_GET_PROC(GetMappedFileNameA);
71 PSAPI_GET_PROC(GetMappedFileNameW);
72 PSAPI_GET_PROC(GetProcessMemoryInfo);
73 PSAPI_GET_PROC(GetWsChanges);
74 PSAPI_GET_PROC(InitializeProcessForWsWatch);
75 PSAPI_GET_PROC(QueryWorkingSet);
76 /* GetProcessImageFileName is not exported on NT4 */
77 pGetProcessImageFileNameA =
78 (void *)GetProcAddress(hpsapi, "GetProcessImageFileNameA");
79 pGetProcessImageFileNameW =
80 (void *)GetProcAddress(hpsapi, "GetProcessImageFileNameW");
81 pNtQueryVirtualMemory = (void *)GetProcAddress(GetModuleHandle("ntdll.dll"), "NtQueryVirtualMemory");
82 return TRUE;
83 }
84
85 static HANDLE hpSR, hpQI, hpVR, hpQV, hpAA;
86 static const HANDLE hBad = (HANDLE)0xdeadbeef;
87
88 static void test_EnumProcesses(void)
89 {
90 DWORD pid, ret, cbUsed = 0xdeadbeef;
91
92 SetLastError(0xdeadbeef);
93 ret = pEnumProcesses(NULL, 0, &cbUsed);
94 ok(ret == 1, "failed with %d\n", GetLastError());
95 ok(cbUsed == 0, "cbUsed=%d\n", cbUsed);
96
97 SetLastError(0xdeadbeef);
98 ret = pEnumProcesses(&pid, 4, &cbUsed);
99 ok(ret == 1, "failed with %d\n", GetLastError());
100 ok(cbUsed == 4, "cbUsed=%d\n", cbUsed);
101 }
102
103 static void test_EnumProcessModules(void)
104 {
105 HMODULE hMod = GetModuleHandle(NULL);
106 DWORD ret, cbNeeded = 0xdeadbeef;
107
108 if(!winetest_interactive)
109 win_skip("Stack corruption - ROSTEST-122\n");
110 return;
111
112 SetLastError(0xdeadbeef);
113 pEnumProcessModules(NULL, NULL, 0, &cbNeeded);
114 ok(GetLastError() == ERROR_INVALID_HANDLE, "expected error=ERROR_INVALID_HANDLE but got %d\n", GetLastError());
115
116 SetLastError(0xdeadbeef);
117 pEnumProcessModules(hpQI, NULL, 0, &cbNeeded);
118 ok(GetLastError() == ERROR_ACCESS_DENIED, "expected error=ERROR_ACCESS_DENIED but got %d\n", GetLastError());
119
120 SetLastError(0xdeadbeef);
121 ret = pEnumProcessModules(hpQI, &hMod, sizeof(HMODULE), NULL);
122 ok(!ret, "succeeded\n");
123 ok(GetLastError() == ERROR_ACCESS_DENIED, "expected error=ERROR_ACCESS_DENIED but got %d\n", GetLastError());
124
125 SetLastError(0xdeadbeef);
126 ret = pEnumProcessModules(hpQV, &hMod, sizeof(HMODULE), NULL);
127 ok(!ret, "succeeded\n");
128 ok(GetLastError() == ERROR_NOACCESS, "expected error=ERROR_NOACCESS but got %d\n", GetLastError());
129
130 SetLastError(0xdeadbeef);
131 ret = pEnumProcessModules(hpQV, NULL, 0, &cbNeeded);
132 ok(ret == 1, "failed with %d\n", GetLastError());
133
134 SetLastError(0xdeadbeef);
135 ret = pEnumProcessModules(hpQV, &hMod, sizeof(HMODULE), &cbNeeded);
136 if(ret != 1)
137 return;
138 ok(hMod == GetModuleHandle(NULL),
139 "hMod=%p GetModuleHandle(NULL)=%p\n", hMod, GetModuleHandle(NULL));
140 ok(cbNeeded % sizeof(hMod) == 0, "not a multiple of sizeof(HMODULE) cbNeeded=%d\n", cbNeeded);
141 /* Windows sometimes has a bunch of extra dlls, presumably brought in by
142 * aclayers.dll.
143 */
144 if (cbNeeded < 4 * sizeof(HMODULE) || cbNeeded > 30 * sizeof(HMODULE))
145 {
146 HMODULE hmods[100];
147 int i;
148 ok(0, "cbNeeded=%d\n", cbNeeded);
149
150 pEnumProcessModules(hpQV, hmods, sizeof(hmods), &cbNeeded);
151 for (i = 0 ; i < cbNeeded/sizeof(*hmods); i++)
152 {
153 char path[1024];
154 GetModuleFileNameA(hmods[i], path, sizeof(path));
155 trace("i=%d hmod=%p path=[%s]\n", i, hmods[i], path);
156 }
157 }
158 }
159
160 static void test_GetModuleInformation(void)
161 {
162 HMODULE hMod = GetModuleHandle(NULL);
163 MODULEINFO info;
164 DWORD ret;
165
166 SetLastError(0xdeadbeef);
167 pGetModuleInformation(NULL, hMod, &info, sizeof(info));
168 ok(GetLastError() == ERROR_INVALID_HANDLE, "expected error=ERROR_INVALID_HANDLE but got %d\n", GetLastError());
169
170 SetLastError(0xdeadbeef);
171 pGetModuleInformation(hpQI, hMod, &info, sizeof(info));
172 ok(GetLastError() == ERROR_ACCESS_DENIED, "expected error=ERROR_ACCESS_DENIED but got %d\n", GetLastError());
173
174 SetLastError(0xdeadbeef);
175 pGetModuleInformation(hpQV, hBad, &info, sizeof(info));
176 ok(GetLastError() == ERROR_INVALID_HANDLE, "expected error=ERROR_INVALID_HANDLE but got %d\n", GetLastError());
177
178 SetLastError(0xdeadbeef);
179 pGetModuleInformation(hpQV, hMod, &info, sizeof(info)-1);
180 ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER, "expected error=ERROR_INSUFFICIENT_BUFFER but got %d\n", GetLastError());
181
182 SetLastError(0xdeadbeef);
183 ret = pGetModuleInformation(hpQV, hMod, &info, sizeof(info));
184 ok(ret == 1, "failed with %d\n", GetLastError());
185 ok(info.lpBaseOfDll == hMod, "lpBaseOfDll=%p hMod=%p\n", info.lpBaseOfDll, hMod);
186 }
187
188 static void test_GetProcessMemoryInfo(void)
189 {
190 PROCESS_MEMORY_COUNTERS pmc;
191 DWORD ret;
192
193 SetLastError(0xdeadbeef);
194 ret = pGetProcessMemoryInfo(NULL, &pmc, sizeof(pmc));
195 ok(!ret, "GetProcessMemoryInfo should fail\n");
196 ok(GetLastError() == ERROR_INVALID_HANDLE, "expected error=ERROR_INVALID_HANDLE but got %d\n", GetLastError());
197
198 SetLastError(0xdeadbeef);
199 ret = pGetProcessMemoryInfo(hpSR, &pmc, sizeof(pmc));
200 todo_wine
201 ok(!ret, "GetProcessMemoryInfo should fail\n");
202 todo_wine
203 ok(GetLastError() == ERROR_ACCESS_DENIED, "expected error=ERROR_ACCESS_DENIED but got %d\n", GetLastError());
204
205 SetLastError(0xdeadbeef);
206 ret = pGetProcessMemoryInfo(hpQI, &pmc, sizeof(pmc)-1);
207 ok(!ret, "GetProcessMemoryInfo should fail\n");
208 ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER, "expected error=ERROR_INSUFFICIENT_BUFFER but got %d\n", GetLastError());
209
210 SetLastError(0xdeadbeef);
211 ret = pGetProcessMemoryInfo(hpQI, &pmc, sizeof(pmc));
212 ok(ret == 1, "failed with %d\n", GetLastError());
213 }
214
215 static BOOL nt_get_mapped_file_name(HANDLE process, LPVOID addr, LPWSTR name, DWORD len)
216 {
217 MEMORY_SECTION_NAME *section_name;
218 WCHAR *buf;
219 SIZE_T buf_len, ret_len;
220 NTSTATUS status;
221
222 if (!pNtQueryVirtualMemory) return FALSE;
223
224 buf_len = len * sizeof(WCHAR) + sizeof(MEMORY_SECTION_NAME);
225 buf = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, buf_len);
226
227 ret_len = 0xdeadbeef;
228 status = pNtQueryVirtualMemory(process, addr, MemorySectionName, buf, buf_len, &ret_len);
229 todo_wine
230 ok(!status, "NtQueryVirtualMemory error %x\n", status);
231 /* FIXME: remove once Wine is fixed */
232 if (status) return FALSE;
233
234 section_name = (MEMORY_SECTION_NAME *)buf;
235 ok(ret_len == section_name->SectionFileName.MaximumLength + sizeof(*section_name), "got %lu, %u\n",
236 ret_len, section_name->SectionFileName.MaximumLength);
237 ok((char *)section_name->SectionFileName.Buffer == (char *)section_name + sizeof(*section_name), "got %p, %p\n",
238 section_name, section_name->SectionFileName.Buffer);
239 ok(section_name->SectionFileName.MaximumLength == section_name->SectionFileName.Length + sizeof(WCHAR), "got %u, %u\n",
240 section_name->SectionFileName.MaximumLength, section_name->SectionFileName.Length);
241 ok(section_name->SectionFileName.Length == lstrlenW(section_name->SectionFileName.Buffer) * sizeof(WCHAR), "got %u, %u\n",
242 section_name->SectionFileName.Length, lstrlenW(section_name->SectionFileName.Buffer));
243
244 memcpy(name, section_name->SectionFileName.Buffer, section_name->SectionFileName.MaximumLength);
245 HeapFree(GetProcessHeap(), 0, buf);
246 return TRUE;
247 }
248
249 static void test_GetMappedFileName(void)
250 {
251 HMODULE hMod = GetModuleHandle(NULL);
252 char szMapPath[MAX_PATH], szModPath[MAX_PATH], *szMapBaseName;
253 DWORD ret;
254 char *base;
255 char temp_path[MAX_PATH], file_name[MAX_PATH], map_name[MAX_PATH], device_name[MAX_PATH], drive[3];
256 WCHAR map_nameW[MAX_PATH], nt_map_name[MAX_PATH];
257 HANDLE hfile, hmap;
258
259 SetLastError(0xdeadbeef);
260 ret = pGetMappedFileNameA(NULL, hMod, szMapPath, sizeof(szMapPath));
261 ok(!ret, "GetMappedFileName should fail\n");
262 todo_wine
263 ok(GetLastError() == ERROR_INVALID_HANDLE, "expected error=ERROR_INVALID_HANDLE but got %d\n", GetLastError());
264
265 SetLastError(0xdeadbeef);
266 ret = pGetMappedFileNameA(hpSR, hMod, szMapPath, sizeof(szMapPath));
267 ok(!ret, "GetMappedFileName should fail\n");
268 todo_wine
269 ok(GetLastError() == ERROR_ACCESS_DENIED, "expected error=ERROR_ACCESS_DENIED but got %d\n", GetLastError());
270
271 SetLastError( 0xdeadbeef );
272 ret = pGetMappedFileNameA(hpQI, hMod, szMapPath, sizeof(szMapPath));
273 todo_wine
274 ok( ret || broken(GetLastError() == ERROR_UNEXP_NET_ERR), /* win2k */
275 "GetMappedFileNameA failed with error %u\n", GetLastError() );
276 if (ret)
277 {
278 ok(ret == strlen(szMapPath), "szMapPath=\"%s\" ret=%d\n", szMapPath, ret);
279 todo_wine
280 ok(szMapPath[0] == '\\', "szMapPath=\"%s\"\n", szMapPath);
281 szMapBaseName = strrchr(szMapPath, '\\'); /* That's close enough for us */
282 todo_wine
283 ok(szMapBaseName && *szMapBaseName, "szMapPath=\"%s\"\n", szMapPath);
284 if (szMapBaseName)
285 {
286 GetModuleFileNameA(NULL, szModPath, sizeof(szModPath));
287 ok(!strcmp(strrchr(szModPath, '\\'), szMapBaseName),
288 "szModPath=\"%s\" szMapBaseName=\"%s\"\n", szModPath, szMapBaseName);
289 }
290 }
291
292 GetTempPath(MAX_PATH, temp_path);
293 GetTempFileName(temp_path, "map", 0, file_name);
294
295 drive[0] = file_name[0];
296 drive[1] = ':';
297 drive[2] = 0;
298 SetLastError(0xdeadbeef);
299 ret = QueryDosDevice(drive, device_name, sizeof(device_name));
300 ok(ret, "QueryDosDevice error %d\n", GetLastError());
301 trace("%s -> %s\n", drive, device_name);
302
303 SetLastError(0xdeadbeef);
304 hfile = CreateFile(file_name, GENERIC_READ | GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, 0);
305 ok(hfile != INVALID_HANDLE_VALUE, "CreateFile(%s) error %d\n", file_name, GetLastError());
306 SetFilePointer(hfile, 0x4000, NULL, FILE_BEGIN);
307 SetEndOfFile(hfile);
308
309 SetLastError(0xdeadbeef);
310 hmap = CreateFileMapping(hfile, NULL, PAGE_READONLY | SEC_COMMIT, 0, 0, NULL);
311 ok(hmap != 0, "CreateFileMapping error %d\n", GetLastError());
312
313 SetLastError(0xdeadbeef);
314 base = MapViewOfFile(hmap, FILE_MAP_READ, 0, 0, 0);
315 ok(base != NULL, "MapViewOfFile error %d\n", GetLastError());
316
317 SetLastError(0xdeadbeef);
318 ret = pGetMappedFileNameA(GetCurrentProcess(), base, map_name, 0);
319 ok(!ret, "GetMappedFileName should fail\n");
320 todo_wine
321 ok(GetLastError() == ERROR_INVALID_PARAMETER || GetLastError() == ERROR_INSUFFICIENT_BUFFER,
322 "wrong error %d\n", GetLastError());
323
324 SetLastError(0xdeadbeef);
325 ret = pGetMappedFileNameA(GetCurrentProcess(), base, 0, sizeof(map_name));
326 ok(!ret, "GetMappedFileName should fail\n");
327 todo_wine
328 ok(GetLastError() == ERROR_INVALID_PARAMETER, "expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
329
330 SetLastError(0xdeadbeef);
331 ret = pGetMappedFileNameA(GetCurrentProcess(), base, map_name, 1);
332 todo_wine
333 ok(ret == 1, "GetMappedFileName error %d\n", GetLastError());
334 ok(!map_name[0] || broken(map_name[0] == device_name[0]) /* before win2k */, "expected 0, got %c\n", map_name[0]);
335
336 SetLastError(0xdeadbeef);
337 ret = pGetMappedFileNameA(GetCurrentProcess(), base, map_name, sizeof(map_name));
338 todo_wine {
339 ok(ret, "GetMappedFileName error %d\n", GetLastError());
340 ok(ret > strlen(device_name), "map_name should be longer than device_name\n");
341 ok(memcmp(map_name, device_name, strlen(device_name)) == 0, "map name does not start with a device name: %s\n", map_name);
342 }
343
344 SetLastError(0xdeadbeef);
345 ret = pGetMappedFileNameW(GetCurrentProcess(), base, map_nameW, sizeof(map_nameW)/sizeof(map_nameW[0]));
346 todo_wine {
347 ok(ret, "GetMappedFileNameW error %d\n", GetLastError());
348 ok(ret > strlen(device_name), "map_name should be longer than device_name\n");
349 }
350 if (nt_get_mapped_file_name(GetCurrentProcess(), base, nt_map_name, sizeof(nt_map_name)/sizeof(nt_map_name[0])))
351 {
352 ok(memcmp(map_nameW, nt_map_name, lstrlenW(map_nameW)) == 0, "map name does not start with a device name: %s\n", map_name);
353 WideCharToMultiByte(CP_ACP, 0, map_nameW, -1, map_name, MAX_PATH, NULL, NULL);
354 ok(memcmp(map_name, device_name, strlen(device_name)) == 0, "map name does not start with a device name: %s\n", map_name);
355 }
356
357 SetLastError(0xdeadbeef);
358 ret = pGetMappedFileNameA(GetCurrentProcess(), base + 0x2000, map_name, sizeof(map_name));
359 todo_wine {
360 ok(ret, "GetMappedFileName error %d\n", GetLastError());
361 ok(ret > strlen(device_name), "map_name should be longer than device_name\n");
362 ok(memcmp(map_name, device_name, strlen(device_name)) == 0, "map name does not start with a device name: %s\n", map_name);
363 }
364
365 SetLastError(0xdeadbeef);
366 ret = pGetMappedFileNameA(GetCurrentProcess(), base + 0x4000, map_name, sizeof(map_name));
367 ok(!ret, "GetMappedFileName should fail\n");
368 todo_wine
369 ok(GetLastError() == ERROR_UNEXP_NET_ERR, "expected ERROR_UNEXP_NET_ERR, got %d\n", GetLastError());
370
371 SetLastError(0xdeadbeef);
372 ret = pGetMappedFileNameA(GetCurrentProcess(), NULL, map_name, sizeof(map_name));
373 ok(!ret, "GetMappedFileName should fail\n");
374 todo_wine
375 ok(GetLastError() == ERROR_UNEXP_NET_ERR, "expected ERROR_UNEXP_NET_ERR, got %d\n", GetLastError());
376
377 SetLastError(0xdeadbeef);
378 ret = pGetMappedFileNameA(0, base, map_name, sizeof(map_name));
379 ok(!ret, "GetMappedFileName should fail\n");
380 todo_wine
381 ok(GetLastError() == ERROR_INVALID_HANDLE, "expected ERROR_INVALID_HANDLE, got %d\n", GetLastError());
382
383 UnmapViewOfFile(base);
384 CloseHandle(hmap);
385 CloseHandle(hfile);
386 DeleteFile(file_name);
387
388 SetLastError(0xdeadbeef);
389 hmap = CreateFileMapping(INVALID_HANDLE_VALUE, NULL, PAGE_READONLY | SEC_COMMIT, 0, 4096, NULL);
390 ok(hmap != 0, "CreateFileMapping error %d\n", GetLastError());
391
392 SetLastError(0xdeadbeef);
393 base = MapViewOfFile(hmap, FILE_MAP_READ, 0, 0, 0);
394 ok(base != NULL, "MapViewOfFile error %d\n", GetLastError());
395
396 SetLastError(0xdeadbeef);
397 ret = pGetMappedFileNameA(GetCurrentProcess(), base, map_name, sizeof(map_name));
398 ok(!ret, "GetMappedFileName should fail\n");
399 todo_wine
400 ok(GetLastError() == ERROR_FILE_INVALID, "expected ERROR_FILE_INVALID, got %d\n", GetLastError());
401
402 UnmapViewOfFile(base);
403 CloseHandle(hmap);
404 }
405
406 static void test_GetProcessImageFileName(void)
407 {
408 HMODULE hMod = GetModuleHandle(NULL);
409 char szImgPath[MAX_PATH], szMapPath[MAX_PATH];
410 WCHAR szImgPathW[MAX_PATH];
411 DWORD ret, ret1;
412
413 if(pGetProcessImageFileNameA == NULL)
414 return;
415
416 /* This function is available on WinXP+ only */
417 SetLastError(0xdeadbeef);
418 if(!pGetProcessImageFileNameA(hpQI, szImgPath, sizeof(szImgPath)))
419 {
420 if(GetLastError() == ERROR_INVALID_FUNCTION) {
421 win_skip("GetProcessImageFileName not implemented\n");
422 return;
423 }
424
425 if(GetLastError() == 0xdeadbeef)
426 todo_wine ok(0, "failed without error code\n");
427 else
428 todo_wine ok(0, "failed with %d\n", GetLastError());
429 }
430
431 SetLastError(0xdeadbeef);
432 pGetProcessImageFileNameA(NULL, szImgPath, sizeof(szImgPath));
433 ok(GetLastError() == ERROR_INVALID_HANDLE, "expected error=ERROR_INVALID_HANDLE but got %d\n", GetLastError());
434
435 SetLastError(0xdeadbeef);
436 pGetProcessImageFileNameA(hpSR, szImgPath, sizeof(szImgPath));
437 ok(GetLastError() == ERROR_ACCESS_DENIED, "expected error=ERROR_ACCESS_DENIED but got %d\n", GetLastError());
438
439 SetLastError(0xdeadbeef);
440 pGetProcessImageFileNameA(hpQI, szImgPath, 0);
441 ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER, "expected error=ERROR_INSUFFICIENT_BUFFER but got %d\n", GetLastError());
442
443 ret = pGetProcessImageFileNameA(hpQI, szImgPath, sizeof(szImgPath));
444 ret1 = pGetMappedFileNameA(hpQV, hMod, szMapPath, sizeof(szMapPath));
445 if(ret && ret1)
446 {
447 /* Windows returns 2*strlen-1 */
448 todo_wine ok(ret >= strlen(szImgPath), "szImgPath=\"%s\" ret=%d\n", szImgPath, ret);
449 todo_wine ok(!strcmp(szImgPath, szMapPath), "szImgPath=\"%s\" szMapPath=\"%s\"\n", szImgPath, szMapPath);
450 }
451
452 SetLastError(0xdeadbeef);
453 pGetProcessImageFileNameW(NULL, szImgPathW, sizeof(szImgPathW));
454 ok(GetLastError() == ERROR_INVALID_HANDLE, "expected error=ERROR_INVALID_HANDLE but got %d\n", GetLastError());
455
456 /* no information about correct buffer size returned: */
457 SetLastError(0xdeadbeef);
458 pGetProcessImageFileNameW(hpQI, szImgPathW, 0);
459 ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER, "expected error=ERROR_INSUFFICIENT_BUFFER but got %d\n", GetLastError());
460
461 SetLastError(0xdeadbeef);
462 pGetProcessImageFileNameW(hpQI, NULL, 0);
463 ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER, "expected error=ERROR_INSUFFICIENT_BUFFER but got %d\n", GetLastError());
464
465 /* correct call */
466 memset(szImgPathW, 0xff, sizeof(szImgPathW));
467 ret = pGetProcessImageFileNameW(hpQI, szImgPathW, sizeof(szImgPathW)/sizeof(WCHAR));
468 ok(ret > 0, "GetProcessImageFileNameW should have succeeded.\n");
469 ok(szImgPathW[0] == '\\', "GetProcessImageFileNameW should have returned an NT path.\n");
470 ok(lstrlenW(szImgPathW) == ret, "Expected length to be %d, got %d\n", ret, lstrlenW(szImgPathW));
471
472 /* boundary values of 'size' */
473 SetLastError(0xdeadbeef);
474 pGetProcessImageFileNameW(hpQI, szImgPathW, ret);
475 ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER, "expected error=ERROR_INSUFFICIENT_BUFFER but got %d\n", GetLastError());
476
477 memset(szImgPathW, 0xff, sizeof(szImgPathW));
478 ret = pGetProcessImageFileNameW(hpQI, szImgPathW, ret + 1);
479 ok(ret > 0, "GetProcessImageFileNameW should have succeeded.\n");
480 ok(szImgPathW[0] == '\\', "GetProcessImageFileNameW should have returned an NT path.\n");
481 ok(lstrlenW(szImgPathW) == ret, "Expected length to be %d, got %d\n", ret, lstrlenW(szImgPathW));
482 }
483
484 static void test_GetModuleFileNameEx(void)
485 {
486 HMODULE hMod = GetModuleHandle(NULL);
487 char szModExPath[MAX_PATH+1], szModPath[MAX_PATH+1];
488 WCHAR buffer[MAX_PATH];
489 DWORD ret;
490
491 SetLastError(0xdeadbeef);
492 ret = pGetModuleFileNameExA(NULL, hMod, szModExPath, sizeof(szModExPath));
493 ok( !ret, "GetModuleFileNameExA succeeded\n" );
494 ok(GetLastError() == ERROR_INVALID_HANDLE, "expected error=ERROR_INVALID_HANDLE but got %d\n", GetLastError());
495
496 SetLastError(0xdeadbeef);
497 ret = pGetModuleFileNameExA(hpQI, hMod, szModExPath, sizeof(szModExPath));
498 ok( !ret, "GetModuleFileNameExA succeeded\n" );
499 ok(GetLastError() == ERROR_ACCESS_DENIED, "expected error=ERROR_ACCESS_DENIED but got %d\n", GetLastError());
500
501 SetLastError(0xdeadbeef);
502 ret = pGetModuleFileNameExA(hpQV, hBad, szModExPath, sizeof(szModExPath));
503 ok( !ret, "GetModuleFileNameExA succeeded\n" );
504 ok(GetLastError() == ERROR_INVALID_HANDLE, "expected error=ERROR_INVALID_HANDLE but got %d\n", GetLastError());
505
506 ret = pGetModuleFileNameExA(hpQV, NULL, szModExPath, sizeof(szModExPath));
507 if(!ret)
508 return;
509 ok(ret == strlen(szModExPath), "szModExPath=\"%s\" ret=%d\n", szModExPath, ret);
510 GetModuleFileNameA(NULL, szModPath, sizeof(szModPath));
511 ok(!strncmp(szModExPath, szModPath, MAX_PATH),
512 "szModExPath=\"%s\" szModPath=\"%s\"\n", szModExPath, szModPath);
513
514 SetLastError(0xdeadbeef);
515 memset( szModExPath, 0xcc, sizeof(szModExPath) );
516 ret = pGetModuleFileNameExA(hpQV, NULL, szModExPath, 4 );
517 ok( ret == 4, "wrong length %u\n", ret );
518 ok( broken(szModExPath[3]) /*w2kpro*/ || strlen(szModExPath) == 3,
519 "szModExPath=\"%s\" ret=%d\n", szModExPath, ret );
520 ok(GetLastError() == 0xdeadbeef, "got error %d\n", GetLastError());
521
522 SetLastError(0xdeadbeef);
523 ret = pGetModuleFileNameExA(hpQV, NULL, szModExPath, 0 );
524 ok( ret == 0, "wrong length %u\n", ret );
525 ok(GetLastError() == ERROR_INVALID_PARAMETER, "got error %d\n", GetLastError());
526
527 SetLastError(0xdeadbeef);
528 memset( buffer, 0xcc, sizeof(buffer) );
529 ret = pGetModuleFileNameExW(hpQV, NULL, buffer, 4 );
530 ok( ret == 4, "wrong length %u\n", ret );
531 ok( broken(buffer[3]) /*w2kpro*/ || lstrlenW(buffer) == 3,
532 "buffer=%s ret=%d\n", wine_dbgstr_w(buffer), ret );
533 ok(GetLastError() == 0xdeadbeef, "got error %d\n", GetLastError());
534
535 SetLastError(0xdeadbeef);
536 buffer[0] = 0xcc;
537 ret = pGetModuleFileNameExW(hpQV, NULL, buffer, 0 );
538 ok( ret == 0, "wrong length %u\n", ret );
539 ok(GetLastError() == 0xdeadbeef, "got error %d\n", GetLastError());
540 ok( buffer[0] == 0xcc, "buffer modified %s\n", wine_dbgstr_w(buffer) );
541 }
542
543 static void test_GetModuleBaseName(void)
544 {
545 HMODULE hMod = GetModuleHandle(NULL);
546 char szModPath[MAX_PATH], szModBaseName[MAX_PATH];
547 DWORD ret;
548
549 SetLastError(0xdeadbeef);
550 pGetModuleBaseNameA(NULL, hMod, szModBaseName, sizeof(szModBaseName));
551 ok(GetLastError() == ERROR_INVALID_HANDLE, "expected error=ERROR_INVALID_HANDLE but got %d\n", GetLastError());
552
553 SetLastError(0xdeadbeef);
554 pGetModuleBaseNameA(hpQI, hMod, szModBaseName, sizeof(szModBaseName));
555 ok(GetLastError() == ERROR_ACCESS_DENIED, "expected error=ERROR_ACCESS_DENIED but got %d\n", GetLastError());
556
557 SetLastError(0xdeadbeef);
558 pGetModuleBaseNameA(hpQV, hBad, szModBaseName, sizeof(szModBaseName));
559 ok(GetLastError() == ERROR_INVALID_HANDLE, "expected error=ERROR_INVALID_HANDLE but got %d\n", GetLastError());
560
561 ret = pGetModuleBaseNameA(hpQV, NULL, szModBaseName, sizeof(szModBaseName));
562 if(!ret)
563 return;
564 ok(ret == strlen(szModBaseName), "szModBaseName=\"%s\" ret=%d\n", szModBaseName, ret);
565 GetModuleFileNameA(NULL, szModPath, sizeof(szModPath));
566 ok(!strcmp(strrchr(szModPath, '\\') + 1, szModBaseName),
567 "szModPath=\"%s\" szModBaseName=\"%s\"\n", szModPath, szModBaseName);
568 }
569
570 static void test_ws_functions(void)
571 {
572 PSAPI_WS_WATCH_INFORMATION wswi[4096];
573 ULONG_PTR pages[4096];
574 char *addr;
575 unsigned int i;
576 BOOL ret;
577
578 SetLastError(0xdeadbeef);
579 pEmptyWorkingSet(NULL);
580 todo_wine ok(GetLastError() == ERROR_INVALID_HANDLE, "expected error=ERROR_INVALID_HANDLE but got %d\n", GetLastError());
581
582 SetLastError(0xdeadbeef);
583 pEmptyWorkingSet(hpSR);
584 todo_wine ok(GetLastError() == ERROR_ACCESS_DENIED, "expected error=ERROR_ACCESS_DENIED but got %d\n", GetLastError());
585
586 SetLastError(0xdeadbeef);
587 ret = pEmptyWorkingSet(hpAA);
588 ok(ret == 1, "failed with %d\n", GetLastError());
589
590 SetLastError( 0xdeadbeef );
591 ret = pInitializeProcessForWsWatch( NULL );
592 todo_wine ok( !ret, "InitializeProcessForWsWatch succeeded\n" );
593 if (!ret)
594 {
595 if (GetLastError() == ERROR_INVALID_FUNCTION) /* not supported on xp in wow64 mode */
596 {
597 trace( "InitializeProcessForWsWatch not supported\n" );
598 return;
599 }
600 ok( GetLastError() == ERROR_INVALID_HANDLE, "wrong error %u\n", GetLastError() );
601 }
602 SetLastError(0xdeadbeef);
603 ret = pInitializeProcessForWsWatch(hpAA);
604 ok(ret == 1, "failed with %d\n", GetLastError());
605
606 addr = VirtualAlloc(NULL, 1, MEM_COMMIT, PAGE_READWRITE);
607 if(!addr)
608 return;
609
610 *addr = 0; /* make sure it's paged in (needed on wow64) */
611 if(!VirtualLock(addr, 1))
612 {
613 trace("locking failed (error=%d) - skipping test\n", GetLastError());
614 goto free_page;
615 }
616
617 SetLastError(0xdeadbeef);
618 ret = pQueryWorkingSet(hpQI, pages, 4096 * sizeof(ULONG_PTR));
619 todo_wine ok(ret == 1, "failed with %d\n", GetLastError());
620 if(ret == 1)
621 {
622 for(i = 0; i < pages[0]; i++)
623 if((pages[i+1] & ~0xfffL) == (ULONG_PTR)addr)
624 {
625 todo_wine ok(ret == 1, "QueryWorkingSet found our page\n");
626 goto test_gwsc;
627 }
628
629 todo_wine ok(0, "QueryWorkingSet didn't find our page\n");
630 }
631
632 test_gwsc:
633 SetLastError(0xdeadbeef);
634 ret = pGetWsChanges(hpQI, wswi, sizeof(wswi));
635 todo_wine ok(ret == 1, "failed with %d\n", GetLastError());
636 if(ret == 1)
637 {
638 for(i = 0; wswi[i].FaultingVa; i++)
639 if(((ULONG_PTR)wswi[i].FaultingVa & ~0xfffL) == (ULONG_PTR)addr)
640 {
641 todo_wine ok(ret == 1, "GetWsChanges found our page\n");
642 goto free_page;
643 }
644
645 todo_wine ok(0, "GetWsChanges didn't find our page\n");
646 }
647
648 free_page:
649 VirtualFree(addr, 0, MEM_RELEASE);
650 }
651
652 START_TEST(psapi_main)
653 {
654 HMODULE hpsapi = LoadLibraryA("psapi.dll");
655
656 if(!hpsapi)
657 {
658 win_skip("Could not load psapi.dll\n");
659 return;
660 }
661
662 if(InitFunctionPtrs(hpsapi))
663 {
664 DWORD pid = GetCurrentProcessId();
665
666 hpSR = OpenProcess(STANDARD_RIGHTS_REQUIRED, FALSE, pid);
667 hpQI = OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, pid);
668 hpVR = OpenProcess(PROCESS_VM_READ, FALSE, pid);
669 hpQV = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, pid);
670 hpAA = OpenProcess(PROCESS_ALL_ACCESS, FALSE, pid);
671
672 if(hpSR && hpQI && hpVR && hpQV && hpAA)
673 {
674 test_EnumProcesses();
675 test_EnumProcessModules();
676 test_GetModuleInformation();
677 test_GetProcessMemoryInfo();
678 test_GetMappedFileName();
679 test_GetProcessImageFileName();
680 test_GetModuleFileNameEx();
681 test_GetModuleBaseName();
682 test_ws_functions();
683 }
684 CloseHandle(hpSR);
685 CloseHandle(hpQI);
686 CloseHandle(hpVR);
687 CloseHandle(hpQV);
688 CloseHandle(hpAA);
689 }
690
691 FreeLibrary(hpsapi);
692 }