1 /* 2 * COPYRIGHT: See COPYING in the top level directory 3 * PROJECT: ReactOS kernel 4 * FILE: ntoskrnl/io/iomgr/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 INIT_FUNCTION 33 VOID 34 IopInitBootLog(BOOLEAN StartBootLog) 35 { 36 ExInitializeResourceLite(&IopBootLogResource); 37 if (StartBootLog) IopStartBootLog(); 38 } 39 40 41 INIT_FUNCTION 42 VOID 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 */ 417