mirror of
https://github.com/reactos/reactos.git
synced 2026-10-18 08:41:56 +08:00
With Windows 10/11 new enum fields were added to RTL_BSD_ITEM_TYPE namely RtlBsdPowerTransitionExtension, RtlBsdItemFeatureConfigurationState and RtlBsdItemRevocationListInfo. Currently there's no information about what fields does RTL_BSD_ITEM_REVOCATION_LIST have at the moment, so it's stubbed out. RTL_BSD_DATA_POWER_TRANSITION_EXTENSION is used by RtlBsdPowerTransitionExtension that contains extended power information such as critical thermal shutdown and whatnot. The source of these fields is from PHNT -> https://github.com/winsiderss/systeminformer/blob/master/phnt/include/ntrtl.h#L15124 That stuff is particularly useful when working futher on RSOH (the Red Screen of Hell feature) as we can use RtlGetSetBootStatusData to set the thermal condition bit and have this popup screen be displayed on next boot if the kernel finds out the system was running too hot.
291 lines
7.9 KiB
C
291 lines
7.9 KiB
C
/*
|
|
* PROJECT: ReactOS Runtime Library
|
|
* LICENSE: See COPYING in the top level directory
|
|
* FILE: lib/rtl/bootdata.c
|
|
* PURPOSE: Boot Status Data Implementation
|
|
* PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org)
|
|
* Eric Kohl
|
|
*/
|
|
|
|
/* INCLUDES *****************************************************************/
|
|
|
|
#include <rtl.h>
|
|
#define NDEBUG
|
|
#include <debug.h>
|
|
|
|
typedef struct _RTL_BSD_ITEM_TABLE_ENTRY
|
|
{
|
|
UCHAR Offset;
|
|
UCHAR Size;
|
|
} RTL_BSD_ITEM_TABLE_ENTRY;
|
|
|
|
/* FUNCTIONS *****************************************************************/
|
|
|
|
PRTL_BSD_DATA DummyBsd;
|
|
RTL_BSD_ITEM_TABLE_ENTRY BsdItemTable[RtlBsdItemMax] =
|
|
{
|
|
{
|
|
FIELD_OFFSET(RTL_BSD_DATA, Version),
|
|
sizeof(&DummyBsd->Version)
|
|
}, // RtlBsdItemVersionNumber
|
|
{
|
|
FIELD_OFFSET(RTL_BSD_DATA, ProductType),
|
|
sizeof(&DummyBsd->ProductType)
|
|
}, // RtlBsdItemProductType
|
|
{
|
|
FIELD_OFFSET(RTL_BSD_DATA, AabEnabled),
|
|
sizeof(&DummyBsd->AabEnabled)
|
|
}, // RtlBsdItemAabEnabled
|
|
{
|
|
FIELD_OFFSET(RTL_BSD_DATA, AabTimeout),
|
|
sizeof(&DummyBsd->AabTimeout)
|
|
}, // RtlBsdItemAabTimeout
|
|
{
|
|
FIELD_OFFSET(RTL_BSD_DATA, LastBootSucceeded),
|
|
sizeof(&DummyBsd->LastBootSucceeded)
|
|
}, // RtlBsdItemBootGood
|
|
{
|
|
FIELD_OFFSET(RTL_BSD_DATA, LastBootShutdown),
|
|
sizeof(&DummyBsd->LastBootShutdown)
|
|
}, // RtlBsdItemBootShutdown
|
|
{
|
|
FIELD_OFFSET(RTL_BSD_DATA, SleepInProgress),
|
|
sizeof(&DummyBsd->SleepInProgress)
|
|
}, // RtlBsdSleepInProgress
|
|
{
|
|
FIELD_OFFSET(RTL_BSD_DATA, PowerTransition),
|
|
sizeof(&DummyBsd->PowerTransition)
|
|
}, // RtlBsdPowerTransition
|
|
{
|
|
FIELD_OFFSET(RTL_BSD_DATA, BootAttemptCount),
|
|
sizeof(&DummyBsd->BootAttemptCount)
|
|
}, // RtlBsdItemBootAttemptCount
|
|
{
|
|
FIELD_OFFSET(RTL_BSD_DATA, LastBootCheckpoint),
|
|
sizeof(&DummyBsd->LastBootCheckpoint)
|
|
}, // RtlBsdItemBootCheckpoint
|
|
{
|
|
FIELD_OFFSET(RTL_BSD_DATA, LastBootId),
|
|
sizeof(&DummyBsd->LastBootId)
|
|
}, // RtlBsdItemBootId
|
|
{
|
|
FIELD_OFFSET(RTL_BSD_DATA, LastSuccessfulShutdownBootId),
|
|
sizeof(&DummyBsd->LastSuccessfulShutdownBootId)
|
|
}, // RtlBsdItemShutdownBootId
|
|
{
|
|
FIELD_OFFSET(RTL_BSD_DATA, LastReportedAbnormalShutdownBootId),
|
|
sizeof(&DummyBsd->LastReportedAbnormalShutdownBootId)
|
|
}, // RtlBsdItemReportedAbnormalShutdownBootId
|
|
{
|
|
FIELD_OFFSET(RTL_BSD_DATA, ErrorInfo),
|
|
sizeof(&DummyBsd->ErrorInfo)
|
|
}, // RtlBsdItemErrorInfo
|
|
{
|
|
FIELD_OFFSET(RTL_BSD_DATA, PowerButtonPressInfo),
|
|
sizeof(&DummyBsd->PowerButtonPressInfo)
|
|
}, // RtlBsdItemPowerButtonPressInfo
|
|
{
|
|
FIELD_OFFSET(RTL_BSD_DATA, Checksum),
|
|
sizeof(&DummyBsd->Checksum)
|
|
}, // RtlBsdItemChecksum
|
|
{
|
|
FIELD_OFFSET(RTL_BSD_DATA, PowerTransitionExtension),
|
|
sizeof(&DummyBsd->PowerTransitionExtension)
|
|
}, // RtlBsdPowerTransitionExtension
|
|
{
|
|
FIELD_OFFSET(RTL_BSD_DATA, ItemFeatureConfigState),
|
|
sizeof(&DummyBsd->ItemFeatureConfigState)
|
|
}, // RtlBsdItemFeatureConfigurationState
|
|
{
|
|
FIELD_OFFSET(RTL_BSD_DATA, ItemRevocationList),
|
|
sizeof(&DummyBsd->ItemRevocationList)
|
|
}, // RtlBsdItemRevocationListInfo
|
|
};
|
|
|
|
/*
|
|
* @implemented
|
|
*/
|
|
NTSTATUS
|
|
NTAPI
|
|
RtlCreateBootStatusDataFile (
|
|
VOID
|
|
)
|
|
{
|
|
IO_STATUS_BLOCK IoStatusBlock;
|
|
LARGE_INTEGER AllocationSize;
|
|
LARGE_INTEGER ByteOffset;
|
|
UNICODE_STRING FileName =
|
|
RTL_CONSTANT_STRING(L"\\SystemRoot\\bootstat.dat");
|
|
OBJECT_ATTRIBUTES ObjectAttributes =
|
|
RTL_CONSTANT_OBJECT_ATTRIBUTES(&FileName, OBJ_CASE_INSENSITIVE);
|
|
HANDLE FileHandle;
|
|
NTSTATUS Status;
|
|
RTL_BSD_DATA InitialBsd;
|
|
|
|
/* Create the boot status data file */
|
|
AllocationSize.QuadPart = 0x800;
|
|
DBG_UNREFERENCED_LOCAL_VARIABLE(AllocationSize);
|
|
Status = ZwCreateFile(&FileHandle,
|
|
FILE_GENERIC_READ | FILE_GENERIC_WRITE,
|
|
&ObjectAttributes,
|
|
&IoStatusBlock,
|
|
NULL, //&AllocationSize,
|
|
FILE_ATTRIBUTE_SYSTEM,
|
|
0,
|
|
FILE_CREATE,
|
|
FILE_SYNCHRONOUS_IO_NONALERT,
|
|
NULL,
|
|
0);
|
|
if (NT_SUCCESS(Status))
|
|
{
|
|
/* Setup a sane looking initial BSD */
|
|
RtlZeroMemory(&InitialBsd, sizeof(InitialBsd));
|
|
InitialBsd.Version = sizeof(InitialBsd);
|
|
InitialBsd.ProductType = NtProductWinNt;
|
|
InitialBsd.AabEnabled = 1;
|
|
InitialBsd.AabTimeout = 30;
|
|
InitialBsd.LastBootSucceeded = TRUE;
|
|
|
|
/* Write it to disk */
|
|
ByteOffset.QuadPart = 0;
|
|
Status = ZwWriteFile(FileHandle,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
&IoStatusBlock,
|
|
&InitialBsd,
|
|
sizeof(InitialBsd),
|
|
&ByteOffset,
|
|
NULL);
|
|
}
|
|
|
|
/* Close the file */
|
|
ZwClose(FileHandle);
|
|
|
|
return Status;
|
|
}
|
|
|
|
/*
|
|
* @implemented
|
|
*/
|
|
NTSTATUS
|
|
NTAPI
|
|
RtlGetSetBootStatusData (
|
|
_In_ HANDLE FileHandle,
|
|
_In_ BOOLEAN Read,
|
|
_In_ RTL_BSD_ITEM_TYPE DataClass,
|
|
_In_ PVOID Buffer,
|
|
_In_ ULONG BufferSize,
|
|
_Out_opt_ PULONG ReturnLength
|
|
)
|
|
{
|
|
IO_STATUS_BLOCK IoStatusBlock;
|
|
LARGE_INTEGER ByteOffset;
|
|
NTSTATUS Status;
|
|
|
|
DPRINT("RtlGetSetBootStatusData (%p %u %d %p %lu %p)\n",
|
|
FileHandle, Read, DataClass, Buffer, BufferSize, ReturnLength);
|
|
|
|
if (DataClass >= RtlBsdItemMax)
|
|
{
|
|
return STATUS_INVALID_PARAMETER;
|
|
}
|
|
|
|
if (BufferSize > BsdItemTable[DataClass].Size)
|
|
{
|
|
return STATUS_BUFFER_TOO_SMALL;
|
|
}
|
|
|
|
ByteOffset.HighPart = 0;
|
|
ByteOffset.LowPart = BsdItemTable[DataClass].Offset;
|
|
|
|
if (Read)
|
|
{
|
|
Status = ZwReadFile(FileHandle,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
&IoStatusBlock,
|
|
Buffer,
|
|
BufferSize,
|
|
&ByteOffset,
|
|
NULL);
|
|
}
|
|
else
|
|
{
|
|
Status = ZwWriteFile(FileHandle,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
&IoStatusBlock,
|
|
Buffer,
|
|
BufferSize,
|
|
&ByteOffset,
|
|
NULL);
|
|
}
|
|
|
|
if (NT_SUCCESS(Status))
|
|
{
|
|
if (ReturnLength)
|
|
{
|
|
*ReturnLength = BsdItemTable[DataClass].Size;
|
|
}
|
|
}
|
|
|
|
return Status;
|
|
}
|
|
|
|
/*
|
|
* @implemented
|
|
*/
|
|
NTSTATUS
|
|
NTAPI
|
|
RtlLockBootStatusData (
|
|
_Out_ PHANDLE FileHandle
|
|
)
|
|
{
|
|
UNICODE_STRING FileName =
|
|
RTL_CONSTANT_STRING(L"\\SystemRoot\\bootstat.dat");
|
|
OBJECT_ATTRIBUTES ObjectAttributes =
|
|
RTL_CONSTANT_OBJECT_ATTRIBUTES(&FileName, OBJ_CASE_INSENSITIVE);
|
|
HANDLE LocalFileHandle;
|
|
NTSTATUS Status;
|
|
IO_STATUS_BLOCK IoStatusBlock;
|
|
|
|
/* Intialize the file handle */
|
|
*FileHandle = NULL;
|
|
|
|
/* Open the boot status data file */
|
|
Status = ZwOpenFile(&LocalFileHandle,
|
|
FILE_ALL_ACCESS,
|
|
&ObjectAttributes,
|
|
&IoStatusBlock,
|
|
0,
|
|
FILE_SYNCHRONOUS_IO_NONALERT);
|
|
if (NT_SUCCESS(Status))
|
|
{
|
|
/* Return the file handle */
|
|
*FileHandle = LocalFileHandle;
|
|
}
|
|
|
|
return Status;
|
|
}
|
|
|
|
/*
|
|
* @implemented
|
|
*/
|
|
NTSTATUS
|
|
NTAPI
|
|
RtlUnlockBootStatusData (
|
|
_In_ HANDLE FileHandle
|
|
)
|
|
{
|
|
IO_STATUS_BLOCK IoStatusBlock;
|
|
|
|
/* Flush the file and close it */
|
|
ZwFlushBuffersFile(FileHandle, &IoStatusBlock);
|
|
return ZwClose(FileHandle);
|
|
}
|
|
|
|
/* EOF */
|