00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
#include "iop.h"
00027
#include "elfkrnl.h"
00028
00029 typedef struct _IOP_ERROR_LOG_CONTEXT {
00030 KDPC ErrorLogDpc;
00031 KTIMER ErrorLogTimer;
00032 }
IOP_ERROR_LOG_CONTEXT, *
PIOP_ERROR_LOG_CONTEXT;
00033
00034
00035
00036
00037
00038 BOOLEAN
00039
IopErrorLogConnectPort(
00040 VOID
00041 );
00042
00043
VOID
00044
IopErrorLogDpc(
00045 IN
struct _KDPC *Dpc,
00046 IN PVOID DeferredContext,
00047 IN PVOID SystemArgument1,
00048 IN PVOID SystemArgument2
00049 );
00050
00051 PLIST_ENTRY
00052
IopErrorLogGetEntry(
00053 );
00054
00055
VOID
00056
IopErrorLogQueueRequest(
00057 VOID
00058 );
00059
00060
VOID
00061
IopErrorLogRequeueEntry(
00062 IN PLIST_ENTRY ListEntry
00063 );
00064
00065
#ifdef ALLOC_PRAGMA
00066
#pragma alloc_text(PAGE, IopErrorLogThread)
00067
#pragma alloc_text(PAGE, IopErrorLogConnectPort)
00068
#pragma alloc_text(PAGE, IopErrorLogQueueRequest)
00069
#endif
00070
00071
00072
00073
00074
00075 WORK_QUEUE_ITEM IopErrorLogWorkItem;
00076 HANDLE
ErrorLogPort;
00077 BOOLEAN
ErrorLogPortConnected;
00078 BOOLEAN
IopErrorLogPortPending;
00079 BOOLEAN
IopErrorLogDisabledThisBoot;
00080
00081
00082
00083
00084
00085 #define IO_ERROR_NAME_LENGTH 100
00086
00087
VOID
00088 IopErrorLogThread(
00089 IN PVOID StartContext
00090 )
00091
00092
00093
00094
00095
00096
00097
00098
00099
00100
00101
00102
00103
00104
00105
00106
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 }
00564
00565 BOOLEAN
00566 IopErrorLogConnectPort(
00567 VOID
00568 )
00569
00570
00571
00572
00573
00574
00575
00576
00577
00578
00579
00580
00581
00582
00583
00584
00585
00586
00587
00588
00589 {
00590
00591 UNICODE_STRING errorPortName;
00592
NTSTATUS status;
00593 ULONG maxMessageLength;
00594 SECURITY_QUALITY_OF_SERVICE dynamicQos;
00595
00596
PAGED_CODE();
00597
00598
00599
00600
00601
00602
if (
ErrorLogPortConnected) {
00603
00604
00605
00606
00607
00608
return(
TRUE);
00609 }
00610
00611
00612
00613
00614
00615
00616
00617 dynamicQos.ImpersonationLevel = SecurityImpersonation;
00618 dynamicQos.ContextTrackingMode = SECURITY_DYNAMIC_TRACKING;
00619 dynamicQos.EffectiveOnly =
TRUE;
00620
00621
00622
00623
00624
00625
RtlInitUnicodeString( &errorPortName, ELF_PORT_NAME_U );
00626
00627 status =
NtConnectPort( &
ErrorLogPort,
00628 &errorPortName,
00629 &dynamicQos,
00630 (PPORT_VIEW)
NULL,
00631 (PREMOTE_PORT_VIEW)
NULL,
00632 &maxMessageLength,
00633 (PVOID)
NULL,
00634 (PULONG)
NULL );
00635
00636
if (
NT_SUCCESS( status )) {
00637
if (maxMessageLength >= IO_ERROR_LOG_MESSAGE_LENGTH) {
00638
ErrorLogPortConnected =
TRUE;
00639
return(
TRUE);
00640 }
else {
00641
NtClose(
ErrorLogPort);
00642 }
00643 }
00644
00645
00646
00647
00648
00649
00650
IopErrorLogQueueRequest();
00651
00652
00653
00654
00655
00656
return(
FALSE);
00657 }
00658
00659
VOID
00660 IopErrorLogDpc(
00661 IN
struct _KDPC *Dpc,
00662 IN PVOID DeferredContext,
00663 IN PVOID SystemArgument1,
00664 IN PVOID SystemArgument2
00665 )
00666
00667
00668
00669
00670
00671
00672
00673
00674
00675
00676
00677
00678
00679
00680
00681
00682
00683
00684
00685
00686
00687
00688
00689
00690
00691
00692 {
00693
00694
00695
00696
00697
if (Dpc !=
NULL) {
00698
ExFreePool(Dpc);
00699 }
00700
00701
ExInitializeWorkItem( &
IopErrorLogWorkItem,
IopErrorLogThread,
NULL );
00702
00703
ExQueueWorkItem( &
IopErrorLogWorkItem,
DelayedWorkQueue );
00704 }
00705
00706 PLIST_ENTRY
00707 IopErrorLogGetEntry(
00708 )
00709
00710
00711
00712
00713
00714
00715
00716
00717
00718
00719
00720
00721
00722
00723
00724
00725
00726
00727
00728 {
00729 KIRQL irql;
00730 PLIST_ENTRY listEntry;
00731
00732
00733
00734
00735
00736 ExAcquireSpinLock( &
IopErrorLogLock, &irql );
00737
if (IsListEmpty( &
IopErrorLogListHead )) {
00738
00739
00740
00741
00742
00743
00744
IopErrorLogPortPending =
FALSE;
00745 listEntry = (PLIST_ENTRY)
NULL;
00746 }
else {
00747
00748
00749
00750
00751
00752 listEntry = RemoveHeadList( &
IopErrorLogListHead );
00753 }
00754
00755 ExReleaseSpinLock( &
IopErrorLogLock, irql );
00756
return listEntry;
00757 }
00758
00759
VOID
00760 IopErrorLogQueueRequest(
00761 VOID
00762 )
00763
00764
00765
00766
00767
00768
00769
00770
00771
00772
00773
00774
00775
00776
00777
00778
00779
00780
00781
00782 {
00783 LARGE_INTEGER interval;
00784
PIOP_ERROR_LOG_CONTEXT context;
00785
00786
PAGED_CODE();
00787
00788
00789
00790
00791
00792 context =
ExAllocatePool(
NonPagedPool,
sizeof(
IOP_ERROR_LOG_CONTEXT ) );
00793
00794
if (context ==
NULL) {
00795
00796
00797
00798
00799
00800
00801
00802
00803
00804
00805
IopErrorLogPortPending =
FALSE;
00806
return;
00807 }
00808
00809
KeInitializeDpc( &context->
ErrorLogDpc,
00810
IopErrorLogDpc,
00811
NULL );
00812
00813
KeInitializeTimer( &context->
ErrorLogTimer );
00814
00815
00816
00817
00818
00819 interval.QuadPart = - 10 * 1000 * 1000 * 30;
00820
00821
00822
00823
00824
00825
KeSetTimer( &context->
ErrorLogTimer, interval, &context->
ErrorLogDpc );
00826 }
00827
00828
VOID
00829 IopErrorLogRequeueEntry(
00830 IN PLIST_ENTRY ListEntry
00831 )
00832
00833
00834
00835
00836
00837
00838
00839
00840
00841
00842
00843
00844
00845
00846
00847
00848
00849
00850
00851 {
00852 KIRQL irql;
00853
00854
00855
00856
00857
00858
00859
00860 ExAcquireSpinLock( &
IopErrorLogLock, &irql );
00861 InsertHeadList( &
IopErrorLogListHead, ListEntry );
00862
ErrorLogPortConnected =
FALSE;
00863 ExReleaseSpinLock( &
IopErrorLogLock, irql );
00864 }