xref: /reactos/sdk/lib/epsapi/enum/drivers.c (revision c2c66aff)
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
PsaEnumerateSystemModules(IN PSYSMOD_ENUM_ROUTINE Callback,IN OUT PVOID CallbackContext)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
PsaCaptureSystemModules(OUT PRTL_PROCESS_MODULES * SystemModules)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
PsaWalkSystemModules(IN PRTL_PROCESS_MODULES SystemModules,IN PSYSMOD_ENUM_ROUTINE Callback,IN OUT PVOID CallbackContext)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
PsaWalkFirstSystemModule(IN PRTL_PROCESS_MODULES SystemModules)177 PsaWalkFirstSystemModule(IN PRTL_PROCESS_MODULES SystemModules)
178 {
179   return &(SystemModules->Modules[0]);
180 }
181 
182 PRTL_PROCESS_MODULE_INFORMATION FASTCALL
PsaWalkNextSystemModule(IN PRTL_PROCESS_MODULES CurrentSystemModule)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 */
191