Synchronize with trunk r58528.
[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 pTmp = PsaiMalloc(nSize);
104
105 if(pTmp == NULL)
106 {
107 Status = STATUS_NO_MEMORY;
108 DPRINT(FAILED_WITH_STATUS, "PsaiMalloc", Status);
109 break;
110 }
111
112 psmModules = pTmp;
113
114 /* query the information */
115 Status = NtQuerySystemInformation(SystemModuleInformation,
116 psmModules,
117 nSize,
118 NULL);
119
120 /* double the buffer for the next loop */
121 nSize *= 2;
122 } while(Status == STATUS_INFO_LENGTH_MISMATCH);
123
124 if(!NT_SUCCESS(Status))
125 {
126 DPRINT(FAILED_WITH_STATUS, "NtQuerySystemInformation", Status);
127 break;
128 }
129
130 *SystemModules = psmModules;
131
132 Status = STATUS_SUCCESS;
133 #if 0
134 }
135 __finally
136 {
137 #else
138 } while(0);
139 #endif
140 /* in case of failure, free the buffer */
141 if(!NT_SUCCESS(Status))
142 {
143 PsaiFree(psmModules);
144 }
145 #if 0
146 }
147 #endif
148
149 return Status;
150 }
151
152 NTSTATUS NTAPI
153 PsaWalkSystemModules(IN PRTL_PROCESS_MODULES SystemModules,
154 IN PSYSMOD_ENUM_ROUTINE Callback,
155 IN OUT PVOID CallbackContext)
156 {
157 ULONG i;
158 NTSTATUS Status;
159
160 /* repeat until all modules have been returned */
161 for(i = 0; i < SystemModules->NumberOfModules; i++)
162 {
163 /* return current module to the callback */
164 Status = Callback(&(SystemModules->Modules[i]), CallbackContext);
165
166 if(!NT_SUCCESS(Status))
167 {
168 return Status;
169 }
170 }
171
172 return STATUS_SUCCESS;
173 }
174
175 PRTL_PROCESS_MODULE_INFORMATION FASTCALL
176 PsaWalkFirstSystemModule(IN PRTL_PROCESS_MODULES SystemModules)
177 {
178 return &(SystemModules->Modules[0]);
179 }
180
181 PRTL_PROCESS_MODULE_INFORMATION FASTCALL
182 PsaWalkNextSystemModule(IN PRTL_PROCESS_MODULES CurrentSystemModule)
183 {
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])));
187 }
188
189 /* EOF */