/* * 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 * 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 #define NDEBUG #include /* 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 */