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