Branch setupapi (again)
[reactos.git] / reactos / lib / epsapi / enum / drivers.c
1 /* $Id$
2 */
3 /*
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>
10 * UPDATE HISTORY:
11 * 02/04/2003: Created
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
15 */
16
17 #include <stddef.h>
18 #define NTOS_MODE_USER
19 #include <ntos.h>
20
21 #define NDEBUG
22 #include <debug.h>
23
24 #include <epsapi.h>
25
26 NTSTATUS NTAPI
27 PsaEnumerateSystemModules(IN PSYSMOD_ENUM_ROUTINE Callback,
28 IN OUT PVOID CallbackContext)
29 {
30 PSYSTEM_MODULE_INFORMATION psmModules;
31 NTSTATUS Status = STATUS_SUCCESS;
32
33 #if 0
34 __try
35 {
36 #else
37 do
38 {
39 #endif
40 /* capture the system modules */
41 Status = PsaCaptureSystemModules(&psmModules);
42
43 if(!NT_SUCCESS(Status))
44 {
45 break;
46 }
47
48 /* walk the system modules */
49 Status = PsaWalkSystemModules(psmModules, Callback, CallbackContext);
50 #if 0
51 }
52 __finally
53 {
54 #else
55 } while(0);
56 #endif
57 /* free the capture */
58 PsaFreeCapture(psmModules);
59 #if 0
60 }
61 #endif
62
63 return Status;
64 }
65
66 NTSTATUS NTAPI
67 PsaCaptureSystemModules(OUT PSYSTEM_MODULE_INFORMATION *SystemModules)
68 {
69 SIZE_T nSize = 0;
70 PSYSTEM_MODULE_INFORMATION psmModules;
71 NTSTATUS Status;
72
73 #if 0
74 __try
75 {
76 #else
77 do
78 {
79 #endif
80 /* initial probe. We just get the count of system modules */
81 Status = NtQuerySystemInformation(SystemModuleInformation,
82 &nSize,
83 sizeof(nSize),
84 NULL);
85
86 if(!NT_SUCCESS(Status) && (Status != STATUS_INFO_LENGTH_MISMATCH))
87 {
88 DPRINT(FAILED_WITH_STATUS, "NtQuerySystemInformation", Status);
89 break;
90 }
91
92 /* RATIONALE: the loading of a system module is a rare occurrence. To
93 minimize memory operations that could be expensive, or fragment the
94 pool/heap, we try to determine the buffer size in advance, knowing that
95 the number of elements is unlikely to change */
96 nSize = sizeof(SYSTEM_MODULE_INFORMATION) +
97 ((psmModules->Count - 1) * sizeof(SYSTEM_MODULE_INFORMATION));
98
99 psmModules = NULL;
100
101 do
102 {
103 PVOID pTmp;
104
105 /* free the buffer, and reallocate it to the new size. RATIONALE: since we
106 ignore the buffer's content at this point, there's no point in a realloc,
107 that could end up copying a large chunk of data we'd discard anyway */
108 PsaiFree(psmModules);
109 pTmp = PsaiMalloc(nSize);
110
111 if(pTmp == NULL)
112 {
113 Status = STATUS_NO_MEMORY;
114 DPRINT(FAILED_WITH_STATUS, "PsaiMalloc", Status);
115 break;
116 }
117
118 psmModules = pTmp;
119
120 /* query the information */
121 Status = NtQuerySystemInformation(SystemModuleInformation,
122 psmModules,
123 nSize,
124 NULL);
125
126 /* double the buffer for the next loop */
127 nSize *= 2;
128 } while(Status == STATUS_INFO_LENGTH_MISMATCH);
129
130 if(!NT_SUCCESS(Status))
131 {
132 DPRINT(FAILED_WITH_STATUS, "NtQuerySystemInformation", Status);
133 break;
134 }
135
136 *SystemModules = psmModules;
137
138 Status = STATUS_SUCCESS;
139 #if 0
140 }
141 __finally
142 {
143 #else
144 } while(0);
145 #endif
146 /* in case of failure, free the buffer */
147 if(!NT_SUCCESS(Status))
148 {
149 PsaiFree(psmModules);
150 }
151 #if 0
152 }
153 #endif
154
155 return Status;
156 }
157
158 NTSTATUS NTAPI
159 PsaWalkSystemModules(IN PSYSTEM_MODULE_INFORMATION SystemModules,
160 IN PSYSMOD_ENUM_ROUTINE Callback,
161 IN OUT PVOID CallbackContext)
162 {
163 ULONG i;
164 NTSTATUS Status;
165
166 /* repeat until all modules have been returned */
167 for(i = 0; i < SystemModules->Count; i++)
168 {
169 /* return current module to the callback */
170 Status = Callback(&(SystemModules->Module[i]), CallbackContext);
171
172 if(!NT_SUCCESS(Status))
173 {
174 return Status;
175 }
176 }
177
178 return STATUS_SUCCESS;
179 }
180
181 PSYSTEM_MODULE_INFORMATION_ENTRY FASTCALL
182 PsaWalkFirstSystemModule(IN PSYSTEM_MODULE_INFORMATION SystemModules)
183 {
184 return &(SystemModules->Module[0]);
185 }
186
187 PSYSTEM_MODULE_INFORMATION_ENTRY FASTCALL
188 PsaWalkNextSystemModule(IN PSYSTEM_MODULE_INFORMATION CurrentSystemModule)
189 {
190 return (PSYSTEM_MODULE_INFORMATION_ENTRY)((ULONG_PTR)CurrentSystemModule +
191 (offsetof(SYSTEM_MODULE_INFORMATION, Module[1]) -
192 offsetof(SYSTEM_MODULE_INFORMATION, Module[0])));
193 }
194
195 /* EOF */