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
00028
00029
00030
00031
00032
VOID
00033
IopFreeMiniPacket (
00034
PIOP_MINI_COMPLETION_PACKET MiniPacket
00035 );
00036
00037
00038
00039
00040
00041
#ifdef ALLOC_PRAGMA
00042
#pragma alloc_text(PAGE, NtCreateIoCompletion)
00043
#pragma alloc_text(PAGE, NtOpenIoCompletion)
00044
#pragma alloc_text(PAGE, NtQueryIoCompletion)
00045
#pragma alloc_text(PAGE, NtRemoveIoCompletion)
00046
#pragma alloc_text(PAGE, NtSetIoCompletion)
00047
#pragma alloc_text(PAGE, IoSetIoCompletion)
00048
#endif
00049
00050
NTSTATUS
00051 NtCreateIoCompletion (
00052 IN PHANDLE IoCompletionHandle,
00053 IN ACCESS_MASK DesiredAccess,
00054 IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL,
00055 IN ULONG Count OPTIONAL
00056 )
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087 {
00088
00089 HANDLE
Handle;
00090
KPROCESSOR_MODE PreviousMode;
00091 PVOID IoCompletion;
00092
NTSTATUS Status;
00093
00094
00095
00096
00097
00098
00099
00100
00101
try {
00102
00103
00104
00105
00106
00107
00108 PreviousMode = KeGetPreviousMode();
00109
if (PreviousMode !=
KernelMode) {
00110
ProbeForWriteHandle(IoCompletionHandle);
00111 }
00112
00113
00114
00115
00116
00117
Status =
ObCreateObject(PreviousMode,
00118
IoCompletionObjectType,
00119
ObjectAttributes,
00120 PreviousMode,
00121
NULL,
00122
sizeof(
KQUEUE),
00123 0,
00124 0,
00125 (PVOID *)&IoCompletion);
00126
00127
00128
00129
00130
00131
00132
00133
if (
NT_SUCCESS(
Status)) {
00134
KeInitializeQueue((
PKQUEUE)IoCompletion,
Count);
00135
Status =
ObInsertObject(IoCompletion,
00136
NULL,
00137 DesiredAccess,
00138 0,
00139 (PVOID *)
NULL,
00140 &
Handle);
00141
00142
00143
00144
00145
00146
00147
00148
00149
00150
if (
NT_SUCCESS(
Status)) {
00151
try {
00152 *IoCompletionHandle =
Handle;
00153
00154 } except(
ExSystemExceptionFilter()) {
00155 NOTHING;
00156 }
00157 }
00158 }
00159
00160
00161
00162
00163
00164
00165
00166 } except(
ExSystemExceptionFilter()) {
00167
Status = GetExceptionCode();
00168 }
00169
00170
00171
00172
00173
00174
return Status;
00175 }
00176
00177
NTSTATUS
00178 NtOpenIoCompletion (
00179 OUT PHANDLE IoCompletionHandle,
00180 IN ACCESS_MASK DesiredAccess,
00181 IN POBJECT_ATTRIBUTES ObjectAttributes
00182 )
00183
00184
00185
00186
00187
00188
00189
00190
00191
00192
00193
00194
00195
00196
00197
00198
00199
00200
00201
00202
00203
00204
00205
00206
00207
00208 {
00209
00210 HANDLE
Handle;
00211
KPROCESSOR_MODE PreviousMode;
00212
NTSTATUS Status;
00213
00214
00215
00216
00217
00218
00219
00220
00221
try {
00222
00223
00224
00225
00226
00227
00228 PreviousMode = KeGetPreviousMode();
00229
if (PreviousMode !=
KernelMode) {
00230
ProbeForWriteHandle(IoCompletionHandle);
00231 }
00232
00233
00234
00235
00236
00237
00238
Status =
ObOpenObjectByName(
ObjectAttributes,
00239
IoCompletionObjectType,
00240 PreviousMode,
00241
NULL,
00242 DesiredAccess,
00243
NULL,
00244 &
Handle);
00245
00246
00247
00248
00249
00250
00251
00252
00253
if (
NT_SUCCESS(
Status)) {
00254
try {
00255 *IoCompletionHandle =
Handle;
00256
00257 } except(
ExSystemExceptionFilter()) {
00258 NOTHING;
00259 }
00260 }
00261
00262
00263
00264
00265
00266
00267
00268 } except(
ExSystemExceptionFilter()) {
00269
Status = GetExceptionCode();
00270 }
00271
00272
00273
00274
00275
00276
00277
return Status;
00278 }
00279
00280
00281
NTSTATUS
00282 NtQueryIoCompletion (
00283 IN HANDLE IoCompletionHandle,
00284 IN IO_COMPLETION_INFORMATION_CLASS IoCompletionInformationClass,
00285 OUT PVOID IoCompletionInformation,
00286 IN ULONG IoCompletionInformationLength,
00287 OUT PULONG ReturnLength OPTIONAL
00288 )
00289
00290
00291
00292
00293
00294
00295
00296
00297
00298
00299
00300
00301
00302
00303
00304
00305
00306
00307
00308
00309
00310
00311
00312
00313
00314
00315
00316
00317
00318
00319
00320 {
00321
00322 PVOID IoCompletion;
00323 LONG Depth;
00324
KPROCESSOR_MODE PreviousMode;
00325
NTSTATUS Status;
00326
00327
00328
00329
00330
00331
00332
00333
00334
00335
try {
00336
00337
00338
00339
00340
00341 PreviousMode = KeGetPreviousMode();
00342
if (PreviousMode !=
KernelMode) {
00343
ProbeForWrite(IoCompletionInformation,
00344
sizeof(IO_COMPLETION_BASIC_INFORMATION),
00345
sizeof(ULONG));
00346
00347
if (ARGUMENT_PRESENT(ReturnLength)) {
00348
ProbeForWriteUlong(ReturnLength);
00349 }
00350 }
00351
00352
00353
00354
00355
00356
if (IoCompletionInformationClass != IoCompletionBasicInformation) {
00357
return STATUS_INVALID_INFO_CLASS;
00358 }
00359
00360
if (IoCompletionInformationLength !=
sizeof(IO_COMPLETION_BASIC_INFORMATION)) {
00361
return STATUS_INFO_LENGTH_MISMATCH;
00362 }
00363
00364
00365
00366
00367
00368
Status =
ObReferenceObjectByHandle(IoCompletionHandle,
00369 IO_COMPLETION_QUERY_STATE,
00370
IoCompletionObjectType,
00371 PreviousMode,
00372 &IoCompletion,
00373
NULL);
00374
00375
00376
00377
00378
00379
00380
00381
00382
00383
00384
00385
if (
NT_SUCCESS(
Status)) {
00386 Depth =
KeReadStateQueue((
PKQUEUE)IoCompletion);
00387
ObDereferenceObject(IoCompletion);
00388
try {
00389 ((PIO_COMPLETION_BASIC_INFORMATION)IoCompletionInformation)->Depth = Depth;
00390
if (ARGUMENT_PRESENT(ReturnLength)) {
00391 *ReturnLength =
sizeof(IO_COMPLETION_BASIC_INFORMATION);
00392 }
00393
00394 } except(
ExSystemExceptionFilter()) {
00395 NOTHING;
00396 }
00397 }
00398
00399
00400
00401
00402
00403
00404
00405 } except(
ExSystemExceptionFilter()) {
00406
Status = GetExceptionCode();
00407 }
00408
00409
00410
00411
00412
00413
return Status;
00414 }
00415
00416
NTSTATUS
00417 NtSetIoCompletion (
00418 IN HANDLE IoCompletionHandle,
00419 IN PVOID KeyContext,
00420 IN PVOID ApcContext,
00421 IN NTSTATUS IoStatus,
00422 IN ULONG_PTR IoStatusInformation
00423 )
00424
00425
00426
00427
00428
00429
00430
00431
00432
00433
00434
00435
00436
00437
00438
00439
00440
00441
00442
00443
00444
00445
00446
00447
00448
00449
00450
00451
00452
00453
00454
00455
00456 {
00457 PVOID IoCompletion;
00458
PIOP_MINI_COMPLETION_PACKET MiniPacket;
00459
NTSTATUS Status;
00460
00461
PAGED_CODE();
00462
00463
Status =
ObReferenceObjectByHandle(IoCompletionHandle,
00464 IO_COMPLETION_MODIFY_STATE,
00465
IoCompletionObjectType,
00466 KeGetPreviousMode(),
00467 &IoCompletion,
00468
NULL);
00469
00470
if (
NT_SUCCESS(
Status)) {
00471
Status =
IoSetIoCompletion(IoCompletion,
00472 KeyContext,
00473 ApcContext,
00474 IoStatus,
00475 IoStatusInformation,
00476
TRUE);
00477
00478
ObDereferenceObject(IoCompletion);
00479 }
00480
return Status;
00481
00482 }
00483
00484
NTSTATUS
00485 NtRemoveIoCompletion (
00486 IN HANDLE IoCompletionHandle,
00487 OUT PVOID *KeyContext,
00488 OUT PVOID *ApcContext,
00489 OUT PIO_STATUS_BLOCK IoStatusBlock,
00490 IN PLARGE_INTEGER Timeout OPTIONAL
00491 )
00492
00493
00494
00495
00496
00497
00498
00499
00500
00501
00502
00503
00504
00505
00506
00507
00508
00509
00510
00511
00512
00513
00514
00515
00516
00517
00518
00519
00520
00521
00522
00523
00524 {
00525
00526 PLARGE_INTEGER CapturedTimeout;
00527 PLIST_ENTRY Entry;
00528 PVOID IoCompletion;
00529
PIRP Irp;
00530
KPROCESSOR_MODE PreviousMode;
00531
NTSTATUS Status;
00532 LARGE_INTEGER TimeoutValue;
00533 PVOID LocalApcContext;
00534 PVOID LocalKeyContext;
00535 IO_STATUS_BLOCK LocalIoStatusBlock;
00536
PIOP_MINI_COMPLETION_PACKET MiniPacket;
00537
00538
00539
00540
00541
00542
00543
00544
00545
00546
00547
try {
00548
00549
00550
00551
00552
00553
00554 CapturedTimeout =
NULL;
00555 PreviousMode = KeGetPreviousMode();
00556
if (PreviousMode !=
KernelMode) {
00557
ProbeForWriteUlong_ptr((PULONG_PTR)ApcContext);
00558
ProbeForWriteUlong_ptr((PULONG_PTR)KeyContext);
00559
ProbeForWriteIoStatus(IoStatusBlock);
00560
if (ARGUMENT_PRESENT(Timeout)) {
00561 CapturedTimeout = &TimeoutValue;
00562 TimeoutValue =
ProbeAndReadLargeInteger(Timeout);
00563 }
00564
00565 }
else{
00566
if (ARGUMENT_PRESENT(Timeout)) {
00567 CapturedTimeout = Timeout;
00568 }
00569 }
00570
00571
00572
00573
00574
00575
Status =
ObReferenceObjectByHandle(IoCompletionHandle,
00576 IO_COMPLETION_MODIFY_STATE,
00577
IoCompletionObjectType,
00578 PreviousMode,
00579 &IoCompletion,
00580
NULL);
00581
00582
00583
00584
00585
00586
00587
00588
00589
00590
00591
00592
if (
NT_SUCCESS(
Status)) {
00593 Entry =
KeRemoveQueue((
PKQUEUE)IoCompletion,
00594 PreviousMode,
00595 CapturedTimeout);
00596
00597
00598
00599
00600
00601
00602
if (((LONG_PTR)Entry == STATUS_TIMEOUT) ||
00603 ((LONG_PTR)Entry == STATUS_USER_APC)) {
00604
Status = (
NTSTATUS)((LONG_PTR)Entry);
00605
00606 }
else {
00607
00608
00609
00610
00611
00612
00613
00614
Status = STATUS_SUCCESS;
00615
try {
00616 MiniPacket = CONTAINING_RECORD(Entry,
00617
IOP_MINI_COMPLETION_PACKET,
00618 ListEntry);
00619
00620
if ( MiniPacket->
PacketType ==
IopCompletionPacketIrp ) {
00621
Irp = CONTAINING_RECORD(Entry,
IRP, Tail.Overlay.ListEntry);
00622 LocalApcContext =
Irp->
Overlay.AsynchronousParameters.UserApcContext;
00623 LocalKeyContext = (PVOID)
Irp->
Tail.CompletionKey;
00624 LocalIoStatusBlock =
Irp->
IoStatus;
00625
IoFreeIrp(
Irp);
00626
00627 }
else {
00628
00629 LocalApcContext = MiniPacket->
ApcContext;
00630 LocalKeyContext = (PVOID)MiniPacket->
KeyContext;
00631 LocalIoStatusBlock.Status = MiniPacket->
IoStatus;
00632 LocalIoStatusBlock.Information = MiniPacket->
IoStatusInformation;
00633
IopFreeMiniPacket(MiniPacket);
00634 }
00635
00636 *ApcContext = LocalApcContext;
00637 *KeyContext = LocalKeyContext;
00638 *IoStatusBlock = LocalIoStatusBlock;
00639
00640 } except(
ExSystemExceptionFilter()) {
00641 NOTHING;
00642 }
00643 }
00644
00645
00646
00647
00648
00649
ObDereferenceObject(IoCompletion);
00650 }
00651
00652
00653
00654
00655
00656
00657
00658 } except(
ExSystemExceptionFilter()) {
00659
Status = GetExceptionCode();
00660 }
00661
00662
00663
00664
00665
00666
return Status;
00667 }
00668
00669
NTKERNELAPI
00670
NTSTATUS
00671 IoSetIoCompletion (
00672 IN PVOID IoCompletion,
00673 IN PVOID KeyContext,
00674 IN PVOID ApcContext,
00675 IN NTSTATUS IoStatus,
00676 IN ULONG_PTR IoStatusInformation,
00677 IN BOOLEAN Quota
00678 )
00679
00680
00681
00682
00683
00684
00685
00686
00687
00688
00689
00690
00691
00692
00693
00694
00695
00696
00697
00698
00699
00700
00701
00702
00703
00704
00705
00706
00707
00708
00709
00710
00711 {
00712
00713
PNPAGED_LOOKASIDE_LIST Lookaside;
00714
PIOP_MINI_COMPLETION_PACKET MiniPacket;
00715 ULONG PacketType;
00716 PKPRCB Prcb;
00717
NTSTATUS Status = STATUS_SUCCESS;
00718
00719
PAGED_CODE();
00720
00721
00722
00723
00724
00725 PacketType =
IopCompletionPacketMini;
00726 Prcb =
KeGetCurrentPrcb();
00727 Lookaside = Prcb->PPLookasideList[
LookasideCompletionList].P;
00728 Lookaside->
L.
TotalAllocates += 1;
00729 MiniPacket = (PVOID)
ExInterlockedPopEntrySList(&Lookaside->
L.
ListHead,
00730 &Lookaside->
Lock);
00731
00732
00733
00734
00735
00736
00737
if (MiniPacket ==
NULL) {
00738 Lookaside->
L.
AllocateMisses += 1;
00739 Lookaside = Prcb->PPLookasideList[
LookasideCompletionList].
L;
00740 Lookaside->
L.
TotalAllocates += 1;
00741 MiniPacket = (PVOID)
ExInterlockedPopEntrySList(&Lookaside->
L.
ListHead,
00742 &Lookaside->
Lock);
00743 }
00744
00745
00746
00747
00748
00749
00750
if (MiniPacket ==
NULL) {
00751 Lookaside->
L.
AllocateMisses += 1;
00752
00753
00754
00755
00756
00757
00758
if (Quota !=
FALSE) {
00759 PacketType =
IopCompletionPacketQuota;
00760
try {
00761 MiniPacket =
ExAllocatePoolWithQuotaTag(
NonPagedPool,
00762
sizeof(*MiniPacket),
00763 ' pcI');
00764
00765 } except(
EXCEPTION_EXECUTE_HANDLER) {
00766 NOTHING;
00767 }
00768
00769 }
else {
00770 MiniPacket =
ExAllocatePoolWithTag(
NonPagedPool,
00771
sizeof(*MiniPacket),
00772 ' pcI');
00773 }
00774 }
00775
00776
00777
00778
00779
00780
00781
if (MiniPacket !=
NULL) {
00782 MiniPacket->
PacketType = PacketType;
00783 MiniPacket->
KeyContext = KeyContext;
00784 MiniPacket->
ApcContext = ApcContext;
00785 MiniPacket->
IoStatus = IoStatus;
00786 MiniPacket->
IoStatusInformation = IoStatusInformation;
00787
KeInsertQueue((
PKQUEUE)IoCompletion, &MiniPacket->
ListEntry);
00788
00789 }
else {
00790
Status = STATUS_INSUFFICIENT_RESOURCES;
00791 }
00792
00793
return Status;
00794 }
00795
00796
VOID
00797 IopFreeMiniPacket (
00798
PIOP_MINI_COMPLETION_PACKET MiniPacket
00799 )
00800
00801
00802
00803
00804
00805
00806
00807
00808
00809
00810
00811
00812
00813
00814
00815
00816
00817 {
00818
00819
PNPAGED_LOOKASIDE_LIST Lookaside;
00820 PKPRCB Prcb;
00821
00822
00823
00824
00825
00826
00827
00828
00829 Prcb =
KeGetCurrentPrcb();
00830 Lookaside = Prcb->PPLookasideList[
LookasideCompletionList].P;
00831 Lookaside->
L.
TotalFrees += 1;
00832
if (
ExQueryDepthSList(&Lookaside->
L.
ListHead) >= Lookaside->
L.
Depth) {
00833 Lookaside->
L.
FreeMisses += 1;
00834 Lookaside = Prcb->PPLookasideList[
LookasideCompletionList].
L;
00835 Lookaside->
L.
TotalFrees += 1;
00836
if (
ExQueryDepthSList(&Lookaside->
L.
ListHead) >= Lookaside->
L.
Depth) {
00837 Lookaside->
L.
FreeMisses += 1;
00838
ExFreePool(MiniPacket);
00839
00840 }
else {
00841
if (MiniPacket->
PacketType ==
IopCompletionPacketQuota) {
00842
ExReturnPoolQuota(MiniPacket);
00843 }
00844
00845
ExInterlockedPushEntrySList(&Lookaside->
L.
ListHead,
00846 (PSINGLE_LIST_ENTRY)MiniPacket,
00847 &Lookaside->
Lock);
00848 }
00849
00850 }
else {
00851
if (MiniPacket->
PacketType ==
IopCompletionPacketQuota) {
00852
ExReturnPoolQuota(MiniPacket);
00853 }
00854
00855
ExInterlockedPushEntrySList(&Lookaside->
L.
ListHead,
00856 (PSINGLE_LIST_ENTRY)MiniPacket,
00857 &Lookaside->
Lock);
00858 }
00859
00860
return;
00861 }
00862
00863
VOID
00864 IopDeleteIoCompletion (
00865 IN PVOID Object
00866 )
00867
00868
00869
00870
00871
00872
00873
00874
00875
00876
00877
00878
00879
00880
00881
00882
00883
00884
00885
00886 {
00887
00888 PLIST_ENTRY FirstEntry;
00889
PIRP Irp;
00890 PLIST_ENTRY NextEntry;
00891
PIOP_MINI_COMPLETION_PACKET MiniPacket;
00892
00893
00894
00895
00896
00897
00898 FirstEntry =
KeRundownQueue((
PKQUEUE)Object);
00899
if (FirstEntry !=
NULL) {
00900 NextEntry = FirstEntry;
00901
do {
00902 MiniPacket = CONTAINING_RECORD(NextEntry,
00903
IOP_MINI_COMPLETION_PACKET,
00904 ListEntry);
00905
00906 NextEntry = NextEntry->Flink;
00907
if (MiniPacket->
PacketType ==
IopCompletionPacketIrp) {
00908
Irp = CONTAINING_RECORD(MiniPacket,
IRP, Tail.Overlay.
ListEntry);
00909
IoFreeIrp(
Irp);
00910
00911 }
else {
00912
IopFreeMiniPacket(MiniPacket);
00913 }
00914
00915 }
while (FirstEntry != NextEntry);
00916 }
00917
00918
return;
00919 }