2 * COPYRIGHT: See COPYING in the top level directory
3 * LICENSE: See LGPL.txt in the top level directory
4 * PROJECT: ReactOS system libraries
5 * FILE: reactos/lib/epsapi/enum/drivers.c
6 * PURPOSE: Enumerate system modules
7 * PROGRAMMER: KJK::Hyperion <noog@libero.it>
10 * 12/04/2003: internal PSAPI renamed EPSAPI (Extended PSAPI) and
11 * isolated in its own library to clear the confusion
12 * and improve reusability
21 PsaEnumerateSystemModules(IN PSYSMOD_ENUM_ROUTINE Callback
,
22 IN OUT PVOID CallbackContext
)
24 PRTL_PROCESS_MODULES psmModules
;
25 NTSTATUS Status
= STATUS_SUCCESS
;
34 /* capture the system modules */
35 Status
= PsaCaptureSystemModules(&psmModules
);
37 if(!NT_SUCCESS(Status
))
42 /* walk the system modules */
43 Status
= PsaWalkSystemModules(psmModules
, Callback
, CallbackContext
);
51 /* free the capture */
52 PsaFreeCapture(psmModules
);
61 PsaCaptureSystemModules(OUT PRTL_PROCESS_MODULES
*SystemModules
)
64 PRTL_PROCESS_MODULES psmModules
= NULL
;
74 /* initial probe. We just get the count of system modules */
75 Status
= NtQuerySystemInformation(SystemModuleInformation
,
80 if(!NT_SUCCESS(Status
) && (Status
!= STATUS_INFO_LENGTH_MISMATCH
))
82 DPRINT(FAILED_WITH_STATUS
, "NtQuerySystemInformation", Status
);
86 /* RATIONALE: the loading of a system module is a rare occurrence. To
87 minimize memory operations that could be expensive, or fragment the
88 pool/heap, we try to determine the buffer size in advance, knowing that
89 the number of elements is unlikely to change */
90 nSize
= sizeof(RTL_PROCESS_MODULES
) +
91 (nSize
* sizeof(RTL_PROCESS_MODULES
));
99 /* free the buffer, and reallocate it to the new size. RATIONALE: since we
100 ignore the buffer's content at this point, there's no point in a realloc,
101 that could end up copying a large chunk of data we'd discard anyway */
102 PsaiFree(psmModules
);
103 pTmp
= PsaiMalloc(nSize
);
107 Status
= STATUS_NO_MEMORY
;
108 DPRINT(FAILED_WITH_STATUS
, "PsaiMalloc", Status
);
114 /* query the information */
115 Status
= NtQuerySystemInformation(SystemModuleInformation
,
120 /* double the buffer for the next loop */
122 } while(Status
== STATUS_INFO_LENGTH_MISMATCH
);
124 if(!NT_SUCCESS(Status
))
126 DPRINT(FAILED_WITH_STATUS
, "NtQuerySystemInformation", Status
);
130 *SystemModules
= psmModules
;
132 Status
= STATUS_SUCCESS
;
140 /* in case of failure, free the buffer */
141 if(!NT_SUCCESS(Status
))
143 PsaiFree(psmModules
);
153 PsaWalkSystemModules(IN PRTL_PROCESS_MODULES SystemModules
,
154 IN PSYSMOD_ENUM_ROUTINE Callback
,
155 IN OUT PVOID CallbackContext
)
160 /* repeat until all modules have been returned */
161 for(i
= 0; i
< SystemModules
->NumberOfModules
; i
++)
163 /* return current module to the callback */
164 Status
= Callback(&(SystemModules
->Modules
[i
]), CallbackContext
);
166 if(!NT_SUCCESS(Status
))
172 return STATUS_SUCCESS
;
175 PRTL_PROCESS_MODULE_INFORMATION FASTCALL
176 PsaWalkFirstSystemModule(IN PRTL_PROCESS_MODULES SystemModules
)
178 return &(SystemModules
->Modules
[0]);
181 PRTL_PROCESS_MODULE_INFORMATION FASTCALL
182 PsaWalkNextSystemModule(IN PRTL_PROCESS_MODULES CurrentSystemModule
)
184 return (PRTL_PROCESS_MODULE_INFORMATION
)((ULONG_PTR
)CurrentSystemModule
+
185 (FIELD_OFFSET(RTL_PROCESS_MODULES
, Modules
[1]) -
186 FIELD_OFFSET(RTL_PROCESS_MODULES
, Modules
[0])));