Commit in reactos/lib/kernel32/misc on MAIN
toolhelp.c+1021-2181.4 -> 1.5
implemented Heap32ListFirst(), Heap32ListNext(), Module32First(), Module32FirstW(), Module32Next(), Module32NextW(), Process32First(), Process32FirstW(), Process32Next(), Process32NextW(), Thread32First(), Thread32Next(), Toolhelp32ReadProcessMemory() and CreateToolhelp32Snapshot().
Currently only the flags TH32CS_SNAPPROCESS, TH32CS_SNAPTHREAD and TH32CS_INHERIT are supported, snapshots of heaps and modules are not fully implemented yet.

reactos/lib/kernel32/misc
toolhelp.c 1.4 -> 1.5
diff -u -r1.4 -r1.5
--- toolhelp.c	28 Aug 2004 22:06:02 -0000	1.4
+++ toolhelp.c	31 Oct 2004 00:04:19 -0000	1.5
@@ -1,4 +1,22 @@
-/* $Id: toolhelp.c,v 1.4 2004/08/28 22:06:02 navaraf Exp $
+/*
+ *  ReactOS kernel
+ *  Copyright (C) 2004 ReactOS Team
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+/* $Id: toolhelp.c,v 1.5 2004/10/31 00:04:19 weiden Exp $
  *
  * KERNEL32.DLL toolhelp functions
  *
@@ -6,339 +24,1124 @@
  * PROJECT:         ReactOS system libraries
  * FILE:            lib/kernel32/misc/toolhelp.c
  * PURPOSE:         Toolhelp functions
- * PROGRAMMER:      Robert Dickenson (robd@mok.lvcm.com)
+ * 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:
- *                  Created 05 January 2003
+ *                  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 "../include/debug.h"
+
+/* INTERNAL DEFINITIONS *******************************************************/
+
+#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.
  */
 
-#include <windows.h>
-#include <tlhelp32.h>
+#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(PDEBUG_BUFFER HeapDebug,
+                           PDEBUG_BUFFER ModuleDebug,
+                           PVOID ProcThrdInfo,
+                           ULONG 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,
+                   PDEBUG_BUFFER *HeapDebug,
+                   PDEBUG_BUFFER *ModuleDebug,
+                   PVOID *ProcThrdInfo,
+                   ULONG *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,
+                                               PDI_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,
+                                               PDI_MODULES,
+                                               *HeapDebug);
+    }
+    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,
+                                    PDEBUG_BUFFER HeapDebug,
+                                    PDEBUG_BUFFER 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;
+  ULONG ViewSize, i;
+  ULONG nProcesses = 0, nThreads = 0, nHeaps = 0, nModules = 0;
+  ULONG RequiredSnapshotSize = sizeof(TH32SNAPSHOT);
+  PHEAP_INFORMATION hi = NULL;
+  PMODULE_INFORMATION mi = NULL;
+  NTSTATUS Status = STATUS_SUCCESS;
+
+  /*
+   * Determine the required size for the heap snapshot
+   */
+  if(dwFlags & TH32CS_SNAPHEAPLIST)
+  {
+    hi = (PHEAP_INFORMATION)HeapDebug->HeapInformation;
+    nHeaps = hi->HeapCount;
+    RequiredSnapshotSize += nHeaps * sizeof(HEAPLIST32);
+  }
+
+  /*
+   * Determine the required size for the module snapshot
+   */
+  if(dwFlags & TH32CS_SNAPMODULE)
+  {
+    mi = (PMODULE_INFORMATION)ModuleDebug->ModuleInformation;
+    nModules = mi->ModuleCount;
+    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 = 0; /* FIXME - use the base address of the heap we're iterating */
+      HeapListEntry->dwFlags = 0; /* FIXME - use the flags of the heap we're iterating */
+
+      HeapListEntry++;
+    }
+
+    DataOffset += hi->HeapCount * 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->th32ProcessID = th32ProcessID;
 
+      /* FIXME - fill the MODULEENTRY32W structure */
 
-#define CHECK_PARAM_SIZE(ptr, siz) \
-    if (!ptr || ptr->dwSize != siz) { \
-        SetLastError(ERROR_INVALID_PARAMETER); \
-        return FALSE; \
+      ModuleListEntry++;
     }
 
