00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
#include "exp.h"
00025
#pragma hdrstop
00026
00027
#include <stdarg.h>
00028
#include <string.h>
00029
#include <memprint.h>
00030
#undef DbgPrint
00031
00032
00033
00034
00035
00036
VOID
00037
MemPrintWriteCompleteApc (
00038 IN PVOID ApcContext,
00039 IN PIO_STATUS_BLOCK IoStatusBlock,
00040 IN ULONG Reserved
00041 );
00042
00043
VOID
00044
MemPrintWriteThread (
00045 IN PVOID Dummy
00046 );
00047
00048
00049
00050
00051
00052
00053 #define MEM_PRINT_MAX_MESSAGE_SIZE 256
00054
00055
00056
00057
00058
00059
00060 #define MEM_PRINT_SUBBUFFER_SIZE (MemPrintBufferSize / MemPrintSubbufferCount)
00061
00062 #define GET_MEM_PRINT_SUBBUFFER(i) ((CSHORT)( (i) / MEM_PRINT_SUBBUFFER_SIZE ))
00063
00064
00065
00066
00067
00068
00069 typedef struct _MEM_PRINT_MESSAGE_HEADER {
00070 USHORT Size;
00071 USHORT Type;
00072 }
MEM_PRINT_MESSAGE_HEADER, *
PMEM_PRINT_MESSAGE_HEADER;
00073
00074
00075
00076
00077
00078 CLONG
MemPrintBufferSize =
MEM_PRINT_DEF_BUFFER_SIZE;
00079 CLONG
MemPrintSubbufferCount =
MEM_PRINT_DEF_SUBBUFFER_COUNT;
00080 PCHAR
MemPrintBuffer;
00081
00082 ULONG
MemPrintFlags =
MEM_PRINT_FLAG_CONSOLE;
00083
00084 KSPIN_LOCK
MemPrintSpinLock;
00085
00086 CHAR MemPrintTempBuffer[
MEM_PRINT_MAX_MESSAGE_SIZE];
00087
00088 BOOLEAN
MemPrintInitialized =
FALSE;
00089
00090
00091
00092
00093
00094 CLONG
MemPrintIndex = 0;
00095
00096
00097
00098
00099
00100
00101
00102 CLONG
MemPrintCurrentSubbuffer = 0;
00103
00104
00105
00106
00107
00108
00109
00110 BOOLEAN
MemPrintSubbufferWriting[
MEM_PRINT_MAX_SUBBUFFER_COUNT];
00111
00112
00113
00114
00115
00116
00117
00118
00119
00120 KEVENT MemPrintSubbufferFullEvent[
MEM_PRINT_MAX_SUBBUFFER_COUNT];
00121
00122
00123
VOID
00124 MemPrintInitialize (
00125 VOID
00126 )
00127
00128
00129
00130
00131
00132
00133
00134
00135
00136
00137
00138
00139
00140
00141
00142
00143
00144
00145
00146 {
00147 CLONG i;
00148
NTSTATUS status;
00149 HANDLE threadHandle;
00150
00151
if (
MemPrintInitialized ) {
00152
return;
00153 }
00154
00155
00156
00157
00158
00159
00160
00161
MemPrintBuffer =
ExAllocatePoolWithTag(
NonPagedPool,
MemPrintBufferSize, 'rPeM' );
00162
00163
if (
MemPrintBuffer ==
NULL ) {
00164
00165
MemPrintBufferSize /= 2;
00166
DbgPrint(
"Unable to allocate DbgPrint buffer--trying size = %ld\n",
00167
MemPrintBufferSize );
00168
MemPrintBuffer =
ExAllocatePoolWithTag(
NonPagedPool,
MemPrintBufferSize, 'rPeM' );
00169
00170
if (
MemPrintBuffer ==
NULL ) {
00171
DbgPrint(
"Couldn't allocate DbgPrint buffer.\n" );
00172
return;
00173 }
else {
00174
00175
00176 }
00177
00178 }
else {
00179
00180
00181 }
00182
00183
00184
00185
00186
00187
00188
00189
KeInitializeSpinLock( &
MemPrintSpinLock );
00190
00191
00192
00193
00194
00195
00196
if (
MemPrintSubbufferCount < 2 ) {
00197
MemPrintSubbufferCount = 2;
00198 }
else if (
MemPrintSubbufferCount >
MEM_PRINT_MAX_SUBBUFFER_COUNT ) {
00199
MemPrintSubbufferCount =
MEM_PRINT_MAX_SUBBUFFER_COUNT;
00200 }
00201
00202
00203
00204
00205
00206
00207
00208
00209
00210
00211
for ( i = 0; i <
MemPrintSubbufferCount; i++ ) {
00212
MemPrintSubbufferWriting[i] =
FALSE;
00213
KeInitializeEvent(
00214 &
MemPrintSubbufferFullEvent[i],
00215 SynchronizationEvent,
00216
FALSE
00217 );
00218 }
00219
00220
00221
00222
00223
00224
00225 status =
PsCreateSystemThread(
00226 &threadHandle,
00227 PROCESS_ALL_ACCESS,
00228
NULL,
00229 NtCurrentProcess(),
00230
NULL,
00231
MemPrintWriteThread,
00232
NULL
00233 );
00234
00235
if ( !
NT_SUCCESS(status) ) {
00236
DbgPrint(
"MemPrintInitialize: PsCreateSystemThread failed: %X\n",
00237 status );
00238
return;
00239 }
00240
00241
MemPrintInitialized =
TRUE;
00242 ZwClose( threadHandle );
00243
00244
return;
00245
00246 }
00247
00248
00249
VOID
00250 MemPrint (
00251 CHAR *Format, ...
00252 )
00253
00254
00255
00256
00257
00258
00259
00260
00261
00262
00263
00264
00265
00266
00267
00268
00269
00270
00271
00272
00273 {
00274 va_list arglist;
00275 KIRQL oldIrql;
00276 CLONG nextSubbuffer;
00277
PMEM_PRINT_MESSAGE_HEADER messageHeader;
00278
CHAR tempBuffer[
MEM_PRINT_MAX_MESSAGE_SIZE];
00279
00280 va_start(arglist, Format);
00281 _vsnprintf( tempBuffer,
sizeof( tempBuffer ), Format, arglist );
00282 va_end(arglist);
00283
00284
00285
00286
00287
00288
00289
if ( !
MemPrintInitialized ) {
00290
00291
DbgPrint(
"%s", tempBuffer );
00292
return;
00293 }
00294
00295
00296
00297
00298
00299
00300
KeAcquireSpinLock( &
MemPrintSpinLock, &oldIrql );
00301
00302
00303
00304
00305
00306
00307
00308
00309 nextSubbuffer =
00310
GET_MEM_PRINT_SUBBUFFER(
MemPrintIndex +
MEM_PRINT_MAX_MESSAGE_SIZE );
00311
00312
if ( nextSubbuffer !=
MemPrintCurrentSubbuffer ) {
00313
00314
00315
00316
00317
00318
00319
00320
if ( nextSubbuffer ==
MemPrintSubbufferCount ) {
00321 nextSubbuffer = 0;
00322 }
00323
00324
00325
00326
00327
00328
if (
MemPrintSubbufferWriting[nextSubbuffer] ) {
00329
00330
00331
00332
00333
00334
KeReleaseSpinLock( &
MemPrintSpinLock, oldIrql );
00335
00336
DbgPrint(
"%s", tempBuffer );
00337
00338
return;
00339 }
00340
00341
00342
00343
00344
00345
00346
00347
00348
00349
00350
00351
00352
00353
if ( nextSubbuffer == 0 ) {
00354
00355
00356
00357
00358
00359
00360 messageHeader =
00361 (
PMEM_PRINT_MESSAGE_HEADER)&
MemPrintBuffer[
MemPrintIndex];
00362 RtlStoreUshort(
00363 &messageHeader->
Size,
00364 (
USHORT)(
MemPrintBufferSize -
MemPrintIndex - 1)
00365 );
00366 RtlStoreUshort(
00367 &messageHeader->
Type,
00368 (
USHORT)0xffff
00369 );
00370
00371
00372
00373
00374
00375
for (
MemPrintIndex +=
sizeof(
MEM_PRINT_MESSAGE_HEADER);
00376
MemPrintIndex <
MemPrintBufferSize;
00377
MemPrintIndex++ ) {
00378
00379
MemPrintBuffer[
MemPrintIndex] = 0;
00380 }
00381
00382
00383
00384
00385
00386
00387
MemPrintIndex = 0;
00388 }
00389 }
00390
00391
00392
00393
00394
00395
00396 messageHeader = (
PMEM_PRINT_MESSAGE_HEADER)&
MemPrintBuffer[
MemPrintIndex];
00397
00398
if (
MemPrintFlags &
MEM_PRINT_FLAG_HEADER ) {
00399
MemPrintIndex +=
sizeof(
MEM_PRINT_MESSAGE_HEADER);
00400 }
00401
00402
00403
00404
00405
00406
00407
ASSERT(
MemPrintIndex +
MEM_PRINT_MAX_MESSAGE_SIZE -
00408
sizeof(
MEM_PRINT_MESSAGE_HEADER) <=
MemPrintBufferSize );
00409
00410
00411 RtlMoveMemory( &
MemPrintBuffer[
MemPrintIndex], tempBuffer,
strlen(tempBuffer)+1 );
00412
00413
MemPrintIndex +=
strlen(tempBuffer);
00414
00415
00416
00417
00418
00419
if (
MemPrintFlags &
MEM_PRINT_FLAG_HEADER ) {
00420 messageHeader->
Size =
00421 (
USHORT)( &
MemPrintBuffer[
MemPrintIndex] - (PCHAR)messageHeader );
00422 messageHeader->
Type = (
USHORT)0xdead;
00423 messageHeader++;
00424 }
00425
00426
00427
00428
00429
00430
00431
00432
if ( &
MemPrintBuffer[
MemPrintIndex] - (PCHAR)messageHeader >
00433
MEM_PRINT_MAX_MESSAGE_SIZE ) {
00434
DbgPrint(
"Message too long!! :\n" );
00435
DbgPrint(
"%s", messageHeader );
00436 DbgBreakPoint( );
00437 }
00438
00439
00440
00441
00442
00443
if (
MemPrintFlags &
MEM_PRINT_FLAG_CONSOLE ) {
00444
DbgPrint(
"%s", messageHeader );
00445 }
00446
00447
00448
00449
00450
00451 nextSubbuffer =
GET_MEM_PRINT_SUBBUFFER(
MemPrintIndex );
00452
00453
if ( nextSubbuffer !=
MemPrintCurrentSubbuffer ) {
00454
00455
00456
00457
00458
00459
00460
00461
00462
00463
00464
MemPrintSubbufferWriting[
MemPrintCurrentSubbuffer] =
TRUE;
00465
00466
00467
00468
00469
00470
00471
KeSetEvent(
00472 &
MemPrintSubbufferFullEvent[
MemPrintCurrentSubbuffer],
00473 2,
00474
FALSE
00475 );
00476
00477
00478
00479
00480
00481
MemPrintCurrentSubbuffer = nextSubbuffer;
00482 }
00483
00484
KeReleaseSpinLock( &
MemPrintSpinLock, oldIrql );
00485
00486
return;
00487
00488 }
00489
00490
00491
VOID
00492 MemPrintFlush (
00493 VOID
00494 )
00495
00496
00497
00498
00499
00500
00501
00502
00503
00504
00505
00506
00507
00508
00509
00510
00511
00512
00513
00514 {
00515 KIRQL oldIrql;
00516
PMEM_PRINT_MESSAGE_HEADER messageHeader;
00517 CLONG nextSubbufferIndex;
00518 LARGE_INTEGER delayInterval;
00519
00520
00521
00522
00523
00524
KeAcquireSpinLock( &
MemPrintSpinLock, &oldIrql );
00525
00526
DbgPrint(
"Flushing subbuffer %ld\n",
MemPrintCurrentSubbuffer );
00527
00528
00529
00530
00531
00532 messageHeader =
00533 (
PMEM_PRINT_MESSAGE_HEADER)&
MemPrintBuffer[
MemPrintIndex];
00534 messageHeader->
Size =
00535 (
USHORT)(
MemPrintBufferSize -
MemPrintIndex - 1);
00536 messageHeader->
Type = (
USHORT)0xffff;
00537
00538
00539
00540
00541
00542 nextSubbufferIndex =
00543 (
MemPrintCurrentSubbuffer + 1) *
MEM_PRINT_SUBBUFFER_SIZE;
00544
00545
00546
00547
00548
00549
for (
MemPrintIndex +=
sizeof(
MEM_PRINT_MESSAGE_HEADER);
00550
MemPrintIndex < nextSubbufferIndex;
00551
MemPrintIndex++ ) {
00552
00553
MemPrintBuffer[
MemPrintIndex] = 0;
00554 }
00555
00556
00557
00558
00559
00560
MemPrintSubbufferWriting[
MemPrintCurrentSubbuffer] =
TRUE;
00561
00562
KeSetEvent(
00563 &
MemPrintSubbufferFullEvent[
MemPrintCurrentSubbuffer],
00564 8,
00565
FALSE
00566 );
00567
00568
00569
00570
00571
00572
00573
MemPrintCurrentSubbuffer++;
00574
00575
KeReleaseSpinLock( &
MemPrintSpinLock, oldIrql );
00576
00577
00578
00579
00580
00581
00582
00583
00584
00585
00586 delayInterval.QuadPart = -10*10*1000*1000;
00587
00588
DbgPrint(
"Delaying...\n" );
00589
KeDelayExecutionThread(
KernelMode,
TRUE, &delayInterval );
00590
DbgPrint(
"Woke up.\n" );
00591
00592
return;
00593
00594 }
00595
00596
00597
VOID
00598 MemPrintWriteThread (
00599 IN PVOID Dummy
00600 )
00601
00602
00603
00604
00605
00606
00607
00608
00609
00610
00611
00612
00613
00614
00615
00616
00617
00618
00619
00620
00621
00622 {
00623
NTSTATUS status;
00624 IO_STATUS_BLOCK ioStatusBlock[
MEM_PRINT_MAX_SUBBUFFER_COUNT];
00625 IO_STATUS_BLOCK localIoStatusBlock;
00626 CLONG i;
00627 KPRIORITY threadPriorityLevel;
00628
00629
NTSTATUS waitStatus;
00630 PVOID waitObjects[64];
00631
KWAIT_BLOCK waitBlockArray[
MEM_PRINT_MAX_SUBBUFFER_COUNT];
00632
00633 OBJECT_ATTRIBUTES objectAttributes;
00634 PCHAR fileName =
MEM_PRINT_LOG_FILE_NAME;
00635 ANSI_STRING fileNameString;
00636 HANDLE fileHandle;
00637
00638 LARGE_INTEGER fileAllocation;
00639 LARGE_INTEGER fileAllocationIncrement;
00640 LARGE_INTEGER totalBytesWritten;
00641 LARGE_INTEGER writeSize;
00642
00643 LARGE_INTEGER delayInterval;
00644 ULONG attempts = 0;
00645
00646 UNICODE_STRING UnicodeFileName;
00647
00648 Dummy;
00649
00650
00651
00652
00653
00654
00655
RtlInitAnsiString( &fileNameString, fileName );
00656 status =
RtlAnsiStringToUnicodeString(&UnicodeFileName,&fileNameString,
TRUE);
00657
if ( !
NT_SUCCESS(status) ) {
00658
NtTerminateThread( NtCurrentThread(), status );
00659 }
00660
00661 InitializeObjectAttributes(
00662 &objectAttributes,
00663 &UnicodeFileName,
00664 OBJ_CASE_INSENSITIVE,
00665
NULL,
00666
NULL
00667 );
00668
00669
00670
00671
00672
00673
00674
00675 fileAllocationIncrement.LowPart =
MemPrintBufferSize * 8;
00676 fileAllocationIncrement.HighPart = 0;
00677 fileAllocation = fileAllocationIncrement;
00678
00679
00680
00681
00682
00683
00684
00685
00686
00687
while (
TRUE ) {
00688
00689 status =
NtCreateFile(
00690 &fileHandle,
00691 FILE_WRITE_DATA,
00692 &objectAttributes,
00693 &localIoStatusBlock,
00694 &fileAllocation,
00695 FILE_ATTRIBUTE_NORMAL,
00696 FILE_SHARE_READ,
00697 FILE_OVERWRITE_IF,
00698 FILE_SEQUENTIAL_ONLY,
00699
NULL,
00700 0
L
00701 );
00702
00703
if ( (status != STATUS_OBJECT_PATH_NOT_FOUND) || (++attempts >= 3) ) {
00704
RtlFreeUnicodeString(&UnicodeFileName);
00705
break;
00706 }
00707
00708 delayInterval.QuadPart = -5*10*1000*1000;
00709
KeDelayExecutionThread(
KernelMode,
FALSE, &delayInterval );
00710
00711 }
00712
00713
if ( !
NT_SUCCESS(status) ) {
00714
DbgPrint(
"NtCreateFile for log file failed: %X\n", status );
00715
NtTerminateThread( NtCurrentThread(), status );
00716 }
00717
00718
00719
00720
00721
00722 totalBytesWritten.LowPart = 0;
00723 totalBytesWritten.HighPart = 0;
00724 writeSize.LowPart =
MEM_PRINT_SUBBUFFER_SIZE;
00725 writeSize.HighPart = 0;
00726
00727
00728
00729
00730
00731
for ( i = 0; i <
MemPrintSubbufferCount; i++ ) {
00732 waitObjects[i] = &
MemPrintSubbufferFullEvent[i];
00733 }
00734
00735
00736
00737
00738
00739 threadPriorityLevel = LOW_REALTIME_PRIORITY + 1;
00740
00741 status =
NtSetInformationThread(
00742 NtCurrentThread(),
00743 ThreadPriority,
00744 &threadPriorityLevel,
00745
sizeof(threadPriorityLevel)
00746 );
00747
00748
if ( !
NT_SUCCESS(status) ) {
00749
DbgPrint(
"Unable to set error log thread priority: %X\n", status );
00750 }
00751
00752
00753
00754
00755
00756
00757
00758
while (
TRUE ) {
00759
00760 waitStatus =
KeWaitForMultipleObjects(
00761 (CCHAR)
MemPrintSubbufferCount,
00762 waitObjects,
00763 WaitAny,
00764
Executive,
00765
KernelMode,
00766
TRUE,
00767
NULL,
00768 waitBlockArray
00769 );
00770
00771
if ( !
NT_SUCCESS(waitStatus) ) {
00772
DbgPrint(
"KeWaitForMultipleObjects failed: %X\n", waitStatus );
00773
NtTerminateThread( NtCurrentThread(), waitStatus );
00774 }
00775
00776
00777
00778
ASSERT( (CCHAR)waitStatus < (CCHAR)
MemPrintSubbufferCount );
00779
00780
00781
00782
00783
00784
00785
if ( (
MemPrintFlags &
MEM_PRINT_FLAG_FILE) == 0 ) {
00786
00787 KIRQL oldIrql;
00788
00789
KeAcquireSpinLock( &
MemPrintSpinLock, &oldIrql );
00790
MemPrintSubbufferWriting[ waitStatus ] =
FALSE;
00791
KeReleaseSpinLock( &
MemPrintSpinLock, oldIrql );
00792
00793
continue;
00794 }
00795
00796
00797
00798
00799
00800
00801
00802 status =
NtWriteFile(
00803 fileHandle,
00804
NULL,
00805
MemPrintWriteCompleteApc,
00806 (PVOID)waitStatus,
00807 &ioStatusBlock[waitStatus],
00808 &
MemPrintBuffer[waitStatus *
MEM_PRINT_SUBBUFFER_SIZE],
00809
MEM_PRINT_SUBBUFFER_SIZE,
00810 &totalBytesWritten,
00811
NULL
00812 );
00813
00814
if ( !
NT_SUCCESS(status) ) {
00815
DbgPrint(
"NtWriteFile for log file failed: %X\n", status );
00816 }
00817
00818
00819
00820
00821
00822 totalBytesWritten.QuadPart = totalBytesWritten.QuadPart + writeSize.QuadPart;
00823
00824
00825
00826
00827
00828
00829
00830
00831
00832
if ( totalBytesWritten.QuadPart >= fileAllocation.QuadPart ) {
00833
00834 fileAllocation.QuadPart =
00835 fileAllocation.QuadPart + fileAllocationIncrement.QuadPart;
00836
00837
DbgPrint(
"Enlarging log file to %ld bytes.\n",
00838 fileAllocation.LowPart );
00839
00840 status =
NtSetInformationFile(
00841 fileHandle,
00842 &localIoStatusBlock,
00843 &fileAllocation,
00844
sizeof(fileAllocation),
00845 FileAllocationInformation
00846 );
00847
00848
if ( !
NT_SUCCESS(status) ) {
00849
DbgPrint(
"Attempt to extend log file failed: %X\n", status );
00850 fileAllocation.QuadPart =
00851 fileAllocation.QuadPart - fileAllocationIncrement.QuadPart;
00852 }
00853 }
00854 }
00855
00856
return;
00857
00858 }
00859
00860
00861
VOID
00862 MemPrintWriteCompleteApc (
00863 IN PVOID ApcContext,
00864 IN PIO_STATUS_BLOCK IoStatusBlock,
00865 IN ULONG Reserved
00866 )
00867
00868
00869
00870
00871
00872
00873
00874
00875
00876
00877
00878
00879
00880
00881
00882
00883
00884
00885
00886
00887
00888
00889
00890
00891 {
00892 KIRQL oldIrql;
00893
00894
if ( !
NT_SUCCESS(IoStatusBlock->Status) ) {
00895
DbgPrint(
"NtWriteFile for subbuffer %ld failed: %X\n",
00896 ApcContext, IoStatusBlock->Status );
00897
return;
00898 }
00899
00900
00901
DbgPrint(
"." );
00902
00903
00904
00905
00906
00907
00908
00909
KeAcquireSpinLock( &
MemPrintSpinLock, &oldIrql );
00910
MemPrintSubbufferWriting[ (ULONG_PTR)ApcContext ] =
FALSE;
00911
KeReleaseSpinLock( &
MemPrintSpinLock, oldIrql );
00912
00913
return;
00914
00915 Reserved;
00916
00917 }