00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
#include "cmp.h"
00023
00024 ULONG
perftouchbuffer = 0;
00025
00026
#ifdef ALLOC_PRAGMA
00027
#pragma alloc_text(PAGE,CmpAllocate)
00028
#ifdef POOL_TAGGING
00029
#pragma alloc_text(PAGE,CmpAllocateTag)
00030
#endif
00031
#pragma alloc_text(PAGE,CmpFree)
00032
#pragma alloc_text(PAGE,CmpDoFileSetSize)
00033
#pragma alloc_text(PAGE,CmpFileRead)
00034
#pragma alloc_text(PAGE,CmpFileWrite)
00035
#pragma alloc_text(PAGE,CmpFileFlush)
00036
#endif
00037
00038 extern BOOLEAN
CmpNoWrite;
00039
00040
00041
00042
00043
00044 #define MAX_FILE_IO 0x10000
00045
00046 #define CmpIoFileRead 1
00047 #define CmpIoFileWrite 2
00048 #define CmpIoFileSetSize 3
00049 #define CmpIoFileFlush 4
00050
00051
extern struct {
00052 ULONG
Action;
00053 HANDLE
Handle;
00054 NTSTATUS Status;
00055 }
CmRegistryIODebug;
00056
00057
00058
00059
00060
00061 PVOID
00062 CmpAllocate(
00063 ULONG Size,
00064 BOOLEAN UseForIo
00065 )
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086 {
00087 PVOID result;
00088 ULONG pooltype;
00089
#if DBG
00090
PVOID Caller;
00091 PVOID CallerCaller;
00092
RtlGetCallersAddress(&Caller, &CallerCaller);
00093
#endif
00094
00095
if (
CmpClaimGlobalQuota(
Size) ==
FALSE) {
00096
return NULL;
00097 }
00098
00099 pooltype = (UseForIo) ?
PagedPoolCacheAligned :
PagedPool;
00100 result =
ExAllocatePoolWithTag(
00101 pooltype,
00102
Size,
00103 CM_POOL_TAG
00104 );
00105
00106
#if DBG
00107
CMLOG(
CML_MINOR,
CMS_POOL) {
00108 KdPrint((
"**CmpAllocate: allocate:%08lx, ",
Size));
00109 KdPrint((
"type:%d, at:%08lx ",
PagedPool, result));
00110 KdPrint((
"c:%08lx cc:%08lx\n", Caller, CallerCaller));
00111 }
00112
#endif
00113
00114
if (result ==
NULL) {
00115
CmpReleaseGlobalQuota(
Size);
00116 }
00117
00118
return result;
00119 }
00120
00121
#ifdef POOL_TAGGING
00122
PVOID
00123
CmpAllocateTag(
00124 ULONG Size,
00125 BOOLEAN UseForIo,
00126 ULONG Tag
00127 )
00128
00129
00130
00131
00132
00133
00134
00135
00136
00137
00138
00139
00140
00141
00142
00143
00144
00145
00146
00147
00148 {
00149 PVOID result;
00150 ULONG pooltype;
00151
#if DBG
00152
PVOID Caller;
00153 PVOID CallerCaller;
00154
RtlGetCallersAddress(&Caller, &CallerCaller);
00155
#endif
00156
00157
if (
CmpClaimGlobalQuota(Size) ==
FALSE) {
00158
return NULL;
00159 }
00160
00161 pooltype = (UseForIo) ?
PagedPoolCacheAligned :
PagedPool;
00162 result =
ExAllocatePoolWithTag(
00163 pooltype,
00164 Size,
00165 Tag
00166 );
00167
00168
#if DBG
00169
CMLOG(CML_MINOR, CMS_POOL) {
00170 KdPrint((
"**CmpAllocate: allocate:%08lx, ", Size));
00171 KdPrint((
"type:%d, at:%08lx ", PagedPool, result));
00172 KdPrint((
"c:%08lx cc:%08lx\n", Caller, CallerCaller));
00173 }
00174
#endif
00175
00176
if (result ==
NULL) {
00177
CmpReleaseGlobalQuota(Size);
00178 }
00179
00180
return result;
00181 }
00182
#endif
00183
00184
00185
VOID
00186 CmpFree(
00187 PVOID MemoryBlock,
00188 ULONG GlobalQuotaSize
00189 )
00190
00191
00192
00193
00194
00195
00196
00197
00198
00199
00200
00201
00202
00203
00204
00205
00206
00207
00208
00209
00210 {
00211
#if DBG
00212
PVOID Caller;
00213 PVOID CallerCaller;
00214
RtlGetCallersAddress(&Caller, &CallerCaller);
00215
CMLOG(
CML_MINOR,
CMS_POOL) {
00216 KdPrint((
"**FREEING:%08lx c,cc:%08lx,%08lx\n", MemoryBlock, Caller, CallerCaller));
00217 }
00218
#endif
00219
ASSERT(GlobalQuotaSize > 0);
00220
CmpReleaseGlobalQuota(GlobalQuotaSize);
00221
ExFreePool(MemoryBlock);
00222
return;
00223 }
00224
00225
00226
NTSTATUS
00227 CmpDoFileSetSize(
00228
PHHIVE Hive,
00229 ULONG FileType,
00230 ULONG FileSize
00231 )
00232
00233
00234
00235
00236
00237
00238
00239
00240
00241
00242
00243
00244
00245
00246
00247
00248
00249
00250
00251
00252
00253
00254
00255
00256
00257 {
00258
PCMHIVE CmHive;
00259 HANDLE FileHandle;
00260
NTSTATUS Status;
00261 FILE_END_OF_FILE_INFORMATION FileInfo;
00262 IO_STATUS_BLOCK IoStatus;
00263 BOOLEAN oldFlag;
00264
00265
ASSERT(FIELD_OFFSET(
CMHIVE,
Hive) == 0);
00266
00267 CmHive = (
PCMHIVE)
Hive;
00268 FileHandle = CmHive->
FileHandles[FileType];
00269
if (FileHandle ==
NULL) {
00270
return TRUE;
00271 }
00272
00273
00274
00275
00276 oldFlag =
IoSetThreadHardErrorMode(
FALSE);
00277
00278 FileInfo.EndOfFile.HighPart = 0
L;
00279 FileInfo.EndOfFile.LowPart = FileSize;
00280
00281
ASSERT_PASSIVE_LEVEL();
00282
00283
Status =
ZwSetInformationFile(
00284 FileHandle,
00285 &IoStatus,
00286 (PVOID)&FileInfo,
00287
sizeof(FILE_END_OF_FILE_INFORMATION),
00288 FileEndOfFileInformation
00289 );
00290
00291
if (
NT_SUCCESS(
Status)) {
00292
ASSERT(IoStatus.Status ==
Status);
00293 }
else {
00294
00295
00296
00297
00298
CmRegistryIODebug.Action =
CmpIoFileSetSize;
00299
CmRegistryIODebug.Handle = FileHandle;
00300
CmRegistryIODebug.Status =
Status;
00301
DbgPrint(
"CmpFileSetSize:\tHandle=%08lx NewLength=%08lx \n", FileHandle, FileSize);
00302 }
00303
00304
00305
00306
00307
IoSetThreadHardErrorMode(oldFlag);
00308
00309
return Status;
00310 }
00311
00312
NTSTATUS
00313 CmpCreateEvent(
00314 IN EVENT_TYPE eventType,
00315 OUT PHANDLE eventHandle,
00316 OUT
PKEVENT *event
00317 )
00318 {
00319
NTSTATUS status;
00320 OBJECT_ATTRIBUTES obja;
00321
00322 InitializeObjectAttributes( &obja,
NULL, OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE,
NULL,
NULL );
00323 status = ZwCreateEvent(
00324 eventHandle,
00325 EVENT_ALL_ACCESS,
00326 &obja,
00327 eventType,
00328
FALSE);
00329
00330
if (!
NT_SUCCESS(status)) {
00331
return status;
00332 }
00333
00334 status =
ObReferenceObjectByHandle(
00335 *eventHandle,
00336 EVENT_ALL_ACCESS,
00337
NULL,
00338
KernelMode,
00339 event,
00340
NULL);
00341
00342
if (!
NT_SUCCESS(status)) {
00343 ZwClose(*eventHandle);
00344
return status;
00345 }
00346
return status;
00347 }
00348
00349
00350 BOOLEAN
00351 CmpFileRead (
00352
PHHIVE Hive,
00353 ULONG FileType,
00354 PULONG FileOffset,
00355 PVOID DataBuffer,
00356 ULONG DataLength
00357 )
00358
00359
00360
00361
00362
00363
00364
00365
00366
00367
00368
00369
00370
00371
00372
00373
00374
00375
00376
00377
00378
00379
00380
00381
00382
00383
00384
00385
00386
00387
00388
00389
00390
00391
00392 {
00393
NTSTATUS status;
00394 LARGE_INTEGER
Offset;
00395 IO_STATUS_BLOCK IoStatus;
00396
PCMHIVE CmHive;
00397 HANDLE FileHandle;
00398 ULONG LengthToRead;
00399 HANDLE eventHandle =
NULL;
00400
PKEVENT eventObject =
NULL;
00401
00402
ASSERT(FIELD_OFFSET(
CMHIVE,
Hive) == 0);
00403 CmHive = (
PCMHIVE)
Hive;
00404 FileHandle = CmHive->
FileHandles[FileType];
00405
if (FileHandle ==
NULL) {
00406
return TRUE;
00407 }
00408
00409
CMLOG(
CML_MAJOR,
CMS_IO) {
00410 KdPrint((
"CmpFileRead:\n"));
00411 KdPrint((
"\tHandle=%08lx Offset=%08lx ", FileHandle, *FileOffset));
00412 KdPrint((
"Buffer=%08lx Length=%08lx\n", DataBuffer, DataLength));
00413 }
00414
00415
00416
00417
00418
if ((0xffffffff - *FileOffset) < DataLength) {
00419
CMLOG(
CML_MAJOR,
CMS_IO_ERROR) KdPrint((
"CmpFileRead: runoff\n"));
00420
return FALSE;
00421 }
00422
00423 status =
CmpCreateEvent(
00424 SynchronizationEvent,
00425 &eventHandle,
00426 &eventObject);
00427
if (!
NT_SUCCESS(status))
00428
return FALSE;
00429
00430
00431
00432
00433
00434
00435
00436
00437
ASSERT_PASSIVE_LEVEL();
00438
while (DataLength > 0) {
00439
00440
00441
00442
00443
Offset.LowPart = *FileOffset;
00444
Offset.HighPart = 0
L;
00445
00446
00447
00448
00449
if (DataLength >
MAX_FILE_IO) {
00450 LengthToRead =
MAX_FILE_IO;
00451 }
else {
00452 LengthToRead = DataLength;
00453 }
00454
00455 status = ZwReadFile(
00456 FileHandle,
00457 eventHandle,
00458
NULL,
00459
NULL,
00460 &IoStatus,
00461 DataBuffer,
00462 LengthToRead,
00463 &
Offset,
00464
NULL
00465 );
00466
00467
if (STATUS_PENDING == status) {
00468 status =
KeWaitForSingleObject(eventObject,
Executive,
00469
KernelMode,
FALSE,
NULL);
00470
ASSERT(STATUS_SUCCESS == status);
00471 status = IoStatus.Status;
00472 }
00473
00474
00475
00476
00477 *FileOffset =
Offset.LowPart + LengthToRead;
00478 DataLength -= LengthToRead;
00479 (PUCHAR)DataBuffer += LengthToRead;
00480
00481
if (
NT_SUCCESS(status)) {
00482
ASSERT(IoStatus.Status == status);
00483
if (IoStatus.Information != LengthToRead) {
00484
CMLOG(
CML_MAJOR,
CMS_IO_ERROR) {
00485 KdPrint((
"CmpFileRead:\n\t"));
00486 KdPrint((
"Failure1: status = %08lx ", status));
00487 KdPrint((
"IoInformation = %08lx\n", IoStatus.Information));
00488 }
00489
ObDereferenceObject(eventObject);
00490 ZwClose(eventHandle);
00491
return FALSE;
00492 }
00493 }
else {
00494
00495
00496
00497
CmRegistryIODebug.Action =
CmpIoFileRead;
00498
CmRegistryIODebug.Handle = FileHandle;
00499
CmRegistryIODebug.Status = status;
00500
DbgPrint(
"CmpFileRead:\tFailure2: status = %08lx IoStatus = %08lx\n", status, IoStatus.Status);
00501
00502
ObDereferenceObject(eventObject);
00503 ZwClose(eventHandle);
00504
return FALSE;
00505 }
00506
00507 }
00508
ObDereferenceObject(eventObject);
00509 ZwClose(eventHandle);
00510
return TRUE;
00511 }
00512
00513
00514
00515 BOOLEAN
00516 CmpFileWrite(
00517
PHHIVE Hive,
00518 ULONG FileType,
00519 PCMP_OFFSET_ARRAY offsetArray,
00520 ULONG offsetArrayCount,
00521 PULONG FileOffset
00522 )
00523
00524
00525
00526
00527
00528
00529
00530
00531
00532
00533
00534
00535
00536
00537
00538
00539
00540
00541
00542
00543
00544
00545
00546
00547
00548
00549
00550
00551
00552
00553
00554
00555
00556
00557
00558 {
00559
NTSTATUS status;
00560 LARGE_INTEGER
Offset;
00561
PCMHIVE CmHive;
00562 HANDLE FileHandle;
00563 ULONG LengthToWrite;
00564 LONG WaitBufferCount = 0;
00565 LONG idx;
00566 ULONG arrayCount = 0;
00567 PVOID DataBuffer;
00568 ULONG DataLength;
00569 HANDLE eventHandles[MAXIMUM_WAIT_OBJECTS];
00570
PKEVENT eventObjects[MAXIMUM_WAIT_OBJECTS];
00571
KWAIT_BLOCK waitBlockArray[MAXIMUM_WAIT_OBJECTS];
00572 IO_STATUS_BLOCK IoStatus[MAXIMUM_WAIT_OBJECTS];
00573 BOOLEAN ret_val =
TRUE;
00574
00575
if (
CmpNoWrite) {
00576
return TRUE;
00577 }
00578
00579
ASSERT(FIELD_OFFSET(
CMHIVE,
Hive) == 0);
00580 CmHive = (
PCMHIVE)
Hive;
00581 FileHandle = CmHive->
FileHandles[FileType];
00582
if (FileHandle ==
NULL) {
00583
return TRUE;
00584 }
00585
00586
CMLOG(
CML_MAJOR,
CMS_IO) {
00587 KdPrint((
"CmpFileWrite:\n"));
00588 KdPrint((
"\tHandle=%08lx ", FileHandle));
00589 }
00590
00591
for (idx = 0; idx < MAXIMUM_WAIT_OBJECTS; idx++) {
00592 eventHandles[idx] =
NULL;
00593 }
00594
00595
00596
00597
for (idx = 0; (ULONG) idx < offsetArrayCount; idx++) {
00598
char * start = offsetArray[idx].DataBuffer;
00599
char * end = (
char *) start + offsetArray[idx].DataLength;
00600
while (start < end) {
00601
00602
00603
perftouchbuffer += (ULONG) *start;
00604 start +=
PAGE_SIZE;
00605 }
00606 }
00607
00608
00609
00610
00611
00612
00613
00614
00615
ASSERT_PASSIVE_LEVEL();
00616 arrayCount = 0;
00617 DataLength = 0;
00618
00619
00620
while (arrayCount < offsetArrayCount) {
00621 WaitBufferCount = 0;
00622
00623
00624
while ((arrayCount < offsetArrayCount) &&
00625 (WaitBufferCount < MAXIMUM_WAIT_OBJECTS)) {
00626
00627
00628
00629
if (DataLength == 0) {
00630 *FileOffset = offsetArray[arrayCount].FileOffset;
00631 DataBuffer = offsetArray[arrayCount].DataBuffer;
00632 DataLength = offsetArray[arrayCount].DataLength;
00633
00634
00635
00636
00637
if ((0xffffffff - *FileOffset) < DataLength) {
00638
CMLOG(
CML_MAJOR,
CMS_IO_ERROR) KdPrint((
"CmpFileWrite: runoff\n"));
00639
goto Error_Exit;
00640 }
00641 }
00642
00643
00644
while ((DataLength > 0) && (WaitBufferCount < MAXIMUM_WAIT_OBJECTS)) {
00645
00646
00647
00648
00649
Offset.LowPart = *FileOffset;
00650
Offset.HighPart = 0
L;
00651
00652
00653
00654
00655
if (DataLength >
MAX_FILE_IO) {
00656 LengthToWrite =
MAX_FILE_IO;
00657 }
else {
00658 LengthToWrite = DataLength;
00659 }
00660
00661
00662
if (eventHandles[WaitBufferCount] ==
NULL) {
00663 status =
CmpCreateEvent(SynchronizationEvent,
00664 &eventHandles[WaitBufferCount],
00665 &eventObjects[WaitBufferCount]);
00666
if (!
NT_SUCCESS(status)) {
00667
00668 eventHandles[WaitBufferCount] =
NULL;
00669
goto Error_Exit;
00670 }
00671 }
00672
00673 status = ZwWriteFile(FileHandle,
00674 eventHandles[WaitBufferCount],
00675
NULL,
00676
NULL,
00677 &IoStatus[WaitBufferCount],
00678 DataBuffer,
00679 LengthToWrite,
00680 &
Offset,
00681
NULL);
00682
00683
if (!
NT_SUCCESS(status)) {
00684
goto Error_Exit;
00685 }
00686
00687 WaitBufferCount++;
00688
00689
00690
00691
00692 *FileOffset =
Offset.LowPart + LengthToWrite;
00693 DataLength -= LengthToWrite;
00694 (PUCHAR)DataBuffer += LengthToWrite;
00695 }
00696
00697 arrayCount++;
00698
00699 }
00700
00701
00702 status =
KeWaitForMultipleObjects(WaitBufferCount,
00703 eventObjects,
00704 WaitAll,
00705
Executive,
00706
KernelMode,
00707
FALSE,
00708
NULL,
00709 waitBlockArray);
00710
00711
if (!
NT_SUCCESS(status))
00712
goto Error_Exit;
00713
00714
for (idx = 0; idx < WaitBufferCount; idx++) {
00715
if (!
NT_SUCCESS(IoStatus[idx].
Status)) {
00716 ret_val =
FALSE;
00717
goto Done;
00718 }
00719 }
00720
00721
00722
00723
if (DataLength > 0) {
00724 arrayCount--;
00725 }
00726
00727 }
00728
00729 ret_val =
TRUE;
00730
00731
goto Done;
00732 Error_Exit:
00733
00734
00735
00736
CmRegistryIODebug.Action =
CmpIoFileWrite;
00737
CmRegistryIODebug.Handle = FileHandle;
00738
CmRegistryIODebug.Status = status;
00739
DbgPrint(
"CmpFileWrite: error exiting %d\n", status);
00740
00741
00742
00743
00744
00745
00746
if (WaitBufferCount > 0) {
00747 status =
KeWaitForMultipleObjects(WaitBufferCount,
00748 eventObjects,
00749 WaitAll,
00750
Executive,
00751
KernelMode,
00752
FALSE,
00753
NULL,
00754 waitBlockArray);
00755 }
00756
00757
00758 ret_val =
FALSE;
00759 Done:
00760 idx = 0;
00761
00762
while ((idx < MAXIMUM_WAIT_OBJECTS) && (eventHandles[idx] !=
NULL)) {
00763
ObDereferenceObject(eventObjects[idx]);
00764 ZwClose(eventHandles[idx]);
00765 idx++;
00766 }
00767
return ret_val;
00768 }
00769
00770
00771 BOOLEAN
00772 CmpFileFlush (
00773
PHHIVE Hive,
00774 ULONG FileType
00775 )
00776
00777
00778
00779
00780
00781
00782
00783
00784
00785
00786
00787
00788
00789
00790
00791
00792
00793
00794 {
00795
NTSTATUS status;
00796 IO_STATUS_BLOCK IoStatus;
00797
PCMHIVE CmHive;
00798 HANDLE FileHandle;
00799
00800
ASSERT(FIELD_OFFSET(
CMHIVE,
Hive) == 0);
00801 CmHive = (
PCMHIVE)
Hive;
00802 FileHandle = CmHive->
FileHandles[FileType];
00803
if (FileHandle ==
NULL) {
00804
return TRUE;
00805 }
00806
00807
if (
CmpNoWrite) {
00808
return TRUE;
00809 }
00810
00811
CMLOG(
CML_MAJOR,
CMS_IO) {
00812 KdPrint((
"CmpFileFlush:\n\tHandle = %08lx\n", FileHandle));
00813 }
00814
00815
ASSERT_PASSIVE_LEVEL();
00816
00817 status = ZwFlushBuffersFile(
00818 FileHandle,
00819 &IoStatus
00820 );
00821
00822
if (
NT_SUCCESS(status)) {
00823
ASSERT(IoStatus.Status == status);
00824
return TRUE;
00825 }
else {
00826
00827
00828
00829
CmRegistryIODebug.Action =
CmpIoFileFlush;
00830
CmRegistryIODebug.Handle = FileHandle;
00831
CmRegistryIODebug.Status = status;
00832
DbgPrint(
"CmpFileFlush:\tFailure1: status = %08lx IoStatus = %08lx\n",status,IoStatus.Status);
00833
return FALSE;
00834 }
00835
return TRUE;
00836 }