示例#1
0
void
Test_RtlFindNextForwardRunClear(void)
{
    RTL_BITMAP BitMapHeader;
    ULONG *Buffer;
    ULONG Index;

    Buffer = AllocateGuarded(2 * sizeof(*Buffer));
    Buffer[0] = 0xF9F078B2;
    Buffer[1] = 0x3F303F30;

    RtlInitializeBitMap(&BitMapHeader, Buffer, 0);
    ok_int(RtlFindNextForwardRunClear(&BitMapHeader, 0, &Index), 0);
    ok_int(Index, 0);
    ok_int(RtlFindNextForwardRunClear(&BitMapHeader, 1, &Index), 0);
    ok_int(Index, 1);

    Index = -1;
    RtlInitializeBitMap(&BitMapHeader, Buffer, 8);
    ok_int(RtlFindNextForwardRunClear(&BitMapHeader, 0, &Index), 1);
    ok_int(Index, 0);
    ok_int(RtlFindNextForwardRunClear(&BitMapHeader, 1, &Index), 2);
    ok_int(Index, 2);
    ok_int(RtlFindNextForwardRunClear(&BitMapHeader, 7, &Index), 0);
    ok_int(Index, 8);
    ok_int(RtlFindNextForwardRunClear(&BitMapHeader, 17, &Index), 0);
    ok_int(Index, 17);
    ok_int(RtlFindNextForwardRunClear(&BitMapHeader, 39, &Index), 0);
    ok_int(Index, 39);
    FreeGuarded(Buffer);
}
示例#2
0
文件: emsdrv.c 项目: reactos/reactos
static UCHAR InitSystemHandle(USHORT NumPages)
{
    //
    // FIXME: This is an adapted copy of EmsAlloc!!
    //

    ULONG i, CurrentIndex = 0;
    PEMS_HANDLE HandleEntry = &HandleTable[EMS_SYSTEM_HANDLE];

    /* The system handle must never have been initialized before */
    ASSERT(!HandleEntry->Allocated);

    /* Now allocate it */
    HandleEntry->Allocated = TRUE;

    while (HandleEntry->PageCount < NumPages)
    {
        ULONG RunStart;
        ULONG RunSize = RtlFindNextForwardRunClear(&AllocBitmap, CurrentIndex, &RunStart);

        if (RunSize == 0)
        {
            /* Free what's been allocated already and report failure */
            EmsFree(EMS_SYSTEM_HANDLE);
            // FIXME: For this function (and EmsAlloc as well),
            // use instead an internal function that just uses
            // PEMS_HANDLE pointers instead. It's only in the
            // EMS interrupt handler that we should do the
            // unfolding.
            return EMS_STATUS_INSUFFICIENT_PAGES;
        }
        else if ((HandleEntry->PageCount + RunSize) > NumPages)
        {
            /* We don't need the entire run */
            RunSize = NumPages - HandleEntry->PageCount;
        }

        CurrentIndex = RunStart + RunSize;
        HandleEntry->PageCount += RunSize;
        RtlSetBits(&AllocBitmap, RunStart, RunSize);

        for (i = 0; i < RunSize; i++)
        {
            PageTable[RunStart + i].Handle = EMS_SYSTEM_HANDLE;
            InsertTailList(&HandleEntry->PageList, &PageTable[RunStart + i].Entry);
        }
    }

    return EMS_STATUS_SUCCESS;
}
示例#3
0
文件: himem.c 项目: GYGit/reactos
static WORD XmsGetLargestFreeBlock(VOID)
{
    WORD Result = 0;
    DWORD CurrentIndex = 0;
    ULONG RunStart;
    ULONG RunSize;

    while (CurrentIndex < XMS_BLOCKS)
    {
        RunSize = RtlFindNextForwardRunClear(&AllocBitmap, CurrentIndex, &RunStart);
        if (RunSize == 0) break;

        /* Update the maximum */
        if (RunSize > Result) Result = RunSize;

        /* Go to the next run */
        CurrentIndex = RunStart + RunSize;
    }

    return Result;
}
示例#4
0
文件: emsdrv.c 项目: reactos/reactos
static UCHAR EmsAlloc(USHORT NumPages, PUSHORT Handle)
{
    ULONG i, CurrentIndex = 0;
    PEMS_HANDLE HandleEntry;

    if (NumPages == 0) return EMS_STATUS_ZERO_PAGES;

    HandleEntry = CreateHandle(Handle);
    if (!HandleEntry)  return EMS_STATUS_NO_MORE_HANDLES;

    while (HandleEntry->PageCount < NumPages)
    {
        ULONG RunStart;
        ULONG RunSize = RtlFindNextForwardRunClear(&AllocBitmap, CurrentIndex, &RunStart);

        if (RunSize == 0)
        {
            /* Free what's been allocated already and report failure */
            EmsFree(*Handle);
            return EMS_STATUS_INSUFFICIENT_PAGES;
        }
        else if ((HandleEntry->PageCount + RunSize) > NumPages)
        {
            /* We don't need the entire run */
            RunSize = NumPages - HandleEntry->PageCount;
        }

        CurrentIndex = RunStart + RunSize;
        HandleEntry->PageCount += RunSize;
        RtlSetBits(&AllocBitmap, RunStart, RunSize);

        for (i = 0; i < RunSize; i++)
        {
            PageTable[RunStart + i].Handle = *Handle;
            InsertTailList(&HandleEntry->PageList, &PageTable[RunStart + i].Entry);
        }
    }

    return EMS_STATUS_SUCCESS;
}
示例#5
0
文件: volinfo.c 项目: Moteesh/reactos
/** 
* NtfsAllocateClusters 
* Allocates a run of clusters. The run allocated might be smaller than DesiredClusters.
*/
NTSTATUS
NtfsAllocateClusters(PDEVICE_EXTENSION DeviceExt,
                     ULONG FirstDesiredCluster,
                     ULONG DesiredClusters, 
                     PULONG FirstAssignedCluster, 
                     PULONG AssignedClusters)
{
    NTSTATUS Status;
    PFILE_RECORD_HEADER BitmapRecord;
    PNTFS_ATTR_CONTEXT DataContext;
    ULONGLONG BitmapDataSize;
    PUCHAR BitmapData;
    ULONGLONG FreeClusters = 0;
    RTL_BITMAP Bitmap;
    ULONG AssignedRun;
    ULONG LengthWritten;

    DPRINT1("NtfsAllocateClusters(%p, %lu, %lu, %p, %p)\n", DeviceExt, FirstDesiredCluster, DesiredClusters, FirstAssignedCluster, AssignedClusters);

    BitmapRecord = ExAllocateFromNPagedLookasideList(&DeviceExt->FileRecLookasideList);
    if (BitmapRecord == NULL)
    {
        return STATUS_INSUFFICIENT_RESOURCES;
    }

    Status = ReadFileRecord(DeviceExt, NTFS_FILE_BITMAP, BitmapRecord);
    if (!NT_SUCCESS(Status))
    {
        ExFreeToNPagedLookasideList(&DeviceExt->FileRecLookasideList, BitmapRecord);
        return Status;
    }

    Status = FindAttribute(DeviceExt, BitmapRecord, AttributeData, L"", 0, &DataContext, NULL);
    if (!NT_SUCCESS(Status))
    {
        ExFreeToNPagedLookasideList(&DeviceExt->FileRecLookasideList, BitmapRecord);
        return Status;
    }

    BitmapDataSize = AttributeDataLength(DataContext->pRecord);
    BitmapDataSize = min(BitmapDataSize, 0xffffffff);
    ASSERT((BitmapDataSize * 8) >= DeviceExt->NtfsInfo.ClusterCount);
    BitmapData = ExAllocatePoolWithTag(NonPagedPool, ROUND_UP(BitmapDataSize, DeviceExt->NtfsInfo.BytesPerSector), TAG_NTFS);
    if (BitmapData == NULL)
    {
        ReleaseAttributeContext(DataContext);
        ExFreeToNPagedLookasideList(&DeviceExt->FileRecLookasideList, BitmapRecord);
        return  STATUS_INSUFFICIENT_RESOURCES;
    }

    DPRINT1("Total clusters: %I64x\n", DeviceExt->NtfsInfo.ClusterCount);
    DPRINT1("Total clusters in bitmap: %I64x\n", BitmapDataSize * 8);
    DPRINT1("Diff in size: %I64d B\n", ((BitmapDataSize * 8) - DeviceExt->NtfsInfo.ClusterCount) * DeviceExt->NtfsInfo.SectorsPerCluster * DeviceExt->NtfsInfo.BytesPerSector);

    ReadAttribute(DeviceExt, DataContext, 0, (PCHAR)BitmapData, (ULONG)BitmapDataSize);

    RtlInitializeBitMap(&Bitmap, (PULONG)BitmapData, DeviceExt->NtfsInfo.ClusterCount);
    FreeClusters = RtlNumberOfClearBits(&Bitmap);

    if (FreeClusters < DesiredClusters)
    {
        ReleaseAttributeContext(DataContext);

        ExFreePoolWithTag(BitmapData, TAG_NTFS);
        ExFreeToNPagedLookasideList(&DeviceExt->FileRecLookasideList, BitmapRecord);
        return STATUS_DISK_FULL;
    }
    
    // TODO: Observe MFT reservation zone

    // Can we get one contiguous run?
    AssignedRun = RtlFindClearBitsAndSet(&Bitmap, DesiredClusters, FirstDesiredCluster);

    if (AssignedRun != 0xFFFFFFFF)
    {
        *FirstAssignedCluster = AssignedRun;
        *AssignedClusters = DesiredClusters;
    }
    else
    {
        // we can't get one contiguous run
        *AssignedClusters = RtlFindNextForwardRunClear(&Bitmap, FirstDesiredCluster, FirstAssignedCluster);
        
        if (*AssignedClusters == 0)
        {
            // we couldn't find any runs starting at DesiredFirstCluster
            *AssignedClusters = RtlFindLongestRunClear(&Bitmap, FirstAssignedCluster);
        }
            
    }
                
    Status = WriteAttribute(DeviceExt, DataContext, 0, BitmapData, (ULONG)BitmapDataSize, &LengthWritten, BitmapRecord);
    
    ReleaseAttributeContext(DataContext);

    ExFreePoolWithTag(BitmapData, TAG_NTFS);
    ExFreeToNPagedLookasideList(&DeviceExt->FileRecLookasideList, BitmapRecord);

    return Status;
}
示例#6
0
文件: himem.c 项目: GYGit/reactos
static UCHAR XmsRealloc(WORD Handle, WORD NewSize)
{
    DWORD BlockNumber;
    PXMS_HANDLE HandleEntry = GetHandleRecord(Handle);
    DWORD CurrentIndex = 0;
    ULONG RunStart;
    ULONG RunSize;

    if (!ValidateHandle(HandleEntry))
        return XMS_STATUS_INVALID_HANDLE;

    if (HandleEntry->LockCount)
        return XMS_STATUS_LOCKED;

    /* Get the block number */
    BlockNumber = (HandleEntry->Address - XMS_ADDRESS) / XMS_BLOCK_SIZE;

    if (NewSize < HandleEntry->Size)
    {
        /* Just reduce the size of this block */
        RtlClearBits(&AllocBitmap, BlockNumber + NewSize, HandleEntry->Size - NewSize);
        FreeBlocks += HandleEntry->Size - NewSize;
        HandleEntry->Size = NewSize;
    }
    else if (NewSize > HandleEntry->Size)
    {
        /* Check if we can expand in-place */
        if (RtlAreBitsClear(&AllocBitmap,
                            BlockNumber + HandleEntry->Size,
                            NewSize - HandleEntry->Size))
        {
            /* Just increase the size of this block */
            RtlSetBits(&AllocBitmap,
                       BlockNumber + HandleEntry->Size,
                       NewSize - HandleEntry->Size);
            FreeBlocks -= NewSize - HandleEntry->Size;
            HandleEntry->Size = NewSize;

            /* We're done */
            return XMS_STATUS_SUCCESS;
        }

        /* Deallocate the current block range */
        RtlClearBits(&AllocBitmap, BlockNumber, HandleEntry->Size);

        /* Find a new place for this block */
        while (CurrentIndex < XMS_BLOCKS)
        {
            RunSize = RtlFindNextForwardRunClear(&AllocBitmap, CurrentIndex, &RunStart);
            if (RunSize == 0) break;

            if (RunSize >= NewSize)
            {
                /* Allocate the new range */
                RtlSetBits(&AllocBitmap, RunStart, NewSize);

                /* Move the data to the new location */
                RtlMoveMemory((PVOID)REAL_TO_PHYS(XMS_ADDRESS + RunStart * XMS_BLOCK_SIZE),
                              (PVOID)REAL_TO_PHYS(HandleEntry->Address),
                              HandleEntry->Size * XMS_BLOCK_SIZE);

                /* Update the handle entry */
                HandleEntry->Address = XMS_ADDRESS + RunStart * XMS_BLOCK_SIZE;
                HandleEntry->Size = NewSize;

                /* Update the free block counter */
                FreeBlocks -= NewSize - HandleEntry->Size;

                return XMS_STATUS_SUCCESS;
            }

            /* Keep searching */
            CurrentIndex = RunStart + RunSize;
        }

        /* Restore the old block range */
        RtlSetBits(&AllocBitmap, BlockNumber, HandleEntry->Size);
        return XMS_STATUS_OUT_OF_MEMORY;
    }
    
    return XMS_STATUS_SUCCESS;
}
示例#7
0
文件: himem.c 项目: GYGit/reactos
static UCHAR XmsAlloc(WORD Size, PWORD Handle)
{
    BYTE i;
    PXMS_HANDLE HandleEntry;
    DWORD CurrentIndex = 0;
    ULONG RunStart;
    ULONG RunSize;

    if (Size > FreeBlocks) return XMS_STATUS_OUT_OF_MEMORY;

    for (i = 0; i < XMS_MAX_HANDLES; i++)
    {
        HandleEntry = &HandleTable[i];
        if (HandleEntry->Handle == 0)
        {
            *Handle = i + 1;
            break;
        }
    }

    if (i == XMS_MAX_HANDLES) return XMS_STATUS_OUT_OF_HANDLES;

    /* Optimize blocks */
    for (i = 0; i < XMS_MAX_HANDLES; i++)
    {
        /* Skip free and locked blocks */
        if (HandleEntry->Handle == 0 || HandleEntry->LockCount > 0) continue;

        CurrentIndex = (HandleEntry->Address - XMS_ADDRESS) / XMS_BLOCK_SIZE;

        /* Check if there is any free space before this block */
        RunSize = RtlFindLastBackwardRunClear(&AllocBitmap, CurrentIndex, &RunStart);
        if (RunSize == 0) break;

        /* Move this block back */
        RtlMoveMemory((PVOID)REAL_TO_PHYS(HandleEntry->Address - RunSize * XMS_BLOCK_SIZE),
                      (PVOID)REAL_TO_PHYS(HandleEntry->Address),
                      RunSize * XMS_BLOCK_SIZE);

        /* Update the address */
        HandleEntry->Address -= RunSize * XMS_BLOCK_SIZE;
    }

    while (CurrentIndex < XMS_BLOCKS)
    {
        RunSize = RtlFindNextForwardRunClear(&AllocBitmap, CurrentIndex, &RunStart);
        if (RunSize == 0) break;

        if (RunSize >= HandleEntry->Size)
        {
            /* Allocate it here */
            HandleEntry->Handle = i + 1;
            HandleEntry->LockCount = 0;
            HandleEntry->Size = Size;
            HandleEntry->Address = XMS_ADDRESS + RunStart * XMS_BLOCK_SIZE;

            FreeBlocks -= Size;
            RtlSetBits(&AllocBitmap, RunStart, HandleEntry->Size);

            return XMS_STATUS_SUCCESS;
        }

        /* Keep searching */
        CurrentIndex = RunStart + RunSize;
    }

    return XMS_STATUS_OUT_OF_MEMORY;
}
示例#8
0
ULONG NtdllBitmap::FindNextForwardRunClear( ULONG from_index, PULONG starting_run_index )
{
	assert(RtlFindNextForwardRunClear != NULL);
	return RtlFindNextForwardRunClear(this, from_index, starting_run_index);
}