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
);
104 pTmp
= PsaiMalloc(nSize
);
108 Status
= STATUS_NO_MEMORY
;
109 DPRINT(FAILED_WITH_STATUS
, "PsaiMalloc", Status
);
115 /* query the information */
116 Status
= NtQuerySystemInformation(SystemModuleInformation
,
121 /* double the buffer for the next loop */
123 } while(Status
== STATUS_INFO_LENGTH_MISMATCH
);
125 if(!NT_SUCCESS(Status
))
127 DPRINT(FAILED_WITH_STATUS
, "NtQuerySystemInformation", Status
);
131 *SystemModules
= psmModules
;
133 Status
= STATUS_SUCCESS
;
141 /* in case of failure, free the buffer */
142 if(!NT_SUCCESS(Status
) && psmModules
!= NULL
)
144 PsaiFree(psmModules
);
154 PsaWalkSystemModules(IN PRTL_PROCESS_MODULES SystemModules
,
155 IN PSYSMOD_ENUM_ROUTINE Callback
,
156 IN OUT PVOID CallbackContext
)
161 /* repeat until all modules have been returned */
162 for(i
= 0; i
< SystemModules
->NumberOfModules
; i
++)
164 /* return current module to the callback */
165 Status
= Callback(&(SystemModules
->Modules
[i
]), CallbackContext
);
167 if(!NT_SUCCESS(Status
))
173 return STATUS_SUCCESS
;
176 PRTL_PROCESS_MODULE_INFORMATION FASTCALL
177 PsaWalkFirstSystemModule(IN PRTL_PROCESS_MODULES SystemModules
)
179 return &(SystemModules
->Modules
[0]);
182 PRTL_PROCESS_MODULE_INFORMATION FASTCALL
183 PsaWalkNextSystemModule(IN PRTL_PROCESS_MODULES CurrentSystemModule
)
185 return (PRTL_PROCESS_MODULE_INFORMATION
)((ULONG_PTR
)CurrentSystemModule
+
186 (FIELD_OFFSET(RTL_PROCESS_MODULES
, Modules
[1]) -
187 FIELD_OFFSET(RTL_PROCESS_MODULES
, Modules
[0])));