implemented Heap32ListFirst(), Heap32ListNext(), Module32First(), Module32FirstW...
[reactos.git] / reactos / lib / kernel32 / misc / toolhelp.c
1 /*
2 * ReactOS kernel
3 * Copyright (C) 2004 ReactOS Team
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18 */
19 /* $Id: toolhelp.c,v 1.5 2004/10/31 00:04:19 weiden Exp $
20 *
21 * KERNEL32.DLL toolhelp functions
22 *
23 * COPYRIGHT: See COPYING in the top level directory
24 * PROJECT: ReactOS system libraries
25 * FILE: lib/kernel32/misc/toolhelp.c
26 * PURPOSE: Toolhelp functions
27 * PROGRAMMER: Thomas Weidenmueller <w3seek@reactos.com>
28 * Robert Dickenson (robd@mok.lvcm.com)
29 *
30 * NOTES: Do NOT use the heap functions in here because they
31 * adulterate the heap statistics!
32 *
33 * UPDATE HISTORY:
34 * 10/30/2004 Implemented some parts (w3)
35 * Inspired by the book "Windows NT Native API"
36 * Created 05 January 2003 (robd)
37 */
38
39 #include <k32.h>
40
41 #define NDEBUG
42 #include "../include/debug.h"
43
44 /* INTERNAL DEFINITIONS *******************************************************/
45
46 #define CHECK_PARAM_SIZE(ptr, siz) \
47 if((ptr) == NULL || (ptr)->dwSize != (siz)) \
48 { \
49 SetLastError(ERROR_INVALID_PARAMETER); \
50 return FALSE; \
51 }
52
53 /*
54 * Tests in win showed that the dwSize field can be greater than the actual size
55 * of the structure for the ansi functions. I found this out by accidently
56 * forgetting to set the dwSize field in a test application and it just didn't
57 * work in ros but in win.
58 */
59
60 #define CHECK_PARAM_SIZEA(ptr, siz) \
61 if((ptr) == NULL || (ptr)->dwSize < (siz)) \
62 { \
63 SetLastError(ERROR_INVALID_PARAMETER); \
64 return FALSE; \
65 }
66
67 #define OffsetToPtr(Snapshot, Offset) \
68 ((ULONG_PTR)((Snapshot) + 1) + (ULONG_PTR)(Offset))
69
70 typedef struct _TH32SNAPSHOT
71 {
72 /* Heap list */
73 ULONG HeapListCount;
74 ULONG HeapListIndex;
75 ULONG_PTR HeapListOffset;
76 /* Module list */
77 ULONG ModuleListCount;
78 ULONG ModuleListIndex;
79 ULONG_PTR ModuleListOffset;
80 /* Process list */
81 ULONG ProcessListCount;
82 ULONG ProcessListIndex;
83 ULONG_PTR ProcessListOffset;
84 /* Thread list */
85 ULONG ThreadListCount;
86 ULONG ThreadListIndex;
87 ULONG_PTR ThreadListOffset;
88 } TH32SNAPSHOT, *PTH32SNAPSHOT;
89
90 /* INTERNAL FUNCTIONS *********************************************************/
91
92 static VOID
93 TH32FreeAllocatedResources(PDEBUG_BUFFER HeapDebug,
94 PDEBUG_BUFFER ModuleDebug,
95 PVOID ProcThrdInfo,
96 ULONG ProcThrdInfoSize)
97 {
98 if(HeapDebug != NULL)
99 {
100 RtlDestroyQueryDebugBuffer(HeapDebug);
101 }
102 if(ModuleDebug != NULL)
103 {
104 RtlDestroyQueryDebugBuffer(ModuleDebug);
105 }
106
107 if(ProcThrdInfo != NULL)
108 {
109 NtFreeVirtualMemory(NtCurrentProcess(),
110 ProcThrdInfo,
111 &ProcThrdInfoSize,
112 MEM_RELEASE);
113 }
114 }
115
116 static NTSTATUS
117 TH32CreateSnapshot(DWORD dwFlags,
118 DWORD th32ProcessID,
119 PDEBUG_BUFFER *HeapDebug,
120 PDEBUG_BUFFER *ModuleDebug,
121 PVOID *ProcThrdInfo,
122 ULONG *ProcThrdInfoSize)
123 {
124 NTSTATUS Status = STATUS_SUCCESS;
125
126 *HeapDebug = NULL;
127 *ModuleDebug = NULL;
128 *ProcThrdInfo = NULL;
129 *ProcThrdInfoSize = 0;
130
131 /*
132 * Allocate the debug information for a heap snapshot
133 */
134 if(dwFlags & TH32CS_SNAPHEAPLIST)
135 {
136 *HeapDebug = RtlCreateQueryDebugBuffer(0, FALSE);
137 if(*HeapDebug != NULL)
138 {
139 Status = RtlQueryProcessDebugInformation(th32ProcessID,
140 PDI_HEAPS,
141 *HeapDebug);
142 }
143 else
144 Status = STATUS_UNSUCCESSFUL;
145 }
146
147 /*
148 * Allocate the debug information for a module snapshot
149 */
150 if(dwFlags & TH32CS_SNAPMODULE &&
151 NT_SUCCESS(Status))
152 {
153 *ModuleDebug = RtlCreateQueryDebugBuffer(0, FALSE);
154 if(*ModuleDebug != NULL)
155 {
156 Status = RtlQueryProcessDebugInformation(th32ProcessID,
157 PDI_MODULES,
158 *HeapDebug);
159 }
160 else
161 Status = STATUS_UNSUCCESSFUL;
162 }
163
164 /*
165 * Allocate enough memory for the system's process list
166 */
167
168 if(dwFlags & (TH32CS_SNAPPROCESS | TH32CS_SNAPTHREAD) &&
169 NT_SUCCESS(Status))
170 {
171 for(;;)
172 {
173 (*ProcThrdInfoSize) += 0x10000;
174 Status = NtAllocateVirtualMemory(NtCurrentProcess(),
175 ProcThrdInfo,
176 0,
177 ProcThrdInfoSize,
178 MEM_COMMIT,
179 PAGE_READWRITE);
180 if(!NT_SUCCESS(Status))
181 {
182 break;
183 }
184
185 Status = NtQuerySystemInformation(SystemProcessInformation,
186 *ProcThrdInfo,
187 *ProcThrdInfoSize,
188 NULL);
189 if(Status == STATUS_INFO_LENGTH_MISMATCH)
190 {
191 NtFreeVirtualMemory(NtCurrentProcess(),
192 ProcThrdInfo,
193 ProcThrdInfoSize,
194 MEM_RELEASE);
195 *ProcThrdInfo = NULL;
196 }
197 else
198 {
199 break;
200 }
201 }
202 }
203
204 /*
205 * Free resources in case of failure!
206 */
207
208 if(!NT_SUCCESS(Status))
209 {
210 TH32FreeAllocatedResources(*HeapDebug,
211 *ModuleDebug,
212 *ProcThrdInfo,
213 *ProcThrdInfoSize);
214 }
215
216 return Status;
217 }
218
219 static NTSTATUS
220 TH32CreateSnapshotSectionInitialize(DWORD dwFlags,
221 DWORD th32ProcessID,
222 PDEBUG_BUFFER HeapDebug,
223 PDEBUG_BUFFER ModuleDebug,
224 PVOID ProcThrdInfo,
225 HANDLE *SectionHandle)
226 {
227 PSYSTEM_PROCESS_INFORMATION ProcessInfo;
228 LPHEAPLIST32 HeapListEntry;
229 LPMODULEENTRY32W ModuleListEntry;
230 LPPROCESSENTRY32W ProcessListEntry;
231 LPTHREADENTRY32 ThreadListEntry;
232 OBJECT_ATTRIBUTES ObjectAttributes;
233 LARGE_INTEGER SSize, SOffset;
234 HANDLE hSection;
235 PTH32SNAPSHOT Snapshot;
236 ULONG_PTR DataOffset;
237 ULONG ViewSize, i;
238 ULONG nProcesses = 0, nThreads = 0, nHeaps = 0, nModules = 0;
239 ULONG RequiredSnapshotSize = sizeof(TH32SNAPSHOT);
240 PHEAP_INFORMATION hi = NULL;
241 PMODULE_INFORMATION mi = NULL;
242 NTSTATUS Status = STATUS_SUCCESS;
243
244 /*
245 * Determine the required size for the heap snapshot
246 */
247 if(dwFlags & TH32CS_SNAPHEAPLIST)
248 {
249 hi = (PHEAP_INFORMATION)HeapDebug->HeapInformation;
250 nHeaps = hi->HeapCount;
251 RequiredSnapshotSize += nHeaps * sizeof(HEAPLIST32);
252 }
253
254 /*
255 * Determine the required size for the module snapshot
256 */
257 if(dwFlags & TH32CS_SNAPMODULE)
258 {
259 mi = (PMODULE_INFORMATION)ModuleDebug->ModuleInformation;
260 nModules = mi->ModuleCount;
261 RequiredSnapshotSize += nModules * sizeof(MODULEENTRY32W);
262 }
263
264 /*
265 * Determine the required size for the processes and threads snapshot
266 */
267 if(dwFlags & (TH32CS_SNAPPROCESS | TH32CS_SNAPTHREAD))
268 {
269 ULONG ProcOffset = 0;
270
271 ProcessInfo = (PSYSTEM_PROCESS_INFORMATION)ProcThrdInfo;
272 do
273 {
274 ProcessInfo = (PSYSTEM_PROCESS_INFORMATION)((ULONG_PTR)ProcessInfo + ProcOffset);
275 nProcesses++;
276 nThreads += ProcessInfo->NumberOfThreads;
277 ProcOffset = ProcessInfo->NextEntryOffset;
278 } while(ProcOffset != 0);
279
280 if(dwFlags & TH32CS_SNAPPROCESS)
281 {
282 RequiredSnapshotSize += nProcesses * sizeof(PROCESSENTRY32W);
283 }
284 if(dwFlags & TH32CS_SNAPTHREAD)
285 {
286 RequiredSnapshotSize += nThreads * sizeof(THREADENTRY32);
287 }
288 }
289
290 /*
291 * Create and map the section
292 */
293
294 SSize.QuadPart = RequiredSnapshotSize;
295
296 InitializeObjectAttributes(&ObjectAttributes,
297 NULL,
298 ((dwFlags & TH32CS_INHERIT) ? OBJ_INHERIT : 0),
299 NULL,
300 NULL);
301
302 Status = NtCreateSection(&hSection,
303 SECTION_ALL_ACCESS,
304 &ObjectAttributes,
305 &SSize,
306 PAGE_READWRITE,
307 SEC_COMMIT,
308 NULL);
309 if(!NT_SUCCESS(Status))
310 {
311 return Status;
312 }
313
314 SOffset.QuadPart = 0;
315 ViewSize = 0;
316 Snapshot = NULL;
317
318 Status = NtMapViewOfSection(hSection,
319 NtCurrentProcess(),
320 (PVOID*)&Snapshot,
321 0,
322 0,
323 &SOffset,
324 &ViewSize,
325 ViewShare,
326 0,
327 PAGE_READWRITE);
328 if(!NT_SUCCESS(Status))
329 {
330 NtClose(hSection);
331 return Status;
332 }
333
334 RtlZeroMemory(Snapshot, sizeof(TH32SNAPSHOT));
335 DataOffset = 0;
336
337 /*
338 * Initialize the section data and fill it with all the data we collected
339 */
340
341 /* initialize the heap list */
342 if(dwFlags & TH32CS_SNAPHEAPLIST)
343 {
344 Snapshot->HeapListCount = nHeaps;
345 Snapshot->HeapListOffset = DataOffset;
346 HeapListEntry = (LPHEAPLIST32)OffsetToPtr(Snapshot, DataOffset);
347 for(i = 0; i < nHeaps; i++)
348 {
349 HeapListEntry->dwSize = sizeof(HEAPLIST32);
350 HeapListEntry->th32ProcessID = th32ProcessID;
351 HeapListEntry->th32HeapID = 0; /* FIXME - use the base address of the heap we're iterating */
352 HeapListEntry->dwFlags = 0; /* FIXME - use the flags of the heap we're iterating */
353
354 HeapListEntry++;
355 }
356
357 DataOffset += hi->HeapCount * sizeof(HEAPLIST32);
358 }
359
360 /* initialize the module list */
361 if(dwFlags & TH32CS_SNAPMODULE)
362 {
363 Snapshot->ModuleListCount = nModules;
364 Snapshot->ModuleListOffset = DataOffset;
365 ModuleListEntry = (LPMODULEENTRY32W)OffsetToPtr(Snapshot, DataOffset);
366 for(i = 0; i < nModules; i++)
367 {
368 ModuleListEntry->dwSize = sizeof(MODULEENTRY32W);
369 ModuleListEntry->th32ProcessID = th32ProcessID;
370
371 /* FIXME - fill the MODULEENTRY32W structure */
372
373 ModuleListEntry++;
374 }
375
376 DataOffset += mi->ModuleCount * sizeof(MODULEENTRY32W);
377 }
378
379 /* initialize the process list */
380 if(dwFlags & TH32CS_SNAPPROCESS)
381 {
382 ULONG ProcOffset = 0;
383
384 Snapshot->ProcessListCount = nProcesses;
385 Snapshot->ProcessListOffset = DataOffset;
386 ProcessListEntry = (LPPROCESSENTRY32W)OffsetToPtr(Snapshot, DataOffset);
387 ProcessInfo = (PSYSTEM_PROCESS_INFORMATION)ProcThrdInfo;
388 do
389 {
390 ProcessInfo = (PSYSTEM_PROCESS_INFORMATION)((ULONG_PTR)ProcessInfo + ProcOffset);
391
392 ProcessListEntry->dwSize = sizeof(PROCESSENTRY32W);
393 ProcessListEntry->cntUsage = 0; /* no longer used */
394 ProcessListEntry->th32ProcessID = (ULONG)ProcessInfo->UniqueProcessId;
395 ProcessListEntry->th32DefaultHeapID = 0; /* no longer used */
396 ProcessListEntry->th32ModuleID = 0; /* no longer used */
397 ProcessListEntry->cntThreads = ProcessInfo->NumberOfThreads;
398 ProcessListEntry->th32ParentProcessID = (ULONG)ProcessInfo->InheritedFromUniqueProcessId;
399 ProcessListEntry->pcPriClassBase = ProcessInfo->BasePriority;
400 ProcessListEntry->dwFlags = 0; /* no longer used */
401 if(ProcessInfo->ImageName.Buffer != NULL)
402 {
403 DbgPrint("proc: %ws\n", ProcessInfo->ImageName.Buffer);
404 lstrcpynW(ProcessListEntry->szExeFile,
405 ProcessInfo->ImageName.Buffer,
406 min(ProcessInfo->ImageName.Length, sizeof(ProcessListEntry->szExeFile) / sizeof(ProcessListEntry->szExeFile[0])));
407 }
408 else
409 {
410 lstrcpyW(ProcessListEntry->szExeFile, L"[System Process]");
411 }
412
413 ProcessListEntry++;
414
415 ProcOffset = ProcessInfo->NextEntryOffset;
416 } while(ProcOffset != 0);
417
418 DataOffset += nProcesses * sizeof(PROCESSENTRY32W);
419 }
420
421 /* initialize the thread list */
422 if(dwFlags & TH32CS_SNAPTHREAD)
423 {
424 ULONG ProcOffset = 0;
425
426 Snapshot->ThreadListCount = nThreads;
427 Snapshot->ThreadListOffset = DataOffset;
428 ThreadListEntry = (LPTHREADENTRY32)OffsetToPtr(Snapshot, DataOffset);
429 ProcessInfo = (PSYSTEM_PROCESS_INFORMATION)ProcThrdInfo;
430 do
431 {
432 PSYSTEM_THREAD_INFORMATION ThreadInfo;
433 ULONG n;
434
435 ProcessInfo = (PSYSTEM_PROCESS_INFORMATION)((ULONG_PTR)ProcessInfo + ProcOffset);
436 ThreadInfo = (PSYSTEM_THREAD_INFORMATION)(ProcessInfo + 1);
437
438 for(n = 0; n < ProcessInfo->NumberOfThreads; n++)
439 {
440 ThreadListEntry->dwSize = sizeof(THREADENTRY32);
441 ThreadListEntry->cntUsage = 0; /* no longer used */
442 ThreadListEntry->th32ThreadID = (ULONG)ThreadInfo->ClientId.UniqueThread;
443 ThreadListEntry->th32OwnerProcessID = (ULONG)ThreadInfo->ClientId.UniqueProcess;
444 ThreadListEntry->tpBasePri = ThreadInfo->BasePriority;
445 ThreadListEntry->tpDeltaPri = 0; /* no longer used */
446 ThreadListEntry->dwFlags = 0; /* no longer used */
447
448 ThreadInfo++;
449 ThreadListEntry++;
450 }
451
452 ProcOffset = ProcessInfo->NextEntryOffset;
453 } while(ProcOffset != 0);
454 }
455
456 /*
457 * We're done, unmap the view and return the section handle
458 */
459
460 Status = NtUnmapViewOfSection(NtCurrentProcess(), (PVOID)Snapshot);
461
462 if(NT_SUCCESS(Status))
463 {
464 *SectionHandle = hSection;
465 }
466 else
467 {
468 NtClose(hSection);
469 }
470
471 return Status;
472 }
473
474 /* PUBLIC FUNCTIONS ***********************************************************/
475
476 /*
477 * @unimplemented
478 */
479 BOOL
480 STDCALL
481 Heap32First(LPHEAPENTRY32 lphe, DWORD th32ProcessID, DWORD th32HeapID)
482 {
483 CHECK_PARAM_SIZE(lphe, sizeof(HEAPENTRY32));
484
485 SetLastError(ERROR_NO_MORE_FILES);
486 return FALSE;
487 }
488
489
490 /*
491 * @unimplemented
492 */
493 BOOL
494 STDCALL
495 Heap32Next(LPHEAPENTRY32 lphe)
496 {
497 CHECK_PARAM_SIZE(lphe, sizeof(HEAPENTRY32));
498
499 SetLastError(ERROR_NO_MORE_FILES);
500 return FALSE;
501 }
502
503
504 /*
505 * @implemented
506 */
507 BOOL
508 STDCALL
509 Heap32ListFirst(HANDLE hSnapshot, LPHEAPLIST32 lphl)
510 {
511 PTH32SNAPSHOT Snapshot;
512 LARGE_INTEGER SOffset;
513 ULONG ViewSize;
514 NTSTATUS Status;
515
516 CHECK_PARAM_SIZE(lphl, sizeof(HEAPLIST32));
517
518 SOffset.QuadPart = 0;
519 ViewSize = 0;
520 Snapshot = NULL;
521
522 Status = NtMapViewOfSection(hSnapshot,
523 NtCurrentProcess(),
524 (PVOID*)&Snapshot,
525 0,
526 0,
527 &SOffset,
528 &ViewSize,
529 ViewShare,
530 0,
531 PAGE_READWRITE);
532 if(NT_SUCCESS(Status))
533 {
534 BOOL Ret;
535
536 if(Snapshot->ModuleListCount > 0)
537 {
538 LPHEAPLIST32 Entries = (LPHEAPLIST32)OffsetToPtr(Snapshot, Snapshot->HeapListOffset);
539 Snapshot->HeapListIndex = 1;
540 RtlCopyMemory(lphl, &Entries[0], sizeof(HEAPLIST32));
541 Ret = TRUE;
542 }
543 else
544 {
545 SetLastError(ERROR_NO_MORE_FILES);
546 Ret = FALSE;
547 }
548
549 NtUnmapViewOfSection(NtCurrentProcess(), (PVOID)Snapshot);
550 return Ret;
551 }
552
553 SetLastErrorByStatus(Status);
554 return FALSE;
555 }
556
557
558 /*
559 * @implemented
560 */
561 BOOL
562 STDCALL
563 Heap32ListNext(HANDLE hSnapshot, LPHEAPLIST32 lphl)
564 {
565 PTH32SNAPSHOT Snapshot;
566 LARGE_INTEGER SOffset;
567 ULONG ViewSize;
568 NTSTATUS Status;
569
570 CHECK_PARAM_SIZE(lphl, sizeof(HEAPLIST32));
571
572 SOffset.QuadPart = 0;
573 ViewSize = 0;
574 Snapshot = NULL;
575
576 Status = NtMapViewOfSection(hSnapshot,
577 NtCurrentProcess(),
578 (PVOID*)&Snapshot,
579 0,
580 0,
581 &SOffset,
582 &ViewSize,
583 ViewShare,
584 0,
585 PAGE_READWRITE);
586 if(NT_SUCCESS(Status))
587 {
588 BOOL Ret;
589
590 if(Snapshot->HeapListCount > 0 &&
591 Snapshot->HeapListIndex < Snapshot->HeapListCount)
592 {
593 LPHEAPLIST32 Entries = (LPHEAPLIST32)OffsetToPtr(Snapshot, Snapshot->HeapListOffset);
594 RtlCopyMemory(lphl, &Entries[Snapshot->HeapListIndex++], sizeof(HEAPLIST32));
595 Ret = TRUE;
596 }
597 else
598 {
599 SetLastError(ERROR_NO_MORE_FILES);
600 Ret = FALSE;
601 }
602
603 NtUnmapViewOfSection(NtCurrentProcess(), (PVOID)Snapshot);
604 return Ret;
605 }
606
607 SetLastErrorByStatus(Status);
608 return FALSE;
609 }
610
611
612 /*
613 * @implemented
614 */
615 BOOL
616 STDCALL
617 Module32First(HANDLE hSnapshot, LPMODULEENTRY32 lpme)
618 {
619 MODULEENTRY32W me;
620 BOOL Ret;
621
622 CHECK_PARAM_SIZEA(lpme, sizeof(MODULEENTRY32));
623
624 me.dwSize = sizeof(MODULEENTRY32W);
625
626 Ret = Module32FirstW(hSnapshot, &me);
627 if(Ret)
628 {
629 lpme->th32ModuleID = me.th32ModuleID;
630 lpme->th32ProcessID = me.th32ProcessID;
631 lpme->GlblcntUsage = me.GlblcntUsage;
632 lpme->ProccntUsage = me.ProccntUsage;
633 lpme->modBaseAddr = me.modBaseAddr;
634 lpme->modBaseSize = me.modBaseSize;
635 lpme->hModule = me.hModule;
636
637 WideCharToMultiByte(CP_ACP, 0, me.szModule, -1, lpme->szModule, sizeof(lpme->szModule), 0, 0);
638 WideCharToMultiByte(CP_ACP, 0, me.szExePath, -1, lpme->szExePath, sizeof(lpme->szExePath), 0, 0);
639 }
640
641 return Ret;
642 }
643
644
645 /*
646 * @implemented
647 */
648 BOOL
649 STDCALL
650 Module32FirstW(HANDLE hSnapshot, LPMODULEENTRY32W lpme)
651 {
652 PTH32SNAPSHOT Snapshot;
653 LARGE_INTEGER SOffset;
654 ULONG ViewSize;
655 NTSTATUS Status;
656
657 CHECK_PARAM_SIZE(lpme, sizeof(MODULEENTRY32W));
658
659 SOffset.QuadPart = 0;
660 ViewSize = 0;
661 Snapshot = NULL;
662
663 Status = NtMapViewOfSection(hSnapshot,
664 NtCurrentProcess(),
665 (PVOID*)&Snapshot,
666 0,
667 0,
668 &SOffset,
669 &ViewSize,
670 ViewShare,
671 0,
672 PAGE_READWRITE);
673 if(NT_SUCCESS(Status))
674 {
675 BOOL Ret;
676
677 if(Snapshot->ModuleListCount > 0)
678 {
679 LPMODULEENTRY32W Entries = (LPMODULEENTRY32W)OffsetToPtr(Snapshot, Snapshot->ModuleListOffset);
680 Snapshot->ModuleListIndex = 1;
681 RtlCopyMemory(lpme, &Entries[0], sizeof(MODULEENTRY32W));
682 Ret = TRUE;
683 }
684 else
685 {
686 SetLastError(ERROR_NO_MORE_FILES);
687 Ret = FALSE;
688 }
689
690 NtUnmapViewOfSection(NtCurrentProcess(), (PVOID)Snapshot);
691 return Ret;
692 }
693
694 SetLastErrorByStatus(Status);
695 return FALSE;
696 }
697
698
699 /*
700 * @implemented
701 */
702 BOOL
703 STDCALL
704 Module32Next(HANDLE hSnapshot, LPMODULEENTRY32 lpme)
705 {
706 MODULEENTRY32W me;
707 BOOL Ret;
708
709 CHECK_PARAM_SIZEA(lpme, sizeof(MODULEENTRY32));
710
711 me.dwSize = sizeof(MODULEENTRY32W);
712
713 Ret = Module32NextW(hSnapshot, &me);
714 if(Ret)
715 {
716 lpme->th32ModuleID = me.th32ModuleID;
717 lpme->th32ProcessID = me.th32ProcessID;
718 lpme->GlblcntUsage = me.GlblcntUsage;
719 lpme->ProccntUsage = me.ProccntUsage;
720 lpme->modBaseAddr = me.modBaseAddr;
721 lpme->modBaseSize = me.modBaseSize;
722 lpme->hModule = me.hModule;
723
724 WideCharToMultiByte(CP_ACP, 0, me.szModule, -1, lpme->szModule, sizeof(lpme->szModule), 0, 0);
725 WideCharToMultiByte(CP_ACP, 0, me.szExePath, -1, lpme->szExePath, sizeof(lpme->szExePath), 0, 0);
726 }
727
728 return Ret;
729 }
730
731
732 BOOL
733 STDCALL
734 Module32NextW(HANDLE hSnapshot, LPMODULEENTRY32W lpme)
735 {
736 PTH32SNAPSHOT Snapshot;
737 LARGE_INTEGER SOffset;
738 ULONG ViewSize;
739 NTSTATUS Status;
740
741 CHECK_PARAM_SIZE(lpme, sizeof(MODULEENTRY32W));
742
743 SOffset.QuadPart = 0;
744 ViewSize = 0;
745 Snapshot = NULL;
746
747 Status = NtMapViewOfSection(hSnapshot,
748 NtCurrentProcess(),
749 (PVOID*)&Snapshot,
750 0,
751 0,
752 &SOffset,
753 &ViewSize,
754 ViewShare,
755 0,
756 PAGE_READWRITE);
757 if(NT_SUCCESS(Status))
758 {
759 BOOL Ret;
760
761 if(Snapshot->ModuleListCount > 0 &&
762 Snapshot->ModuleListIndex < Snapshot->ModuleListCount)
763 {
764 LPMODULEENTRY32W Entries = (LPMODULEENTRY32W)OffsetToPtr(Snapshot, Snapshot->ModuleListOffset);
765 RtlCopyMemory(lpme, &Entries[Snapshot->ProcessListIndex++], sizeof(MODULEENTRY32W));
766 Ret = TRUE;
767 }
768 else
769 {
770 SetLastError(ERROR_NO_MORE_FILES);
771 Ret = FALSE;
772 }
773
774 NtUnmapViewOfSection(NtCurrentProcess(), (PVOID)Snapshot);
775 return Ret;
776 }
777
778 SetLastErrorByStatus(Status);
779 return FALSE;
780 }
781
782
783 /*
784 * @implemented
785 */
786 BOOL
787 STDCALL
788 Process32First(HANDLE hSnapshot, LPPROCESSENTRY32 lppe)
789 {
790 PROCESSENTRY32W pe;
791 BOOL Ret;
792
793 CHECK_PARAM_SIZEA(lppe, sizeof(PROCESSENTRY32));
794
795 pe.dwSize = sizeof(PROCESSENTRY32W);
796
797 Ret = Process32FirstW(hSnapshot, &pe);
798 if(Ret)
799 {
800 lppe->cntUsage = pe.cntUsage;
801 lppe->th32ProcessID = pe.th32ProcessID;
802 lppe->th32DefaultHeapID = pe.th32DefaultHeapID;
803 lppe->th32ModuleID = pe.th32ModuleID;
804 lppe->cntThreads = pe.cntThreads;
805 lppe->th32ParentProcessID = pe.th32ParentProcessID;
806 lppe->pcPriClassBase = pe.pcPriClassBase;
807 lppe->dwFlags = pe.dwFlags;
808
809 WideCharToMultiByte(CP_ACP, 0, pe.szExeFile, -1, lppe->szExeFile, sizeof(lppe->szExeFile), 0, 0);
810 }
811
812 return Ret;
813 }
814
815
816 /*
817 * @implemented
818 */
819 BOOL
820 STDCALL
821 Process32FirstW(HANDLE hSnapshot, LPPROCESSENTRY32W lppe)
822 {
823 PTH32SNAPSHOT Snapshot;
824 LARGE_INTEGER SOffset;
825 ULONG ViewSize;
826 NTSTATUS Status;
827
828 CHECK_PARAM_SIZE(lppe, sizeof(PROCESSENTRY32W));
829
830 SOffset.QuadPart = 0;
831 ViewSize = 0;
832 Snapshot = NULL;
833
834 Status = NtMapViewOfSection(hSnapshot,
835 NtCurrentProcess(),
836 (PVOID*)&Snapshot,
837 0,
838 0,
839 &SOffset,
840 &ViewSize,
841 ViewShare,
842 0,
843 PAGE_READWRITE);
844 if(NT_SUCCESS(Status))
845 {
846 BOOL Ret;
847
848 if(Snapshot->ProcessListCount > 0)
849 {
850 LPPROCESSENTRY32W Entries = (LPPROCESSENTRY32W)OffsetToPtr(Snapshot, Snapshot->ProcessListOffset);
851
852 Snapshot->ProcessListIndex = 1;
853 RtlCopyMemory(lppe, &Entries[0], sizeof(PROCESSENTRY32W));
854 Ret = TRUE;
855 }
856 else
857 {
858
859 SetLastError(ERROR_NO_MORE_FILES);
860 Ret = FALSE;
861 }
862
863 NtUnmapViewOfSection(NtCurrentProcess(), (PVOID)Snapshot);
864 return Ret;
865 }
866
867 SetLastErrorByStatus(Status);
868 return FALSE;
869 }
870
871
872 /*
873 * @implemented
874 */
875 BOOL
876 STDCALL
877 Process32Next(HANDLE hSnapshot, LPPROCESSENTRY32 lppe)
878 {
879 PROCESSENTRY32W pe;
880 BOOL Ret;
881
882 CHECK_PARAM_SIZEA(lppe, sizeof(PROCESSENTRY32));
883
884 pe.dwSize = sizeof(PROCESSENTRY32W);
885
886 Ret = Process32NextW(hSnapshot, &pe);
887 if(Ret)
888 {
889 lppe->cntUsage = pe.cntUsage;
890 lppe->th32ProcessID = pe.th32ProcessID;
891 lppe->th32DefaultHeapID = pe.th32DefaultHeapID;
892 lppe->th32ModuleID = pe.th32ModuleID;
893 lppe->cntThreads = pe.cntThreads;
894 lppe->th32ParentProcessID = pe.th32ParentProcessID;
895 lppe->pcPriClassBase = pe.pcPriClassBase;
896 lppe->dwFlags = pe.dwFlags;
897
898 WideCharToMultiByte(CP_ACP, 0, pe.szExeFile, -1, lppe->szExeFile, sizeof(lppe->szExeFile), 0, 0);
899 }
900
901 return Ret;
902 }
903
904
905 /*
906 * @implemented
907 */
908 BOOL
909 STDCALL
910 Process32NextW(HANDLE hSnapshot, LPPROCESSENTRY32W lppe)
911 {
912 PTH32SNAPSHOT Snapshot;
913 LARGE_INTEGER SOffset;
914 ULONG ViewSize;
915 NTSTATUS Status;
916
917 CHECK_PARAM_SIZE(lppe, sizeof(PROCESSENTRY32W));
918
919 SOffset.QuadPart = 0;
920 ViewSize = 0;
921 Snapshot = NULL;
922
923 Status = NtMapViewOfSection(hSnapshot,
924 NtCurrentProcess(),
925 (PVOID*)&Snapshot,
926 0,
927 0,
928 &SOffset,
929 &ViewSize,
930 ViewShare,
931 0,
932 PAGE_READWRITE);
933 if(NT_SUCCESS(Status))
934 {
935 BOOL Ret;
936
937 if(Snapshot->ProcessListCount > 0 &&
938 Snapshot->ProcessListIndex < Snapshot->ProcessListCount)
939 {
940 LPPROCESSENTRY32W Entries = (LPPROCESSENTRY32W)OffsetToPtr(Snapshot, Snapshot->ProcessListOffset);
941 RtlCopyMemory(lppe, &Entries[Snapshot->ProcessListIndex++], sizeof(PROCESSENTRY32W));
942 Ret = TRUE;
943 }
944 else
945 {
946 SetLastError(ERROR_NO_MORE_FILES);
947 Ret = FALSE;
948 }
949
950 NtUnmapViewOfSection(NtCurrentProcess(), (PVOID)Snapshot);
951 return Ret;
952 }
953
954 SetLastErrorByStatus(Status);
955 return FALSE;
956 }
957
958
959 /*
960 * @implemented
961 */
962 BOOL
963 STDCALL
964 Thread32First(HANDLE hSnapshot, LPTHREADENTRY32 lpte)
965 {
966 PTH32SNAPSHOT Snapshot;
967 LARGE_INTEGER SOffset;
968 ULONG ViewSize;
969 NTSTATUS Status;
970
971 CHECK_PARAM_SIZE(lpte, sizeof(THREADENTRY32));
972
973 SOffset.QuadPart = 0;
974 ViewSize = 0;
975 Snapshot = NULL;
976
977 Status = NtMapViewOfSection(hSnapshot,
978 NtCurrentProcess(),
979 (PVOID*)&Snapshot,
980 0,
981 0,
982 &SOffset,
983 &ViewSize,
984 ViewShare,
985 0,
986 PAGE_READWRITE);
987 if(NT_SUCCESS(Status))
988 {
989 BOOL Ret;
990
991 if(Snapshot->ThreadListCount > 0)
992 {
993 LPTHREADENTRY32 Entries = (LPTHREADENTRY32)OffsetToPtr(Snapshot, Snapshot->ThreadListOffset);
994 Snapshot->ThreadListIndex = 1;
995 RtlCopyMemory(lpte, &Entries[0], sizeof(THREADENTRY32));
996 Ret = TRUE;
997 }
998 else
999 {
1000 SetLastError(ERROR_NO_MORE_FILES);
1001 Ret = FALSE;
1002 }
1003
1004 NtUnmapViewOfSection(NtCurrentProcess(), (PVOID)Snapshot);
1005 return Ret;
1006 }
1007
1008 SetLastErrorByStatus(Status);
1009 return FALSE;
1010 }
1011
1012
1013 /*
1014 * @implemented
1015 */
1016 BOOL
1017 STDCALL
1018 Thread32Next(HANDLE hSnapshot, LPTHREADENTRY32 lpte)
1019 {
1020 PTH32SNAPSHOT Snapshot;
1021 LARGE_INTEGER SOffset;
1022 ULONG ViewSize;
1023 NTSTATUS Status;
1024
1025 CHECK_PARAM_SIZE(lpte, sizeof(THREADENTRY32));
1026
1027 SOffset.QuadPart = 0;
1028 ViewSize = 0;
1029 Snapshot = NULL;
1030
1031 Status = NtMapViewOfSection(hSnapshot,
1032 NtCurrentProcess(),
1033 (PVOID*)&Snapshot,
1034 0,
1035 0,
1036 &SOffset,
1037 &ViewSize,
1038 ViewShare,
1039 0,
1040 PAGE_READWRITE);
1041 if(NT_SUCCESS(Status))
1042 {
1043 BOOL Ret;
1044
1045 if(Snapshot->ThreadListCount > 0 &&
1046 Snapshot->ThreadListIndex < Snapshot->ThreadListCount)
1047 {
1048 LPTHREADENTRY32 Entries = (LPTHREADENTRY32)OffsetToPtr(Snapshot, Snapshot->ThreadListOffset);
1049 RtlCopyMemory(lpte, &Entries[Snapshot->ThreadListIndex++], sizeof(THREADENTRY32));
1050 Ret = TRUE;
1051 }
1052 else
1053 {
1054 SetLastError(ERROR_NO_MORE_FILES);
1055 Ret = FALSE;
1056 }
1057
1058 NtUnmapViewOfSection(NtCurrentProcess(), (PVOID)Snapshot);
1059 return Ret;
1060 }
1061
1062 SetLastErrorByStatus(Status);
1063 return FALSE;
1064 }
1065
1066
1067 /*
1068 * @implemented
1069 */
1070 BOOL
1071 STDCALL
1072 Toolhelp32ReadProcessMemory(DWORD th32ProcessID, LPCVOID lpBaseAddress,
1073 LPVOID lpBuffer, DWORD cbRead, LPDWORD lpNumberOfBytesRead)
1074 {
1075 HANDLE hProcess = OpenProcess(PROCESS_VM_READ, FALSE, th32ProcessID);
1076 if(hProcess != NULL)
1077 {
1078 BOOL Ret = ReadProcessMemory(hProcess, lpBaseAddress, lpBuffer, cbRead, lpNumberOfBytesRead);
1079 CloseHandle(hProcess);
1080 return Ret;
1081 }
1082
1083 return FALSE;
1084 }
1085
1086
1087 /*
1088 * @implemented
1089 */
1090 HANDLE
1091 STDCALL
1092 CreateToolhelp32Snapshot(DWORD dwFlags, DWORD th32ProcessID)
1093 {
1094 PDEBUG_BUFFER HeapDebug, ModuleDebug;
1095 PVOID ProcThrdInfo;
1096 ULONG ProcThrdInfoSize;
1097 HANDLE hSnapShotSection;
1098 NTSTATUS Status;
1099
1100 if(th32ProcessID == 0)
1101 {
1102 th32ProcessID = GetCurrentProcessId();
1103 }
1104
1105 /*
1106 * Get all information required for the snapshot
1107 */
1108 Status = TH32CreateSnapshot(dwFlags,
1109 th32ProcessID,
1110 &HeapDebug,
1111 &ModuleDebug,
1112 &ProcThrdInfo,
1113 &ProcThrdInfoSize);
1114 if(!NT_SUCCESS(Status))
1115 {
1116 SetLastErrorByStatus(Status);
1117 return NULL;
1118 }
1119
1120 /*
1121 * Create a section handle and initialize the collected information
1122 */
1123 Status = TH32CreateSnapshotSectionInitialize(dwFlags,
1124 th32ProcessID,
1125 HeapDebug,
1126 ModuleDebug,
1127 ProcThrdInfo,
1128 &hSnapShotSection);
1129
1130 /*
1131 * Free the temporarily allocated memory to collect all information
1132 */
1133 TH32FreeAllocatedResources(HeapDebug,
1134 ModuleDebug,
1135 ProcThrdInfo,
1136 ProcThrdInfoSize);
1137
1138 if(!NT_SUCCESS(Status))
1139 {
1140 SetLastErrorByStatus(Status);
1141 return NULL;
1142 }
1143
1144 return hSnapShotSection;
1145 }
1146
1147 /* EOF */