- Replaced server requests by native APIs in EnumProcessModules,
GetModuleBaseNameW, GetModuleFileNameExW and GetModuleInformation. - Make EnumProcessModules return modules in load order - Set ERROR_INSUFFICIENT_BUFFER in GetModuleInformation when failing due to (cb < sizeof(MODULEINFO)).
This commit is contained in:
parent
fc6b6f4848
commit
f192bb60f8
|
@ -24,15 +24,128 @@
|
||||||
#include "windef.h"
|
#include "windef.h"
|
||||||
#include "winbase.h"
|
#include "winbase.h"
|
||||||
#include "winerror.h"
|
#include "winerror.h"
|
||||||
#include "wine/server.h"
|
|
||||||
#include "wine/unicode.h"
|
#include "wine/unicode.h"
|
||||||
#include "wine/debug.h"
|
#include "wine/debug.h"
|
||||||
#include "winnls.h"
|
#include "winnls.h"
|
||||||
|
#include "winternl.h"
|
||||||
#include "ntstatus.h"
|
#include "ntstatus.h"
|
||||||
#include "psapi.h"
|
#include "psapi.h"
|
||||||
|
|
||||||
WINE_DEFAULT_DEBUG_CHANNEL(psapi);
|
WINE_DEFAULT_DEBUG_CHANNEL(psapi);
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
HANDLE hProcess;
|
||||||
|
PLIST_ENTRY pHead, pCurrent;
|
||||||
|
LDR_MODULE LdrModule;
|
||||||
|
} MODULE_ITERATOR;
|
||||||
|
|
||||||
|
/***********************************************************************
|
||||||
|
* PSAPI_ModuleIteratorInit [internal]
|
||||||
|
*
|
||||||
|
* Prepares to iterate through the loaded modules of the given process.
|
||||||
|
*
|
||||||
|
* RETURNS
|
||||||
|
* Success: TRUE
|
||||||
|
* Failure: FALSE
|
||||||
|
*/
|
||||||
|
static BOOL PSAPI_ModuleIteratorInit(MODULE_ITERATOR *iter, HANDLE hProcess)
|
||||||
|
{
|
||||||
|
PROCESS_BASIC_INFORMATION pbi;
|
||||||
|
PPEB_LDR_DATA pLdrData;
|
||||||
|
NTSTATUS status;
|
||||||
|
|
||||||
|
/* Get address of PEB */
|
||||||
|
status = NtQueryInformationProcess(hProcess, ProcessBasicInformation,
|
||||||
|
&pbi, sizeof(pbi), NULL);
|
||||||
|
if (status != STATUS_SUCCESS)
|
||||||
|
{
|
||||||
|
SetLastError(RtlNtStatusToDosError(status));
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Read address of LdrData from PEB */
|
||||||
|
if (!ReadProcessMemory(hProcess, &((PPEB)pbi.PebBaseAddress)->LdrData,
|
||||||
|
&pLdrData, sizeof(pLdrData), NULL))
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
/* Read address of first module from LdrData */
|
||||||
|
if (!ReadProcessMemory(hProcess,
|
||||||
|
&pLdrData->InLoadOrderModuleList.Flink,
|
||||||
|
&iter->pCurrent, sizeof(iter->pCurrent), NULL))
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
iter->pHead = &pLdrData->InLoadOrderModuleList;
|
||||||
|
iter->hProcess = hProcess;
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/***********************************************************************
|
||||||
|
* PSAPI_ModuleIteratorNext [internal]
|
||||||
|
*
|
||||||
|
* Iterates to the next module.
|
||||||
|
*
|
||||||
|
* RETURNS
|
||||||
|
* 1 : Success
|
||||||
|
* 0 : No more modules
|
||||||
|
* -1 : Failure
|
||||||
|
*
|
||||||
|
* NOTES
|
||||||
|
* Every function which uses this routine suffers from a race condition
|
||||||
|
* when a module is unloaded during the enumeration which can cause the
|
||||||
|
* function to fail. As there is no way to lock the loader of another
|
||||||
|
* process we can't avoid that.
|
||||||
|
*/
|
||||||
|
static INT PSAPI_ModuleIteratorNext(MODULE_ITERATOR *iter)
|
||||||
|
{
|
||||||
|
if (iter->pCurrent == iter->pHead)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if (!ReadProcessMemory(iter->hProcess, CONTAINING_RECORD(iter->pCurrent,
|
||||||
|
LDR_MODULE, InLoadOrderModuleList),
|
||||||
|
&iter->LdrModule, sizeof(iter->LdrModule), NULL))
|
||||||
|
return -1;
|
||||||
|
else
|
||||||
|
iter->pCurrent = iter->LdrModule.InLoadOrderModuleList.Flink;
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/***********************************************************************
|
||||||
|
* PSAPI_GetLdrModule [internal]
|
||||||
|
*
|
||||||
|
* Reads the LDR_MODULE structure of the given module.
|
||||||
|
*
|
||||||
|
* RETURNS
|
||||||
|
* Success: TRUE
|
||||||
|
* Failure: FALSE
|
||||||
|
*/
|
||||||
|
|
||||||
|
static BOOL PSAPI_GetLdrModule(HANDLE hProcess, HMODULE hModule,
|
||||||
|
LDR_MODULE *pLdrModule)
|
||||||
|
{
|
||||||
|
MODULE_ITERATOR iter;
|
||||||
|
INT ret;
|
||||||
|
|
||||||
|
if (!PSAPI_ModuleIteratorInit(&iter, hProcess))
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
while ((ret = PSAPI_ModuleIteratorNext(&iter)) > 0)
|
||||||
|
/* When hModule is NULL we return the process image - which will be
|
||||||
|
* the first module since our iterator uses InLoadOrderModuleList */
|
||||||
|
if (!hModule || hModule == (HMODULE)iter.LdrModule.BaseAddress)
|
||||||
|
{
|
||||||
|
*pLdrModule = iter.LdrModule;
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ret == 0)
|
||||||
|
SetLastError(ERROR_INVALID_HANDLE);
|
||||||
|
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
/***********************************************************************
|
/***********************************************************************
|
||||||
* EmptyWorkingSet (PSAPI.@)
|
* EmptyWorkingSet (PSAPI.@)
|
||||||
*/
|
*/
|
||||||
|
@ -106,12 +219,12 @@ BOOL WINAPI EnumProcesses(DWORD *lpdwProcessIDs, DWORD cb, DWORD *lpcbUsed)
|
||||||
|
|
||||||
spi = pBuf;
|
spi = pBuf;
|
||||||
|
|
||||||
for(*lpcbUsed = 0; cb >= sizeof(DWORD); cb -= sizeof(DWORD))
|
for (*lpcbUsed = 0; cb >= sizeof(DWORD); cb -= sizeof(DWORD))
|
||||||
{
|
{
|
||||||
*lpdwProcessIDs++ = spi->dwProcessID;
|
*lpdwProcessIDs++ = spi->dwProcessID;
|
||||||
*lpcbUsed += sizeof(DWORD);
|
*lpcbUsed += sizeof(DWORD);
|
||||||
|
|
||||||
if(spi->dwOffset == 0)
|
if (spi->dwOffset == 0)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
spi = (SYSTEM_PROCESS_INFORMATION *)(((PCHAR)spi) + spi->dwOffset);
|
spi = (SYSTEM_PROCESS_INFORMATION *)(((PCHAR)spi) + spi->dwOffset);
|
||||||
|
@ -123,83 +236,32 @@ BOOL WINAPI EnumProcesses(DWORD *lpdwProcessIDs, DWORD cb, DWORD *lpcbUsed)
|
||||||
|
|
||||||
/***********************************************************************
|
/***********************************************************************
|
||||||
* EnumProcessModules (PSAPI.@)
|
* EnumProcessModules (PSAPI.@)
|
||||||
|
*
|
||||||
|
* NOTES
|
||||||
|
* Returned list is in load order.
|
||||||
*/
|
*/
|
||||||
BOOL WINAPI EnumProcessModules(HANDLE hProcess, HMODULE *lphModule,
|
BOOL WINAPI EnumProcessModules(HANDLE hProcess, HMODULE *lphModule,
|
||||||
DWORD cb, LPDWORD lpcbNeeded)
|
DWORD cb, LPDWORD lpcbNeeded)
|
||||||
{
|
{
|
||||||
HANDLE hSnapshot;
|
MODULE_ITERATOR iter;
|
||||||
DWORD pid;
|
INT ret;
|
||||||
DWORD count;
|
|
||||||
DWORD countMax;
|
|
||||||
int ret;
|
|
||||||
HMODULE hModule;
|
|
||||||
|
|
||||||
TRACE("(hProcess=%p, %p, %ld, %p)\n",
|
if (!PSAPI_ModuleIteratorInit(&iter, hProcess))
|
||||||
hProcess, lphModule, cb, lpcbNeeded );
|
|
||||||
|
|
||||||
if ( lphModule == NULL )
|
|
||||||
cb = 0;
|
|
||||||
if ( lpcbNeeded != NULL )
|
|
||||||
*lpcbNeeded = 0;
|
|
||||||
|
|
||||||
SERVER_START_REQ( get_process_info )
|
|
||||||
{
|
|
||||||
req->handle = hProcess;
|
|
||||||
if ( !wine_server_call_err( req ) )
|
|
||||||
pid = (DWORD)reply->pid;
|
|
||||||
else
|
|
||||||
pid = 0;
|
|
||||||
}
|
|
||||||
SERVER_END_REQ;
|
|
||||||
|
|
||||||
if ( pid == 0 )
|
|
||||||
{
|
|
||||||
FIXME("no pid for hProcess %p\n" ,hProcess);
|
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
|
||||||
|
|
||||||
SERVER_START_REQ( create_snapshot )
|
*lpcbNeeded = 0;
|
||||||
|
|
||||||
|
while ((ret = PSAPI_ModuleIteratorNext(&iter)) > 0)
|
||||||
{
|
{
|
||||||
req->flags = SNAP_MODULE;
|
if (cb >= sizeof(HMODULE))
|
||||||
req->inherit = FALSE;
|
|
||||||
req->pid = pid;
|
|
||||||
wine_server_call_err( req );
|
|
||||||
hSnapshot = reply->handle;
|
|
||||||
}
|
|
||||||
SERVER_END_REQ;
|
|
||||||
if ( hSnapshot == 0 )
|
|
||||||
{
|
|
||||||
FIXME("cannot create snapshot\n");
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
count = 0;
|
|
||||||
countMax = cb / sizeof(HMODULE);
|
|
||||||
for (;;)
|
|
||||||
{
|
|
||||||
SERVER_START_REQ( next_module )
|
|
||||||
{
|
{
|
||||||
req->handle = hSnapshot;
|
*lphModule++ = (HMODULE)iter.LdrModule.BaseAddress;
|
||||||
req->reset = (count == 0);
|
cb -= sizeof(HMODULE);
|
||||||
if ((ret = !wine_server_call_err( req )))
|
|
||||||
{
|
|
||||||
hModule = (HMODULE)reply->base;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
SERVER_END_REQ;
|
*lpcbNeeded += sizeof(HMODULE);
|
||||||
if ( !ret ) break;
|
|
||||||
TRACE("module 0x%p\n", hModule);
|
|
||||||
if ( count < countMax )
|
|
||||||
lphModule[count] = hModule;
|
|
||||||
count++;
|
|
||||||
}
|
}
|
||||||
CloseHandle( hSnapshot );
|
|
||||||
|
|
||||||
if ( lpcbNeeded != NULL )
|
return (ret == 0);
|
||||||
*lpcbNeeded = sizeof(HMODULE) * count;
|
|
||||||
|
|
||||||
TRACE("return %lu modules\n", count);
|
|
||||||
|
|
||||||
return TRUE;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/***********************************************************************
|
/***********************************************************************
|
||||||
|
@ -324,23 +386,18 @@ DWORD WINAPI GetModuleBaseNameA(HANDLE hProcess, HMODULE hModule,
|
||||||
DWORD WINAPI GetModuleBaseNameW(HANDLE hProcess, HMODULE hModule,
|
DWORD WINAPI GetModuleBaseNameW(HANDLE hProcess, HMODULE hModule,
|
||||||
LPWSTR lpBaseName, DWORD nSize)
|
LPWSTR lpBaseName, DWORD nSize)
|
||||||
{
|
{
|
||||||
WCHAR tmp[MAX_PATH];
|
LDR_MODULE LdrModule;
|
||||||
WCHAR* ptr;
|
|
||||||
int ptrlen;
|
|
||||||
|
|
||||||
if(!lpBaseName || !nSize) {
|
if (!PSAPI_GetLdrModule(hProcess, hModule, &LdrModule))
|
||||||
SetLastError(ERROR_INVALID_PARAMETER);
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
|
||||||
|
|
||||||
if (!GetModuleFileNameExW(hProcess, hModule, tmp,
|
nSize = min(LdrModule.BaseDllName.Length / sizeof(WCHAR), nSize);
|
||||||
sizeof(tmp)/sizeof(WCHAR)))
|
if (!ReadProcessMemory(hProcess, LdrModule.BaseDllName.Buffer,
|
||||||
|
lpBaseName, nSize * sizeof(WCHAR), NULL))
|
||||||
return 0;
|
return 0;
|
||||||
TRACE("%s\n", debugstr_w(tmp));
|
|
||||||
if ((ptr = strrchrW(tmp, '\\')) != NULL) ptr++; else ptr = tmp;
|
lpBaseName[nSize] = 0;
|
||||||
ptrlen = strlenW(ptr);
|
return nSize;
|
||||||
memcpy(lpBaseName, ptr, min(ptrlen+1,nSize) * sizeof(WCHAR));
|
|
||||||
return min(ptrlen, nSize);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/***********************************************************************
|
/***********************************************************************
|
||||||
|
@ -385,39 +442,18 @@ DWORD WINAPI GetModuleFileNameExA(HANDLE hProcess, HMODULE hModule,
|
||||||
DWORD WINAPI GetModuleFileNameExW(HANDLE hProcess, HMODULE hModule,
|
DWORD WINAPI GetModuleFileNameExW(HANDLE hProcess, HMODULE hModule,
|
||||||
LPWSTR lpFileName, DWORD nSize)
|
LPWSTR lpFileName, DWORD nSize)
|
||||||
{
|
{
|
||||||
DWORD len = 0;
|
LDR_MODULE LdrModule;
|
||||||
|
|
||||||
|
if(!PSAPI_GetLdrModule(hProcess, hModule, &LdrModule))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
nSize = min(LdrModule.FullDllName.Length / sizeof(WCHAR), nSize);
|
||||||
|
if (!ReadProcessMemory(hProcess, LdrModule.FullDllName.Buffer,
|
||||||
|
lpFileName, nSize * sizeof(WCHAR), NULL))
|
||||||
|
return 0;
|
||||||
|
|
||||||
TRACE("(hProcess=%p, hModule=%p, %p, %ld)\n",
|
lpFileName[nSize] = 0;
|
||||||
hProcess, hModule, lpFileName, nSize);
|
return nSize;
|
||||||
|
|
||||||
if (!lpFileName || !nSize) return 0;
|
|
||||||
|
|
||||||
if ( hProcess == GetCurrentProcess() )
|
|
||||||
{
|
|
||||||
DWORD len = GetModuleFileNameW( hModule, lpFileName, nSize );
|
|
||||||
if (nSize) lpFileName[nSize - 1] = '\0';
|
|
||||||
TRACE("return (cur) %s (%lu)\n", debugstr_w(lpFileName), len);
|
|
||||||
return len;
|
|
||||||
}
|
|
||||||
|
|
||||||
lpFileName[0] = 0;
|
|
||||||
|
|
||||||
SERVER_START_REQ( get_dll_info )
|
|
||||||
{
|
|
||||||
req->handle = hProcess;
|
|
||||||
req->base_address = hModule;
|
|
||||||
wine_server_set_reply( req, lpFileName, (nSize - 1) * sizeof(WCHAR) );
|
|
||||||
if (!wine_server_call_err( req ))
|
|
||||||
{
|
|
||||||
len = wine_server_reply_size(reply) / sizeof(WCHAR);
|
|
||||||
lpFileName[len] = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
SERVER_END_REQ;
|
|
||||||
|
|
||||||
TRACE("return %s (%lu)\n", debugstr_w(lpFileName), len);
|
|
||||||
|
|
||||||
return len;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/***********************************************************************
|
/***********************************************************************
|
||||||
|
@ -426,27 +462,20 @@ DWORD WINAPI GetModuleFileNameExW(HANDLE hProcess, HMODULE hModule,
|
||||||
BOOL WINAPI GetModuleInformation(HANDLE hProcess, HMODULE hModule,
|
BOOL WINAPI GetModuleInformation(HANDLE hProcess, HMODULE hModule,
|
||||||
LPMODULEINFO lpmodinfo, DWORD cb)
|
LPMODULEINFO lpmodinfo, DWORD cb)
|
||||||
{
|
{
|
||||||
BOOL ret = FALSE;
|
LDR_MODULE LdrModule;
|
||||||
|
|
||||||
TRACE("(hProcess=%p, hModule=%p, %p, %ld)\n",
|
if (cb < sizeof(MODULEINFO))
|
||||||
hProcess, hModule, lpmodinfo, cb);
|
|
||||||
|
|
||||||
if (cb < sizeof(MODULEINFO)) return FALSE;
|
|
||||||
|
|
||||||
SERVER_START_REQ( get_dll_info )
|
|
||||||
{
|
{
|
||||||
req->handle = hProcess;
|
SetLastError(ERROR_INSUFFICIENT_BUFFER);
|
||||||
req->base_address = (void*)hModule;
|
return FALSE;
|
||||||
if (!wine_server_call_err( req ))
|
|
||||||
{
|
|
||||||
ret = TRUE;
|
|
||||||
lpmodinfo->lpBaseOfDll = (void*)hModule;
|
|
||||||
lpmodinfo->SizeOfImage = reply->size;
|
|
||||||
lpmodinfo->EntryPoint = reply->entry_point;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
SERVER_END_REQ;
|
|
||||||
|
|
||||||
|
if (!PSAPI_GetLdrModule(hProcess, hModule, &LdrModule))
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
lpmodinfo->lpBaseOfDll = LdrModule.BaseAddress;
|
||||||
|
lpmodinfo->SizeOfImage = LdrModule.SizeOfImage;
|
||||||
|
lpmodinfo->EntryPoint = LdrModule.EntryPoint;
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue