reactos/sdk/lib/drivers/aux_klib/aux_klib.c
2021-06-11 15:33:08 +03:00

229 lines
6.2 KiB
C

/*
* 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();
if (gKlibInitialized != 1)
{
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;
// 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;
}
if (*InformationLength < modulesSize)
{
status = STATUS_BUFFER_TOO_SMALL;
*InformationLength = modulesSize;
goto Cleanup;
}
// copy the information to the input array
for (UINT32 i = 0; i < processModules->NumberOfModules; i++)
{
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;
}