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
17 #define WIN32_NO_STATUS
19 #define NTOS_MODE_USER
20 #include <ndk/ntndk.h>
25 #include <epsapi/epsapi.h>
28 PsaEnumerateSystemModules(IN PSYSMOD_ENUM_ROUTINE Callback
,
29 IN OUT PVOID CallbackContext
)
31 PSYSTEM_MODULE_INFORMATION psmModules
;
32 NTSTATUS Status
= STATUS_SUCCESS
;
41 /* capture the system modules */
42 Status
= PsaCaptureSystemModules(&psmModules
);
44 if(!NT_SUCCESS(Status
))
49 /* walk the system modules */
50 Status
= PsaWalkSystemModules(psmModules
, Callback
, CallbackContext
);
58 /* free the capture */
59 PsaFreeCapture(psmModules
);
68 PsaCaptureSystemModules(OUT PSYSTEM_MODULE_INFORMATION
*SystemModules
)
71 PSYSTEM_MODULE_INFORMATION psmModules
= NULL
;
81 /* initial probe. We just get the count of system modules */
82 Status
= NtQuerySystemInformation(SystemModuleInformation
,
87 if(!NT_SUCCESS(Status
) && (Status
!= STATUS_INFO_LENGTH_MISMATCH
))
89 DPRINT(FAILED_WITH_STATUS
, "NtQuerySystemInformation", Status
);
93 /* RATIONALE: the loading of a system module is a rare occurrence. To
94 minimize memory operations that could be expensive, or fragment the
95 pool/heap, we try to determine the buffer size in advance, knowing that
96 the number of elements is unlikely to change */
97 nSize
= sizeof(SYSTEM_MODULE_INFORMATION
) +
98 (nSize
* sizeof(SYSTEM_MODULE_INFORMATION
));
106 /* free the buffer, and reallocate it to the new size. RATIONALE: since we
107 ignore the buffer's content at this point, there's no point in a realloc,
108 that could end up copying a large chunk of data we'd discard anyway */
109 PsaiFree(psmModules
);
110 pTmp
= PsaiMalloc(nSize
);
114 Status
= STATUS_NO_MEMORY
;
115 DPRINT(FAILED_WITH_STATUS
, "PsaiMalloc", Status
);
121 /* query the information */
122 Status
= NtQuerySystemInformation(SystemModuleInformation
,
127 /* double the buffer for the next loop */
129 } while(Status
== STATUS_INFO_LENGTH_MISMATCH
);
131 if(!NT_SUCCESS(Status
))
133 DPRINT(FAILED_WITH_STATUS
, "NtQuerySystemInformation", Status
);
137 *SystemModules
= psmModules
;
139 Status
= STATUS_SUCCESS
;
147 /* in case of failure, free the buffer */
148 if(!NT_SUCCESS(Status
))
150 PsaiFree(psmModules
);
160 PsaWalkSystemModules(IN PSYSTEM_MODULE_INFORMATION SystemModules
,
161 IN PSYSMOD_ENUM_ROUTINE Callback
,
162 IN OUT PVOID CallbackContext
)
167 /* repeat until all modules have been returned */
168 for(i
= 0; i
< SystemModules
->Count
; i
++)
170 /* return current module to the callback */
171 Status
= Callback(&(SystemModules
->Module
[i
]), CallbackContext
);
173 if(!NT_SUCCESS(Status
))
179 return STATUS_SUCCESS
;
182 PSYSTEM_MODULE_INFORMATION_ENTRY FASTCALL
183 PsaWalkFirstSystemModule(IN PSYSTEM_MODULE_INFORMATION SystemModules
)
185 return &(SystemModules
->Module
[0]);
188 PSYSTEM_MODULE_INFORMATION_ENTRY FASTCALL
189 PsaWalkNextSystemModule(IN PSYSTEM_MODULE_INFORMATION CurrentSystemModule
)
191 return (PSYSTEM_MODULE_INFORMATION_ENTRY
)((ULONG_PTR
)CurrentSystemModule
+
192 (FIELD_OFFSET(SYSTEM_MODULE_INFORMATION
, Module
[1]) -
193 FIELD_OFFSET(SYSTEM_MODULE_INFORMATION
, Module
[0])));