/* * 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 #define NDEBUG #include 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 */