reactos/dll/win32/kernel32/client/toolhelp.c

1311 lines
34 KiB
C

/*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS system libraries
* FILE: dll/win32/kernel32/client/toolhelp.c
* PURPOSE: Toolhelp functions
* PROGRAMMER: Thomas Weidenmueller <w3seek@reactos.com>
* Robert Dickenson (robd@mok.lvcm.com)
*
* NOTES: Do NOT use the heap functions in here because they
* adulterate the heap statistics!
*
* UPDATE HISTORY:
* 10/30/2004 Implemented some parts (w3)
* Inspired by the book "Windows NT Native API"
* Created 05 January 2003 (robd)
*/
#include <k32.h>
#define NDEBUG
#include <debug.h>
/* INTERNAL DEFINITIONS *******************************************************/
typedef struct _RTLP_HEAP_ENTRY
{
ULONG Size;
USHORT Flags;
USHORT Unknown1; /* FIXME */
ULONG Unknown2; /* FIXME */
PVOID Address;
} RTLP_HEAP_ENTRY, *PRTLP_HEAP_ENTRY;
#define CHECK_PARAM_SIZE(ptr, siz) \
if((ptr) == NULL || (ptr)->dwSize != (siz)) \
{ \
SetLastError(ERROR_INVALID_PARAMETER); \
return FALSE; \
}
/*
* Tests in win showed that the dwSize field can be greater than the actual size
* of the structure for the ansi functions. I found this out by accidently
* forgetting to set the dwSize field in a test application and it just didn't
* work in ros but in win.
*/
#define CHECK_PARAM_SIZEA(ptr, siz) \
if((ptr) == NULL || (ptr)->dwSize < (siz)) \
{ \
SetLastError(ERROR_INVALID_PARAMETER); \
return FALSE; \
}
#define OffsetToPtr(Snapshot, Offset) \
((ULONG_PTR)((Snapshot) + 1) + (ULONG_PTR)(Offset))
typedef struct _TH32SNAPSHOT
{
/* Heap list */
ULONG HeapListCount;
ULONG HeapListIndex;
ULONG_PTR HeapListOffset;
/* Module list */
ULONG ModuleListCount;
ULONG ModuleListIndex;
ULONG_PTR ModuleListOffset;
/* Process list */
ULONG ProcessListCount;
ULONG ProcessListIndex;
ULONG_PTR ProcessListOffset;
/* Thread list */
ULONG ThreadListCount;
ULONG ThreadListIndex;
ULONG_PTR ThreadListOffset;
} TH32SNAPSHOT, *PTH32SNAPSHOT;
/* INTERNAL FUNCTIONS *********************************************************/
static VOID
TH32FreeAllocatedResources(PRTL_DEBUG_INFORMATION HeapDebug,
PRTL_DEBUG_INFORMATION ModuleDebug,
PVOID ProcThrdInfo,
SIZE_T ProcThrdInfoSize)
{
if(HeapDebug != NULL)
{
RtlDestroyQueryDebugBuffer(HeapDebug);
}
if(ModuleDebug != NULL)
{
RtlDestroyQueryDebugBuffer(ModuleDebug);
}
if(ProcThrdInfo != NULL)
{
NtFreeVirtualMemory(NtCurrentProcess(),
&ProcThrdInfo,
&ProcThrdInfoSize,
MEM_RELEASE);
}
}
static NTSTATUS
TH32CreateSnapshot(DWORD dwFlags,
DWORD th32ProcessID,
PRTL_DEBUG_INFORMATION *HeapDebug,
PRTL_DEBUG_INFORMATION *ModuleDebug,
PVOID *ProcThrdInfo,
SIZE_T *ProcThrdInfoSize)
{
NTSTATUS Status = STATUS_SUCCESS;
*HeapDebug = NULL;
*ModuleDebug = NULL;
*ProcThrdInfo = NULL;
*ProcThrdInfoSize = 0;
/*
* Allocate the debug information for a heap snapshot
*/
if(dwFlags & TH32CS_SNAPHEAPLIST)
{
*HeapDebug = RtlCreateQueryDebugBuffer(0, FALSE);
if(*HeapDebug != NULL)
{
Status = RtlQueryProcessDebugInformation(th32ProcessID,
RTL_DEBUG_QUERY_HEAPS,
*HeapDebug);
}
else
Status = STATUS_UNSUCCESSFUL;
}
/*
* Allocate the debug information for a module snapshot
*/
if(dwFlags & TH32CS_SNAPMODULE &&
NT_SUCCESS(Status))
{
*ModuleDebug = RtlCreateQueryDebugBuffer(0, FALSE);
if(*ModuleDebug != NULL)
{
Status = RtlQueryProcessDebugInformation(th32ProcessID,
RTL_DEBUG_QUERY_MODULES,
*ModuleDebug);
}
else
Status = STATUS_UNSUCCESSFUL;
}
/*
* Allocate enough memory for the system's process list
*/
if(dwFlags & (TH32CS_SNAPPROCESS | TH32CS_SNAPTHREAD) &&
NT_SUCCESS(Status))
{
for(;;)
{
(*ProcThrdInfoSize) += 0x10000;
Status = NtAllocateVirtualMemory(NtCurrentProcess(),
ProcThrdInfo,
0,
ProcThrdInfoSize,
MEM_COMMIT,
PAGE_READWRITE);
if(!NT_SUCCESS(Status))
{
break;
}
Status = NtQuerySystemInformation(SystemProcessInformation,
*ProcThrdInfo,
*ProcThrdInfoSize,
NULL);
if(Status == STATUS_INFO_LENGTH_MISMATCH)
{
NtFreeVirtualMemory(NtCurrentProcess(),
ProcThrdInfo,
ProcThrdInfoSize,
MEM_RELEASE);
*ProcThrdInfo = NULL;
}
else
{
break;
}
}
}
/*
* Free resources in case of failure!
*/
if(!NT_SUCCESS(Status))
{
TH32FreeAllocatedResources(*HeapDebug,
*ModuleDebug,
*ProcThrdInfo,
*ProcThrdInfoSize);
}
return Status;
}
static NTSTATUS
TH32CreateSnapshotSectionInitialize(DWORD dwFlags,
DWORD th32ProcessID,
PRTL_DEBUG_INFORMATION HeapDebug,
PRTL_DEBUG_INFORMATION ModuleDebug,
PVOID ProcThrdInfo,
HANDLE *SectionHandle)
{
PSYSTEM_PROCESS_INFORMATION ProcessInfo;
LPHEAPLIST32 HeapListEntry;
LPMODULEENTRY32W ModuleListEntry;
LPPROCESSENTRY32W ProcessListEntry;
LPTHREADENTRY32 ThreadListEntry;
OBJECT_ATTRIBUTES ObjectAttributes;
LARGE_INTEGER SSize, SOffset;
HANDLE hSection;
PTH32SNAPSHOT Snapshot;
ULONG_PTR DataOffset;
SIZE_T ViewSize;
ULONG i, nProcesses = 0, nThreads = 0, nHeaps = 0, nModules = 0;
ULONG RequiredSnapshotSize = sizeof(TH32SNAPSHOT);
PRTL_PROCESS_HEAPS hi = NULL;
PRTL_PROCESS_MODULES mi = NULL;
NTSTATUS Status = STATUS_SUCCESS;
/*
* Determine the required size for the heap snapshot
*/
if(dwFlags & TH32CS_SNAPHEAPLIST)
{
hi = (PRTL_PROCESS_HEAPS)HeapDebug->Heaps;
nHeaps = hi->NumberOfHeaps;
RequiredSnapshotSize += nHeaps * sizeof(HEAPLIST32);
}
/*
* Determine the required size for the module snapshot
*/
if(dwFlags & TH32CS_SNAPMODULE)
{
mi = (PRTL_PROCESS_MODULES)ModuleDebug->Modules;
nModules = mi->NumberOfModules;
RequiredSnapshotSize += nModules * sizeof(MODULEENTRY32W);
}
/*
* Determine the required size for the processes and threads snapshot
*/
if(dwFlags & (TH32CS_SNAPPROCESS | TH32CS_SNAPTHREAD))
{
ULONG ProcOffset = 0;
ProcessInfo = (PSYSTEM_PROCESS_INFORMATION)ProcThrdInfo;
do
{
ProcessInfo = (PSYSTEM_PROCESS_INFORMATION)((ULONG_PTR)ProcessInfo + ProcOffset);
nProcesses++;
nThreads += ProcessInfo->NumberOfThreads;
ProcOffset = ProcessInfo->NextEntryOffset;
} while(ProcOffset != 0);
if(dwFlags & TH32CS_SNAPPROCESS)
{
RequiredSnapshotSize += nProcesses * sizeof(PROCESSENTRY32W);
}
if(dwFlags & TH32CS_SNAPTHREAD)
{
RequiredSnapshotSize += nThreads * sizeof(THREADENTRY32);
}
}
/*
* Create and map the section
*/
SSize.QuadPart = RequiredSnapshotSize;
InitializeObjectAttributes(&ObjectAttributes,
NULL,
((dwFlags & TH32CS_INHERIT) ? OBJ_INHERIT : 0),
NULL,
NULL);
Status = NtCreateSection(&hSection,
SECTION_ALL_ACCESS,
&ObjectAttributes,
&SSize,
PAGE_READWRITE,
SEC_COMMIT,
NULL);
if(!NT_SUCCESS(Status))
{
return Status;
}
SOffset.QuadPart = 0;
ViewSize = 0;
Snapshot = NULL;
Status = NtMapViewOfSection(hSection,
NtCurrentProcess(),
(PVOID*)&Snapshot,
0,
0,
&SOffset,
&ViewSize,
ViewShare,
0,
PAGE_READWRITE);
if(!NT_SUCCESS(Status))
{
NtClose(hSection);
return Status;
}
RtlZeroMemory(Snapshot, sizeof(TH32SNAPSHOT));
DataOffset = 0;
/*
* Initialize the section data and fill it with all the data we collected
*/
/* initialize the heap list */
if(dwFlags & TH32CS_SNAPHEAPLIST)
{
Snapshot->HeapListCount = nHeaps;
Snapshot->HeapListOffset = DataOffset;
HeapListEntry = (LPHEAPLIST32)OffsetToPtr(Snapshot, DataOffset);
for(i = 0; i < nHeaps; i++)
{
HeapListEntry->dwSize = sizeof(HEAPLIST32);
HeapListEntry->th32ProcessID = th32ProcessID;
HeapListEntry->th32HeapID = (ULONG_PTR)hi->Heaps[i].BaseAddress;
HeapListEntry->dwFlags = hi->Heaps[i].Flags;
HeapListEntry++;
}
DataOffset += hi->NumberOfHeaps * sizeof(HEAPLIST32);
}
/* initialize the module list */
if(dwFlags & TH32CS_SNAPMODULE)
{
Snapshot->ModuleListCount = nModules;
Snapshot->ModuleListOffset = DataOffset;
ModuleListEntry = (LPMODULEENTRY32W)OffsetToPtr(Snapshot, DataOffset);
for(i = 0; i < nModules; i++)
{
ModuleListEntry->dwSize = sizeof(MODULEENTRY32W);
ModuleListEntry->th32ModuleID = 1; /* no longer used, always set to one! */
ModuleListEntry->th32ProcessID = th32ProcessID;
ModuleListEntry->GlblcntUsage = mi->Modules[i].LoadCount;
ModuleListEntry->ProccntUsage = mi->Modules[i].LoadCount;
ModuleListEntry->modBaseAddr = (BYTE*)mi->Modules[i].ImageBase;
ModuleListEntry->modBaseSize = mi->Modules[i].ImageSize;
ModuleListEntry->hModule = (HMODULE)mi->Modules[i].ImageBase;
MultiByteToWideChar(CP_ACP,
0,
&mi->Modules[i].FullPathName[mi->Modules[i].OffsetToFileName],
-1,
ModuleListEntry->szModule,
sizeof(ModuleListEntry->szModule) / sizeof(ModuleListEntry->szModule[0]));
MultiByteToWideChar(CP_ACP,
0,
mi->Modules[i].FullPathName,
-1,
ModuleListEntry->szExePath,
sizeof(ModuleListEntry->szExePath) / sizeof(ModuleListEntry->szExePath[0]));
ModuleListEntry++;
}
DataOffset += mi->NumberOfModules * sizeof(MODULEENTRY32W);
}
/* initialize the process list */
if(dwFlags & TH32CS_SNAPPROCESS)
{
ULONG ProcOffset = 0;
Snapshot->ProcessListCount = nProcesses;
Snapshot->ProcessListOffset = DataOffset;
ProcessListEntry = (LPPROCESSENTRY32W)OffsetToPtr(Snapshot, DataOffset);
ProcessInfo = (PSYSTEM_PROCESS_INFORMATION)ProcThrdInfo;
do
{
ProcessInfo = (PSYSTEM_PROCESS_INFORMATION)((ULONG_PTR)ProcessInfo + ProcOffset);
ProcessListEntry->dwSize = sizeof(PROCESSENTRY32W);
ProcessListEntry->cntUsage = 0; /* no longer used */
ProcessListEntry->th32ProcessID = (ULONG_PTR)ProcessInfo->UniqueProcessId;
ProcessListEntry->th32DefaultHeapID = 0; /* no longer used */
ProcessListEntry->th32ModuleID = 0; /* no longer used */
ProcessListEntry->cntThreads = ProcessInfo->NumberOfThreads;
ProcessListEntry->th32ParentProcessID = (ULONG_PTR)ProcessInfo->InheritedFromUniqueProcessId;
ProcessListEntry->pcPriClassBase = ProcessInfo->BasePriority;
ProcessListEntry->dwFlags = 0; /* no longer used */
if(ProcessInfo->ImageName.Buffer != NULL)
{
ULONG ExeFileLength = min(ProcessInfo->ImageName.Length,
sizeof(ProcessListEntry->szExeFile) - sizeof(WCHAR));
RtlCopyMemory(ProcessListEntry->szExeFile,
ProcessInfo->ImageName.Buffer,
ExeFileLength);
ProcessListEntry->szExeFile[ExeFileLength / sizeof(WCHAR)] = UNICODE_NULL;
}
else
{
lstrcpyW(ProcessListEntry->szExeFile, L"[System Process]");
}
ProcessListEntry++;
ProcOffset = ProcessInfo->NextEntryOffset;
} while(ProcOffset != 0);
DataOffset += nProcesses * sizeof(PROCESSENTRY32W);
}
/* initialize the thread list */
if(dwFlags & TH32CS_SNAPTHREAD)
{
ULONG ProcOffset = 0;
Snapshot->ThreadListCount = nThreads;
Snapshot->ThreadListOffset = DataOffset;
ThreadListEntry = (LPTHREADENTRY32)OffsetToPtr(Snapshot, DataOffset);
ProcessInfo = (PSYSTEM_PROCESS_INFORMATION)ProcThrdInfo;
do
{
PSYSTEM_THREAD_INFORMATION ThreadInfo;
ULONG n;
ProcessInfo = (PSYSTEM_PROCESS_INFORMATION)((ULONG_PTR)ProcessInfo + ProcOffset);
ThreadInfo = (PSYSTEM_THREAD_INFORMATION)(ProcessInfo + 1);
for(n = 0; n < ProcessInfo->NumberOfThreads; n++)
{
ThreadListEntry->dwSize = sizeof(THREADENTRY32);
ThreadListEntry->cntUsage = 0; /* no longer used */
ThreadListEntry->th32ThreadID = (ULONG_PTR)ThreadInfo->ClientId.UniqueThread;
ThreadListEntry->th32OwnerProcessID = (ULONG_PTR)ThreadInfo->ClientId.UniqueProcess;
ThreadListEntry->tpBasePri = ThreadInfo->BasePriority;
ThreadListEntry->tpDeltaPri = 0; /* no longer used */
ThreadListEntry->dwFlags = 0; /* no longer used */
ThreadInfo++;
ThreadListEntry++;
}
ProcOffset = ProcessInfo->NextEntryOffset;
} while(ProcOffset != 0);
}
/*
* We're done, unmap the view and return the section handle
*/
Status = NtUnmapViewOfSection(NtCurrentProcess(), (PVOID)Snapshot);
if(NT_SUCCESS(Status))
{
*SectionHandle = hSection;
}
else
{
NtClose(hSection);
}
return Status;
}
/* PUBLIC FUNCTIONS ***********************************************************/
/*
* @implemented
*/
BOOL
WINAPI
Heap32First(LPHEAPENTRY32 lphe, DWORD th32ProcessID, DWORD th32HeapID)
{
PRTL_DEBUG_INFORMATION DebugInfo;
PRTL_HEAP_INFORMATION Heap;
PRTLP_HEAP_ENTRY Block, LastBlock;
ULONG i;
NTSTATUS Status;
CHECK_PARAM_SIZE(lphe, sizeof(HEAPENTRY32));
DebugInfo = RtlCreateQueryDebugBuffer(0,
FALSE);
if (DebugInfo == NULL)
{
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
return FALSE;
}
Status = RtlQueryProcessDebugInformation(th32ProcessID,
RTL_DEBUG_QUERY_HEAPS | RTL_DEBUG_QUERY_HEAP_BLOCKS,
DebugInfo);
if (NT_SUCCESS(Status))
{
Status = STATUS_NO_MORE_FILES;
for (i = 0;
i != DebugInfo->Heaps->NumberOfHeaps;
i++)
{
Heap = &DebugInfo->Heaps->Heaps[i];
if ((ULONG_PTR)Heap->BaseAddress == th32HeapID)
{
lphe->hHandle = (HANDLE)Heap->BaseAddress;
lphe->dwAddress = 0;
lphe->dwBlockSize = 0;
lphe->dwFlags = 0;
lphe->dwLockCount = 0;
lphe->dwResvd = 0;
lphe->th32ProcessID = th32ProcessID;
lphe->th32HeapID = (ULONG_PTR)Heap->BaseAddress;
Block = (PRTLP_HEAP_ENTRY)Heap->Entries;
LastBlock = Block + Heap->NumberOfEntries;
while (Block != LastBlock && (Block->Flags & PROCESS_HEAP_UNCOMMITTED_RANGE))
{
lphe->dwResvd++;
lphe->dwAddress = (ULONG_PTR)((ULONG_PTR)Block->Address + Heap->EntryOverhead);
Block++;
}
if (Block != LastBlock && lphe->dwResvd != 0)
{
lphe->dwBlockSize = Block->Size;
if (Block->Flags & 0x2F1) /* FIXME */
lphe->dwFlags = LF32_FIXED;
else if (Block->Flags & 0x20) /* FIXME */
lphe->dwFlags = LF32_MOVEABLE;
else if (Block->Flags & 0x100) /* FIXME */
lphe->dwFlags = LF32_FREE;
Status = STATUS_SUCCESS;
}
break;
}
}
}
RtlDestroyQueryDebugBuffer(DebugInfo);
if (!NT_SUCCESS(Status))
{
BaseSetLastNTError(Status);
return FALSE;
}
return TRUE;
}
/*
* @implemented
*/
BOOL
WINAPI
Heap32Next(LPHEAPENTRY32 lphe)
{
PRTL_DEBUG_INFORMATION DebugInfo;
PRTL_HEAP_INFORMATION Heap;
PRTLP_HEAP_ENTRY Block, LastBlock;
BOOLEAN FoundUncommitted = FALSE;
ULONG i;
NTSTATUS Status;
CHECK_PARAM_SIZE(lphe, sizeof(HEAPENTRY32));
DebugInfo = RtlCreateQueryDebugBuffer(0,
FALSE);
if (DebugInfo == NULL)
{
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
return FALSE;
}
Status = RtlQueryProcessDebugInformation(lphe->th32ProcessID,
RTL_DEBUG_QUERY_HEAPS | RTL_DEBUG_QUERY_HEAP_BLOCKS,
DebugInfo);
if (NT_SUCCESS(Status))
{
Status = STATUS_NO_MORE_FILES;
for (i = 0;
i != DebugInfo->Heaps->NumberOfHeaps;
i++)
{
Heap = &DebugInfo->Heaps->Heaps[i];
if ((ULONG_PTR)Heap->BaseAddress == lphe->th32HeapID)
{
if (++lphe->dwResvd < Heap->NumberOfEntries)
{
lphe->dwFlags = 0;
Block = (PRTLP_HEAP_ENTRY)Heap->Entries + lphe->dwResvd;
LastBlock = (PRTLP_HEAP_ENTRY)Heap->Entries + Heap->NumberOfEntries;
while (Block < LastBlock && (Block->Flags & PROCESS_HEAP_UNCOMMITTED_RANGE))
{
lphe->dwResvd++;
lphe->dwAddress = (ULONG_PTR)((ULONG_PTR)Block->Address + Heap->EntryOverhead);
FoundUncommitted = TRUE;
Block++;
}
if (Block < LastBlock)
{
if (!FoundUncommitted)
lphe->dwAddress += lphe->dwBlockSize;
lphe->dwBlockSize = Block->Size;
if (Block->Flags & 0x2F1) /* FIXME */
lphe->dwFlags = LF32_FIXED;
else if (Block->Flags & 0x20) /* FIXME */
lphe->dwFlags = LF32_MOVEABLE;
else if (Block->Flags & 0x100) /* FIXME */
lphe->dwFlags = LF32_FREE;
Status = STATUS_SUCCESS;
}
}
break;
}
}
}
RtlDestroyQueryDebugBuffer(DebugInfo);
if (!NT_SUCCESS(Status))
{
BaseSetLastNTError(Status);
return FALSE;
}
return TRUE;
}
/*
* @implemented
*/
BOOL
WINAPI
Heap32ListFirst(HANDLE hSnapshot, LPHEAPLIST32 lphl)
{
PTH32SNAPSHOT Snapshot;
LARGE_INTEGER SOffset;
SIZE_T ViewSize;
NTSTATUS Status;
CHECK_PARAM_SIZE(lphl, sizeof(HEAPLIST32));
SOffset.QuadPart = 0;
ViewSize = 0;
Snapshot = NULL;
Status = NtMapViewOfSection(hSnapshot,
NtCurrentProcess(),
(PVOID*)&Snapshot,
0,
0,
&SOffset,
&ViewSize,
ViewShare,
0,
PAGE_READWRITE);
if(NT_SUCCESS(Status))
{
BOOL Ret;
if(Snapshot->HeapListCount > 0)
{
LPHEAPLIST32 Entries = (LPHEAPLIST32)OffsetToPtr(Snapshot, Snapshot->HeapListOffset);
Snapshot->HeapListIndex = 1;
RtlCopyMemory(lphl, &Entries[0], sizeof(HEAPLIST32));
Ret = TRUE;
}
else
{
SetLastError(ERROR_NO_MORE_FILES);
Ret = FALSE;
}
NtUnmapViewOfSection(NtCurrentProcess(), (PVOID)Snapshot);
return Ret;
}
BaseSetLastNTError(Status);
return FALSE;
}
/*
* @implemented
*/
BOOL
WINAPI
Heap32ListNext(HANDLE hSnapshot, LPHEAPLIST32 lphl)
{
PTH32SNAPSHOT Snapshot;
LARGE_INTEGER SOffset;
SIZE_T ViewSize;
NTSTATUS Status;
CHECK_PARAM_SIZE(lphl, sizeof(HEAPLIST32));
SOffset.QuadPart = 0;
ViewSize = 0;
Snapshot = NULL;
Status = NtMapViewOfSection(hSnapshot,
NtCurrentProcess(),
(PVOID*)&Snapshot,
0,
0,
&SOffset,
&ViewSize,
ViewShare,
0,
PAGE_READWRITE);
if(NT_SUCCESS(Status))
{
BOOL Ret;
if(Snapshot->HeapListCount > 0 &&
Snapshot->HeapListIndex < Snapshot->HeapListCount)
{
LPHEAPLIST32 Entries = (LPHEAPLIST32)OffsetToPtr(Snapshot, Snapshot->HeapListOffset);
RtlCopyMemory(lphl, &Entries[Snapshot->HeapListIndex++], sizeof(HEAPLIST32));
Ret = TRUE;
}
else
{
SetLastError(ERROR_NO_MORE_FILES);
Ret = FALSE;
}
NtUnmapViewOfSection(NtCurrentProcess(), (PVOID)Snapshot);
return Ret;
}
BaseSetLastNTError(Status);
return FALSE;
}
/*
* @implemented
*/
BOOL
WINAPI
Module32First(HANDLE hSnapshot, LPMODULEENTRY32 lpme)
{
MODULEENTRY32W me;
BOOL Ret;
CHECK_PARAM_SIZEA(lpme, sizeof(MODULEENTRY32));
me.dwSize = sizeof(MODULEENTRY32W);
Ret = Module32FirstW(hSnapshot, &me);
if(Ret)
{
lpme->th32ModuleID = me.th32ModuleID;
lpme->th32ProcessID = me.th32ProcessID;
lpme->GlblcntUsage = me.GlblcntUsage;
lpme->ProccntUsage = me.ProccntUsage;
lpme->modBaseAddr = me.modBaseAddr;
lpme->modBaseSize = me.modBaseSize;
lpme->hModule = me.hModule;
WideCharToMultiByte(CP_ACP, 0, me.szModule, -1, lpme->szModule, sizeof(lpme->szModule), 0, 0);
WideCharToMultiByte(CP_ACP, 0, me.szExePath, -1, lpme->szExePath, sizeof(lpme->szExePath), 0, 0);
}
return Ret;
}
/*
* @implemented
*/
BOOL
WINAPI
Module32FirstW(HANDLE hSnapshot, LPMODULEENTRY32W lpme)
{
PTH32SNAPSHOT Snapshot;
LARGE_INTEGER SOffset;
SIZE_T ViewSize;
NTSTATUS Status;
CHECK_PARAM_SIZE(lpme, sizeof(MODULEENTRY32W));
SOffset.QuadPart = 0;
ViewSize = 0;
Snapshot = NULL;
Status = NtMapViewOfSection(hSnapshot,
NtCurrentProcess(),
(PVOID*)&Snapshot,
0,
0,
&SOffset,
&ViewSize,
ViewShare,
0,
PAGE_READWRITE);
if(NT_SUCCESS(Status))
{
BOOL Ret;
if(Snapshot->ModuleListCount > 0)
{
LPMODULEENTRY32W Entries = (LPMODULEENTRY32W)OffsetToPtr(Snapshot, Snapshot->ModuleListOffset);
Snapshot->ModuleListIndex = 1;
RtlCopyMemory(lpme, &Entries[0], sizeof(MODULEENTRY32W));
Ret = TRUE;
}
else
{
SetLastError(ERROR_NO_MORE_FILES);
Ret = FALSE;
}
NtUnmapViewOfSection(NtCurrentProcess(), (PVOID)Snapshot);
return Ret;
}
BaseSetLastNTError(Status);
return FALSE;
}
/*
* @implemented
*/
BOOL
WINAPI
Module32Next(HANDLE hSnapshot, LPMODULEENTRY32 lpme)
{
MODULEENTRY32W me;
BOOL Ret;
CHECK_PARAM_SIZEA(lpme, sizeof(MODULEENTRY32));
me.dwSize = sizeof(MODULEENTRY32W);
Ret = Module32NextW(hSnapshot, &me);
if(Ret)
{
lpme->th32ModuleID = me.th32ModuleID;
lpme->th32ProcessID = me.th32ProcessID;
lpme->GlblcntUsage = me.GlblcntUsage;
lpme->ProccntUsage = me.ProccntUsage;
lpme->modBaseAddr = me.modBaseAddr;
lpme->modBaseSize = me.modBaseSize;
lpme->hModule = me.hModule;
WideCharToMultiByte(CP_ACP, 0, me.szModule, -1, lpme->szModule, sizeof(lpme->szModule), 0, 0);
WideCharToMultiByte(CP_ACP, 0, me.szExePath, -1, lpme->szExePath, sizeof(lpme->szExePath), 0, 0);
}
return Ret;
}
/*
* @implemented
*/
BOOL
WINAPI
Module32NextW(HANDLE hSnapshot, LPMODULEENTRY32W lpme)
{
PTH32SNAPSHOT Snapshot;
LARGE_INTEGER SOffset;
SIZE_T ViewSize;
NTSTATUS Status;
CHECK_PARAM_SIZE(lpme, sizeof(MODULEENTRY32W));
SOffset.QuadPart = 0;
ViewSize = 0;
Snapshot = NULL;
Status = NtMapViewOfSection(hSnapshot,
NtCurrentProcess(),
(PVOID*)&Snapshot,
0,
0,
&SOffset,
&ViewSize,
ViewShare,
0,
PAGE_READWRITE);
if(NT_SUCCESS(Status))
{
BOOL Ret;
if((Snapshot->ModuleListCount > 0) &&
(Snapshot->ModuleListIndex < Snapshot->ModuleListCount))
{
LPMODULEENTRY32W Entries = (LPMODULEENTRY32W)OffsetToPtr(Snapshot, Snapshot->ModuleListOffset);
RtlCopyMemory(lpme, &Entries[Snapshot->ModuleListIndex++], sizeof(MODULEENTRY32W));
Ret = TRUE;
}
else
{
SetLastError(ERROR_NO_MORE_FILES);
Ret = FALSE;
}
NtUnmapViewOfSection(NtCurrentProcess(), (PVOID)Snapshot);
return Ret;
}
BaseSetLastNTError(Status);
return FALSE;
}
/*
* @implemented
*/
BOOL
WINAPI
Process32First(HANDLE hSnapshot, LPPROCESSENTRY32 lppe)
{
PROCESSENTRY32W pe;
BOOL Ret;
CHECK_PARAM_SIZEA(lppe, sizeof(PROCESSENTRY32));
pe.dwSize = sizeof(PROCESSENTRY32W);
Ret = Process32FirstW(hSnapshot, &pe);
if(Ret)
{
lppe->cntUsage = pe.cntUsage;
lppe->th32ProcessID = pe.th32ProcessID;
lppe->th32DefaultHeapID = pe.th32DefaultHeapID;
lppe->th32ModuleID = pe.th32ModuleID;
lppe->cntThreads = pe.cntThreads;
lppe->th32ParentProcessID = pe.th32ParentProcessID;
lppe->pcPriClassBase = pe.pcPriClassBase;
lppe->dwFlags = pe.dwFlags;
WideCharToMultiByte(CP_ACP, 0, pe.szExeFile, -1, lppe->szExeFile, sizeof(lppe->szExeFile), 0, 0);
}
return Ret;
}
/*
* @implemented
*/
BOOL
WINAPI
Process32FirstW(HANDLE hSnapshot, LPPROCESSENTRY32W lppe)
{
PTH32SNAPSHOT Snapshot;
LARGE_INTEGER SOffset;
SIZE_T ViewSize;
NTSTATUS Status;
CHECK_PARAM_SIZE(lppe, sizeof(PROCESSENTRY32W));
SOffset.QuadPart = 0;
ViewSize = 0;
Snapshot = NULL;
Status = NtMapViewOfSection(hSnapshot,
NtCurrentProcess(),
(PVOID*)&Snapshot,
0,
0,
&SOffset,
&ViewSize,
ViewShare,
0,
PAGE_READWRITE);
if(NT_SUCCESS(Status))
{
BOOL Ret;
if(Snapshot->ProcessListCount > 0)
{
LPPROCESSENTRY32W Entries = (LPPROCESSENTRY32W)OffsetToPtr(Snapshot, Snapshot->ProcessListOffset);
Snapshot->ProcessListIndex = 1;
RtlCopyMemory(lppe, &Entries[0], sizeof(PROCESSENTRY32W));
Ret = TRUE;
}
else
{
SetLastError(ERROR_NO_MORE_FILES);
Ret = FALSE;
}
NtUnmapViewOfSection(NtCurrentProcess(), (PVOID)Snapshot);
return Ret;
}
BaseSetLastNTError(Status);
return FALSE;
}
/*
* @implemented
*/
BOOL
WINAPI
Process32Next(HANDLE hSnapshot, LPPROCESSENTRY32 lppe)
{
PROCESSENTRY32W pe;
BOOL Ret;
CHECK_PARAM_SIZEA(lppe, sizeof(PROCESSENTRY32));
pe.dwSize = sizeof(PROCESSENTRY32W);
Ret = Process32NextW(hSnapshot, &pe);
if(Ret)
{
lppe->cntUsage = pe.cntUsage;
lppe->th32ProcessID = pe.th32ProcessID;
lppe->th32DefaultHeapID = pe.th32DefaultHeapID;
lppe->th32ModuleID = pe.th32ModuleID;
lppe->cntThreads = pe.cntThreads;
lppe->th32ParentProcessID = pe.th32ParentProcessID;
lppe->pcPriClassBase = pe.pcPriClassBase;
lppe->dwFlags = pe.dwFlags;
WideCharToMultiByte(CP_ACP, 0, pe.szExeFile, -1, lppe->szExeFile, sizeof(lppe->szExeFile), 0, 0);
}
return Ret;
}
/*
* @implemented
*/
BOOL
WINAPI
Process32NextW(HANDLE hSnapshot, LPPROCESSENTRY32W lppe)
{
PTH32SNAPSHOT Snapshot;
LARGE_INTEGER SOffset;
SIZE_T ViewSize;
NTSTATUS Status;
CHECK_PARAM_SIZE(lppe, sizeof(PROCESSENTRY32W));
SOffset.QuadPart = 0;
ViewSize = 0;
Snapshot = NULL;
Status = NtMapViewOfSection(hSnapshot,
NtCurrentProcess(),
(PVOID*)&Snapshot,
0,
0,
&SOffset,
&ViewSize,
ViewShare,
0,
PAGE_READWRITE);
if(NT_SUCCESS(Status))
{
BOOL Ret;
if(Snapshot->ProcessListCount > 0 &&
Snapshot->ProcessListIndex < Snapshot->ProcessListCount)
{
LPPROCESSENTRY32W Entries = (LPPROCESSENTRY32W)OffsetToPtr(Snapshot, Snapshot->ProcessListOffset);
RtlCopyMemory(lppe, &Entries[Snapshot->ProcessListIndex++], sizeof(PROCESSENTRY32W));
Ret = TRUE;
}
else
{
SetLastError(ERROR_NO_MORE_FILES);
Ret = FALSE;
}
NtUnmapViewOfSection(NtCurrentProcess(), (PVOID)Snapshot);
return Ret;
}
BaseSetLastNTError(Status);
return FALSE;
}
/*
* @implemented
*/
BOOL
WINAPI
Thread32First(HANDLE hSnapshot, LPTHREADENTRY32 lpte)
{
PTH32SNAPSHOT Snapshot;
LARGE_INTEGER SOffset;
SIZE_T ViewSize;
NTSTATUS Status;
CHECK_PARAM_SIZE(lpte, sizeof(THREADENTRY32));
SOffset.QuadPart = 0;
ViewSize = 0;
Snapshot = NULL;
Status = NtMapViewOfSection(hSnapshot,
NtCurrentProcess(),
(PVOID*)&Snapshot,
0,
0,
&SOffset,
&ViewSize,
ViewShare,
0,
PAGE_READWRITE);
if(NT_SUCCESS(Status))
{
BOOL Ret;
if(Snapshot->ThreadListCount > 0)
{
LPTHREADENTRY32 Entries = (LPTHREADENTRY32)OffsetToPtr(Snapshot, Snapshot->ThreadListOffset);
Snapshot->ThreadListIndex = 1;
RtlCopyMemory(lpte, &Entries[0], sizeof(THREADENTRY32));
Ret = TRUE;
}
else
{
SetLastError(ERROR_NO_MORE_FILES);
Ret = FALSE;
}
NtUnmapViewOfSection(NtCurrentProcess(), (PVOID)Snapshot);
return Ret;
}
BaseSetLastNTError(Status);
return FALSE;
}
/*
* @implemented
*/
BOOL
WINAPI
Thread32Next(HANDLE hSnapshot, LPTHREADENTRY32 lpte)
{
PTH32SNAPSHOT Snapshot;
LARGE_INTEGER SOffset;
SIZE_T ViewSize;
NTSTATUS Status;
CHECK_PARAM_SIZE(lpte, sizeof(THREADENTRY32));
SOffset.QuadPart = 0;
ViewSize = 0;
Snapshot = NULL;
Status = NtMapViewOfSection(hSnapshot,
NtCurrentProcess(),
(PVOID*)&Snapshot,
0,
0,
&SOffset,
&ViewSize,
ViewShare,
0,
PAGE_READWRITE);
if(NT_SUCCESS(Status))
{
BOOL Ret;
if(Snapshot->ThreadListCount > 0 &&
Snapshot->ThreadListIndex < Snapshot->ThreadListCount)
{
LPTHREADENTRY32 Entries = (LPTHREADENTRY32)OffsetToPtr(Snapshot, Snapshot->ThreadListOffset);
RtlCopyMemory(lpte, &Entries[Snapshot->ThreadListIndex++], sizeof(THREADENTRY32));
Ret = TRUE;
}
else
{
SetLastError(ERROR_NO_MORE_FILES);
Ret = FALSE;
}
NtUnmapViewOfSection(NtCurrentProcess(), (PVOID)Snapshot);
return Ret;
}
BaseSetLastNTError(Status);
return FALSE;
}
/*
* @implemented
*/
BOOL
WINAPI
Toolhelp32ReadProcessMemory(DWORD th32ProcessID, LPCVOID lpBaseAddress,
LPVOID lpBuffer, SIZE_T cbRead, SIZE_T* lpNumberOfBytesRead)
{
HANDLE hProcess = OpenProcess(PROCESS_VM_READ, FALSE, th32ProcessID);
if(hProcess != NULL)
{
BOOL Ret = ReadProcessMemory(hProcess, lpBaseAddress, lpBuffer, cbRead, lpNumberOfBytesRead);
CloseHandle(hProcess);
return Ret;
}
return FALSE;
}
/*
* @implemented
*/
HANDLE
WINAPI
CreateToolhelp32Snapshot(DWORD dwFlags, DWORD th32ProcessID)
{
PRTL_DEBUG_INFORMATION HeapDebug, ModuleDebug;
PVOID ProcThrdInfo;
SIZE_T ProcThrdInfoSize;
NTSTATUS Status;
HANDLE hSnapShotSection = NULL;
if(th32ProcessID == 0)
{
th32ProcessID = GetCurrentProcessId();
}
/*
* Get all information required for the snapshot
*/
Status = TH32CreateSnapshot(dwFlags,
th32ProcessID,
&HeapDebug,
&ModuleDebug,
&ProcThrdInfo,
&ProcThrdInfoSize);
if(!NT_SUCCESS(Status))
{
BaseSetLastNTError(Status);
return NULL;
}
/*
* Create a section handle and initialize the collected information
*/
Status = TH32CreateSnapshotSectionInitialize(dwFlags,
th32ProcessID,
HeapDebug,
ModuleDebug,
ProcThrdInfo,
&hSnapShotSection);
/*
* Free the temporarily allocated memory which is no longer needed
*/
TH32FreeAllocatedResources(HeapDebug,
ModuleDebug,
ProcThrdInfo,
ProcThrdInfoSize);
if(!NT_SUCCESS(Status))
{
BaseSetLastNTError(Status);
return NULL;
}
return hSnapShotSection;
}
/* EOF */