Sorry, most devices were reinstalled at each boot, as the calculated crc32 for the...
[reactos.git] / reactos / ntoskrnl / io / bootlog.c
1 /* $Id$
2 *
3 * COPYRIGHT: See COPYING in the top level directory
4 * PROJECT: ReactOS kernel
5 * FILE: ntoskrnl/io/bootlog.c
6 * PURPOSE: Boot log file support
7 *
8 * PROGRAMMERS: Eric Kohl
9 */
10
11 /* INCLUDES *****************************************************************/
12
13 #include <ntoskrnl.h>
14 #define NDEBUG
15 #include <internal/debug.h>
16
17
18 /* GLOBALS ******************************************************************/
19
20 static BOOLEAN IopBootLogCreate = FALSE;
21 static BOOLEAN IopBootLogEnabled = FALSE;
22 static BOOLEAN IopLogFileEnabled = FALSE;
23 static ULONG IopLogEntryCount = 0;
24 static ERESOURCE IopBootLogResource;
25
26
27 /* FUNCTIONS ****************************************************************/
28
29 VOID INIT_FUNCTION
30 IopInitBootLog(BOOLEAN StartBootLog)
31 {
32 ExInitializeResourceLite(&IopBootLogResource);
33 if (StartBootLog) IopStartBootLog();
34 }
35
36
37 VOID INIT_FUNCTION
38 IopStartBootLog(VOID)
39 {
40 IopBootLogCreate = TRUE;
41 IopBootLogEnabled = TRUE;
42 }
43
44
45 VOID
46 IopStopBootLog(VOID)
47 {
48 IopBootLogEnabled = FALSE;
49 }
50
51
52 VOID
53 IopBootLog(PUNICODE_STRING DriverName,
54 BOOLEAN Success)
55 {
56 OBJECT_ATTRIBUTES ObjectAttributes;
57 WCHAR Buffer[256];
58 WCHAR ValueNameBuffer[8];
59 UNICODE_STRING KeyName;
60 UNICODE_STRING ValueName;
61 HANDLE ControlSetKey;
62 HANDLE BootLogKey;
63 NTSTATUS Status;
64
65 if (IopBootLogEnabled == FALSE)
66 return;
67
68 ExAcquireResourceExclusiveLite(&IopBootLogResource, TRUE);
69
70 DPRINT("Boot log: %wS %wZ\n",
71 Success ? L"Loaded driver" : L"Did not load driver",
72 DriverName);
73
74 swprintf(Buffer,
75 L"%ws %wZ",
76 Success ? L"Loaded driver" : L"Did not load driver",
77 DriverName);
78
79 swprintf(ValueNameBuffer,
80 L"%lu",
81 IopLogEntryCount);
82
83 RtlInitUnicodeString(&KeyName,
84 L"\\Registry\\Machine\\System\\CurrentControlSet");
85 InitializeObjectAttributes(&ObjectAttributes,
86 &KeyName,
87 OBJ_CASE_INSENSITIVE,
88 NULL,
89 NULL);
90 Status = ZwOpenKey(&ControlSetKey,
91 KEY_ALL_ACCESS,
92 &ObjectAttributes);
93 if (!NT_SUCCESS(Status))
94 {
95 DPRINT1("ZwOpenKey() failed (Status %lx)\n", Status);
96 ExReleaseResourceLite(&IopBootLogResource);
97 return;
98 }
99
100 RtlInitUnicodeString(&KeyName, L"BootLog");
101 InitializeObjectAttributes(&ObjectAttributes,
102 &KeyName,
103 OBJ_CASE_INSENSITIVE | OBJ_OPENIF,
104 ControlSetKey,
105 NULL);
106 Status = ZwCreateKey(&BootLogKey,
107 KEY_ALL_ACCESS,
108 &ObjectAttributes,
109 0,
110 NULL,
111 REG_OPTION_NON_VOLATILE,
112 NULL);
113 if (!NT_SUCCESS(Status))
114 {
115 DPRINT1("ZwCreateKey() failed (Status %lx)\n", Status);
116 ZwClose(ControlSetKey);
117 ExReleaseResourceLite(&IopBootLogResource);
118 return;
119 }
120
121 RtlInitUnicodeString(&ValueName, ValueNameBuffer);
122 Status = ZwSetValueKey(BootLogKey,
123 &ValueName,
124 0,
125 REG_SZ,
126 (PVOID)Buffer,
127 (wcslen(Buffer) + 1) * sizeof(WCHAR));
128 ZwClose(BootLogKey);
129 ZwClose(ControlSetKey);
130
131 if (!NT_SUCCESS(Status))
132 {
133 DPRINT1("NtSetValueKey() failed (Status %lx)\n", Status);
134 }
135 else
136 {
137 IopLogEntryCount++;
138 }
139
140 ExReleaseResourceLite(&IopBootLogResource);
141 }
142
143
144 static NTSTATUS
145 IopWriteLogFile(PWSTR LogText)
146 {
147 OBJECT_ATTRIBUTES ObjectAttributes;
148 UNICODE_STRING FileName;
149 IO_STATUS_BLOCK IoStatusBlock;
150 HANDLE FileHandle;
151 PWSTR CrLf = L"\r\n";
152 NTSTATUS Status;
153
154 DPRINT("IopWriteLogFile() called\n");
155
156 RtlInitUnicodeString(&FileName,
157 L"\\SystemRoot\\rosboot.log");
158 InitializeObjectAttributes(&ObjectAttributes,
159 &FileName,
160 OBJ_CASE_INSENSITIVE | OBJ_OPENIF,
161 NULL,
162 NULL);
163
164 Status = ZwCreateFile(&FileHandle,
165 FILE_APPEND_DATA,
166 &ObjectAttributes,
167 &IoStatusBlock,
168 NULL,
169 0,
170 0,
171 FILE_OPEN,
172 FILE_NON_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT,
173 NULL,
174 0);
175 if (!NT_SUCCESS(Status))
176 {
177 DPRINT1("ZwCreateFile() failed (Status %lx)\n", Status);
178 return Status;
179 }
180
181 if (LogText != NULL)
182 {
183 Status = ZwWriteFile(FileHandle,
184 NULL,
185 NULL,
186 NULL,
187 &IoStatusBlock,
188 (PVOID)LogText,
189 wcslen(LogText) * sizeof(WCHAR),
190 NULL,
191 NULL);
192 if (!NT_SUCCESS(Status))
193 {
194 DPRINT1("ZwWriteFile() failed (Status %lx)\n", Status);
195 ZwClose(FileHandle);
196 return Status;
197 }
198 }
199
200 /* L"\r\n" */
201 Status = ZwWriteFile(FileHandle,
202 NULL,
203 NULL,
204 NULL,
205 &IoStatusBlock,
206 (PVOID)CrLf,
207 2 * sizeof(WCHAR),
208 NULL,
209 NULL);
210
211 ZwClose(FileHandle);
212
213 if (!NT_SUCCESS(Status))
214 {
215 DPRINT1("ZwWriteFile() failed (Status %lx)\n", Status);
216 }
217
218 return Status;
219 }
220
221
222 static NTSTATUS
223 IopCreateLogFile(VOID)
224 {
225 OBJECT_ATTRIBUTES ObjectAttributes;
226 UNICODE_STRING FileName;
227 IO_STATUS_BLOCK IoStatusBlock;
228 HANDLE FileHandle;
229 LARGE_INTEGER ByteOffset;
230 WCHAR Signature;
231 NTSTATUS Status;
232
233 DPRINT("IopSaveBootLogToFile() called\n");
234
235 ExAcquireResourceExclusiveLite(&IopBootLogResource, TRUE);
236
237 RtlInitUnicodeString(&FileName,
238 L"\\SystemRoot\\rosboot.log");
239 InitializeObjectAttributes(&ObjectAttributes,
240 &FileName,
241 OBJ_CASE_INSENSITIVE | OBJ_OPENIF,
242 NULL,
243 NULL);
244
245 Status = ZwCreateFile(&FileHandle,
246 FILE_ALL_ACCESS,
247 &ObjectAttributes,
248 &IoStatusBlock,
249 NULL,
250 0,
251 0,
252 FILE_SUPERSEDE,
253 FILE_NON_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT,
254 NULL,
255 0);
256 if (!NT_SUCCESS(Status))
257 {
258 DPRINT1("ZwCreateFile() failed (Status %lx)\n", Status);
259 return Status;
260 }
261
262 ByteOffset.QuadPart = (LONGLONG)0;
263
264 Signature = 0xFEFF;
265 Status = ZwWriteFile(FileHandle,
266 NULL,
267 NULL,
268 NULL,
269 &IoStatusBlock,
270 (PVOID)&Signature,
271 sizeof(WCHAR),
272 &ByteOffset,
273 NULL);
274 if (!NT_SUCCESS(Status))
275 {
276 DPRINT1("ZwWriteKey() failed (Status %lx)\n", Status);
277 }
278
279 ZwClose(FileHandle);
280
281 return Status;
282 }
283
284
285 VOID
286 IopSaveBootLogToFile(VOID)
287 {
288 PKEY_VALUE_PARTIAL_INFORMATION KeyInfo;
289 WCHAR ValueNameBuffer[8];
290 OBJECT_ATTRIBUTES ObjectAttributes;
291 UNICODE_STRING KeyName;
292 UNICODE_STRING ValueName;
293 HANDLE KeyHandle;
294 ULONG BufferSize;
295 ULONG ResultLength;
296 ULONG i;
297 NTSTATUS Status;
298
299 if (IopBootLogCreate == FALSE)
300 return;
301
302 DPRINT("IopSaveBootLogToFile() called\n");
303
304 ExAcquireResourceExclusiveLite(&IopBootLogResource, TRUE);
305
306 Status = IopCreateLogFile();
307 if (!NT_SUCCESS(Status))
308 {
309 DPRINT1("IopCreateLogFile() failed (Status %lx)\n", Status);
310 ExReleaseResourceLite(&IopBootLogResource);
311 return;
312 }
313
314 Status = IopWriteLogFile(L"ReactOS "KERNEL_VERSION_STR);
315 if (!NT_SUCCESS(Status))
316 {
317 DPRINT1("IopWriteLogFile() failed (Status %lx)\n", Status);
318 ExReleaseResourceLite(&IopBootLogResource);
319 return;
320 }
321
322 Status = IopWriteLogFile(NULL);
323 if (!NT_SUCCESS(Status))
324 {
325 DPRINT1("IopWriteLogFile() failed (Status %lx)\n", Status);
326 ExReleaseResourceLite(&IopBootLogResource);
327 return;
328 }
329
330
331 BufferSize = sizeof(KEY_VALUE_PARTIAL_INFORMATION) + 256 * sizeof(WCHAR);
332 KeyInfo = ExAllocatePool(PagedPool,
333 BufferSize);
334 if (KeyInfo == NULL)
335 {
336 CHECKPOINT1;
337 ExReleaseResourceLite(&IopBootLogResource);
338 return;
339 }
340
341 RtlInitUnicodeString(&KeyName,
342 L"\\Registry\\Machine\\System\\CurrentControlSet\\BootLog");
343 InitializeObjectAttributes(&ObjectAttributes,
344 &KeyName,
345 OBJ_CASE_INSENSITIVE,
346 NULL,
347 NULL);
348 Status = ZwOpenKey(&KeyHandle,
349 KEY_ALL_ACCESS,
350 &ObjectAttributes);
351 if (!NT_SUCCESS(Status))
352 {
353 CHECKPOINT1;
354 ExFreePool(KeyInfo);
355 ExReleaseResourceLite(&IopBootLogResource);
356 return;
357 }
358
359 for (i = 0; ; i++)
360 {
361 swprintf(ValueNameBuffer,
362 L"%lu", i);
363
364 RtlInitUnicodeString(&ValueName,
365 ValueNameBuffer);
366
367 Status = ZwQueryValueKey(KeyHandle,
368 &ValueName,
369 KeyValuePartialInformation,
370 KeyInfo,
371 BufferSize,
372 &ResultLength);
373 if (Status == STATUS_OBJECT_NAME_NOT_FOUND)
374 {
375 break;
376 }
377
378 if (!NT_SUCCESS(Status))
379 {
380 CHECKPOINT1;
381 ZwClose(KeyHandle);
382 ExFreePool(KeyInfo);
383 ExReleaseResourceLite(&IopBootLogResource);
384 return;
385 }
386
387 Status = IopWriteLogFile((PWSTR)&KeyInfo->Data);
388 if (!NT_SUCCESS(Status))
389 {
390 CHECKPOINT1;
391 ZwClose(KeyHandle);
392 ExFreePool(KeyInfo);
393 ExReleaseResourceLite(&IopBootLogResource);
394 return;
395 }
396
397 /* Delete keys */
398 ZwDeleteValueKey(KeyHandle,
399 &ValueName);
400 }
401
402 ZwClose(KeyHandle);
403
404 ExFreePool(KeyInfo);
405
406 IopLogFileEnabled = TRUE;
407 ExReleaseResourceLite(&IopBootLogResource);
408
409 DPRINT("IopSaveBootLogToFile() done\n");
410 }
411
412 /* EOF */