+    DataOffset += mi->ModuleCount * 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)ProcessInfo->UniqueProcessId;
+      ProcessListEntry->th32DefaultHeapID = 0; /* no longer used */
+      ProcessListEntry->th32ModuleID = 0; /* no longer used */
+      ProcessListEntry->cntThreads = ProcessInfo->NumberOfThreads;
+      ProcessListEntry->th32ParentProcessID = (ULONG)ProcessInfo->InheritedFromUniqueProcessId;
+      ProcessListEntry->pcPriClassBase = ProcessInfo->BasePriority;
+      ProcessListEntry->dwFlags = 0; /* no longer used */
+      if(ProcessInfo->ImageName.Buffer != NULL)
+      {
+        DbgPrint("proc: %ws\n", ProcessInfo->ImageName.Buffer);
+        lstrcpynW(ProcessListEntry->szExeFile,
+                  ProcessInfo->ImageName.Buffer,
+                  min(ProcessInfo->ImageName.Length, sizeof(ProcessListEntry->szExeFile) / sizeof(ProcessListEntry->szExeFile[0])));
+      }
+      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)ThreadInfo->ClientId.UniqueThread;
+        ThreadListEntry->th32OwnerProcessID = (ULONG)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 ***********************************************************/
 
 /*
  * @unimplemented
  */
-BOOL WINAPI
+BOOL
+STDCALL
 Heap32First(LPHEAPENTRY32 lphe, DWORD th32ProcessID, DWORD th32HeapID)
 {
-    CHECK_PARAM_SIZE(lphe, sizeof(HEAPENTRY32));
+  CHECK_PARAM_SIZE(lphe, sizeof(HEAPENTRY32));
 
-    SetLastError(ERROR_NO_MORE_FILES);
-    return FALSE;
+  SetLastError(ERROR_NO_MORE_FILES);
+  return FALSE;
 }
 
 
 /*
  * @unimplemented
  */
-BOOL WINAPI
+BOOL
+STDCALL
 Heap32Next(LPHEAPENTRY32 lphe)
 {
-/*
-typedef struct tagHEAPENTRY32 {
-	DWORD dwSize;
-	HANDLE hHandle;
-	DWORD dwAddress;
-	DWORD dwBlockSize;
-	DWORD dwFlags;
-	DWORD dwLockCount;
-	DWORD dwResvd;
-	DWORD th32ProcessID;
-	DWORD th32HeapID;
-} HEAPENTRY32,*PHEAPENTRY32,*LPHEAPENTRY32;
- */
-    SetLastError(ERROR_NO_MORE_FILES);
-    return FALSE;
+  CHECK_PARAM_SIZE(lphe, sizeof(HEAPENTRY32));
+
+  SetLastError(ERROR_NO_MORE_FILES);
+  return FALSE;
 }
 
 
 /*
- * @unimplemented
+ * @implemented
  */
-BOOL WINAPI
+BOOL
+STDCALL
 Heap32ListFirst(HANDLE hSnapshot, LPHEAPLIST32 lphl)
 {
-    CHECK_PARAM_SIZE(lphl, sizeof(HEAPLIST32));
+  PTH32SNAPSHOT Snapshot;
+  LARGE_INTEGER SOffset;
+  ULONG 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->ModuleListCount > 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;
+    }
 
-    SetLastError(ERROR_NO_MORE_FILES);
-    return FALSE;
+    NtUnmapViewOfSection(NtCurrentProcess(), (PVOID)Snapshot);
+    return Ret;
+  }
+
+  SetLastErrorByStatus(Status);
+  return FALSE;
 }
 
 
 /*
- * @unimplemented
+ * @implemented
  */
-BOOL WINAPI
-Heap32ListNext(HANDLE hSnapshot, LPHEAPLIST32 lph1)
+BOOL
+STDCALL
+Heap32ListNext(HANDLE hSnapshot, LPHEAPLIST32 lphl)
 {
-/*
-typedef struct tagHEAPLIST32 {
-	DWORD dwSize;
-	DWORD th32ProcessID;
-	DWORD th32HeapID;
-	DWORD dwFlags;
-} HEAPLIST32,*PHEAPLIST32,*LPHEAPLIST32;
- */
-    SetLastError(ERROR_NO_MORE_FILES);
-    return FALSE;
+  PTH32SNAPSHOT Snapshot;
+  LARGE_INTEGER SOffset;
+  ULONG 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;
+  }
+
+  SetLastErrorByStatus(Status);
+  return FALSE;
 }
 
 
 /*
- * @unimplemented
+ * @implemented
  */
-BOOL WINAPI
+BOOL
+STDCALL
 Module32First(HANDLE hSnapshot, LPMODULEENTRY32 lpme)
 {
-    CHECK_PARAM_SIZE(lpme, sizeof(MODULEENTRY32));
+  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);
+  }
 
-    SetLastError(ERROR_NO_MORE_FILES);
-    return FALSE;
+  return Ret;
 }
 
 
 /*
- * @unimplemented
+ * @implemented
  */
-BOOL WINAPI
+BOOL
+STDCALL
 Module32FirstW(HANDLE hSnapshot, LPMODULEENTRY32W lpme)
 {
-    CHECK_PARAM_SIZE(lpme, sizeof(MODULEENTRY32W));
+  PTH32SNAPSHOT Snapshot;
+  LARGE_INTEGER SOffset;
+  ULONG 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;
+    }
 
