📄 psapi.c
字号:
/* $Id: psapi.c 21880 2006-05-10 17:47:44Z ion $
*/
/*
* COPYRIGHT: See COPYING in the top level directory
* LICENSE: See LGPL.txt in the top level directory
* PROJECT: ReactOS system libraries
* FILE: reactos/lib/psapi/misc/win32.c
* PURPOSE: Win32 interfaces for PSAPI
* PROGRAMMER: KJK::Hyperion <noog@libero.it>
* Thomas Weidenmueller <w3seek@reactos.com>
* UPDATE HISTORY:
* 10/06/2002: Created
*/
#include "precomp.h"
#define NDEBUG
#include <debug.h>
BOOLEAN
WINAPI
DllMain(HINSTANCE hDllHandle,
DWORD nReason,
LPVOID Reserved)
{
switch(nReason)
{
case DLL_PROCESS_ATTACH:
DisableThreadLibraryCalls(hDllHandle);
break;
}
return TRUE;
}
/* INTERNAL *******************************************************************/
typedef struct _ENUM_DEVICE_DRIVERS_CONTEXT
{
LPVOID *lpImageBase;
DWORD nCount;
} ENUM_DEVICE_DRIVERS_CONTEXT, *PENUM_DEVICE_DRIVERS_CONTEXT;
NTSTATUS STDCALL
EnumDeviceDriversCallback(IN PRTL_PROCESS_MODULE_INFORMATION CurrentModule,
IN OUT PVOID CallbackContext)
{
PENUM_DEVICE_DRIVERS_CONTEXT Context = (PENUM_DEVICE_DRIVERS_CONTEXT)CallbackContext;
/* no more buffer space */
if(Context->nCount == 0)
{
return STATUS_INFO_LENGTH_MISMATCH;
}
/* return current module */
*Context->lpImageBase = CurrentModule->ImageBase;
/* go to next array slot */
Context->lpImageBase++;
Context->nCount--;
return STATUS_SUCCESS;
}
typedef struct _ENUM_PROCESSES_CONTEXT
{
DWORD *lpidProcess;
DWORD nCount;
} ENUM_PROCESSES_CONTEXT, *PENUM_PROCESSES_CONTEXT;
NTSTATUS STDCALL
EnumProcessesCallback(IN PSYSTEM_PROCESS_INFORMATION CurrentProcess,
IN OUT PVOID CallbackContext)
{
PENUM_PROCESSES_CONTEXT Context = (PENUM_PROCESSES_CONTEXT)CallbackContext;
/* no more buffer space */
if(Context->nCount == 0)
{
return STATUS_INFO_LENGTH_MISMATCH;
}
/* return current process */
*Context->lpidProcess = (DWORD)CurrentProcess->UniqueProcessId;
/* go to next array slot */
Context->lpidProcess++;
Context->nCount--;
return STATUS_SUCCESS;
}
typedef struct _ENUM_PROCESS_MODULES_CONTEXT
{
HMODULE *lphModule;
DWORD nCount;
} ENUM_PROCESS_MODULES_CONTEXT, *PENUM_PROCESS_MODULES_CONTEXT;
NTSTATUS STDCALL
EnumProcessModulesCallback(IN HANDLE ProcessHandle,
IN PLDR_DATA_TABLE_ENTRY CurrentModule,
IN OUT PVOID CallbackContext)
{
PENUM_PROCESS_MODULES_CONTEXT Context = (PENUM_PROCESS_MODULES_CONTEXT)CallbackContext;
/* no more buffer space */
if(Context->nCount == 0)
{
return STATUS_INFO_LENGTH_MISMATCH;
}
/* return current process */
*Context->lphModule = CurrentModule->DllBase;
/* go to next array slot */
Context->lphModule++;
Context->nCount--;
return STATUS_SUCCESS;
}
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;
NTSTATUS STDCALL
GetDeviceDriverNameCallback(IN PRTL_PROCESS_MODULE_INFORMATION CurrentModule,
IN OUT PVOID CallbackContext)
{
PGET_DEVICE_DRIVER_NAME_CONTEXT Context = (PGET_DEVICE_DRIVER_NAME_CONTEXT)CallbackContext;
/* module found */
if(Context->ImageBase == CurrentModule->ImageBase)
{
PCHAR pcModuleName;
ULONG l;
/* get the full name or just the filename part */
if(Context->bFullName)
pcModuleName = &CurrentModule->FullPathName[0];
else
pcModuleName = &CurrentModule->FullPathName[CurrentModule->OffsetToFileName];
/* get the length of the name */
l = strlen(pcModuleName);
if(Context->nSize <= l)
{
/* use the user buffer's length */
l = Context->nSize;
}
else
{
/* enough space for the null terminator */
Context->nSize = ++l;
}
/* copy the string */
if(Context->bUnicode)
{
ANSI_STRING AnsiString;
UNICODE_STRING UnicodeString;
UnicodeString.Length = 0;
UnicodeString.MaximumLength = l * sizeof(WCHAR);
UnicodeString.Buffer = Context->lpUnicodeName;
RtlInitAnsiString(&AnsiString, pcModuleName);
/* driver names should always be in language-neutral ASCII, so we don't
bother calling AreFileApisANSI() */
RtlAnsiStringToUnicodeString(&UnicodeString, &AnsiString, FALSE);
}
else
{
memcpy(Context->lpAnsiName, pcModuleName, l);
}
/* terminate the enumeration */
return STATUS_NO_MORE_FILES;
}
else
{
/* continue searching */
return STATUS_SUCCESS;
}
}
static DWORD
InternalGetDeviceDriverName(BOOLEAN bUnicode,
BOOLEAN bFullName,
LPVOID ImageBase,
LPVOID lpName,
DWORD nSize)
{
GET_DEVICE_DRIVER_NAME_CONTEXT Context;
NTSTATUS Status;
if(lpName == NULL || nSize == 0)
{
return 0;
}
if(ImageBase == NULL)
{
SetLastError(ERROR_INVALID_HANDLE);
return 0;
}
Context.ImageBase = ImageBase;
Context.bFullName = bFullName;
Context.bUnicode = bUnicode;
Context.nSize = nSize;
Context.lpName = lpName;
/* start the enumeration */
Status = PsaEnumerateSystemModules(GetDeviceDriverNameCallback, &Context);
if(Status == STATUS_NO_MORE_FILES)
{
/* module was found, return string size */
return Context.nSize;
}
else if(NT_SUCCESS(Status))
{
/* module was not found */
SetLastError(ERROR_INVALID_HANDLE);
}
else
{
/* an error occurred */
SetLastErrorByStatus(Status);
}
return 0;
}
static DWORD
InternalGetMappedFileName(BOOLEAN bUnicode,
HANDLE hProcess,
LPVOID lpv,
LPVOID lpName,
DWORD nSize)
{
PMEMORY_SECTION_NAME pmsnName;
ULONG nBufSize;
NTSTATUS Status;
if(nSize == 0 || 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 = PsaiMalloc(nBufSize + sizeof(MEMORY_SECTION_NAME));
if(pmsnName == NULL)
{
SetLastError(ERROR_OUTOFMEMORY);
return 0;
}
/* initialize the destination buffer */
pmsnName->SectionFileName.Length = 0;
pmsnName->SectionFileName.Length = nBufSize;
#if 0
__try
{
#endif
/* query the name */
Status = NtQueryVirtualMemory(hProcess,
lpv,
MemorySectionName,
pmsnName,
nBufSize,
NULL);
if(!NT_SUCCESS(Status))
{
PsaiFree(pmsnName);
SetLastErrorByStatus(Status);
return 0;
}
if(bUnicode)
{
/* destination is an Unicode string: direct copy */
memcpy((LPWSTR)lpName, pmsnName + 1, pmsnName->SectionFileName.Length);
PsaiFree(pmsnName);
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 AnsiString;
AnsiString.Length = 0;
AnsiString.MaximumLength = nSize;
AnsiString.Buffer = (LPSTR)lpName;
if(AreFileApisANSI())
RtlUnicodeStringToAnsiString(&AnsiString, &pmsnName->SectionFileName, FALSE);
else
RtlUnicodeStringToOemString(&AnsiString, &pmsnName->SectionFileName, FALSE);
PsaiFree(pmsnName);
if(AnsiString.Length < nSize)
{
/* null-terminate the string */
((LPSTR)lpName)[AnsiString.Length] = 0;
return AnsiString.Length + 1;
}
return AnsiString.Length;
}
#if 0
}
__finally
{
PsaiFree(pmsnName);
}
#endif
}
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;
NTSTATUS STDCALL
GetModuleInformationCallback(IN HANDLE ProcessHandle,
IN PLDR_DATA_TABLE_ENTRY CurrentModule,
IN OUT PVOID CallbackContext)
{
PGET_MODULE_INFORMATION_CONTEXT Context = (PGET_MODULE_INFORMATION_CONTEXT)CallbackContext;
/* found the module we were looking for */
if(CurrentModule->DllBase == Context->hModule)
{
/* we want the module name */
if(Context->Flags.bWantName)
{
PUNICODE_STRING SourceString;
ULONG l;
NTSTATUS Status;
if(Context->Flags.bFullName)
SourceString = &(CurrentModule->FullDllName);
else
SourceString = &(CurrentModule->BaseDllName);
SourceString->Length -= SourceString->Length % sizeof(WCHAR);
/* l is the byte size of the user buffer */
l = Context->nBufSize * sizeof(WCHAR);
/* if the user buffer has room for the string and a null terminator */
if(l >= (SourceString->Length + sizeof(WCHAR)))
{
/* limit the buffer size */
l = SourceString->Length;
/* null-terminate the string */
if(Context->Flags.bUnicode)
Context->lpUnicodeName[l / sizeof(WCHAR)] = 0;
else
Context->lpAnsiName[l / sizeof(WCHAR)] = 0;
}
if(Context->Flags.bUnicode)
{
/* Unicode: direct copy */
/* NOTE: I've chosen not to check for ProcessHandle == NtCurrentProcess(),
this function is complicated enough as it is */
Status = NtReadVirtualMemory(ProcessHandle,
SourceString->Buffer,
Context->lpUnicodeName,
l,
NULL);
if(!NT_SUCCESS(Status))
{
Context->nBufSize = 0;
return Status;
}
Context->nBufSize = l / sizeof(WCHAR);
}
else
{
/* ANSI/OEM: convert and copy */
LPWSTR pwcUnicodeBuf;
ANSI_STRING AnsiString;
UNICODE_STRING UnicodeString;
AnsiString.Length = 0;
AnsiString.MaximumLength = Context->nBufSize;
AnsiString.Buffer = Context->lpAnsiName;
/* allocate the local buffer */
pwcUnicodeBuf = PsaiMalloc(SourceString->Length);
#if 0
__try
{
#endif
if(pwcUnicodeBuf == NULL)
{
Status = STATUS_NO_MEMORY;
goto exitWithStatus;
}
/* copy the string in the local buffer */
Status = NtReadVirtualMemory(ProcessHandle,
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -