mirror of
https://github.com/reactos/reactos.git
synced 2024-12-29 10:35:28 +00:00
1310 lines
34 KiB
C
1310 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 */
|