2021-03-10 13:43:59 +00:00
|
|
|
/*
|
|
|
|
* PROJECT: ReactOS SDK: Auxiliary Kernel-Mode Library
|
|
|
|
* LICENSE: BSD-2-Clause-Views (https://spdx.org/licenses/BSD-2-Clause-Views)
|
|
|
|
* PURPOSE: Main source file
|
|
|
|
* COPYRIGHT: Copyright 2019-2020 Max Korostil <mrmks04@yandex.ru>
|
|
|
|
* Copyright 2021 Victor Perevertkin <victor.perevertkin@reactos.org>
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include <ntifs.h>
|
|
|
|
#include <ntintsafe.h>
|
|
|
|
#include <ndk/ntndk.h>
|
|
|
|
#include <pseh/pseh2.h>
|
|
|
|
#include <aux_klib.h>
|
|
|
|
|
|
|
|
#define TAG_AUXK 'AuxK'
|
|
|
|
|
|
|
|
typedef NTSTATUS (NTAPI *PFN_RTLQUERYMODULEINFORMATION)(PULONG, ULONG, PVOID);
|
|
|
|
|
|
|
|
PFN_RTLQUERYMODULEINFORMATION pfnRtlQueryModuleInformation;
|
|
|
|
LONG gKlibInitialized = 0;
|
|
|
|
|
|
|
|
|
|
|
|
CODE_SEG("PAGE")
|
|
|
|
NTSTATUS
|
|
|
|
NTAPI
|
|
|
|
AuxKlibInitialize(VOID)
|
|
|
|
{
|
|
|
|
RTL_OSVERSIONINFOW osVersion;
|
|
|
|
UNICODE_STRING strRtlQueryModuleInformation = RTL_CONSTANT_STRING(L"RtlQueryModuleInformation");
|
|
|
|
|
|
|
|
PAGED_CODE();
|
|
|
|
|
|
|
|
if (!gKlibInitialized)
|
|
|
|
{
|
|
|
|
RtlGetVersion(&osVersion);
|
|
|
|
if (osVersion.dwMajorVersion >= 5)
|
|
|
|
{
|
|
|
|
pfnRtlQueryModuleInformation = MmGetSystemRoutineAddress(&strRtlQueryModuleInformation);
|
|
|
|
InterlockedExchange(&gKlibInitialized, 1);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
return STATUS_NOT_SUPPORTED;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return STATUS_SUCCESS;
|
|
|
|
}
|
|
|
|
|
|
|
|
CODE_SEG("PAGE")
|
|
|
|
NTSTATUS
|
|
|
|
NTAPI
|
|
|
|
AuxKlibQueryModuleInformation(
|
|
|
|
_In_ PULONG InformationLength,
|
|
|
|
_In_ ULONG SizePerModule,
|
|
|
|
_Inout_ PAUX_MODULE_EXTENDED_INFO ModuleInfo)
|
|
|
|
{
|
|
|
|
NTSTATUS status;
|
|
|
|
|
|
|
|
PAGED_CODE();
|
|
|
|
|
2021-06-11 12:29:21 +00:00
|
|
|
if (gKlibInitialized != 1)
|
2021-03-10 13:43:59 +00:00
|
|
|
{
|
|
|
|
return STATUS_UNSUCCESSFUL;
|
|
|
|
}
|
|
|
|
|
|
|
|
// if we have the function exported from the kernel, use it
|
|
|
|
if (pfnRtlQueryModuleInformation != NULL)
|
|
|
|
{
|
|
|
|
return pfnRtlQueryModuleInformation(InformationLength, SizePerModule, ModuleInfo);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (SizePerModule != sizeof(AUX_MODULE_BASIC_INFO) &&
|
|
|
|
SizePerModule != sizeof(AUX_MODULE_EXTENDED_INFO))
|
|
|
|
{
|
|
|
|
return STATUS_INVALID_PARAMETER_2;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ((ULONG_PTR)ModuleInfo & (TYPE_ALIGNMENT(AUX_MODULE_EXTENDED_INFO) - 1))
|
|
|
|
{
|
|
|
|
return STATUS_INVALID_PARAMETER_3;
|
|
|
|
}
|
|
|
|
|
|
|
|
// first call the function with a place for only 1 module
|
|
|
|
RTL_PROCESS_MODULES processModulesMinimal;
|
|
|
|
PRTL_PROCESS_MODULES processModules = &processModulesMinimal;
|
|
|
|
ULONG sysInfoLength = sizeof(processModulesMinimal);
|
|
|
|
ULONG resultLength;
|
2021-06-11 12:29:21 +00:00
|
|
|
|
2021-03-10 13:43:59 +00:00
|
|
|
// loop until we have a large-enough buffer for all modules
|
|
|
|
do
|
|
|
|
{
|
|
|
|
status = ZwQuerySystemInformation(SystemModuleInformation,
|
|
|
|
processModules,
|
|
|
|
sysInfoLength,
|
|
|
|
&resultLength);
|
|
|
|
|
|
|
|
if (status == STATUS_INFO_LENGTH_MISMATCH)
|
|
|
|
{
|
|
|
|
// free the old buffer if it's not the first one
|
|
|
|
if (processModules != &processModulesMinimal)
|
|
|
|
{
|
|
|
|
ExFreePoolWithTag(processModules, TAG_AUXK);
|
|
|
|
}
|
|
|
|
|
|
|
|
_SEH2_TRY
|
|
|
|
{
|
|
|
|
// allocate the new one
|
|
|
|
processModules = ExAllocatePoolWithQuotaTag(PagedPool, resultLength, TAG_AUXK);
|
|
|
|
}
|
|
|
|
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
|
|
|
|
{
|
|
|
|
_SEH2_YIELD(return _SEH2_GetExceptionCode());
|
|
|
|
}
|
|
|
|
_SEH2_END;
|
|
|
|
|
|
|
|
if (!processModules)
|
|
|
|
{
|
|
|
|
return STATUS_INSUFFICIENT_RESOURCES;
|
|
|
|
}
|
|
|
|
sysInfoLength = resultLength;
|
|
|
|
}
|
|
|
|
|
|
|
|
} while (status == STATUS_INFO_LENGTH_MISMATCH);
|
|
|
|
|
|
|
|
if (!NT_SUCCESS(status))
|
|
|
|
{
|
|
|
|
goto Cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
ULONG modulesSize;
|
|
|
|
status = RtlULongMult(SizePerModule, processModules->NumberOfModules, &modulesSize);
|
|
|
|
if (!NT_SUCCESS(status))
|
|
|
|
{
|
|
|
|
goto Cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (ModuleInfo == NULL)
|
|
|
|
{
|
|
|
|
ASSERT(status == STATUS_SUCCESS);
|
|
|
|
*InformationLength = modulesSize;
|
|
|
|
goto Cleanup;
|
|
|
|
}
|
|
|
|
|
2021-06-11 12:29:21 +00:00
|
|
|
if (*InformationLength < modulesSize)
|
2021-03-10 13:43:59 +00:00
|
|
|
{
|
|
|
|
status = STATUS_BUFFER_TOO_SMALL;
|
|
|
|
*InformationLength = modulesSize;
|
|
|
|
goto Cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
// copy the information to the input array
|
2021-06-11 12:29:21 +00:00
|
|
|
for (UINT32 i = 0; i < processModules->NumberOfModules; i++)
|
2021-03-10 13:43:59 +00:00
|
|
|
{
|
|
|
|
ModuleInfo[i].BasicInfo.ImageBase = processModules->Modules[i].ImageBase;
|
|
|
|
|
|
|
|
if (SizePerModule == sizeof(AUX_MODULE_EXTENDED_INFO))
|
|
|
|
{
|
|
|
|
ModuleInfo[i].ImageSize = processModules->Modules[i].ImageSize;
|
|
|
|
ModuleInfo[i].FileNameOffset = processModules->Modules[i].OffsetToFileName;
|
|
|
|
RtlCopyMemory(&ModuleInfo[i].FullPathName,
|
|
|
|
processModules->Modules[i].FullPathName,
|
|
|
|
sizeof(processModules->Modules[i].FullPathName));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
Cleanup:
|
|
|
|
// don't accidentally free the stack buffer
|
|
|
|
if (processModules != NULL && processModules != &processModulesMinimal)
|
|
|
|
{
|
|
|
|
ExFreePoolWithTag(processModules, TAG_AUXK);
|
|
|
|
}
|
|
|
|
|
|
|
|
return status;
|
|
|
|
}
|
|
|
|
|
|
|
|
NTSTATUS
|
|
|
|
AuxKlibGetBugCheckData(
|
|
|
|
_Inout_ PKBUGCHECK_DATA BugCheckData)
|
|
|
|
{
|
|
|
|
if (BugCheckData->BugCheckDataSize != sizeof(*BugCheckData))
|
|
|
|
{
|
|
|
|
return STATUS_INFO_LENGTH_MISMATCH;
|
|
|
|
}
|
|
|
|
|
|
|
|
BugCheckData->BugCheckCode = KiBugCheckData[0];
|
|
|
|
BugCheckData->Parameter1 = KiBugCheckData[1];
|
|
|
|
BugCheckData->Parameter2 = KiBugCheckData[2];
|
|
|
|
BugCheckData->Parameter3 = KiBugCheckData[3];
|
|
|
|
BugCheckData->Parameter4 = KiBugCheckData[4];
|
|
|
|
|
|
|
|
return STATUS_SUCCESS;
|
|
|
|
}
|
|
|
|
|
|
|
|
PIMAGE_EXPORT_DIRECTORY
|
|
|
|
AuxKlibGetImageExportDirectory(
|
|
|
|
_In_ PVOID ImageBase)
|
|
|
|
{
|
|
|
|
ULONG size;
|
|
|
|
return RtlImageDirectoryEntryToData(ImageBase, TRUE, IMAGE_DIRECTORY_ENTRY_EXPORT, &size);
|
|
|
|
}
|
|
|
|
|
|
|
|
_IRQL_requires_max_(PASSIVE_LEVEL)
|
|
|
|
CODE_SEG("PAGE")
|
|
|
|
NTSTATUS
|
|
|
|
NTAPI
|
|
|
|
AuxKlibEnumerateSystemFirmwareTables (
|
|
|
|
_In_ ULONG FirmwareTableProviderSignature,
|
|
|
|
_Out_writes_bytes_to_opt_(BufferLength, *ReturnLength) PVOID FirmwareTableBuffer,
|
|
|
|
_In_ ULONG BufferLength,
|
|
|
|
_Out_opt_ PULONG ReturnLength)
|
|
|
|
{
|
|
|
|
return STATUS_NOT_IMPLEMENTED;
|
|
|
|
}
|
|
|
|
|
|
|
|
_IRQL_requires_max_(PASSIVE_LEVEL)
|
|
|
|
CODE_SEG("PAGE")
|
|
|
|
NTSTATUS
|
|
|
|
NTAPI
|
|
|
|
AuxKlibGetSystemFirmwareTable (
|
|
|
|
_In_ ULONG FirmwareTableProviderSignature,
|
|
|
|
_In_ ULONG FirmwareTableID,
|
|
|
|
_Out_writes_bytes_to_opt_(BufferLength, *ReturnLength) PVOID FirmwareTableBuffer,
|
|
|
|
_In_ ULONG BufferLength,
|
|
|
|
_Out_opt_ PULONG ReturnLength)
|
|
|
|
{
|
|
|
|
return STATUS_NOT_IMPLEMENTED;
|
|
|
|
}
|