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 */ 191