Sync with trunk r62754.
[reactos.git] / lib / epsapi / enum / drivers.c
1 /*
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>
8 * UPDATE HISTORY:
9 * 02/04/2003: Created
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
13 */
14
15 #include "precomp.h"
16
17 #define NDEBUG
18 #include <debug.h>
19
20 NTSTATUS NTAPI
21 PsaEnumerateSystemModules(IN PSYSMOD_ENUM_ROUTINE Callback,
22 IN OUT PVOID CallbackContext)
23 {
24 PRTL_PROCESS_MODULES psmModules;
25 NTSTATUS Status = STATUS_SUCCESS;
26
27 #if 0
28 __try
29 {
30 #else
31 do
32 {
33 #endif
34 /* capture the system modules */
35 Status = PsaCaptureSystemModules(&psmModules);
36
37 if(!NT_SUCCESS(Status))
38 {
39 break;
40 }
41
42 /* walk the system modules */
43 Status = PsaWalkSystemModules(psmModules, Callback, CallbackContext);
44 #if 0
45 }
46 __finally
47 {
48 #else
49 } while(0);
50 #endif
51 /* free the capture */
52 PsaFreeCapture(psmModules);
53 #if 0
54 }
55 #endif
56
57 return Status;
58 }
59
60 NTSTATUS NTAPI
61 PsaCaptureSystemModules(OUT PRTL_PROCESS_MODULES *SystemModules)
62 {
63 SIZE_T nSize = 0;
64 PRTL_PROCESS_MODULES psmModules = NULL;
65 NTSTATUS Status;
66
67 #if 0
68 __try
69 {
70 #else
71 do
72 {
73 #endif
74 /* initial probe. We just get the count of system modules */
75 Status = NtQuerySystemInformation(SystemModuleInformation,
76 &nSize,
77 sizeof(nSize),
78 NULL);
79
80 if(!NT_SUCCESS(Status) && (Status != STATUS_INFO_LENGTH_MISMATCH))
81 {
82 DPRINT(FAILED_WITH_STATUS, "NtQuerySystemInformation", Status);
83 break;
84 }
85
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));
92
93 psmModules = NULL;
94
95 do
96 {
97 PVOID pTmp;
98
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 psmModules = NULL;
104 pTmp = PsaiMalloc(nSize);
105
106 if(pTmp == NULL)
107 {
108 Status = STATUS_NO_MEMORY;
109 DPRINT(FAILED_WITH_STATUS, "PsaiMalloc", Status);
110 break;
111 }
112
113 psmModules = pTmp;
114
115 /* query the information */
116 Status = NtQuerySystemInformation(SystemModuleInformation,
117 psmModules,
118 nSize,
119 NULL);
120
121 /* double the buffer for the next loop */
122 nSize *= 2;
123 } while(Status == STATUS_INFO_LENGTH_MISMATCH);
124
125 if(!NT_SUCCESS(Status))
126 {
127 DPRINT(FAILED_WITH_STATUS, "NtQuerySystemInformation", Status);
128 break;
129 }
130
131 *SystemModules = psmModules;
132
133 Status = STATUS_SUCCESS;
134 #if 0
135 }
136 __finally
137 {
138 #else
139 } while(0);
140 #endif
141 /* in case of failure, free the buffer */
142 if(!NT_SUCCESS(Status) && psmModules != NULL)
143 {
144 PsaiFree(psmModules);
145 }
146 #if 0
147 }
148 #endif
149
150 return Status;
151 }
152
153 NTSTATUS NTAPI
154 PsaWalkSystemModules(IN PRTL_PROCESS_MODULES SystemModules,
155 IN PSYSMOD_ENUM_ROUTINE Callback,
156 IN OUT PVOID CallbackContext)
157 {
158 ULONG i;
159 NTSTATUS Status;
160
161 /* repeat until all modules have been returned */
162 for(i = 0; i < SystemModules->NumberOfModules; i++)
163 {
164 /* return current module to the callback */
165 Status = Callback(&(SystemModules->Modules[i]), CallbackContext);
166
167 if(!NT_SUCCESS(Status))
168 {
169 return Status;
170 }
171 }
172
173 return STATUS_SUCCESS;
174 }
175
176 PRTL_PROCESS_MODULE_INFORMATION FASTCALL
177 PsaWalkFirstSystemModule(IN PRTL_PROCESS_MODULES SystemModules)
178 {
179 return &(SystemModules->Modules[0]);
180 }
181
182 PRTL_PROCESS_MODULE_INFORMATION FASTCALL
183 PsaWalkNextSystemModule(IN PRTL_PROCESS_MODULES CurrentSystemModule)
184 {
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])));
188 }
189
190 /* EOF */