mirror of
https://github.com/reactos/reactos.git
synced 2024-08-26 05:08:39 +00:00
![Alex Ionescu](/assets/img/avatar_default.png)
[NDK]: Document latest RTL_BSD_DATA as of RS3 based on ext.dll WinDBG extension "!blackboxbsd" which outputs the entire structure field by field :). [NDK]: Update RTL_BSD_ITEM_TYPE thanks to ole32 symbols [RTL]: Move system volume APIs to sysvol.c [RTL]: Fill out BsdItemTable based on actual field offsets/sizes and not hardcoded magic numbers which we won't ask where they came from. [RTL]: Make RtlCreateBootStatusDataFile use an appropriate structure for initializing the buffer instead of "UCHAR Buffer[12] = {0xC,0,0,0, 1,0,0,0, 1, 0x1e, 1, 0};" which appears like magic knowledge. [RTL]: Rename "WriteMode" to "Read" in RtlGetSetBootStatusData since it's much less confusing. [RTL]: Some formatting fixes, SAL updates.
279 lines
7.4 KiB
C
279 lines
7.4 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
|
|
};
|
|
|
|
/*
|
|
* @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 */
|