00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
#include "ntrtlp.h"
00022
#include "range.h"
00023
00024
#if DBG
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034 LONG RtlRangeDebugLevel = 0;
00035
00036
#endif
00037
00038
NTSTATUS
00039
RtlpAddRange(
00040 IN OUT PLIST_ENTRY ListHead,
00041 IN
PRTLP_RANGE_LIST_ENTRY Entry,
00042 IN ULONG AddRangeFlags
00043 );
00044
00045
NTSTATUS
00046
RtlpAddToMergedRange(
00047 IN
PRTLP_RANGE_LIST_ENTRY Merged,
00048 IN
PRTLP_RANGE_LIST_ENTRY Entry,
00049 IN ULONG AddRangeFlags
00050 );
00051
00052
NTSTATUS
00053
RtlpConvertToMergedRange(
00054 IN
PRTLP_RANGE_LIST_ENTRY Entry
00055 );
00056
00057
PRTLP_RANGE_LIST_ENTRY
00058
RtlpCreateRangeListEntry(
00059 IN ULONGLONG Start,
00060 IN ULONGLONG End,
00061 IN UCHAR Attributes,
00062 IN PVOID UserData,
00063 IN PVOID Owner
00064 );
00065
00066
NTSTATUS
00067
RtlpAddIntersectingRanges(
00068 IN PLIST_ENTRY ListHead,
00069 IN
PRTLP_RANGE_LIST_ENTRY First,
00070 IN
PRTLP_RANGE_LIST_ENTRY Entry,
00071 IN ULONG AddRangeFlags
00072 );
00073
00074
NTSTATUS
00075
RtlpDeleteFromMergedRange(
00076 IN
PRTLP_RANGE_LIST_ENTRY Delete,
00077 IN
PRTLP_RANGE_LIST_ENTRY Merged
00078 );
00079
00080
PRTLP_RANGE_LIST_ENTRY
00081
RtlpCopyRangeListEntry(
00082
PRTLP_RANGE_LIST_ENTRY Entry
00083 );
00084
00085
VOID
00086
RtlpDeleteRangeListEntry(
00087 IN
PRTLP_RANGE_LIST_ENTRY Entry
00088 );
00089
00090 BOOLEAN
00091
RtlpIsRangeAvailable(
00092 IN PRTL_RANGE_LIST_ITERATOR Iterator,
00093 IN ULONGLONG Start,
00094 IN ULONGLONG End,
00095 IN UCHAR AttributeAvailableMask,
00096 IN BOOLEAN SharedOK,
00097 IN BOOLEAN NullConflictOK,
00098 IN BOOLEAN Forward,
00099 IN PVOID Context OPTIONAL,
00100 IN PRTL_CONFLICT_RANGE_CALLBACK Callback OPTIONAL
00101 );
00102
00103
#if DBG
00104
00105
VOID
00106
RtlpDumpRangeListEntry(
00107 LONG Level,
00108
PRTLP_RANGE_LIST_ENTRY Entry,
00109 BOOLEAN Indent
00110 );
00111
00112
VOID
00113
RtlpDumpRangeList(
00114 LONG Level,
00115 PRTL_RANGE_LIST RangeList
00116 );
00117
00118
#else
00119
00120 #define RtlpDumpRangeListEntry(Level, Entry, Indent)
00121 #define RtlpDumpRangeList(Level, RangeList)
00122
00123
#endif // DBG
00124
00125
00126
00127
00128
00129
#ifdef ALLOC_PRAGMA
00130
00131
#if defined(NTOS_KERNEL_RUNTIME)
00132
#pragma alloc_text(INIT, RtlInitializeRangeListPackage)
00133
#endif
00134
00135
#pragma alloc_text(PAGE, RtlpAddRange)
00136
#pragma alloc_text(PAGE, RtlpAddToMergedRange)
00137
#pragma alloc_text(PAGE, RtlpConvertToMergedRange)
00138
#pragma alloc_text(PAGE, RtlpCreateRangeListEntry)
00139
#pragma alloc_text(PAGE, RtlpAddIntersectingRanges)
00140
#pragma alloc_text(PAGE, RtlpDeleteFromMergedRange)
00141
#pragma alloc_text(PAGE, RtlpCopyRangeListEntry)
00142
#pragma alloc_text(PAGE, RtlpDeleteRangeListEntry)
00143
#pragma alloc_text(PAGE, RtlpIsRangeAvailable)
00144
00145
#if DBG
00146
#pragma alloc_text(PAGE, RtlpDumpRangeListEntry)
00147
#pragma alloc_text(PAGE, RtlpDumpRangeList)
00148
#endif
00149
00150
#pragma alloc_text(PAGE, RtlInitializeRangeList)
00151
#pragma alloc_text(PAGE, RtlAddRange)
00152
#pragma alloc_text(PAGE, RtlDeleteRange)
00153
#pragma alloc_text(PAGE, RtlDeleteOwnersRanges)
00154
#pragma alloc_text(PAGE, RtlCopyRangeList)
00155
#pragma alloc_text(PAGE, RtlFreeRangeList)
00156
#pragma alloc_text(PAGE, RtlIsRangeAvailable)
00157
#pragma alloc_text(PAGE, RtlFindRange)
00158
#pragma alloc_text(PAGE, RtlGetFirstRange)
00159
#pragma alloc_text(PAGE, RtlGetNextRange)
00160
#pragma alloc_text(PAGE, RtlMergeRangeLists)
00161
#pragma alloc_text(PAGE, RtlInvertRangeList)
00162
00163
#endif // ALLOC_PRAGMA
00164
00165
00166
00167
00168
00169
#if defined(NTOS_KERNEL_RUNTIME)
00170
00171
00172
00173
00174
00175
00176
#define RTLP_RANGE_LIST_ENTRY_LOOKASIDE_DEPTH 16
00177
00178
PAGED_LOOKASIDE_LIST RtlpRangeListEntryLookasideList;
00179
00180
VOID
00181 RtlInitializeRangeListPackage(
00182 VOID
00183 )
00184
00185
00186
00187
00188
00189
00190
00191
00192
00193
00194
00195
00196
00197
00198
00199
00200
00201 {
00202
ExInitializePagedLookasideList(
00203 &RtlpRangeListEntryLookasideList,
00204
NULL,
00205
NULL,
00206 0,
00207
sizeof(
RTLP_RANGE_LIST_ENTRY),
00208
RTL_RANGE_LIST_ENTRY_TAG,
00209 RTLP_RANGE_LIST_ENTRY_LOOKASIDE_DEPTH
00210 );
00211
00212 }
00213
00214
00215
00216
00217
00218
00219
00220
#define RtlpAllocateRangeListEntry() \
00221
(PRTLP_RANGE_LIST_ENTRY) ExAllocateFromPagedLookasideList( \
00222
&RtlpRangeListEntryLookasideList \
00223
)
00224
00225
00226
00227
00228
00229
00230
00231
#define RtlpFreeRangeListEntry(Entry) \
00232
ExFreeToPagedLookasideList(&RtlpRangeListEntryLookasideList, (Entry))
00233
00234
00235
00236
00237
00238
00239
00240
00241
#define RtlpRangeListAllocatePool(Size) \
00242
ExAllocatePoolWithTag(PagedPool, (Size), RTL_RANGE_LIST_MISC_TAG)
00243
00244
00245
00246
00247
00248
00249
00250
#define RtlpRangeListFreePool(Free) \
00251
ExFreePool(Free)
00252
00253
00254
#else // defined(NTOS_KERNEL_RUNTIME)
00255
00256
00257
00258
00259
00260
00261
00262
00263
00264
00265
00266
00267 #define RtlpAllocateRangeListEntry() \
00268
(PRTLP_RANGE_LIST_ENTRY) RtlAllocateHeap( \
00269
RtlProcessHeap(), \
00270
RTL_RANGE_LIST_ENTRY_TAG, \
00271
sizeof(RTLP_RANGE_LIST_ENTRY) \
00272
)
00273
00274
00275
00276
00277
00278
00279
00280 #define RtlpFreeRangeListEntry(Entry) \
00281
RtlFreeHeap( RtlProcessHeap(), 0, (Entry) )
00282
00283
00284
00285
00286
00287
00288
00289 #define RtlpRangeListAllocatePool(Size) \
00290
RtlAllocateHeap(RtlProcessHeap(), RTL_RANGE_LIST_MISC_TAG, (Size))
00291
00292
00293
00294
00295
00296
00297
00298 #define RtlpRangeListFreePool(Free) \
00299
RtlFreeHeap( RtlProcessHeap(), 0, (Free) )
00300
00301
00302
#endif // defined(NTOS_KERNEL_RUNTIME)
00303
00304
VOID
00305 RtlInitializeRangeList(
00306 IN OUT PRTL_RANGE_LIST RangeList
00307 )
00308
00309
00310
00311
00312
00313
00314
00315
00316
00317
00318
00319
00320
00321
00322
00323
00324
00325
00326 {
00327
RTL_PAGED_CODE();
00328
00329
ASSERT(RangeList);
00330
00331
DEBUG_PRINT(1, (
"RtlInitializeRangeList(0x%08x)\n", RangeList));
00332
00333 InitializeListHead(&RangeList->ListHead);
00334 RangeList->Flags = 0;
00335 RangeList->Count = 0;
00336 RangeList->Stamp = 0;
00337 }
00338
00339
NTSTATUS
00340 RtlAddRange(
00341 IN OUT PRTL_RANGE_LIST RangeList,
00342 IN ULONGLONG Start,
00343 IN ULONGLONG End,
00344 IN UCHAR Attributes,
00345 IN ULONG Flags,
00346 IN PVOID UserData, OPTIONAL
00347 IN PVOID Owner OPTIONAL
00348 )
00349
00350
00351
00352
00353
00354
00355
00356
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 {
00394
00395
NTSTATUS status;
00396
PRTLP_RANGE_LIST_ENTRY newEntry =
NULL;
00397
00398
RTL_PAGED_CODE();
00399
00400
DEBUG_PRINT(1,
00401 (
"RtlAddRange(0x%08x, 0x%I64x, 0x%I64x, 0x%08x, 0x%08x, 0x%08x)\n",
00402 RangeList,
00403
Start,
00404
End,
00405 Flags,
00406 UserData,
00407
Owner
00408 ));
00409
00410
00411
00412
00413
00414
if (
End <
Start) {
00415
return STATUS_INVALID_PARAMETER;
00416 }
00417
00418
00419
00420
00421
00422
if (!(newEntry =
RtlpCreateRangeListEntry(
Start,
End, Attributes, UserData,
Owner))) {
00423
return STATUS_INSUFFICIENT_RESOURCES;
00424 }
00425
00426
00427
00428
00429
00430
if (Flags & RTL_RANGE_LIST_ADD_SHARED) {
00431 newEntry->
PublicFlags |= RTL_RANGE_SHARED;
00432 }
00433
00434 status =
RtlpAddRange(&RangeList->ListHead,
00435 newEntry,
00436 Flags
00437 );
00438
00439
if (
NT_SUCCESS(status)) {
00440
00441
00442
00443
00444 RangeList->Count++;
00445 RangeList->Stamp++;
00446
00447 }
else {
00448
00449
00450
00451
00452
00453
RtlpFreeRangeListEntry(newEntry);
00454 }
00455
00456
return status;
00457
00458 }
00459
00460
NTSTATUS
00461 RtlpAddRange(
00462 IN OUT PLIST_ENTRY ListHead,
00463 IN
PRTLP_RANGE_LIST_ENTRY Entry,
00464 IN ULONG AddRangeFlags
00465 )
00466
00467
00468
00469
00470
00471
00472
00473
00474
00475
00476
00477
00478
00479
00480
00481
00482
00483
00484
00485
00486
00487
00488
00489
00490 {
00491
NTSTATUS status = STATUS_SUCCESS;
00492
PRTLP_RANGE_LIST_ENTRY previous, current;
00493 ULONGLONG start, end;
00494
00495
DEBUG_PRINT(2,
00496 (
"RtlpAddRange(0x%08x, 0x%08x{0x%I64x-0x%I64x}, 0x%08x)\n",
00497 ListHead,
00498 Entry,
00499 Entry->Start,
00500 Entry->End,
00501 AddRangeFlags
00502 ));
00503
00504
RTL_PAGED_CODE();
00505
ASSERT(Entry);
00506
00507 start = Entry->Start;
00508 end = Entry->End;
00509
00510
00511
00512
00513
00514 Entry->PublicFlags &= ~RTL_RANGE_CONFLICT;
00515
00516
00517
00518
00519
00520
FOR_ALL_IN_LIST(
RTLP_RANGE_LIST_ENTRY, ListHead, current) {
00521
00522
if (end < current->
Start) {
00523
00524
00525
00526
00527
00528
DEBUG_PRINT(2, (
"Completely before\n"));
00529
00530
InsertEntryList(current->
ListEntry.Blink,
00531 &Entry->ListEntry
00532 );
00533
00534
goto exit;
00535
00536 }
else if (
RANGE_INTERSECT(Entry, current)) {
00537
00538 status =
RtlpAddIntersectingRanges(ListHead,
00539 current,
00540 Entry,
00541 AddRangeFlags);
00542
00543
goto exit;
00544
00545 }
00546 }
00547
00548
00549
00550
00551
00552
DEBUG_PRINT(2, (
"After all existing ranges\n"));
00553
00554 InsertTailList(ListHead,
00555 &Entry->ListEntry
00556 );
00557
00558
exit:
00559
00560
return status;
00561
00562 }
00563
00564
NTSTATUS
00565 RtlpAddToMergedRange(
00566 IN
PRTLP_RANGE_LIST_ENTRY Merged,
00567 IN
PRTLP_RANGE_LIST_ENTRY Entry,
00568 IN ULONG AddRangeFlags
00569 )
00570
00571
00572
00573
00574
00575
00576
00577
00578
00579
00580
00581
00582
00583
00584
00585
00586
00587
00588
00589
00590
00591
00592
00593 {
00594
PRTLP_RANGE_LIST_ENTRY current;
00595 PLIST_ENTRY insert =
NULL;
00596 BOOLEAN entryShared;
00597
00598
RTL_PAGED_CODE();
00599
ASSERT(Merged);
00600
ASSERT(Entry);
00601
ASSERT(
MERGED(Merged));
00602
00603 entryShared =
SHARED(Entry);
00604
00605
00606
00607
00608
00609
FOR_ALL_IN_LIST(
RTLP_RANGE_LIST_ENTRY, &Merged->Merged.ListHead, current) {
00610
00611
00612
00613
00614
00615
if (
RANGE_INTERSECT(current, Entry)
00616 && !(entryShared &&
SHARED(current))) {
00617
00618
00619
00620
00621
00622
if (AddRangeFlags & RTL_RANGE_LIST_ADD_IF_CONFLICT) {
00623
00624
00625
00626
00627
00628 current->
PublicFlags |= RTL_RANGE_CONFLICT;
00629 Entry->PublicFlags |= RTL_RANGE_CONFLICT;
00630
00631 }
else {
00632
00633
00634
00635
00636
00637
return STATUS_RANGE_LIST_CONFLICT;
00638
00639 }
00640 }
00641
00642
00643
00644
00645
00646
if (!insert && current->
Start > Entry->Start) {
00647
00648
00649
00650
00651
00652 insert = current->
ListEntry.Blink;
00653 }
00654 }
00655
00656
00657
00658
00659
00660
if (!insert) {
00661
00662
00663
00664
00665
00666 InsertTailList(&Merged->Merged.ListHead,
00667 &Entry->ListEntry
00668 );
00669
00670 }
else {
00671
00672
00673
00674
00675
00676
InsertEntryList(insert,
00677 &Entry->ListEntry
00678 );
00679 }
00680
00681
00682
00683
00684
00685
00686
if (Entry->Start < Merged->Start) {
00687 Merged->Start = Entry->Start;
00688 }
00689
00690
if (Entry->End > Merged->End) {
00691 Merged->End = Entry->End;
00692 }
00693
00694
00695
00696
00697
00698
00699
if (
SHARED(Merged) && !entryShared) {
00700
00701
DEBUG_PRINT(2,
00702 (
"RtlpAddToMergedRange: Merged range no longer completely shared\n"));
00703
00704 Merged->PublicFlags &= ~RTL_RANGE_SHARED;
00705 }
00706
00707
return STATUS_SUCCESS;
00708 }
00709
00710
NTSTATUS
00711 RtlpConvertToMergedRange(
00712 IN
PRTLP_RANGE_LIST_ENTRY Entry
00713 )
00714
00715
00716
00717
00718
00719
00720
00721
00722
00723
00724
00725
00726
00727
00728
00729
00730
00731
00732 {
00733
PRTLP_RANGE_LIST_ENTRY newEntry;
00734
00735
RTL_PAGED_CODE();
00736
ASSERT(Entry);
00737
ASSERT(!
MERGED(Entry));
00738
ASSERT(!
CONFLICT(Entry));
00739
00740
00741
00742
00743
00744
if (!(newEntry =
RtlpCopyRangeListEntry(Entry))) {
00745
return STATUS_INSUFFICIENT_RESOURCES;
00746 }
00747
00748
00749
00750
00751
00752
00753 InitializeListHead(&Entry->Merged.ListHead);
00754 Entry->PrivateFlags =
RTLP_RANGE_LIST_ENTRY_MERGED;
00755
00756
ASSERT(Entry->PublicFlags == RTL_RANGE_SHARED || Entry->PublicFlags == 0);
00757
00758
00759
00760
00761
00762 InsertHeadList(&Entry->Merged.ListHead,
00763 &newEntry->
ListEntry
00764 );
00765
00766
00767
return STATUS_SUCCESS;
00768 }
00769
00770
PRTLP_RANGE_LIST_ENTRY
00771 RtlpCreateRangeListEntry(
00772 IN ULONGLONG Start,
00773 IN ULONGLONG End,
00774 IN UCHAR Attributes,
00775 IN PVOID UserData,
00776 IN PVOID Owner
00777 )
00778
00779
00780
00781
00782
00783
00784
00785
00786
00787
00788
00789
00790
00791
00792
00793
00794
00795
00796
00797
00798
00799
00800
00801
00802
00803
00804
00805
00806
00807
00808 {
00809
PRTLP_RANGE_LIST_ENTRY entry;
00810
00811
RTL_PAGED_CODE();
00812
ASSERT(
Start <=
End);
00813
00814
00815
00816
00817
00818
if (entry =
RtlpAllocateRangeListEntry()) {
00819
00820
00821
00822
00823
00824
#if DBG
00825
entry->
ListEntry.Flink =
NULL;
00826 entry->
ListEntry.Blink =
NULL;
00827
#endif
00828
00829 entry->
PublicFlags = 0;
00830 entry->
PrivateFlags = 0;
00831 entry->
Start =
Start;
00832 entry->
End =
End;
00833 entry->
Allocated.UserData = UserData;
00834 entry->
Allocated.Owner =
Owner;
00835 entry->
Attributes = Attributes;
00836 }
00837
00838
return entry;
00839
00840 }
00841
00842
NTSTATUS
00843 RtlpAddIntersectingRanges(
00844 IN PLIST_ENTRY ListHead,
00845 IN
PRTLP_RANGE_LIST_ENTRY First,
00846 IN
PRTLP_RANGE_LIST_ENTRY Entry,
00847 IN ULONG AddRangeFlags
00848 )
00849
00850
00851
00852
00853
00854
00855
00856
00857
00858
00859
00860
00861
00862
00863
00864
00865
00866
00867
00868
00869
00870
00871
00872
00873
00874
00875 {
00876
NTSTATUS status;
00877
PRTLP_RANGE_LIST_ENTRY current, next, currentMerged, nextMerged;
00878 BOOLEAN entryShared;
00879
00880
RTL_PAGED_CODE();
00881
ASSERT(First);
00882
ASSERT(Entry);
00883
00884 entryShared =
SHARED(Entry);
00885
00886
00887
00888
00889
00890
if (!(AddRangeFlags & RTL_RANGE_LIST_ADD_IF_CONFLICT)) {
00891
00892
00893
00894
00895
00896 current = First;
00897
FOR_REST_IN_LIST(
RTLP_RANGE_LIST_ENTRY, ListHead, current) {
00898
00899
if (Entry->End < current->
Start) {
00900
00901
00902
00903
00904
00905
00906
break;
00907
00908 }
else if (
MERGED(current)) {
00909
00910
00911
00912
00913
00914
FOR_ALL_IN_LIST(
RTLP_RANGE_LIST_ENTRY,
00915 ¤t->
Merged.ListHead,
00916 currentMerged) {
00917
00918
00919
00920
00921
00922
if (
RANGE_INTERSECT(currentMerged, Entry)
00923 && !(entryShared &&
SHARED(currentMerged))) {
00924
00925
00926
00927
00928
00929
return STATUS_RANGE_LIST_CONFLICT;
00930
00931 }
00932 }
00933
00934 }
else if (!(entryShared &&
SHARED(current))) {
00935
00936
00937
00938
00939
00940
return STATUS_RANGE_LIST_CONFLICT;
00941 }
00942 }
00943 }
00944
00945
00946
00947
00948
00949
00950
00951
00952
if (!
MERGED(First)) {
00953
00954 status =
RtlpConvertToMergedRange(First);
00955
00956
if (!
NT_SUCCESS(status)) {
00957
goto cleanup;
00958 }
00959
00960 }
00961
00962
ASSERT(
MERGED(First));
00963
00964 current =
RANGE_LIST_ENTRY_FROM_LIST_ENTRY(First->ListEntry.Flink);
00965
00966
00967
00968
00969
00970
00971
FOR_REST_IN_LIST_SAFE(
RTLP_RANGE_LIST_ENTRY, ListHead, current, next) {
00972
00973
if (Entry->End < current->
Start) {
00974
00975
00976
00977
00978
00979
break;
00980 }
00981
00982
if (
MERGED(current)) {
00983
00984
00985
00986
00987
00988
FOR_ALL_IN_LIST_SAFE(
RTLP_RANGE_LIST_ENTRY,
00989 ¤t->
Merged.ListHead,
00990 currentMerged,
00991 nextMerged) {
00992
00993
00994
00995
00996
00997 RemoveEntryList(¤tMerged->
ListEntry);
00998
00999
01000
01001
01002
01003 status =
RtlpAddToMergedRange(First,
01004 currentMerged,
01005 AddRangeFlags
01006 );
01007
01008
01009
01010
01011
01012
01013
ASSERT(
NT_SUCCESS(status));
01014
01015 }
01016
01017
01018
01019
01020
01021
ASSERT(IsListEmpty(¤t->
Merged.ListHead));
01022
01023 RemoveEntryList(¤t->
ListEntry);
01024
RtlpFreeRangeListEntry(current);
01025
01026 }
else {
01027
01028
01029
01030
01031
01032 RemoveEntryList(¤t->
ListEntry);
01033
01034
01035
01036
01037
01038 status =
RtlpAddToMergedRange(First,
01039 current,
01040 AddRangeFlags
01041 );
01042
01043
01044
01045
01046
01047
01048
ASSERT(
NT_SUCCESS(status));
01049
01050 }
01051 }
01052
01053
01054
01055
01056
01057 status =
RtlpAddToMergedRange(First,
01058 Entry,
01059 AddRangeFlags
01060 );
01061
01062
ASSERT(
NT_SUCCESS(status));
01063
01064 cleanup:
01065
01066
return status;
01067
01068 }
01069
01070
NTSTATUS
01071 RtlDeleteRange(
01072 IN OUT PRTL_RANGE_LIST RangeList,
01073 IN ULONGLONG Start,
01074 IN ULONGLONG End,
01075 IN PVOID Owner
01076 )
01077
01078
01079
01080
01081
01082
01083
01084
01085
01086
01087
01088
01089
01090
01091
01092
01093
01094
01095
01096
01097
01098
01099
01100 {
01101
NTSTATUS status = STATUS_RANGE_NOT_FOUND;
01102
PRTLP_RANGE_LIST_ENTRY current, next, currentMerged, nextMerged;
01103
01104
RTL_PAGED_CODE();
01105
ASSERT(RangeList);
01106
01107
DEBUG_PRINT(1,
01108 (
"RtlDeleteRange(0x%08x, 0x%I64x, 0x%I64x, 0x%08x)\n",
01109 RangeList,
01110
Start,
01111
End,
01112
Owner
01113 ));
01114
01115
01116
FOR_ALL_IN_LIST_SAFE(
RTLP_RANGE_LIST_ENTRY,
01117 &RangeList->ListHead,
01118 current,
01119 next) {
01120
01121
01122
01123
01124
01125
if (
End < current->
Start) {
01126
01127
01128
01129
01130
01131
break;
01132 }
01133
01134
if (
MERGED(current)) {
01135
01136
01137
01138
01139
01140
if (
Start >= current->
Start &&
End <= current->
End) {
01141
01142
FOR_ALL_IN_LIST_SAFE(
RTLP_RANGE_LIST_ENTRY,
01143 ¤t->
Merged.ListHead,
01144 currentMerged,
01145 nextMerged) {
01146
01147
if (currentMerged->
Start ==
Start
01148 && currentMerged->
End ==
End
01149 && currentMerged->
Allocated.Owner ==
Owner) {
01150
01151
01152
01153
01154
01155
01156 status =
RtlpDeleteFromMergedRange(currentMerged,
01157 current
01158 );
01159
goto exit;
01160 }
01161
01162 }
01163 }
01164
01165 }
else if (current->
Start ==
Start
01166 && current->
End ==
End
01167 && current->
Allocated.Owner ==
Owner) {
01168
01169
01170
01171
01172
01173 RemoveEntryList(¤t->
ListEntry);
01174
RtlpFreeRangeListEntry(current);
01175 status = STATUS_SUCCESS;
01176
goto exit;
01177 }
01178 }
01179
01180
exit:
01181
01182
if (
NT_SUCCESS(status)) {
01183
01184
01185
01186
01187
01188 RangeList->Count--;
01189 RangeList->Stamp++;
01190
01191 }
01192
01193
return status;
01194 }
01195
01196
NTSTATUS
01197 RtlDeleteOwnersRanges(
01198 IN OUT PRTL_RANGE_LIST RangeList,
01199 IN PVOID Owner
01200 )
01201
01202
01203
01204
01205
01206
01207
01208
01209
01210
01211
01212
01213
01214
01215
01216
01217
01218
01219 {
01220
NTSTATUS status = STATUS_SUCCESS;
01221
PRTLP_RANGE_LIST_ENTRY current, next, currentMerged, nextMerged;
01222
01223
RTL_PAGED_CODE();
01224
ASSERT(RangeList);
01225
01226
DEBUG_PRINT(1,
01227 (
"RtlDeleteOwnersRanges(0x%08x, 0x%08x)\n",
01228 RangeList,
01229
Owner
01230 ));
01231
01232 findNext:
01233
01234
FOR_ALL_IN_LIST_SAFE(
RTLP_RANGE_LIST_ENTRY,
01235 &RangeList->ListHead,
01236 current,
01237 next) {
01238
01239
if (
MERGED(current)) {
01240
01241
FOR_ALL_IN_LIST_SAFE(
RTLP_RANGE_LIST_ENTRY,
01242 ¤t->
Merged.ListHead,
01243 currentMerged,
01244 nextMerged) {
01245
01246
if (currentMerged->
Allocated.Owner ==
Owner) {
01247
01248
01249
01250
01251
01252
01253
DEBUG_PRINT(2,
01254 (
"RtlDeleteOwnersRanges: Deleting merged range \
01255
(Start=%I64x, End=%I64x)\n",
01256 currentMerged->
Start,
01257 currentMerged->
End
01258 ));
01259
01260 status =
RtlpDeleteFromMergedRange(currentMerged,
01261 current
01262 );
01263
if (!
NT_SUCCESS(status)) {
01264
goto cleanup;
01265 }
01266
01267 RangeList->Count--;
01268 RangeList->Stamp++;
01269
01270
01271
01272
01273
01274
01275
01276
goto findNext;
01277
01278 }
01279 }
01280
01281 }
else if (current->
Allocated.Owner ==
Owner) {
01282
01283
01284
01285
01286
01287 RemoveEntryList(¤t->
ListEntry);
01288
RtlpFreeRangeListEntry(current);
01289
01290
DEBUG_PRINT(2,
01291 (
"RtlDeleteOwnersRanges: Deleting range (Start=%I64x,End=%I64x)\n",
01292 current->
Start,
01293 current->
End
01294 ));
01295
01296 RangeList->Count--;
01297 RangeList->Stamp++;
01298
01299 status = STATUS_SUCCESS;
01300
01301 }
01302 }
01303
01304 cleanup:
01305
01306
return status;
01307
01308 }
01309
01310
NTSTATUS
01311 RtlpDeleteFromMergedRange(
01312 IN
PRTLP_RANGE_LIST_ENTRY Delete,
01313 IN
PRTLP_RANGE_LIST_ENTRY Merged
01314 )
01315
01316
01317
01318
01319
01320
01321
01322
01323
01324
01325
01326
01327
01328
01329
01330
01331
01332
01333
01334
01335
01336
01337
01338
01339
01340
01341 {
01342
NTSTATUS status = STATUS_SUCCESS;
01343
PRTLP_RANGE_LIST_ENTRY current, next;
01344 LIST_ENTRY keepList;
01345 PLIST_ENTRY previousInsert, nextInsert;
01346
01347
RTL_PAGED_CODE();
01348
ASSERT(
MERGED(Merged));
01349
01350
01351
01352
01353
01354 RemoveEntryList(&
Delete->ListEntry);
01355
01356
01357
01358
01359
01360 InitializeListHead(&keepList);
01361
01362
01363
01364
01365
01366
01367
FOR_ALL_IN_LIST_SAFE(
RTLP_RANGE_LIST_ENTRY,
01368 &Merged->Merged.ListHead,
01369 current,
01370 next) {
01371
01372
01373
01374
01375
01376
01377 RemoveEntryList(¤t->
ListEntry);
01378
01379
01380
01381
01382
01383
01384 current->
PublicFlags &= ~RTL_RANGE_CONFLICT;
01385
01386 status =
RtlpAddRange(&keepList,
01387 current,
01388 RTL_RANGE_LIST_ADD_IF_CONFLICT
01389 );
01390
01391
if (!
NT_SUCCESS(status)) {
01392
01393
01394
01395
goto cleanup;
01396 }
01397 }
01398
01399
if (!IsListEmpty(&keepList)) {
01400
01401
01402
01403
01404
01405
01406 previousInsert = Merged->ListEntry.Blink;
01407 nextInsert = Merged->ListEntry.Flink;
01408
01409 previousInsert->Flink = keepList.Flink;
01410 keepList.Flink->Blink = previousInsert;
01411
01412 nextInsert->Blink = keepList.Blink;
01413 keepList.Blink->Flink = nextInsert;
01414
01415 }
else {
01416
01417 RemoveEntryList(&Merged->ListEntry);
01418
01419 }
01420
01421
01422
01423
01424
01425
RtlpFreeRangeListEntry(
Delete);
01426
RtlpFreeRangeListEntry(Merged);
01427
01428
return status;
01429
01430 cleanup:
01431
01432
01433
01434
01435
01436
01437
01438
ASSERT(status == STATUS_INSUFFICIENT_RESOURCES);
01439
01440
01441
01442
01443
01444
FOR_ALL_IN_LIST_SAFE(
RTLP_RANGE_LIST_ENTRY, &keepList, current, next) {
01445
01446 status =
RtlpAddToMergedRange(Merged,
01447 current,
01448 RTL_RANGE_LIST_ADD_IF_CONFLICT
01449 );
01450
01451
ASSERT(
NT_SUCCESS(status));
01452 }
01453
01454
01455
01456
01457
01458 status =
RtlpAddToMergedRange(Merged,
01459
Delete,
01460 RTL_RANGE_LIST_ADD_IF_CONFLICT
01461 );
01462
01463
return status;
01464 }
01465
01466
PRTLP_RANGE_LIST_ENTRY
01467 RtlpCopyRangeListEntry(
01468
PRTLP_RANGE_LIST_ENTRY Entry
01469 )
01470
01471
01472
01473
01474
01475
01476
01477
01478
01479
01480
01481
01482
01483
01484
01485
01486
01487 {
01488
PRTLP_RANGE_LIST_ENTRY newEntry;
01489
01490
RTL_PAGED_CODE();
01491
ASSERT(Entry);
01492
01493
if (newEntry =
RtlpAllocateRangeListEntry()) {
01494
01495 RtlCopyMemory(newEntry, Entry,
sizeof(
RTLP_RANGE_LIST_ENTRY));
01496
01497
#if DBG
01498
newEntry->
ListEntry.Flink =
NULL;
01499 newEntry->
ListEntry.Blink =
NULL;
01500
#endif
01501
01502
if (
MERGED(Entry)) {
01503
01504
01505
01506
01507
01508
PRTLP_RANGE_LIST_ENTRY current, newMerged;
01509
01510 InitializeListHead(&newEntry->
Merged.ListHead);
01511
01512
FOR_ALL_IN_LIST(
RTLP_RANGE_LIST_ENTRY,
01513 &Entry->
Merged.ListHead,
01514 current) {
01515
01516
01517
01518
01519
01520 newMerged =
RtlpAllocateRangeListEntry();
01521
01522
if (!newMerged) {
01523
goto cleanup;
01524 }
01525
01526 RtlCopyMemory(newMerged, current,
sizeof(
RTLP_RANGE_LIST_ENTRY));
01527
01528
01529
01530
01531
01532 InsertTailList(&newEntry->
Merged.ListHead, &newMerged->
ListEntry);
01533 }
01534 }
01535 }
01536
01537
return newEntry;
01538
01539 cleanup:
01540
01541
01542
01543
01544
01545
RtlpDeleteRangeListEntry(newEntry);
01546
01547
return NULL;
01548
01549 }
01550
01551
NTSTATUS
01552 RtlCopyRangeList(
01553 OUT PRTL_RANGE_LIST CopyRangeList,
01554 IN PRTL_RANGE_LIST RangeList
01555 )
01556
01557
01558
01559
01560
01561
01562
01563
01564
01565
01566
01567
01568
01569
01570
01571
01572
01573
01574
01575
01576
01577 {
01578
01579
NTSTATUS status = STATUS_SUCCESS;
01580
PRTLP_RANGE_LIST_ENTRY current, newEntry, currentMerged, newMerged;
01581
01582
RTL_PAGED_CODE();
01583
ASSERT(RangeList);
01584
ASSERT(CopyRangeList);
01585
01586
01587
DEBUG_PRINT(1,
01588 (
"RtlCopyRangeList(0x%08x, 0x%08x)\n",
01589 CopyRangeList,
01590 RangeList
01591 ));
01592
01593
01594
01595
01596
01597
if (CopyRangeList->Count != 0) {
01598
return STATUS_INVALID_PARAMETER;
01599 }
01600
01601
01602
01603
01604
01605 CopyRangeList->Flags = RangeList->Flags;
01606 CopyRangeList->Count = RangeList->Count;
01607 CopyRangeList->Stamp = RangeList->Stamp;
01608
01609
01610
01611
01612
01613
FOR_ALL_IN_LIST(
RTLP_RANGE_LIST_ENTRY, &RangeList->ListHead, current) {
01614
01615
01616
01617
01618
01619 newEntry =
RtlpCopyRangeListEntry(current);
01620
01621
if (!newEntry) {
01622 status = STATUS_INSUFFICIENT_RESOURCES;
01623
goto cleanup;
01624 }
01625
01626
01627
01628
01629
01630 InsertTailList(&CopyRangeList->ListHead, &newEntry->
ListEntry);
01631 }
01632
01633
return status;
01634
01635 cleanup:
01636
01637
01638
01639
01640
01641
RtlFreeRangeList(CopyRangeList);
01642
return status;
01643
01644 }
01645
01646
VOID
01647 RtlpDeleteRangeListEntry(
01648 IN
PRTLP_RANGE_LIST_ENTRY Entry
01649 )
01650
01651
01652
01653
01654
01655
01656
01657
01658
01659
01660
01661
01662
01663
01664
01665
01666
01667
01668
01669 {
01670
RTL_PAGED_CODE();
01671
01672
if (
MERGED(Entry)) {
01673
01674
PRTLP_RANGE_LIST_ENTRY current, next;
01675
01676
01677
01678
01679
01680
FOR_ALL_IN_LIST_SAFE(
RTLP_RANGE_LIST_ENTRY,
01681 &Entry->Merged.ListHead,
01682 current,
01683 next) {
01684
01685
RtlpFreeRangeListEntry(current);
01686 }
01687 }
01688
01689
RtlpFreeRangeListEntry(Entry);
01690 }
01691
01692
VOID
01693 RtlFreeRangeList(
01694 IN PRTL_RANGE_LIST RangeList
01695 )
01696
01697
01698
01699
01700
01701
01702
01703
01704
01705
01706
01707
01708
01709
01710
01711 {
01712
01713
PRTLP_RANGE_LIST_ENTRY current, next;
01714
01715
01716
01717
01718
01719
RTL_PAGED_CODE();
01720
ASSERT(RangeList);
01721
01722
01723
01724
01725
01726 RangeList->Flags = 0;
01727 RangeList->Count = 0;
01728
01729
FOR_ALL_IN_LIST_SAFE(
RTLP_RANGE_LIST_ENTRY,
01730 &RangeList->ListHead,
01731 current,
01732 next) {
01733
01734
01735
01736
01737
01738 RemoveEntryList(¤t->
ListEntry);
01739
RtlpDeleteRangeListEntry(current);
01740 }
01741 }
01742
01743
NTSTATUS
01744 RtlIsRangeAvailable(
01745 IN PRTL_RANGE_LIST RangeList,
01746 IN ULONGLONG Start,
01747 IN ULONGLONG End,
01748 IN ULONG Flags,
01749 IN UCHAR AttributeAvailableMask,
01750 IN PVOID Context OPTIONAL,
01751 IN PRTL_CONFLICT_RANGE_CALLBACK Callback OPTIONAL,
01752 OUT PBOOLEAN Available
01753 )
01754
01755
01756
01757
01758
01759
01760
01761
01762
01763
01764
01765
01766
01767
01768
01769
01770
01771
01772
01773
01774
01775
01776
01777
01778
01779
01780
01781
01782
01783
01784 {
01785
NTSTATUS status;
01786 RTL_RANGE_LIST_ITERATOR iterator;
01787 PRTL_RANGE
dummy;
01788
01789
RTL_PAGED_CODE();
01790
01791
ASSERT(RangeList);
01792
ASSERT(Available);
01793
01794
DEBUG_PRINT(1,
01795 (
"RtlIsRangeAvailable(0x%08x, 0x%I64x, 0x%I64x, 0x%08x, 0x%08x)\n",
01796 RangeList,
01797
Start,
01798
End,
01799 Flags,
01800 Available
01801 ));
01802
01803
01804
01805
01806 status =
RtlGetFirstRange(RangeList, &iterator, &
dummy);
01807
01808
01809
if (status == STATUS_NO_MORE_ENTRIES) {
01810
01811
01812
01813
01814 *Available =
TRUE;
01815
return STATUS_SUCCESS;
01816
01817 }
else if (!
NT_SUCCESS(status)) {
01818
01819
return status;
01820
01821 }
01822
01823 *Available =
RtlpIsRangeAvailable(&iterator,
01824
Start,
01825
End,
01826 AttributeAvailableMask,
01827 (BOOLEAN)(Flags & RTL_RANGE_LIST_SHARED_OK),
01828 (BOOLEAN)(Flags & RTL_RANGE_LIST_NULL_CONFLICT_OK),
01829
TRUE,
01830 Context,
01831 Callback
01832 );
01833
01834
return STATUS_SUCCESS;
01835
01836 }
01837
01838 BOOLEAN
01839 RtlpIsRangeAvailable(
01840 IN PRTL_RANGE_LIST_ITERATOR Iterator,
01841 IN ULONGLONG Start,
01842 IN ULONGLONG End,
01843 IN UCHAR AttributeAvailableMask,
01844 IN BOOLEAN SharedOK,
01845 IN BOOLEAN NullConflictOK,
01846 IN BOOLEAN Forward,
01847 IN PVOID Context OPTIONAL,
01848 IN PRTL_CONFLICT_RANGE_CALLBACK Callback OPTIONAL
01849 )
01850
01851
01852
01853
01854
01855
01856
01857
01858
01859
01860
01861
01862
01863
01864
01865
01866
01867
01868
01869
01870
01871
01872
01873
01874
01875 {
01876 PRTL_RANGE current;
01877
01878
RTL_PAGED_CODE();
01879
01880
ASSERT(Iterator);
01881
01882
FOR_REST_OF_RANGES(Iterator, current, Forward) {
01883
01884
01885
01886
01887
01888
01889
if (Forward) {
01890
if (!Iterator->MergedHead &&
End < current->Start) {
01891
break;
01892 }
01893 }
else {
01894
if (!Iterator->MergedHead &&
Start > current->End) {
01895
break;
01896 }
01897 }
01898
01899
01900
01901
01902
if (
RANGE_LIMITS_INTERSECT(
Start,
End, current->Start, current->End)) {
01903
01904
DEBUG_PRINT(2,
01905 (
"Intersection 0x%I64x-0x%I64x and 0x%I64x-0x%I64x\n",
01906
Start,
01907
End,
01908 current->Start,
01909 current->End
01910 ));
01911
01912
01913
01914
01915
01916
01917
01918
if (!((SharedOK && (current->Flags & RTL_RANGE_SHARED))
01919 || (current->Attributes & AttributeAvailableMask)
01920 || (NullConflictOK && (current->Owner ==
NULL))
01921 )
01922 ) {
01923
01924
01925
01926
01927
01928
01929
if (ARGUMENT_PRESENT(Callback)) {
01930
if ((*Callback)(Context, (PRTL_RANGE)current)) {
01931
01932
DEBUG_PRINT(2,
01933 (
"User provided callback overrode conflict\n",
01934
Start,
01935
End,
01936 current->Start,
01937 current->End
01938 ));
01939
01940
continue;
01941 }
01942 }
01943
01944
return FALSE;
01945 }
01946 }
01947 }
01948
01949
01950
return TRUE;
01951 }
01952
01953
NTSTATUS
01954 RtlFindRange(
01955 IN PRTL_RANGE_LIST RangeList,
01956 IN ULONGLONG Minimum,
01957 IN ULONGLONG Maximum,
01958 IN ULONG Length,
01959 IN ULONG Alignment,
01960 IN ULONG Flags,
01961 IN UCHAR AttributeAvailableMask,
01962 IN PVOID Context OPTIONAL,
01963 IN PRTL_CONFLICT_RANGE_CALLBACK Callback OPTIONAL,
01964 OUT PULONGLONG Start
01965 )
01966
01967
01968
01969
01970
01971
01972
01973
01974
01975
01976
01977
01978
01979
01980
01981
01982
01983
01984
01985
01986
01987
01988
01989
01990
01991
01992
01993
01994
01995
01996
01997
01998
01999
02000
02001
02002
02003 {
02004
02005 ULONGLONG start, end;
02006 RTL_RANGE_LIST_ITERATOR iterator;
02007 PRTL_RANGE
dummy;
02008 BOOLEAN sharedOK, nullConflictOK;
02009
02010
RTL_PAGED_CODE();
02011
02012
ASSERT(RangeList);
02013
ASSERT(
Start);
02014
ASSERT(Alignment > 0);
02015
ASSERT(Length > 0);
02016
02017
DEBUG_PRINT(1,
02018 (
"RtlFindRange(0x%08x, 0x%I64x, 0x%I64x, 0x%08x, 0x%08x, 0x%08x, 0x%08x)\n",
02019 RangeList,
02020 Minimum,
02021 Maximum,
02022 Length,
02023 Alignment,
02024 Flags,
02025
Start
02026 ));
02027
02028
02029
02030
02031
02032 start = Maximum - (Length - 1);
02033 start -= start % Alignment;
02034
02035
02036
02037
02038
02039
if ((Minimum > Maximum)
02040 || (Maximum - Minimum < Length - 1)
02041 || (Minimum + Alignment < Minimum)
02042 || (start < Minimum)
02043 || (Length == 0)
02044 || (Alignment == 0)) {
02045
02046
return STATUS_INVALID_PARAMETER;
02047 }
02048
02049 sharedOK = (BOOLEAN) Flags & RTL_RANGE_LIST_SHARED_OK;
02050 nullConflictOK = (BOOLEAN) Flags & RTL_RANGE_LIST_NULL_CONFLICT_OK;
02051
02052
02053
02054
02055 end = start + Length - 1;
02056
02057
02058
02059
02060
02061
RtlGetLastRange(RangeList, &iterator, &
dummy);
02062
02063
02064
02065
02066
02067
02068
do {
02069
02070
DEBUG_PRINT(2,
02071 (
"RtlFindRange: Testing range %I64x-%I64x\n",
02072 start,
02073 end
02074 ));
02075
02076
if (
RtlpIsRangeAvailable(&iterator,
02077 start,
02078 end,
02079 AttributeAvailableMask,
02080 sharedOK,
02081 nullConflictOK,
02082
FALSE,
02083 Context,
02084 Callback)) {
02085
02086 *
Start = start;
02087
02088
02089
02090
02091
02092
02093
ASSERT(*
Start >= Minimum && *
Start + Length - 1 <= Maximum);
02094
02095
return STATUS_SUCCESS;
02096 }
02097
02098
02099
02100
02101
02102
02103
02104 start = ((
PRTLP_RANGE_LIST_ENTRY)(iterator.Current))->Start;
02105
if ((start - Length) > start) {
02106
02107
02108
02109
02110
02111
break;
02112 }
02113
02114 start -= Length;
02115 start -= start % Alignment;
02116 end = start + Length - 1;
02117
02118 }
while ( start >= Minimum );
02119
02120
return STATUS_UNSUCCESSFUL;
02121 }
02122
02123
NTSTATUS
02124 RtlGetFirstRange(
02125 IN PRTL_RANGE_LIST RangeList,
02126 OUT PRTL_RANGE_LIST_ITERATOR Iterator,
02127 OUT PRTL_RANGE *Range
02128 )
02129
02130
02131
02132
02133
02134
02135
02136
02137
02138
02139
02140
02141
02142
02143
02144
02145
02146
02147
02148
02149
02150
02151
02152 {
02153
NTSTATUS status = STATUS_SUCCESS;
02154
PRTLP_RANGE_LIST_ENTRY first;
02155
02156
RTL_PAGED_CODE();
02157
02158
02159
02160
02161
02162 Iterator->RangeListHead = &RangeList->ListHead;
02163 Iterator->Stamp = RangeList->Stamp;
02164
02165
if (!IsListEmpty(&RangeList->ListHead)) {
02166
02167 first =
RANGE_LIST_ENTRY_FROM_LIST_ENTRY(RangeList->ListHead.Flink);
02168
02169
02170
02171
02172
02173
02174
if (
MERGED(first)) {
02175
02176
ASSERT(!IsListEmpty(&first->
Merged.ListHead));
02177
02178 Iterator->MergedHead = &first->
Merged.ListHead;
02179 Iterator->Current =
RANGE_LIST_ENTRY_FROM_LIST_ENTRY(
02180 first->
Merged.ListHead.Flink
02181 );
02182
02183 }
else {
02184
02185 Iterator->MergedHead =
NULL;
02186 Iterator->Current = first;
02187 }
02188
02189 *Range = (PRTL_RANGE) Iterator->Current;
02190
02191 }
else {
02192
02193 Iterator->Current =
NULL;
02194 Iterator->MergedHead =
NULL;
02195
02196 *Range =
NULL;
02197
02198 status = STATUS_NO_MORE_ENTRIES;
02199 }
02200
02201
return status;
02202 }
02203
02204
NTSTATUS
02205 RtlGetLastRange(
02206 IN PRTL_RANGE_LIST RangeList,
02207 OUT PRTL_RANGE_LIST_ITERATOR Iterator,
02208 OUT PRTL_RANGE *Range
02209 )
02210
02211
02212
02213
02214
02215
02216
02217
02218
02219
02220
02221
02222
02223
02224
02225
02226
02227
02228
02229
02230
02231
02232
02233 {
02234
NTSTATUS status = STATUS_SUCCESS;
02235
PRTLP_RANGE_LIST_ENTRY first;
02236
02237
RTL_PAGED_CODE();
02238
02239
02240
02241
02242
02243 Iterator->RangeListHead = &RangeList->ListHead;
02244 Iterator->Stamp = RangeList->Stamp;
02245
02246
if (!IsListEmpty(&RangeList->ListHead)) {
02247
02248 first =
RANGE_LIST_ENTRY_FROM_LIST_ENTRY(RangeList->ListHead.Blink);
02249
02250
02251
02252
02253
02254
02255
if (
MERGED(first)) {
02256
02257
ASSERT(!IsListEmpty(&first->
Merged.ListHead));
02258
02259 Iterator->MergedHead = &first->
Merged.ListHead;
02260 Iterator->Current =
RANGE_LIST_ENTRY_FROM_LIST_ENTRY(
02261 first->
Merged.ListHead.Blink
02262 );
02263
02264 }
else {
02265
02266 Iterator->MergedHead =
NULL;
02267 Iterator->Current = first;
02268 }
02269
02270 *Range = (PRTL_RANGE) Iterator->Current;
02271
02272 }
else {
02273
02274 Iterator->Current =
NULL;
02275 Iterator->MergedHead =
NULL;
02276
02277 *Range =
NULL;
02278
02279 status = STATUS_NO_MORE_ENTRIES;
02280 }
02281
02282
return status;
02283 }
02284
02285
NTSTATUS
02286 RtlGetNextRange(
02287 IN OUT PRTL_RANGE_LIST_ITERATOR Iterator,
02288 OUT PRTL_RANGE *Range,
02289 IN BOOLEAN MoveForwards
02290 )
02291
02292
02293
02294
02295
02296
02297
02298
02299
02300
02301
02302
02303
02304
02305
02306
02307
02308
02309
02310
02311
02312
02313
02314
02315
02316
02317
02318
02319
02320 {
02321
PRTLP_RANGE_LIST_ENTRY mergedEntry, next;
02322 PLIST_ENTRY entry;
02323
02324
RTL_PAGED_CODE();
02325
02326
02327
02328
02329
02330
if (
RANGE_LIST_FROM_LIST_HEAD(Iterator->RangeListHead)->Stamp !=
02331 Iterator->Stamp) {
02332
02333
ASSERTMSG(
02334
"RtlGetNextRange: Add/Delete operations have been performed while \
02335
iterating through a list\n",
FALSE);
02336
02337
return STATUS_INVALID_PARAMETER;
02338 }
02339
02340
02341
02342
02343
02344
if (!Iterator->Current) {
02345 *Range =
NULL;
02346
return STATUS_NO_MORE_ENTRIES;
02347 }
02348
02349 entry = &((
PRTLP_RANGE_LIST_ENTRY)(Iterator->Current))->ListEntry;
02350 next =
RANGE_LIST_ENTRY_FROM_LIST_ENTRY(
02351 MoveForwards ? entry->Flink : entry->Blink);
02352
02353
ASSERT(next);
02354
02355
02356
02357
02358
if (Iterator->MergedHead) {
02359
02360
02361
02362
02363
if (&next->
ListEntry == Iterator->MergedHead) {
02364
02365
02366
02367
02368 mergedEntry = CONTAINING_RECORD(
02369 Iterator->MergedHead,
02370
RTLP_RANGE_LIST_ENTRY,
02371 Merged.ListHead
02372 );
02373
02374
02375
02376
02377
02378 next = MoveForwards ?
02379
RANGE_LIST_ENTRY_FROM_LIST_ENTRY(
02380 mergedEntry->
ListEntry.Flink
02381 )
02382 :
RANGE_LIST_ENTRY_FROM_LIST_ENTRY(
02383 mergedEntry->
ListEntry.Blink
02384 );
02385 Iterator->MergedHead =
NULL;
02386
02387 }
else {
02388
02389
02390
02391
02392 Iterator->Current = next;
02393 *Range = (PRTL_RANGE) next;
02394
02395
return STATUS_SUCCESS;
02396 }
02397 }
02398
02399
02400
02401
02402
if (&next->
ListEntry == Iterator->RangeListHead) {
02403
02404
02405
02406
02407 Iterator->Current =
NULL;
02408 *Range =
NULL;
02409
return STATUS_NO_MORE_ENTRIES;
02410
02411 }
else {
02412
02413
02414
02415
02416
02417
if (
MERGED(next)) {
02418
02419
02420
02421
02422
ASSERT(!Iterator->MergedHead);
02423
02424 Iterator->MergedHead = &next->
Merged.ListHead;
02425 Iterator->Current = MoveForwards ?
02426
RANGE_LIST_ENTRY_FROM_LIST_ENTRY(
02427 next->
Merged.ListHead.Flink
02428 )
02429 :
RANGE_LIST_ENTRY_FROM_LIST_ENTRY(
02430 next->
Merged.ListHead.Blink
02431 );
02432 }
else {
02433
02434
02435
02436
02437
02438 Iterator->Current =
RANGE_LIST_ENTRY_FROM_LIST_ENTRY(
02439 &next->
ListEntry
02440 );
02441 }
02442
02443 *Range = (PRTL_RANGE) Iterator->Current;
02444 }
02445
02446
return STATUS_SUCCESS;
02447 }
02448
02449
NTSTATUS
02450 RtlMergeRangeLists(
02451 OUT PRTL_RANGE_LIST MergedRangeList,
02452 IN PRTL_RANGE_LIST RangeList1,
02453 IN PRTL_RANGE_LIST RangeList2,
02454 IN ULONG Flags
02455 )
02456
02457
02458
02459
02460
02461
02462
02463
02464
02465
02466
02467
02468
02469
02470
02471
02472
02473
02474
02475
02476
02477
02478
02479
02480
02481
02482
02483 {
02484
NTSTATUS status;
02485
PRTLP_RANGE_LIST_ENTRY current, currentMerged, newEntry;
02486 ULONG addFlags;
02487
02488
RTL_PAGED_CODE();
02489
02490
DEBUG_PRINT(1,
02491 (
"RtlMergeRangeList(0x%08x, 0x%08x, 0x%08x, 0x%08x)\n",
02492 MergedRangeList,
02493 RangeList1,
02494 RangeList2,
02495 Flags
02496 ));
02497
02498
02499
02500
02501
02502 status =
RtlCopyRangeList(MergedRangeList, RangeList1);
02503
02504
if (!
NT_SUCCESS(status)) {
02505
goto cleanup;
02506 }
02507
02508
02509
02510
02511
02512
FOR_ALL_IN_LIST(
RTLP_RANGE_LIST_ENTRY, &RangeList2->ListHead, current) {
02513
02514
if (
MERGED(current)) {
02515
02516
FOR_ALL_IN_LIST(
RTLP_RANGE_LIST_ENTRY,
02517 ¤t->
Merged.ListHead,
02518 currentMerged) {
02519
02520
if (!(newEntry =
RtlpCopyRangeListEntry(currentMerged))) {
02521 status = STATUS_INSUFFICIENT_RESOURCES;
02522
goto cleanup;
02523 }
02524
02525
if (
CONFLICT(currentMerged)) {
02526
02527
02528
02529
02530
02531
02532 addFlags = Flags | RTL_RANGE_LIST_ADD_IF_CONFLICT;
02533 }
else {
02534
02535 addFlags = Flags;
02536 }
02537
02538 status =
RtlpAddRange(&MergedRangeList->ListHead,
02539 newEntry,
02540 addFlags
02541 );
02542
02543 }
02544
02545 }
else {
02546
02547
02548
if (!(newEntry =
RtlpCopyRangeListEntry(current))){
02549 status = STATUS_INSUFFICIENT_RESOURCES;
02550
goto cleanup;
02551 }
02552
02553
if (
CONFLICT(current)) {
02554
02555
02556
02557
02558
02559
02560 addFlags = Flags | RTL_RANGE_LIST_ADD_IF_CONFLICT;
02561 }
else {
02562 addFlags = Flags;
02563 }
02564
02565 status =
RtlpAddRange(&MergedRangeList->ListHead,
02566 newEntry,
02567 addFlags
02568 );
02569
02570
if (!
NT_SUCCESS(status)) {
02571
goto cleanup;
02572 }
02573 }
02574
02575 }
02576
02577
02578
02579
02580 MergedRangeList->Count += RangeList2->Count;
02581 MergedRangeList->Stamp += RangeList2->Count;
02582
02583
return status;
02584
02585 cleanup:
02586
02587
02588
02589
02590
02591
02592
RtlFreeRangeList(MergedRangeList);
02593
02594
return status;
02595
02596 }
02597
02598
NTSTATUS
02599 RtlInvertRangeList(
02600 OUT PRTL_RANGE_LIST InvertedRangeList,
02601 IN PRTL_RANGE_LIST RangeList
02602 )
02603
02604
02605
02606
02607
02608
02609
02610
02611
02612
02613
02614
02615
02616
02617
02618
02619
02620
02621
02622
02623
02624 {
02625
02626
PRTLP_RANGE_LIST_ENTRY currentRange;
02627 ULONGLONG currentStart = 0;
02628
NTSTATUS status;
02629
02630
RTL_PAGED_CODE();
02631
02632
02633
02634
02635
02636
02637
ASSERT(InvertedRangeList->Count == 0);
02638
02639
02640
02641
02642
02643
02644
02645
FOR_ALL_IN_LIST(
RTLP_RANGE_LIST_ENTRY,
02646 &RangeList->ListHead,
02647 currentRange) {
02648
02649
if (currentRange->
Start > currentStart) {
02650
02651
02652
02653
02654
02655 status =
RtlAddRange(InvertedRangeList,
02656 currentStart,
02657 currentRange->
Start-1,
02658 0,
02659 0,
02660 0,
02661
NULL);
02662
02663
if (!
NT_SUCCESS(status)) {
02664
return status;
02665 }
02666 }
02667
02668 currentStart = currentRange->
End + 1;
02669 }
02670
02671
02672
02673
02674
02675
02676
02677
02678
02679
if (currentStart > (currentStart - 1)) {
02680
02681 status =
RtlAddRange(InvertedRangeList,
02682 currentStart,
02683
MAX_ULONGLONG,
02684 0,
02685 0,
02686 0,
02687
NULL);
02688
02689
if (!
NT_SUCCESS(status)) {
02690
return status;
02691 }
02692 }
02693
02694
return STATUS_SUCCESS;
02695
02696 }
02697
02698
02699
#if DBG
02700
02701
VOID
02702
RtlpDumpRangeListEntry(
02703 LONG Level,
02704
PRTLP_RANGE_LIST_ENTRY Entry,
02705 BOOLEAN Indent
02706 )
02707 {
02708 PWSTR indentString;
02709
PRTLP_RANGE_LIST_ENTRY current;
02710
02711
RTL_PAGED_CODE();
02712
02713
if (Indent) {
02714 indentString =
L"\t\t";
02715 }
else {
02716 indentString =
L"";
02717 }
02718
02719
02720
02721
02722
DEBUG_PRINT(Level,
02723 (
"%sRange (0x%08x): 0x%I64x-0x%I64x\n",
02724 indentString,
02725 Entry,
02726 Entry->
Start,
02727 Entry->
End
02728 ));
02729
02730
02731
02732
02733
02734
DEBUG_PRINT(Level, (
"%s\tPrivateFlags: ", indentString));
02735
02736
if (
MERGED(Entry)) {
02737
DEBUG_PRINT(Level, (
"MERGED "));
02738
02739 }
02740
02741
DEBUG_PRINT(Level, (
"\n%s\tPublicFlags: ", indentString));
02742
02743
if (
SHARED(Entry)) {
02744
DEBUG_PRINT(Level, (
"SHARED "));
02745 }
02746
02747
if (
CONFLICT(Entry)) {
02748
DEBUG_PRINT(Level, (
"CONFLICT "));
02749 }
02750
02751
DEBUG_PRINT(Level, (
"\n"));
02752
02753
02754
if (
MERGED(Entry)) {
02755
02756
DEBUG_PRINT(Level, (
"%sMerged entries:\n", indentString));
02757
02758
02759
02760
02761
02762
FOR_ALL_IN_LIST(
RTLP_RANGE_LIST_ENTRY,
02763 &Entry->
Merged.ListHead,
02764 current) {
02765
RtlpDumpRangeListEntry(Level, current, TRUE);
02766 }
02767
02768
02769 }
else {
02770
02771
02772
02773
02774
02775
DEBUG_PRINT(Level,
02776 (
"%s\tUserData: 0x%08x\n\tOwner: 0x%08x\n",
02777 indentString,
02778 Entry->
Allocated.UserData,
02779 Entry->
Allocated.Owner
02780 ));
02781 }
02782 }
02783
02784
VOID
02785
RtlpDumpRangeList(
02786 LONG Level,
02787 PRTL_RANGE_LIST RangeList
02788 )
02789
02790 {
02791
PRTLP_RANGE_LIST_ENTRY current, currentMerged;
02792
02793
RTL_PAGED_CODE();
02794
02795
DEBUG_PRINT(Level,
02796 (
"*** Range List (0x%08x) - Count: %i\n",
02797 RangeList,
02798 RangeList->Count
02799 ));
02800
02801
FOR_ALL_IN_LIST(
RTLP_RANGE_LIST_ENTRY, &RangeList->ListHead, current) {
02802
02803
02804
02805
02806
02807
RtlpDumpRangeListEntry(Level, current, FALSE);
02808 }
02809 }
02810
02811
#endif