Added keyboard data format.
[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     int    ptrlen;
342
343     if(!lpBaseName || !nSize) {
344         SetLastError(ERROR_INVALID_PARAMETER);
345         return 0;
346     }
347
348     if (!GetModuleFileNameExW(hProcess, hModule, tmp,
349                               sizeof(tmp)/sizeof(WCHAR)))
350         return 0;
351     TRACE("%s\n", debugstr_w(tmp));
352     if ((ptr = strrchrW(tmp, '\\')) != NULL) ptr++; else ptr = tmp;
353     ptrlen = strlenW(ptr);
354     memcpy(lpBaseName, ptr, min(ptrlen+1,nSize) * sizeof(WCHAR));
355     return min(ptrlen, nSize);
356 }
357
358 /***********************************************************************
359  *           GetModuleFileNameExA (PSAPI.@)
360  */
361 DWORD WINAPI GetModuleFileNameExA(HANDLE hProcess, HMODULE hModule, 
362                                   LPSTR lpFileName, DWORD nSize)
363 {
364     WCHAR *ptr;
365
366     TRACE("(hProcess=%p, hModule=%p, %p, %ld)\n",
367           hProcess, hModule, lpFileName, nSize);
368
369     if (!lpFileName || !nSize) return 0;
370
371     if ( hProcess == GetCurrentProcess() )
372     {
373         DWORD len = GetModuleFileNameA( hModule, lpFileName, nSize );
374         if (nSize) lpFileName[nSize - 1] = '\0';
375         return len;
376     }
377
378     if (!(ptr = HeapAlloc(GetProcessHeap(), 0, nSize * sizeof(WCHAR)))) return 0;
379
380     if (!GetModuleFileNameExW(hProcess, hModule, ptr, nSize))
381     {
382         lpFileName[0] = '\0';
383     }
384     else
385     {
386         if (!WideCharToMultiByte( CP_ACP, 0, ptr, -1, lpFileName, nSize, NULL, NULL ))
387             lpFileName[nSize - 1] = 0;
388     }
389
390     HeapFree(GetProcessHeap(), 0, ptr);
391     return strlen(lpFileName);
392 }
393
394 /***********************************************************************
395  *           GetModuleFileNameExW (PSAPI.@)
396  */
397 DWORD WINAPI GetModuleFileNameExW(HANDLE hProcess, HMODULE hModule, 
398                                   LPWSTR lpFileName, DWORD nSize)
399 {
400     DWORD len = 0;
401
402     TRACE("(hProcess=%p, hModule=%p, %p, %ld)\n",
403           hProcess, hModule, lpFileName, nSize);
404
405     if (!lpFileName || !nSize) return 0;
406
407     if ( hProcess == GetCurrentProcess() )
408     {
409         DWORD len = GetModuleFileNameW( hModule, lpFileName, nSize );
410         if (nSize) lpFileName[nSize - 1] = '\0';
411         TRACE("return (cur) %s (%lu)\n", debugstr_w(lpFileName), len);
412         return len;
413     }
414
415     lpFileName[0] = 0;
416
417     SERVER_START_REQ( get_dll_info )
418     {
419         req->handle       = hProcess;
420         req->base_address = hModule;
421         wine_server_set_reply( req, lpFileName, (nSize - 1) * sizeof(WCHAR) );
422         if (!wine_server_call_err( req ))
423         {
424             len = wine_server_reply_size(reply) / sizeof(WCHAR);
425             lpFileName[len] = 0;
426         }
427     }
428     SERVER_END_REQ;
429
430     TRACE("return %s (%lu)\n", debugstr_w(lpFileName), len);
431
432     return len;
433 }
434
435 /***********************************************************************
436  *           GetModuleInformation (PSAPI.@)
437  */
438 BOOL WINAPI GetModuleInformation(HANDLE hProcess, HMODULE hModule, 
439                                  LPMODULEINFO lpmodinfo, DWORD cb)
440 {
441     BOOL ret = FALSE;
442
443     TRACE("(hProcess=%p, hModule=%p, %p, %ld)\n",
444           hProcess, hModule, lpmodinfo, cb);
445
446     if (cb < sizeof(MODULEINFO)) return FALSE;
447
448     SERVER_START_REQ( get_dll_info )
449     {
450         req->handle       = hProcess;
451         req->base_address = (void*)hModule;
452         if (!wine_server_call_err( req ))
453         {
454             ret = TRUE;
455             lpmodinfo->lpBaseOfDll = (void*)hModule;
456             lpmodinfo->SizeOfImage = reply->size;
457             lpmodinfo->EntryPoint  = reply->entry_point;
458         }
459     }
460     SERVER_END_REQ;
461
462     return TRUE;
463 }
464
465 /***********************************************************************
466  *           GetPerformanceInfo (PSAPI.@)
467  */
468 BOOL WINAPI GetPerformanceInfo( PPERFORMANCE_INFORMATION info, DWORD size )
469 {
470     NTSTATUS status;
471
472     TRACE( "(%p, %ld)\n", info, size );
473
474     status = NtQueryInformationProcess( GetCurrentProcess(), SystemPerformanceInformation, info, size, NULL );
475
476     if (status)
477     {
478         SetLastError( RtlNtStatusToDosError( status ) );
479         return FALSE;
480     }
481     return TRUE;
482 }
483
484 /***********************************************************************
485  *           GetProcessImageFileNameA (PSAPI.@)
486  */
487 DWORD WINAPI GetProcessImageFileNameA( HANDLE process, LPSTR file, DWORD size )
488 {
489     FIXME("(%p, %p, %ld) stub\n", process, file, size );
490     return 0;
491 }
492
493 /***********************************************************************
494  *           GetProcessImageFileNameW (PSAPI.@)
495  */
496 DWORD WINAPI GetProcessImageFileNameW( HANDLE process, LPWSTR file, DWORD size )
497 {
498     FIXME("(%p, %p, %ld) stub\n", process, file, size );
499     return 0;
500 }
501
502 /***********************************************************************
503  *           GetProcessMemoryInfo (PSAPI.@)
504  *
505  * Retrieve memory usage information for a given process
506  *
507  */
508 BOOL WINAPI GetProcessMemoryInfo( HANDLE process, PPROCESS_MEMORY_COUNTERS counters, DWORD size )
509 {
510     NTSTATUS status;
511     VM_COUNTERS vmc;
512
513     TRACE( "(%p, %p, %ld)\n", process, counters, size );
514
515     status = NtQueryInformationProcess( process, ProcessVmCounters, &vmc, sizeof(vmc), NULL );
516
517     if (status)
518     {
519         SetLastError( RtlNtStatusToDosError( status ) );
520         return FALSE;
521     }
522
523     /* FIXME: check size */
524
525     counters->cb = sizeof(PROCESS_MEMORY_COUNTERS);
526     counters->PageFaultCount = vmc.PageFaultCount;
527     counters->PeakWorkingSetSize = vmc.PeakWorkingSetSize;
528     counters->WorkingSetSize = vmc.WorkingSetSize;
529     counters->QuotaPeakPagedPoolUsage = vmc.QuotaPeakPagedPoolUsage;
530     counters->QuotaPagedPoolUsage = vmc.QuotaPagedPoolUsage;
531     counters->QuotaPeakNonPagedPoolUsage = vmc.QuotaPeakNonPagedPoolUsage;
532     counters->QuotaNonPagedPoolUsage = vmc.QuotaNonPagedPoolUsage;
533     counters->PagefileUsage = vmc.PagefileUsage;
534     counters->PeakPagefileUsage = vmc.PeakPagefileUsage;
535
536     return TRUE;
537 }
538
539 /***********************************************************************
540  *           GetWsChanges (PSAPI.@)
541  */
542 BOOL WINAPI GetWsChanges( HANDLE process, PPSAPI_WS_WATCH_INFORMATION watchinfo, DWORD size )
543 {
544     NTSTATUS status;
545
546     TRACE( "(%p, %p, %ld)\n", process, watchinfo, size );
547
548     status = NtQueryVirtualMemory( process, NULL, ProcessWorkingSetWatch, watchinfo, size, NULL );
549
550     if (status)
551     {
552         SetLastError( RtlNtStatusToDosError( status ) );
553         return FALSE;
554     }
555     return TRUE;
556 }
557
558 /***********************************************************************
559  *           InitializeProcessForWsWatch (PSAPI.@)
560  */
561 BOOL WINAPI InitializeProcessForWsWatch(HANDLE hProcess)
562 {
563     FIXME("(hProcess=%p): stub\n", hProcess);
564
565     return TRUE;
566 }
567
568 /***********************************************************************
569  *           QueryWorkingSet (PSAPI.@)
570  */
571 BOOL WINAPI QueryWorkingSet( HANDLE process, LPVOID buffer, DWORD size )
572 {
573     NTSTATUS status;
574
575     TRACE( "(%p, %p, %ld)\n", process, buffer, size );
576
577     status = NtQueryVirtualMemory( process, NULL, MemoryWorkingSetList, buffer, size, NULL );
578
579     if (status)
580     {
581         SetLastError( RtlNtStatusToDosError( status ) );
582         return FALSE;
583     }
584     return TRUE;
585 }
586
587 /***********************************************************************
588  *           QueryWorkingSetEx (PSAPI.@)
589  */
590 BOOL WINAPI QueryWorkingSetEx( HANDLE process, LPVOID buffer, DWORD size )
591 {
592     NTSTATUS status;
593
594     TRACE( "(%p, %p, %ld)\n", process, buffer, size );
595
596     status = NtQueryVirtualMemory( process, NULL, MemoryWorkingSetList, buffer,  size, NULL );
597
598     if (status)
599     {
600         SetLastError( RtlNtStatusToDosError( status ) );
601         return FALSE;
602     }
603     return TRUE;
604 }