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