00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
#include "lpcp.h"
00022
00023
#ifdef ALLOC_PRAGMA
00024
#pragma alloc_text(INIT,LpcpInitializePortZone)
00025
#pragma alloc_text(PAGE,LpcpInitializePortQueue)
00026
#pragma alloc_text(PAGE,LpcpDestroyPortQueue)
00027
#pragma alloc_text(PAGE,LpcpExtendPortZone)
00028
#pragma alloc_text(PAGE,LpcpAllocateFromPortZone)
00029
#pragma alloc_text(PAGE,LpcpFreeToPortZone)
00030
#pragma alloc_text(PAGE,LpcpSaveDataInfoMessage)
00031
#pragma alloc_text(PAGE,LpcpFreeDataInfoMessage)
00032
#pragma alloc_text(PAGE,LpcpFindDataInfoMessage)
00033
#endif
00034
00035
00036
NTSTATUS
00037 LpcpInitializePortQueue (
00038 IN
PLPCP_PORT_OBJECT Port
00039 )
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057 {
00058
PLPCP_NONPAGED_PORT_QUEUE NonPagedPortQueue;
00059
00060
PAGED_CODE();
00061
00062
00063
00064
00065
00066 NonPagedPortQueue =
ExAllocatePoolWithTag(
NonPagedPool,
00067
sizeof(
LPCP_NONPAGED_PORT_QUEUE),
00068 'troP' );
00069
00070
if (NonPagedPortQueue ==
NULL) {
00071
00072
return STATUS_INSUFFICIENT_RESOURCES;
00073 }
00074
00075
00076
00077
00078
00079
KeInitializeSemaphore( &NonPagedPortQueue->
Semaphore, 0, 0x7FFFFFFF );
00080
00081 NonPagedPortQueue->
BackPointer = Port;
00082
00083
00084
00085
00086
00087 Port->
MsgQueue.
Semaphore = &NonPagedPortQueue->
Semaphore;
00088
00089
00090
00091
00092
00093 InitializeListHead( &Port->MsgQueue.ReceiveHead );
00094
00095
00096
00097
00098
00099
return STATUS_SUCCESS;
00100 }
00101
00102
00103
VOID
00104 LpcpDestroyPortQueue (
00105 IN
PLPCP_PORT_OBJECT Port,
00106 IN BOOLEAN CleanupAndDestroy
00107 )
00108
00109
00110
00111
00112
00113
00114
00115
00116
00117
00118
00119
00120
00121
00122
00123
00124
00125
00126
00127
00128
00129
00130
00131 {
00132 PLIST_ENTRY Next, Head;
00133
PETHREAD ThreadWaitingForReply;
00134
PLPCP_MESSAGE Msg;
00135
00136
PAGED_CODE();
00137
00138
00139
00140
00141
00142
00143
00144
LpcpAcquireLpcpLock();
00145
00146
if (Port->ConnectedPort !=
NULL) {
00147
00148 Port->ConnectedPort->ConnectedPort =
NULL;
00149 }
00150
00151
00152
00153
00154
00155
if ((Port->Flags &
PORT_TYPE) ==
SERVER_CONNECTION_PORT) {
00156
00157 Port->Flags |=
PORT_NAME_DELETED;
00158 }
00159
00160
00161
00162
00163
00164
00165
00166
00167 Head = &Port->LpcReplyChainHead;
00168 Next = Head->Flink;
00169
00170
while ((Next !=
NULL) && (Next != Head)) {
00171
00172 ThreadWaitingForReply = CONTAINING_RECORD( Next,
ETHREAD, LpcReplyChain );
00173
00174
00175
00176
00177
00178
if ( ThreadWaitingForReply->
LpcExitThreadCalled ) {
00179
00180
break;
00181 }
00182
00183 Next = Next->Flink;
00184
00185 RemoveEntryList( &ThreadWaitingForReply->
LpcReplyChain );
00186
00187 InitializeListHead( &ThreadWaitingForReply->
LpcReplyChain );
00188
00189
if (!
KeReadStateSemaphore( &ThreadWaitingForReply->
LpcReplySemaphore )) {
00190
00191
00192
00193
00194
00195
00196 Msg = ThreadWaitingForReply->
LpcReplyMessage;
00197
00198
if ( Msg ) {
00199
00200
00201
00202
00203
00204
00205
if ((Msg->
Request.u2.s2.Type & ~LPC_KERNELMODE_MESSAGE) == LPC_CONNECTION_REQUEST) {
00206
00207
PLPCP_CONNECTION_MESSAGE ConnectMsg;
00208
00209 ConnectMsg = (
PLPCP_CONNECTION_MESSAGE)(Msg + 1);
00210
00211
if ( ConnectMsg->
SectionToMap !=
NULL ) {
00212
00213
ObDereferenceObject( ConnectMsg->
SectionToMap );
00214 }
00215 }
00216
00217 ThreadWaitingForReply->
LpcReplyMessage =
NULL;
00218
00219
LpcpFreeToPortZone( Msg,
TRUE );
00220 }
00221
00222 ThreadWaitingForReply->
LpcReplyMessageId = 0;
00223
00224
KeReleaseSemaphore( &ThreadWaitingForReply->
LpcReplySemaphore,
00225 0,
00226 1
L,
00227
FALSE );
00228 }
00229 }
00230
00231 InitializeListHead( &Port->LpcReplyChainHead );
00232
00233
00234
00235
00236
00237
00238 Head = &Port->MsgQueue.ReceiveHead;
00239 Next = Head->Flink;
00240
00241
while ((Next !=
NULL) && (Next != Head)) {
00242
00243 Msg = CONTAINING_RECORD( Next,
LPCP_MESSAGE, Entry );
00244
00245 Next = Next->Flink;
00246
00247 InitializeListHead( &Msg->
Entry );
00248
00249
LpcpFreeToPortZone( Msg,
TRUE );
00250 }
00251
00252
00253
00254
00255
00256 InitializeListHead( &Port->MsgQueue.ReceiveHead );
00257
00258
LpcpReleaseLpcpLock();
00259
00260
00261
00262
00263
00264
if ( CleanupAndDestroy ) {
00265
00266
00267
00268
00269
00270
if (Port->MsgQueue.Semaphore !=
NULL) {
00271
00272
ExFreePool( CONTAINING_RECORD( Port->MsgQueue.Semaphore,
00273
LPCP_NONPAGED_PORT_QUEUE,
00274 Semaphore ));
00275 }
00276 }
00277
00278
00279
00280
00281
00282
return;
00283 }
00284
00285
00286
NTSTATUS
00287 LpcpInitializePortZone (
00288 IN ULONG MaxEntrySize,
00289 IN ULONG SegmentSize,
00290 IN ULONG MaxPoolUsage
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
NTSTATUS Status;
00319 PVOID Segment;
00320
PLPCP_MESSAGE Msg;
00321 LONG SegSize;
00322
00323
PAGED_CODE();
00324
00325
00326
00327
00328
00329
LpcpZone.
MaxPoolUsage = MaxPoolUsage;
00330
LpcpZone.
GrowSize = SegmentSize;
00331
00332
00333
00334
00335
00336 Segment =
ExAllocatePoolWithTag(
PagedPool, SegmentSize, 'ZcpL' );
00337
00338
if (Segment ==
NULL) {
00339
00340
return STATUS_INSUFFICIENT_RESOURCES;
00341 }
00342
00343
KeInitializeEvent( &
LpcpZone.
FreeEvent, SynchronizationEvent,
FALSE );
00344
00345
Status =
ExInitializeZone( &
LpcpZone.
Zone,
00346 MaxEntrySize,
00347 Segment,
00348 SegmentSize );
00349
00350
if (!
NT_SUCCESS(
Status )) {
00351
00352
ExFreePool( Segment );
00353 }
00354
00355
00356
00357
00358
00359
00360
00361
00362
00363
00364 SegSize =
PAGE_SIZE;
00365 LpcpTotalNumberOfMessages = 0;
00366
00367
00368
00369
00370
00371 Msg = (
PLPCP_MESSAGE)((
PZONE_SEGMENT_HEADER)Segment + 1);
00372
00373
00374
00375
00376
00377
while (SegSize >= (LONG)
LpcpZone.
Zone.
BlockSize) {
00378
00379 Msg->
ZoneIndex = (
USHORT)++LpcpTotalNumberOfMessages;
00380 Msg->
Reserved0 = 0;
00381 Msg->
Request.MessageId = 0;
00382
00383 Msg = (
PLPCP_MESSAGE)((PCHAR)Msg +
LpcpZone.
Zone.
BlockSize);
00384
00385 SegSize -=
LpcpZone.
Zone.
BlockSize;
00386 }
00387
00388
00389
00390
00391
00392
return Status;
00393 }
00394
00395
00396
NTSTATUS
00397 LpcpExtendPortZone (
00398 VOID
00399 )
00400
00401
00402
00403
00404
00405
00406
00407
00408
00409
00410
00411
00412
00413
00414
00415
00416
00417
00418
00419 {
00420
NTSTATUS Status;
00421 PVOID Segment;
00422
PLPCP_MESSAGE Msg;
00423 LARGE_INTEGER WaitTimeout;
00424 BOOLEAN AlreadyRetried;
00425 LONG SegmentSize;
00426
00427
PAGED_CODE();
00428
00429 AlreadyRetried =
FALSE;
00430
00431 retry:
00432
00433
00434
00435
00436
00437
00438
if ((
LpcpZone.
Zone.
TotalSegmentSize +
LpcpZone.
GrowSize) >
LpcpZone.
MaxPoolUsage) {
00439
00440
LpcpPrint((
"Out of space in global LPC zone - current size is %08x\n",
00441
LpcpZone.
Zone.
TotalSegmentSize ));
00442
00443
00444
00445
00446
00447
00448
00449
00450 WaitTimeout.QuadPart = Int32x32To64( 1000, -10000 );
00451
00452
LpcpReleaseLpcpLock();
00453
00454
Status =
KeWaitForSingleObject( &
LpcpZone.
FreeEvent,
00455
Executive,
00456
KernelMode,
00457
FALSE,
00458 &WaitTimeout );
00459
00460
LpcpAcquireLpcpLock();
00461
00462
if (
Status != STATUS_SUCCESS) {
00463
00464
LpcpPrint((
"Error waiting for %lx->FreeEvent - Status == %X\n",
00465 &
LpcpZone,
00466
Status ));
00467
00468
if ( !AlreadyRetried ) {
00469
00470 AlreadyRetried =
TRUE;
00471
00472
LpcpZone.
MaxPoolUsage +=
LpcpZone.
GrowSize;
00473
00474
goto retry;
00475 }
00476 }
00477
00478
00479
00480
00481
00482
00483
return Status;
00484 }
00485
00486
00487
00488
00489
00490
00491 Segment =
ExAllocatePoolWithTag(
PagedPool,
LpcpZone.
GrowSize, 'ZcpL' );
00492
00493
if (Segment ==
NULL) {
00494
00495
return STATUS_INSUFFICIENT_RESOURCES;
00496 }
00497
00498
Status =
ExExtendZone( &
LpcpZone.
Zone,
00499 Segment,
00500
LpcpZone.
GrowSize );
00501
00502
if (!
NT_SUCCESS(
Status )) {
00503
00504
ExFreePool( Segment );
00505 }
00506
00507
#if DEVL
00508
00509
else {
00510
00511
LpcpTrace((
"Extended LPC zone by %x for a total of %x\n",
00512
LpcpZone.
GrowSize,
LpcpZone.
Zone.
TotalSegmentSize ));
00513
00514
00515
00516
00517
00518
00519
00520
00521
00522
00523 SegmentSize =
PAGE_SIZE;
00524
00525 Msg = (
PLPCP_MESSAGE)((
PZONE_SEGMENT_HEADER)Segment + 1);
00526
00527
while (SegmentSize >= (LONG)
LpcpZone.
Zone.
BlockSize) {
00528
00529 Msg->
ZoneIndex = (
USHORT)++LpcpTotalNumberOfMessages;
00530
00531 Msg = (
PLPCP_MESSAGE)((PCHAR)Msg +
LpcpZone.
Zone.
BlockSize);
00532
00533 SegmentSize -=
LpcpZone.
Zone.
BlockSize;
00534 }
00535
00536
00537
00538
00539
00540
00541
LpcpReleaseLpcpLock();
00542
00543
KeSetEvent( &
LpcpZone.
FreeEvent,
00544
LPC_RELEASE_WAIT_INCREMENT,
00545
FALSE );
00546
00547
LpcpAcquireLpcpLock();
00548 }
00549
00550
#endif
00551
00552
return Status;
00553 }
00554
00555
00556
PLPCP_MESSAGE
00557
FASTCALL
00558 LpcpAllocateFromPortZone (
00559 ULONG Size
00560 )
00561
00562
00563
00564
00565
00566
00567
00568
00569
00570
00571
00572
00573
00574
00575
00576
00577
00578
00579
00580
00581 {
00582
NTSTATUS Status;
00583
PLPCP_MESSAGE Msg;
00584
00585
PAGED_CODE();
00586
00587
00588
00589
00590
00591
00592
do {
00593
00594
00595
00596
00597
00598
00599
00600 Msg = (
PLPCP_MESSAGE)
ExAllocateFromZone( &
LpcpZone.
Zone );
00601
00602
if (Msg !=
NULL) {
00603
00604
LpcpTrace((
"Allocate Msg %lx\n", Msg ));
00605
00606 InitializeListHead( &Msg->
Entry );
00607
00608 Msg->
RepliedToThread =
NULL;
00609
00610
#if DBG
00611
00612
00613
00614
00615 Msg->
ZoneIndex |= LPCP_ZONE_MESSAGE_ALLOCATED;
00616
#endif
00617
00618
return Msg;
00619 }
00620
00621
00622
00623
00624
00625
00626
LpcpTrace((
"Extending Zone %lx\n", &
LpcpZone.
Zone ));
00627
00628
Status =
LpcpExtendPortZone( );
00629
00630 }
while (
NT_SUCCESS(
Status));
00631
00632
00633
00634
00635
00636
return NULL;
00637 }
00638
00639
00640
VOID
00641
FASTCALL
00642 LpcpFreeToPortZone (
00643 IN
PLPCP_MESSAGE Msg,
00644 IN BOOLEAN MutexOwned
00645 )
00646
00647
00648
00649
00650
00651
00652
00653
00654
00655
00656
00657
00658
00659
00660
00661
00662
00663
00664
00665 {
00666 BOOLEAN ZoneMemoryAvailable =
FALSE;
00667
PLPCP_CONNECTION_MESSAGE ConnectMsg;
00668
00669
PAGED_CODE();
00670
00671
00672
00673
00674
00675
if (!MutexOwned) {
00676
00677
LpcpAcquireLpcpLock();
00678 }
00679
00680
LpcpTrace((
"Free Msg %lx\n", Msg ));
00681
00682
#if DBG
00683
00684
00685
00686
00687
00688
if (!(Msg->ZoneIndex & LPCP_ZONE_MESSAGE_ALLOCATED)) {
00689
00690
LpcpPrint((
"Msg %lx has already been freed.\n", Msg ));
00691 DbgBreakPoint();
00692
00693
if (!MutexOwned) {
00694
00695
LpcpReleaseLpcpLock();
00696 }
00697
00698
return;
00699 }
00700
00701 Msg->ZoneIndex &= ~LPCP_ZONE_MESSAGE_ALLOCATED;
00702
00703
#endif
00704
00705
00706
00707
00708
00709
if (Msg->Reserved0 != 0) {
00710
00711
00712
00713
00714
00715
00716
00717
if (!IsListEmpty( &Msg->Entry )) {
00718
00719 RemoveEntryList( &Msg->Entry );
00720
00721 InitializeListHead( &Msg->Entry );
00722 }
00723
00724
00725
00726
00727
00728
00729
if (Msg->RepliedToThread !=
NULL) {
00730
00731
ObDereferenceObject( Msg->RepliedToThread );
00732
00733 Msg->RepliedToThread =
NULL;
00734 }
00735
00736
00737
00738
00739
00740
00741
00742
if ((Msg->Request.u2.s2.Type & ~LPC_KERNELMODE_MESSAGE) == LPC_CONNECTION_REQUEST) {
00743
00744 ConnectMsg = (
PLPCP_CONNECTION_MESSAGE)(Msg + 1);
00745
00746
if (ConnectMsg->
ClientPort) {
00747
00748
PLPCP_PORT_OBJECT ClientPort;
00749
00750
00751
00752
00753
00754
00755
00756 ClientPort = ConnectMsg->
ClientPort;
00757
00758 ConnectMsg->
ClientPort =
NULL;
00759
00760
LpcpReleaseLpcpLock();
00761
00762
ObDereferenceObject( ClientPort );
00763
00764
LpcpAcquireLpcpLock();
00765 }
00766 }
00767
00768
00769
00770
00771
00772 Msg->Reserved0 = 0;
00773 ZoneMemoryAvailable = (BOOLEAN)(
ExFreeToZone( &
LpcpZone.
Zone, &Msg->FreeEntry ) ==
NULL);
00774 }
00775
00776
00777
00778
00779
00780
if (!MutexOwned) {
00781
00782
LpcpReleaseLpcpLock();
00783 }
00784
00785
00786
00787
00788
00789
00790
00791
00792
00793
if (ZoneMemoryAvailable) {
00794
00795
KeSetEvent( &
LpcpZone.
FreeEvent,
00796
LPC_RELEASE_WAIT_INCREMENT,
00797
FALSE );
00798 }
00799
00800
00801
00802
00803
00804
return;
00805 }
00806
00807
00808
VOID
00809 LpcpSaveDataInfoMessage (
00810 IN
PLPCP_PORT_OBJECT Port,
00811
PLPCP_MESSAGE Msg
00812 )
00813
00814
00815
00816
00817
00818
00819
00820
00821
00822
00823
00824
00825
00826
00827
00828
00829
00830
00831
00832
00833 {
00834
PAGED_CODE();
00835
00836
00837
00838
00839
00840
LpcpAcquireLpcpLock();
00841
00842
00843
00844
00845
00846
if ((Port->Flags &
PORT_TYPE) >
UNCONNECTED_COMMUNICATION_PORT) {
00847
00848 Port = Port->ConnectionPort;
00849 }
00850
00851
LpcpTrace((
"%s Saving DataInfo Message %lx (%u.%u) Port: %lx\n",
00852
PsGetCurrentProcess()->ImageFileName,
00853 Msg,
00854 Msg->
Request.MessageId,
00855 Msg->
Request.CallbackId,
00856 Port ));
00857
00858
00859
00860
00861
00862 InsertTailList( &Port->LpcDataInfoChainHead, &Msg->
Entry );
00863
00864
00865
00866
00867
00868
LpcpReleaseLpcpLock();
00869
00870
00871
00872
00873
00874
return;
00875 }
00876
00877
00878
VOID
00879 LpcpFreeDataInfoMessage (
00880 IN
PLPCP_PORT_OBJECT Port,
00881 IN ULONG MessageId,
00882 IN ULONG CallbackId
00883 )
00884
00885
00886
00887
00888
00889
00890
00891
00892
00893
00894
00895
00896
00897
00898
00899
00900
00901
00902
00903
00904
00905 {
00906
PLPCP_MESSAGE Msg;
00907 PLIST_ENTRY Head, Next;
00908
00909
PAGED_CODE();
00910
00911
00912
00913
00914
00915
if ((Port->Flags &
PORT_TYPE) >
UNCONNECTED_COMMUNICATION_PORT) {
00916
00917 Port = Port->ConnectionPort;
00918 }
00919
00920
00921
00922
00923
00924 Head = &Port->LpcDataInfoChainHead;
00925 Next = Head->Flink;
00926
00927
while (Next != Head) {
00928
00929 Msg = CONTAINING_RECORD( Next,
LPCP_MESSAGE, Entry );
00930
00931
00932
00933
00934
00935
00936
00937
if ((Msg->
Request.MessageId == MessageId) &&
00938 (Msg->
Request.CallbackId == CallbackId)) {
00939
00940
LpcpTrace((
"%s Removing DataInfo Message %lx (%u.%u) Port: %lx\n",
00941
PsGetCurrentProcess()->ImageFileName,
00942 Msg,
00943 Msg->
Request.MessageId,
00944 Msg->
Request.CallbackId,
00945 Port ));
00946
00947 RemoveEntryList( &Msg->
Entry );
00948
00949 InitializeListHead( &Msg->
Entry );
00950
00951
LpcpFreeToPortZone( Msg,
TRUE );
00952
00953
return;
00954
00955 }
else {
00956
00957
00958
00959
00960
00961 Next = Next->Flink;
00962 }
00963 }
00964
00965
00966
00967
00968
00969
LpcpTrace((
"%s Unable to find DataInfo Message (%u.%u) Port: %lx\n",
00970
PsGetCurrentProcess()->ImageFileName,
00971 MessageId,
00972 CallbackId,
00973 Port ));
00974
00975
return;
00976 }
00977
00978
00979
PLPCP_MESSAGE
00980 LpcpFindDataInfoMessage (
00981 IN
PLPCP_PORT_OBJECT Port,
00982 IN ULONG MessageId,
00983 IN ULONG CallbackId
00984 )
00985
00986
00987
00988
00989
00990
00991
00992
00993
00994
00995
00996
00997
00998
00999
01000
01001
01002
01003
01004
01005
01006
01007
01008 {
01009
PLPCP_MESSAGE Msg;
01010 PLIST_ENTRY Head, Next;
01011
01012
PAGED_CODE();
01013
01014
01015
01016
01017
01018
if ((Port->Flags &
PORT_TYPE) >
UNCONNECTED_COMMUNICATION_PORT) {
01019
01020 Port = Port->ConnectionPort;
01021 }
01022
01023
01024
01025
01026
01027
01028 Head = &Port->LpcDataInfoChainHead;
01029 Next = Head->Flink;
01030
01031
while (Next != Head) {
01032
01033 Msg = CONTAINING_RECORD( Next,
LPCP_MESSAGE, Entry );
01034
01035
if ((Msg->
Request.MessageId == MessageId) &&
01036 (Msg->
Request.CallbackId == CallbackId)) {
01037
01038
LpcpTrace((
"%s Found DataInfo Message %lx (%u.%u) Port: %lx\n",
01039
PsGetCurrentProcess()->ImageFileName,
01040 Msg,
01041 Msg->
Request.MessageId,
01042 Msg->
Request.CallbackId,
01043 Port ));
01044
01045
return Msg;
01046
01047 }
else {
01048
01049 Next = Next->Flink;
01050 }
01051 }
01052
01053
01054
01055
01056
01057
LpcpTrace((
"%s Unable to find DataInfo Message (%u.%u) Port: %lx\n",
01058
PsGetCurrentProcess()->ImageFileName,
01059 MessageId,
01060 CallbackId,
01061 Port ));
01062
01063
return NULL;
01064 }