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>
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
17 #include <ddk/ntddk.h>
25 PsaEnumerateSystemModules
27 IN PSYSMOD_ENUM_ROUTINE Callback,
28 IN OUT PVOID CallbackContext
31 register NTSTATUS nErrCode = STATUS_SUCCESS;
32 PSYSTEM_MODULES psmModules = NULL;
40 /* capture the system modules */
41 nErrCode = PsaCaptureSystemModules(&psmModules);
43 if(!NT_SUCCESS(nErrCode))
47 /* walk the system modules */
48 nErrCode = PsaWalkSystemModules(psmModules, Callback, CallbackContext);
56 /* free the capture */
57 PsaFreeCapture(psmModules);
62 /* return the last status */
68 PsaCaptureSystemModules
70 OUT PSYSTEM_MODULES * SystemModules
74 register NTSTATUS nErrCode;
75 register PSYSTEM_MODULES psmModules = (PSYSTEM_MODULES)&nSize;
83 /* initial probe. We just get the count of system modules */
84 nErrCode = NtQuerySystemInformation
86 SystemModuleInformation,
92 if(nErrCode != STATUS_INFO_LENGTH_MISMATCH && !NT_SUCCESS(nErrCode))
95 DPRINT(FAILED_WITH_STATUS, "NtQuerySystemInformation", nErrCode);
99 /* RATIONALE: the loading of a system module is a rare occurrence. To
100 minimize memory operations that could be expensive, or fragment the
101 pool/heap, we try to determine the buffer size in advance, knowing that
102 the number of elements is unlikely to change */
104 sizeof(*psmModules) +
105 (psmModules->Count - 1) * sizeof(SYSTEM_MODULE_INFORMATION);
111 register void * pTmp;
113 /* free the buffer, and reallocate it to the new size. RATIONALE: since we
114 ignore the buffer's content at this point, there's no point in a realloc,
115 that could end up copying a large chunk of data we'd discard anyway */
116 PsaiFree(psmModules);
117 pTmp = PsaiMalloc(nSize);
122 nErrCode = STATUS_NO_MEMORY;
123 DPRINT(FAILED_WITH_STATUS, "PsaiMalloc", nErrCode);
129 /* query the information */
130 nErrCode = NtQuerySystemInformation
132 SystemModuleInformation,
138 /* double the buffer for the next loop */
141 /* repeat until the buffer is big enough */
142 while(nErrCode == STATUS_INFO_LENGTH_MISMATCH);
144 if(!NT_SUCCESS(nErrCode))
147 DPRINT(FAILED_WITH_STATUS, "NtQuerySystemInformation", nErrCode);
152 *SystemModules = psmModules;
154 nErrCode = STATUS_SUCCESS;
162 /* in case of failure, free the buffer */
163 if(!NT_SUCCESS(nErrCode))
164 PsaiFree(psmModules);
169 /* return the last status */
177 IN PSYSTEM_MODULES SystemModules,
178 IN PSYSMOD_ENUM_ROUTINE Callback,
179 IN OUT PVOID CallbackContext
182 register NTSTATUS nErrCode;
185 /* repeat until all modules have been returned */
186 for(i = 0; i < SystemModules->Count; ++ i)
188 /* return current module to the callback */
189 nErrCode = Callback(&(SystemModules->Modules[i]), CallbackContext);
191 if(!NT_SUCCESS(nErrCode))
197 return STATUS_SUCCESS;
200 PSYSTEM_MODULE_INFORMATION
202 PsaWalkFirstSystemModule
204 IN PSYSTEM_MODULES SystemModules
207 return &(SystemModules->Modules[0]);
210 PSYSTEM_MODULE_INFORMATION
212 PsaWalkNextSystemModule
214 IN PSYSTEM_MODULE_INFORMATION CurrentSystemModule
217 return (PSYSTEM_MODULE_INFORMATION)
219 (ULONG_PTR)CurrentSystemModule +
221 offsetof(SYSTEM_MODULES, Modules[1]) -
222 offsetof(SYSTEM_MODULES, Modules[0])