1 /* 2 * PROJECT: ReactOS SDK: Auxiliary Kernel-Mode Library 3 * LICENSE: BSD-2-Clause-Views (https://spdx.org/licenses/BSD-2-Clause-Views) 4 * PURPOSE: Main source file 5 * COPYRIGHT: Copyright 2019-2020 Max Korostil <mrmks04@yandex.ru> 6 * Copyright 2021 Victor Perevertkin <victor.perevertkin@reactos.org> 7 */ 8 9 #include <ntifs.h> 10 #include <ntintsafe.h> 11 #include <ndk/ntndk.h> 12 #include <pseh/pseh2.h> 13 #include <aux_klib.h> 14 15 #define TAG_AUXK 'AuxK' 16 17 typedef NTSTATUS (NTAPI *PFN_RTLQUERYMODULEINFORMATION)(PULONG, ULONG, PVOID); 18 19 PFN_RTLQUERYMODULEINFORMATION pfnRtlQueryModuleInformation; 20 LONG gKlibInitialized = 0; 21 22 23 CODE_SEG("PAGE") 24 NTSTATUS 25 NTAPI 26 AuxKlibInitialize(VOID) 27 { 28 RTL_OSVERSIONINFOW osVersion; 29 UNICODE_STRING strRtlQueryModuleInformation = RTL_CONSTANT_STRING(L"RtlQueryModuleInformation"); 30 31 PAGED_CODE(); 32 33 if (!gKlibInitialized) 34 { 35 RtlGetVersion(&osVersion); 36 if (osVersion.dwMajorVersion >= 5) 37 { 38 pfnRtlQueryModuleInformation = MmGetSystemRoutineAddress(&strRtlQueryModuleInformation); 39 InterlockedExchange(&gKlibInitialized, 1); 40 } 41 else 42 { 43 return STATUS_NOT_SUPPORTED; 44 } 45 } 46 47 return STATUS_SUCCESS; 48 } 49 50 CODE_SEG("PAGE") 51 NTSTATUS 52 NTAPI 53 AuxKlibQueryModuleInformation( 54 _In_ PULONG InformationLength, 55 _In_ ULONG SizePerModule, 56 _Inout_ PAUX_MODULE_EXTENDED_INFO ModuleInfo) 57 { 58 NTSTATUS status; 59 60 PAGED_CODE(); 61 62 if (gKlibInitialized != 1) 63 { 64 return STATUS_UNSUCCESSFUL; 65 } 66 67 // if we have the function exported from the kernel, use it 68 if (pfnRtlQueryModuleInformation != NULL) 69 { 70 return pfnRtlQueryModuleInformation(InformationLength, SizePerModule, ModuleInfo); 71 } 72 73 if (SizePerModule != sizeof(AUX_MODULE_BASIC_INFO) && 74 SizePerModule != sizeof(AUX_MODULE_EXTENDED_INFO)) 75 { 76 return STATUS_INVALID_PARAMETER_2; 77 } 78 79 if ((ULONG_PTR)ModuleInfo & (TYPE_ALIGNMENT(AUX_MODULE_EXTENDED_INFO) - 1)) 80 { 81 return STATUS_INVALID_PARAMETER_3; 82 } 83 84 // first call the function with a place for only 1 module 85 RTL_PROCESS_MODULES processModulesMinimal; 86 PRTL_PROCESS_MODULES processModules = &processModulesMinimal; 87 ULONG sysInfoLength = sizeof(processModulesMinimal); 88 ULONG resultLength; 89 90 // loop until we have a large-enough buffer for all modules 91 do 92 { 93 status = ZwQuerySystemInformation(SystemModuleInformation, 94 processModules, 95 sysInfoLength, 96 &resultLength); 97 98 if (status == STATUS_INFO_LENGTH_MISMATCH) 99 { 100 // free the old buffer if it's not the first one 101 if (processModules != &processModulesMinimal) 102 { 103 ExFreePoolWithTag(processModules, TAG_AUXK); 104 } 105 106 _SEH2_TRY 107 { 108 // allocate the new one 109 processModules = ExAllocatePoolWithQuotaTag(PagedPool, resultLength, TAG_AUXK); 110 } 111 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 112 { 113 _SEH2_YIELD(return _SEH2_GetExceptionCode()); 114 } 115 _SEH2_END; 116 117 if (!processModules) 118 { 119 return STATUS_INSUFFICIENT_RESOURCES; 120 } 121 sysInfoLength = resultLength; 122 } 123 124 } while (status == STATUS_INFO_LENGTH_MISMATCH); 125 126 if (!NT_SUCCESS(status)) 127 { 128 goto Cleanup; 129 } 130 131 ULONG modulesSize; 132 status = RtlULongMult(SizePerModule, processModules->NumberOfModules, &modulesSize); 133 if (!NT_SUCCESS(status)) 134 { 135 goto Cleanup; 136 } 137 138 if (ModuleInfo == NULL) 139 { 140 ASSERT(status == STATUS_SUCCESS); 141 *InformationLength = modulesSize; 142 goto Cleanup; 143 } 144 145 if (*InformationLength < modulesSize) 146 { 147 status = STATUS_BUFFER_TOO_SMALL; 148 *InformationLength = modulesSize; 149 goto Cleanup; 150 } 151 152 // copy the information to the input array 153 for (UINT32 i = 0; i < processModules->NumberOfModules; i++) 154 { 155 ModuleInfo[i].BasicInfo.ImageBase = processModules->Modules[i].ImageBase; 156 157 if (SizePerModule == sizeof(AUX_MODULE_EXTENDED_INFO)) 158 { 159 ModuleInfo[i].ImageSize = processModules->Modules[i].ImageSize; 160 ModuleInfo[i].FileNameOffset = processModules->Modules[i].OffsetToFileName; 161 RtlCopyMemory(&ModuleInfo[i].FullPathName, 162 processModules->Modules[i].FullPathName, 163 sizeof(processModules->Modules[i].FullPathName)); 164 } 165 } 166 167 Cleanup: 168 // don't accidentally free the stack buffer 169 if (processModules != NULL && processModules != &processModulesMinimal) 170 { 171 ExFreePoolWithTag(processModules, TAG_AUXK); 172 } 173 174 return status; 175 } 176 177 NTSTATUS 178 AuxKlibGetBugCheckData( 179 _Inout_ PKBUGCHECK_DATA BugCheckData) 180 { 181 if (BugCheckData->BugCheckDataSize != sizeof(*BugCheckData)) 182 { 183 return STATUS_INFO_LENGTH_MISMATCH; 184 } 185 186 BugCheckData->BugCheckCode = KiBugCheckData[0]; 187 BugCheckData->Parameter1 = KiBugCheckData[1]; 188 BugCheckData->Parameter2 = KiBugCheckData[2]; 189 BugCheckData->Parameter3 = KiBugCheckData[3]; 190 BugCheckData->Parameter4 = KiBugCheckData[4]; 191 192 return STATUS_SUCCESS; 193 } 194 195 PIMAGE_EXPORT_DIRECTORY 196 AuxKlibGetImageExportDirectory( 197 _In_ PVOID ImageBase) 198 { 199 ULONG size; 200 return RtlImageDirectoryEntryToData(ImageBase, TRUE, IMAGE_DIRECTORY_ENTRY_EXPORT, &size); 201 } 202 203 _IRQL_requires_max_(PASSIVE_LEVEL) 204 CODE_SEG("PAGE") 205 NTSTATUS 206 NTAPI 207 AuxKlibEnumerateSystemFirmwareTables ( 208 _In_ ULONG FirmwareTableProviderSignature, 209 _Out_writes_bytes_to_opt_(BufferLength, *ReturnLength) PVOID FirmwareTableBuffer, 210 _In_ ULONG BufferLength, 211 _Out_opt_ PULONG ReturnLength) 212 { 213 return STATUS_NOT_IMPLEMENTED; 214 } 215 216 _IRQL_requires_max_(PASSIVE_LEVEL) 217 CODE_SEG("PAGE") 218 NTSTATUS 219 NTAPI 220 AuxKlibGetSystemFirmwareTable ( 221 _In_ ULONG FirmwareTableProviderSignature, 222 _In_ ULONG FirmwareTableID, 223 _Out_writes_bytes_to_opt_(BufferLength, *ReturnLength) PVOID FirmwareTableBuffer, 224 _In_ ULONG BufferLength, 225 _Out_opt_ PULONG ReturnLength) 226 { 227 return STATUS_NOT_IMPLEMENTED; 228 } 229