PSAPI: all the annoying stuff (enumeration and search, basically) has been taken care of. Only profiling remains to be implemented.

Check out the subsystem-independent routines in enum/ (FWIW: the whole DLL only imports two calls from kernel32.dll, SetLastError and AreFileApisANSI): they've been tested, and they could make for a great static library, to implement task manager, tlist, ToolHelp API, etc. Maybe a future addition to mingwnt?

svn path=/trunk/; revision=3441
This commit is contained in:
KJK::Hyperion 2002-08-31 15:36:56 +00:00
parent c0b94f90f9
commit a0cbde7bb0
8 changed files with 746 additions and 233 deletions

View file

@ -1,4 +1,4 @@
/* $Id: module.c,v 1.2 2002/08/29 23:57:53 hyperion Exp $
/* $Id: module.c,v 1.3 2002/08/31 15:36:55 hyperion Exp $
*/
/*
* COPYRIGHT: See COPYING in the top level directory
@ -23,8 +23,7 @@ STDCALL
PsaEnumerateSystemModules
(
IN PSYSMOD_ENUM_ROUTINE Callback,
IN OUT PVOID CallbackContext,
IN OUT PVOID AllocatorContext
IN OUT PVOID CallbackContext
)
{
ULONG nSize;
@ -63,8 +62,8 @@ PsaEnumerateSystemModules
/* free the buffer, and reallocate it to the new size. RATIONALE: since we
ignore the buffer's content at this point, there's no point in a realloc(),
that could end up copying a large chunk of data we'd discard anyway */
PsaFree(AllocatorContext, pnModuleCount);
pTmp = PsaMalloc(AllocatorContext, nSize);
free(pnModuleCount);
pTmp = malloc(nSize);
if(pTmp == NULL)
{
@ -119,7 +118,7 @@ PsaEnumerateSystemModules
esm_Finalize:
/* free the buffer */
PsaFree(AllocatorContext, pnModuleCount);
free(pnModuleCount);
return (nErrCode);
}

View file

