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
21 #define WIN32_NO_STATUS
23 #define NTOS_MODE_USER
24 #include <ndk/ntndk.h>
29 #include <epsapi/epsapi.h>
32 PsaEnumerateProcessModules(IN HANDLE ProcessHandle
,
33 IN PPROCMOD_ENUM_ROUTINE Callback
,
34 IN OUT PVOID CallbackContext
)
38 /* current process - use direct memory copy */
39 /* FIXME - compare process id instead of a handle */
40 if(ProcessHandle
== NtCurrentProcess())
42 PLIST_ENTRY ListHead
, Current
;
48 ListHead
= &(NtCurrentPeb()->Ldr
->InLoadOrderModuleList
);
49 Current
= ListHead
->Flink
;
51 while(Current
!= ListHead
)
53 PLDR_DATA_TABLE_ENTRY LoaderModule
= CONTAINING_RECORD(Current
, LDR_DATA_TABLE_ENTRY
, InLoadOrderLinks
);
55 /* return the current module to the callback */
56 Status
= Callback(ProcessHandle
, LoaderModule
, CallbackContext
);
58 if(!NT_SUCCESS(Status
))
63 Current
= LoaderModule
->InLoadOrderLinks
.Flink
;
67 __except(EXCEPTION_EXECUTE_HANDLER
)
69 return GetExceptionCode();
75 PROCESS_BASIC_INFORMATION BasicInformation
;
76 PPEB_LDR_DATA LoaderData
;
77 LDR_DATA_TABLE_ENTRY LoaderModule
;
78 PLIST_ENTRY ListHead
, Current
;
80 /* query the process basic information (includes the PEB address) */
81 Status
= NtQueryInformationProcess(ProcessHandle
,
82 ProcessBasicInformation
,
84 sizeof(BasicInformation
),
87 if(!NT_SUCCESS(Status
))
89 DPRINT(FAILED_WITH_STATUS
, "NtQueryInformationProcess", Status
);
93 /* get the address of the PE Loader data */
94 Status
= NtReadVirtualMemory(ProcessHandle
,
95 &(BasicInformation
.PebBaseAddress
->Ldr
),
100 if(!NT_SUCCESS(Status
))
102 DPRINT(FAILED_WITH_STATUS
, "NtReadVirtualMemory", Status
);
106 /* head of the module list: the last element in the list will point to this */
107 ListHead
= &LoaderData
->InLoadOrderModuleList
;
109 /* get the address of the first element in the list */
110 Status
= NtReadVirtualMemory(ProcessHandle
,
111 &(LoaderData
->InLoadOrderModuleList
.Flink
),
116 while(Current
!= ListHead
)
118 /* read the current module */
119 Status
= NtReadVirtualMemory(ProcessHandle
,
120 CONTAINING_RECORD(Current
, LDR_DATA_TABLE_ENTRY
, InLoadOrderLinks
),
122 sizeof(LoaderModule
),
125 if(!NT_SUCCESS(Status
))
127 DPRINT(FAILED_WITH_STATUS
, "NtReadVirtualMemory", Status
);
131 /* return the current module to the callback */
132 Status
= Callback(ProcessHandle
, &LoaderModule
, CallbackContext
);
134 if(!NT_SUCCESS(Status
))
139 /* address of the next module in the list */
140 Current
= LoaderModule
.InLoadOrderLinks
.Flink
;
144 return STATUS_SUCCESS
;