-    SetLastError(ERROR_NO_MORE_FILES);
-    return FALSE;
+    NtUnmapViewOfSection(NtCurrentProcess(), (PVOID)Snapshot);
+    return Ret;
+  }
+
+  SetLastErrorByStatus(Status);
+  return FALSE;
 }
 
 
 /*
- * @unimplemented
+ * @implemented
  */
-BOOL WINAPI
+BOOL
+STDCALL
 Module32Next(HANDLE hSnapshot, LPMODULEENTRY32 lpme)
 {
-/*
-typedef struct tagMODULEENTRY32 {
-	DWORD dwSize;
-	DWORD th32ModuleID;
-	DWORD th32ProcessID;
-	DWORD GlblcntUsage;
-	DWORD ProccntUsage;
-	BYTE *modBaseAddr;
-	DWORD modBaseSize;
-	HMODULE hModule;
-	char szModule[MAX_MODULE_NAME32 + 1];
-	char szExePath[MAX_PATH];
-} MODULEENTRY32,*PMODULEENTRY32,*LPMODULEENTRY32;
- */
-    SetLastError(ERROR_NO_MORE_FILES);
-    return FALSE;
+  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;
 }
 
-BOOL WINAPI
+
+BOOL
+STDCALL
 Module32NextW(HANDLE hSnapshot, LPMODULEENTRY32W lpme)
 {
-/*
-typedef struct tagMODULEENTRY32W {
-	DWORD dwSize;
-	DWORD th32ModuleID;
-	DWORD th32ProcessID;
-	DWORD GlblcntUsage;
-	DWORD ProccntUsage;
-	BYTE *modBaseAddr;
-	DWORD modBaseSize;
-	HMODULE hModule; 
-	WCHAR szModule[MAX_MODULE_NAME32 + 1];
-	WCHAR szExePath[MAX_PATH];
-} MODULEENTRY32W,*PMODULEENTRY32W,*LPMODULEENTRY32W;
+  PTH32SNAPSHOT Snapshot;
+  LARGE_INTEGER SOffset;
+  ULONG 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->ProcessListIndex++], sizeof(MODULEENTRY32W));
+      Ret = TRUE;
+    }
+    else
+    {
+      SetLastError(ERROR_NO_MORE_FILES);
+      Ret = FALSE;
+    }
 
- */
-    SetLastError(ERROR_NO_MORE_FILES);
-    return FALSE;
+    NtUnmapViewOfSection(NtCurrentProcess(), (PVOID)Snapshot);
+    return Ret;
+  }
+
+  SetLastErrorByStatus(Status);
+  return FALSE;
 }
 
 
 /*
- * @unimplemented
+ * @implemented
  */
-BOOL STDCALL
+BOOL
+STDCALL
 Process32First(HANDLE hSnapshot, LPPROCESSENTRY32 lppe)
 {
-    CHECK_PARAM_SIZE(lppe, sizeof(PROCESSENTRY32));
+  PROCESSENTRY32W pe;
+  BOOL Ret;
+
+  CHECK_PARAM_SIZEA(lppe, sizeof(PROCESSENTRY32));
 
-    SetLastError(ERROR_NO_MORE_FILES);
-    return FALSE;
+  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;
 }
 
 
 /*
- * @unimplemented
+ * @implemented
  */
-BOOL STDCALL
-Process32Next(HANDLE hSnapshot, LPPROCESSENTRY32 lppe)
+BOOL
+STDCALL
+Process32FirstW(HANDLE hSnapshot, LPPROCESSENTRY32W lppe)
 {
-/*
-typedef struct tagPROCESSENTRY32 {
-	DWORD dwSize;
-	DWORD cntUsage;
-	DWORD th32ProcessID;
-	DWORD th32DefaultHeapID;
-	DWORD th32ModuleID;
-	DWORD cntThreads;
-	DWORD th32ParentProcessID;
-	LONG pcPriClassBase;
-	DWORD dwFlags;
-	CHAR  szExeFile[MAX_PATH];
-} PROCESSENTRY32,*PPROCESSENTRY32,*LPPROCESSENTRY32;
- */
-    SetLastError(ERROR_NO_MORE_FILES);
-    return FALSE;
+  PTH32SNAPSHOT Snapshot;
+  LARGE_INTEGER SOffset;
+  ULONG 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;
+  }
+
+  SetLastErrorByStatus(Status);
+  return FALSE;
 }
 
 
 /*
- * @unimplemented
+ * @implemented
  */
-BOOL STDCALL
-Process32FirstW(HANDLE hSnapshot, LPPROCESSENTRY32W lppe)
+BOOL
+STDCALL
+Process32Next(HANDLE hSnapshot, LPPROCESSENTRY32 lppe)
[truncated at 1000 lines; 369 more skipped]
CVSspam 0.2.8