fixed typo
[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.8 2004/10/31 19:24:31 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 *ModuleDebug);
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 lstrcpynW(ProcessListEntry->szExeFile,
404 ProcessInfo->ImageName.Buffer,
405 min(ProcessInfo->ImageName.Length, sizeof(ProcessListEntry->szExeFile) / sizeof(ProcessListEntry->szExeFile[0])));
406 }
407 else
408 {
409 lstrcpyW(ProcessListEntry->szExeFile, L"[System Process]");
410 }
411
412 ProcessListEntry++;
413
414 ProcOffset = ProcessInfo->NextEntryOffset;
415 } while(ProcOffset != 0);
416
417 DataOffset += nProcesses * sizeof(PROCESSENTRY32W);
418 }
419
420 /* initialize the thread list */
421 if(dwFlags & TH32CS_SNAPTHREAD)
422 {
423 ULONG ProcOffset = 0;
424
425 Snapshot->ThreadListCount = nThreads;
426 Snapshot->ThreadListOffset = DataOffset;
427 ThreadListEntry = (LPTHREADENTRY32)OffsetToPtr(Snapshot, DataOffset);
428 ProcessInfo = (PSYSTEM_PROCESS_INFORMATION)ProcThrdInfo;
429 do
430 {
431 PSYSTEM_THREAD_INFORMATION ThreadInfo;
432 ULONG n;
433
434 ProcessInfo = (PSYSTEM_PROCESS_INFORMATION)((ULONG_PTR)ProcessInfo + ProcOffset);
435 ThreadInfo = (PSYSTEM_THREAD_INFORMATION)(ProcessInfo + 1);
436
437 for(n = 0; n < ProcessInfo->NumberOfThreads; n++)
438 {
439 ThreadListEntry->dwSize = sizeof(THREADENTRY32);
440 ThreadListEntry->cntUsage = 0; /* no longer used */
441 ThreadListEntry->th32ThreadID = (ULONG)ThreadInfo->ClientId.UniqueThread;
442 ThreadListEntry->th32OwnerProcessID = (ULONG)ThreadInfo->ClientId.UniqueProcess;
443 ThreadListEntry->tpBasePri = ThreadInfo->BasePriority;
444 ThreadListEntry->tpDeltaPri = 0; /* no longer used */
445 ThreadListEntry->dwFlags = 0; /* no longer used */
446
447 ThreadInfo++;
448 ThreadListEntry++;
449 }
450
451 ProcOffset = ProcessInfo->NextEntryOffset;
452 } while(ProcOffset != 0);
453 }
454
455 /*
456 * We're done, unmap the view and return the section handle
457 */
458
459 Status = NtUnmapViewOfSection(NtCurrentProcess(), (PVOID)Snapshot);
460
461 if(NT_SUCCESS(Status))
462 {
463 *SectionHandle = hSection;
464 }
465 else
466 {
467 NtClose(hSection);
468 }
469
470 return Status;
471 }
472
473 /* PUBLIC FUNCTIONS ***********************************************************/
474
475 /*
476 * @unimplemented
477 */
478 BOOL
479 STDCALL
480 Heap32First(LPHEAPENTRY32 lphe, DWORD th32ProcessID, DWORD th32HeapID)
481 {
482 CHECK_PARAM_SIZE(lphe, sizeof(HEAPENTRY32));
483
484 SetLastError(ERROR_NO_MORE_FILES);
485 return FALSE;
486 }
487
488
489 /*
490 * @unimplemented
491 */
492 BOOL
493 STDCALL
494 Heap32Next(LPHEAPENTRY32 lphe)
495 {
496 CHECK_PARAM_SIZE(lphe, sizeof(HEAPENTRY32));
497
498 SetLastError(ERROR_NO_MORE_FILES);
499 return FALSE;
500 }
501
502
503 /*
504 * @implemented
505 */
506 BOOL
507 STDCALL
508 Heap32ListFirst(HANDLE hSnapshot, LPHEAPLIST32 lphl)
509 {
510 PTH32SNAPSHOT Snapshot;
511 LARGE_INTEGER SOffset;
512 ULONG ViewSize;
513 NTSTATUS Status;
514
515 CHECK_PARAM_SIZE(lphl, sizeof(HEAPLIST32));
516
517 SOffset.QuadPart = 0;
518 ViewSize = 0;
519 Snapshot = NULL;
520
521 Status = NtMapViewOfSection(hSnapshot,
522 NtCurrentProcess(),
523 (PVOID*)&Snapshot,
524 0,
525 0,
526 &SOffset,
527 &ViewSize,
528 ViewShare,
529 0,
530 PAGE_READWRITE);
531 if(NT_SUCCESS(Status))
532 {
533 BOOL Ret;
534
535 if(Snapshot->ModuleListCount > 0)
536 {
537 LPHEAPLIST32 Entries = (LPHEAPLIST32)OffsetToPtr(Snapshot, Snapshot->HeapListOffset);
538 Snapshot->HeapListIndex = 1;
539 RtlCopyMemory(lphl, &Entries[0], sizeof(HEAPLIST32));
540 Ret = TRUE;
541 }
542 else
543 {
544 SetLastError(ERROR_NO_MORE_FILES);
545 Ret = FALSE;
546 }
547
548 NtUnmapViewOfSection(NtCurrentProcess(), (PVOID)Snapshot);
549 return Ret;
550 }
551
552 SetLastErrorByStatus(Status);
553 return FALSE;
554 }
555
556
557 /*
558 * @implemented
559 */
560 BOOL
561 STDCALL
562 Heap32ListNext(HANDLE hSnapshot, LPHEAPLIST32 lphl)
563 {
564 PTH32SNAPSHOT Snapshot;
565 LARGE_INTEGER SOffset;
566 ULONG ViewSize;
567 NTSTATUS Status;
568
569 CHECK_PARAM_SIZE(lphl, sizeof(HEAPLIST32));
570
571 SOffset.QuadPart = 0;
572 ViewSize = 0;
573 Snapshot = NULL;
574
575 Status = NtMapViewOfSection(hSnapshot,
576 NtCurrentProcess(),
577 (PVOID*)&Snapshot,
578 0,
579 0,
580 &SOffset,
581 &ViewSize,
582 ViewShare,
583 0,
584 PAGE_READWRITE);
585 if(NT_SUCCESS(Status))
586 {
587 BOOL Ret;
588
589 if(Snapshot->HeapListCount > 0 &&
590 Snapshot->HeapListIndex < Snapshot->HeapListCount)
591 {
592 LPHEAPLIST32 Entries = (LPHEAPLIST32)OffsetToPtr(Snapshot, Snapshot->HeapListOffset);
593 RtlCopyMemory(lphl, &Entries[Snapshot->HeapListIndex++], sizeof(HEAPLIST32));
594 Ret = TRUE;
595 }
596 else
597 {
598 SetLastError(ERROR_NO_MORE_FILES);
599 Ret = FALSE;
600 }
601
602 NtUnmapViewOfSection(NtCurrentProcess(), (PVOID)Snapshot);
603 return Ret;
604 }
605
606 SetLastErrorByStatus(Status);
607 return FALSE;
608 }
609
610
611 /*
612 * @implemented
613 */
614 BOOL
615 STDCALL
616 Module32First(HANDLE hSnapshot, LPMODULEENTRY32 lpme)
617 {
618 MODULEENTRY32W me;
619 BOOL Ret;
620
621 CHECK_PARAM_SIZEA(lpme, sizeof(MODULEENTRY32));
622
623 me.dwSize = sizeof(MODULEENTRY32W);
624
625 Ret = Module32FirstW(hSnapshot, &me);
626 if(Ret)
627 {
628 lpme->th32ModuleID = me.th32ModuleID;
629 lpme->th32ProcessID = me.th32ProcessID;
630 lpme->GlblcntUsage = me.GlblcntUsage;
631 lpme->ProccntUsage = me.ProccntUsage;
632 lpme->modBaseAddr = me.modBaseAddr;
633 lpme->modBaseSize = me.modBaseSize;
634 lpme->hModule = me.hModule;
635
636 WideCharToMultiByte(CP_ACP, 0, me.szModule, -1, lpme->szModule, sizeof(lpme->szModule), 0, 0);
637 WideCharToMultiByte(CP_ACP, 0, me.szExePath, -1, lpme->szExePath, sizeof(lpme->szExePath), 0, 0);
638 }
639
640 return Ret;
641 }
642
643
644 /*
645 * @implemented
646 */
647 BOOL
648 STDCALL
649 Module32FirstW(HANDLE hSnapshot, LPMODULEENTRY32W lpme)
650 {
651 PTH32SNAPSHOT Snapshot;
652 LARGE_INTEGER SOffset;
653 ULONG ViewSize;
654 NTSTATUS Status;
655
656 CHECK_PARAM_SIZE(lpme, sizeof(MODULEENTRY32W));
657
658 SOffset.QuadPart = 0;
659 ViewSize = 0;
660 Snapshot = NULL;
661
662 Status = NtMapViewOfSection(hSnapshot,
663 NtCurrentProcess(),
664 (PVOID*)&Snapshot,
665 0,
666 0,
667 &SOffset,
668 &ViewSize,
669 ViewShare,
670 0,
671 PAGE_READWRITE);
672 if(NT_SUCCESS(Status))
673 {
674 BOOL Ret;
675
676 if(Snapshot->ModuleListCount > 0)
677 {
678 LPMODULEENTRY32W Entries = (LPMODULEENTRY32W)OffsetToPtr(Snapshot, Snapshot->ModuleListOffset);
679 Snapshot->ModuleListIndex = 1;
680 RtlCopyMemory(lpme, &Entries[0], sizeof(MODULEENTRY32W));
681 Ret = TRUE;
682 }
683 else
684 {
685 SetLastError(ERROR_NO_MORE_FILES);
686 Ret = FALSE;
687 }
688
689 NtUnmapViewOfSection(NtCurrentProcess(), (PVOID)Snapshot);
690 return Ret;
691 }
692
693 SetLastErrorByStatus(Status);
694 return FALSE;
695 }
696
697
698 /*
699 * @implemented
700 */
701 BOOL
702 STDCALL
703 Module32Next(HANDLE hSnapshot, LPMODULEENTRY32 lpme)
704 {
705 MODULEENTRY32W me;
706 BOOL Ret;
707
708 CHECK_PARAM_SIZEA(lpme, sizeof(MODULEENTRY32));
709
710 me.dwSize = sizeof(MODULEENTRY32W);
711
712 Ret = Module32NextW(hSnapshot, &me);
713 if(Ret)
714 {
715 lpme->th32ModuleID = me.th32ModuleID;
716 lpme->th32ProcessID = me.th32ProcessID;
717 lpme->GlblcntUsage = me.GlblcntUsage;
718 lpme->ProccntUsage = me.ProccntUsage;
719 lpme->modBaseAddr = me.modBaseAddr;
720 lpme->modBaseSize = me.modBaseSize;
721 lpme->hModule = me.hModule;
722
723 WideCharToMultiByte(CP_ACP, 0, me.szModule, -1, lpme->szModule, sizeof(lpme->szModule), 0, 0);
724 WideCharToMultiByte(CP_ACP, 0, me.szExePath, -1, lpme->szExePath, sizeof(lpme->szExePath), 0, 0);
725 }
726
727 return Ret;
728 }
729
730
731 BOOL
732 STDCALL
733 Module32NextW(HANDLE hSnapshot, LPMODULEENTRY32W lpme)
734 {
735 PTH32SNAPSHOT Snapshot;
736 LARGE_INTEGER SOffset;
737 ULONG ViewSize;
738 NTSTATUS Status;
739
740 CHECK_PARAM_SIZE(lpme, sizeof(MODULEENTRY32W));
741
742 SOffset.QuadPart = 0;
743 ViewSize = 0;
744 Snapshot = NULL;
745
746 Status = NtMapViewOfSection(hSnapshot,
747 NtCurrentProcess(),
748 (PVOID*)&Snapshot,
749 0,
750 0,
751 &SOffset,
752 &ViewSize,
753 ViewShare,
754 0,
755 PAGE_READWRITE);
756 if(NT_SUCCESS(Status))
757 {
758 BOOL Ret;
759
760 if(Snapshot->ModuleListCount > 0 &&
761 Snapshot->ModuleListIndex < Snapshot->ModuleListCount)
762 {
763 LPMODULEENTRY32W Entries = (LPMODULEENTRY32W)OffsetToPtr(Snapshot, Snapshot->ModuleListOffset);
764 RtlCopyMemory(lpme, &Entries[Snapshot->ProcessListIndex++], sizeof(MODULEENTRY32W));
765 Ret = TRUE;
766 }
767 else
768 {
769 SetLastError(ERROR_NO_MORE_FILES);
770 Ret = FALSE;
771 }
772
773 NtUnmapViewOfSection(NtCurrentProcess(), (PVOID)Snapshot);
774 return Ret;
775 }
776
777 SetLastErrorByStatus(Status);
778 return FALSE;
779 }
780
781
782 /*
783 * @implemented
784 */
785 BOOL
786 STDCALL
787 Process32First(HANDLE hSnapshot, LPPROCESSENTRY32 lppe)
788 {
789 PROCESSENTRY32W pe;
790 BOOL Ret;
791
792 CHECK_PARAM_SIZEA(lppe, sizeof(PROCESSENTRY32));
793
794 pe.dwSize = sizeof(PROCESSENTRY32W);
795
796 Ret = Process32FirstW(hSnapshot, &pe);
797 if(Ret)
798 {
799 lppe->cntUsage = pe.cntUsage;
800 lppe->th32ProcessID = pe.th32ProcessID;
801 lppe->th32DefaultHeapID = pe.th32DefaultHeapID;
802 lppe->th32ModuleID = pe.th32ModuleID;
803 lppe->cntThreads = pe.cntThreads;
804 lppe->th32ParentProcessID = pe.th32ParentProcessID;
805 lppe->pcPriClassBase = pe.pcPriClassBase;
806 lppe->dwFlags = pe.dwFlags;
807
808 WideCharToMultiByte(CP_ACP, 0, pe.szExeFile, -1, lppe->szExeFile, sizeof(lppe->szExeFile), 0, 0);
809 }
810
811 return Ret;
812 }
813
814
815 /*
816 * @implemented
817 */
818 BOOL
819 STDCALL
820 Process32FirstW(HANDLE hSnapshot, LPPROCESSENTRY32W lppe)
821 {
822 PTH32SNAPSHOT Snapshot;
823 LARGE_INTEGER SOffset;
824 ULONG ViewSize;
825 NTSTATUS Status;
826
827 CHECK_PARAM_SIZE(lppe, sizeof(PROCESSENTRY32W));
828
829 SOffset.QuadPart = 0;
830 ViewSize = 0;
831 Snapshot = NULL;
832
833 Status = NtMapViewOfSection(hSnapshot,
834 NtCurrentProcess(),
835 (PVOID*)&Snapshot,
836 0,
837 0,
838 &SOffset,
839 &ViewSize,
840 ViewShare,
841 0,
842 PAGE_READWRITE);
843 if(NT_SUCCESS(Status))
844 {
845 BOOL Ret;
846
847 if(Snapshot->ProcessListCount > 0)
848 {
849 LPPROCESSENTRY32W Entries = (LPPROCESSENTRY32W)OffsetToPtr(Snapshot, Snapshot->ProcessListOffset);
850
851 Snapshot->ProcessListIndex = 1;
852 RtlCopyMemory(lppe, &Entries[0], sizeof(PROCESSENTRY32W));
853 Ret = TRUE;
854 }
855 else
856 {
857
858 SetLastError(ERROR_NO_MORE_FILES);
859 Ret = FALSE;
860 }
861
862 NtUnmapViewOfSection(NtCurrentProcess(), (PVOID)Snapshot);
863 return Ret;
864 }
865
866 SetLastErrorByStatus(Status);
867 return FALSE;
868 }
869
870
871 /*
872 * @implemented
873 */
874 BOOL
875 STDCALL
876 Process32Next(HANDLE hSnapshot, LPPROCESSENTRY32 lppe)
877 {
878 PROCESSENTRY32W pe;
879 BOOL Ret;
880
881 CHECK_PARAM_SIZEA(lppe, sizeof(PROCESSENTRY32));
882
883 pe.dwSize = sizeof(PROCESSENTRY32W);
884
885 Ret = Process32NextW(hSnapshot, &pe);
886 if(Ret)
887 {
888 lppe->cntUsage = pe.cntUsage;
889 lppe->th32ProcessID = pe.th32ProcessID;
890 lppe->th32DefaultHeapID = pe.th32DefaultHeapID;
891 lppe->th32ModuleID = pe.th32ModuleID;
892 lppe->cntThreads = pe.cntThreads;
893 lppe->th32ParentProcessID = pe.th32ParentProcessID;
894 lppe->pcPriClassBase = pe.pcPriClassBase;
895 lppe->dwFlags = pe.dwFlags;
896
897 WideCharToMultiByte(CP_ACP, 0, pe.szExeFile, -1, lppe->szExeFile, sizeof(lppe->szExeFile), 0, 0);
898 }
899
900 return Ret;
901 }
902
903
904 /*
905 * @implemented
906 */
907 BOOL
908 STDCALL
909 Process32NextW(HANDLE hSnapshot, LPPROCESSENTRY32W lppe)
910 {
911 PTH32SNAPSHOT Snapshot;
912 LARGE_INTEGER SOffset;
913 ULONG ViewSize;
914 NTSTATUS Status;
915
916 CHECK_PARAM_SIZE(lppe, sizeof(PROCESSENTRY32W));
917
918 SOffset.QuadPart = 0;
919 ViewSize = 0;
920 Snapshot = NULL;
921
922 Status = NtMapViewOfSection(hSnapshot,
923 NtCurrentProcess(),
924 (PVOID*)&Snapshot,
925 0,
926 0,
927 &SOffset,
928 &ViewSize,
929 ViewShare,
930 0,
931 PAGE_READWRITE);
932 if(NT_SUCCESS(Status))
933 {
934 BOOL Ret;
935
936 if(Snapshot->ProcessListCount > 0 &&
937 Snapshot->ProcessListIndex < Snapshot->ProcessListCount)
938 {
939 LPPROCESSENTRY32W Entries = (LPPROCESSENTRY32W)OffsetToPtr(Snapshot, Snapshot->ProcessListOffset);
940 RtlCopyMemory(lppe, &Entries[Snapshot->ProcessListIndex++], sizeof(PROCESSENTRY32W));
941 Ret = TRUE;
942 }
943 else
944 {
945 SetLastError(ERROR_NO_MORE_FILES);
946 Ret = FALSE;
947 }
948
949 NtUnmapViewOfSection(NtCurrentProcess(), (PVOID)Snapshot);
950 return Ret;
951 }
952
953 SetLastErrorByStatus(Status);
954 return FALSE;
955 }
956
957
958 /*
959 * @implemented
960 */
961 BOOL
962 STDCALL
963 Thread32First(HANDLE hSnapshot, LPTHREADENTRY32 lpte)
964 {
965 PTH32SNAPSHOT Snapshot;
966 LARGE_INTEGER SOffset;
967 ULONG ViewSize;
968 NTSTATUS Status;
969
970 CHECK_PARAM_SIZE(lpte, sizeof(THREADENTRY32));
971
972 SOffset.QuadPart = 0;
973 ViewSize = 0;
974 Snapshot = NULL;
975
976 Status = NtMapViewOfSection(hSnapshot,
977 NtCurrentProcess(),
978 (PVOID*)&Snapshot,
979 0,
980 0,
981 &SOffset,
982 &ViewSize,
983 ViewShare,
984 0,
985 PAGE_READWRITE);
986 if(NT_SUCCESS(Status))
987 {
988 BOOL Ret;
989
990 if(Snapshot->ThreadListCount > 0)
991 {
992 LPTHREADENTRY32 Entries = (LPTHREADENTRY32)OffsetToPtr(Snapshot, Snapshot->ThreadListOffset);
993 Snapshot->ThreadListIndex = 1;
994 RtlCopyMemory(lpte, &Entries[0], sizeof(THREADENTRY32));
995 Ret = TRUE;
996 }
997 else
998 {
999 SetLastError(ERROR_NO_MORE_FILES);
1000 Ret = FALSE;
1001 }
1002
1003 NtUnmapViewOfSection(NtCurrentProcess(), (PVOID)Snapshot);
1004 return Ret;
1005 }
1006
1007 SetLastErrorByStatus(Status);
1008 return FALSE;
1009 }
1010
1011
1012 /*
1013 * @implemented
1014 */
1015 BOOL
1016 STDCALL
1017 Thread32Next(HANDLE hSnapshot, LPTHREADENTRY32 lpte)
1018 {
1019 PTH32SNAPSHOT Snapshot;
1020 LARGE_INTEGER SOffset;
1021 ULONG ViewSize;
1022 NTSTATUS Status;
1023
1024 CHECK_PARAM_SIZE(lpte, sizeof(THREADENTRY32));
1025
1026 SOffset.QuadPart = 0;
1027 ViewSize = 0;
1028 Snapshot = NULL;
1029
1030 Status = NtMapViewOfSection(hSnapshot,
1031 NtCurrentProcess(),
1032 (PVOID*)&Snapshot,
1033 0,
1034 0,
1035 &SOffset,
1036 &ViewSize,
1037 ViewShare,
1038 0,
1039 PAGE_READWRITE);
1040 if(NT_SUCCESS(Status))
1041 {
1042 BOOL Ret;
1043
1044 if(Snapshot->ThreadListCount > 0 &&
1045 Snapshot->ThreadListIndex < Snapshot->ThreadListCount)
1046 {
1047 LPTHREADENTRY32 Entries = (LPTHREADENTRY32)OffsetToPtr(Snapshot, Snapshot->ThreadListOffset);
1048 RtlCopyMemory(lpte, &Entries[Snapshot->ThreadListIndex++], sizeof(THREADENTRY32));
1049 Ret = TRUE;
1050 }
1051 else
1052 {
1053 SetLastError(ERROR_NO_MORE_FILES);
1054 Ret = FALSE;
1055 }
1056
1057 NtUnmapViewOfSection(NtCurrentProcess(), (PVOID)Snapshot);
1058 return Ret;
1059 }
1060
1061 SetLastErrorByStatus(Status);
1062 return FALSE;
1063 }
1064
1065
1066 /*
1067 * @implemented
1068 */
1069 BOOL
1070 STDCALL
1071 Toolhelp32ReadProcessMemory(DWORD th32ProcessID, LPCVOID lpBaseAddress,
1072 LPVOID lpBuffer, DWORD cbRead, LPDWORD lpNumberOfBytesRead)
1073 {
1074 HANDLE hProcess = OpenProcess(PROCESS_VM_READ, FALSE, th32ProcessID);
1075 if(hProcess != NULL)
1076 {
1077 BOOL Ret = ReadProcessMemory(hProcess, lpBaseAddress, lpBuffer, cbRead, lpNumberOfBytesRead);
1078 CloseHandle(hProcess);
1079 return Ret;
1080 }
1081
1082 return FALSE;
1083 }
1084
1085
1086 /*
1087 * @implemented
1088 */
1089 HANDLE
1090 STDCALL
1091 CreateToolhelp32Snapshot(DWORD dwFlags, DWORD th32ProcessID)
1092 {
1093 PDEBUG_BUFFER HeapDebug, ModuleDebug;
1094 PVOID ProcThrdInfo;
1095 ULONG ProcThrdInfoSize;
1096 HANDLE hSnapShotSection;
1097 NTSTATUS Status;
1098
1099 if(th32ProcessID == 0)
1100 {
1101 th32ProcessID = GetCurrentProcessId();
1102 }
1103
1104 /*
1105 * Get all information required for the snapshot
1106 */
1107 Status = TH32CreateSnapshot(dwFlags,
1108 th32ProcessID,
1109 &HeapDebug,
1110 &ModuleDebug,
1111 &ProcThrdInfo,
1112 &ProcThrdInfoSize);
1113 if(!NT_SUCCESS(Status))
1114 {
1115 SetLastErrorByStatus(Status);
1116 return NULL;
1117 }
1118
1119 /*
1120 * Create a section handle and initialize the collected information
1121 */
1122 Status = TH32CreateSnapshotSectionInitialize(dwFlags,
1123 th32ProcessID,
1124 HeapDebug,
1125 ModuleDebug,
1126 ProcThrdInfo,
1127 &hSnapShotSection);
1128
1129 /*
1130 * Free the temporarily allocated memory which is no longer needed
1131 */
1132 TH32FreeAllocatedResources(HeapDebug,
1133 ModuleDebug,
1134 ProcThrdInfo,
1135 ProcThrdInfoSize);
1136
1137 if(!NT_SUCCESS(Status))
1138 {
1139 SetLastErrorByStatus(Status);
1140 return NULL;
1141 }
1142
1143 return hSnapShotSection;
1144 }
1145
1146 /* EOF */