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