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
18 #define NTOS_MODE_USER
28 PsaEnumerateSystemModules
30 IN PSYSMOD_ENUM_ROUTINE Callback,
31 IN OUT PVOID CallbackContext
34 register NTSTATUS nErrCode = STATUS_SUCCESS;
35 PSYSTEM_MODULE_INFORMATION psmModules = NULL;
43 /* capture the system modules */
44 nErrCode = PsaCaptureSystemModules(&psmModules);
46 if(!NT_SUCCESS(nErrCode))
50 /* walk the system modules */
51 nErrCode = PsaWalkSystemModules(psmModules, Callback, CallbackContext);
59 /* free the capture */
60 PsaFreeCapture(psmModules);
65 /* return the last status */
71 PsaCaptureSystemModules
73 OUT PSYSTEM_MODULE_INFORMATION * SystemModules
77 register NTSTATUS nErrCode;
78 register PSYSTEM_MODULE_INFORMATION psmModules = (PSYSTEM_MODULE_INFORMATION)&nSize;
86 /* initial probe. We just get the count of system modules */
87 nErrCode = NtQuerySystemInformation
89 SystemModuleInformation,
95 if(nErrCode != STATUS_INFO_LENGTH_MISMATCH && !NT_SUCCESS(nErrCode))
98 DPRINT(FAILED_WITH_STATUS, "NtQuerySystemInformation", nErrCode);
102 /* RATIONALE: the loading of a system module is a rare occurrence. To
103 minimize memory operations that could be expensive, or fragment the
104 pool/heap, we try to determine the buffer size in advance, knowing that
105 the number of elements is unlikely to change */
107 sizeof(*psmModules) +
108 (psmModules->Count - 1) * sizeof(SYSTEM_MODULE_INFORMATION);
114 register void * pTmp;
116 /* free the buffer, and reallocate it to the new size. RATIONALE: since we
117 ignore the buffer's content at this point, there's no point in a realloc,
118 that could end up copying a large chunk of data we'd discard anyway */
119 PsaiFree(psmModules);
120 pTmp = PsaiMalloc(nSize);
125 nErrCode = STATUS_NO_MEMORY;
126 DPRINT(FAILED_WITH_STATUS, "PsaiMalloc", nErrCode);
132 /* query the information */
133 nErrCode = NtQuerySystemInformation
135 SystemModuleInformation,
141 /* double the buffer for the next loop */
144 /* repeat until the buffer is big enough */
145 while(nErrCode == STATUS_INFO_LENGTH_MISMATCH);
147 if(!NT_SUCCESS(nErrCode))
150 DPRINT(FAILED_WITH_STATUS, "NtQuerySystemInformation", nErrCode);
155 *SystemModules = psmModules;
157 nErrCode = STATUS_SUCCESS;
165 /* in case of failure, free the buffer */
166 if(!NT_SUCCESS(nErrCode))
167 PsaiFree(psmModules);
172 /* return the last status */
180 IN PSYSTEM_MODULE_INFORMATION SystemModules,
181 IN PSYSMOD_ENUM_ROUTINE Callback,
182 IN OUT PVOID CallbackContext
185 register NTSTATUS nErrCode;
188 /* repeat until all modules have been returned */
189 for(i = 0; i < SystemModules->Count; ++ i)
191 /* return current module to the callback */
192 nErrCode = Callback(&(SystemModules->Module[i]), CallbackContext);
194 if(!NT_SUCCESS(nErrCode))
200 return STATUS_SUCCESS;
203 PSYSTEM_MODULE_INFORMATION_ENTRY
205 PsaWalkFirstSystemModule
207 IN PSYSTEM_MODULE_INFORMATION SystemModules
210 return &(SystemModules->Module[0]);
213 PSYSTEM_MODULE_INFORMATION_ENTRY
215 PsaWalkNextSystemModule
217 IN PSYSTEM_MODULE_INFORMATION CurrentSystemModule
220 return (PSYSTEM_MODULE_INFORMATION_ENTRY)
222 (ULONG_PTR)CurrentSystemModule +
224 offsetof(SYSTEM_MODULE_INFORMATION, Module[1]) -
225 offsetof(SYSTEM_MODULE_INFORMATION, Module[0])