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>
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
22 #include <ddk/ntddk.h>
24 #include <ntdll/ldr.h>
30 PsaEnumerateProcessModules
32 IN HANDLE ProcessHandle,
33 IN PPROCMOD_ENUM_ROUTINE Callback,
34 IN OUT PVOID CallbackContext
37 register NTSTATUS nErrCode;
39 /* current process - use direct memory copy */
40 if(ProcessHandle == NtCurrentProcess())
42 register PLIST_ENTRY pleListHead;
43 register PLIST_ENTRY pleCurEntry;
46 /* FIXME: activate this when GCC supports SEH */
50 pleListHead = &(NtCurrentPeb()->Ldr->InLoadOrderModuleList);
51 pleCurEntry = pleListHead->Flink;
53 while(pleCurEntry != pleListHead)
55 register PLDR_MODULE plmModule = CONTAINING_RECORD
62 /* return the current module to the callback */
63 nErrCode = Callback(ProcessHandle, plmModule, CallbackContext);
65 if(!NT_SUCCESS(nErrCode))
69 pleCurEntry = plmModule->InLoadOrderModuleList.Flink;
72 /* FIXME: activate this when GCC supports SEH */
74 __except(EXCEPTION_EXECUTE_HANDLER)
76 return GetExceptionCode();
83 PROCESS_BASIC_INFORMATION pbiInfo;
84 PPEB_LDR_DATA ppldLdrData;
86 PLIST_ENTRY pleListHead;
87 PLIST_ENTRY pleCurEntry;
89 /* query the process basic information (includes the PEB address) */
90 nErrCode = NtQueryInformationProcess
93 ProcessBasicInformation,
99 if(!NT_SUCCESS(nErrCode))
102 DPRINT(FAILED_WITH_STATUS, "NtQueryInformationProcess", nErrCode);
106 /* get the address of the PE Loader data */
107 nErrCode = NtReadVirtualMemory
110 &(pbiInfo.PebBaseAddress->Ldr),
116 if(!NT_SUCCESS(nErrCode))
119 DPRINT(FAILED_WITH_STATUS, "NtReadVirtualMemory", nErrCode);
123 /* head of the module list: the last element in the list will point to this */
124 pleListHead = &ppldLdrData->InLoadOrderModuleList;
126 /* get the address of the first element in the list */
127 nErrCode = NtReadVirtualMemory
130 &(ppldLdrData->InLoadOrderModuleList.Flink),
136 while(pleCurEntry != pleListHead)
138 /* read the current module */
139 nErrCode = NtReadVirtualMemory
142 CONTAINING_RECORD(pleCurEntry, LDR_MODULE, InLoadOrderModuleList),
148 if(!NT_SUCCESS(nErrCode))
151 DPRINT(FAILED_WITH_STATUS, "NtReadVirtualMemory", nErrCode);
155 /* return the current module to the callback */
156 nErrCode = Callback(ProcessHandle, &lmModule, CallbackContext);
158 if(!NT_SUCCESS(nErrCode))
162 /* address of the next module in the list */
163 pleCurEntry = lmModule.InLoadOrderModuleList.Flink;
169 return (STATUS_SUCCESS);