3b0d201f78767c5851bdd4198ce3809637efa72d
[reactos.git] / reactos / 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 #include <windows.h>
22 #define NTOS_MODE_USER
23 #include <ndk/ntndk.h>
24
25 #define NDEBUG
26 #include <debug.h>
27
28 #include <epsapi.h>
29
30 NTSTATUS NTAPI
31 PsaEnumerateProcessModules(IN HANDLE ProcessHandle,
32 IN PPROCMOD_ENUM_ROUTINE Callback,
33 IN OUT PVOID CallbackContext)
34 {
35 NTSTATUS Status;
36
37 /* current process - use direct memory copy */
38 /* FIXME - compare process id instead of a handle */
39 if(ProcessHandle == NtCurrentProcess())
40 {
41 PLIST_ENTRY ListHead, Current;
42
43 #if 0
44 __try
45 {
46 #endif
47 ListHead = &(NtCurrentPeb()->Ldr->InLoadOrderModuleList);
48 Current = ListHead->Flink;
49
50 while(Current != ListHead)
51 {
52 PLDR_MODULE LoaderModule = CONTAINING_RECORD(Current, LDR_MODULE, InLoadOrderModuleList);
53
54 /* return the current module to the callback */
55 Status = Callback(ProcessHandle, LoaderModule, CallbackContext);
56
57 if(!NT_SUCCESS(Status))
58 {
59 goto Failure;
60 }
61
62 Current = LoaderModule->InLoadOrderModuleList.Flink;
63 }
64 #if 0
65 }
66 __except(EXCEPTION_EXECUTE_HANDLER)
67 {
68 return GetExceptionCode();
69 }
70 #endif
71 }
72 else
73 {
74 PROCESS_BASIC_INFORMATION BasicInformation;
75 PPEB_LDR_DATA LoaderData;
76 LDR_MODULE LoaderModule;
77 PLIST_ENTRY ListHead, Current;
78
79 /* query the process basic information (includes the PEB address) */
80 Status = NtQueryInformationProcess(ProcessHandle,
81 ProcessBasicInformation,
82 &BasicInformation,
83 sizeof(BasicInformation),
84 NULL);
85
86 if(!NT_SUCCESS(Status))
87 {
88 DPRINT(FAILED_WITH_STATUS, "NtQueryInformationProcess", Status);
89 goto Failure;
90 }
91
92 /* get the address of the PE Loader data */
93 Status = NtReadVirtualMemory(ProcessHandle,
94 &(BasicInformation.PebBaseAddress->Ldr),
95 &LoaderData,
96 sizeof(LoaderData),
97 NULL);
98
99 if(!NT_SUCCESS(Status))
100 {
101 DPRINT(FAILED_WITH_STATUS, "NtReadVirtualMemory", Status);
102 goto Failure;
103 }
104
105 /* head of the module list: the last element in the list will point to this */
106 ListHead = &LoaderData->InLoadOrderModuleList;
107
108 /* get the address of the first element in the list */
109 Status = NtReadVirtualMemory(ProcessHandle,
110 &(LoaderData->InLoadOrderModuleList.Flink),
111 &Current,
112 sizeof(Current),
113 NULL);
114
115 while(Current != ListHead)
116 {
117 /* read the current module */
118 Status = NtReadVirtualMemory(ProcessHandle,
119 CONTAINING_RECORD(Current, LDR_MODULE, InLoadOrderModuleList),
120 &LoaderModule,
121 sizeof(LoaderModule),
122 NULL);
123
124 if(!NT_SUCCESS(Status))
125 {
126 DPRINT(FAILED_WITH_STATUS, "NtReadVirtualMemory", Status);
127 goto Failure;
128 }
129
130 /* return the current module to the callback */
131 Status = Callback(ProcessHandle, &LoaderModule, CallbackContext);
132
133 if(!NT_SUCCESS(Status))
134 {
135 goto Failure;
136 }
137
138 /* address of the next module in the list */
139 Current = LoaderModule.InLoadOrderModuleList.Flink;
140 }
141 }
142
143 return STATUS_SUCCESS;
144
145 Failure:
146 return Status;
147 }
148
149 /* EOF */