00094 :
00095
00096 This
is the main loop
for the I/O error log thread which executes in
the
00097 system process context. This routine
is started when
the system
is
00098 initialized.
00099
00100 Arguments:
00101
00102 StartContext - Startup context; not used.
00103
00104 Return Value:
00105
00106 None.
00107
00108 --*/
00109
00110 {
00111
PERROR_LOG_ENTRY errorLogEntry;
00112 UNICODE_STRING nameString;
00113 PLIST_ENTRY listEntry;
00114 PIO_ERROR_LOG_MESSAGE errorMessage;
00115
NTSTATUS status;
00116 PELF_PORT_MSG portMessage;
00117 PCHAR objectName;
00118 ULONG messageLength;
00119 ULONG driverNameLength;
00120 ULONG deviceNameLength;
00121 ULONG objectNameLength;
00122 ULONG remainingLength;
00123 ULONG stringLength;
00124
CHAR nameBuffer[
IO_ERROR_NAME_LENGTH+
sizeof( OBJECT_NAME_INFORMATION )];
00125
PDRIVER_OBJECT driverObject;
00126 POBJECT_NAME_INFORMATION nameInformation;
00127 PIO_ERROR_LOG_PACKET errorData;
00128 PWSTR string;
00129
00130
PAGED_CODE();
00131
00132 UNREFERENCED_PARAMETER( StartContext );
00133
00134
00135
00136
00137
00138
00139
if (!
IopErrorLogConnectPort()) {
00140
00141
00142
00143
00144
00145
00146
return;
00147 }
00148
00149
00150
00151
00152
00153
00154 messageLength = IO_ERROR_LOG_MESSAGE_LENGTH;
00155 portMessage =
ExAllocatePool(PagedPool, messageLength);
00156
00157
if (portMessage ==
NULL) {
00158
00159
00160
00161
00162
00163
00164
IopErrorLogQueueRequest();
00165
return;
00166 }
00167
00168 RtlZeroMemory( portMessage,
sizeof( *portMessage ) );
00169 portMessage->MessageType = IO_ERROR_LOG;
00170 errorMessage = &portMessage->u.IoErrorLogMessage;
00171
00172 nameInformation = (PVOID) &nameBuffer;
00173
00174
00175
00176
00177
00178
00179
00180
00181
00182
00183
00184
00185
00186
00187
00188
00189
00190
for (;;) {
00191
00192
00193
00194
00195
00196
00197
00198
00199
00200
00201
00202
if (!(listEntry =
IopErrorLogGetEntry())) {
00203
break;
00204 }
00205
00206 errorLogEntry = CONTAINING_RECORD( listEntry,
00207
ERROR_LOG_ENTRY,
00208 ListEntry );
00209
00210
00211
00212
00213
00214
00215
00216
00217
00218
00219 messageLength =
sizeof( IO_ERROR_LOG_MESSAGE ) -
00220
sizeof(
ERROR_LOG_ENTRY ) -
sizeof( IO_ERROR_LOG_PACKET ) +
00221 errorLogEntry->
Size;
00222
00223 errorData = (PIO_ERROR_LOG_PACKET) (errorLogEntry + 1);
00224
00225
00226
00227
00228
00229 RtlMoveMemory( &errorMessage->EntryData,
00230 errorData,
00231 errorLogEntry->
Size -
sizeof(
ERROR_LOG_ENTRY ) );
00232
00233 errorMessage->TimeStamp = errorLogEntry->
TimeStamp;
00234 errorMessage->Type =
IO_TYPE_ERROR_MESSAGE;
00235
00236
00237
00238
00239
00240
00241
00242
if (errorData->NumberOfStrings != 0) {
00243
00244
00245
00246
00247
00248
00249 objectName = (PCHAR) (&errorMessage->EntryData) +
00250 errorData->StringOffset;
00251
00252 }
else {
00253
00254
00255
00256
00257
00258
00259 objectName = (PCHAR) errorMessage + messageLength;
00260
00261 }
00262
00263
00264
00265
00266
00267 objectName = (PCHAR) ((ULONG_PTR) (objectName +
sizeof(WCHAR) - 1) &
00268 ~(ULONG_PTR)(
sizeof(WCHAR) - 1));
00269
00270 errorMessage->DriverNameOffset = (ULONG)(objectName - (PCHAR) errorMessage);
00271
00272 remainingLength = (ULONG)((PCHAR) portMessage + IO_ERROR_LOG_MESSAGE_LENGTH
00273 - objectName);
00274
00275
00276
00277
00278
00279
00280
00281 driverObject = errorLogEntry->
DriverObject;
00282 driverNameLength = 0;
00283
00284
if (driverObject !=
NULL) {
00285
if (driverObject->
DriverName.Buffer !=
NULL) {
00286
00287 nameString.Buffer = driverObject->
DriverName.Buffer;
00288 driverNameLength = driverObject->
DriverName.Length;
00289 }
00290
00291
if (driverNameLength == 0) {
00292
00293
00294
00295
00296
00297 status =
ObQueryNameString( driverObject,
00298 nameInformation,
00299 IO_ERROR_NAME_LENGTH +
sizeof( OBJECT_NAME_INFORMATION ),
00300 &objectNameLength );
00301
00302
if (!
NT_SUCCESS( status ) || !nameInformation->Name.Length) {
00303
00304
00305
00306
00307
00308 driverNameLength = 0;
00309
00310 }
else {
00311 nameString = nameInformation->Name;
00312 }
00313
00314 }
00315
00316 }
else {
00317
00318
00319
00320
00321
00322
00323
00324
00325
00326 nameString.Buffer =
L"Application Popup";
00327 driverNameLength = wcslen(nameString.Buffer) *
sizeof(WCHAR);
00328 }
00329
00330
if (driverNameLength != 0 ) {
00331
00332
00333
00334
00335
00336 string = nameString.Buffer +
00337 (driverNameLength /
sizeof(WCHAR));
00338
00339 driverNameLength =
sizeof(WCHAR);
00340 string--;
00341
while (*string !=
L'\\' && string != nameString.Buffer) {
00342 string--;
00343 driverNameLength +=
sizeof(WCHAR);
00344 }
00345
00346
if (*string ==
L'\\') {
00347 string++;
00348 driverNameLength -=
sizeof(WCHAR);
00349 }
00350
00351
00352
00353
00354
00355
00356
00357
if (driverNameLength > remainingLength - (3 *
sizeof(WCHAR))) {
00358 driverNameLength = remainingLength - (3 *
sizeof(WCHAR));
00359 }
00360
00361 RtlMoveMemory(
00362 objectName,
00363 string,
00364 driverNameLength
00365 );
00366
00367 }
00368
00369
00370
00371
00372
00373
00374 *((PWSTR) (objectName + driverNameLength)) =
L'\0';
00375 driverNameLength +=
sizeof(WCHAR);
00376
00377
00378
00379
00380
00381 objectName += driverNameLength;
00382 remainingLength -= driverNameLength;
00383
00384 errorMessage->EntryData.StringOffset = (
USHORT)(objectName - (PCHAR) errorMessage);
00385
00386
if (errorLogEntry->
DeviceObject !=
NULL) {
00387
00388 status =
ObQueryNameString( errorLogEntry->
DeviceObject,
00389 nameInformation,
00390 IO_ERROR_NAME_LENGTH +
sizeof( OBJECT_NAME_INFORMATION ) - driverNameLength,
00391 &objectNameLength );
00392
00393
if (!
NT_SUCCESS( status ) || !nameInformation->Name.Length) {
00394
00395
00396
00397
00398
00399 nameInformation->Name.Length = 0;
00400 nameInformation->Name.Buffer =
L"\0";
00401
00402 }
00403
00404
00405
00406
00407
00408
00409
00410 }
else {
00411
00412
00413
00414
00415
00416
00417
00418 nameInformation->Name.Length = 0;
00419 nameInformation->Name.Buffer =
L"\0";
00420
00421 }
00422
00423 deviceNameLength = nameInformation->Name.Length;
00424
00425
00426
00427
00428
00429
00430
if (deviceNameLength > remainingLength - (2 *
sizeof(WCHAR))) {
00431
00432 deviceNameLength = remainingLength - (2 *
sizeof(WCHAR));
00433
00434 }
00435
00436 RtlMoveMemory( objectName,
00437 nameInformation->Name.Buffer,
00438 deviceNameLength );
00439
00440
00441
00442
00443
00444
00445 *((PWSTR) (objectName + deviceNameLength)) =
L'\0';
00446 deviceNameLength +=
sizeof(WCHAR);
00447
00448
00449
00450
00451
00452 errorMessage->EntryData.NumberOfStrings++;
00453 objectName += deviceNameLength;
00454 remainingLength -= deviceNameLength;
00455
00456
if (errorData->NumberOfStrings) {
00457
00458 stringLength = errorLogEntry->
Size -
sizeof(
ERROR_LOG_ENTRY ) -
00459 errorData->StringOffset;
00460
00461
00462
00463
00464
00465
00466
if (stringLength > remainingLength -
sizeof(WCHAR)) {
00467
00468
00469 messageLength -= stringLength - remainingLength;
00470 stringLength = remainingLength -
sizeof(WCHAR);
00471
00472 }
00473
00474
00475
00476
00477
00478 RtlMoveMemory( objectName,
00479 (PCHAR) errorData + errorData->StringOffset,
00480 stringLength );
00481
00482
00483
00484
00485
00486
00487 *((PWSTR) (objectName + stringLength)) =
L'\0';
00488
00489 }
00490
00491
00492
00493
00494
00495 errorMessage->DriverNameLength = (
USHORT) driverNameLength;
00496 messageLength += deviceNameLength + driverNameLength;
00497 errorMessage->Size = (
USHORT) messageLength;
00498
00499 messageLength += FIELD_OFFSET ( ELF_PORT_MSG, u ) -
00500 FIELD_OFFSET (ELF_PORT_MSG, MessageType);
00501
00502 portMessage->PortMessage.u1.s1.TotalLength = (
USHORT)
00503 (
sizeof( PORT_MESSAGE ) + messageLength);
00504 portMessage->PortMessage.u1.s1.DataLength = (
USHORT) (messageLength);
00505 status =
NtRequestPort( ErrorLogPort, (PPORT_MESSAGE) portMessage );
00506
00507
if (!
NT_SUCCESS( status )) {
00508
00509
00510
00511
00512
00513
00514
00515
00516
00517
00518
NtClose( ErrorLogPort );
00519
00520
IopErrorLogRequeueEntry( &errorLogEntry->
ListEntry );
00521
00522
IopErrorLogQueueRequest();
00523
00524
break;
00525
00526 }
else {
00527
00528
00529
00530
00531
00532
00533
ExInterlockedAddUlong( &IopErrorLogAllocation,
00534 (ULONG) ( -errorLogEntry->
Size ),
00535 &IopErrorLogAllocationLock );
00536
00537
00538
00539
00540
00541
00542
00543
if (errorLogEntry->
DeviceObject !=
NULL) {
00544
ObDereferenceObject( errorLogEntry->
DeviceObject );
00545 }
00546
00547
if (driverObject !=
NULL) {
00548
ObDereferenceObject( errorLogEntry->
DriverObject );
00549 }
00550
00551
ExFreePool( errorLogEntry );
00552
00553 }
00554
00555 }
00556
00557
00558
00559
00560
00561
ExFreePool(portMessage);
00562
00563 }