kernel32: Moved GetProcessMemoryInfo implementation to kernel32.
[wine.git] / dlls / psapi / psapi_main.c
blob0b8e5b065b63e7fcee1f438a42f867db824b6d5d
1 /*
2 * PSAPI library
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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
22 #include <stdarg.h>
24 #include "ntstatus.h"
25 #define WIN32_NO_STATUS
26 #include "windef.h"
27 #include "winbase.h"
28 #include "winerror.h"
29 #include "wine/unicode.h"
30 #include "wine/debug.h"
31 #include "winnls.h"
32 #include "winternl.h"
33 #include "psapi.h"
35 WINE_DEFAULT_DEBUG_CHANNEL(psapi);
37 typedef struct
39 HANDLE hProcess;
40 PLIST_ENTRY pHead, pCurrent;
41 LDR_MODULE LdrModule;
42 } MODULE_ITERATOR;
44 /***********************************************************************
45 * PSAPI_ModuleIteratorInit [internal]
47 * Prepares to iterate through the loaded modules of the given process.
49 * RETURNS
50 * Success: TRUE
51 * Failure: FALSE
53 static BOOL PSAPI_ModuleIteratorInit(MODULE_ITERATOR *iter, HANDLE hProcess)
55 PROCESS_BASIC_INFORMATION pbi;
56 PPEB_LDR_DATA pLdrData;
57 NTSTATUS status;
59 /* Get address of PEB */
60 status = NtQueryInformationProcess(hProcess, ProcessBasicInformation,
61 &pbi, sizeof(pbi), NULL);
62 if (status != STATUS_SUCCESS)
64 SetLastError(RtlNtStatusToDosError(status));
65 return FALSE;
68 /* Read address of LdrData from PEB */
69 if (!ReadProcessMemory(hProcess, &pbi.PebBaseAddress->LdrData,
70 &pLdrData, sizeof(pLdrData), NULL))
71 return FALSE;
73 /* Read address of first module from LdrData */
74 if (!ReadProcessMemory(hProcess,
75 &pLdrData->InLoadOrderModuleList.Flink,
76 &iter->pCurrent, sizeof(iter->pCurrent), NULL))
77 return FALSE;
79 iter->pHead = &pLdrData->InLoadOrderModuleList;
80 iter->hProcess = hProcess;
82 return TRUE;
85 /***********************************************************************
86 * PSAPI_ModuleIteratorNext [internal]
88 * Iterates to the next module.
90 * RETURNS
91 * 1 : Success
92 * 0 : No more modules
93 * -1 : Failure
95 * NOTES
96 * Every function which uses this routine suffers from a race condition
97 * when a module is unloaded during the enumeration which can cause the
98 * function to fail. As there is no way to lock the loader of another
99 * process we can't avoid that.
101 static INT PSAPI_ModuleIteratorNext(MODULE_ITERATOR *iter)
103 if (iter->pCurrent == iter->pHead)
104 return 0;
106 if (!ReadProcessMemory(iter->hProcess, CONTAINING_RECORD(iter->pCurrent,
107 LDR_MODULE, InLoadOrderModuleList),
108 &iter->LdrModule, sizeof(iter->LdrModule), NULL))
109 return -1;
110 else
111 iter->pCurrent = iter->LdrModule.InLoadOrderModuleList.Flink;
113 return 1;
116 /***********************************************************************
117 * PSAPI_GetLdrModule [internal]
119 * Reads the LDR_MODULE structure of the given module.
121 * RETURNS
122 * Success: TRUE
123 * Failure: FALSE
126 static BOOL PSAPI_GetLdrModule(HANDLE hProcess, HMODULE hModule,
127 LDR_MODULE *pLdrModule)
129 MODULE_ITERATOR iter;
130 INT ret;
132 if (!PSAPI_ModuleIteratorInit(&iter, hProcess))
133 return FALSE;
135 while ((ret = PSAPI_ModuleIteratorNext(&iter)) > 0)
136 /* When hModule is NULL we return the process image - which will be
137 * the first module since our iterator uses InLoadOrderModuleList */
138 if (!hModule || hModule == iter.LdrModule.BaseAddress)
140 *pLdrModule = iter.LdrModule;
141 return TRUE;
144 if (ret == 0)
145 SetLastError(ERROR_INVALID_HANDLE);
147 return FALSE;
150 /***********************************************************************
151 * EnumDeviceDrivers (PSAPI.@)
153 BOOL WINAPI EnumDeviceDrivers(LPVOID *lpImageBase, DWORD cb, LPDWORD lpcbNeeded)
155 FIXME("(%p, %d, %p): stub\n", lpImageBase, cb, lpcbNeeded);
157 if (lpcbNeeded)
158 *lpcbNeeded = 0;
160 return TRUE;
163 /***********************************************************************
164 * EnumPageFilesA (PSAPI.@)
166 BOOL WINAPI EnumPageFilesA( PENUM_PAGE_FILE_CALLBACKA callback, LPVOID context )
168 FIXME("(%p, %p) stub\n", callback, context );
169 return FALSE;
172 /***********************************************************************
173 * EnumPageFilesW (PSAPI.@)
175 BOOL WINAPI EnumPageFilesW( PENUM_PAGE_FILE_CALLBACKW callback, LPVOID context )
177 FIXME("(%p, %p) stub\n", callback, context );
178 return FALSE;
181 /***********************************************************************
182 * GetDeviceDriverBaseNameA (PSAPI.@)
184 DWORD WINAPI GetDeviceDriverBaseNameA(LPVOID ImageBase, LPSTR lpBaseName,
185 DWORD nSize)
187 FIXME("(%p, %p, %d): stub\n", ImageBase, lpBaseName, nSize);
189 if (lpBaseName && nSize)
190 lpBaseName[0] = '\0';
192 return 0;
195 /***********************************************************************
196 * GetDeviceDriverBaseNameW (PSAPI.@)
198 DWORD WINAPI GetDeviceDriverBaseNameW(LPVOID ImageBase, LPWSTR lpBaseName,
199 DWORD nSize)
201 FIXME("(%p, %p, %d): stub\n", ImageBase, lpBaseName, nSize);
203 if (lpBaseName && nSize)
204 lpBaseName[0] = '\0';
206 return 0;
209 /***********************************************************************
210 * GetDeviceDriverFileNameA (PSAPI.@)
212 DWORD WINAPI GetDeviceDriverFileNameA(LPVOID ImageBase, LPSTR lpFilename,
213 DWORD nSize)
215 FIXME("(%p, %p, %d): stub\n", ImageBase, lpFilename, nSize);
217 if (lpFilename && nSize)
218 lpFilename[0] = '\0';
220 return 0;
223 /***********************************************************************
224 * GetDeviceDriverFileNameW (PSAPI.@)
226 DWORD WINAPI GetDeviceDriverFileNameW(LPVOID ImageBase, LPWSTR lpFilename,
227 DWORD nSize)
229 FIXME("(%p, %p, %d): stub\n", ImageBase, lpFilename, nSize);
231 if (lpFilename && nSize)
232 lpFilename[0] = '\0';
234 return 0;
237 /***********************************************************************
238 * GetMappedFileNameA (PSAPI.@)
240 DWORD WINAPI GetMappedFileNameA(HANDLE hProcess, LPVOID lpv, LPSTR lpFilename,
241 DWORD nSize)
243 FIXME("(%p, %p, %p, %d): stub\n", hProcess, lpv, lpFilename, nSize);
245 if (lpFilename && nSize)
246 lpFilename[0] = '\0';
248 return 0;
251 /***********************************************************************
252 * GetMappedFileNameW (PSAPI.@)
254 DWORD WINAPI GetMappedFileNameW(HANDLE hProcess, LPVOID lpv, LPWSTR lpFilename,
255 DWORD nSize)
257 FIXME("(%p, %p, %p, %d): stub\n", hProcess, lpv, lpFilename, nSize);
259 if (lpFilename && nSize)
260 lpFilename[0] = '\0';
262 return 0;
265 /***********************************************************************
266 * GetModuleBaseNameA (PSAPI.@)
268 DWORD WINAPI GetModuleBaseNameA(HANDLE hProcess, HMODULE hModule,
269 LPSTR lpBaseName, DWORD nSize)
271 WCHAR *lpBaseNameW;
272 DWORD buflenW, ret = 0;
274 if(!lpBaseName || !nSize) {
275 SetLastError(ERROR_INVALID_PARAMETER);
276 return 0;
278 lpBaseNameW = HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR) * nSize);
279 buflenW = GetModuleBaseNameW(hProcess, hModule, lpBaseNameW, nSize);
280 TRACE("%d, %s\n", buflenW, debugstr_w(lpBaseNameW));
281 if (buflenW)
283 ret = WideCharToMultiByte(CP_ACP, 0, lpBaseNameW, buflenW,
284 lpBaseName, nSize, NULL, NULL);
285 if (ret < nSize) lpBaseName[ret] = 0;
287 HeapFree(GetProcessHeap(), 0, lpBaseNameW);
288 return ret;
291 /***********************************************************************
292 * GetModuleBaseNameW (PSAPI.@)
294 DWORD WINAPI GetModuleBaseNameW(HANDLE hProcess, HMODULE hModule,
295 LPWSTR lpBaseName, DWORD nSize)
297 LDR_MODULE LdrModule;
299 if (!PSAPI_GetLdrModule(hProcess, hModule, &LdrModule))
300 return 0;
302 nSize = min(LdrModule.BaseDllName.Length / sizeof(WCHAR), nSize);
303 if (!ReadProcessMemory(hProcess, LdrModule.BaseDllName.Buffer,
304 lpBaseName, nSize * sizeof(WCHAR), NULL))
305 return 0;
307 lpBaseName[nSize] = 0;
308 return nSize;
311 /***********************************************************************
312 * GetModuleFileNameExA (PSAPI.@)
314 DWORD WINAPI GetModuleFileNameExA(HANDLE hProcess, HMODULE hModule,
315 LPSTR lpFileName, DWORD nSize)
317 WCHAR *ptr;
319 TRACE("(hProcess=%p, hModule=%p, %p, %d)\n",
320 hProcess, hModule, lpFileName, nSize);
322 if (!lpFileName || !nSize) return 0;
324 if ( hProcess == GetCurrentProcess() )
326 DWORD len = GetModuleFileNameA( hModule, lpFileName, nSize );
327 if (nSize) lpFileName[nSize - 1] = '\0';
328 return len;
331 if (!(ptr = HeapAlloc(GetProcessHeap(), 0, nSize * sizeof(WCHAR)))) return 0;
333 if (!GetModuleFileNameExW(hProcess, hModule, ptr, nSize))
335 lpFileName[0] = '\0';
337 else
339 if (!WideCharToMultiByte( CP_ACP, 0, ptr, -1, lpFileName, nSize, NULL, NULL ))
340 lpFileName[nSize - 1] = 0;
343 HeapFree(GetProcessHeap(), 0, ptr);
344 return strlen(lpFileName);
347 /***********************************************************************
348 * GetModuleFileNameExW (PSAPI.@)
350 DWORD WINAPI GetModuleFileNameExW(HANDLE hProcess, HMODULE hModule,
351 LPWSTR lpFileName, DWORD nSize)
353 LDR_MODULE LdrModule;
355 if(!PSAPI_GetLdrModule(hProcess, hModule, &LdrModule))
356 return 0;
358 nSize = min(LdrModule.FullDllName.Length / sizeof(WCHAR), nSize);
359 if (!ReadProcessMemory(hProcess, LdrModule.FullDllName.Buffer,
360 lpFileName, nSize * sizeof(WCHAR), NULL))
361 return 0;
363 lpFileName[nSize] = 0;
364 return nSize;
367 /***********************************************************************
368 * GetModuleInformation (PSAPI.@)
370 BOOL WINAPI GetModuleInformation(HANDLE hProcess, HMODULE hModule,
371 LPMODULEINFO lpmodinfo, DWORD cb)
373 LDR_MODULE LdrModule;
375 if (cb < sizeof(MODULEINFO))
377 SetLastError(ERROR_INSUFFICIENT_BUFFER);
378 return FALSE;
381 if (!PSAPI_GetLdrModule(hProcess, hModule, &LdrModule))
382 return FALSE;
384 lpmodinfo->lpBaseOfDll = LdrModule.BaseAddress;
385 lpmodinfo->SizeOfImage = LdrModule.SizeOfImage;
386 lpmodinfo->EntryPoint = LdrModule.EntryPoint;
387 return TRUE;
390 /***********************************************************************
391 * GetPerformanceInfo (PSAPI.@)
393 BOOL WINAPI GetPerformanceInfo( PPERFORMANCE_INFORMATION info, DWORD size )
395 NTSTATUS status;
397 TRACE( "(%p, %d)\n", info, size );
399 status = NtQuerySystemInformation( SystemPerformanceInformation, info, size, NULL );
401 if (status)
403 SetLastError( RtlNtStatusToDosError( status ) );
404 return FALSE;
406 return TRUE;
409 /***********************************************************************
410 * GetWsChanges (PSAPI.@)
412 BOOL WINAPI GetWsChanges( HANDLE process, PPSAPI_WS_WATCH_INFORMATION watchinfo, DWORD size )
414 NTSTATUS status;
416 TRACE( "(%p, %p, %d)\n", process, watchinfo, size );
418 status = NtQueryInformationProcess( process, ProcessWorkingSetWatch, watchinfo, size, NULL );
420 if (status)
422 SetLastError( RtlNtStatusToDosError( status ) );
423 return FALSE;
425 return TRUE;
428 /***********************************************************************
429 * InitializeProcessForWsWatch (PSAPI.@)
431 BOOL WINAPI InitializeProcessForWsWatch(HANDLE hProcess)
433 FIXME("(hProcess=%p): stub\n", hProcess);
435 return TRUE;