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