4 * Copyright 1998 Patrik Stridvall
5 * Copyright 2003 Eric Pouech
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.
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.
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
27 #include "wine/server.h"
28 #include "wine/unicode.h"
29 #include "wine/debug.h"
34 WINE_DEFAULT_DEBUG_CHANNEL(psapi
);
36 /***********************************************************************
37 * EmptyWorkingSet (PSAPI.@)
39 BOOL WINAPI
EmptyWorkingSet(HANDLE hProcess
)
41 return SetProcessWorkingSetSize(hProcess
, 0xFFFFFFFF, 0xFFFFFFFF);
44 /***********************************************************************
45 * EnumDeviceDrivers (PSAPI.@)
47 BOOL WINAPI
EnumDeviceDrivers(LPVOID
*lpImageBase
, DWORD cb
, LPDWORD lpcbNeeded
)
49 FIXME("(%p, %ld, %p): stub\n", lpImageBase
, cb
, lpcbNeeded
);
57 /***********************************************************************
58 * EnumPageFilesA (PSAPI.@)
60 BOOL WINAPI
EnumPageFilesA( PENUM_PAGE_FILE_CALLBACKA callback
, LPVOID context
)
62 FIXME("(%p, %p) stub\n", callback
, context
);
66 /***********************************************************************
67 * EnumPageFilesW (PSAPI.@)
69 BOOL WINAPI
EnumPageFilesW( PENUM_PAGE_FILE_CALLBACKW callback
, LPVOID context
)
71 FIXME("(%p, %p) stub\n", callback
, context
);
75 /***********************************************************************
76 * EnumProcesses (PSAPI.@)
78 BOOL WINAPI
EnumProcesses(DWORD
*lpidProcess
, DWORD cb
, DWORD
*lpcbNeeded
)
86 TRACE("(%p, %ld, %p)\n", lpidProcess
,cb
, lpcbNeeded
);
88 if ( lpidProcess
== NULL
)
90 if ( lpcbNeeded
!= NULL
)
93 SERVER_START_REQ( create_snapshot
)
95 req
->flags
= SNAP_PROCESS
;
98 wine_server_call_err( req
);
99 hSnapshot
= reply
->handle
;
103 if ( hSnapshot
== 0 )
105 FIXME("cannot create snapshot\n");
109 countMax
= cb
/ sizeof(DWORD
);
112 SERVER_START_REQ( next_process
)
114 req
->handle
= hSnapshot
;
115 req
->reset
= (count
== 0);
116 if ((ret
= !wine_server_call_err( req
)))
121 TRACE("process 0x%08lx\n", pid
);
122 if ( count
< countMax
)
123 lpidProcess
[count
] = pid
;
126 CloseHandle( hSnapshot
);
128 if ( lpcbNeeded
!= NULL
)
129 *lpcbNeeded
= sizeof(DWORD
) * count
;
131 TRACE("return %lu processes\n", count
);
136 /***********************************************************************
137 * EnumProcessModules (PSAPI.@)
139 BOOL WINAPI
EnumProcessModules(HANDLE hProcess
, HMODULE
*lphModule
,
140 DWORD cb
, LPDWORD lpcbNeeded
)
149 TRACE("(hProcess=%p, %p, %ld, %p)\n",
150 hProcess
, lphModule
, cb
, lpcbNeeded
);
152 if ( lphModule
== NULL
)
154 if ( lpcbNeeded
!= NULL
)
157 SERVER_START_REQ( get_process_info
)
159 req
->handle
= hProcess
;
160 if ( !wine_server_call_err( req
) )
161 pid
= (DWORD
)reply
->pid
;
169 FIXME("no pid for hProcess %p\n" ,hProcess
);
173 SERVER_START_REQ( create_snapshot
)
175 req
->flags
= SNAP_MODULE
;
176 req
->inherit
= FALSE
;
178 wine_server_call_err( req
);
179 hSnapshot
= reply
->handle
;
182 if ( hSnapshot
== 0 )
184 FIXME("cannot create snapshot\n");
188 countMax
= cb
/ sizeof(HMODULE
);
191 SERVER_START_REQ( next_module
)
193 req
->handle
= hSnapshot
;
194 req
->reset
= (count
== 0);
195 if ((ret
= !wine_server_call_err( req
)))
197 hModule
= (HMODULE
)reply
->base
;
202 TRACE("module 0x%p\n", hModule
);
203 if ( count
< countMax
)
204 lphModule
[count
] = hModule
;
207 CloseHandle( hSnapshot
);
209 if ( lpcbNeeded
!= NULL
)
210 *lpcbNeeded
= sizeof(HMODULE
) * count
;
212 TRACE("return %lu modules\n", count
);
217 /***********************************************************************
218 * GetDeviceDriverBaseNameA (PSAPI.@)
220 DWORD WINAPI
GetDeviceDriverBaseNameA(LPVOID ImageBase
, LPSTR lpBaseName
,
223 FIXME("(%p, %s, %ld): stub\n",
224 ImageBase
, debugstr_a(lpBaseName
), nSize
);
226 if (lpBaseName
&& nSize
)
227 lpBaseName
[0] = '\0';
232 /***********************************************************************
233 * GetDeviceDriverBaseNameW (PSAPI.@)
235 DWORD WINAPI
GetDeviceDriverBaseNameW(LPVOID ImageBase
, LPWSTR lpBaseName
,
238 FIXME("(%p, %s, %ld): stub\n",
239 ImageBase
, debugstr_w(lpBaseName
), nSize
);
241 if (lpBaseName
&& nSize
)
242 lpBaseName
[0] = '\0';
247 /***********************************************************************
248 * GetDeviceDriverFileNameA (PSAPI.@)
250 DWORD WINAPI
GetDeviceDriverFileNameA(LPVOID ImageBase
, LPSTR lpFilename
,
253 FIXME("(%p, %s, %ld): stub\n",
254 ImageBase
, debugstr_a(lpFilename
), nSize
);
256 if (lpFilename
&& nSize
)
257 lpFilename
[0] = '\0';
262 /***********************************************************************
263 * GetDeviceDriverFileNameW (PSAPI.@)
265 DWORD WINAPI
GetDeviceDriverFileNameW(LPVOID ImageBase
, LPWSTR lpFilename
,
268 FIXME("(%p, %s, %ld): stub\n",
269 ImageBase
, debugstr_w(lpFilename
), nSize
);
271 if (lpFilename
&& nSize
)
272 lpFilename
[0] = '\0';
277 /***********************************************************************
278 * GetMappedFileNameA (PSAPI.@)
280 DWORD WINAPI
GetMappedFileNameA(HANDLE hProcess
, LPVOID lpv
, LPSTR lpFilename
,
283 FIXME("(hProcess=%p, %p, %s, %ld): stub\n",
284 hProcess
, lpv
, debugstr_a(lpFilename
), nSize
);
286 if (lpFilename
&& nSize
)
287 lpFilename
[0] = '\0';
292 /***********************************************************************
293 * GetMappedFileNameW (PSAPI.@)
295 DWORD WINAPI
GetMappedFileNameW(HANDLE hProcess
, LPVOID lpv
, LPWSTR lpFilename
,
298 FIXME("(hProcess=%p, %p, %s, %ld): stub\n",
299 hProcess
, lpv
, debugstr_w(lpFilename
), nSize
);
301 if (lpFilename
&& nSize
)
302 lpFilename
[0] = '\0';
307 /***********************************************************************
308 * GetModuleBaseNameA (PSAPI.@)
310 DWORD WINAPI
GetModuleBaseNameA(HANDLE hProcess
, HMODULE hModule
,
311 LPSTR lpBaseName
, DWORD nSize
)
314 DWORD buflenW
, ret
= 0;
316 if(!lpBaseName
|| !nSize
) {
317 SetLastError(ERROR_INVALID_PARAMETER
);
320 lpBaseNameW
= HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR
) * nSize
);
321 buflenW
= GetModuleBaseNameW(hProcess
, hModule
, lpBaseNameW
, nSize
);
322 TRACE("%ld, %s\n", buflenW
, debugstr_w(lpBaseNameW
));
325 ret
= WideCharToMultiByte(CP_ACP
, 0, lpBaseNameW
, buflenW
,
326 lpBaseName
, nSize
, NULL
, NULL
);
327 if (ret
< nSize
) lpBaseName
[ret
] = 0;
329 HeapFree(GetProcessHeap(), 0, lpBaseNameW
);
333 /***********************************************************************
334 * GetModuleBaseNameW (PSAPI.@)
336 DWORD WINAPI
GetModuleBaseNameW(HANDLE hProcess
, HMODULE hModule
,
337 LPWSTR lpBaseName
, DWORD nSize
)
343 if(!lpBaseName
|| !nSize
) {
344 SetLastError(ERROR_INVALID_PARAMETER
);
348 if (!GetModuleFileNameExW(hProcess
, hModule
, tmp
,
349 sizeof(tmp
)/sizeof(WCHAR
)))
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
);
358 /***********************************************************************
359 * GetModuleFileNameExA (PSAPI.@)
361 DWORD WINAPI
GetModuleFileNameExA(HANDLE hProcess
, HMODULE hModule
,
362 LPSTR lpFileName
, DWORD nSize
)
366 TRACE("(hProcess=%p, hModule=%p, %p, %ld)\n",
367 hProcess
, hModule
, lpFileName
, nSize
);
369 if (!lpFileName
|| !nSize
) return 0;
371 if ( hProcess
== GetCurrentProcess() )
373 DWORD len
= GetModuleFileNameA( hModule
, lpFileName
, nSize
);
374 if (nSize
) lpFileName
[nSize
- 1] = '\0';
378 if (!(ptr
= HeapAlloc(GetProcessHeap(), 0, nSize
* sizeof(WCHAR
)))) return 0;
380 if (!GetModuleFileNameExW(hProcess
, hModule
, ptr
, nSize
))
382 lpFileName
[0] = '\0';
386 if (!WideCharToMultiByte( CP_ACP
, 0, ptr
, -1, lpFileName
, nSize
, NULL
, NULL
))
387 lpFileName
[nSize
- 1] = 0;
390 HeapFree(GetProcessHeap(), 0, ptr
);
391 return strlen(lpFileName
);
394 /***********************************************************************
395 * GetModuleFileNameExW (PSAPI.@)
397 DWORD WINAPI
GetModuleFileNameExW(HANDLE hProcess
, HMODULE hModule
,
398 LPWSTR lpFileName
, DWORD nSize
)
402 TRACE("(hProcess=%p, hModule=%p, %p, %ld)\n",
403 hProcess
, hModule
, lpFileName
, nSize
);
405 if (!lpFileName
|| !nSize
) return 0;
407 if ( hProcess
== GetCurrentProcess() )
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
);
417 SERVER_START_REQ( get_dll_info
)
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
))
424 len
= wine_server_reply_size(reply
) / sizeof(WCHAR
);
430 TRACE("return %s (%lu)\n", debugstr_w(lpFileName
), len
);
435 /***********************************************************************
436 * GetModuleInformation (PSAPI.@)
438 BOOL WINAPI
GetModuleInformation(HANDLE hProcess
, HMODULE hModule
,
439 LPMODULEINFO lpmodinfo
, DWORD cb
)
443 TRACE("(hProcess=%p, hModule=%p, %p, %ld)\n",
444 hProcess
, hModule
, lpmodinfo
, cb
);
446 if (cb
< sizeof(MODULEINFO
)) return FALSE
;
448 SERVER_START_REQ( get_dll_info
)
450 req
->handle
= hProcess
;
451 req
->base_address
= (void*)hModule
;
452 if (!wine_server_call_err( req
))
455 lpmodinfo
->lpBaseOfDll
= (void*)hModule
;
456 lpmodinfo
->SizeOfImage
= reply
->size
;
457 lpmodinfo
->EntryPoint
= reply
->entry_point
;
465 /***********************************************************************
466 * GetPerformanceInfo (PSAPI.@)
468 BOOL WINAPI
GetPerformanceInfo( PPERFORMANCE_INFORMATION info
, DWORD size
)
472 TRACE( "(%p, %ld)\n", info
, size
);
474 status
= NtQueryInformationProcess( GetCurrentProcess(), SystemPerformanceInformation
, info
, size
, NULL
);
478 SetLastError( RtlNtStatusToDosError( status
) );
484 /***********************************************************************
485 * GetProcessImageFileNameA (PSAPI.@)
487 DWORD WINAPI
GetProcessImageFileNameA( HANDLE process
, LPSTR file
, DWORD size
)
489 FIXME("(%p, %p, %ld) stub\n", process
, file
, size
);
493 /***********************************************************************
494 * GetProcessImageFileNameW (PSAPI.@)
496 DWORD WINAPI
GetProcessImageFileNameW( HANDLE process
, LPWSTR file
, DWORD size
)
498 FIXME("(%p, %p, %ld) stub\n", process
, file
, size
);
502 /***********************************************************************
503 * GetProcessMemoryInfo (PSAPI.@)
505 * Retrieve memory usage information for a given process
508 BOOL WINAPI
GetProcessMemoryInfo( HANDLE process
, PPROCESS_MEMORY_COUNTERS counters
, DWORD size
)
513 TRACE( "(%p, %p, %ld)\n", process
, counters
, size
);
515 status
= NtQueryInformationProcess( process
, ProcessVmCounters
, &vmc
, sizeof(vmc
), NULL
);
519 SetLastError( RtlNtStatusToDosError( status
) );
523 /* FIXME: check size */
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
;
539 /***********************************************************************
540 * GetWsChanges (PSAPI.@)
542 BOOL WINAPI
GetWsChanges( HANDLE process
, PPSAPI_WS_WATCH_INFORMATION watchinfo
, DWORD size
)
546 TRACE( "(%p, %p, %ld)\n", process
, watchinfo
, size
);
548 status
= NtQueryVirtualMemory( process
, NULL
, ProcessWorkingSetWatch
, watchinfo
, size
, NULL
);
552 SetLastError( RtlNtStatusToDosError( status
) );
558 /***********************************************************************
559 * InitializeProcessForWsWatch (PSAPI.@)
561 BOOL WINAPI
InitializeProcessForWsWatch(HANDLE hProcess
)
563 FIXME("(hProcess=%p): stub\n", hProcess
);
568 /***********************************************************************
569 * QueryWorkingSet (PSAPI.@)
571 BOOL WINAPI
QueryWorkingSet( HANDLE process
, LPVOID buffer
, DWORD size
)
575 TRACE( "(%p, %p, %ld)\n", process
, buffer
, size
);
577 status
= NtQueryVirtualMemory( process
, NULL
, MemoryWorkingSetList
, buffer
, size
, NULL
);
581 SetLastError( RtlNtStatusToDosError( status
) );
587 /***********************************************************************
588 * QueryWorkingSetEx (PSAPI.@)
590 BOOL WINAPI
QueryWorkingSetEx( HANDLE process
, LPVOID buffer
, DWORD size
)
594 TRACE( "(%p, %p, %ld)\n", process
, buffer
, size
);
596 status
= NtQueryVirtualMemory( process
, NULL
, MemoryWorkingSetList
, buffer
, size
, NULL
);
600 SetLastError( RtlNtStatusToDosError( status
) );