Handle a number as a parameter for custom action 19.
[wine] / dlls / psapi / psapi_main.c
1 /*
2  *      PSAPI library
3  *
4  * Copyright 1998 Patrik Stridvall
5  * Copyright 2003 Eric Pouech
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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
20  */
21
22 #include <stdarg.h>
23
24 #include "windef.h"
25 #include "winbase.h"
26 #include "winerror.h"
27 #include "wine/server.h"
28 #include "wine/unicode.h"
29 #include "wine/debug.h"
30 #include "winnls.h"
31 #include "ntstatus.h"
32 #include "psapi.h"
33
34 WINE_DEFAULT_DEBUG_CHANNEL(psapi);
35
36 /***********************************************************************
37  *           EmptyWorkingSet (PSAPI.@)
38  */
39 BOOL WINAPI EmptyWorkingSet(HANDLE hProcess)
40 {
41     return SetProcessWorkingSetSize(hProcess, 0xFFFFFFFF, 0xFFFFFFFF);
42 }
43
44 /***********************************************************************
45  *           EnumDeviceDrivers (PSAPI.@)
46  */
47 BOOL WINAPI EnumDeviceDrivers(LPVOID *lpImageBase, DWORD cb, LPDWORD lpcbNeeded)
48 {
49     FIXME("(%p, %ld, %p): stub\n", lpImageBase, cb, lpcbNeeded);
50
51     if (lpcbNeeded)
52         *lpcbNeeded = 0;
53
54     return TRUE;
55 }
56
57 /***********************************************************************
58  *           EnumPageFilesA (PSAPI.@)
59  */
60 BOOL WINAPI EnumPageFilesA( PENUM_PAGE_FILE_CALLBACKA callback, LPVOID context )
61 {
62     FIXME("(%p, %p) stub\n", callback, context );
63     return FALSE;
64 }
65
66 /***********************************************************************
67  *           EnumPageFilesW (PSAPI.@)
68  */
69 BOOL WINAPI EnumPageFilesW( PENUM_PAGE_FILE_CALLBACKW callback, LPVOID context )
70 {
71     FIXME("(%p, %p) stub\n", callback, context );
72     return FALSE;
73 }
74
75 /***********************************************************************
76  *           EnumProcesses (PSAPI.@)
77  */
78 BOOL WINAPI EnumProcesses(DWORD *lpidProcess, DWORD cb, DWORD *lpcbNeeded)
79 {
80     HANDLE      hSnapshot;
81     DWORD       count;
82     DWORD       countMax;
83     DWORD       pid;
84     int         ret;
85
86     TRACE("(%p, %ld, %p)\n", lpidProcess,cb, lpcbNeeded);
87
88     if ( lpidProcess == NULL )
89         cb = 0;
90     if ( lpcbNeeded != NULL )
91         *lpcbNeeded = 0;
92
93     SERVER_START_REQ( create_snapshot )
94     {
95         req->flags   = SNAP_PROCESS;
96         req->inherit = FALSE;
97         req->pid     = 0;
98         wine_server_call_err( req );
99         hSnapshot = reply->handle;
100     }
101     SERVER_END_REQ;
102
103     if ( hSnapshot == 0 )
104     {
105         FIXME("cannot create snapshot\n");
106         return FALSE;
107     }
108     count = 0;
109     countMax = cb / sizeof(DWORD);
110     for (;;)
111     {
112         SERVER_START_REQ( next_process )
113         {
114             req->handle = hSnapshot;
115             req->reset = (count == 0);
116             if ((ret = !wine_server_call_err( req )))
117                 pid = reply->pid;
118         }
119         SERVER_END_REQ;
120         if (!ret) break;
121         TRACE("process 0x%08lx\n", pid);
122         if ( count < countMax )
123             lpidProcess[count] = pid;
124         count++;
125     }
126     CloseHandle( hSnapshot );
127
128     if ( lpcbNeeded != NULL )
129         *lpcbNeeded = sizeof(DWORD) * count;
130
131     TRACE("return %lu processes\n", count);
132
133     return TRUE;
134 }
135
136 /***********************************************************************
137  *           EnumProcessModules (PSAPI.@)
138  */
139 BOOL WINAPI EnumProcessModules(HANDLE hProcess, HMODULE *lphModule, 
140                                DWORD cb, LPDWORD lpcbNeeded)
141 {
142     HANDLE      hSnapshot;
143     DWORD       pid;
144     DWORD       count;
145     DWORD       countMax;
146     int         ret;
147     HMODULE     hModule;
148
149     TRACE("(hProcess=%p, %p, %ld, %p)\n",
150           hProcess, lphModule, cb, lpcbNeeded );
151
152     if ( lphModule == NULL )
153         cb = 0;
154     if ( lpcbNeeded != NULL )
155         *lpcbNeeded = 0;
156
157     SERVER_START_REQ( get_process_info )
158     {
159         req->handle = hProcess;
160         if ( !wine_server_call_err( req ) )
161             pid = (DWORD)reply->pid;
162         else
163             pid = 0;
164     }
165     SERVER_END_REQ;
166
167     if ( pid == 0 )
168     {
169         FIXME("no pid for hProcess %p\n" ,hProcess);
170         return FALSE;
171     }
172
173     SERVER_START_REQ( create_snapshot )
174     {
175         req->flags   = SNAP_MODULE;
176         req->inherit = FALSE;
177         req->pid     = pid;
178         wine_server_call_err( req );
179         hSnapshot = reply->handle;
180     }
181     SERVER_END_REQ;
182     if ( hSnapshot == 0 )
183     {
184         FIXME("cannot create snapshot\n");
185         return FALSE;
186     }
187     count = 0;
188     countMax = cb / sizeof(HMODULE);
189     for (;;)
190     {
191         SERVER_START_REQ( next_module )
192         {
193             req->handle = hSnapshot;
194             req->reset = (count == 0);
195             if ((ret = !wine_server_call_err( req )))
196             {
197                 hModule = (HMODULE)reply->base;
198             }
199         }
200         SERVER_END_REQ;
201         if ( !ret ) break;
202         TRACE("module 0x%p\n", hModule);
203         if ( count < countMax )
204             lphModule[count] = hModule;
205         count++;
206     }
207     CloseHandle( hSnapshot );
208
209     if ( lpcbNeeded != NULL )
210         *lpcbNeeded = sizeof(HMODULE) * count;
211
212     TRACE("return %lu modules\n", count);
213
214     return TRUE;
215 }
216
217 /***********************************************************************
218  *          GetDeviceDriverBaseNameA (PSAPI.@)
219  */
220 DWORD WINAPI GetDeviceDriverBaseNameA(LPVOID ImageBase, LPSTR lpBaseName, 
221                                       DWORD nSize)
222 {
223     FIXME("(%p, %s, %ld): stub\n",
224           ImageBase, debugstr_a(lpBaseName), nSize);
225
226     if (lpBaseName && nSize)
227         lpBaseName[0] = '\0';
228
229     return 0;
230 }
231
232 /***********************************************************************
233  *           GetDeviceDriverBaseNameW (PSAPI.@)
234  */
235 DWORD WINAPI GetDeviceDriverBaseNameW(LPVOID ImageBase, LPWSTR lpBaseName, 
236                                       DWORD nSize)
237 {
238     FIXME("(%p, %s, %ld): stub\n",
239           ImageBase, debugstr_w(lpBaseName), nSize);
240
241     if (lpBaseName && nSize)
242         lpBaseName[0] = '\0';
243
244     return 0;
245 }
246
247 /***********************************************************************
248  *           GetDeviceDriverFileNameA (PSAPI.@)
249  */
250 DWORD WINAPI GetDeviceDriverFileNameA(LPVOID ImageBase, LPSTR lpFilename, 
251                                       DWORD nSize)
252 {
253     FIXME("(%p, %s, %ld): stub\n",
254           ImageBase, debugstr_a(lpFilename), nSize);
255
256     if (lpFilename && nSize)
257         lpFilename[0] = '\0';
258
259     return 0;
260 }
261
262 /***********************************************************************
263  *           GetDeviceDriverFileNameW (PSAPI.@)
264  */
265 DWORD WINAPI GetDeviceDriverFileNameW(LPVOID ImageBase, LPWSTR lpFilename, 
266                                       DWORD nSize)
267 {
268     FIXME("(%p, %s, %ld): stub\n",
269           ImageBase, debugstr_w(lpFilename), nSize);
270
271     if (lpFilename && nSize)
272         lpFilename[0] = '\0';
273
274     return 0;
275 }
276
277 /***********************************************************************
278  *           GetMappedFileNameA (PSAPI.@)
279  */
280 DWORD WINAPI GetMappedFileNameA(HANDLE hProcess, LPVOID lpv, LPSTR lpFilename, 
281                                 DWORD nSize)
282 {
283     FIXME("(hProcess=%p, %p, %s, %ld): stub\n",
284           hProcess, lpv, debugstr_a(lpFilename), nSize);
285
286     if (lpFilename && nSize)
287         lpFilename[0] = '\0';
288
289     return 0;
290 }
291
292 /***********************************************************************
293  *           GetMappedFileNameW (PSAPI.@)
294  */
295 DWORD WINAPI GetMappedFileNameW(HANDLE hProcess, LPVOID lpv, LPWSTR lpFilename, 
296                                 DWORD nSize)
297 {
298     FIXME("(hProcess=%p, %p, %s, %ld): stub\n",
299           hProcess, lpv, debugstr_w(lpFilename), nSize);
300
301     if (lpFilename && nSize)
302         lpFilename[0] = '\0';
303
304     return 0;
305 }
306
307 /***********************************************************************
308  *           GetModuleBaseNameA (PSAPI.@)
309  */
310 DWORD WINAPI GetModuleBaseNameA(HANDLE hProcess, HMODULE hModule, 
311                                 LPSTR lpBaseName, DWORD nSize)
312 {
313     WCHAR *lpBaseNameW;
314     DWORD buflenW, ret = 0;
315
316     if(!lpBaseName || !nSize) {
317         SetLastError(ERROR_INVALID_PARAMETER);
318         return 0;
319     }
320     lpBaseNameW = HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR) * nSize);
321     buflenW = GetModuleBaseNameW(hProcess, hModule, lpBaseNameW, nSize);
322     TRACE("%ld, %s\n", buflenW, debugstr_w(lpBaseNameW));
323     if (buflenW)
324     {
325         ret = WideCharToMultiByte(CP_ACP, 0, lpBaseNameW, buflenW,
326                                   lpBaseName, nSize, NULL, NULL);
327         if (ret < nSize) lpBaseName[ret] = 0;
328     }
329     HeapFree(GetProcessHeap(), 0, lpBaseNameW);
330     return ret;
331 }
332
333 /***********************************************************************
334  *           GetModuleBaseNameW (PSAPI.@)
335  */
336 DWORD WINAPI GetModuleBaseNameW(HANDLE hProcess, HMODULE hModule, 
337                                 LPWSTR lpBaseName, DWORD nSize)
338 {
339     WCHAR  tmp[MAX_PATH];
340     WCHAR* ptr;
341
342     if(!lpBaseName || !nSize) {
343         SetLastError(ERROR_INVALID_PARAMETER);
344         return 0;
345     }
346
347     if (!GetModuleFileNameExW(hProcess, hModule, tmp,
348                               sizeof(tmp)/sizeof(WCHAR)))
349         return 0;
350     TRACE("%s\n", debugstr_w(tmp));
351     if ((ptr = strrchrW(tmp, '\\')) != NULL) ptr++; else ptr = tmp;
352     strncpyW(lpBaseName, ptr, nSize);
353     return min(strlenW(ptr), nSize);
354 }
355
356 /***********************************************************************
357  *           GetModuleFileNameExA (PSAPI.@)
358  */
359 DWORD WINAPI GetModuleFileNameExA(HANDLE hProcess, HMODULE hModule, 
360                                   LPSTR lpFileName, DWORD nSize)
361 {
362     WCHAR *ptr;
363
364     TRACE("(hProcess=%p, hModule=%p, %p, %ld)\n",
365           hProcess, hModule, lpFileName, nSize);
366
367     if (!lpFileName || !nSize) return 0;
368
369     if ( hProcess == GetCurrentProcess() )
370     {
371         DWORD len = GetModuleFileNameA( hModule, lpFileName, nSize );
372         if (nSize) lpFileName[nSize - 1] = '\0';
373         return len;
374     }
375
376     if (!(ptr = HeapAlloc(GetProcessHeap(), 0, nSize * sizeof(WCHAR)))) return 0;
377
378     if (!GetModuleFileNameExW(hProcess, hModule, ptr, nSize))
379     {
380         lpFileName[0] = '\0';
381     }
382     else
383     {
384         if (!WideCharToMultiByte( CP_ACP, 0, ptr, -1, lpFileName, nSize, NULL, NULL ))
385             lpFileName[nSize - 1] = 0;
386     }
387
388     HeapFree(GetProcessHeap(), 0, ptr);
389     return strlen(lpFileName);
390 }
391
392 /***********************************************************************
393  *           GetModuleFileNameExW (PSAPI.@)
394  */
395 DWORD WINAPI GetModuleFileNameExW(HANDLE hProcess, HMODULE hModule, 
396                                   LPWSTR lpFileName, DWORD nSize)
397 {
398     DWORD len = 0;
399
400     TRACE("(hProcess=%p, hModule=%p, %p, %ld)\n",
401           hProcess, hModule, lpFileName, nSize);
402
403     if (!lpFileName || !nSize) return 0;
404
405     if ( hProcess == GetCurrentProcess() )
406     {
407         DWORD len = GetModuleFileNameW( hModule, lpFileName, nSize );
408         if (nSize) lpFileName[nSize - 1] = '\0';
409         TRACE("return (cur) %s (%lu)\n", debugstr_w(lpFileName), len);
410         return len;
411     }
412
413     lpFileName[0] = 0;
414
415     SERVER_START_REQ( get_dll_info )
416     {
417         req->handle       = hProcess;
418         req->base_address = hModule;
419         wine_server_set_reply( req, lpFileName, (nSize - 1) * sizeof(WCHAR) );
420         if (!wine_server_call_err( req ))
421         {
422             len = wine_server_reply_size(reply) / sizeof(WCHAR);
423             lpFileName[len] = 0;
424         }
425     }
426     SERVER_END_REQ;
427
428     TRACE("return %s (%lu)\n", debugstr_w(lpFileName), len);
429
430     return len;
431 }
432
433 /***********************************************************************
434  *           GetModuleInformation (PSAPI.@)
435  */
436 BOOL WINAPI GetModuleInformation(HANDLE hProcess, HMODULE hModule, 
437                                  LPMODULEINFO lpmodinfo, DWORD cb)
438 {
439     BOOL ret = FALSE;
440
441     TRACE("(hProcess=%p, hModule=%p, %p, %ld)\n",
442           hProcess, hModule, lpmodinfo, cb);
443
444     if (cb < sizeof(MODULEINFO)) return FALSE;
445
446     SERVER_START_REQ( get_dll_info )
447     {
448         req->handle       = hProcess;
449         req->base_address = (void*)hModule;
450         if (!wine_server_call_err( req ))
451         {
452             ret = TRUE;
453             lpmodinfo->lpBaseOfDll = (void*)hModule;
454             lpmodinfo->SizeOfImage = reply->size;
455             lpmodinfo->EntryPoint  = reply->entry_point;
456         }
457     }
458     SERVER_END_REQ;
459
460     return TRUE;
461 }
462
463 /***********************************************************************
464  *           GetPerformanceInfo (PSAPI.@)
465  */
466 BOOL WINAPI GetPerformanceInfo( PPERFORMANCE_INFORMATION info, DWORD size )
467 {
468     NTSTATUS status;
469
470     TRACE( "(%p, %ld)\n", info, size );
471
472     status = NtQueryInformationProcess( GetCurrentProcess(), SystemPerformanceInformation, info, size, NULL );
473
474     if (status)
475     {
476         SetLastError( RtlNtStatusToDosError( status ) );
477         return FALSE;
478     }
479     return TRUE;
480 }
481
482 /***********************************************************************
483  *           GetProcessImageFileNameA (PSAPI.@)
484  */
485 DWORD WINAPI GetProcessImageFileNameA( HANDLE process, LPSTR file, DWORD size )
486 {
487     FIXME("(%p, %p, %ld) stub\n", process, file, size );
488     return 0;
489 }
490
491 /***********************************************************************
492  *           GetProcessImageFileNameW (PSAPI.@)
493  */
494 DWORD WINAPI GetProcessImageFileNameW( HANDLE process, LPWSTR file, DWORD size )
495 {
496     FIXME("(%p, %p, %ld) stub\n", process, file, size );
497     return 0;
498 }
499
500 /***********************************************************************
501  *           GetProcessMemoryInfo (PSAPI.@)
502  *
503  * Retrieve memory usage information for a given process
504  *
505  */
506 BOOL WINAPI GetProcessMemoryInfo( HANDLE process, PPROCESS_MEMORY_COUNTERS counters, DWORD size )
507 {
508     NTSTATUS status;
509     VM_COUNTERS vmc;
510
511     TRACE( "(%p, %p, %ld)\n", process, counters, size );
512
513     status = NtQueryInformationProcess( process, ProcessVmCounters, &vmc, sizeof(vmc), NULL );
514
515     if (status)
516     {
517         SetLastError( RtlNtStatusToDosError( status ) );
518         return FALSE;
519     }
520
521     /* FIXME: check size */
522
523     counters->cb = sizeof(PROCESS_MEMORY_COUNTERS);
524     counters->PageFaultCount = vmc.PageFaultCount;
525     counters->PeakWorkingSetSize = vmc.PeakWorkingSetSize;
526     counters->WorkingSetSize = vmc.WorkingSetSize;
527     counters->QuotaPeakPagedPoolUsage = vmc.QuotaPeakPagedPoolUsage;
528     counters->QuotaPagedPoolUsage = vmc.QuotaPagedPoolUsage;
529     counters->QuotaPeakNonPagedPoolUsage = vmc.QuotaPeakNonPagedPoolUsage;
530     counters->QuotaNonPagedPoolUsage = vmc.QuotaNonPagedPoolUsage;
531     counters->PagefileUsage = vmc.PagefileUsage;
532     counters->PeakPagefileUsage = vmc.PeakPagefileUsage;
533
534     return TRUE;
535 }
536
537 /***********************************************************************
538  *           GetWsChanges (PSAPI.@)
539  */
540 BOOL WINAPI GetWsChanges( HANDLE process, PPSAPI_WS_WATCH_INFORMATION watchinfo, DWORD size )
541 {
542     NTSTATUS status;
543
544     TRACE( "(%p, %p, %ld)\n", process, watchinfo, size );
545
546     status = NtQueryVirtualMemory( process, NULL, ProcessWorkingSetWatch, watchinfo, size, NULL );
547
548     if (status)
549     {
550         SetLastError( RtlNtStatusToDosError( status ) );
551         return FALSE;
552     }
553     return TRUE;
554 }
555
556 /***********************************************************************
557  *           InitializeProcessForWsWatch (PSAPI.@)
558  */
559 BOOL WINAPI InitializeProcessForWsWatch(HANDLE hProcess)
560 {
561     FIXME("(hProcess=%p): stub\n", hProcess);
562
563     return TRUE;
564 }
565
566 /***********************************************************************
567  *           QueryWorkingSet (PSAPI.@)
568  */
569 BOOL WINAPI QueryWorkingSet( HANDLE process, LPVOID buffer, DWORD size )
570 {
571     NTSTATUS status;
572
573     TRACE( "(%p, %p, %ld)\n", process, buffer, size );
574
575     status = NtQueryVirtualMemory( process, NULL, MemoryWorkingSetList, buffer, size, NULL );
576
577     if (status)
578     {
579         SetLastError( RtlNtStatusToDosError( status ) );
580         return FALSE;
581     }
582     return TRUE;
583 }
584
585 /***********************************************************************
586  *           QueryWorkingSetEx (PSAPI.@)
587  */
588 BOOL WINAPI QueryWorkingSetEx( HANDLE process, LPVOID buffer, DWORD size )
589 {
590     NTSTATUS status;
591
592     TRACE( "(%p, %p, %ld)\n", process, buffer, size );
593
594     status = NtQueryVirtualMemory( process, NULL, MemoryWorkingSetList, buffer,  size, NULL );
595
596     if (status)
597     {
598         SetLastError( RtlNtStatusToDosError( status ) );
599         return FALSE;
600     }
601     return TRUE;
602 }