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
25 #define WIN32_NO_STATUS
29 #include "wine/unicode.h"
30 #include "wine/debug.h"
35 WINE_DEFAULT_DEBUG_CHANNEL(psapi
);
40 PLIST_ENTRY pHead
, pCurrent
;
44 /***********************************************************************
45 * PSAPI_ModuleIteratorInit [internal]
47 * Prepares to iterate through the loaded modules of the given process.
53 static BOOL
PSAPI_ModuleIteratorInit(MODULE_ITERATOR
*iter
, HANDLE hProcess
)
55 PROCESS_BASIC_INFORMATION pbi
;
56 PPEB_LDR_DATA pLdrData
;
59 /* Get address of PEB */
60 status
= NtQueryInformationProcess(hProcess
, ProcessBasicInformation
,
61 &pbi
, sizeof(pbi
), NULL
);
62 if (status
!= STATUS_SUCCESS
)
64 SetLastError(RtlNtStatusToDosError(status
));
68 /* Read address of LdrData from PEB */
69 if (!ReadProcessMemory(hProcess
, &pbi
.PebBaseAddress
->LdrData
,
70 &pLdrData
, sizeof(pLdrData
), NULL
))
73 /* Read address of first module from LdrData */
74 if (!ReadProcessMemory(hProcess
,
75 &pLdrData
->InLoadOrderModuleList
.Flink
,
76 &iter
->pCurrent
, sizeof(iter
->pCurrent
), NULL
))
79 iter
->pHead
= &pLdrData
->InLoadOrderModuleList
;
80 iter
->hProcess
= hProcess
;
85 /***********************************************************************
86 * PSAPI_ModuleIteratorNext [internal]
88 * Iterates to the next module.
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
)
106 if (!ReadProcessMemory(iter
->hProcess
, CONTAINING_RECORD(iter
->pCurrent
,
107 LDR_MODULE
, InLoadOrderModuleList
),
108 &iter
->LdrModule
, sizeof(iter
->LdrModule
), NULL
))
111 iter
->pCurrent
= iter
->LdrModule
.InLoadOrderModuleList
.Flink
;
116 /***********************************************************************
117 * PSAPI_GetLdrModule [internal]
119 * Reads the LDR_MODULE structure of the given module.
126 static BOOL
PSAPI_GetLdrModule(HANDLE hProcess
, HMODULE hModule
,
127 LDR_MODULE
*pLdrModule
)
129 MODULE_ITERATOR iter
;
132 if (!PSAPI_ModuleIteratorInit(&iter
, hProcess
))
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
;
145 SetLastError(ERROR_INVALID_HANDLE
);
150 /***********************************************************************
151 * EnumDeviceDrivers (PSAPI.@)
153 BOOL WINAPI
EnumDeviceDrivers(LPVOID
*lpImageBase
, DWORD cb
, LPDWORD lpcbNeeded
)
155 FIXME("(%p, %d, %p): stub\n", lpImageBase
, cb
, lpcbNeeded
);
163 /***********************************************************************
164 * EnumPageFilesA (PSAPI.@)
166 BOOL WINAPI
EnumPageFilesA( PENUM_PAGE_FILE_CALLBACKA callback
, LPVOID context
)
168 FIXME("(%p, %p) stub\n", callback
, context
);
172 /***********************************************************************
173 * EnumPageFilesW (PSAPI.@)
175 BOOL WINAPI
EnumPageFilesW( PENUM_PAGE_FILE_CALLBACKW callback
, LPVOID context
)
177 FIXME("(%p, %p) stub\n", callback
, context
);
181 /***********************************************************************
182 * GetDeviceDriverBaseNameA (PSAPI.@)
184 DWORD WINAPI
GetDeviceDriverBaseNameA(LPVOID ImageBase
, LPSTR lpBaseName
,
187 FIXME("(%p, %p, %d): stub\n", ImageBase
, lpBaseName
, nSize
);
189 if (lpBaseName
&& nSize
)
190 lpBaseName
[0] = '\0';
195 /***********************************************************************
196 * GetDeviceDriverBaseNameW (PSAPI.@)
198 DWORD WINAPI
GetDeviceDriverBaseNameW(LPVOID ImageBase
, LPWSTR lpBaseName
,
201 FIXME("(%p, %p, %d): stub\n", ImageBase
, lpBaseName
, nSize
);
203 if (lpBaseName
&& nSize
)
204 lpBaseName
[0] = '\0';
209 /***********************************************************************
210 * GetDeviceDriverFileNameA (PSAPI.@)
212 DWORD WINAPI
GetDeviceDriverFileNameA(LPVOID ImageBase
, LPSTR lpFilename
,
215 FIXME("(%p, %p, %d): stub\n", ImageBase
, lpFilename
, nSize
);
217 if (lpFilename
&& nSize
)
218 lpFilename
[0] = '\0';
223 /***********************************************************************
224 * GetDeviceDriverFileNameW (PSAPI.@)
226 DWORD WINAPI
GetDeviceDriverFileNameW(LPVOID ImageBase
, LPWSTR lpFilename
,
229 FIXME("(%p, %p, %d): stub\n", ImageBase
, lpFilename
, nSize
);
231 if (lpFilename
&& nSize
)
232 lpFilename
[0] = '\0';
237 /***********************************************************************
238 * GetMappedFileNameA (PSAPI.@)
240 DWORD WINAPI
GetMappedFileNameA(HANDLE hProcess
, LPVOID lpv
, LPSTR lpFilename
,
243 FIXME("(%p, %p, %p, %d): stub\n", hProcess
, lpv
, lpFilename
, nSize
);
245 if (lpFilename
&& nSize
)
246 lpFilename
[0] = '\0';
251 /***********************************************************************
252 * GetMappedFileNameW (PSAPI.@)
254 DWORD WINAPI
GetMappedFileNameW(HANDLE hProcess
, LPVOID lpv
, LPWSTR lpFilename
,
257 FIXME("(%p, %p, %p, %d): stub\n", hProcess
, lpv
, lpFilename
, nSize
);
259 if (lpFilename
&& nSize
)
260 lpFilename
[0] = '\0';
265 /***********************************************************************
266 * GetModuleBaseNameA (PSAPI.@)
268 DWORD WINAPI
GetModuleBaseNameA(HANDLE hProcess
, HMODULE hModule
,
269 LPSTR lpBaseName
, DWORD nSize
)
272 DWORD buflenW
, ret
= 0;
274 if(!lpBaseName
|| !nSize
) {
275 SetLastError(ERROR_INVALID_PARAMETER
);
278 lpBaseNameW
= HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR
) * nSize
);
279 buflenW
= GetModuleBaseNameW(hProcess
, hModule
, lpBaseNameW
, nSize
);
280 TRACE("%d, %s\n", buflenW
, debugstr_w(lpBaseNameW
));
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
);
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
))
302 nSize
= min(LdrModule
.BaseDllName
.Length
/ sizeof(WCHAR
), nSize
);
303 if (!ReadProcessMemory(hProcess
, LdrModule
.BaseDllName
.Buffer
,
304 lpBaseName
, nSize
* sizeof(WCHAR
), NULL
))
307 lpBaseName
[nSize
] = 0;
311 /***********************************************************************
312 * GetModuleFileNameExA (PSAPI.@)
314 DWORD WINAPI
GetModuleFileNameExA(HANDLE hProcess
, HMODULE hModule
,
315 LPSTR lpFileName
, DWORD nSize
)
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';
331 if (!(ptr
= HeapAlloc(GetProcessHeap(), 0, nSize
* sizeof(WCHAR
)))) return 0;
333 if (!GetModuleFileNameExW(hProcess
, hModule
, ptr
, nSize
))
335 lpFileName
[0] = '\0';
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
))
358 nSize
= min(LdrModule
.FullDllName
.Length
/ sizeof(WCHAR
), nSize
);
359 if (!ReadProcessMemory(hProcess
, LdrModule
.FullDllName
.Buffer
,
360 lpFileName
, nSize
* sizeof(WCHAR
), NULL
))
363 lpFileName
[nSize
] = 0;
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
);
381 if (!PSAPI_GetLdrModule(hProcess
, hModule
, &LdrModule
))
384 lpmodinfo
->lpBaseOfDll
= LdrModule
.BaseAddress
;
385 lpmodinfo
->SizeOfImage
= LdrModule
.SizeOfImage
;
386 lpmodinfo
->EntryPoint
= LdrModule
.EntryPoint
;
390 /***********************************************************************
391 * GetPerformanceInfo (PSAPI.@)
393 BOOL WINAPI
GetPerformanceInfo( PPERFORMANCE_INFORMATION info
, DWORD size
)
397 TRACE( "(%p, %d)\n", info
, size
);
399 status
= NtQuerySystemInformation( SystemPerformanceInformation
, info
, size
, NULL
);
403 SetLastError( RtlNtStatusToDosError( status
) );
409 /***********************************************************************
410 * GetWsChanges (PSAPI.@)
412 BOOL WINAPI
GetWsChanges( HANDLE process
, PPSAPI_WS_WATCH_INFORMATION watchinfo
, DWORD size
)
416 TRACE( "(%p, %p, %d)\n", process
, watchinfo
, size
);
418 status
= NtQueryInformationProcess( process
, ProcessWorkingSetWatch
, watchinfo
, size
, NULL
);
422 SetLastError( RtlNtStatusToDosError( status
) );
428 /***********************************************************************
429 * InitializeProcessForWsWatch (PSAPI.@)
431 BOOL WINAPI
InitializeProcessForWsWatch(HANDLE hProcess
)
433 FIXME("(hProcess=%p): stub\n", hProcess
);