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