1 /* $Id: drivers.c 52985 2011-07-28 16:21:48Z akhaldi $
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
23 PsaEnumerateSystemModules(IN PSYSMOD_ENUM_ROUTINE Callback
,
24 IN OUT PVOID CallbackContext
)
26 PRTL_PROCESS_MODULES psmModules
;
27 NTSTATUS Status
= STATUS_SUCCESS
;
36 /* capture the system modules */
37 Status
= PsaCaptureSystemModules(&psmModules
);
39 if(!NT_SUCCESS(Status
))
44 /* walk the system modules */
45 Status
= PsaWalkSystemModules(psmModules
, Callback
, CallbackContext
);
53 /* free the capture */
54 PsaFreeCapture(psmModules
);
63 PsaCaptureSystemModules(OUT PRTL_PROCESS_MODULES
*SystemModules
)
66 PRTL_PROCESS_MODULES psmModules
= NULL
;
76 /* initial probe. We just get the count of system modules */
77 Status
= NtQuerySystemInformation(SystemModuleInformation
,
82 if(!NT_SUCCESS(Status
) && (Status
!= STATUS_INFO_LENGTH_MISMATCH
))
84 DPRINT(FAILED_WITH_STATUS
, "NtQuerySystemInformation", Status
);
88 /* RATIONALE: the loading of a system module is a rare occurrence. To
89 minimize memory operations that could be expensive, or fragment the
90 pool/heap, we try to determine the buffer size in advance, knowing that
91 the number of elements is unlikely to change */
92 nSize
= sizeof(RTL_PROCESS_MODULES
) +
93 (nSize
* sizeof(RTL_PROCESS_MODULES
));
101 /* free the buffer, and reallocate it to the new size. RATIONALE: since we
102 ignore the buffer's content at this point, there's no point in a realloc,
103 that could end up copying a large chunk of data we'd discard anyway */
104 PsaiFree(psmModules
);
105 pTmp
= PsaiMalloc(nSize
);
109 Status
= STATUS_NO_MEMORY
;
110 DPRINT(FAILED_WITH_STATUS
, "PsaiMalloc", Status
);
116 /* query the information */
117 Status
= NtQuerySystemInformation(SystemModuleInformation
,
122 /* double the buffer for the next loop */
124 } while(Status
== STATUS_INFO_LENGTH_MISMATCH
);
126 if(!NT_SUCCESS(Status
))
128 DPRINT(FAILED_WITH_STATUS
, "NtQuerySystemInformation", Status
);
132 *SystemModules
= psmModules
;
134 Status
= STATUS_SUCCESS
;
142 /* in case of failure, free the buffer */
143 if(!NT_SUCCESS(Status
))
145 PsaiFree(psmModules
);
155 PsaWalkSystemModules(IN PRTL_PROCESS_MODULES SystemModules
,
156 IN PSYSMOD_ENUM_ROUTINE Callback
,
157 IN OUT PVOID CallbackContext
)
162 /* repeat until all modules have been returned */
163 for(i
= 0; i
< SystemModules
->NumberOfModules
; i
++)
165 /* return current module to the callback */
166 Status
= Callback(&(SystemModules
->Modules
[i
]), CallbackContext
);
168 if(!NT_SUCCESS(Status
))
174 return STATUS_SUCCESS
;
177 PRTL_PROCESS_MODULE_INFORMATION FASTCALL
178 PsaWalkFirstSystemModule(IN PRTL_PROCESS_MODULES SystemModules
)
180 return &(SystemModules
->Modules
[0]);
183 PRTL_PROCESS_MODULE_INFORMATION FASTCALL
184 PsaWalkNextSystemModule(IN PRTL_PROCESS_MODULES CurrentSystemModule
)
186 return (PRTL_PROCESS_MODULE_INFORMATION
)((ULONG_PTR
)CurrentSystemModule
+
187 (FIELD_OFFSET(RTL_PROCESS_MODULES
, Modules
[1]) -
188 FIELD_OFFSET(RTL_PROCESS_MODULES
, Modules
[0])));