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
27 PsaEnumerateSystemModules(IN PSYSMOD_ENUM_ROUTINE Callback
,
28 IN OUT PVOID CallbackContext
)
30 PSYSTEM_MODULE_INFORMATION psmModules
;
31 NTSTATUS Status
= STATUS_SUCCESS
;
40 /* capture the system modules */
41 Status
= PsaCaptureSystemModules(&psmModules
);
43 if(!NT_SUCCESS(Status
))
48 /* walk the system modules */
49 Status
= PsaWalkSystemModules(psmModules
, Callback
, CallbackContext
);
57 /* free the capture */
58 PsaFreeCapture(psmModules
);
67 PsaCaptureSystemModules(OUT PSYSTEM_MODULE_INFORMATION
*SystemModules
)
70 PSYSTEM_MODULE_INFORMATION psmModules
= NULL
;
80 /* initial probe. We just get the count of system modules */
81 Status
= NtQuerySystemInformation(SystemModuleInformation
,
86 if(!NT_SUCCESS(Status
) && (Status
!= STATUS_INFO_LENGTH_MISMATCH
))
88 DPRINT(FAILED_WITH_STATUS
, "NtQuerySystemInformation", Status
);
92 /* RATIONALE: the loading of a system module is a rare occurrence. To
93 minimize memory operations that could be expensive, or fragment the
94 pool/heap, we try to determine the buffer size in advance, knowing that
95 the number of elements is unlikely to change */
96 nSize
= sizeof(SYSTEM_MODULE_INFORMATION
) +
97 (nSize
* sizeof(SYSTEM_MODULE_INFORMATION
));
105 /* free the buffer, and reallocate it to the new size. RATIONALE: since we
106 ignore the buffer's content at this point, there's no point in a realloc,
107 that could end up copying a large chunk of data we'd discard anyway */
108 PsaiFree(psmModules
);
109 pTmp
= PsaiMalloc(nSize
);
113 Status
= STATUS_NO_MEMORY
;
114 DPRINT(FAILED_WITH_STATUS
, "PsaiMalloc", Status
);
120 /* query the information */
121 Status
= NtQuerySystemInformation(SystemModuleInformation
,
126 /* double the buffer for the next loop */
128 } while(Status
== STATUS_INFO_LENGTH_MISMATCH
);
130 if(!NT_SUCCESS(Status
))
132 DPRINT(FAILED_WITH_STATUS
, "NtQuerySystemInformation", Status
);
136 *SystemModules
= psmModules
;
138 Status
= STATUS_SUCCESS
;
146 /* in case of failure, free the buffer */
147 if(!NT_SUCCESS(Status
))
149 PsaiFree(psmModules
);
159 PsaWalkSystemModules(IN PSYSTEM_MODULE_INFORMATION SystemModules
,
160 IN PSYSMOD_ENUM_ROUTINE Callback
,
161 IN OUT PVOID CallbackContext
)
166 /* repeat until all modules have been returned */
167 for(i
= 0; i
< SystemModules
->Count
; i
++)
169 /* return current module to the callback */
170 Status
= Callback(&(SystemModules
->Module
[i
]), CallbackContext
);
172 if(!NT_SUCCESS(Status
))
178 return STATUS_SUCCESS
;
181 PSYSTEM_MODULE_INFORMATION_ENTRY FASTCALL
182 PsaWalkFirstSystemModule(IN PSYSTEM_MODULE_INFORMATION SystemModules
)
184 return &(SystemModules
->Module
[0]);
187 PSYSTEM_MODULE_INFORMATION_ENTRY FASTCALL
188 PsaWalkNextSystemModule(IN PSYSTEM_MODULE_INFORMATION CurrentSystemModule
)
190 return (PSYSTEM_MODULE_INFORMATION_ENTRY
)((ULONG_PTR
)CurrentSystemModule
+
191 (offsetof(SYSTEM_MODULE_INFORMATION
, Module
[1]) -
192 offsetof(SYSTEM_MODULE_INFORMATION
, Module
[0])));