Revert tree-restructure attempt: r66583, r66582, r66581, r66578, sauf ntdll changes...
[reactos.git] / reactos / dll / win32 / kernel32 / client / toolhelp.c
1 /*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS system libraries
4 * FILE: dll/win32/kernel32/misc/toolhelp.c
5 * PURPOSE: Toolhelp functions
6 * PROGRAMMER: Thomas Weidenmueller <w3seek@reactos.com>
7 * Robert Dickenson (robd@mok.lvcm.com)
8 *
9 * NOTES: Do NOT use the heap functions in here because they
10 * adulterate the heap statistics!
11 *
12 * UPDATE HISTORY:
13 * 10/30/2004 Implemented some parts (w3)
14 * Inspired by the book "Windows NT Native API"
15 * Created 05 January 2003 (robd)
16 */
17
18 #include <k32.h>
19
20 #define NDEBUG
21 #include <debug.h>
22
23 /* INTERNAL DEFINITIONS *******************************************************/
24
25 typedef struct _RTLP_HEAP_ENTRY
26 {
27 ULONG Size;
28 USHORT Flags;
29 USHORT Unknown1; /* FIXME */
30 ULONG Unknown2; /* FIXME */
31 PVOID Address;
32 } RTLP_HEAP_ENTRY, *PRTLP_HEAP_ENTRY;
33
34 #define CHECK_PARAM_SIZE(ptr, siz) \
35 if((ptr) == NULL || (ptr)->dwSize != (siz)) \
36 { \
37 SetLastError(ERROR_INVALID_PARAMETER); \
38 return FALSE; \
39 }
40
41 /*
42 * Tests in win showed that the dwSize field can be greater than the actual size
43 * of the structure for the ansi functions. I found this out by accidently
44 * forgetting to set the dwSize field in a test application and it just didn't
45 * work in ros but in win.
46 */
47
48 #define CHECK_PARAM_SIZEA(ptr, siz) \
49 if((ptr) == NULL || (ptr)->dwSize < (siz)) \
50 { \
51 SetLastError(ERROR_INVALID_PARAMETER); \
52 return FALSE; \
53 }
54
55 #define OffsetToPtr(Snapshot, Offset) \
56 ((ULONG_PTR)((Snapshot) + 1) + (ULONG_PTR)(Offset))
57
58 typedef struct _TH32SNAPSHOT
59 {
60 /* Heap list */
61 ULONG HeapListCount;
62 ULONG HeapListIndex;
63 ULONG_PTR HeapListOffset;
64 /* Module list */
65 ULONG ModuleListCount;
66 ULONG ModuleListIndex;
67 ULONG_PTR ModuleListOffset;
68 /* Process list */
69 ULONG ProcessListCount;
70 ULONG ProcessListIndex;
71 ULONG_PTR ProcessListOffset;
72 /* Thread list */
73 ULONG ThreadListCount;
74 ULONG ThreadListIndex;
75 ULONG_PTR ThreadListOffset;
76 } TH32SNAPSHOT, *PTH32SNAPSHOT;
77
78 /* INTERNAL FUNCTIONS *********************************************************/
79
80 static VOID
81 TH32FreeAllocatedResources(PRTL_DEBUG_INFORMATION HeapDebug,
82 PRTL_DEBUG_INFORMATION ModuleDebug,
83 PVOID ProcThrdInfo,
84 SIZE_T ProcThrdInfoSize)
85 {
86 if(HeapDebug != NULL)
87 {
88 RtlDestroyQueryDebugBuffer(HeapDebug);
89 }
90 if(ModuleDebug != NULL)
91 {
92 RtlDestroyQueryDebugBuffer(ModuleDebug);
93 }
94
95 if(ProcThrdInfo != NULL)
96 {
97 NtFreeVirtualMemory(NtCurrentProcess(),
98 &ProcThrdInfo,
99 &ProcThrdInfoSize,
100 MEM_RELEASE);
101 }
102 }
103
104 static NTSTATUS
105 TH32CreateSnapshot(DWORD dwFlags,
106 DWORD th32ProcessID,
107 PRTL_DEBUG_INFORMATION *HeapDebug,
108 PRTL_DEBUG_INFORMATION *ModuleDebug,
109 PVOID *ProcThrdInfo,
110 SIZE_T *ProcThrdInfoSize)
111 {
112 NTSTATUS Status = STATUS_SUCCESS;
113
114 *HeapDebug = NULL;
115 *ModuleDebug = NULL;
116 *ProcThrdInfo = NULL;
117 *ProcThrdInfoSize = 0;
118
119 /*
120 * Allocate the debug information for a heap snapshot
121 */
122 if(dwFlags & TH32CS_SNAPHEAPLIST)
123 {
124 *HeapDebug = RtlCreateQueryDebugBuffer(0, FALSE);
125 if(*HeapDebug != NULL)
126 {
127 Status = RtlQueryProcessDebugInformation(th32ProcessID,
128 RTL_DEBUG_QUERY_HEAPS,
129 *HeapDebug);
130 }
131 else
132 Status = STATUS_UNSUCCESSFUL;
133 }
134
135 /*
136 * Allocate the debug information for a module snapshot
137 */
138 if(dwFlags & TH32CS_SNAPMODULE &&
139 NT_SUCCESS(Status))
140 {
141 *ModuleDebug = RtlCreateQueryDebugBuffer(0, FALSE);
142 if(*ModuleDebug != NULL)
143 {
144 Status = RtlQueryProcessDebugInformation(th32ProcessID,
145 RTL_DEBUG_QUERY_MODULES,
146 *ModuleDebug);
147 }
148 else
149 Status = STATUS_UNSUCCESSFUL;
150 }
151
152 /*
153 * Allocate enough memory for the system's process list
154 */
155
156 if(dwFlags & (TH32CS_SNAPPROCESS | TH32CS_SNAPTHREAD) &&
157 NT_SUCCESS(Status))
158 {
159 for(;;)
160 {
161 (*ProcThrdInfoSize) += 0x10000;
162 Status = NtAllocateVirtualMemory(NtCurrentProcess(),
163 ProcThrdInfo,
164 0,
165 ProcThrdInfoSize,
166 MEM_COMMIT,
167 PAGE_READWRITE);
168 if(!NT_SUCCESS(Status))
169 {
170 break;
171 }
172
173 Status = NtQuerySystemInformation(SystemProcessInformation,
174 *ProcThrdInfo,
175 *ProcThrdInfoSize,
176 NULL);
177 if(Status == STATUS_INFO_LENGTH_MISMATCH)
178 {
179 NtFreeVirtualMemory(NtCurrentProcess(),
180 ProcThrdInfo,
181 ProcThrdInfoSize,
182 MEM_RELEASE);
183 *ProcThrdInfo = NULL;
184 }
185 else
186 {
187 break;
188 }
189 }
190 }
191
192 /*
193 * Free resources in case of failure!
194 */
195
196 if(!NT_SUCCESS(Status))
197 {
198 TH32FreeAllocatedResources(*HeapDebug,
199 *ModuleDebug,
200 *ProcThrdInfo,
201 *ProcThrdInfoSize);
202 }
203
204 return Status;
205 }
206
207 static NTSTATUS
208 TH32CreateSnapshotSectionInitialize(DWORD dwFlags,
209 DWORD th32ProcessID,
210 PRTL_DEBUG_INFORMATION HeapDebug,
211 PRTL_DEBUG_INFORMATION ModuleDebug,
212 PVOID ProcThrdInfo,
213 HANDLE *SectionHandle)
214 {
215 PSYSTEM_PROCESS_INFORMATION ProcessInfo;
216 LPHEAPLIST32 HeapListEntry;
217 LPMODULEENTRY32W ModuleListEntry;
218 LPPROCESSENTRY32W ProcessListEntry;
219 LPTHREADENTRY32 ThreadListEntry;
220 OBJECT_ATTRIBUTES ObjectAttributes;
221 LARGE_INTEGER SSize, SOffset;
222 HANDLE hSection;
223 PTH32SNAPSHOT Snapshot;
224 ULONG_PTR DataOffset;
225 SIZE_T ViewSize;
226 ULONG i, nProcesses = 0, nThreads = 0, nHeaps = 0, nModules = 0;
227 ULONG RequiredSnapshotSize = sizeof(TH32SNAPSHOT);
228 PRTL_PROCESS_HEAPS hi = NULL;
229 PRTL_PROCESS_MODULES mi = NULL;
230 NTSTATUS Status = STATUS_SUCCESS;
231
232 /*
233 * Determine the required size for the heap snapshot
234 */
235 if(dwFlags & TH32CS_SNAPHEAPLIST)
236 {
237 hi = (PRTL_PROCESS_HEAPS)HeapDebug->Heaps;
238 nHeaps = hi->NumberOfHeaps;
239 RequiredSnapshotSize += nHeaps * sizeof(HEAPLIST32);
240 }
241
242 /*
243 * Determine the required size for the module snapshot
244 */
245 if(dwFlags & TH32CS_SNAPMODULE)
246 {
247 mi = (PRTL_PROCESS_MODULES)ModuleDebug->Modules;
248 nModules = mi->NumberOfModules;
249 RequiredSnapshotSize += nModules * sizeof(MODULEENTRY32W);
250 }
251
252 /*
253 * Determine the required size for the processes and threads snapshot
254 */
255 if(dwFlags & (TH32CS_SNAPPROCESS | TH32CS_SNAPTHREAD))
256 {
257 ULONG ProcOffset = 0;
258
259 ProcessInfo = (PSYSTEM_PROCESS_INFORMATION)ProcThrdInfo;
260 do
261 {
262 ProcessInfo = (PSYSTEM_PROCESS_INFORMATION)((ULONG_PTR)ProcessInfo + ProcOffset);
263 nProcesses++;
264 nThreads += ProcessInfo->NumberOfThreads;
265 ProcOffset = ProcessInfo->NextEntryOffset;
266 } while(ProcOffset != 0);
267
268 if(dwFlags & TH32CS_SNAPPROCESS)
269 {
270 RequiredSnapshotSize += nProcesses * sizeof(PROCESSENTRY32W);
271 }
272 if(dwFlags & TH32CS_SNAPTHREAD)
273 {
274 RequiredSnapshotSize += nThreads * sizeof(THREADENTRY32);
275 }
276 }
277
278 /*
279 * Create and map the section
280 */
281
282 SSize.QuadPart = RequiredSnapshotSize;
283
284 InitializeObjectAttributes(&ObjectAttributes,
285 NULL,
286 ((dwFlags & TH32CS_INHERIT) ? OBJ_INHERIT : 0),
287 NULL,
288 NULL);
289
290 Status = NtCreateSection(&hSection,
291 SECTION_ALL_ACCESS,
292 &ObjectAttributes,
293 &SSize,
294 PAGE_READWRITE,
295 SEC_COMMIT,
296 NULL);
297 if(!NT_SUCCESS(Status))
298 {
299 return Status;
300 }
301
302 SOffset.QuadPart = 0;
303 ViewSize = 0;
304 Snapshot = NULL;
305
306 Status = NtMapViewOfSection(hSection,
307 NtCurrentProcess(),
308 (PVOID*)&Snapshot,
309 0,
310 0,
311 &SOffset,
312 &ViewSize,
313 ViewShare,
314 0,
315 PAGE_READWRITE);
316 if(!NT_SUCCESS(Status))
317 {
318 NtClose(hSection);
319 return Status;
320 }
321
322 RtlZeroMemory(Snapshot, sizeof(TH32SNAPSHOT));
323 DataOffset = 0;
324
325 /*
326 * Initialize the section data and fill it with all the data we collected
327 */
328
329 /* initialize the heap list */
330 if(dwFlags & TH32CS_SNAPHEAPLIST)
331 {
332 Snapshot->HeapListCount = nHeaps;
333 Snapshot->HeapListOffset = DataOffset;
334 HeapListEntry = (LPHEAPLIST32)OffsetToPtr(Snapshot, DataOffset);
335 for(i = 0; i < nHeaps; i++)
336 {
337 HeapListEntry->dwSize = sizeof(HEAPLIST32);
338 HeapListEntry->th32ProcessID = th32ProcessID;
339 HeapListEntry->th32HeapID = (ULONG_PTR)hi->Heaps[i].BaseAddress;
340 HeapListEntry->dwFlags = hi->Heaps[i].Flags;
341
342 HeapListEntry++;
343 }
344
345 DataOffset += hi->NumberOfHeaps * sizeof(HEAPLIST32);
346 }
347
348 /* initialize the module list */
349 if(dwFlags & TH32CS_SNAPMODULE)
350 {
351 Snapshot->ModuleListCount = nModules;
352 Snapshot->ModuleListOffset = DataOffset;
353 ModuleListEntry = (LPMODULEENTRY32W)OffsetToPtr(Snapshot, DataOffset);
354 for(i = 0; i < nModules; i++)
355 {
356 ModuleListEntry->dwSize = sizeof(MODULEENTRY32W);
357 ModuleListEntry->th32ModuleID = 1; /* no longer used, always set to one! */
358 ModuleListEntry->th32ProcessID = th32ProcessID;
359 ModuleListEntry->GlblcntUsage = mi->Modules[i].LoadCount;
360 ModuleListEntry->ProccntUsage = mi->Modules[i].LoadCount;
361 ModuleListEntry->modBaseAddr = (BYTE*)mi->Modules[i].ImageBase;
362 ModuleListEntry->modBaseSize = mi->Modules[i].ImageSize;
363 ModuleListEntry->hModule = (HMODULE)mi->Modules[i].ImageBase;
364
365 MultiByteToWideChar(CP_ACP,
366 0,
367 &mi->Modules[i].FullPathName[mi->Modules[i].OffsetToFileName],
368 -1,
369 ModuleListEntry->szModule,
370 sizeof(ModuleListEntry->szModule) / sizeof(ModuleListEntry->szModule[0]));
371
372 MultiByteToWideChar(CP_ACP,
373 0,
374 mi->Modules[i].FullPathName,
375 -1,
376 ModuleListEntry->szExePath,
377 sizeof(ModuleListEntry->szExePath) / sizeof(ModuleListEntry->szExePath[0]));
378
379 ModuleListEntry++;
380 }
381
382 DataOffset += mi->NumberOfModules * sizeof(MODULEENTRY32W);
383 }
384
385 /* initialize the process list */
386 if(dwFlags & TH32CS_SNAPPROCESS)
387 {
388 ULONG ProcOffset = 0;
389
390 Snapshot->ProcessListCount = nProcesses;
391 Snapshot->ProcessListOffset = DataOffset;
392 ProcessListEntry = (LPPROCESSENTRY32W)OffsetToPtr(Snapshot, DataOffset);
393 ProcessInfo = (PSYSTEM_PROCESS_INFORMATION)ProcThrdInfo;
394 do
395 {
396 ProcessInfo = (PSYSTEM_PROCESS_INFORMATION)((ULONG_PTR)ProcessInfo + ProcOffset);
397
398 ProcessListEntry->dwSize = sizeof(PROCESSENTRY32W);
399 ProcessListEntry->cntUsage = 0; /* no longer used */
400 ProcessListEntry->th32ProcessID = (ULONG_PTR)ProcessInfo->UniqueProcessId;
401 ProcessListEntry->th32DefaultHeapID = 0; /* no longer used */
402 ProcessListEntry->th32ModuleID = 0; /* no longer used */
403 ProcessListEntry->cntThreads = ProcessInfo->NumberOfThreads;
404 ProcessListEntry->th32ParentProcessID = (ULONG_PTR)ProcessInfo->InheritedFromUniqueProcessId;
405 ProcessListEntry->pcPriClassBase = ProcessInfo->BasePriority;
406 ProcessListEntry->dwFlags = 0; /* no longer used */
407 if(ProcessInfo->ImageName.Buffer != NULL)
408 {
409 ULONG ExeFileLength = min(ProcessInfo->ImageName.Length,
410 sizeof(ProcessListEntry->szExeFile) - sizeof(WCHAR));
411 RtlCopyMemory(ProcessListEntry->szExeFile,
412 ProcessInfo->ImageName.Buffer,
413 ExeFileLength);
414 ProcessListEntry->szExeFile[ExeFileLength / sizeof(WCHAR)] = UNICODE_NULL;
415 }
416 else
417 {
418 lstrcpyW(ProcessListEntry->szExeFile, L"[System Process]");
419 }
420
421 ProcessListEntry++;
422
423 ProcOffset = ProcessInfo->NextEntryOffset;
424 } while(ProcOffset != 0);
425
426 DataOffset += nProcesses * sizeof(PROCESSENTRY32W);
427 }
428
429 /* initialize the thread list */
430 if(dwFlags & TH32CS_SNAPTHREAD)
431 {
432 ULONG ProcOffset = 0;
433
434 Snapshot->ThreadListCount = nThreads;
435 Snapshot->ThreadListOffset = DataOffset;
436 ThreadListEntry = (LPTHREADENTRY32)OffsetToPtr(Snapshot, DataOffset);
437 ProcessInfo = (PSYSTEM_PROCESS_INFORMATION)ProcThrdInfo;
438 do
439 {
440 PSYSTEM_THREAD_INFORMATION ThreadInfo;
441 ULONG n;
442
443 ProcessInfo = (PSYSTEM_PROCESS_INFORMATION)((ULONG_PTR)ProcessInfo + ProcOffset);
444 ThreadInfo = (PSYSTEM_THREAD_INFORMATION)(ProcessInfo + 1);
445
446 for(n = 0; n < ProcessInfo->NumberOfThreads; n++)
447 {
448 ThreadListEntry->dwSize = sizeof(THREADENTRY32);
449 ThreadListEntry->cntUsage = 0; /* no longer used */
450 ThreadListEntry->th32ThreadID = (ULONG_PTR)ThreadInfo->ClientId.UniqueThread;
451 ThreadListEntry->th32OwnerProcessID = (ULONG_PTR)ThreadInfo->ClientId.UniqueProcess;
452 ThreadListEntry->tpBasePri = ThreadInfo->BasePriority;
453 ThreadListEntry->tpDeltaPri = 0; /* no longer used */
454 ThreadListEntry->dwFlags = 0; /* no longer used */
455
456 ThreadInfo++;
457 ThreadListEntry++;
458 }
459
460 ProcOffset = ProcessInfo->NextEntryOffset;
461 } while(ProcOffset != 0);
462 }
463
464 /*
465 * We're done, unmap the view and return the section handle
466 */
467
468 Status = NtUnmapViewOfSection(NtCurrentProcess(), (PVOID)Snapshot);
469
470 if(NT_SUCCESS(Status))
471 {
472 *SectionHandle = hSection;
473 }
474 else
475 {
476 NtClose(hSection);
477 }
478
479 return Status;
480 }
481
482 /* PUBLIC FUNCTIONS ***********************************************************/
483
484 /*
485 * @implemented
486 */
487 BOOL
488 WINAPI
489 Heap32First(LPHEAPENTRY32 lphe, DWORD th32ProcessID, DWORD th32HeapID)
490 {
491 PRTL_DEBUG_INFORMATION DebugInfo;
492 PRTL_HEAP_INFORMATION Heap;
493 PRTLP_HEAP_ENTRY Block, LastBlock;
494 ULONG i;
495 NTSTATUS Status;
496
497 CHECK_PARAM_SIZE(lphe, sizeof(HEAPENTRY32));
498
499 DebugInfo = RtlCreateQueryDebugBuffer(0,
500 FALSE);
501 if (DebugInfo == NULL)
502 {
503 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
504 return FALSE;
505 }
506
507 Status = RtlQueryProcessDebugInformation(th32ProcessID,
508 RTL_DEBUG_QUERY_HEAPS | RTL_DEBUG_QUERY_HEAP_BLOCKS,
509 DebugInfo);
510
511 if (NT_SUCCESS(Status))
512 {
513 Status = STATUS_NO_MORE_FILES;
514
515 for (i = 0;
516 i != DebugInfo->Heaps->NumberOfHeaps;
517 i++)
518 {
519 Heap = &DebugInfo->Heaps->Heaps[i];
520
521 if ((ULONG_PTR)Heap->BaseAddress == th32HeapID)
522 {
523 lphe->hHandle = (HANDLE)Heap->BaseAddress;
524 lphe->dwAddress = 0;
525 lphe->dwBlockSize = 0;
526 lphe->dwFlags = 0;
527 lphe->dwLockCount = 0;
528 lphe->dwResvd = 0;
529 lphe->th32ProcessID = th32ProcessID;
530 lphe->th32HeapID = (ULONG_PTR)Heap->BaseAddress;
531
532 Block = (PRTLP_HEAP_ENTRY)Heap->Entries;
533 LastBlock = Block + Heap->NumberOfEntries;
534
535 while (Block != LastBlock && (Block->Flags & PROCESS_HEAP_UNCOMMITTED_RANGE))
536 {
537 lphe->dwResvd++;
538 lphe->dwAddress = (ULONG_PTR)((ULONG_PTR)Block->Address + Heap->EntryOverhead);
539 Block++;
540 }
541
542 if (Block != LastBlock && lphe->dwResvd != 0)
543 {
544 lphe->dwBlockSize = Block->Size;
545
546 if (Block->Flags & 0x2F1) /* FIXME */
547 lphe->dwFlags = LF32_FIXED;
548 else if (Block->Flags & 0x20) /* FIXME */
549 lphe->dwFlags = LF32_MOVEABLE;
550 else if (Block->Flags & 0x100) /* FIXME */
551 lphe->dwFlags = LF32_FREE;
552
553 Status = STATUS_SUCCESS;
554 }
555
556 break;
557 }
558 }
559 }
560
561 RtlDestroyQueryDebugBuffer(DebugInfo);
562
563 if (!NT_SUCCESS(Status))
564 {
565 BaseSetLastNTError(Status);
566 return FALSE;
567 }
568
569 return TRUE;
570 }
571
572
573 /*
574 * @implemented
575 */
576 BOOL
577 WINAPI
578 Heap32Next(LPHEAPENTRY32 lphe)
579 {
580 PRTL_DEBUG_INFORMATION DebugInfo;
581 PRTL_HEAP_INFORMATION Heap;
582 PRTLP_HEAP_ENTRY Block, LastBlock;
583 BOOLEAN FoundUncommitted = FALSE;
584 ULONG i;
585 NTSTATUS Status;
586
587 CHECK_PARAM_SIZE(lphe, sizeof(HEAPENTRY32));
588
589 DebugInfo = RtlCreateQueryDebugBuffer(0,
590 FALSE);
591 if (DebugInfo == NULL)
592 {
593 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
594 return FALSE;
595 }
596
597 Status = RtlQueryProcessDebugInformation(lphe->th32ProcessID,
598 RTL_DEBUG_QUERY_HEAPS | RTL_DEBUG_QUERY_HEAP_BLOCKS,
599 DebugInfo);
600
601 if (NT_SUCCESS(Status))
602 {
603 Status = STATUS_NO_MORE_FILES;
604
605 for (i = 0;
606 i != DebugInfo->Heaps->NumberOfHeaps;
607 i++)
608 {
609 Heap = &DebugInfo->Heaps->Heaps[i];
610
611 if ((ULONG_PTR)Heap->BaseAddress == lphe->th32HeapID)
612 {
613 if (++lphe->dwResvd < Heap->NumberOfEntries)
614 {
615 lphe->dwFlags = 0;
616
617 Block = (PRTLP_HEAP_ENTRY)Heap->Entries + lphe->dwResvd;
618 LastBlock = (PRTLP_HEAP_ENTRY)Heap->Entries + Heap->NumberOfEntries;
619
620 while (Block < LastBlock && (Block->Flags & PROCESS_HEAP_UNCOMMITTED_RANGE))
621 {
622 lphe->dwResvd++;
623 lphe->dwAddress = (ULONG_PTR)((ULONG_PTR)Block->Address + Heap->EntryOverhead);
624 FoundUncommitted = TRUE;
625 Block++;
626 }
627
628 if (Block < LastBlock)
629 {
630 if (!FoundUncommitted)
631 lphe->dwAddress += lphe->dwBlockSize;
632
633 lphe->dwBlockSize = Block->Size;
634
635 if (Block->Flags & 0x2F1) /* FIXME */
636 lphe->dwFlags = LF32_FIXED;
637 else if (Block->Flags & 0x20) /* FIXME */
638 lphe->dwFlags = LF32_MOVEABLE;
639 else if (Block->Flags & 0x100) /* FIXME */
640 lphe->dwFlags = LF32_FREE;
641
642 Status = STATUS_SUCCESS;
643 }
644 }
645
646 break;
647 }
648 }
649 }
650
651 RtlDestroyQueryDebugBuffer(DebugInfo);
652
653 if (!NT_SUCCESS(Status))
654 {
655 BaseSetLastNTError(Status);
656 return FALSE;
657 }
658
659 return TRUE;
660
661 }
662
663
664 /*
665 * @implemented
666 */
667 BOOL
668 WINAPI
669 Heap32ListFirst(HANDLE hSnapshot, LPHEAPLIST32 lphl)
670 {
671 PTH32SNAPSHOT Snapshot;
672 LARGE_INTEGER SOffset;
673 SIZE_T ViewSize;
674 NTSTATUS Status;
675
676 CHECK_PARAM_SIZE(lphl, sizeof(HEAPLIST32));
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->HeapListCount > 0)
697 {
698 LPHEAPLIST32 Entries = (LPHEAPLIST32)OffsetToPtr(Snapshot, Snapshot->HeapListOffset);
699 Snapshot->HeapListIndex = 1;
700 RtlCopyMemory(lphl, &Entries[0], sizeof(HEAPLIST32));
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 BaseSetLastNTError(Status);
714 return FALSE;
715 }
716
717
718 /*
719 * @implemented
720 */
721 BOOL
722 WINAPI
723 Heap32ListNext(HANDLE hSnapshot, LPHEAPLIST32 lphl)
724 {
725 PTH32SNAPSHOT Snapshot;
726 LARGE_INTEGER SOffset;
727 SIZE_T ViewSize;
728 NTSTATUS Status;
729
730 CHECK_PARAM_SIZE(lphl, sizeof(HEAPLIST32));
731
732 SOffset.QuadPart = 0;
733 ViewSize = 0;
734 Snapshot = NULL;
735
736 Status = NtMapViewOfSection(hSnapshot,
737 NtCurrentProcess(),
738 (PVOID*)&Snapshot,
739 0,
740 0,
741 &SOffset,
742 &ViewSize,
743 ViewShare,
744 0,
745 PAGE_READWRITE);
746 if(NT_SUCCESS(Status))
747 {
748 BOOL Ret;
749
750 if(Snapshot->HeapListCount > 0 &&
751 Snapshot->HeapListIndex < Snapshot->HeapListCount)
752 {
753 LPHEAPLIST32 Entries = (LPHEAPLIST32)OffsetToPtr(Snapshot, Snapshot->HeapListOffset);
754 RtlCopyMemory(lphl, &Entries[Snapshot->HeapListIndex++], sizeof(HEAPLIST32));
755 Ret = TRUE;
756 }
757 else
758 {
759 SetLastError(ERROR_NO_MORE_FILES);
760 Ret = FALSE;
761 }
762
763 NtUnmapViewOfSection(NtCurrentProcess(), (PVOID)Snapshot);
764 return Ret;
765 }
766
767 BaseSetLastNTError(Status);
768 return FALSE;
769 }
770
771
772 /*
773 * @implemented
774 */
775 BOOL
776 WINAPI
777 Module32First(HANDLE hSnapshot, LPMODULEENTRY32 lpme)
778 {
779 MODULEENTRY32W me;
780 BOOL Ret;
781
782 CHECK_PARAM_SIZEA(lpme, sizeof(MODULEENTRY32));
783
784 me.dwSize = sizeof(MODULEENTRY32W);
785
786 Ret = Module32FirstW(hSnapshot, &me);
787 if(Ret)
788 {
789 lpme->th32ModuleID = me.th32ModuleID;
790 lpme->th32ProcessID = me.th32ProcessID;
791 lpme->GlblcntUsage = me.GlblcntUsage;
792 lpme->ProccntUsage = me.ProccntUsage;
793 lpme->modBaseAddr = me.modBaseAddr;
794 lpme->modBaseSize = me.modBaseSize;
795 lpme->hModule = me.hModule;
796
797 WideCharToMultiByte(CP_ACP, 0, me.szModule, -1, lpme->szModule, sizeof(lpme->szModule), 0, 0);
798 WideCharToMultiByte(CP_ACP, 0, me.szExePath, -1, lpme->szExePath, sizeof(lpme->szExePath), 0, 0);
799 }
800
801 return Ret;
802 }
803
804
805 /*
806 * @implemented
807 */
808 BOOL
809 WINAPI
810 Module32FirstW(HANDLE hSnapshot, LPMODULEENTRY32W lpme)
811 {
812 PTH32SNAPSHOT Snapshot;
813 LARGE_INTEGER SOffset;
814 SIZE_T ViewSize;
815 NTSTATUS Status;
816
817 CHECK_PARAM_SIZE(lpme, sizeof(MODULEENTRY32W));
818
819 SOffset.QuadPart = 0;
820 ViewSize = 0;
821 Snapshot = NULL;
822
823 Status = NtMapViewOfSection(hSnapshot,
824 NtCurrentProcess(),
825 (PVOID*)&Snapshot,
826 0,
827 0,
828 &SOffset,
829 &ViewSize,
830 ViewShare,
831 0,
832 PAGE_READWRITE);
833 if(NT_SUCCESS(Status))
834 {
835 BOOL Ret;
836
837 if(Snapshot->ModuleListCount > 0)
838 {
839 LPMODULEENTRY32W Entries = (LPMODULEENTRY32W)OffsetToPtr(Snapshot, Snapshot->ModuleListOffset);
840 Snapshot->ModuleListIndex = 1;
841 RtlCopyMemory(lpme, &Entries[0], sizeof(MODULEENTRY32W));
842 Ret = TRUE;
843 }
844 else
845 {
846 SetLastError(ERROR_NO_MORE_FILES);
847 Ret = FALSE;
848 }
849
850 NtUnmapViewOfSection(NtCurrentProcess(), (PVOID)Snapshot);
851 return Ret;
852 }
853
854 BaseSetLastNTError(Status);
855 return FALSE;
856 }
857
858
859 /*
860 * @implemented
861 */
862 BOOL
863 WINAPI
864 Module32Next(HANDLE hSnapshot, LPMODULEENTRY32 lpme)
865 {
866 MODULEENTRY32W me;
867 BOOL Ret;
868
869 CHECK_PARAM_SIZEA(lpme, sizeof(MODULEENTRY32));
870
871 me.dwSize = sizeof(MODULEENTRY32W);
872
873 Ret = Module32NextW(hSnapshot, &me);
874 if(Ret)
875 {
876 lpme->th32ModuleID = me.th32ModuleID;
877 lpme->th32ProcessID = me.th32ProcessID;
878 lpme->GlblcntUsage = me.GlblcntUsage;
879 lpme->ProccntUsage = me.ProccntUsage;
880 lpme->modBaseAddr = me.modBaseAddr;
881 lpme->modBaseSize = me.modBaseSize;
882 lpme->hModule = me.hModule;
883
884 WideCharToMultiByte(CP_ACP, 0, me.szModule, -1, lpme->szModule, sizeof(lpme->szModule), 0, 0);
885 WideCharToMultiByte(CP_ACP, 0, me.szExePath, -1, lpme->szExePath, sizeof(lpme->szExePath), 0, 0);
886 }
887
888 return Ret;
889 }
890
891
892 /*
893 * @implemented
894 */
895 BOOL
896 WINAPI
897 Module32NextW(HANDLE hSnapshot, LPMODULEENTRY32W lpme)
898 {
899 PTH32SNAPSHOT Snapshot;
900 LARGE_INTEGER SOffset;
901 SIZE_T ViewSize;
902 NTSTATUS Status;
903
904 CHECK_PARAM_SIZE(lpme, sizeof(MODULEENTRY32W));
905
906 SOffset.QuadPart = 0;
907 ViewSize = 0;
908 Snapshot = NULL;
909
910 Status = NtMapViewOfSection(hSnapshot,
911 NtCurrentProcess(),
912 (PVOID*)&Snapshot,
913 0,
914 0,
915 &SOffset,
916 &ViewSize,
917 ViewShare,
918 0,
919 PAGE_READWRITE);
920 if(NT_SUCCESS(Status))
921 {
922 BOOL Ret;
923
924 if((Snapshot->ModuleListCount > 0) &&
925 (Snapshot->ModuleListIndex < Snapshot->ModuleListCount))
926 {
927 LPMODULEENTRY32W Entries = (LPMODULEENTRY32W)OffsetToPtr(Snapshot, Snapshot->ModuleListOffset);
928 RtlCopyMemory(lpme, &Entries[Snapshot->ModuleListIndex++], sizeof(MODULEENTRY32W));
929 Ret = TRUE;
930 }
931 else
932 {
933 SetLastError(ERROR_NO_MORE_FILES);
934 Ret = FALSE;
935 }
936
937 NtUnmapViewOfSection(NtCurrentProcess(), (PVOID)Snapshot);
938 return Ret;
939 }
940
941 BaseSetLastNTError(Status);
942 return FALSE;
943 }
944
945
946 /*
947 * @implemented
948 */
949 BOOL
950 WINAPI
951 Process32First(HANDLE hSnapshot, LPPROCESSENTRY32 lppe)
952 {
953 PROCESSENTRY32W pe;
954 BOOL Ret;
955
956 CHECK_PARAM_SIZEA(lppe, sizeof(PROCESSENTRY32));
957
958 pe.dwSize = sizeof(PROCESSENTRY32W);
959
960 Ret = Process32FirstW(hSnapshot, &pe);
961 if(Ret)
962 {
963 lppe->cntUsage = pe.cntUsage;
964 lppe->th32ProcessID = pe.th32ProcessID;
965 lppe->th32DefaultHeapID = pe.th32DefaultHeapID;
966 lppe->th32ModuleID = pe.th32ModuleID;
967 lppe->cntThreads = pe.cntThreads;
968 lppe->th32ParentProcessID = pe.th32ParentProcessID;
969 lppe->pcPriClassBase = pe.pcPriClassBase;
970 lppe->dwFlags = pe.dwFlags;
971
972 WideCharToMultiByte(CP_ACP, 0, pe.szExeFile, -1, lppe->szExeFile, sizeof(lppe->szExeFile), 0, 0);
973 }
974
975 return Ret;
976 }
977
978
979 /*
980 * @implemented
981 */
982 BOOL
983 WINAPI
984 Process32FirstW(HANDLE hSnapshot, LPPROCESSENTRY32W lppe)
985 {
986 PTH32SNAPSHOT Snapshot;
987 LARGE_INTEGER SOffset;
988 SIZE_T ViewSize;
989 NTSTATUS Status;
990
991 CHECK_PARAM_SIZE(lppe, sizeof(PROCESSENTRY32W));
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->ProcessListCount > 0)
1012 {
1013 LPPROCESSENTRY32W Entries = (LPPROCESSENTRY32W)OffsetToPtr(Snapshot, Snapshot->ProcessListOffset);
1014
1015 Snapshot->ProcessListIndex = 1;
1016 RtlCopyMemory(lppe, &Entries[0], sizeof(PROCESSENTRY32W));
1017 Ret = TRUE;
1018 }
1019 else
1020 {
1021
1022 SetLastError(ERROR_NO_MORE_FILES);
1023 Ret = FALSE;
1024 }
1025
1026 NtUnmapViewOfSection(NtCurrentProcess(), (PVOID)Snapshot);
1027 return Ret;
1028 }
1029
1030 BaseSetLastNTError(Status);
1031 return FALSE;
1032 }
1033
1034
1035 /*
1036 * @implemented
1037 */
1038 BOOL
1039 WINAPI
1040 Process32Next(HANDLE hSnapshot, LPPROCESSENTRY32 lppe)
1041 {
1042 PROCESSENTRY32W pe;
1043 BOOL Ret;
1044
1045 CHECK_PARAM_SIZEA(lppe, sizeof(PROCESSENTRY32));
1046
1047 pe.dwSize = sizeof(PROCESSENTRY32W);
1048
1049 Ret = Process32NextW(hSnapshot, &pe);
1050 if(Ret)
1051 {
1052 lppe->cntUsage = pe.cntUsage;
1053 lppe->th32ProcessID = pe.th32ProcessID;
1054 lppe->th32DefaultHeapID = pe.th32DefaultHeapID;
1055 lppe->th32ModuleID = pe.th32ModuleID;
1056 lppe->cntThreads = pe.cntThreads;
1057 lppe->th32ParentProcessID = pe.th32ParentProcessID;
1058 lppe->pcPriClassBase = pe.pcPriClassBase;
1059 lppe->dwFlags = pe.dwFlags;
1060
1061 WideCharToMultiByte(CP_ACP, 0, pe.szExeFile, -1, lppe->szExeFile, sizeof(lppe->szExeFile), 0, 0);
1062 }
1063
1064 return Ret;
1065 }
1066
1067
1068 /*
1069 * @implemented
1070 */
1071 BOOL
1072 WINAPI
1073 Process32NextW(HANDLE hSnapshot, LPPROCESSENTRY32W lppe)
1074 {
1075 PTH32SNAPSHOT Snapshot;
1076 LARGE_INTEGER SOffset;
1077 SIZE_T ViewSize;
1078 NTSTATUS Status;
1079
1080 CHECK_PARAM_SIZE(lppe, sizeof(PROCESSENTRY32W));
1081
1082 SOffset.QuadPart = 0;
1083 ViewSize = 0;
1084 Snapshot = NULL;
1085
1086 Status = NtMapViewOfSection(hSnapshot,
1087 NtCurrentProcess(),
1088 (PVOID*)&Snapshot,
1089 0,
1090 0,
1091 &SOffset,
1092 &ViewSize,
1093 ViewShare,
1094 0,
1095 PAGE_READWRITE);
1096 if(NT_SUCCESS(Status))
1097 {
1098 BOOL Ret;
1099
1100 if(Snapshot->ProcessListCount > 0 &&
1101 Snapshot->ProcessListIndex < Snapshot->ProcessListCount)
1102 {
1103 LPPROCESSENTRY32W Entries = (LPPROCESSENTRY32W)OffsetToPtr(Snapshot, Snapshot->ProcessListOffset);
1104 RtlCopyMemory(lppe, &Entries[Snapshot->ProcessListIndex++], sizeof(PROCESSENTRY32W));
1105 Ret = TRUE;
1106 }
1107 else
1108 {
1109 SetLastError(ERROR_NO_MORE_FILES);
1110 Ret = FALSE;
1111 }
1112
1113 NtUnmapViewOfSection(NtCurrentProcess(), (PVOID)Snapshot);
1114 return Ret;
1115 }
1116
1117 BaseSetLastNTError(Status);
1118 return FALSE;
1119 }
1120
1121
1122 /*
1123 * @implemented
1124 */
1125 BOOL
1126 WINAPI
1127 Thread32First(HANDLE hSnapshot, LPTHREADENTRY32 lpte)
1128 {
1129 PTH32SNAPSHOT Snapshot;
1130 LARGE_INTEGER SOffset;
1131 SIZE_T ViewSize;
1132 NTSTATUS Status;
1133
1134 CHECK_PARAM_SIZE(lpte, sizeof(THREADENTRY32));
1135
1136 SOffset.QuadPart = 0;
1137 ViewSize = 0;
1138 Snapshot = NULL;
1139
1140 Status = NtMapViewOfSection(hSnapshot,
1141 NtCurrentProcess(),
1142 (PVOID*)&Snapshot,
1143 0,
1144 0,
1145 &SOffset,
1146 &ViewSize,
1147 ViewShare,
1148 0,
1149 PAGE_READWRITE);
1150 if(NT_SUCCESS(Status))
1151 {
1152 BOOL Ret;
1153
1154 if(Snapshot->ThreadListCount > 0)
1155 {
1156 LPTHREADENTRY32 Entries = (LPTHREADENTRY32)OffsetToPtr(Snapshot, Snapshot->ThreadListOffset);
1157 Snapshot->ThreadListIndex = 1;
1158 RtlCopyMemory(lpte, &Entries[0], sizeof(THREADENTRY32));
1159 Ret = TRUE;
1160 }
1161 else
1162 {
1163 SetLastError(ERROR_NO_MORE_FILES);
1164 Ret = FALSE;
1165 }
1166
1167 NtUnmapViewOfSection(NtCurrentProcess(), (PVOID)Snapshot);
1168 return Ret;
1169 }
1170
1171 BaseSetLastNTError(Status);
1172 return FALSE;
1173 }
1174
1175
1176 /*
1177 * @implemented
1178 */
1179 BOOL
1180 WINAPI
1181 Thread32Next(HANDLE hSnapshot, LPTHREADENTRY32 lpte)
1182 {
1183 PTH32SNAPSHOT Snapshot;
1184 LARGE_INTEGER SOffset;
1185 SIZE_T ViewSize;
1186 NTSTATUS Status;
1187
1188 CHECK_PARAM_SIZE(lpte, sizeof(THREADENTRY32));
1189
1190 SOffset.QuadPart = 0;
1191 ViewSize = 0;
1192 Snapshot = NULL;
1193
1194 Status = NtMapViewOfSection(hSnapshot,
1195 NtCurrentProcess(),
1196 (PVOID*)&Snapshot,
1197 0,
1198 0,
1199 &SOffset,
1200 &ViewSize,
1201 ViewShare,
1202 0,
1203 PAGE_READWRITE);
1204 if(NT_SUCCESS(Status))
1205 {
1206 BOOL Ret;
1207
1208 if(Snapshot->ThreadListCount > 0 &&
1209 Snapshot->ThreadListIndex < Snapshot->ThreadListCount)
1210 {
1211 LPTHREADENTRY32 Entries = (LPTHREADENTRY32)OffsetToPtr(Snapshot, Snapshot->ThreadListOffset);
1212 RtlCopyMemory(lpte, &Entries[Snapshot->ThreadListIndex++], sizeof(THREADENTRY32));
1213 Ret = TRUE;
1214 }
1215 else
1216 {
1217 SetLastError(ERROR_NO_MORE_FILES);
1218 Ret = FALSE;
1219 }
1220
1221 NtUnmapViewOfSection(NtCurrentProcess(), (PVOID)Snapshot);
1222 return Ret;
1223 }
1224
1225 BaseSetLastNTError(Status);
1226 return FALSE;
1227 }
1228
1229
1230 /*
1231 * @implemented
1232 */
1233 BOOL
1234 WINAPI
1235 Toolhelp32ReadProcessMemory(DWORD th32ProcessID, LPCVOID lpBaseAddress,
1236 LPVOID lpBuffer, SIZE_T cbRead, SIZE_T* lpNumberOfBytesRead)
1237 {
1238 HANDLE hProcess = OpenProcess(PROCESS_VM_READ, FALSE, th32ProcessID);
1239 if(hProcess != NULL)
1240 {
1241 BOOL Ret = ReadProcessMemory(hProcess, lpBaseAddress, lpBuffer, cbRead, lpNumberOfBytesRead);
1242 CloseHandle(hProcess);
1243 return Ret;
1244 }
1245
1246 return FALSE;
1247 }
1248
1249
1250 /*
1251 * @implemented
1252 */
1253 HANDLE
1254 WINAPI
1255 CreateToolhelp32Snapshot(DWORD dwFlags, DWORD th32ProcessID)
1256 {
1257 PRTL_DEBUG_INFORMATION HeapDebug, ModuleDebug;
1258 PVOID ProcThrdInfo;
1259 SIZE_T ProcThrdInfoSize;
1260 NTSTATUS Status;
1261 HANDLE hSnapShotSection = NULL;
1262
1263 if(th32ProcessID == 0)
1264 {
1265 th32ProcessID = GetCurrentProcessId();
1266 }
1267
1268 /*
1269 * Get all information required for the snapshot
1270 */
1271 Status = TH32CreateSnapshot(dwFlags,
1272 th32ProcessID,
1273 &HeapDebug,
1274 &ModuleDebug,
1275 &ProcThrdInfo,
1276 &ProcThrdInfoSize);
1277 if(!NT_SUCCESS(Status))
1278 {
1279 BaseSetLastNTError(Status);
1280 return NULL;
1281 }
1282
1283 /*
1284 * Create a section handle and initialize the collected information
1285 */
1286 Status = TH32CreateSnapshotSectionInitialize(dwFlags,
1287 th32ProcessID,
1288 HeapDebug,
1289 ModuleDebug,
1290 ProcThrdInfo,
1291 &hSnapShotSection);
1292
1293 /*
1294 * Free the temporarily allocated memory which is no longer needed
1295 */
1296 TH32FreeAllocatedResources(HeapDebug,
1297 ModuleDebug,
1298 ProcThrdInfo,
1299 ProcThrdInfoSize);
1300
1301 if(!NT_SUCCESS(Status))
1302 {
1303 BaseSetLastNTError(Status);
1304 return NULL;
1305 }
1306
1307 return hSnapShotSection;
1308 }
1309
1310 /* EOF */