- Update to r53061
[reactos.git] / lib / epsapi / enum / modules.c
1 /* $Id$
2 */
3 /*
4 * COPYRIGHT: See COPYING in the top level directory
5 * LICENSE: See LGPL.txt in the top level directory
6 * PROJECT: ReactOS system libraries
7 * FILE: reactos/lib/epsapi/enum/module.c
8 * PURPOSE: Enumerate process modules
9 * PROGRAMMER: KJK::Hyperion <noog@libero.it>
10 * UPDATE HISTORY:
11 * 10/06/2002: Created
12 * 29/08/2002: Generalized the interface to improve reusability,
13 * more efficient use of memory operations
14 * 12/02/2003: malloc and free renamed to PsaiMalloc and PsaiFree,
15 * for better reusability
16 * 02/04/2003: System modules enumeration moved into its own file
17 * 12/04/2003: internal PSAPI renamed EPSAPI (Extended PSAPI) and
18 * isolated in its own library to clear the confusion
19 * and improve reusability
20 */
21
22 #include "precomp.h"
23
24 #define NDEBUG
25 #include <debug.h>
26
27 NTSTATUS NTAPI
28 PsaEnumerateProcessModules(IN HANDLE ProcessHandle,
29 IN PPROCMOD_ENUM_ROUTINE Callback,
30 IN OUT PVOID CallbackContext)
31 {
32 NTSTATUS Status;
33
34 /* current process - use direct memory copy */
35 /* FIXME - compare process id instead of a handle */
36 if(ProcessHandle == NtCurrentProcess())
37 {
38 PLIST_ENTRY ListHead, Current;
39
40 #if 0
41 __try
42 {
43 #endif
44 ListHead = &(NtCurrentPeb()->Ldr->InLoadOrderModuleList);
45 Current = ListHead->Flink;
46
47 while(Current != ListHead)
48 {
49 PLDR_DATA_TABLE_ENTRY LoaderModule = CONTAINING_RECORD(Current, LDR_DATA_TABLE_ENTRY, InLoadOrderLinks);
50
51 /* return the current module to the callback */
52 Status = Callback(ProcessHandle, LoaderModule, CallbackContext);
53
54 if(!NT_SUCCESS(Status))
55 {
56 goto Failure;
57 }
58
59 Current = LoaderModule->InLoadOrderLinks.Flink;
60 }
61 #if 0
62 }
63 __except(EXCEPTION_EXECUTE_HANDLER)
64 {
65 return GetExceptionCode();
66 }
67 #endif
68 }
69 else
70 {
71 PROCESS_BASIC_INFORMATION BasicInformation;
72 PPEB_LDR_DATA LoaderData;
73 LDR_DATA_TABLE_ENTRY LoaderModule;
74 PLIST_ENTRY ListHead, Current;
75
76 /* query the process basic information (includes the PEB address) */
77 Status = NtQueryInformationProcess(ProcessHandle,
78 ProcessBasicInformation,
79 &BasicInformation,
80 sizeof(BasicInformation),
81 NULL);
82
83 if(!NT_SUCCESS(Status))
84 {
85 DPRINT(FAILED_WITH_STATUS, "NtQueryInformationProcess", Status);
86 goto Failure;
87 }
88
89 /* get the address of the PE Loader data */
90 Status = NtReadVirtualMemory(ProcessHandle,
91 &(BasicInformation.PebBaseAddress->Ldr),
92 &LoaderData,
93 sizeof(LoaderData),
94 NULL);
95
96 if(!NT_SUCCESS(Status))
97 {
98 DPRINT(FAILED_WITH_STATUS, "NtReadVirtualMemory", Status);
99 goto Failure;
100 }
101
102 /* head of the module list: the last element in the list will point to this */
103 ListHead = &LoaderData->InLoadOrderModuleList;
104
105 /* get the address of the first element in the list */
106 Status = NtReadVirtualMemory(ProcessHandle,
107 &(LoaderData->InLoadOrderModuleList.Flink),
108 &Current,
109 sizeof(Current),
110 NULL);
111
112 while(Current != ListHead)
113 {
114 /* read the current module */
115 Status = NtReadVirtualMemory(ProcessHandle,
116 CONTAINING_RECORD(Current, LDR_DATA_TABLE_ENTRY, InLoadOrderLinks),
117 &LoaderModule,
118 sizeof(LoaderModule),
119 NULL);
120
121 if(!NT_SUCCESS(Status))
122 {
123 DPRINT(FAILED_WITH_STATUS, "NtReadVirtualMemory", Status);
124 goto Failure;
125 }
126
127 /* return the current module to the callback */
128 Status = Callback(ProcessHandle, &LoaderModule, CallbackContext);
129
130 if(!NT_SUCCESS(Status))
131 {
132 goto Failure;
133 }
134
135 /* address of the next module in the list */
136 Current = LoaderModule.InLoadOrderLinks.Flink;
137 }
138 }
139
140 return STATUS_SUCCESS;
141
142 Failure:
143 return Status;
144 }
145
146 /* EOF */