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