Reactos
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
17typedef NTSTATUS (NTAPI *PFN_RTLQUERYMODULEINFORMATION)(PULONG, ULONG, PVOID);
18
19PFN_RTLQUERYMODULEINFORMATION pfnRtlQueryModuleInformation;
20LONG gKlibInitialized = 0;
21
22
23CODE_SEG("PAGE")
24NTSTATUS
25NTAPI
26AuxKlibInitialize(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
50CODE_SEG("PAGE")
51NTSTATUS
52NTAPI
53AuxKlibQueryModuleInformation(
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
167Cleanup:
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
177NTSTATUS
178AuxKlibGetBugCheckData(
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
195PIMAGE_EXPORT_DIRECTORY
196AuxKlibGetImageExportDirectory(
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)
204CODE_SEG("PAGE")
205NTSTATUS
206NTAPI
207AuxKlibEnumerateSystemFirmwareTables (
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)
217CODE_SEG("PAGE")
218NTSTATUS
219NTAPI
220AuxKlibGetSystemFirmwareTable (
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}