[RTL]: Document and flesh out Boot Status Data (BSD) API/Structures
[reactos.git] / sdk / lib / rtl / bootdata.c
1 /*
2 * PROJECT: ReactOS Runtime Library
3 * LICENSE: See COPYING in the top level directory
4 * FILE: lib/rtl/bootdata.c
5 * PURPOSE: Boot Status Data Implementation
6 * PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org)
7 * Eric Kohl
8 */
9
10 /* INCLUDES *****************************************************************/
11
12 #include <rtl.h>
13 #define NDEBUG
14 #include <debug.h>
15
16 typedef struct _RTL_BSD_ITEM_TABLE_ENTRY
17 {
18 UCHAR Offset;
19 UCHAR Size;
20 } RTL_BSD_ITEM_TABLE_ENTRY;
21
22 /* FUNCTIONS *****************************************************************/
23
24 PRTL_BSD_DATA DummyBsd;
25 RTL_BSD_ITEM_TABLE_ENTRY BsdItemTable[RtlBsdItemMax] =
26 {
27 {
28 FIELD_OFFSET(RTL_BSD_DATA, Version),
29 sizeof(&DummyBsd->Version)
30 }, // RtlBsdItemVersionNumber
31 {
32 FIELD_OFFSET(RTL_BSD_DATA, ProductType),
33 sizeof(&DummyBsd->ProductType)
34 }, // RtlBsdItemProductType
35 {
36 FIELD_OFFSET(RTL_BSD_DATA, AabEnabled),
37 sizeof(&DummyBsd->AabEnabled)
38 }, // RtlBsdItemAabEnabled
39 {
40 FIELD_OFFSET(RTL_BSD_DATA, AabTimeout),
41 sizeof(&DummyBsd->AabTimeout)
42 }, // RtlBsdItemAabTimeout
43 {
44 FIELD_OFFSET(RTL_BSD_DATA, LastBootSucceeded),
45 sizeof(&DummyBsd->LastBootSucceeded)
46 }, // RtlBsdItemBootGood
47 {
48 FIELD_OFFSET(RTL_BSD_DATA, LastBootShutdown),
49 sizeof(&DummyBsd->LastBootShutdown)
50 }, // RtlBsdItemBootShutdown
51 {
52 FIELD_OFFSET(RTL_BSD_DATA, SleepInProgress),
53 sizeof(&DummyBsd->SleepInProgress)
54 }, // RtlBsdSleepInProgress
55 {
56 FIELD_OFFSET(RTL_BSD_DATA, PowerTransition),
57 sizeof(&DummyBsd->PowerTransition)
58 }, // RtlBsdPowerTransition
59 {
60 FIELD_OFFSET(RTL_BSD_DATA, BootAttemptCount),
61 sizeof(&DummyBsd->BootAttemptCount)
62 }, // RtlBsdItemBootAttemptCount
63 {
64 FIELD_OFFSET(RTL_BSD_DATA, LastBootCheckpoint),
65 sizeof(&DummyBsd->LastBootCheckpoint)
66 }, // RtlBsdItemBootCheckpoint
67 {
68 FIELD_OFFSET(RTL_BSD_DATA, LastBootId),
69 sizeof(&DummyBsd->LastBootId)
70 }, // RtlBsdItemBootId
71 {
72 FIELD_OFFSET(RTL_BSD_DATA, LastSuccessfulShutdownBootId),
73 sizeof(&DummyBsd->LastSuccessfulShutdownBootId)
74 }, // RtlBsdItemShutdownBootId
75 {
76 FIELD_OFFSET(RTL_BSD_DATA, LastReportedAbnormalShutdownBootId),
77 sizeof(&DummyBsd->LastReportedAbnormalShutdownBootId)
78 }, // RtlBsdItemReportedAbnormalShutdownBootId
79 {
80 FIELD_OFFSET(RTL_BSD_DATA, ErrorInfo),
81 sizeof(&DummyBsd->ErrorInfo)
82 }, // RtlBsdItemErrorInfo
83 {
84 FIELD_OFFSET(RTL_BSD_DATA, PowerButtonPressInfo),
85 sizeof(&DummyBsd->PowerButtonPressInfo)
86 }, // RtlBsdItemPowerButtonPressInfo
87 {
88 FIELD_OFFSET(RTL_BSD_DATA, Checksum),
89 sizeof(&DummyBsd->Checksum)
90 }, // RtlBsdItemChecksum
91 };
92
93 /*
94 * @implemented
95 */
96 NTSTATUS
97 NTAPI
98 RtlCreateBootStatusDataFile (
99 VOID
100 )
101 {
102 IO_STATUS_BLOCK IoStatusBlock;
103 LARGE_INTEGER AllocationSize;
104 LARGE_INTEGER ByteOffset;
105 UNICODE_STRING FileName =
106 RTL_CONSTANT_STRING(L"\\SystemRoot\\bootstat.dat");
107 OBJECT_ATTRIBUTES ObjectAttributes =
108 RTL_CONSTANT_OBJECT_ATTRIBUTES(&FileName, OBJ_CASE_INSENSITIVE);
109 HANDLE FileHandle;
110 NTSTATUS Status;
111 RTL_BSD_DATA InitialBsd;
112
113 /* Create the boot status data file */
114 AllocationSize.QuadPart = 0x800;
115 DBG_UNREFERENCED_LOCAL_VARIABLE(AllocationSize);
116 Status = ZwCreateFile(&FileHandle,
117 FILE_GENERIC_READ | FILE_GENERIC_WRITE,
118 &ObjectAttributes,
119 &IoStatusBlock,
120 NULL, //&AllocationSize,
121 FILE_ATTRIBUTE_SYSTEM,
122 0,
123 FILE_CREATE,
124 FILE_SYNCHRONOUS_IO_NONALERT,
125 NULL,
126 0);
127 if (NT_SUCCESS(Status))
128 {
129 /* Setup a sane looking initial BSD */
130 RtlZeroMemory(&InitialBsd, sizeof(InitialBsd));
131 InitialBsd.Version = sizeof(InitialBsd);
132 InitialBsd.ProductType = NtProductWinNt;
133 InitialBsd.AabEnabled = 1;
134 InitialBsd.AabTimeout = 30;
135 InitialBsd.LastBootSucceeded = TRUE;
136
137 /* Write it to disk */
138 ByteOffset.QuadPart = 0;
139 Status = ZwWriteFile(FileHandle,
140 NULL,
141 NULL,
142 NULL,
143 &IoStatusBlock,
144 &InitialBsd,
145 sizeof(InitialBsd),
146 &ByteOffset,
147 NULL);
148 }
149
150 /* Close the file */
151 ZwClose(FileHandle);
152
153 return Status;
154 }
155
156 /*
157 * @implemented
158 */
159 NTSTATUS
160 NTAPI
161 RtlGetSetBootStatusData (
162 _In_ HANDLE FileHandle,
163 _In_ BOOLEAN Read,
164 _In_ RTL_BSD_ITEM_TYPE DataClass,
165 _In_ PVOID Buffer,
166 _In_ ULONG BufferSize,
167 _Out_opt_ PULONG ReturnLength
168 )
169 {
170 IO_STATUS_BLOCK IoStatusBlock;
171 LARGE_INTEGER ByteOffset;
172 NTSTATUS Status;
173
174 DPRINT("RtlGetSetBootStatusData (%p %u %d %p %lu %p)\n",
175 FileHandle, Read, DataClass, Buffer, BufferSize, ReturnLength);
176
177 if (DataClass >= RtlBsdItemMax)
178 {
179 return STATUS_INVALID_PARAMETER;
180 }
181
182 if (BufferSize > BsdItemTable[DataClass].Size)
183 {
184 return STATUS_BUFFER_TOO_SMALL;
185 }
186
187 ByteOffset.HighPart = 0;
188 ByteOffset.LowPart = BsdItemTable[DataClass].Offset;
189
190 if (Read)
191 {
192 Status = ZwReadFile(FileHandle,
193 NULL,
194 NULL,
195 NULL,
196 &IoStatusBlock,
197 Buffer,
198 BufferSize,
199 &ByteOffset,
200 NULL);
201 }
202 else
203 {
204 Status = ZwWriteFile(FileHandle,
205 NULL,
206 NULL,
207 NULL,
208 &IoStatusBlock,
209 Buffer,
210 BufferSize,
211 &ByteOffset,
212 NULL);
213 }
214
215 if (NT_SUCCESS(Status))
216 {
217 if (ReturnLength)
218 {
219 *ReturnLength = BsdItemTable[DataClass].Size;
220 }
221 }
222
223 return Status;
224 }
225
226 /*
227 * @implemented
228 */
229 NTSTATUS
230 NTAPI
231 RtlLockBootStatusData (
232 _Out_ PHANDLE FileHandle
233 )
234 {
235 UNICODE_STRING FileName =
236 RTL_CONSTANT_STRING(L"\\SystemRoot\\bootstat.dat");
237 OBJECT_ATTRIBUTES ObjectAttributes =
238 RTL_CONSTANT_OBJECT_ATTRIBUTES(&FileName, OBJ_CASE_INSENSITIVE);
239 HANDLE LocalFileHandle;
240 NTSTATUS Status;
241 IO_STATUS_BLOCK IoStatusBlock;
242
243 /* Intialize the file handle */
244 *FileHandle = NULL;
245
246 /* Open the boot status data file */
247 Status = ZwOpenFile(&LocalFileHandle,
248 FILE_ALL_ACCESS,
249 &ObjectAttributes,
250 &IoStatusBlock,
251 0,
252 FILE_SYNCHRONOUS_IO_NONALERT);
253 if (NT_SUCCESS(Status))
254 {
255 /* Return the file handle */
256 *FileHandle = LocalFileHandle;
257 }
258
259 return Status;
260 }
261
262 /*
263 * @implemented
264 */
265 NTSTATUS
266 NTAPI
267 RtlUnlockBootStatusData (
268 _In_ HANDLE FileHandle
269 )
270 {
271 IO_STATUS_BLOCK IoStatusBlock;
272
273 /* Flush the file and close it */
274 ZwFlushBuffersFile(FileHandle, &IoStatusBlock);
275 return ZwClose(FileHandle);
276 }
277
278 /* EOF */