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
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
#include "FsRtlP.h"
00061
00062
#ifndef INLINE
00063 #define INLINE __inline
00064
#endif
00065
00066
00067
00068
00069
00070 #define TUNNEL_KEY_NAME L"\\Registry\\Machine\\System\\CurrentControlSet\\Control\\FileSystem"
00071 #define TUNNEL_AGE_VALUE_NAME L"MaximumTunnelEntryAgeInSeconds"
00072 #define TUNNEL_SIZE_VALUE_NAME L"MaximumTunnelEntries"
00073 #define KEY_WORK_AREA ((sizeof(KEY_VALUE_FULL_INFORMATION) + sizeof(ULONG)) + 64)
00074
00075
00076
00077
00078
00079 ULONG
TunnelMaxEntries;
00080 ULONG
TunnelMaxAge;
00081
00082
00083
00084
00085
00086
00087
00088
00089
00090 PAGED_LOOKASIDE_LIST TunnelLookasideList;
00091 #define MAX_LOOKASIDE_DEPTH 256
00092
00093 #define LOOKASIDE_NODE_SIZE ( sizeof(TUNNEL_NODE) + \
00094
sizeof(WCHAR)*(8+1+3) + \
00095
sizeof(WCHAR)*(16) + \
00096
sizeof(ULONGLONG) )
00097
00098
00099
00100
00101
00102 #define TUNNEL_FLAG_NON_LOOKASIDE 0x1
00103 #define TUNNEL_FLAG_KEY_SHORT 0x2
00104
00105
00106
00107
00108
00109
00110
00111
00112
00113
00114
00115
00116 typedef struct {
00117
00118
00119
00120
00121
00122 RTL_SPLAY_LINKS CacheLinks;
00123
00124
00125
00126
00127
00128 LIST_ENTRY ListLinks;
00129
00130
00131
00132
00133
00134 LARGE_INTEGER CreateTime;
00135
00136
00137
00138
00139
00140 ULONGLONG DirKey;
00141
00142
00143
00144
00145
00146 ULONG Flags;
00147
00148
00149
00150
00151
00152 UNICODE_STRING LongName;
00153 UNICODE_STRING ShortName;
00154
00155
00156
00157
00158
00159 PVOID TunnelData;
00160 ULONG TunnelDataLength;
00161
00162 }
TUNNEL_NODE, *
PTUNNEL_NODE;
00163
00164
00165
00166
00167
00168
NTSTATUS
00169
FsRtlGetTunnelParameterValue (
00170 IN PUNICODE_STRING ValueName,
00171 IN OUT PULONG Value);
00172
00173
VOID
00174
FsRtlPruneTunnelCache (
00175 IN
PTUNNEL Cache,
00176 IN OUT PLIST_ENTRY FreePoolList);
00177
00178
#ifdef ALLOC_PRAGMA
00179
#pragma alloc_text(PAGE, FsRtlInitializeTunnels)
00180
#pragma alloc_text(PAGE, FsRtlInitializeTunnelCache)
00181
#pragma alloc_text(PAGE, FsRtlAddToTunnelCache)
00182
#pragma alloc_text(PAGE, FsRtlFindInTunnelCache)
00183
#pragma alloc_text(PAGE, FsRtlDeleteKeyFromTunnelCache)
00184
#pragma alloc_text(PAGE, FsRtlDeleteTunnelCache)
00185
#pragma alloc_text(PAGE, FsRtlPruneTunnelCache)
00186
#pragma alloc_text(PAGE, FsRtlGetTunnelParameterValue)
00187
#endif
00188
00189
00190
00191
00192
00193
00194
00195
#if defined(TUNNELTEST) || defined(KEYVIEW)
00196
VOID DumpUnicodeString(UNICODE_STRING *s);
00197
VOID DumpNode(
TUNNEL_NODE *Node, ULONG Indent );
00198
VOID DumpTunnel(
TUNNEL *Tunnel );
00199
#define DblHex64(a) (ULONG)((a >> 32) & 0xffffffff),(ULONG)(a & 0xffffffff)
00200
#endif // TUNNELTEST
00201
00202
#ifdef USERTEST
00203
#include <stdio.h>
00204
#undef KeQuerySystemTime
00205
#define KeQuerySystemTime NtQuerySystemTime
00206
#undef ExInitializeFastMutex
00207
#define ExInitializeFastMutex(arg)
00208
#define ExAcquireFastMutex(arg)
00209
#define ExReleaseFastMutex(arg)
00210
#define DbgPrint printf
00211
#undef PAGED_CODE
00212
#define PAGED_CODE()
00213
#endif
00214
00215
00216
INLINE
00217 LONG
00218 FsRtlCompareNodeAndKey (
00219
TUNNEL_NODE *Node,
00220 ULONGLONG DirectoryKey,
00221 PUNICODE_STRING Name
00222 )
00223
00224
00225
00226
00227
00228
00229
00230
00231
00232
00233
00234
00235
00236
00237
00238
00239
00240
00241
00242
00243 {
00244
return (Node->
DirKey > DirectoryKey ? 1 :
00245 (Node->
DirKey < DirectoryKey ? -1 :
00246
RtlCompareUnicodeString((
FlagOn(Node->
Flags,
TUNNEL_FLAG_KEY_SHORT) ?
00247 &Node->
ShortName : &Node->
LongName),
00248
Name,
00249
TRUE)));
00250 }
00251
00252
00253
INLINE
00254
VOID
00255 FsRtlFreeTunnelNode (
00256 PTUNNEL_NODE Node,
00257 PLIST_ENTRY FreePoolList OPTIONAL
00258 )
00259
00260
00261
00262
00263
00264
00265
00266
00267
00268
00269
00270
00271
00272
00273
00274
00275
00276 {
00277
if (FreePoolList) {
00278
00279 InsertHeadList(FreePoolList, &Node->ListLinks);
00280
00281 }
else {
00282
00283
if (
FlagOn(Node->Flags,
TUNNEL_FLAG_NON_LOOKASIDE)) {
00284
00285
ExFreePool(Node);
00286
00287 }
else {
00288
00289
ExFreeToPagedLookasideList(&
TunnelLookasideList, Node);
00290 }
00291 }
00292 }
00293
00294
00295
INLINE
00296
VOID
00297 FsRtlEmptyFreePoolList (
00298 PLIST_ENTRY FreePoolList
00299 )
00300
00301
00302
00303
00304
00305
00306
00307
00308
00309
00310
00311
00312
00313
00314
00315 {
00316
PTUNNEL_NODE FreeNode;
00317
00318
while (!IsListEmpty(FreePoolList)) {
00319
00320 FreeNode = CONTAINING_RECORD(FreePoolList->Flink,
TUNNEL_NODE, ListLinks);
00321 RemoveEntryList(FreePoolList->Flink);
00322
00323
FsRtlFreeTunnelNode(FreeNode,
NULL);
00324 }
00325 }
00326
00327
00328
INLINE
00329
VOID
00330 FsRtlRemoveNodeFromTunnel (
00331 IN PTUNNEL Cache,
00332 IN PTUNNEL_NODE Node,
00333 IN PLIST_ENTRY FreePoolList,
00334 IN PBOOLEAN Splay OPTIONAL
00335 )
00336
00337
00338
00339
00340
00341
00342
00343
00344
00345
00346
00347
00348
00349
00350
00351
00352
00353
00354
00355
00356
00357
00358
00359
00360
00361 {
00362
if (Splay && *Splay) {
00363
00364 Cache->Cache =
RtlDelete(&Node->CacheLinks);
00365
00366 *Splay =
FALSE;
00367
00368 }
else {
00369
00370
RtlDeleteNoSplay(&Node->CacheLinks, &Cache->Cache);
00371 }
00372
00373 RemoveEntryList(&Node->ListLinks);
00374
00375 Cache->NumEntries--;
00376
00377
FsRtlFreeTunnelNode(Node, FreePoolList);
00378 }
00379
00380
00381
VOID
00382 FsRtlInitializeTunnels (
00383 VOID
00384 )
00385
00386
00387
00388
00389
00390
00391
00392
00393
00394
00395
00396
00397
00398
00399
00400 {
00401 UNICODE_STRING
ValueName;
00402
USHORT LookasideDepth;
00403
00404
PAGED_CODE();
00405
00406
if (
MmIsThisAnNtAsSystem()) {
00407
00408
TunnelMaxEntries = 1024;
00409
00410 }
else {
00411
00412
TunnelMaxEntries = 256;
00413 }
00414
00415
TunnelMaxAge = 15;
00416
00417
00418
00419
00420
00421
00422
00423
00424
ValueName.Buffer =
TUNNEL_SIZE_VALUE_NAME;
00425
ValueName.Length =
sizeof(
TUNNEL_SIZE_VALUE_NAME) -
sizeof(WCHAR);
00426
ValueName.MaximumLength =
sizeof(
TUNNEL_SIZE_VALUE_NAME);
00427 (
VOID)
FsRtlGetTunnelParameterValue(&
ValueName, &
TunnelMaxEntries);
00428
00429
ValueName.Buffer =
TUNNEL_AGE_VALUE_NAME;
00430
ValueName.Length =
sizeof(
TUNNEL_AGE_VALUE_NAME) -
sizeof(WCHAR);
00431
ValueName.MaximumLength =
sizeof(
TUNNEL_AGE_VALUE_NAME);
00432 (
VOID)
FsRtlGetTunnelParameterValue(&
ValueName, &
TunnelMaxAge);
00433
00434
if (
TunnelMaxAge == 0) {
00435
00436
00437
00438
00439
00440
00441
00442
00443
TunnelMaxEntries = 0;
00444 }
00445
00446
00447
00448
00449
00450
TunnelMaxAge *= 10000000;
00451
00452
00453
00454
00455
00456
if (
TunnelMaxEntries > MAXUSHORT) {
00457
00458
00459
00460
00461
00462 LookasideDepth =
MAX_LOOKASIDE_DEPTH;
00463
00464 }
else {
00465
00466 LookasideDepth = ((
USHORT)
TunnelMaxEntries)/16;
00467 }
00468
00469
if (LookasideDepth == 0 &&
TunnelMaxEntries) {
00470
00471
00472
00473
00474
00475 LookasideDepth = (
USHORT)
TunnelMaxEntries + 1;
00476 }
00477
00478
if (LookasideDepth >
MAX_LOOKASIDE_DEPTH) {
00479
00480
00481
00482
00483
00484 LookasideDepth =
MAX_LOOKASIDE_DEPTH;
00485 }
00486
00487
ExInitializePagedLookasideList( &
TunnelLookasideList,
00488
NULL,
00489
NULL,
00490 0,
00491
LOOKASIDE_NODE_SIZE,
00492 'LnuT',
00493 LookasideDepth );
00494
00495
return;
00496 }
00497
00498
00499
00500
00501
00502
00503
00504
00505
00506
00507
00508
00509
00510
00511
00512
00513
00514
00515
00516
VOID
00517 FsRtlInitializeTunnelCache (
00518 IN PTUNNEL Cache
00519 )
00520
00521
00522
00523
00524
00525
00526
00527
00528
00529
00530
00531
00532
00533
00534
00535 {
00536
PAGED_CODE();
00537
00538
ExInitializeFastMutex(&Cache->Mutex);
00539
00540 Cache->Cache =
NULL;
00541 InitializeListHead(&Cache->TimerQueue);
00542 Cache->NumEntries = 0;
00543
00544
return;
00545 }
00546
00547
00548
00549
00550
00551
00552
00553
00554
00555
00556
00557
00558
00559
00560
00561
00562
00563
00564
00565
00566
00567
00568
00569
00570
00571
00572
00573
00574
00575
00576
00577
00578
00579
00580
00581
00582
00583
VOID
00584 FsRtlAddToTunnelCache (
00585 IN PTUNNEL Cache,
00586 IN ULONGLONG DirKey,
00587 IN PUNICODE_STRING ShortName,
00588 IN PUNICODE_STRING LongName,
00589 IN BOOLEAN KeyByShortName,
00590 IN ULONG DataLength,
00591 IN PVOID Data
00592 )
00593
00594
00595
00596
00597
00598
00599
00600
00601
00602
00603
00604
00605
00606
00607
00608
00609
00610
00611
00612
00613
00614
00615
00616
00617
00618
00619
00620
00621
00622
00623
00624
00625
00626
00627
00628 {
00629 LONG
Compare;
00630 ULONG NodeSize;
00631 PUNICODE_STRING NameKey;
00632 PRTL_SPLAY_LINKS *Links;
00633 LIST_ENTRY FreePoolList;
00634
00635
PTUNNEL_NODE Node =
NULL;
00636
PTUNNEL_NODE NewNode =
NULL;
00637 BOOLEAN FreeOldNode =
FALSE;
00638 BOOLEAN AllocatedFromPool =
FALSE;
00639
00640
PAGED_CODE();
00641
00642
00643
00644
00645
00646
if (
TunnelMaxEntries == 0)
return;
00647
00648 InitializeListHead(&FreePoolList);
00649
00650
00651
00652
00653
00654 NodeSize =
sizeof(
TUNNEL_NODE) + ShortName->Length + LongName->Length + DataLength;
00655
00656
if (
LOOKASIDE_NODE_SIZE >= NodeSize) {
00657
00658 NewNode =
ExAllocateFromPagedLookasideList(&
TunnelLookasideList);
00659 }
00660
00661
if (NewNode ==
NULL) {
00662
00663
00664
00665
00666
00667 NewNode =
ExAllocatePoolWithTag(
PagedPool, NodeSize, 'PnuT');
00668
00669
if (NewNode ==
NULL) {
00670
00671
00672
00673
00674
00675
return;
00676 }
00677
00678 AllocatedFromPool =
TRUE;
00679 }
00680
00681
00682
00683
00684
00685 NameKey = (KeyByShortName ? ShortName : LongName);
00686
00687 ExAcquireFastMutex(&Cache->Mutex);
00688
00689 Links = &Cache->Cache;
00690
00691
while (*Links) {
00692
00693 Node = CONTAINING_RECORD(*Links,
TUNNEL_NODE, CacheLinks);
00694
00695
Compare =
FsRtlCompareNodeAndKey(Node, DirKey, NameKey);
00696
00697
if (
Compare > 0) {
00698
00699 Links = &RtlLeftChild(&Node->CacheLinks);
00700
00701 }
else {
00702
00703
if (
Compare < 0) {
00704
00705 Links = &RtlRightChild(&Node->CacheLinks);
00706
00707 }
else {
00708
00709
break;
00710 }
00711 }
00712 }
00713
00714
00715
00716
00717
00718 RtlInitializeSplayLinks(&NewNode->CacheLinks);
00719
00720
if (Node) {
00721
00722
00723
00724
00725
00726
if (*Links) {
00727
00728
00729
00730
00731
00732 RtlRightChild(&NewNode->CacheLinks) = RtlRightChild(*Links);
00733 RtlLeftChild(&NewNode->CacheLinks) = RtlLeftChild(*Links);
00734
00735
if (RtlRightChild(*Links)) RtlParent(RtlRightChild(*Links)) = &NewNode->CacheLinks;
00736
if (RtlLeftChild(*Links)) RtlParent(RtlLeftChild(*Links)) = &NewNode->CacheLinks;
00737
00738
if (!RtlIsRoot(*Links)) {
00739
00740
00741
00742
00743
00744
00745 RtlParent(&NewNode->CacheLinks) = RtlParent(*Links);
00746
00747
if (RtlIsLeftChild(*Links)) {
00748
00749 RtlLeftChild(RtlParent(*Links)) = &NewNode->CacheLinks;
00750
00751 }
else {
00752
00753 RtlRightChild(RtlParent(*Links)) = &NewNode->CacheLinks;
00754 }
00755
00756 }
else {
00757
00758
00759
00760
00761
00762 Cache->Cache = &NewNode->CacheLinks;
00763 }
00764
00765
00766
00767
00768
00769 RemoveEntryList(&Node->ListLinks);
00770
00771
FsRtlFreeTunnelNode(Node, &FreePoolList);
00772
00773 Cache->NumEntries--;
00774
00775 }
else {
00776
00777
00778
00779
00780
00781 NewNode->CacheLinks.Parent = &Node->CacheLinks;
00782 *Links = &NewNode->CacheLinks;
00783 }
00784
00785 }
else {
00786
00787 Cache->Cache = &NewNode->CacheLinks;
00788 }
00789
00790
00791
00792
00793
00794
KeQuerySystemTime(&NewNode->CreateTime);
00795 InsertTailList(&Cache->TimerQueue, &NewNode->ListLinks);
00796
00797 Cache->NumEntries++;
00798
00799
00800
00801
00802
00803 NewNode->DirKey = DirKey;
00804
00805
if (KeyByShortName) {
00806
00807 NewNode->Flags =
TUNNEL_FLAG_KEY_SHORT;
00808
00809 }
else {
00810
00811 NewNode->Flags = 0;
00812 }
00813
00814
00815
00816
00817
00818
00819
00820
00821
00822
00823
00824
00825
00826
00827 NewNode->ShortName.Buffer = (PWCHAR)((PCHAR)NewNode +
sizeof(
TUNNEL_NODE));
00828 NewNode->LongName.Buffer = (PWCHAR)((PCHAR)NewNode +
sizeof(
TUNNEL_NODE) + ShortName->Length);
00829
00830 NewNode->ShortName.Length = NewNode->ShortName.MaximumLength = ShortName->Length;
00831 NewNode->LongName.Length = NewNode->LongName.MaximumLength = LongName->Length;
00832
00833
if (ShortName->Length) {
00834
00835 RtlCopyMemory(NewNode->ShortName.Buffer, ShortName->Buffer, ShortName->Length);
00836 }
00837
00838
if (LongName->Length) {
00839
00840 RtlCopyMemory(NewNode->LongName.Buffer, LongName->Buffer, LongName->Length);
00841 }
00842
00843 NewNode->TunnelData = (PVOID)((PCHAR)NewNode +
sizeof(
TUNNEL_NODE) + ShortName->Length + LongName->Length);
00844
00845 NewNode->TunnelDataLength = DataLength;
00846
00847 RtlCopyMemory(NewNode->TunnelData, Data, DataLength);
00848
00849
if (AllocatedFromPool) {
00850
00851
SetFlag(NewNode->Flags,
TUNNEL_FLAG_NON_LOOKASIDE);
00852 }
00853
00854
#if defined(TUNNELTEST) || defined (KEYVIEW)
00855
DbgPrint(
"FsRtlAddToTunnelCache:\n");
00856 DumpNode(NewNode, 1);
00857
#ifndef KEYVIEW
00858
DumpTunnel(Cache);
00859
#endif
00860
#endif // TUNNELTEST
00861
00862
00863
00864
00865
00866
FsRtlPruneTunnelCache(Cache, &FreePoolList);
00867
00868 ExReleaseFastMutex(&Cache->Mutex);
00869
00870
FsRtlEmptyFreePoolList(&FreePoolList);
00871
00872
return;
00873 }
00874
00875
00876
00877
00878
00879
00880
00881
00882
00883
00884
00885
00886
00887
00888
00889
00890
00891
00892
00893
00894
00895
00896
00897
00898
00899
00900
00901
00902
00903
00904
00905
00906
00907
00908
00909
00910
00911
00912 BOOLEAN
00913 FsRtlFindInTunnelCache (
00914 IN PTUNNEL Cache,
00915 IN ULONGLONG DirKey,
00916 IN PUNICODE_STRING Name,
00917 OUT PUNICODE_STRING ShortName,
00918 OUT PUNICODE_STRING LongName,
00919 IN OUT PULONG DataLength,
00920 OUT PVOID Data
00921 )
00922
00923
00924
00925
00926
00927
00928
00929
00930
00931
00932
00933
00934
00935
00936
00937
00938
00939
00940
00941
00942
00943
00944
00945
00946
00947
00948
00949
00950
00951
00952
00953
00954
00955
00956
00957 {
00958 PRTL_SPLAY_LINKS Links;
00959
PTUNNEL_NODE Node;
00960 LONG
Compare;
00961 LIST_ENTRY FreePoolList;
00962
00963 BOOLEAN
Status =
FALSE;
00964
00965
PAGED_CODE();
00966
00967
00968
00969
00970
00971
if (
TunnelMaxEntries == 0)
return FALSE;
00972
00973 InitializeListHead(&FreePoolList);
00974
00975
#ifdef KEYVIEW
00976
DbgPrint(
"++\nSearching for %wZ , %08x%08x\n--\n",
Name, DblHex64(DirKey));
00977
#endif
00978
00979 ExAcquireFastMutex(&Cache->Mutex);
00980
00981
00982
00983
00984
00985
FsRtlPruneTunnelCache(Cache, &FreePoolList);
00986
00987 Links = Cache->Cache;
00988
00989
while (Links) {
00990
00991 Node = CONTAINING_RECORD(Links,
TUNNEL_NODE, CacheLinks);
00992
00993
Compare =
FsRtlCompareNodeAndKey(Node, DirKey,
Name);
00994
00995
if (
Compare > 0) {
00996
00997 Links = RtlLeftChild(&Node->CacheLinks);
00998
00999 }
else {
01000
01001
if (
Compare < 0) {
01002
01003 Links = RtlRightChild(&Node->CacheLinks);
01004
01005 }
else {
01006
01007
01008
01009
01010
01011
#if defined(TUNNELTEST) || defined(KEYVIEW)
01012
DbgPrint(
"FsRtlFindInTunnelCache:\n");
01013 DumpNode(Node, 1);
01014
#ifndef KEYVIEW
01015
DumpTunnel(Cache);
01016
#endif
01017
#endif // TUNNELTEST
01018
01019
break;
01020 }
01021 }
01022 }
01023
01024
try {
01025
01026
if (Links) {
01027
01028
01029
01030
01031
01032
ASSERT(ShortName->MaximumLength >= (8+1+3)*
sizeof(WCHAR));
01033
RtlCopyUnicodeString(ShortName, &Node->ShortName);
01034
01035
if (LongName->MaximumLength >= Node->LongName.Length) {
01036
01037
RtlCopyUnicodeString(LongName, &Node->LongName);
01038
01039 }
else {
01040
01041
01042
01043
01044
01045 LongName->Buffer =
FsRtlAllocatePoolWithTag(
PagedPool, Node->LongName.Length, '4nuT');
01046 LongName->Length = LongName->MaximumLength = Node->LongName.Length;
01047
01048 RtlCopyMemory(LongName->Buffer, Node->LongName.Buffer, Node->LongName.Length);
01049 }
01050
01051
ASSERT(*DataLength >= Node->TunnelDataLength);
01052 RtlCopyMemory(Data, Node->TunnelData, Node->TunnelDataLength);
01053 *DataLength = Node->TunnelDataLength;
01054
01055
Status =
TRUE;
01056 }
01057
01058 } finally {
01059
01060 ExReleaseFastMutex(&Cache->Mutex);
01061
01062
FsRtlEmptyFreePoolList(&FreePoolList);
01063 }
01064
01065
return Status;
01066 }
01067
01068
01069
01070
01071
01072
01073
01074
01075
01076
01077
01078
01079
01080
01081
01082
01083
01084
01085
VOID
01086 FsRtlDeleteKeyFromTunnelCache (
01087 IN PTUNNEL Cache,
01088 IN ULONGLONG DirKey
01089 )
01090
01091
01092
01093
01094
01095
01096
01097
01098
01099
01100
01101
01102
01103
01104
01105
01106
01107 {
01108 PRTL_SPLAY_LINKS Links;
01109 PRTL_SPLAY_LINKS SuccessorLinks;
01110
PTUNNEL_NODE Node;
01111 LIST_ENTRY FreePoolList;
01112
01113 PRTL_SPLAY_LINKS LastLinks =
NULL;
01114 BOOLEAN Splay =
TRUE;
01115
01116
PAGED_CODE();
01117
01118
01119
01120
01121
01122
if (
TunnelMaxEntries == 0)
return;
01123
01124 InitializeListHead(&FreePoolList);
01125
01126
#ifdef KEYVIEW
01127
DbgPrint(
"++\nDeleting key %08x%08x\n--\n", DblHex64(DirKey));
01128
#endif
01129
01130 ExAcquireFastMutex(&Cache->Mutex);
01131
01132 Links = Cache->Cache;
01133
01134
while (Links) {
01135
01136 Node = CONTAINING_RECORD(Links,
TUNNEL_NODE, CacheLinks);
01137
01138
if (Node->DirKey > DirKey) {
01139
01140
01141
01142
01143
01144 Links = RtlLeftChild(&Node->CacheLinks);
01145
01146 }
else {
01147
01148
if (Node->DirKey < DirKey) {
01149
01150
if (LastLinks) {
01151
01152
01153
01154
01155
01156
01157
break;
01158 }
01159
01160 Links = RtlRightChild(&Node->CacheLinks);
01161
01162 }
else {
01163
01164
01165
01166
01167
01168
01169 LastLinks = Links;
01170 Links = RtlLeftChild(&Node->CacheLinks);
01171 }
01172 }
01173 }
01174
01175
for (Links = LastLinks;
01176 Links;
01177 Links = SuccessorLinks) {
01178
01179 SuccessorLinks =
RtlRealSuccessor(Links);
01180 Node = CONTAINING_RECORD(Links,
TUNNEL_NODE, CacheLinks);
01181
01182
if (Node->DirKey != DirKey) {
01183
01184
01185
01186
01187
01188
break;
01189 }
01190
01191
FsRtlRemoveNodeFromTunnel(Cache, Node, &FreePoolList, &Splay);
01192 }
01193
01194
#ifdef TUNNELTEST
01195
DbgPrint(
"FsRtlDeleteKeyFromTunnelCache:\n");
01196
#ifndef KEYVIEW
01197
DumpTunnel(Cache);
01198
#endif
01199
#endif // TUNNELTEST
01200
01201 ExReleaseFastMutex(&Cache->Mutex);
01202
01203
01204
01205
01206
01207
FsRtlEmptyFreePoolList(&FreePoolList);
01208
01209
return;
01210 }
01211
01212
01213
01214
01215
01216
01217
01218
01219
01220
01221
01222
01223
01224
01225
VOID
01226 FsRtlDeleteTunnelCache (
01227 IN PTUNNEL Cache
01228 )
01229
01230
01231
01232
01233
01234
01235
01236
01237
01238
01239
01240
01241
01242
01243
01244 {
01245
PTUNNEL_NODE Node;
01246 PLIST_ENTRY Link, Next;
01247
01248
PAGED_CODE();
01249
01250
01251
01252
01253
01254
if (
TunnelMaxEntries == 0)
return;
01255
01256
01257
01258
01259
01260 Cache->Cache =
NULL;
01261 Cache->NumEntries = 0;
01262
01263
for (Link = Cache->TimerQueue.Flink;
01264 Link != &Cache->TimerQueue;
01265 Link = Next) {
01266
01267 Next = Link->Flink;
01268
01269 Node = CONTAINING_RECORD(Link,
TUNNEL_NODE, ListLinks);
01270
01271
FsRtlFreeTunnelNode(Node,
NULL);
01272 }
01273
01274 InitializeListHead(&Cache->TimerQueue);
01275
01276
return;
01277 }
01278
01279
01280
VOID
01281 FsRtlPruneTunnelCache (
01282 IN PTUNNEL Cache,
01283 IN OUT PLIST_ENTRY FreePoolList
01284 )
01285
01286
01287
01288
01289
01290
01291
01292
01293
01294
01295
01296
01297
01298
01299
01300
01301
01302
01303
01304
01305 {
01306
PTUNNEL_NODE Node;
01307 LARGE_INTEGER ExpireTime;
01308 LARGE_INTEGER CurrentTime;
01309 BOOLEAN Splay =
TRUE;
01310
01311
PAGED_CODE();
01312
01313
01314
01315
01316
01317
KeQuerySystemTime(&CurrentTime);
01318 ExpireTime.QuadPart = CurrentTime.QuadPart -
TunnelMaxAge;
01319
01320
01321
01322
01323
01324
01325
01326
01327
01328
while (!IsListEmpty(&Cache->TimerQueue)) {
01329
01330 Node = CONTAINING_RECORD(Cache->TimerQueue.Flink,
TUNNEL_NODE, ListLinks);
01331
01332
if (Node->CreateTime.QuadPart < ExpireTime.QuadPart ||
01333 Node->CreateTime.QuadPart > CurrentTime.QuadPart) {
01334
01335
#if defined(TUNNELTEST) || defined(KEYVIEW)
01336
DbgPrint(
"Expiring node %x (%ud%ud 1/10 msec too old)\n", Node, DblHex64(ExpireTime.QuadPart - Node->CreateTime.QuadPart));
01337
#endif // TUNNELTEST
01338
01339
FsRtlRemoveNodeFromTunnel(Cache, Node, FreePoolList, &Splay);
01340
01341 }
else {
01342
01343
01344
01345
01346
01347
break;
01348 }
01349 }
01350
01351
01352
01353
01354
01355
while (Cache->NumEntries >
TunnelMaxEntries) {
01356
01357 Node = CONTAINING_RECORD(Cache->TimerQueue.Flink,
TUNNEL_NODE, ListLinks);
01358
01359
#if defined(TUNNELTEST) || defined(KEYVIEW)
01360
DbgPrint(
"Dumping node %x (%d > %d)\n", Node, Cache->NumEntries,
TunnelMaxEntries);
01361
#endif // TUNNELTEST
01362
01363
FsRtlRemoveNodeFromTunnel(Cache, Node, FreePoolList, &Splay);
01364 }
01365
01366
return;
01367 }
01368
01369
01370
NTSTATUS
01371 FsRtlGetTunnelParameterValue (
01372 IN PUNICODE_STRING ValueName,
01373 IN OUT PULONG Value
01374 )
01375
01376
01377
01378
01379
01380
01381
01382
01383
01384
01385
01386
01387
01388
01389
01390
01391
01392
01393
01394
01395
01396
01397
01398
01399
01400 {
01401 HANDLE
Handle;
01402
NTSTATUS Status;
01403 ULONG RequestLength;
01404 ULONG ResultLength;
01405 UCHAR
Buffer[
KEY_WORK_AREA];
01406 UNICODE_STRING
KeyName;
01407 OBJECT_ATTRIBUTES
ObjectAttributes;
01408 PKEY_VALUE_FULL_INFORMATION KeyValueInformation;
01409
01410
KeyName.Buffer =
TUNNEL_KEY_NAME;
01411
KeyName.Length =
sizeof(
TUNNEL_KEY_NAME) -
sizeof(WCHAR);
01412
KeyName.MaximumLength =
sizeof(
TUNNEL_KEY_NAME);
01413
01414 InitializeObjectAttributes(&
ObjectAttributes,
01415 &
KeyName,
01416 OBJ_CASE_INSENSITIVE,
01417
NULL,
01418
NULL);
01419
01420
Status = ZwOpenKey(&
Handle,
01421 KEY_READ,
01422 &
ObjectAttributes);
01423
01424
if (!
NT_SUCCESS(
Status)) {
01425
01426
return Status;
01427 }
01428
01429 RequestLength =
KEY_WORK_AREA;
01430
01431 KeyValueInformation = (PKEY_VALUE_FULL_INFORMATION)
Buffer;
01432
01433
while (1) {
01434
01435
Status = ZwQueryValueKey(
Handle,
01436
ValueName,
01437 KeyValueFullInformation,
01438 KeyValueInformation,
01439 RequestLength,
01440 &ResultLength);
01441
01442
ASSERT(
Status != STATUS_BUFFER_OVERFLOW );
01443
01444
if (
Status == STATUS_BUFFER_OVERFLOW) {
01445
01446
01447
01448
01449
01450
if (KeyValueInformation != (PKEY_VALUE_FULL_INFORMATION)
Buffer) {
01451
01452
ExFreePool(KeyValueInformation);
01453 }
01454
01455 RequestLength += 256;
01456
01457 KeyValueInformation = (PKEY_VALUE_FULL_INFORMATION)
01458
ExAllocatePoolWithTag(
PagedPool,
01459 RequestLength,
01460 'KnuT');
01461
01462
if (!KeyValueInformation) {
01463
return STATUS_NO_MEMORY;
01464 }
01465
01466 }
else {
01467
01468
break;
01469 }
01470 }
01471
01472 ZwClose(
Handle);
01473
01474
if (
NT_SUCCESS(
Status)) {
01475
01476
if (KeyValueInformation->DataLength != 0) {
01477
01478 PULONG DataPtr;
01479
01480
01481
01482
01483
01484 DataPtr = (PULONG)
01485 ((PUCHAR)KeyValueInformation + KeyValueInformation->DataOffset);
01486 *Value = *DataPtr;
01487
01488 }
else {
01489
01490
01491
01492
01493
01494
Status = STATUS_OBJECT_NAME_NOT_FOUND;
01495 }
01496 }
01497
01498
if (KeyValueInformation != (PKEY_VALUE_FULL_INFORMATION)
Buffer) {
01499
01500
ExFreePool(KeyValueInformation);
01501 }
01502
01503
return Status;
01504 }
01505
01506
01507
#if defined(TUNNELTEST) || defined(KEYVIEW)
01508
01509
VOID
01510 DumpTunnel (
01511 PTUNNEL Tunnel
01512 )
01513 {
01514 PRTL_SPLAY_LINKS SplayLinks,
Ptr;
01515
PTUNNEL_NODE Node;
01516 PLIST_ENTRY Link;
01517 ULONG Indent = 1, i;
01518 ULONG EntryCount = 0;
01519 BOOLEAN CountOff =
FALSE;
01520
01521
DbgPrint(
"++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\n");
01522
01523
DbgPrint(
"NumEntries = %d\n", Tunnel->NumEntries);
01524
DbgPrint(
"****** Cache Tree\n");
01525
01526 SplayLinks = Tunnel->Cache;
01527
01528
if (SplayLinks ==
NULL) {
01529
01530
goto end;
01531 }
01532
01533
while (RtlLeftChild(SplayLinks) !=
NULL) {
01534
01535 SplayLinks = RtlLeftChild(SplayLinks);
01536 Indent++;
01537 }
01538
01539
while (SplayLinks) {
01540
01541 Node = CONTAINING_RECORD( SplayLinks,
TUNNEL_NODE, CacheLinks );
01542
01543 EntryCount++;
01544
01545 DumpNode(Node, Indent);
01546
01547
Ptr = SplayLinks;
01548
01549
01550
01551
01552
01553
01554
01555
01556
01557
01558
01559
01560
01561
01562
01563
01564
if ((
Ptr = RtlRightChild(SplayLinks)) !=
NULL) {
01565
01566 Indent++;
01567
while (RtlLeftChild(Ptr) !=
NULL) {
01568
01569 Indent++;
01570
Ptr = RtlLeftChild(Ptr);
01571 }
01572
01573 SplayLinks =
Ptr;
01574
01575 }
else {
01576
01577
01578
01579
01580
01581
01582
01583
01584
01585
01586
01587
01588
01589
Ptr = SplayLinks;
01590
while (RtlIsRightChild(Ptr)) {
01591
01592 Indent--;
01593
Ptr = RtlParent(Ptr);
01594 }
01595
01596
if (!RtlIsLeftChild(Ptr)) {
01597
01598
01599
01600
01601
01602 SplayLinks =
NULL;
01603
01604 }
else {
01605
01606 Indent--;
01607 SplayLinks = RtlParent(Ptr);
01608 }
01609 }
01610 }
01611
01612 end:
01613
01614
if (CountOff = (EntryCount != Tunnel->NumEntries)) {
01615
01616
DbgPrint(
"!!!!!!!!!! Splay Tree Count Mismatch (%d != %d)\n", EntryCount, Tunnel->NumEntries);
01617 }
01618
01619 EntryCount = 0;
01620
01621
DbgPrint(
"****** Timer Queue\n");
01622
01623
for (Link = Tunnel->TimerQueue.Flink;
01624 Link != &Tunnel->TimerQueue;
01625 Link = Link->Flink) {
01626
01627 Node = CONTAINING_RECORD( Link,
TUNNEL_NODE, ListLinks );
01628
01629 EntryCount++;
01630
01631 DumpNode(Node, 1);
01632 }
01633
01634
if (CountOff |= (EntryCount != Tunnel->NumEntries)) {
01635
01636
DbgPrint(
"!!!!!!!!!! Timer Queue Count Mismatch (%d != %d)\n", EntryCount, Tunnel->NumEntries);
01637 }
01638
01639
ASSERT(!CountOff);
01640
01641
DbgPrint(
"------------------------------------------------------------------\n");
01642 }
01643
01644
#define MAXINDENT 128
01645
#define INDENTSTEP 3
01646
01647
VOID
01648 DumpNode (
01649 PTUNNEL_NODE Node,
01650 ULONG Indent
01651 )
01652 {
01653 ULONG i;
01654
CHAR SpaceBuf[MAXINDENT*INDENTSTEP + 1];
01655
01656 Indent--;
01657
if (Indent > MAXINDENT) {
01658 Indent = MAXINDENT;
01659 }
01660
01661
01662
01663
01664
01665
01666 RtlFillMemory(SpaceBuf, Indent*INDENTSTEP,
' ');
01667 SpaceBuf[Indent*INDENTSTEP] =
'\0';
01668
01669
DbgPrint(
"%sNode 0x%x CreateTime = %08x%08x, DirKey = %08x%08x, Flags = %d\n",
01670 SpaceBuf,
01671 Node,
01672 DblHex64(Node->CreateTime.QuadPart),
01673 DblHex64(Node->DirKey),
01674 Node->Flags );
01675
01676
DbgPrint(
"%sShort = %wZ, Long = %wZ\n", SpaceBuf,
01677 &Node->ShortName,
01678 &Node->LongName );
01679
01680
DbgPrint(
"%sP = %x, R = %x, L = %x\n", SpaceBuf,
01681 RtlParent(&Node->CacheLinks),
01682 RtlRightChild(&Node->CacheLinks),
01683 RtlLeftChild(&Node->CacheLinks) );
01684 }
01685
#endif // TUNNELTEST
01686