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 #define NTOS_MODE_USER
23 #include <ndk/ntndk.h>
28 #include <epsapi/epsapi.h>
31 PsaEnumerateProcessModules(IN HANDLE ProcessHandle
,
32 IN PPROCMOD_ENUM_ROUTINE Callback
,
33 IN OUT PVOID CallbackContext
)
37 /* current process - use direct memory copy */
38 /* FIXME - compare process id instead of a handle */
39 if(ProcessHandle
== NtCurrentProcess())
41 PLIST_ENTRY ListHead
, Current
;
47 ListHead
= &(NtCurrentPeb()->Ldr
->InLoadOrderModuleList
);
48 Current
= ListHead
->Flink
;
50 while(Current
!= ListHead
)
52 PLDR_DATA_TABLE_ENTRY LoaderModule
= CONTAINING_RECORD(Current
, LDR_DATA_TABLE_ENTRY
, InLoadOrderModuleList
);
54 /* return the current module to the callback */
55 Status
= Callback(ProcessHandle
, LoaderModule
, CallbackContext
);
57 if(!NT_SUCCESS(Status
))
62 Current
= LoaderModule
->InLoadOrderModuleList
.Flink
;
66 __except(EXCEPTION_EXECUTE_HANDLER
)
68 return GetExceptionCode();
74 PROCESS_BASIC_INFORMATION BasicInformation
;
75 PPEB_LDR_DATA LoaderData
;
76 LDR_DATA_TABLE_ENTRY LoaderModule
;
77 PLIST_ENTRY ListHead
, Current
;
79 /* query the process basic information (includes the PEB address) */
80 Status
= NtQueryInformationProcess(ProcessHandle
,
81 ProcessBasicInformation
,
83 sizeof(BasicInformation
),
86 if(!NT_SUCCESS(Status
))
88 DPRINT(FAILED_WITH_STATUS
, "NtQueryInformationProcess", Status
);
92 /* get the address of the PE Loader data */
93 Status
= NtReadVirtualMemory(ProcessHandle
,
94 &(BasicInformation
.PebBaseAddress
->Ldr
),
99 if(!NT_SUCCESS(Status
))
101 DPRINT(FAILED_WITH_STATUS
, "NtReadVirtualMemory", Status
);
105 /* head of the module list: the last element in the list will point to this */
106 ListHead
= &LoaderData
->InLoadOrderModuleList
;
108 /* get the address of the first element in the list */
109 Status
= NtReadVirtualMemory(ProcessHandle
,
110 &(LoaderData
->InLoadOrderModuleList
.Flink
),
115 while(Current
!= ListHead
)
117 /* read the current module */
118 Status
= NtReadVirtualMemory(ProcessHandle
,
119 CONTAINING_RECORD(Current
, LDR_DATA_TABLE_ENTRY
, InLoadOrderModuleList
),
121 sizeof(LoaderModule
),
124 if(!NT_SUCCESS(Status
))
126 DPRINT(FAILED_WITH_STATUS
, "NtReadVirtualMemory", Status
);
130 /* return the current module to the callback */
131 Status
= Callback(ProcessHandle
, &LoaderModule
, CallbackContext
);
133 if(!NT_SUCCESS(Status
))
138 /* address of the next module in the list */
139 Current
= LoaderModule
.InLoadOrderModuleList
.Flink
;
143 return STATUS_SUCCESS
;