strmbase: Move BasePin implementation to strmbase.
[wine] / dlls / psapi / tests / psapi_main.c
1 /*
2  * Unit test suite for PSAPI
3  *
4  * Copyright (C) 2005 Felix Nawothnig
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19  */
20
21 #include <stdarg.h>
22 #include <stdio.h>
23
24 #include "windows.h"
25 #include "wine/test.h"
26 #include "psapi.h"
27
28 #define PSAPI_GET_PROC(func) \
29     p ## func = (void*)GetProcAddress(hpsapi, #func); \
30     if(!p ## func) { \
31         ok(0, "GetProcAddress(%s) failed\n", #func); \
32         FreeLibrary(hpsapi); \
33         return FALSE; \
34     }
35
36 /* All PSAPI functions return non-zero and call SetLastError() 
37  * on failure so we can use some macros for convenience */
38
39 #define w32_suc(x) \
40   (SetLastError(0xdeadbeef), \
41    (x) \
42      ? (ok(1, "succeeded\n"), 1) \
43      : GetLastError() == 0xdeadbeef \
44        ? (ok(0, "failed without error code\n"), 0) \
45        : (ok(0, "failed with %d\n", GetLastError()), 0))
46
47 static BOOL  (WINAPI *pEmptyWorkingSet)(HANDLE);
48 static BOOL  (WINAPI *pEnumProcesses)(DWORD*, DWORD, DWORD*);
49 static BOOL  (WINAPI *pEnumProcessModules)(HANDLE, HMODULE*, DWORD, LPDWORD);
50 static DWORD (WINAPI *pGetModuleBaseNameA)(HANDLE, HMODULE, LPSTR, DWORD);
51 static DWORD (WINAPI *pGetModuleFileNameExA)(HANDLE, HMODULE, LPSTR, DWORD);
52 static BOOL  (WINAPI *pGetModuleInformation)(HANDLE, HMODULE, LPMODULEINFO, DWORD);
53 static DWORD (WINAPI *pGetMappedFileNameA)(HANDLE, LPVOID, LPSTR, DWORD);
54 static DWORD (WINAPI *pGetProcessImageFileNameA)(HANDLE, LPSTR, DWORD);
55 static DWORD (WINAPI *pGetProcessImageFileNameW)(HANDLE, LPWSTR, DWORD);
56 static BOOL  (WINAPI *pGetProcessMemoryInfo)(HANDLE, PPROCESS_MEMORY_COUNTERS, DWORD);
57 static BOOL  (WINAPI *pGetWsChanges)(HANDLE, PPSAPI_WS_WATCH_INFORMATION, DWORD);
58 static BOOL  (WINAPI *pInitializeProcessForWsWatch)(HANDLE);
59 static BOOL  (WINAPI *pQueryWorkingSet)(HANDLE, PVOID, DWORD);
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(GetModuleInformation);
69     PSAPI_GET_PROC(GetMappedFileNameA);
70     PSAPI_GET_PROC(GetProcessMemoryInfo);
71     PSAPI_GET_PROC(GetWsChanges);
72     PSAPI_GET_PROC(InitializeProcessForWsWatch);
73     PSAPI_GET_PROC(QueryWorkingSet);
74     /* GetProcessImageFileName is not exported on NT4 */
75     pGetProcessImageFileNameA =
76       (void *)GetProcAddress(hpsapi, "GetProcessImageFileNameA");
77     pGetProcessImageFileNameW =
78       (void *)GetProcAddress(hpsapi, "GetProcessImageFileNameW");
79     return TRUE;
80 }
81
82 static HANDLE hpSR, hpQI, hpVR, hpQV, hpAA;
83 static const HANDLE hBad = (HANDLE)0xdeadbeef;
84
85 static void test_EnumProcesses(void)
86 {
87     DWORD pid, cbUsed = 0xdeadbeef;
88
89     if(w32_suc(pEnumProcesses(NULL, 0, &cbUsed)))
90         ok(cbUsed == 0, "cbUsed=%d\n", cbUsed);
91     if(w32_suc(pEnumProcesses(&pid, 4, &cbUsed)))
92         ok(cbUsed == 4, "cbUsed=%d\n", cbUsed);
93 }
94
95 static void test_EnumProcessModules(void)
96 {
97     HMODULE hMod = GetModuleHandle(NULL);
98     DWORD cbNeeded = 0xdeadbeef;
99
100     SetLastError(0xdeadbeef);
101     pEnumProcessModules(NULL, NULL, 0, &cbNeeded);
102     ok(GetLastError() == ERROR_INVALID_HANDLE, "expected error=ERROR_INVALID_HANDLE but got %d\n", GetLastError());
103
104     SetLastError(0xdeadbeef);
105     pEnumProcessModules(hpQI, NULL, 0, &cbNeeded);
106     ok(GetLastError() == ERROR_ACCESS_DENIED, "expected error=ERROR_ACCESS_DENIED but got %d\n", GetLastError());
107
108     w32_suc(pEnumProcessModules(hpQV, NULL, 0, &cbNeeded));
109     if(!w32_suc(pEnumProcessModules(hpQV, &hMod, sizeof(HMODULE), &cbNeeded)))
110         return;
111     ok(cbNeeded / sizeof(HMODULE) >= 3 && cbNeeded / sizeof(HMODULE) <= 5 * sizeof(HMODULE),
112        "cbNeeded=%d\n", cbNeeded);
113     ok(hMod == GetModuleHandle(NULL),
114        "hMod=%p GetModuleHandle(NULL)=%p\n", hMod, GetModuleHandle(NULL));
115 }
116
117 static void test_GetModuleInformation(void)
118 {
119     HMODULE hMod = GetModuleHandle(NULL);
120     MODULEINFO info;
121     
122     SetLastError(0xdeadbeef);
123     pGetModuleInformation(NULL, hMod, &info, sizeof(info));
124     ok(GetLastError() == ERROR_INVALID_HANDLE, "expected error=ERROR_INVALID_HANDLE but got %d\n", GetLastError());
125
126     SetLastError(0xdeadbeef);
127     pGetModuleInformation(hpQI, hMod, &info, sizeof(info));
128     ok(GetLastError() == ERROR_ACCESS_DENIED, "expected error=ERROR_ACCESS_DENIED but got %d\n", GetLastError());
129
130     SetLastError(0xdeadbeef);
131     pGetModuleInformation(hpQV, hBad, &info, sizeof(info));
132     ok(GetLastError() == ERROR_INVALID_HANDLE, "expected error=ERROR_INVALID_HANDLE but got %d\n", GetLastError());
133
134     SetLastError(0xdeadbeef);
135     pGetModuleInformation(hpQV, hMod, &info, sizeof(info)-1);
136     ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER, "expected error=ERROR_INSUFFICIENT_BUFFER but got %d\n", GetLastError());
137
138     if(w32_suc(pGetModuleInformation(hpQV, hMod, &info, sizeof(info))))
139         ok(info.lpBaseOfDll == hMod, "lpBaseOfDll=%p hMod=%p\n", info.lpBaseOfDll, hMod);
140 }
141
142 static void test_GetProcessMemoryInfo(void)
143 {
144     PROCESS_MEMORY_COUNTERS pmc;
145
146     SetLastError(0xdeadbeef);
147     pGetProcessMemoryInfo(NULL, &pmc, sizeof(pmc));
148     ok(GetLastError() == ERROR_INVALID_HANDLE, "expected error=ERROR_INVALID_HANDLE but got %d\n", GetLastError());
149
150     SetLastError(0xdeadbeef);
151     pGetProcessMemoryInfo(hpSR, &pmc, sizeof(pmc));
152     todo_wine ok(GetLastError() == ERROR_ACCESS_DENIED, "expected error=ERROR_ACCESS_DENIED but got %d\n", GetLastError());
153
154     SetLastError(0xdeadbeef);
155     pGetProcessMemoryInfo(hpQI, &pmc, sizeof(pmc)-1);
156     ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER, "expected error=ERROR_INSUFFICIENT_BUFFER but got %d\n", GetLastError());
157
158     w32_suc(pGetProcessMemoryInfo(hpQI, &pmc, sizeof(pmc)));
159 }
160
161 static void test_GetMappedFileName(void)
162 {
163     HMODULE hMod = GetModuleHandle(NULL);
164     char szMapPath[MAX_PATH], szModPath[MAX_PATH], *szMapBaseName;
165     DWORD ret;
166     
167     SetLastError(0xdeadbeef);
168     pGetMappedFileNameA(NULL, hMod, szMapPath, sizeof(szMapPath));
169     ok(GetLastError() == ERROR_INVALID_HANDLE, "expected error=ERROR_INVALID_HANDLE but got %d\n", GetLastError());
170
171     SetLastError(0xdeadbeef);
172     pGetMappedFileNameA(hpSR, hMod, szMapPath, sizeof(szMapPath));
173     todo_wine ok(GetLastError() == ERROR_ACCESS_DENIED, "expected error=ERROR_ACCESS_DENIED but got %d\n", GetLastError());
174
175     SetLastError( 0xdeadbeef );
176     ret = pGetMappedFileNameA(hpQI, hMod, szMapPath, sizeof(szMapPath));
177     ok( ret || broken(GetLastError() == ERROR_UNEXP_NET_ERR), /* win2k */
178         "GetMappedFileNameA failed with error %u\n", GetLastError() );
179     if (!ret) return;
180     ok(ret == strlen(szMapPath), "szMapPath=\"%s\" ret=%d\n", szMapPath, ret);
181     ok(szMapPath[0] == '\\', "szMapPath=\"%s\"\n", szMapPath);
182     szMapBaseName = strrchr(szMapPath, '\\'); /* That's close enough for us */
183     if(!szMapBaseName || !*szMapBaseName)
184     {
185         ok(0, "szMapPath=\"%s\"\n", szMapPath);
186         return;
187     }
188     GetModuleFileNameA(NULL, szModPath, sizeof(szModPath));
189     ok(!strcmp(strrchr(szModPath, '\\'), szMapBaseName),
190        "szModPath=\"%s\" szMapBaseName=\"%s\"\n", szModPath, szMapBaseName);
191 }
192
193 static void test_GetProcessImageFileName(void)
194 {
195     HMODULE hMod = GetModuleHandle(NULL);
196     char szImgPath[MAX_PATH], szMapPath[MAX_PATH];
197     WCHAR szImgPathW[MAX_PATH];
198     DWORD ret;
199
200     if(pGetProcessImageFileNameA == NULL)
201         return;
202
203     /* This function is available on WinXP+ only */
204     SetLastError(0xdeadbeef);
205     if(!pGetProcessImageFileNameA(hpQI, szImgPath, sizeof(szImgPath)))
206     {
207         if(GetLastError() == ERROR_INVALID_FUNCTION) {
208             win_skip("GetProcessImageFileName not implemented\n");
209             return;
210         }
211
212         if(GetLastError() == 0xdeadbeef)
213             todo_wine ok(0, "failed without error code\n");
214         else
215             todo_wine ok(0, "failed with %d\n", GetLastError());
216     }
217
218     SetLastError(0xdeadbeef);
219     pGetProcessImageFileNameA(NULL, szImgPath, sizeof(szImgPath));
220     todo_wine ok(GetLastError() == ERROR_INVALID_HANDLE, "expected error=ERROR_INVALID_HANDLE but got %d\n", GetLastError());
221
222     SetLastError(0xdeadbeef);
223     pGetProcessImageFileNameA(hpSR, szImgPath, sizeof(szImgPath));
224     todo_wine ok(GetLastError() == ERROR_ACCESS_DENIED, "expected error=ERROR_ACCESS_DENIED but got %d\n", GetLastError());
225
226     SetLastError(0xdeadbeef);
227     pGetProcessImageFileNameA(hpQI, szImgPath, 0);
228     todo_wine ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER, "expected error=ERROR_INSUFFICIENT_BUFFER but got %d\n", GetLastError());
229
230     todo_wine
231     if(w32_suc(ret = pGetProcessImageFileNameA(hpQI, szImgPath, sizeof(szImgPath))) &&
232        w32_suc(pGetMappedFileNameA(hpQV, hMod, szMapPath, sizeof(szMapPath)))) {
233         /* Windows returns 2*strlen-1 */
234         ok(ret >= strlen(szImgPath), "szImgPath=\"%s\" ret=%d\n", szImgPath, ret);
235         ok(!strcmp(szImgPath, szMapPath),
236            "szImgPath=\"%s\" szMapPath=\"%s\"\n", szImgPath, szMapPath);
237     }
238
239     SetLastError(0xdeadbeef);
240     pGetProcessImageFileNameW(NULL, szImgPathW, sizeof(szImgPathW));
241     ok(GetLastError() == ERROR_INVALID_HANDLE, "expected error=ERROR_INVALID_HANDLE but got %d\n", GetLastError());
242
243     /* no information about correct buffer size returned: */
244     SetLastError(0xdeadbeef);
245     pGetProcessImageFileNameW(hpQI, szImgPathW, 0);
246     ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER, "expected error=ERROR_INSUFFICIENT_BUFFER but got %d\n", GetLastError());
247
248     SetLastError(0xdeadbeef);
249     pGetProcessImageFileNameW(hpQI, NULL, 0);
250     ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER, "expected error=ERROR_INSUFFICIENT_BUFFER but got %d\n", GetLastError());
251
252     /* correct call */
253     memset(szImgPathW, 0xff, sizeof(szImgPathW));
254     ret = pGetProcessImageFileNameW(hpQI, szImgPathW, sizeof(szImgPathW)/sizeof(WCHAR));
255     ok(ret > 0, "GetProcessImageFileNameW should have succeeded.\n");
256     ok(szImgPathW[0] == '\\', "GetProcessImageFileNameW should have returned an NT path.\n");
257     ok(lstrlenW(szImgPathW) == ret, "Expected length to be %d, got %d\n", ret, lstrlenW(szImgPathW));
258
259     /* boundary values of 'size' */
260     SetLastError(0xdeadbeef);
261     pGetProcessImageFileNameW(hpQI, szImgPathW, ret);
262     ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER, "expected error=ERROR_INSUFFICIENT_BUFFER but got %d\n", GetLastError());
263
264     memset(szImgPathW, 0xff, sizeof(szImgPathW));
265     ret = pGetProcessImageFileNameW(hpQI, szImgPathW, ret + 1);
266     ok(ret > 0, "GetProcessImageFileNameW should have succeeded.\n");
267     ok(szImgPathW[0] == '\\', "GetProcessImageFileNameW should have returned an NT path.\n");
268     ok(lstrlenW(szImgPathW) == ret, "Expected length to be %d, got %d\n", ret, lstrlenW(szImgPathW));
269 }
270
271 static void test_GetModuleFileNameEx(void)
272 {
273     HMODULE hMod = GetModuleHandle(NULL);
274     char szModExPath[MAX_PATH+1], szModPath[MAX_PATH+1];
275     DWORD ret;
276     
277     SetLastError(0xdeadbeef);
278     pGetModuleFileNameExA(NULL, hMod, szModExPath, sizeof(szModExPath));
279     ok(GetLastError() == ERROR_INVALID_HANDLE, "expected error=ERROR_INVALID_HANDLE but got %d\n", GetLastError());
280
281     SetLastError(0xdeadbeef);
282     pGetModuleFileNameExA(hpQI, hMod, szModExPath, sizeof(szModExPath));
283     ok(GetLastError() == ERROR_ACCESS_DENIED, "expected error=ERROR_ACCESS_DENIED but got %d\n", GetLastError());
284
285     SetLastError(0xdeadbeef);
286     pGetModuleFileNameExA(hpQV, hBad, szModExPath, sizeof(szModExPath));
287     ok(GetLastError() == ERROR_INVALID_HANDLE, "expected error=ERROR_INVALID_HANDLE but got %d\n", GetLastError());
288
289     if(!w32_suc(ret = pGetModuleFileNameExA(hpQV, NULL, szModExPath, sizeof(szModExPath))))
290         return;
291     ok(ret == strlen(szModExPath), "szModExPath=\"%s\" ret=%d\n", szModExPath, ret);
292     GetModuleFileNameA(NULL, szModPath, sizeof(szModPath));
293     ok(!strncmp(szModExPath, szModPath, MAX_PATH), 
294        "szModExPath=\"%s\" szModPath=\"%s\"\n", szModExPath, szModPath);
295 }
296
297 static void test_GetModuleBaseName(void)
298 {
299     HMODULE hMod = GetModuleHandle(NULL);
300     char szModPath[MAX_PATH], szModBaseName[MAX_PATH];
301     DWORD ret;
302
303     SetLastError(0xdeadbeef);
304     pGetModuleBaseNameA(NULL, hMod, szModBaseName, sizeof(szModBaseName));
305     ok(GetLastError() == ERROR_INVALID_HANDLE, "expected error=ERROR_INVALID_HANDLE but got %d\n", GetLastError());
306
307     SetLastError(0xdeadbeef);
308     pGetModuleBaseNameA(hpQI, hMod, szModBaseName, sizeof(szModBaseName));
309     ok(GetLastError() == ERROR_ACCESS_DENIED, "expected error=ERROR_ACCESS_DENIED but got %d\n", GetLastError());
310
311     SetLastError(0xdeadbeef);
312     pGetModuleBaseNameA(hpQV, hBad, szModBaseName, sizeof(szModBaseName));
313     ok(GetLastError() == ERROR_INVALID_HANDLE, "expected error=ERROR_INVALID_HANDLE but got %d\n", GetLastError());
314
315     if(!w32_suc(ret = pGetModuleBaseNameA(hpQV, NULL, szModBaseName, sizeof(szModBaseName))))
316         return;
317     ok(ret == strlen(szModBaseName), "szModBaseName=\"%s\" ret=%d\n", szModBaseName, ret);
318     GetModuleFileNameA(NULL, szModPath, sizeof(szModPath));
319     ok(!strcmp(strrchr(szModPath, '\\') + 1, szModBaseName),
320        "szModPath=\"%s\" szModBaseName=\"%s\"\n", szModPath, szModBaseName);
321 }
322
323 static void test_ws_functions(void)
324 {
325     PSAPI_WS_WATCH_INFORMATION wswi[4096];
326     ULONG_PTR pages[4096];
327     char *addr;
328     unsigned int i;
329     BOOL ret;
330
331     SetLastError(0xdeadbeef);
332     pEmptyWorkingSet(NULL);
333     todo_wine ok(GetLastError() == ERROR_INVALID_HANDLE, "expected error=ERROR_INVALID_HANDLE but got %d\n", GetLastError());
334
335     SetLastError(0xdeadbeef);
336     pEmptyWorkingSet(hpSR);
337     todo_wine ok(GetLastError() == ERROR_ACCESS_DENIED, "expected error=ERROR_ACCESS_DENIED but got %d\n", GetLastError());
338
339     w32_suc(pEmptyWorkingSet(hpAA));
340
341     SetLastError( 0xdeadbeef );
342     ret = pInitializeProcessForWsWatch( NULL );
343     todo_wine ok( !ret, "InitializeProcessForWsWatch succeeded\n" );
344     if (!ret)
345     {
346         if (GetLastError() == ERROR_INVALID_FUNCTION)  /* not supported on xp in wow64 mode */
347         {
348             trace( "InitializeProcessForWsWatch not supported\n" );
349             return;
350         }
351         ok( GetLastError() == ERROR_INVALID_HANDLE, "wrong error %u\n", GetLastError() );
352     }
353     w32_suc(pInitializeProcessForWsWatch(hpAA));
354     
355     if(!w32_suc(addr = VirtualAlloc(NULL, 1, MEM_COMMIT, PAGE_READWRITE)))
356         return;
357
358     *addr = 0; /* make sure it's paged in (needed on wow64) */
359     if(!VirtualLock(addr, 1))
360     {
361         trace("locking failed (error=%d) - skipping test\n", GetLastError());
362         goto free_page;
363     }
364
365     todo_wine if(w32_suc(pQueryWorkingSet(hpQI, pages, 4096 * sizeof(ULONG_PTR))))
366     {
367        for(i = 0; i < pages[0]; i++)
368            if((pages[i+1] & ~0xfffL) == (ULONG_PTR)addr)
369            {
370                ok(1, "QueryWorkingSet found our page\n");
371                goto test_gwsc;
372            }
373        
374        ok(0, "QueryWorkingSet didn't find our page\n");
375     }
376
377 test_gwsc:
378     todo_wine if(w32_suc(pGetWsChanges(hpQI, wswi, sizeof(wswi))))
379     {
380         for(i = 0; wswi[i].FaultingVa; i++)
381             if(((ULONG_PTR)wswi[i].FaultingVa & ~0xfffL) == (ULONG_PTR)addr)
382             {
383                 ok(1, "GetWsChanges found our page\n");
384                 goto free_page;
385             }
386
387         ok(0, "GetWsChanges didn't find our page\n");
388     }
389     
390 free_page:
391     VirtualFree(addr, 0, MEM_RELEASE);
392 }
393
394 START_TEST(psapi_main)
395 {
396     HMODULE hpsapi = LoadLibraryA("psapi.dll");
397     
398     if(!hpsapi)
399     {
400         trace("Could not load psapi.dll\n");
401         return;
402     }
403
404     if(InitFunctionPtrs(hpsapi))
405     {
406         DWORD pid = GetCurrentProcessId();
407
408         w32_suc(hpSR = OpenProcess(STANDARD_RIGHTS_REQUIRED, FALSE, pid));
409         w32_suc(hpQI = OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, pid));
410         w32_suc(hpVR = OpenProcess(PROCESS_VM_READ, FALSE, pid));
411         w32_suc(hpQV = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, pid));
412         w32_suc(hpAA = OpenProcess(PROCESS_ALL_ACCESS, FALSE, pid));
413         if(hpSR && hpQI && hpVR && hpQV && hpAA)
414         {
415             test_EnumProcesses();
416             test_EnumProcessModules();
417             test_GetModuleInformation();
418             test_GetProcessMemoryInfo();
419             todo_wine test_GetMappedFileName();
420             test_GetProcessImageFileName();
421             test_GetModuleFileNameEx();
422             test_GetModuleBaseName();
423             test_ws_functions();
424         }
425         CloseHandle(hpSR);
426         CloseHandle(hpQI);
427         CloseHandle(hpVR);
428         CloseHandle(hpQV);
429         CloseHandle(hpAA);
430     }
431     
432     FreeLibrary(hpsapi);
433 }