Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygenrangelist.c
Go to the documentation of this file.
00001 /* 00002 * COPYRIGHT: See COPYING in the top level directory 00003 * PROJECT: ReactOS system libraries 00004 * FILE: lib/rtl/rangelist.c 00005 * PURPOSE: Range list implementation 00006 * PROGRAMMERS: No programmer listed. 00007 */ 00008 00009 /* INCLUDES *****************************************************************/ 00010 00011 #include <rtl.h> 00012 00013 #define NDEBUG 00014 #include <debug.h> 00015 00016 /* TYPES ********************************************************************/ 00017 00018 typedef struct _RTL_RANGE_ENTRY 00019 { 00020 LIST_ENTRY Entry; 00021 RTL_RANGE Range; 00022 } RTL_RANGE_ENTRY, *PRTL_RANGE_ENTRY; 00023 00024 /* FUNCTIONS ***************************************************************/ 00025 00026 /********************************************************************** 00027 * NAME EXPORTED 00028 * RtlAddRange 00029 * 00030 * DESCRIPTION 00031 * Adds a range to a range list. 00032 * 00033 * ARGUMENTS 00034 * RangeList Range list. 00035 * Start 00036 * End 00037 * Attributes 00038 * Flags 00039 * UserData 00040 * Owner 00041 * 00042 * RETURN VALUE 00043 * Status 00044 * 00045 * TODO: 00046 * - Support shared ranges. 00047 * 00048 * @implemented 00049 */ 00050 NTSTATUS 00051 NTAPI 00052 RtlAddRange(IN OUT PRTL_RANGE_LIST RangeList, 00053 IN ULONGLONG Start, 00054 IN ULONGLONG End, 00055 IN UCHAR Attributes, 00056 IN ULONG Flags, 00057 IN PVOID UserData OPTIONAL, 00058 IN PVOID Owner OPTIONAL) 00059 { 00060 PRTL_RANGE_ENTRY RangeEntry; 00061 //PRTL_RANGE_ENTRY Previous; 00062 PRTL_RANGE_ENTRY Current; 00063 PLIST_ENTRY Entry; 00064 00065 if (Start > End) 00066 return STATUS_INVALID_PARAMETER; 00067 00068 /* Create new range entry */ 00069 RangeEntry = RtlpAllocateMemory(sizeof(RTL_RANGE_ENTRY), 'elRR'); 00070 if (RangeEntry == NULL) 00071 return STATUS_INSUFFICIENT_RESOURCES; 00072 00073 /* Initialize range entry */ 00074 RangeEntry->Range.Start = Start; 00075 RangeEntry->Range.End = End; 00076 RangeEntry->Range.Attributes = Attributes; 00077 RangeEntry->Range.UserData = UserData; 00078 RangeEntry->Range.Owner = Owner; 00079 00080 RangeEntry->Range.Flags = 0; 00081 if (Flags & RTL_RANGE_LIST_ADD_SHARED) 00082 RangeEntry->Range.Flags |= RTL_RANGE_SHARED; 00083 00084 /* Insert range entry */ 00085 if (RangeList->Count == 0) 00086 { 00087 InsertTailList(&RangeList->ListHead, 00088 &RangeEntry->Entry); 00089 RangeList->Count++; 00090 RangeList->Stamp++; 00091 return STATUS_SUCCESS; 00092 } 00093 else 00094 { 00095 //Previous = NULL; 00096 Entry = RangeList->ListHead.Flink; 00097 while (Entry != &RangeList->ListHead) 00098 { 00099 Current = CONTAINING_RECORD(Entry, RTL_RANGE_ENTRY, Entry); 00100 if (Current->Range.Start > RangeEntry->Range.End) 00101 { 00102 /* Insert before current */ 00103 DPRINT("Insert before current\n"); 00104 InsertTailList(&Current->Entry, 00105 &RangeEntry->Entry); 00106 00107 RangeList->Count++; 00108 RangeList->Stamp++; 00109 return STATUS_SUCCESS; 00110 } 00111 00112 //Previous = Current; 00113 Entry = Entry->Flink; 00114 } 00115 00116 DPRINT("Insert tail\n"); 00117 InsertTailList(&RangeList->ListHead, 00118 &RangeEntry->Entry); 00119 RangeList->Count++; 00120 RangeList->Stamp++; 00121 return STATUS_SUCCESS; 00122 } 00123 00124 RtlpFreeMemory(RangeEntry, 0); 00125 00126 return STATUS_UNSUCCESSFUL; 00127 } 00128 00129 00130 /********************************************************************** 00131 * NAME EXPORTED 00132 * RtlCopyRangeList 00133 * 00134 * DESCRIPTION 00135 * Copy a range list. 00136 * 00137 * ARGUMENTS 00138 * CopyRangeList Pointer to the destination range list. 00139 * RangeList Pointer to the source range list. 00140 * 00141 * RETURN VALUE 00142 * Status 00143 * 00144 * @implemented 00145 */ 00146 NTSTATUS 00147 NTAPI 00148 RtlCopyRangeList(OUT PRTL_RANGE_LIST CopyRangeList, 00149 IN PRTL_RANGE_LIST RangeList) 00150 { 00151 PRTL_RANGE_ENTRY Current; 00152 PRTL_RANGE_ENTRY NewEntry; 00153 PLIST_ENTRY Entry; 00154 00155 CopyRangeList->Flags = RangeList->Flags; 00156 00157 Entry = RangeList->ListHead.Flink; 00158 while (Entry != &RangeList->ListHead) 00159 { 00160 Current = CONTAINING_RECORD(Entry, RTL_RANGE_ENTRY, Entry); 00161 00162 NewEntry = RtlpAllocateMemory(sizeof(RTL_RANGE_ENTRY), 'elRR'); 00163 if (NewEntry == NULL) 00164 return STATUS_INSUFFICIENT_RESOURCES; 00165 00166 RtlCopyMemory(&NewEntry->Range, 00167 &Current->Range, 00168 sizeof(RTL_RANGE_ENTRY)); 00169 00170 InsertTailList(&CopyRangeList->ListHead, 00171 &NewEntry->Entry); 00172 00173 CopyRangeList->Count++; 00174 00175 Entry = Entry->Flink; 00176 } 00177 00178 CopyRangeList->Stamp++; 00179 00180 return STATUS_SUCCESS; 00181 } 00182 00183 00184 /********************************************************************** 00185 * NAME EXPORTED 00186 * RtlDeleteOwnersRanges 00187 * 00188 * DESCRIPTION 00189 * Delete all ranges that belong to the given owner. 00190 * 00191 * ARGUMENTS 00192 * RangeList Pointer to the range list. 00193 * Owner User supplied value that identifies the owner 00194 * of the ranges to be deleted. 00195 * 00196 * RETURN VALUE 00197 * Status 00198 * 00199 * @implemented 00200 */ 00201 NTSTATUS 00202 NTAPI 00203 RtlDeleteOwnersRanges(IN OUT PRTL_RANGE_LIST RangeList, 00204 IN PVOID Owner) 00205 { 00206 PRTL_RANGE_ENTRY Current; 00207 PLIST_ENTRY Entry; 00208 00209 Entry = RangeList->ListHead.Flink; 00210 while (Entry != &RangeList->ListHead) 00211 { 00212 Current = CONTAINING_RECORD(Entry, RTL_RANGE_ENTRY, Entry); 00213 if (Current->Range.Owner == Owner) 00214 { 00215 RemoveEntryList (Entry); 00216 RtlpFreeMemory(Current, 0); 00217 00218 RangeList->Count--; 00219 RangeList->Stamp++; 00220 } 00221 00222 Entry = Entry->Flink; 00223 } 00224 00225 return STATUS_SUCCESS; 00226 } 00227 00228 00229 /********************************************************************** 00230 * NAME EXPORTED 00231 * RtlDeleteRange 00232 * 00233 * DESCRIPTION 00234 * Deletes a given range. 00235 * 00236 * ARGUMENTS 00237 * RangeList Pointer to the range list. 00238 * Start Start of the range to be deleted. 00239 * End End of the range to be deleted. 00240 * Owner Owner of the ranges to be deleted. 00241 * 00242 * RETURN VALUE 00243 * Status 00244 * 00245 * @implemented 00246 */ 00247 NTSTATUS 00248 NTAPI 00249 RtlDeleteRange(IN OUT PRTL_RANGE_LIST RangeList, 00250 IN ULONGLONG Start, 00251 IN ULONGLONG End, 00252 IN PVOID Owner) 00253 { 00254 PRTL_RANGE_ENTRY Current; 00255 PLIST_ENTRY Entry; 00256 00257 Entry = RangeList->ListHead.Flink; 00258 while (Entry != &RangeList->ListHead) 00259 { 00260 Current = CONTAINING_RECORD(Entry, RTL_RANGE_ENTRY, Entry); 00261 if (Current->Range.Start == Start && 00262 Current->Range.End == End && 00263 Current->Range.Owner == Owner) 00264 { 00265 RemoveEntryList(Entry); 00266 00267 RtlpFreeMemory(Current, 0); 00268 00269 RangeList->Count--; 00270 RangeList->Stamp++; 00271 return STATUS_SUCCESS; 00272 } 00273 00274 Entry = Entry->Flink; 00275 } 00276 00277 return STATUS_RANGE_NOT_FOUND; 00278 } 00279 00280 00281 /********************************************************************** 00282 * NAME EXPORTED 00283 * RtlFindRange 00284 * 00285 * DESCRIPTION 00286 * Searches for an unused range. 00287 * 00288 * ARGUMENTS 00289 * RangeList Pointer to the range list. 00290 * Minimum 00291 * Maximum 00292 * Length 00293 * Alignment 00294 * Flags 00295 * AttributeAvailableMask 00296 * Context 00297 * Callback 00298 * Start 00299 * 00300 * RETURN VALUE 00301 * Status 00302 * 00303 * TODO 00304 * Support shared ranges and callback. 00305 * 00306 * @implemented 00307 */ 00308 NTSTATUS 00309 NTAPI 00310 RtlFindRange(IN PRTL_RANGE_LIST RangeList, 00311 IN ULONGLONG Minimum, 00312 IN ULONGLONG Maximum, 00313 IN ULONG Length, 00314 IN ULONG Alignment, 00315 IN ULONG Flags, 00316 IN UCHAR AttributeAvailableMask, 00317 IN PVOID Context OPTIONAL, 00318 IN PRTL_CONFLICT_RANGE_CALLBACK Callback OPTIONAL, 00319 OUT PULONGLONG Start) 00320 { 00321 PRTL_RANGE_ENTRY CurrentEntry; 00322 PRTL_RANGE_ENTRY NextEntry; 00323 PLIST_ENTRY Entry; 00324 ULONGLONG RangeMin; 00325 ULONGLONG RangeMax; 00326 00327 if (Alignment == 0 || Length == 0) 00328 { 00329 return STATUS_INVALID_PARAMETER; 00330 } 00331 00332 if (IsListEmpty(&RangeList->ListHead)) 00333 { 00334 *Start = ROUND_DOWN(Maximum - (Length - 1), Alignment); 00335 return STATUS_SUCCESS; 00336 } 00337 00338 NextEntry = NULL; 00339 Entry = RangeList->ListHead.Blink; 00340 while (Entry != &RangeList->ListHead) 00341 { 00342 CurrentEntry = CONTAINING_RECORD(Entry, RTL_RANGE_ENTRY, Entry); 00343 00344 RangeMax = NextEntry ? (NextEntry->Range.Start - 1) : Maximum; 00345 if (RangeMax + (Length - 1) < Minimum) 00346 { 00347 return STATUS_RANGE_NOT_FOUND; 00348 } 00349 00350 RangeMin = ROUND_DOWN(RangeMax - (Length - 1), Alignment); 00351 if (RangeMin < Minimum || 00352 (RangeMax - RangeMin) < (Length - 1)) 00353 { 00354 return STATUS_RANGE_NOT_FOUND; 00355 } 00356 00357 DPRINT("RangeMax: %I64x\n", RangeMax); 00358 DPRINT("RangeMin: %I64x\n", RangeMin); 00359 00360 if (RangeMin > CurrentEntry->Range.End) 00361 { 00362 *Start = RangeMin; 00363 return STATUS_SUCCESS; 00364 } 00365 00366 NextEntry = CurrentEntry; 00367 Entry = Entry->Blink; 00368 } 00369 00370 RangeMax = NextEntry ? (NextEntry->Range.Start - 1) : Maximum; 00371 if (RangeMax + (Length - 1) < Minimum) 00372 { 00373 return STATUS_RANGE_NOT_FOUND; 00374 } 00375 00376 RangeMin = ROUND_DOWN(RangeMax - (Length - 1), Alignment); 00377 if (RangeMin < Minimum || 00378 (RangeMax - RangeMin) < (Length - 1)) 00379 { 00380 return STATUS_RANGE_NOT_FOUND; 00381 } 00382 00383 DPRINT("RangeMax: %I64x\n", RangeMax); 00384 DPRINT("RangeMin: %I64x\n", RangeMin); 00385 00386 *Start = RangeMin; 00387 00388 return STATUS_SUCCESS; 00389 } 00390 00391 00392 /********************************************************************** 00393 * NAME EXPORTED 00394 * RtlFreeRangeList 00395 * 00396 * DESCRIPTION 00397 * Deletes all ranges in a range list. 00398 * 00399 * ARGUMENTS 00400 * RangeList Pointer to the range list. 00401 * 00402 * RETURN VALUE 00403 * None 00404 * 00405 * @implemented 00406 */ 00407 VOID 00408 NTAPI 00409 RtlFreeRangeList(IN PRTL_RANGE_LIST RangeList) 00410 { 00411 PLIST_ENTRY Entry; 00412 PRTL_RANGE_ENTRY Current; 00413 00414 while (!IsListEmpty(&RangeList->ListHead)) 00415 { 00416 Entry = RemoveHeadList(&RangeList->ListHead); 00417 Current = CONTAINING_RECORD(Entry, RTL_RANGE_ENTRY, Entry); 00418 00419 DPRINT ("Range start: %I64u\n", Current->Range.Start); 00420 DPRINT ("Range end: %I64u\n", Current->Range.End); 00421 00422 RtlpFreeMemory(Current, 0); 00423 } 00424 00425 RangeList->Flags = 0; 00426 RangeList->Count = 0; 00427 } 00428 00429 00430 /********************************************************************** 00431 * NAME EXPORTED 00432 * RtlGetFirstRange 00433 * 00434 * DESCRIPTION 00435 * Retrieves the first range of a range list. 00436 * 00437 * ARGUMENTS 00438 * RangeList Pointer to the range list. 00439 * Iterator Pointer to a user supplied list state buffer. 00440 * Range Pointer to the first range. 00441 * 00442 * RETURN VALUE 00443 * Status 00444 * 00445 * @implemented 00446 */ 00447 NTSTATUS 00448 NTAPI 00449 RtlGetFirstRange(IN PRTL_RANGE_LIST RangeList, 00450 OUT PRTL_RANGE_LIST_ITERATOR Iterator, 00451 OUT PRTL_RANGE *Range) 00452 { 00453 Iterator->RangeListHead = &RangeList->ListHead; 00454 Iterator->MergedHead = NULL; 00455 Iterator->Stamp = RangeList->Stamp; 00456 00457 if (IsListEmpty(&RangeList->ListHead)) 00458 { 00459 Iterator->Current = NULL; 00460 *Range = NULL; 00461 return STATUS_NO_MORE_ENTRIES; 00462 } 00463 00464 Iterator->Current = RangeList->ListHead.Flink; 00465 *Range = &((PRTL_RANGE_ENTRY)Iterator->Current)->Range; 00466 00467 return STATUS_SUCCESS; 00468 } 00469 00470 00471 /********************************************************************** 00472 * NAME EXPORTED 00473 * RtlGetNextRange 00474 * 00475 * DESCRIPTION 00476 * Retrieves the next (or previous) range of a range list. 00477 * 00478 * ARGUMENTS 00479 * Iterator Pointer to a user supplied list state buffer. 00480 * Range Pointer to the first range. 00481 * MoveForwards TRUE, get next range 00482 * FALSE, get previous range 00483 * 00484 * RETURN VALUE 00485 * Status 00486 * 00487 * @implemented 00488 */ 00489 NTSTATUS 00490 NTAPI 00491 RtlGetNextRange(IN OUT PRTL_RANGE_LIST_ITERATOR Iterator, 00492 OUT PRTL_RANGE *Range, 00493 IN BOOLEAN MoveForwards) 00494 { 00495 PRTL_RANGE_LIST RangeList; 00496 PLIST_ENTRY Next; 00497 00498 RangeList = CONTAINING_RECORD(Iterator->RangeListHead, RTL_RANGE_LIST, ListHead); 00499 if (Iterator->Stamp != RangeList->Stamp) 00500 return STATUS_INVALID_PARAMETER; 00501 00502 if (MoveForwards) 00503 { 00504 Next = ((PRTL_RANGE_ENTRY)Iterator->Current)->Entry.Flink; 00505 } 00506 else 00507 { 00508 Next = ((PRTL_RANGE_ENTRY)Iterator->Current)->Entry.Blink; 00509 } 00510 00511 if (Next == Iterator->RangeListHead) 00512 return STATUS_NO_MORE_ENTRIES; 00513 00514 Iterator->Current = Next; 00515 *Range = &((PRTL_RANGE_ENTRY)Next)->Range; 00516 00517 return STATUS_SUCCESS; 00518 } 00519 00520 00521 /********************************************************************** 00522 * NAME EXPORTED 00523 * RtlInitializeRangeList 00524 * 00525 * DESCRIPTION 00526 * Initializes a range list. 00527 * 00528 * ARGUMENTS 00529 * RangeList Pointer to a user supplied range list. 00530 * 00531 * RETURN VALUE 00532 * None 00533 * 00534 * @implemented 00535 */ 00536 VOID 00537 NTAPI 00538 RtlInitializeRangeList(IN OUT PRTL_RANGE_LIST RangeList) 00539 { 00540 InitializeListHead(&RangeList->ListHead); 00541 RangeList->Flags = 0; 00542 RangeList->Count = 0; 00543 RangeList->Stamp = 0; 00544 } 00545 00546 00547 /********************************************************************** 00548 * NAME EXPORTED 00549 * RtlInvertRangeList 00550 * 00551 * DESCRIPTION 00552 * Inverts a range list. 00553 * 00554 * ARGUMENTS 00555 * InvertedRangeList Inverted range list. 00556 * RangeList Range list. 00557 * 00558 * RETURN VALUE 00559 * Status 00560 * 00561 * @implemented 00562 */ 00563 NTSTATUS 00564 NTAPI 00565 RtlInvertRangeList(OUT PRTL_RANGE_LIST InvertedRangeList, 00566 IN PRTL_RANGE_LIST RangeList) 00567 { 00568 PRTL_RANGE_ENTRY Previous; 00569 PRTL_RANGE_ENTRY Current; 00570 PLIST_ENTRY Entry; 00571 NTSTATUS Status; 00572 00573 /* Don't invert an empty range list */ 00574 if (IsListEmpty(&RangeList->ListHead)) 00575 { 00576 return STATUS_SUCCESS; 00577 } 00578 00579 /* Add leading and intermediate ranges */ 00580 Previous = NULL; 00581 Entry = RangeList->ListHead.Flink; 00582 while (Entry != &RangeList->ListHead) 00583 { 00584 Current = CONTAINING_RECORD(Entry, RTL_RANGE_ENTRY, Entry); 00585 00586 if (Previous == NULL) 00587 { 00588 if (Current->Range.Start != (ULONGLONG)0) 00589 { 00590 Status = RtlAddRange(InvertedRangeList, 00591 (ULONGLONG)0, 00592 Current->Range.Start - 1, 00593 0, 00594 0, 00595 NULL, 00596 NULL); 00597 if (!NT_SUCCESS(Status)) 00598 return Status; 00599 } 00600 } 00601 else 00602 { 00603 if (Previous->Range.End + 1 != Current->Range.Start) 00604 { 00605 Status = RtlAddRange(InvertedRangeList, 00606 Previous->Range.End + 1, 00607 Current->Range.Start - 1, 00608 0, 00609 0, 00610 NULL, 00611 NULL); 00612 if (!NT_SUCCESS(Status)) 00613 return Status; 00614 } 00615 } 00616 00617 Previous = Current; 00618 Entry = Entry->Flink; 00619 } 00620 00621 /* Add trailing range */ 00622 if (Previous->Range.End + 1 != (ULONGLONG)-1) 00623 { 00624 Status = RtlAddRange(InvertedRangeList, 00625 Previous->Range.End + 1, 00626 (ULONGLONG)-1, 00627 0, 00628 0, 00629 NULL, 00630 NULL); 00631 if (!NT_SUCCESS(Status)) 00632 return Status; 00633 } 00634 00635 return STATUS_SUCCESS; 00636 } 00637 00638 00639 /********************************************************************** 00640 * NAME EXPORTED 00641 * RtlIsRangeAvailable 00642 * 00643 * DESCRIPTION 00644 * Checks whether a range is available or not. 00645 * 00646 * ARGUMENTS 00647 * RangeList Pointer to the range list. 00648 * Start 00649 * End 00650 * Flags 00651 * AttributeAvailableMask 00652 * Context 00653 * Callback 00654 * Available 00655 * 00656 * RETURN VALUE 00657 * Status 00658 * 00659 * TODO: 00660 * - honor Flags and AttributeAvailableMask. 00661 * 00662 * @implemented 00663 */ 00664 NTSTATUS 00665 NTAPI 00666 RtlIsRangeAvailable(IN PRTL_RANGE_LIST RangeList, 00667 IN ULONGLONG Start, 00668 IN ULONGLONG End, 00669 IN ULONG Flags, 00670 IN UCHAR AttributeAvailableMask, 00671 IN PVOID Context OPTIONAL, 00672 IN PRTL_CONFLICT_RANGE_CALLBACK Callback OPTIONAL, 00673 OUT PBOOLEAN Available) 00674 { 00675 PRTL_RANGE_ENTRY Current; 00676 PLIST_ENTRY Entry; 00677 00678 *Available = TRUE; 00679 00680 Entry = RangeList->ListHead.Flink; 00681 while (Entry != &RangeList->ListHead) 00682 { 00683 Current = CONTAINING_RECORD (Entry, RTL_RANGE_ENTRY, Entry); 00684 00685 if (!((Current->Range.Start >= End && Current->Range.End > End) || 00686 (Current->Range.Start <= Start && Current->Range.End < Start && 00687 (!(Flags & RTL_RANGE_SHARED) || 00688 !(Current->Range.Flags & RTL_RANGE_SHARED))))) 00689 { 00690 if (Callback != NULL) 00691 { 00692 *Available = Callback(Context, 00693 &Current->Range); 00694 } 00695 else 00696 { 00697 *Available = FALSE; 00698 } 00699 } 00700 00701 Entry = Entry->Flink; 00702 } 00703 00704 return STATUS_SUCCESS; 00705 } 00706 00707 00708 /********************************************************************** 00709 * NAME EXPORTED 00710 * RtlMergeRangeList 00711 * 00712 * DESCRIPTION 00713 * Merges two range lists. 00714 * 00715 * ARGUMENTS 00716 * MergedRangeList Resulting range list. 00717 * RangeList1 First range list. 00718 * RangeList2 Second range list 00719 * Flags 00720 * 00721 * RETURN VALUE 00722 * Status 00723 * 00724 * @implemented 00725 */ 00726 NTSTATUS 00727 NTAPI 00728 RtlMergeRangeLists(OUT PRTL_RANGE_LIST MergedRangeList, 00729 IN PRTL_RANGE_LIST RangeList1, 00730 IN PRTL_RANGE_LIST RangeList2, 00731 IN ULONG Flags) 00732 { 00733 RTL_RANGE_LIST_ITERATOR Iterator; 00734 PRTL_RANGE Range; 00735 NTSTATUS Status; 00736 00737 /* Copy range list 1 to the merged range list */ 00738 Status = RtlCopyRangeList(MergedRangeList, 00739 RangeList1); 00740 if (!NT_SUCCESS(Status)) 00741 return Status; 00742 00743 /* Add range list 2 entries to the merged range list */ 00744 Status = RtlGetFirstRange(RangeList2, 00745 &Iterator, 00746 &Range); 00747 if (!NT_SUCCESS(Status)) 00748 return (Status == STATUS_NO_MORE_ENTRIES) ? STATUS_SUCCESS : Status; 00749 00750 while (TRUE) 00751 { 00752 Status = RtlAddRange(MergedRangeList, 00753 Range->Start, 00754 Range->End, 00755 Range->Attributes, 00756 Range->Flags | Flags, 00757 Range->UserData, 00758 Range->Owner); 00759 if (!NT_SUCCESS(Status)) 00760 break; 00761 00762 Status = RtlGetNextRange(&Iterator, 00763 &Range, 00764 TRUE); 00765 if (!NT_SUCCESS(Status)) 00766 break; 00767 } 00768 00769 return (Status == STATUS_NO_MORE_ENTRIES) ? STATUS_SUCCESS : Status; 00770 } 00771 00772 /* EOF */ Generated on Sat May 26 2012 04:35:22 for ReactOS by
1.7.6.1
|