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 *lpdwProcessIDs, DWORD cb, DWORD *lpcbUsed)
80 SYSTEM_PROCESS_INFORMATION *spi;
83 ULONG nAlloc = 0x8000;
88 HeapFree(GetProcessHeap(), 0, pBuf);
92 pBuf = HeapAlloc(GetProcessHeap(), 0, nAlloc);
96 status = NtQuerySystemInformation(SystemProcessInformation, pBuf,
98 } while (status == STATUS_INFO_LENGTH_MISMATCH);
100 if (status != STATUS_SUCCESS)
102 HeapFree(GetProcessHeap(), 0, pBuf);
103 SetLastError(RtlNtStatusToDosError(status));
109 for(*lpcbUsed = 0; cb >= sizeof(DWORD); cb -= sizeof(DWORD))
111 *lpdwProcessIDs++ = spi->dwProcessID;
112 *lpcbUsed += sizeof(DWORD);
114 if(spi->dwOffset == 0)
117 spi = (SYSTEM_PROCESS_INFORMATION *)(((PCHAR)spi) + spi->dwOffset);
120 HeapFree(GetProcessHeap(), 0, pBuf);
124 /***********************************************************************
125 * EnumProcessModules (PSAPI.@)
127 BOOL WINAPI EnumProcessModules(HANDLE hProcess, HMODULE *lphModule,
128 DWORD cb, LPDWORD lpcbNeeded)
137 TRACE("(hProcess=%p, %p, %ld, %p)\n",
138 hProcess, lphModule, cb, lpcbNeeded );
140 if ( lphModule == NULL )
142 if ( lpcbNeeded != NULL )
145 SERVER_START_REQ( get_process_info )
147 req->handle = hProcess;
148 if ( !wine_server_call_err( req ) )
149 pid = (DWORD)reply->pid;
157 FIXME("no pid for hProcess %p\n" ,hProcess);
161 SERVER_START_REQ( create_snapshot )
163 req->flags = SNAP_MODULE;
164 req->inherit = FALSE;
166 wine_server_call_err( req );
167 hSnapshot = reply->handle;
170 if ( hSnapshot == 0 )
172 FIXME("cannot create snapshot\n");
176 countMax = cb / sizeof(HMODULE);
179 SERVER_START_REQ( next_module )
181 req->handle = hSnapshot;
182 req->reset = (count == 0);
183 if ((ret = !wine_server_call_err( req )))
185 hModule = (HMODULE)reply->base;
190 TRACE("module 0x%p\n", hModule);
191 if ( count < countMax )
192 lphModule[count] = hModule;
195 CloseHandle( hSnapshot );
197 if ( lpcbNeeded != NULL )
198 *lpcbNeeded = sizeof(HMODULE) * count;
200 TRACE("return %lu modules\n", count);
205 /***********************************************************************
206 * GetDeviceDriverBaseNameA (PSAPI.@)
208 DWORD WINAPI GetDeviceDriverBaseNameA(LPVOID ImageBase, LPSTR lpBaseName,
211 FIXME("(%p, %s, %ld): stub\n",
212 ImageBase, debugstr_a(lpBaseName), nSize);
214 if (lpBaseName && nSize)
215 lpBaseName[0] = '\0';
220 /***********************************************************************
221 * GetDeviceDriverBaseNameW (PSAPI.@)
223 DWORD WINAPI GetDeviceDriverBaseNameW(LPVOID ImageBase, LPWSTR lpBaseName,
226 FIXME("(%p, %s, %ld): stub\n",
227 ImageBase, debugstr_w(lpBaseName), nSize);
229 if (lpBaseName && nSize)
230 lpBaseName[0] = '\0';
235 /***********************************************************************
236 * GetDeviceDriverFileNameA (PSAPI.@)
238 DWORD WINAPI GetDeviceDriverFileNameA(LPVOID ImageBase, LPSTR lpFilename,
241 FIXME("(%p, %s, %ld): stub\n",
242 ImageBase, debugstr_a(lpFilename), nSize);
244 if (lpFilename && nSize)
245 lpFilename[0] = '\0';
250 /***********************************************************************
251 * GetDeviceDriverFileNameW (PSAPI.@)
253 DWORD WINAPI GetDeviceDriverFileNameW(LPVOID ImageBase, LPWSTR lpFilename,
256 FIXME("(%p, %s, %ld): stub\n",
257 ImageBase, debugstr_w(lpFilename), nSize);
259 if (lpFilename && nSize)
260 lpFilename[0] = '\0';
265 /***********************************************************************
266 * GetMappedFileNameA (PSAPI.@)
268 DWORD WINAPI GetMappedFileNameA(HANDLE hProcess, LPVOID lpv, LPSTR lpFilename,
271 FIXME("(hProcess=%p, %p, %s, %ld): stub\n",
272 hProcess, lpv, debugstr_a(lpFilename), nSize);
274 if (lpFilename && nSize)
275 lpFilename[0] = '\0';
280 /***********************************************************************
281 * GetMappedFileNameW (PSAPI.@)
283 DWORD WINAPI GetMappedFileNameW(HANDLE hProcess, LPVOID lpv, LPWSTR lpFilename,
286 FIXME("(hProcess=%p, %p, %s, %ld): stub\n",
287 hProcess, lpv, debugstr_w(lpFilename), nSize);
289 if (lpFilename && nSize)
290 lpFilename[0] = '\0';
295 /***********************************************************************
296 * GetModuleBaseNameA (PSAPI.@)
298 DWORD WINAPI GetModuleBaseNameA(HANDLE hProcess, HMODULE hModule,
299 LPSTR lpBaseName, DWORD nSize)
302 DWORD buflenW, ret = 0;
304 if(!lpBaseName || !nSize) {
305 SetLastError(ERROR_INVALID_PARAMETER);
308 lpBaseNameW = HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR) * nSize);
309 buflenW = GetModuleBaseNameW(hProcess, hModule, lpBaseNameW, nSize);
310 TRACE("%ld, %s\n", buflenW, debugstr_w(lpBaseNameW));
313 ret = WideCharToMultiByte(CP_ACP, 0, lpBaseNameW, buflenW,
314 lpBaseName, nSize, NULL, NULL);
315 if (ret < nSize) lpBaseName[ret] = 0;
317 HeapFree(GetProcessHeap(), 0, lpBaseNameW);
321 /***********************************************************************
322 * GetModuleBaseNameW (PSAPI.@)
324 DWORD WINAPI GetModuleBaseNameW(HANDLE hProcess, HMODULE hModule,
325 LPWSTR lpBaseName, DWORD nSize)
331 if(!lpBaseName || !nSize) {
332 SetLastError(ERROR_INVALID_PARAMETER);
336 if (!GetModuleFileNameExW(hProcess, hModule, tmp,
337 sizeof(tmp)/sizeof(WCHAR)))
339 TRACE("%s\n", debugstr_w(tmp));
340 if ((ptr = strrchrW(tmp, '\\')) != NULL) ptr++; else ptr = tmp;
341 ptrlen = strlenW(ptr);
342 memcpy(lpBaseName, ptr, min(ptrlen+1,nSize) * sizeof(WCHAR));
343 return min(ptrlen, nSize);
346 /***********************************************************************
347 * GetModuleFileNameExA (PSAPI.@)
349 DWORD WINAPI GetModuleFileNameExA(HANDLE hProcess, HMODULE hModule,
350 LPSTR lpFileName, DWORD nSize)
354 TRACE("(hProcess=%p, hModule=%p, %p, %ld)\n",
355 hProcess, hModule, lpFileName, nSize);
357 if (!lpFileName || !nSize) return 0;
359 if ( hProcess == GetCurrentProcess() )
361 DWORD len = GetModuleFileNameA( hModule, lpFileName, nSize );
362 if (nSize) lpFileName[nSize - 1] = '\0';
366 if (!(ptr = HeapAlloc(GetProcessHeap(), 0, nSize * sizeof(WCHAR)))) return 0;
368 if (!GetModuleFileNameExW(hProcess, hModule, ptr, nSize))
370 lpFileName[0] = '\0';
374 if (!WideCharToMultiByte( CP_ACP, 0, ptr, -1, lpFileName, nSize, NULL, NULL ))
375 lpFileName[nSize - 1] = 0;
378 HeapFree(GetProcessHeap(), 0, ptr);
379 return strlen(lpFileName);
382 /***********************************************************************
383 * GetModuleFileNameExW (PSAPI.@)
385 DWORD WINAPI GetModuleFileNameExW(HANDLE hProcess, HMODULE hModule,
386 LPWSTR lpFileName, DWORD nSize)
390 TRACE("(hProcess=%p, hModule=%p, %p, %ld)\n",
391 hProcess, hModule, lpFileName, nSize);
393 if (!lpFileName || !nSize) return 0;
395 if ( hProcess == GetCurrentProcess() )
397 DWORD len = GetModuleFileNameW( hModule, lpFileName, nSize );
398 if (nSize) lpFileName[nSize - 1] = '\0';
399 TRACE("return (cur) %s (%lu)\n", debugstr_w(lpFileName), len);
405 SERVER_START_REQ( get_dll_info )
407 req->handle = hProcess;
408 req->base_address = hModule;
409 wine_server_set_reply( req, lpFileName, (nSize - 1) * sizeof(WCHAR) );
410 if (!wine_server_call_err( req ))
412 len = wine_server_reply_size(reply) / sizeof(WCHAR);
418 TRACE("return %s (%lu)\n", debugstr_w(lpFileName), len);
423 /***********************************************************************
424 * GetModuleInformation (PSAPI.@)
426 BOOL WINAPI GetModuleInformation(HANDLE hProcess, HMODULE hModule,
427 LPMODULEINFO lpmodinfo, DWORD cb)
431 TRACE("(hProcess=%p, hModule=%p, %p, %ld)\n",
432 hProcess, hModule, lpmodinfo, cb);
434 if (cb < sizeof(MODULEINFO)) return FALSE;
436 SERVER_START_REQ( get_dll_info )
438 req->handle = hProcess;
439 req->base_address = (void*)hModule;
440 if (!wine_server_call_err( req ))
443 lpmodinfo->lpBaseOfDll = (void*)hModule;
444 lpmodinfo->SizeOfImage = reply->size;
445 lpmodinfo->EntryPoint = reply->entry_point;
453 /***********************************************************************
454 * GetPerformanceInfo (PSAPI.@)
456 BOOL WINAPI GetPerformanceInfo( PPERFORMANCE_INFORMATION info, DWORD size )
460 TRACE( "(%p, %ld)\n", info, size );
462 status = NtQueryInformationProcess( GetCurrentProcess(), SystemPerformanceInformation, info, size, NULL );
466 SetLastError( RtlNtStatusToDosError( status ) );
472 /***********************************************************************
473 * GetProcessImageFileNameA (PSAPI.@)
475 DWORD WINAPI GetProcessImageFileNameA( HANDLE process, LPSTR file, DWORD size )
477 FIXME("(%p, %p, %ld) stub\n", process, file, size );
481 /***********************************************************************
482 * GetProcessImageFileNameW (PSAPI.@)
484 DWORD WINAPI GetProcessImageFileNameW( HANDLE process, LPWSTR file, DWORD size )
486 FIXME("(%p, %p, %ld) stub\n", process, file, size );
490 /***********************************************************************
491 * GetProcessMemoryInfo (PSAPI.@)
493 * Retrieve memory usage information for a given process
496 BOOL WINAPI GetProcessMemoryInfo( HANDLE process, PPROCESS_MEMORY_COUNTERS counters, DWORD size )
501 TRACE( "(%p, %p, %ld)\n", process, counters, size );
503 status = NtQueryInformationProcess( process, ProcessVmCounters, &vmc, sizeof(vmc), NULL );
507 SetLastError( RtlNtStatusToDosError( status ) );
511 /* FIXME: check size */
513 counters->cb = sizeof(PROCESS_MEMORY_COUNTERS);
514 counters->PageFaultCount = vmc.PageFaultCount;
515 counters->PeakWorkingSetSize = vmc.PeakWorkingSetSize;
516 counters->WorkingSetSize = vmc.WorkingSetSize;
517 counters->QuotaPeakPagedPoolUsage = vmc.QuotaPeakPagedPoolUsage;
518 counters->QuotaPagedPoolUsage = vmc.QuotaPagedPoolUsage;
519 counters->QuotaPeakNonPagedPoolUsage = vmc.QuotaPeakNonPagedPoolUsage;
520 counters->QuotaNonPagedPoolUsage = vmc.QuotaNonPagedPoolUsage;
521 counters->PagefileUsage = vmc.PagefileUsage;
522 counters->PeakPagefileUsage = vmc.PeakPagefileUsage;
527 /***********************************************************************
528 * GetWsChanges (PSAPI.@)
530 BOOL WINAPI GetWsChanges( HANDLE process, PPSAPI_WS_WATCH_INFORMATION watchinfo, DWORD size )
534 TRACE( "(%p, %p, %ld)\n", process, watchinfo, size );
536 status = NtQueryVirtualMemory( process, NULL, ProcessWorkingSetWatch, watchinfo, size, NULL );
540 SetLastError( RtlNtStatusToDosError( status ) );
546 /***********************************************************************
547 * InitializeProcessForWsWatch (PSAPI.@)
549 BOOL WINAPI InitializeProcessForWsWatch(HANDLE hProcess)
551 FIXME("(hProcess=%p): stub\n", hProcess);
556 /***********************************************************************
557 * QueryWorkingSet (PSAPI.@)
559 BOOL WINAPI QueryWorkingSet( HANDLE process, LPVOID buffer, DWORD size )
563 TRACE( "(%p, %p, %ld)\n", process, buffer, size );
565 status = NtQueryVirtualMemory( process, NULL, MemoryWorkingSetList, buffer, size, NULL );
569 SetLastError( RtlNtStatusToDosError( status ) );
575 /***********************************************************************
576 * QueryWorkingSetEx (PSAPI.@)
578 BOOL WINAPI QueryWorkingSetEx( HANDLE process, LPVOID buffer, DWORD size )
582 TRACE( "(%p, %p, %ld)\n", process, buffer, size );
584 status = NtQueryVirtualMemory( process, NULL, MemoryWorkingSetList, buffer, size, NULL );
588 SetLastError( RtlNtStatusToDosError( status ) );