@ -1,4 +1,4 @@
/* $Id: process.c,v 1.2 2002/08/29 23:57:53 hyperion Exp $
/* $Id: process.c,v 1.3 2002/08/31 15:36:55 hyperion Exp $
*/
/*
* COPYRIGHT: See COPYING in the top level directory
@ -23,8 +23,7 @@ STDCALL
PsaEnumerateProcesses
(
IN PPROC_ENUM_ROUTINE Callback,
IN OUT PVOID CallbackContext,
IN OUT PVOID AllocatorContext
IN OUT PVOID CallbackContext
)
{
register NTSTATUS nErrCode = STATUS_SUCCESS;
@ -44,8 +43,8 @@ PsaEnumerateProcesses
/* free the buffer, and reallocate it to the new size. RATIONALE: since we
ignore the buffer's contents at this point, there's no point in a realloc()
that could end up copying a large chunk of data we'd discard anyway */
PsaFree(AllocatorContext, pInfoBuffer);
pTmp = PsaMalloc(AllocatorContext, nSize);
free(pInfoBuffer);
pTmp = malloc(nSize);
if(pTmp == NULL)
{
@ -101,7 +100,7 @@ PsaEnumerateProcesses
esp_Finalize:
/* free the buffer */
PsaFree(AllocatorContext, pInfoBuffer);
free(pInfoBuffer);
/* return the last status */
return (nErrCode);

View file

@ -1,4 +1,4 @@
/* $Id: psapi.h,v 1.2 2002/08/29 23:57:54 hyperion Exp $
/* $Id: psapi.h,v 1.3 2002/08/31 15:36:55 hyperion Exp $
*/
/*
* internal/psapi.h
@ -61,8 +61,7 @@ STDCALL
PsaEnumerateProcesses
(
IN PPROC_ENUM_ROUTINE Callback,
IN OUT PVOID CallbackContext,
IN OUT PVOID AllocatorContext
IN OUT PVOID CallbackContext
);
NTSTATUS
@ -70,8 +69,7 @@ STDCALL
PsaEnumerateSystemModules
(
IN PSYSMOD_ENUM_ROUTINE Callback,
IN OUT PVOID CallbackContext,
IN OUT PVOID AllocatorContext
IN OUT PVOID CallbackContext
);
NTSTATUS
@ -83,11 +81,6 @@ PsaEnumerateProcessModules
IN OUT PVOID CallbackContext
);
/* the user must provide these */
PVOID STDCALL PsaMalloc(IN OUT PVOID Context, IN ULONG Size);
PVOID STDCALL PsaRealloc(IN OUT PVOID Context, IN PVOID Addr, IN ULONG Size);
VOID STDCALL PsaFree(IN OUT PVOID Context, IN PVOID Addr);
/* MACROS */
#define DEFINE_DBG_MSG(__str__) "PSAPI: " __str__ "\n"

View file

@ -1,4 +1,4 @@
# $Id: makefile,v 1.2 2002/06/18 22:15:57 hyperion Exp $
# $Id: makefile,v 1.3 2002/08/31 15:36:56 hyperion Exp $
PATH_TO_TOP = ../..
@ -10,8 +10,6 @@ TARGET_SDKLIBS = ntdll.a kernel32.a
TARGET_CFLAGS = -I./include -Wall
TARGET_LFLAGS = -nostdlib
TARGET_BASE = 0x68F70000
TARGET_OBJECTS = \

View file

@ -1,4 +1,4 @@
/* $Id: stubs.c,v 1.3 2002/08/29 23:57:54 hyperion Exp $ */
/* $Id: stubs.c,v 1.4 2002/08/31 15:36:56 hyperion Exp $ */
#include <windows.h>
#include <psapi.h>
@ -11,124 +11,7 @@ BOOL STDCALL EnumPageFiles(
SetLastError(ERROR_INVALID_FUNCTION);
return FALSE;
}
#endif
DWORD STDCALL GetDeviceDriverBaseNameA(
LPVOID ImageBase, // driver load address
LPSTR lpBaseName, // driver base name buffer
DWORD nSize // size of buffer
)
{
SetLastError(ERROR_INVALID_FUNCTION);
return FALSE;
}
DWORD STDCALL GetDeviceDriverBaseNameW(
LPVOID ImageBase, // driver load address
LPWSTR lpBaseName, // driver base name buffer
DWORD nSize // size of buffer
)
{
SetLastError(ERROR_INVALID_FUNCTION);
return FALSE;
}
DWORD STDCALL GetDeviceDriverFileNameA(
LPVOID ImageBase, // driver load address
LPSTR lpFilename, // path buffer
DWORD nSize // size of buffer
)
{
SetLastError(ERROR_INVALID_FUNCTION);
return FALSE;
}
DWORD STDCALL GetDeviceDriverFileNameW(
LPVOID ImageBase, // driver load address
LPWSTR lpFilename, // path buffer
DWORD nSize // size of buffer
)
{
SetLastError(ERROR_INVALID_FUNCTION);
return FALSE;
}
DWORD STDCALL GetMappedFileNameA(
HANDLE hProcess, // handle to process
LPVOID lpv, // address to verify
LPSTR lpFilename, // file name buffer
DWORD nSize // size of buffer
)
{
SetLastError(ERROR_INVALID_FUNCTION);
return FALSE;
}
DWORD STDCALL GetMappedFileNameW(
HANDLE hProcess, // handle to process
LPVOID lpv, // address to verify
LPWSTR lpFilename, // file name buffer
DWORD nSize // size of buffer
)
{
SetLastError(ERROR_INVALID_FUNCTION);
return FALSE;
}
DWORD STDCALL GetModuleBaseNameA(
HANDLE hProcess, // handle to process
HMODULE hModule, // handle to module
LPSTR lpBaseName, // base name buffer
DWORD nSize // maximum characters to retrieve
)
{
SetLastError(ERROR_INVALID_FUNCTION);
return FALSE;
}
DWORD STDCALL GetModuleBaseNameW(
HANDLE hProcess, // handle to process
HMODULE hModule, // handle to module
LPWSTR lpBaseName, // base name buffer
DWORD nSize // maximum characters to retrieve
)
{
SetLastError(ERROR_INVALID_FUNCTION);
return FALSE;
}
DWORD STDCALL GetModuleFileNameExA(
HANDLE hProcess, // handle to process
HMODULE hModule, // handle to module
LPSTR lpFilename, // path buffer
DWORD nSize // maximum characters to retrieve
)
{
SetLastError(ERROR_INVALID_FUNCTION);
return FALSE;
}
DWORD STDCALL GetModuleFileNameExW(
HANDLE hProcess, // handle to process
HMODULE hModule, // handle to module
LPWSTR lpFilename, // path buffer
DWORD nSize // maximum characters to retrieve
)
{
SetLastError(ERROR_INVALID_FUNCTION);
return FALSE;
}
BOOL STDCALL GetModuleInformation(
HANDLE hProcess, // handle to process
HMODULE hModule, // handle to module
LPMODULEINFO lpmodinfo, // information buffer
DWORD cb // size of buffer
)
{
SetLastError(ERROR_INVALID_FUNCTION);
return FALSE;
}
#if 0
BOOL STDCALL GetPerformanceInfo(
PPERFORMANCE_INFORMATION pPerformanceInformation,
DWORD cb

View file

@ -1,4 +1,4 @@
/* $Id: win32.c,v 1.2 2002/08/29 23:57:54 hyperion Exp $
/* $Id: win32.c,v 1.3 2002/08/31 15:36:56 hyperion Exp $
*/
/*
* COPYRIGHT: See COPYING in the top level directory
@ -12,32 +12,18 @@
#include <windows.h>
#include <psapi.h>
#include <stddef.h>
#include <stdlib.h>
#include <string.h>
#include <ddk/ntddk.h>
#include <internal/psapi.h>
/* Memory allocators for PSAPI */
PVOID STDCALL PsaMalloc(IN OUT PVOID Context, IN ULONG Size)
{
return malloc(Size);
}
PVOID STDCALL PsaRealloc(IN OUT PVOID Context, IN PVOID Addr, IN ULONG Size)
{
return realloc(Addr, Size);
}
VOID STDCALL PsaFree(IN OUT PVOID Context, IN PVOID Addr)
{
free(Addr);
}
/* EmptyWorkingSet */
BOOL STDCALL EmptyWorkingSet(HANDLE hProcess)
{
NTSTATUS nErrCode;
QUOTA_LIMITS qlProcessQuota;
/* query the working set */
nErrCode = NtQueryInformationProcess
(
@ -51,11 +37,11 @@ BOOL STDCALL EmptyWorkingSet(HANDLE hProcess)
/* failure */
if(!NT_SUCCESS(nErrCode))
goto fail;
/* empty the working set */
qlProcessQuota.MinimumWorkingSetSize = -1;
qlProcessQuota.MaximumWorkingSetSize = -1;
/* set the working set */
nErrCode = NtSetInformationProcess
(
@ -68,7 +54,7 @@ BOOL STDCALL EmptyWorkingSet(HANDLE hProcess)
/* success */
if(NT_SUCCESS(nErrCode))
return (TRUE);
fail:
/* failure */
SetLastError(RtlNtStatusToDosError(nErrCode));
@ -100,20 +86,20 @@ NTSTATUS STDCALL EnumDeviceDriversCallback
/* return current module */
*(peddcContext->lpImageBase) = CurrentModule->BaseAddress;
/* go to next array slot */
(peddcContext->lpImageBase) ++;
(peddcContext->nCount) --;
return STATUS_SUCCESS;
}
/* exported interface */
BOOL STDCALL EnumDeviceDrivers
(
LPVOID *lpImageBase,
DWORD cb,
LPDWORD lpcbNeeded
LPVOID *lpImageBase,
DWORD cb,
LPDWORD lpcbNeeded
)
{
register NTSTATUS nErrCode;
@ -127,15 +113,10 @@ BOOL STDCALL EnumDeviceDrivers
*lpcbNeeded = 0;
return (TRUE);
}
/* enumerate the system modules */
nErrCode = PsaEnumerateSystemModules
(
&EnumDeviceDriversCallback,
&eddcContext,
NULL
);
nErrCode = PsaEnumerateSystemModules(&EnumDeviceDriversCallback, &eddcContext);
/* return the count of bytes returned */
*lpcbNeeded = (cb - eddcContext.nCount) * sizeof(PVOID);
@ -174,11 +155,11 @@ NTSTATUS STDCALL EnumProcessesCallback
/* return current process */
*(pepcContext->lpidProcess) = CurrentProcess->ProcessId;
/* go to next array slot */
(pepcContext->lpidProcess) ++;
(pepcContext->nCount) --;
return STATUS_SUCCESS;
}
@ -192,7 +173,7 @@ BOOL STDCALL EnumProcesses
{
register NTSTATUS nErrCode;
ENUM_PROCESSES_CONTEXT epcContext = {lpidProcess, cb / sizeof(DWORD)};
cb /= sizeof(DWORD);
/* do nothing if the buffer is empty */
@ -201,10 +182,10 @@ BOOL STDCALL EnumProcesses
*lpcbNeeded = 0;
return (TRUE);
}
/* enumerate the process ids */
nErrCode = PsaEnumerateProcesses(&EnumProcessesCallback, &epcContext, NULL);
nErrCode = PsaEnumerateProcesses(&EnumProcessesCallback, &epcContext);
*lpcbNeeded = (cb - epcContext.nCount) * sizeof(DWORD);
/* success */
@ -234,7 +215,7 @@ NTSTATUS STDCALL EnumProcessModulesCallback
IN OUT PVOID CallbackContext
)
{
register PENUM_PROCESS_MODULES_CONTEXT pepmcContext =
register PENUM_PROCESS_MODULES_CONTEXT pepmcContext =
(PENUM_PROCESS_MODULES_CONTEXT)CallbackContext;
/* no more buffer space */
@ -243,25 +224,25 @@ NTSTATUS STDCALL EnumProcessModulesCallback
/* return current process */
*(pepmcContext->lphModule) = CurrentModule->BaseAddress;
/* go to next array slot */
(pepmcContext->lphModule) ++;
(pepmcContext->nCount) --;
return STATUS_SUCCESS;
}
/* exported interface */
BOOL STDCALL EnumProcessModules(
HANDLE hProcess, // handle to process
HMODULE *lphModule, // array of module handles
DWORD cb, // size of array
LPDWORD lpcbNeeded // number of bytes required
HANDLE hProcess,
HMODULE *lphModule,
DWORD cb,
LPDWORD lpcbNeeded
)
{
register NTSTATUS nErrCode;
ENUM_PROCESS_MODULES_CONTEXT epmcContext = {lphModule, cb / sizeof(HMODULE)};
cb /= sizeof(DWORD);
/* do nothing if the buffer is empty */
@ -270,7 +251,7 @@ BOOL STDCALL EnumProcessModules(
*lpcbNeeded = 0;
return (TRUE);
}
/* enumerate the process modules */
nErrCode = PsaEnumerateProcessModules
(
@ -278,7 +259,7 @@ BOOL STDCALL EnumProcessModules(
&EnumProcessModulesCallback,
&epmcContext
);
*lpcbNeeded = (cb - epmcContext.nCount) * sizeof(DWORD);
/* success */
@ -292,5 +273,665 @@ BOOL STDCALL EnumProcessModules(
}
}
/* GetDeviceDriverBase/FileName */
/* common callback context */
typedef struct _GET_DEVICE_DRIVER_NAME_CONTEXT
{
LPVOID ImageBase;
struct
{
ULONG bFullName:sizeof(ULONG) * 8 / 2;
ULONG bUnicode:sizeof(ULONG) * 8 / 2;
};
DWORD nSize;
union
{
LPVOID lpName;
LPSTR lpAnsiName;
LPWSTR lpUnicodeName;
};
} GET_DEVICE_DRIVER_NAME_CONTEXT, *PGET_DEVICE_DRIVER_NAME_CONTEXT;
/* common callback routine */
NTSTATUS STDCALL GetDeviceDriverNameCallback
(
IN ULONG ModuleCount,
IN PSYSTEM_MODULE_ENTRY CurrentModule,
IN OUT PVOID CallbackContext
)
{
register PGET_DEVICE_DRIVER_NAME_CONTEXT pgddncContext =
(PGET_DEVICE_DRIVER_NAME_CONTEXT) CallbackContext;
/* module found */
if(pgddncContext->ImageBase == CurrentModule->BaseAddress)
{
register PCHAR pcModuleName;
register ULONG l;
/* get the full name or just the filename part */
if(pgddncContext->bFullName)
pcModuleName = &CurrentModule->Name[0];
else
pcModuleName = &CurrentModule->Name[CurrentModule->PathLength];
/* get the length of the name */
l = strlen(pcModuleName);
/* if user buffer smaller than the name */
if(pgddncContext->nSize <= l)
/* use the user buffer's length */
l = pgddncContext->nSize;
/* if user buffer larger than the name */
else
{
/* enough space for the null terminator */
l ++;
pgddncContext->nSize = l;
}
/* copy the string */
if(pgddncContext->bUnicode)
{
/* Unicode: convert and copy */
ANSI_STRING strAnsi = {l, l, pcModuleName};
UNICODE_STRING wstrUnicode =
{
0,
l * sizeof(WCHAR),
pgddncContext->lpUnicodeName
};
/* driver names should always be in language-neutral ASCII, so we don't
bother calling AreFileApisANSI() */
RtlAnsiStringToUnicodeString(&wstrUnicode, &strAnsi, FALSE);
}
else
/* ANSI/OEM: direct copy */
memcpy(pgddncContext->lpAnsiName, pcModuleName, l);
/* terminate the enumeration */
return STATUS_NO_MORE_FILES;
}
/* continue searching */
else
return STATUS_SUCCESS;
}
/* common internal implementation */
DWORD FASTCALL internalGetDeviceDriverName(
BOOLEAN bUnicode,
BOOLEAN bFullName,
LPVOID ImageBase,
LPVOID lpName,
DWORD nSize
)
{
register NTSTATUS nErrCode;
GET_DEVICE_DRIVER_NAME_CONTEXT gddncContext =
{
ImageBase,
{ bFullName, bUnicode },
nSize,
{ lpName }
};
/* empty buffer */
if(lpName == NULL || nSize == 0)
return 0;
/* invalid image base */
if(ImageBase == NULL)
{
SetLastError(ERROR_INVALID_HANDLE);
return 0;
}
/* start the enumeration */
nErrCode = PsaEnumerateSystemModules
(
&GetDeviceDriverNameCallback,
&gddncContext
);
if(nErrCode == STATUS_NO_MORE_FILES)
/* module was found, return string size */
return gddncContext.nSize;
else
{
if(NT_SUCCESS(nErrCode))
/* module was not found */
SetLastError(ERROR_INVALID_HANDLE);
else
/* an error occurred */
SetLastError(RtlNtStatusToDosError(nErrCode));
/* failure */
return 0;
}
}
/* exported interfaces */
/*
NOTES:
- nSize is not, as stated by Microsoft's documentation, the byte size, but the
count of characters in the buffer
- the return value is the count of characters copied into the buffer
- the functions don't attempt to null-terminate the string
*/
DWORD STDCALL GetDeviceDriverBaseNameA(
LPVOID ImageBase,
LPSTR lpBaseName,
DWORD nSize
)
{
return internalGetDeviceDriverName(FALSE, FALSE, ImageBase, lpBaseName, nSize);
}
DWORD STDCALL GetDeviceDriverFileNameA(
LPVOID ImageBase,
LPSTR lpFilename,
DWORD nSize
)
{
return internalGetDeviceDriverName(FALSE, TRUE, ImageBase, lpFilename, nSize);
}
DWORD STDCALL GetDeviceDriverBaseNameW(
LPVOID ImageBase,
LPWSTR lpBaseName,
DWORD nSize
)
{
return internalGetDeviceDriverName(TRUE, FALSE, ImageBase, lpBaseName, nSize);
}
DWORD STDCALL GetDeviceDriverFileNameW(
LPVOID ImageBase,
LPWSTR lpFilename,
DWORD nSize
)
{
return internalGetDeviceDriverName(TRUE, TRUE, ImageBase, lpFilename, nSize);
}
/* GetMappedFileName */
/* common internal implementation */
DWORD FASTCALL internalGetMappedFileName(
BOOLEAN bUnicode,
HANDLE hProcess,
LPVOID lpv,
LPVOID lpName,
DWORD nSize
)
{
register NTSTATUS nErrCode;
register ULONG nBufSize;
PMEMORY_SECTION_NAME pmsnName;
/* empty buffer */
if(nSize == 0 || (LPSTR)lpName == NULL)
return 0;
if(nSize > (0xFFFF / sizeof(WCHAR)))
/* if the user buffer contains more characters than would fit in an
UNICODE_STRING, limit the buffer size. RATIONALE: we don't limit buffer
size elsewhere because here superfluous buffer size will mean a larger
temporary buffer */
nBufSize = 0xFFFF / sizeof(WCHAR);
else
nBufSize = nSize * sizeof(WCHAR);
/* allocate the memory */
pmsnName = malloc(nBufSize + offsetof(MEMORY_SECTION_NAME, NameBuffer));
if(pmsnName == NULL)
{
/* failure */
SetLastError(ERROR_OUTOFMEMORY);
return 0;
}
/* initialize the destination buffer */
pmsnName->SectionFileName.Length = 0;
pmsnName->SectionFileName.Length = nBufSize;
#if 0
__try
{
#endif
/* query the name */
nErrCode = NtQueryVirtualMemory
(
hProcess,
lpv,
MemorySectionName,
pmsnName,
nBufSize,
NULL
);
if(!NT_SUCCESS(nErrCode))
{
/* failure */
SetLastError(RtlNtStatusToDosError(nErrCode));
#if 0
#else
/* free the buffer */
free(pmsnName);
#endif
return 0;
}
/* copy the name */
if(bUnicode)
{
/* destination is an Unicode string: direct copy */
memcpy
(
(LPWSTR)lpName,
pmsnName->NameBuffer,
pmsnName->SectionFileName.Length
);
#if 0
#else
/* free the buffer */
free(pmsnName);
#endif
if(pmsnName->SectionFileName.Length < nSize)
{
/* null-terminate the string */
((LPWSTR)lpName)[pmsnName->SectionFileName.Length] = 0;
return pmsnName->SectionFileName.Length + 1;
}
return pmsnName->SectionFileName.Length;
}
else
{
ANSI_STRING strAnsi = {0, nSize, (LPSTR)lpName};
if(AreFileApisANSI())
/* destination is an ANSI string: convert and copy */
RtlUnicodeStringToAnsiString(&strAnsi, &pmsnName->SectionFileName, FALSE);
else
/* destination is an OEM string: convert and copy */
RtlUnicodeStringToOemString(&strAnsi, &pmsnName->SectionFileName, FALSE);
#if 0
#else
/* free the buffer */
free(pmsnName);
#endif
if(strAnsi.Length < nSize)
{
/* null-terminate the string */
((LPSTR)lpName)[strAnsi.Length] = 0;
return strAnsi.Length + 1;
}
return strAnsi.Length;
}
#if 0
}
__finally
{
free(pmsnName);
}
#endif
}
/* exported interfaces */
DWORD STDCALL GetMappedFileNameA(
HANDLE hProcess,
LPVOID lpv,
LPSTR lpFilename,
DWORD nSize
)
{
return internalGetMappedFileName(FALSE, hProcess, lpv, lpFilename, nSize);
}
DWORD STDCALL GetMappedFileNameW(
HANDLE hProcess,
LPVOID lpv,
LPWSTR lpFilename,
DWORD nSize
)
{
return internalGetMappedFileName(TRUE, hProcess, lpv, lpFilename, nSize);
}
/* GetModuleInformation */
/* common callback context */
typedef struct _GET_MODULE_INFORMATION_FLAGS
{
ULONG bWantName:sizeof(ULONG) * 8 / 4;
ULONG bUnicode:sizeof(ULONG) * 8 / 4;
ULONG bFullName:sizeof(ULONG) * 8 / 4;
} GET_MODULE_INFORMATION_FLAGS, *PGET_MODULE_INFORMATION_FLAGS;
typedef struct _GET_MODULE_INFORMATION_CONTEXT
{
HMODULE hModule;
GET_MODULE_INFORMATION_FLAGS Flags;
DWORD nBufSize;
union
{
LPWSTR lpUnicodeName;
LPSTR lpAnsiName;
LPMODULEINFO lpmodinfo;
LPVOID lpBuffer;
};
} GET_MODULE_INFORMATION_CONTEXT, *PGET_MODULE_INFORMATION_CONTEXT;
/* common callback */
NTSTATUS STDCALL GetModuleInformationCallback
(
IN HANDLE ProcessHandle,
IN PLDR_MODULE CurrentModule,
IN OUT PVOID CallbackContext
)
{
register PGET_MODULE_INFORMATION_CONTEXT pgmicContext =
(PGET_MODULE_INFORMATION_CONTEXT)CallbackContext;
/* found the module we were looking for */
if(CurrentModule->BaseAddress == pgmicContext->hModule)
{
/* we want the module name */
if(pgmicContext->Flags.bWantName)
{
register NTSTATUS nErrCode;
register PUNICODE_STRING pwstrSource;
register ULONG l;
if(pgmicContext->Flags.bFullName)
/* full name */
pwstrSource = &(CurrentModule->FullDllName);
else
/* base name only */
pwstrSource = &(CurrentModule->BaseDllName);
/* paranoia */
pwstrSource->Length -= pwstrSource->Length % sizeof(WCHAR);
/* l is the byte size of the user buffer */
l = pgmicContext->nBufSize * sizeof(WCHAR);
/* if the user buffer has room for the string and a null terminator */
if(l >= (pwstrSource->Length + sizeof(WCHAR)))
{
/* limit the buffer size */
l = pwstrSource->Length;
/* null-terminate the string */
if(pgmicContext->Flags.bUnicode)
pgmicContext->lpUnicodeName[l / sizeof(WCHAR)] = 0;
else
pgmicContext->lpAnsiName[l / sizeof(WCHAR)] = 0;
}
if(pgmicContext->Flags.bUnicode)
{
/* Unicode: direct copy */
/* NOTE: I've chosen not to check for ProcessHandle == NtCurrentProcess(),
this function is complicated enough as it is */
nErrCode = NtReadVirtualMemory
(
ProcessHandle,
pwstrSource->Buffer,
pgmicContext->lpUnicodeName,
l,
NULL
);
if(NT_SUCCESS(nErrCode))
pgmicContext->nBufSize = l / sizeof(WCHAR);
else
{
pgmicContext->nBufSize = 0;
return nErrCode;
}
}
else
{
/* ANSI/OEM: convert and copy */
register LPWSTR pwcUnicodeBuf;
ANSI_STRING strAnsi = {0, pgmicContext->nBufSize, pgmicContext->lpAnsiName};
UNICODE_STRING wstrUnicodeBuf;
/* allocate the local buffer */
pwcUnicodeBuf = malloc(pwstrSource->Length);
#if 0
__try
{
#endif
if(pwcUnicodeBuf == NULL)
/* failure */
#if 0
return STATUS_NO_MEMORY;
#else
{
nErrCode = STATUS_NO_MEMORY;
goto exitWithStatus;
}
#endif
/* copy the string in the local buffer */
nErrCode = NtReadVirtualMemory
(
ProcessHandle,
pwstrSource->Buffer,
pwcUnicodeBuf,
l,
NULL
);
if(!NT_SUCCESS(nErrCode))
/* failure */
#if 0
return nErrCode;
#else
goto exitWithStatus;
#endif
/* initialize Unicode string buffer */
wstrUnicodeBuf.Length = wstrUnicodeBuf.MaximumLength = l;
wstrUnicodeBuf.Buffer = pwcUnicodeBuf;
/* convert and copy */
if(AreFileApisANSI())
RtlUnicodeStringToAnsiString(&strAnsi, &wstrUnicodeBuf, FALSE);
else
RtlUnicodeStringToOemString(&strAnsi, &wstrUnicodeBuf, FALSE);
/* return the string size */
pgmicContext->nBufSize = strAnsi.Length;
#if 0
}
__finally
{
/* free the buffer */
free(pwcUnicodeBuf);
}
#else
/* success */
nErrCode = STATUS_NO_MORE_FILES;
exitWithStatus:
/* free the buffer */
free(pwcUnicodeBuf);
return nErrCode;
#endif
}
}
/* we want other module information */
else
{
register ULONG nSize = pgmicContext->nBufSize;
/* base address */
if(nSize >= sizeof(CurrentModule->BaseAddress))
{
pgmicContext->lpmodinfo->lpBaseOfDll = CurrentModule->BaseAddress;
nSize -= sizeof(CurrentModule->BaseAddress);
}
/* image size */
if(nSize >= sizeof(CurrentModule->SizeOfImage))
{
pgmicContext->lpmodinfo->SizeOfImage = CurrentModule->SizeOfImage;
nSize -= sizeof(CurrentModule->SizeOfImage);
}
/* entry point */
if(nSize >= sizeof(CurrentModule->EntryPoint))
/* ??? FIXME? is "EntryPoint" just the offset, or the real address? */
pgmicContext->lpmodinfo->EntryPoint = (PVOID)CurrentModule->EntryPoint;
pgmicContext->nBufSize = TRUE;
}
return STATUS_NO_MORE_FILES;
}
return STATUS_SUCCESS;
}
/* common internal implementation */
DWORD FASTCALL internalGetModuleInformation(
HANDLE hProcess,
HMODULE hModule,
GET_MODULE_INFORMATION_FLAGS Flags,
LPVOID lpBuffer,
DWORD nBufSize
)
{
register NTSTATUS nErrCode;
GET_MODULE_INFORMATION_CONTEXT gmicContext =
{
hModule,
Flags,
nBufSize,
{lpBuffer}
};
nErrCode = PsaEnumerateProcessModules
(
hProcess,
&GetModuleInformationCallback,
&gmicContext
);
if(nErrCode == STATUS_NO_MORE_FILES)
return gmicContext.nBufSize;
else
{
if(NT_SUCCESS(nErrCode))
SetLastError(ERROR_INVALID_HANDLE);
else
SetLastError(RtlNtStatusToDosError(nErrCode));
return 0;
}
}
/* exported interfaces */
DWORD STDCALL GetModuleBaseNameA(
HANDLE hProcess, // handle to process
HMODULE hModule, // handle to module
LPSTR lpBaseName, // base name buffer
DWORD nSize // maximum characters to retrieve
)
{
register GET_MODULE_INFORMATION_FLAGS Flags = {TRUE, FALSE, FALSE};
return internalGetModuleInformation
(
hProcess,
hModule,
Flags,
lpBaseName,
nSize
);
}
DWORD STDCALL GetModuleBaseNameW(
HANDLE hProcess, // handle to process
HMODULE hModule, // handle to module
LPWSTR lpBaseName, // base name buffer
DWORD nSize // maximum characters to retrieve
)
{
register GET_MODULE_INFORMATION_FLAGS Flags = {TRUE, TRUE, FALSE};
return internalGetModuleInformation
(
hProcess,
hModule,
Flags,
lpBaseName,
nSize
);
}
DWORD STDCALL GetModuleFileNameExA(
HANDLE hProcess, // handle to process
HMODULE hModule, // handle to module
LPSTR lpFilename, // path buffer
DWORD nSize // maximum characters to retrieve
)
{
register GET_MODULE_INFORMATION_FLAGS Flags = {TRUE, FALSE, TRUE};
return internalGetModuleInformation
(
hProcess,
hModule,
Flags,
lpFilename,
nSize
);
}
DWORD STDCALL GetModuleFileNameExW(
HANDLE hProcess, // handle to process
HMODULE hModule, // handle to module
LPWSTR lpFilename, // path buffer
DWORD nSize // maximum characters to retrieve
)
{
register GET_MODULE_INFORMATION_FLAGS Flags = {TRUE, TRUE, TRUE};
return internalGetModuleInformation
(
hProcess,
hModule,
Flags,
lpFilename,
nSize
);
}
BOOL STDCALL GetModuleInformation(
HANDLE hProcess, // handle to process
HMODULE hModule, // handle to module
LPMODULEINFO lpmodinfo, // information buffer
DWORD cb // size of buffer
)
{
register GET_MODULE_INFORMATION_FLAGS Flags = {FALSE, FALSE, FALSE};
return (BOOL)internalGetModuleInformation
(
hProcess,
hModule,
Flags,
lpmodinfo,
cb
);
}
/* EOF */

View file

@ -1,24 +1,24 @@
; $Id: psapi.def,v 1.1 2002/06/18 22:11:55 hyperion Exp $
; $Id: psapi.def,v 1.2 2002/08/31 15:36:56 hyperion Exp $
;
LIBRARY PSAPI.DLL
EXPORTS
EmptyWorkingSet@4
EnumDeviceDrivers@12
EnumProcessModules@16
EnumProcesses@12
GetDeviceDriverBaseNameA@12
GetDeviceDriverBaseNameW@12
GetDeviceDriverFileNameA@12
GetDeviceDriverFileNameW@12
GetMappedFileNameA@16
GetMappedFileNameW@16
GetModuleBaseNameA@16
GetModuleBaseNameW@16
GetModuleFileNameExA@16
GetModuleFileNameExW@16
GetModuleInformation@16
GetProcessMemoryInfo@12
GetWsChanges@12
InitializeProcessForWsWatch@4
QueryWorkingSet@12
EmptyWorkingSet @10
EnumDeviceDrivers @2
EnumProcessModules @3
EnumProcesses @4
GetDeviceDriverBaseNameA @5
GetDeviceDriverBaseNameW @6
GetDeviceDriverFileNameA @7
GetDeviceDriverFileNameW @8
GetMappedFileNameA @9
GetMappedFileNameW @1
GetModuleBaseNameA @11
GetModuleBaseNameW @12
GetModuleFileNameExA @13
GetModuleFileNameExW @14
GetModuleInformation @15
GetProcessMemoryInfo @16
GetWsChanges @17
InitializeProcessForWsWatch @18
QueryWorkingSet @19

View file

@ -1,24 +1,24 @@
; $Id: psapi.edf,v 1.1 2002/06/18 22:16:53 hyperion Exp $
; $Id: psapi.edf,v 1.2 2002/08/31 15:36:56 hyperion Exp $
;
LIBRARY PSAPI.DLL
EXPORTS
EmptyWorkingSet=EmptyWorkingSet@4
EnumDeviceDrivers=EnumDeviceDrivers@12
EnumProcessModules=EnumProcessModules@16
EnumProcesses=EnumProcesses@12
GetDeviceDriverBaseNameA=GetDeviceDriverBaseNameA@12
GetDeviceDriverBaseNameW=GetDeviceDriverBaseNameW@12
GetDeviceDriverFileNameA=GetDeviceDriverFileNameA@12
GetDeviceDriverFileNameW=GetDeviceDriverFileNameW@12
GetMappedFileNameA=GetMappedFileNameA@16
GetMappedFileNameW=GetMappedFileNameW@16
GetModuleBaseNameA=GetModuleBaseNameA@16
GetModuleBaseNameW=GetModuleBaseNameW@16
GetModuleFileNameExA=GetModuleFileNameExA@16
GetModuleFileNameExW=GetModuleFileNameExW@16
GetModuleInformation=GetModuleInformation@16
GetProcessMemoryInfo=GetProcessMemoryInfo@12
GetWsChanges=GetWsChanges@12
InitializeProcessForWsWatch=InitializeProcessForWsWatch@4
QueryWorkingSet=QueryWorkingSet@12
EmptyWorkingSet=EmptyWorkingSet@4 @10
EnumDeviceDrivers=EnumDeviceDrivers@12 @2
EnumProcessModules=EnumProcessModules@16 @3
EnumProcesses=EnumProcesses@12 @4
GetDeviceDriverBaseNameA=GetDeviceDriverBaseNameA@12 @5
GetDeviceDriverBaseNameW=GetDeviceDriverBaseNameW@12 @6
GetDeviceDriverFileNameA=GetDeviceDriverFileNameA@12 @7
GetDeviceDriverFileNameW=GetDeviceDriverFileNameW@12 @8
GetMappedFileNameA=GetMappedFileNameA@16 @9
GetMappedFileNameW=GetMappedFileNameW@16 @1
GetModuleBaseNameA=GetModuleBaseNameA@16 @11
GetModuleBaseNameW=GetModuleBaseNameW@16 @12
GetModuleFileNameExA=GetModuleFileNameExA@16 @13
GetModuleFileNameExW=GetModuleFileNameExW@16 @14
GetModuleInformation=GetModuleInformation@16 @15
GetProcessMemoryInfo=GetProcessMemoryInfo@12 @16
GetWsChanges=GetWsChanges@12 @17
InitializeProcessForWsWatch=InitializeProcessForWsWatch@4 @18
QueryWorkingSet=QueryWorkingSet@12 @19