00119                    :
00120 
00121     This function extends a region by adding another segment's worth of
00122     blocks to 
the region.
00123 
00124 Arguments:
00125 
00126     Region - Supplies 
the address of a region header.
00127 
00128     Segment - Supplies 
the address of a segment of storage.
00129 
00130     SegmentSize - Supplies 
the size in bytes of Segment.
00131 
00132     
Lock - Supplies 
the address of a spinlock.
00133 
00134 Return Value:
00135 
00136     None.
00137 
00138 --*/
00139 
00140 {
00141 
00142     ULONG 
BlockSize;
00143     SINGLE_LIST_ENTRY FirstEntry;
00144     KIRQL OldIrql;
00145     PSINGLE_LIST_ENTRY LastEntry;
00146     PSINGLE_LIST_ENTRY NextEntry;
00147     ULONG TotalSize;
00148 
00149     
00150     
00151     
00152     
00153     
00154 
00155     
BlockSize = Region->BlockSize;
00156     
if ((((ULONG)Segment & 7) != 0) ||
00157         ((
BlockSize & 7) != 0) ||
00158         (
BlockSize > (SegmentSize - 
sizeof(
REGION_SEGMENT_HEADER)))) {
00159         
KeBugCheckEx(INVALID_REGION_OR_SEGMENT, (ULONG)Segment, SegmentSize, BlockSize, 0);
00160     }
00161 
00162     
00163     
00164     
00165 
00166     TotalSize = ((SegmentSize - 
sizeof(
REGION_SEGMENT_HEADER)) / 
BlockSize) * 
BlockSize;
00167     FirstEntry.Next = 
NULL;
00168     NextEntry = (PSINGLE_LIST_ENTRY)((PCHAR)Segment + 
sizeof(
REGION_SEGMENT_HEADER));
00169     LastEntry = (PSINGLE_LIST_ENTRY)((PCHAR)NextEntry + TotalSize);
00170     
do {
00171        NextEntry->Next = FirstEntry.Next;
00172        FirstEntry.Next = NextEntry;
00173        NextEntry = (PSINGLE_LIST_ENTRY)((PCHAR)NextEntry + 
BlockSize);
00174     } 
while (NextEntry != LastEntry);
00175 
00176     
00177     
00178     
00179     
00180     
00181     
00182     
00183     
00184 
00185     ExAcquireSpinLock(Lock, &OldIrql);
00186     ((
PREGION_SEGMENT_HEADER)Segment)->NextSegment = Region->FirstSegment;
00187     Region->FirstSegment = (
PREGION_SEGMENT_HEADER)Segment;
00188     Region->TotalSize += TotalSize;
00189     NextEntry = (PSINGLE_LIST_ENTRY)((PCHAR)Segment + 
sizeof(
REGION_SEGMENT_HEADER));
00190     LastEntry = (PSINGLE_LIST_ENTRY)((PCHAR)LastEntry - Region->BlockSize);
00191     
do {
00192 
00193         
00194         
00195         
00196         
00197 
00198         FirstEntry.Next = Region->ListHead.Next.Next;
00199 
00200         
00201         
00202         
00203         
00204         
00205         
00206         
00207         
00208 
00209         NextEntry->Next = FirstEntry.Next;
00210     } 
while (InterlockedCompareExchange((PVOID)&Region->ListHead.Next,
00211                                         LastEntry,
00212                                         FirstEntry.Next) != FirstEntry.Next);
00213 
00214     ExReleaseSpinLock(Lock, OldIrql);
00215     
return;
00216 }
}