- Revert 44301
[reactos.git] / lib / epsapi / enum / drivers.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/drivers.c
8 * PURPOSE: Enumerate system modules
9 * PROGRAMMER: KJK::Hyperion <noog@libero.it>
10 * UPDATE HISTORY:
11 * 02/04/2003: Created
12 * 12/04/2003: internal PSAPI renamed EPSAPI (Extended PSAPI) and
13 * isolated in its own library to clear the confusion
14 * and improve reusability
15 */
16
17 #define WIN32_NO_STATUS
18 #include <windows.h>
19 #define NTOS_MODE_USER
20 #include <ndk/ntndk.h>
21
22 #define NDEBUG
23 #include <debug.h>
24
25 #include <epsapi/epsapi.h>
26
27 NTSTATUS NTAPI
28 PsaEnumerateSystemModules(IN PSYSMOD_ENUM_ROUTINE Callback,
29 IN OUT PVOID CallbackContext)
30 {
31 PRTL_PROCESS_MODULES psmModules;
32 NTSTATUS Status = STATUS_SUCCESS;
33
34 #if 0
35 __try
36 {
37 #else
38 do
39 {
40 #endif
41 /* capture the system modules */
42 Status = PsaCaptureSystemModules(&psmModules);
43
44 if(!NT_SUCCESS(Status))
45 {
46 break;
47 }
48
49 /* walk the system modules */
50 Status = PsaWalkSystemModules(psmModules, Callback, CallbackContext);
51 #if 0
52 }
53 __finally
54 {
55 #else
56 } while(0);
57 #endif
58 /* free the capture */
59 PsaFreeCapture(psmModules);
60 #if 0
61 }
62 #endif
63
64 return Status;
65 }
66
67 NTSTATUS NTAPI
68 PsaCaptureSystemModules(OUT PRTL_PROCESS_MODULES *SystemModules)
69 {
70 SIZE_T nSize = 0;
71 PRTL_PROCESS_MODULES psmModules = NULL;
72 NTSTATUS Status;
73
74 #if 0
75 __try
76 {
77 #else
78 do
79 {
80 #endif
81 /* initial probe. We just get the count of system modules */
82 Status = NtQuerySystemInformation(SystemModuleInformation,
83 &nSize,
84 sizeof(nSize),
85 NULL);
86
87 if(!NT_SUCCESS(Status) && (Status != STATUS_INFO_LENGTH_MISMATCH))
88 {
89 DPRINT(FAILED_WITH_STATUS, "NtQuerySystemInformation", Status);
90 break;
91 }
92
93 /* RATIONALE: the loading of a system module is a rare occurrence. To
94 minimize memory operations that could be expensive, or fragment the
95 pool/heap, we try to determine the buffer size in advance, knowing that
96 the number of elements is unlikely to change */
97 nSize = sizeof(RTL_PROCESS_MODULES) +
98 (nSize * sizeof(RTL_PROCESS_MODULES));
99
100 psmModules = NULL;
101
102 do
103 {
104 PVOID pTmp;
105
106 /* free the buffer, and reallocate it to the new size. RATIONALE: since we
107 ignore the buffer's content at this point, there's no point in a realloc,
108 that could end up copying a large chunk of data we'd discard anyway */
109 PsaiFree(psmModules);
110 pTmp = PsaiMalloc(nSize);
111
112 if(pTmp == NULL)
113 {
114 Status = STATUS_NO_MEMORY;
115 DPRINT(FAILED_WITH_STATUS, "PsaiMalloc", Status);
116 break;
117 }
118
119 psmModules = pTmp;
120
121 /* query the information */
122 Status = NtQuerySystemInformation(SystemModuleInformation,
123 psmModules,
124 nSize,
125 NULL);
126
127 /* double the buffer for the next loop */
128 nSize *= 2;
129 } while(Status == STATUS_INFO_LENGTH_MISMATCH);
130
131 if(!NT_SUCCESS(Status))
132 {
133 DPRINT(FAILED_WITH_STATUS, "NtQuerySystemInformation", Status);
134 break;
135 }
136
137 *SystemModules = psmModules;
138
139 Status = STATUS_SUCCESS;
140 #if 0
141 }
142 __finally
143 {
144 #else
145 } while(0);
146 #endif
147 /* in case of failure, free the buffer */
148 if(!NT_SUCCESS(Status))
149 {
150 PsaiFree(psmModules);
151 }
152 #if 0
153 }
154 #endif
155
156 return Status;
157 }
158
159 NTSTATUS NTAPI
160 PsaWalkSystemModules(IN PRTL_PROCESS_MODULES SystemModules,
161 IN PSYSMOD_ENUM_ROUTINE Callback,
162 IN OUT PVOID CallbackContext)
163 {
164 ULONG i;
165 NTSTATUS Status;
166
167 /* repeat until all modules have been returned */
168 for(i = 0; i < SystemModules->NumberOfModules; i++)
169 {
170 /* return current module to the callback */
171 Status = Callback(&(SystemModules->Modules[i]), CallbackContext);
172
173 if(!NT_SUCCESS(Status))
174 {
175 return Status;
176 }
177 }
178
179 return STATUS_SUCCESS;
180 }
181
182 PRTL_PROCESS_MODULE_INFORMATION FASTCALL
183 PsaWalkFirstSystemModule(IN PRTL_PROCESS_MODULES SystemModules)
184 {
185 return &(SystemModules->Modules[0]);
186 }
187
188 PRTL_PROCESS_MODULE_INFORMATION FASTCALL
189 PsaWalkNextSystemModule(IN PRTL_PROCESS_MODULES CurrentSystemModule)
190 {
191 return (PRTL_PROCESS_MODULE_INFORMATION)((ULONG_PTR)CurrentSystemModule +
192 (FIELD_OFFSET(RTL_PROCESS_MODULES, Modules[1]) -
193 FIELD_OFFSET(RTL_PROCESS_MODULES, Modules[0])));
194 }
195
196 /* EOF */