示例#1
0
文件: emulator.c 项目: staring/RosFE
VOID WINAPI EmulatorWriteMemory(PFAST486_STATE State, ULONG Address, PVOID Buffer, ULONG Size)
{
    UNREFERENCED_PARAMETER(State);

    // BIG HACK!!!! To make BIOS images working correctly,
    // until Aleksander rewrites memory management!!
    if (Address >= 0xFFFFFFF0) Address -= 0xFFF00000;

    /* If the A20 line is disabled, mask bit 20 */
    if (!A20Line) Address &= ~(1 << 20);

    /* Make sure the requested address is valid */
    if ((Address + Size) >= MAX_ADDRESS) return;

    /* Make sure we don't write to the ROM area */
    if ((Address + Size) >= ROM_AREA_START && (Address < ROM_AREA_END)) return;

    /* Read the data from the buffer and store it in the virtual address space */
    EmulatorMoveMemory(REAL_TO_PHYS(Address), Buffer, Size);

    /*
     * Check if we modified the VGA memory.
     */
    if (((Address + Size) >= VgaGetVideoBaseAddress())
        && (Address < VgaGetVideoLimitAddress()))
    {
        DWORD VgaAddress = max(Address, VgaGetVideoBaseAddress());
        DWORD ActualSize = min(Address + Size - 1, VgaGetVideoLimitAddress())
                           - VgaAddress + 1;
        LPBYTE SrcBuffer = (LPBYTE)REAL_TO_PHYS(VgaAddress);

        /* Write to the VGA memory */
        VgaWriteMemory(VgaAddress, SrcBuffer, ActualSize);
    }
}
示例#2
0
文件: dem.c 项目: hackbunny/reactos
static VOID WINAPI DosSystemBop(LPWORD Stack)
{
    /* Get the Function Number and skip it */
    BYTE FuncNum = *(PBYTE)SEG_OFF_TO_PTR(getCS(), getIP());
    setIP(getIP() + 1);

    switch (FuncNum)
    {
        case 0x11:  // Load the DOS kernel
        {
            BOOLEAN Success = FALSE;
            HANDLE  hDosKernel;
            ULONG   ulDosKernelSize = 0;

            DPRINT1("You are loading Windows NT DOS!\n");

            /* Open the DOS kernel file */
            hDosKernel = FileOpen("ntdos.sys", &ulDosKernelSize);

            /* If we failed, bail out */
            if (hDosKernel == NULL) goto Quit;

            /*
             * Attempt to load the DOS kernel into memory.
             * The segment where to load the DOS kernel is defined
             * by the DOS BIOS and is found in DI:0000 .
             */
            Success = FileLoadByHandle(hDosKernel,
                                       REAL_TO_PHYS(TO_LINEAR(getDI(), 0x0000)),
                                       ulDosKernelSize,
                                       &ulDosKernelSize);

            DPRINT1("Windows NT DOS loading %s at 0x%04X:0x%04X, size 0x%x ; GetLastError() = %u\n",
                    (Success ? "succeeded" : "failed"),
                    getDI(), 0x0000,
                    ulDosKernelSize,
                    GetLastError());

            /* Close the DOS kernel file */
            FileClose(hDosKernel);

Quit:
            if (!Success)
            {
                /* We failed everything, stop the VDM */
                EmulatorTerminate();
            }

            break;
        }

        default:
        {

            DPRINT1("Unknown DOS System BOP Function: 0x%02X\n", FuncNum);
            // setCF(1); // Disable, otherwise we enter an infinite loop
            break;
        }
    }
}
示例#3
0
文件: emulator.c 项目: staring/RosFE
static VOID
DumpMemoryRaw(HANDLE hFile)
{
    PVOID  Buffer;
    SIZE_T Size;

    /* Dump the VM memory */
    SetFilePointer(hFile, 0, NULL, FILE_BEGIN);
    Buffer = REAL_TO_PHYS(NULL);
    Size   = MAX_ADDRESS - (ULONG_PTR)(NULL);
    WriteFile(hFile, Buffer, Size, &Size, NULL);
}
示例#4
0
文件: dem.c 项目: hackbunny/reactos
BOOLEAN DosInitialize(IN LPCSTR DosKernelFileName)
{
    /* Register the DOS BOPs */
    RegisterBop(BOP_DOS, DosSystemBop        );
    RegisterBop(BOP_CMD, DosCmdInterpreterBop);

    if (DosKernelFileName)
    {
        BOOLEAN Success;
        HANDLE  hDosBios;
        ULONG   ulDosBiosSize = 0;

        /* Open the DOS BIOS file */
        hDosBios = FileOpen(DosKernelFileName, &ulDosBiosSize);

        /* If we failed, bail out */
        if (hDosBios == NULL) return FALSE;

        /* Attempt to load the DOS BIOS into memory */
        Success = FileLoadByHandle(hDosBios,
                                   REAL_TO_PHYS(TO_LINEAR(0x0070, 0x0000)),
                                   ulDosBiosSize,
                                   &ulDosBiosSize);

        DPRINT1("DOS BIOS loading %s at 0x%04X:0x%04X, size 0x%x ; GetLastError() = %u\n",
                (Success ? "succeeded" : "failed"),
                0x0070, 0x0000,
                ulDosBiosSize,
                GetLastError());

        /* Close the DOS BIOS file */
        FileClose(hDosBios);

        if (Success)
        {
            /* Position execution pointers and return */
            setCS(0x0070);
            setIP(0x0000);
        }

        return Success;
    }
    else
    {
        BOOLEAN Result;

        Result  = DosBIOSInitialize();
        // Result &= DosKRNLInitialize();

        return Result;
    }
}
示例#5
0
文件: emulator.c 项目: staring/RosFE
static VOID
DumpMemoryTxt(HANDLE hFile)
{
#define LINE_SIZE   75 + 2
    ULONG  i;
    PBYTE  Ptr1, Ptr2;
    CHAR   LineBuffer[LINE_SIZE];
    PCHAR  Line;
    SIZE_T LineSize;

    /* Dump the VM memory */
    SetFilePointer(hFile, 0, NULL, FILE_BEGIN);
    Ptr1 = Ptr2 = REAL_TO_PHYS(NULL);
    while (MAX_ADDRESS - (ULONG_PTR)PHYS_TO_REAL(Ptr1) > 0)
    {
        Ptr1 = Ptr2;
        Line = LineBuffer;

        /* Print the address */
        Line += snprintf(Line, LINE_SIZE + LineBuffer - Line, "%08x ", PHYS_TO_REAL(Ptr1));

        /* Print up to 16 bytes... */

        /* ... in hexadecimal form first... */
        i = 0;
        while (i++ <= 0x0F && (MAX_ADDRESS - (ULONG_PTR)PHYS_TO_REAL(Ptr1) > 0))
        {
            Line += snprintf(Line, LINE_SIZE + LineBuffer - Line, " %02x", *Ptr1);
            ++Ptr1;
        }

        /* ... align with spaces if needed... */
        RtlFillMemory(Line, 0x0F + 4 - i, ' ');
        Line += 0x0F + 4 - i;

        /* ... then in character form. */
        i = 0;
        while (i++ <= 0x0F && (MAX_ADDRESS - (ULONG_PTR)PHYS_TO_REAL(Ptr2) > 0))
        {
            *Line++ = ((*Ptr2 >= 0x20 && *Ptr2 <= 0x7E) || (*Ptr2 >= 0x80 && *Ptr2 < 0xFF) ? *Ptr2 : '.');
            ++Ptr2;
        }

        /* Newline */
        *Line++ = '\r';
        *Line++ = '\n';

        /* Finally write the line to the file */
        LineSize = Line - LineBuffer;
        WriteFile(hFile, LineBuffer, LineSize, &LineSize, NULL);
    }
}
示例#6
0
文件: dem.c 项目: GYGit/reactos
static VOID DemLoadNTDOSKernel(VOID)
{
    BOOLEAN Success = FALSE;
    LPCSTR  DosKernelFileName = "ntdos.sys";
    HANDLE  hDosKernel;
    ULONG   ulDosKernelSize = 0;

    DPRINT1("You are loading Windows NT DOS!\n");

    /* Open the DOS kernel file */
    hDosKernel = FileOpen(DosKernelFileName, &ulDosKernelSize);
    if (hDosKernel == NULL) goto Quit;

    /*
     * Attempt to load the DOS kernel into memory.
     * The segment where to load the DOS kernel is defined
     * by the DOS BIOS and is found in DI:0000 .
     */
    Success = FileLoadByHandle(hDosKernel,
                               REAL_TO_PHYS(TO_LINEAR(getDI(), 0x0000)),
                               ulDosKernelSize,
                               &ulDosKernelSize);

    DPRINT1("Windows NT DOS file '%s' loading %s at %04X:%04X, size 0x%X (Error: %u).\n",
            DosKernelFileName,
            (Success ? "succeeded" : "failed"),
            getDI(), 0x0000,
            ulDosKernelSize,
            GetLastError());

    /* Close the DOS kernel file */
    FileClose(hDosKernel);

Quit:
    if (!Success)
    {
        /* We failed everything, stop the VDM */
        BiosDisplayMessage("Windows NT DOS kernel file '%s' loading failed (Error: %u). The VDM will shut down.\n",
                           DosKernelFileName, GetLastError());
        EmulatorTerminate();
        return;
    }
}
示例#7
0
文件: dem.c 项目: GYGit/reactos
static VOID WINAPI DosInitialize(LPWORD Stack)
{
    /* Get the DOS BIOS file name (NULL-terminated) */
    // FIXME: Isn't it possible to use some DS:SI instead??
    LPCSTR DosBiosFileName = (LPCSTR)SEG_OFF_TO_PTR(getCS(), getIP());
    setIP(getIP() + strlen(DosBiosFileName) + 1); // Skip it

    DPRINT("DosInitialize('%s')\n", DosBiosFileName);

    /*
     * We succeeded, deregister the DOS Loading BOP
     * so that no app will be able to call us back.
     */
    RegisterBop(BOP_LOAD_DOS, NULL);

    /* Register the DOS BOPs */
    RegisterBop(BOP_DOS, DosSystemBop        );
    RegisterBop(BOP_CMD, DosCmdInterpreterBop);

    if (DosBiosFileName[0] != '\0')
    {
        BOOLEAN Success = FALSE;
        HANDLE  hDosBios;
        ULONG   ulDosBiosSize = 0;

        /* Open the DOS BIOS file */
        hDosBios = FileOpen(DosBiosFileName, &ulDosBiosSize);
        if (hDosBios == NULL) goto Quit;

        /* Attempt to load the DOS BIOS into memory */
        Success = FileLoadByHandle(hDosBios,
                                   REAL_TO_PHYS(TO_LINEAR(0x0070, 0x0000)),
                                   ulDosBiosSize,
                                   &ulDosBiosSize);

        DPRINT1("DOS BIOS file '%s' loading %s at %04X:%04X, size 0x%X (Error: %u).\n",
                DosBiosFileName,
                (Success ? "succeeded" : "failed"),
                0x0070, 0x0000,
                ulDosBiosSize,
                GetLastError());

        /* Close the DOS BIOS file */
        FileClose(hDosBios);

Quit:
        if (!Success)
        {
            BiosDisplayMessage("DOS BIOS file '%s' loading failed (Error: %u). The VDM will shut down.\n",
                               DosBiosFileName, GetLastError());
            return;
        }
    }
    else
    {
        /* Load the 16-bit startup code for DOS32 and register its Starting BOP */
        RtlCopyMemory(SEG_OFF_TO_PTR(0x0070, 0x0000), Startup, sizeof(Startup));

        // This is the equivalent of BOP_LOAD_DOS, function 0x11 "Load the DOS kernel"
        // for the Windows NT DOS.
        RegisterBop(BOP_START_DOS, DosStart);
    }

    /* Position execution pointers for DOS startup and return */
    setCS(0x0070);
    setIP(0x0000);
}
示例#8
0
文件: himem.c 项目: GYGit/reactos
static VOID WINAPI XmsBopProcedure(LPWORD Stack)
{
    switch (getAH())
    {
        /* Get XMS Version */
        case 0x00:
        {
            setAX(0x0300); /*    XMS version 3.00 */
            setBX(0x0301); /* Driver version 3.01 */
            setDX(0x0001); /* HMA present */
            break;
        }

        /* Request HMA */
        case 0x01:
        {
            /* Check whether HMA is already reserved */
            if (IsHmaReserved)
            {
                /* It is, bail out */
                setAX(0x0000);
                setBL(XMS_STATUS_HMA_IN_USE);
                break;
            }

            // NOTE: We implicitely suppose that we always have HMA.
            // If not, we should fail there with the XMS_STATUS_HMA_DOES_NOT_EXIST
            // error code.

            /* Check whether the requested size is above the minimal allowed one */
            if (getDX() < HmaMinSize)
            {
                /* It is not, bail out */
                setAX(0x0000);
                setBL(XMS_STATUS_HMA_MIN_SIZE);
                break;
            }

            /* Reserve it */
            IsHmaReserved = TRUE;
            setAX(0x0001);
            setBL(XMS_STATUS_SUCCESS);
            break;
        }

        /* Release HMA */
        case 0x02:
        {
            /* Check whether HMA was reserved */
            if (!IsHmaReserved)
            {
                /* It was not, bail out */
                setAX(0x0000);
                setBL(XMS_STATUS_HMA_NOT_ALLOCATED);
                break;
            }

            /* Release it */
            IsHmaReserved = FALSE;
            setAX(0x0001);
            setBL(XMS_STATUS_SUCCESS);
            break;
        }

        /* Global Enable A20 */
        case 0x03:
        {
            /* Enable A20 if needed */
            if (!IsA20Enabled)
            {
                XmsLocalEnableA20();
                if (getAX() != 0x0001)
                {
                    /* XmsLocalEnableA20 failed and already set AX and BL to their correct values */
                    break;
                }

                IsA20Enabled = TRUE;
            }

            setAX(0x0001); /* Line successfully enabled */
            setBL(XMS_STATUS_SUCCESS);
            break;
        }

        /* Global Disable A20 */
        case 0x04:
        {
            UCHAR Result = XMS_STATUS_SUCCESS;

            /* Disable A20 if needed */
            if (IsA20Enabled)
            {
                XmsLocalDisableA20();
                if (getAX() != 0x0001)
                {
                    /* XmsLocalDisableA20 failed and already set AX and BL to their correct values */
                    break;
                }

                IsA20Enabled = FALSE;
                Result = getBL();
            }

            setAX(0x0001); /* Line successfully disabled */
            setBL(Result);
            break;
        }

        /* Local Enable A20 */
        case 0x05:
        {
            /* This call sets AX and BL to their correct values */
            XmsLocalEnableA20();
            break;
        }

        /* Local Disable A20 */
        case 0x06:
        {
            /* This call sets AX and BL to their correct values */
            XmsLocalDisableA20();
            break;
        }

        /* Query A20 State */
        case 0x07:
        {
            setAX(EmulatorGetA20());
            setBL(XMS_STATUS_SUCCESS);
            break;
        }

        /* Query Free Extended Memory */
        case 0x08:
        {
            setAX(XmsGetLargestFreeBlock());
            setDX(FreeBlocks);

            if (FreeBlocks > 0)
                setBL(XMS_STATUS_SUCCESS);
            else
                setBL(XMS_STATUS_OUT_OF_MEMORY);

            break;
        }

        /* Allocate Extended Memory Block */
        case 0x09:
        {
            WORD Handle;
            UCHAR Result = XmsAlloc(getDX(), &Handle);

            if (Result == XMS_STATUS_SUCCESS)
            {
                setAX(1);
                setDX(Handle);
            }
            else
            {
                setAX(0);
                setBL(Result);
            }

            break;
        }

        /* Free Extended Memory Block */
        case 0x0A:
        {
            UCHAR Result = XmsFree(getDX());

            setAX(Result == XMS_STATUS_SUCCESS);
            setBL(Result);
            break;
        }

        /* Move Extended Memory Block */
        case 0x0B:
        {
            PVOID SourceAddress, DestAddress;
            PXMS_COPY_DATA CopyData = (PXMS_COPY_DATA)SEG_OFF_TO_PTR(getDS(), getSI());
            PXMS_HANDLE HandleEntry;

            if (CopyData->SourceHandle)
            {
                HandleEntry = GetHandleRecord(CopyData->SourceHandle);
                if (!ValidateHandle(HandleEntry))
                {
                    setAX(0);
                    setBL(XMS_STATUS_BAD_SRC_HANDLE);
                    break;
                }

                if (CopyData->SourceOffset >= HandleEntry->Size * XMS_BLOCK_SIZE)
                {
                    setAX(0);
                    setBL(XMS_STATUS_BAD_SRC_OFFSET);
                }

                SourceAddress = (PVOID)REAL_TO_PHYS(HandleEntry->Address + CopyData->SourceOffset);
            }
            else
            {
                /* The offset is actually a 16-bit segment:offset pointer */
                SourceAddress = FAR_POINTER(CopyData->SourceOffset);
            }

            if (CopyData->DestHandle)
            {
                HandleEntry = GetHandleRecord(CopyData->DestHandle);
                if (!ValidateHandle(HandleEntry))
                {
                    setAX(0);
                    setBL(XMS_STATUS_BAD_DEST_HANDLE);
                    break;
                }

                if (CopyData->DestOffset >= HandleEntry->Size * XMS_BLOCK_SIZE)
                {
                    setAX(0);
                    setBL(XMS_STATUS_BAD_DEST_OFFSET);
                }

                DestAddress = (PVOID)REAL_TO_PHYS(HandleEntry->Address + CopyData->DestOffset);
            }
            else
            {
                /* The offset is actually a 16-bit segment:offset pointer */
                DestAddress = FAR_POINTER(CopyData->DestOffset);
            }

            /* Perform the move */
            RtlMoveMemory(DestAddress, SourceAddress, CopyData->Count);

            setAX(1);
            setBL(XMS_STATUS_SUCCESS);
            break;
        }

        /* Lock Extended Memory Block */
        case 0x0C:
        {
            DWORD Address;
            UCHAR Result = XmsLock(getDX(), &Address);

            if (Result == XMS_STATUS_SUCCESS)
            {
                setAX(1);

                /* Store the LINEAR address in DX:BX */
                setDX(HIWORD(Address));
                setBX(LOWORD(Address));
            }
            else
            {
                setAX(0);
                setBL(Result);
            }

            break;
        }

        /* Unlock Extended Memory Block */
        case 0x0D:
        {
            UCHAR Result = XmsUnlock(getDX());

            setAX(Result == XMS_STATUS_SUCCESS);
            setBL(Result);
            break;
        }

        /* Get Handle Information */
        case 0x0E:
        {
            PXMS_HANDLE HandleEntry = GetHandleRecord(getDX());
            UINT i;
            UCHAR Handles = 0;

            if (!ValidateHandle(HandleEntry))
            {
                setAX(0);
                setBL(XMS_STATUS_INVALID_HANDLE);
                break;
            }

            for (i = 0; i < XMS_MAX_HANDLES; i++)
            {
                if (HandleTable[i].Handle == 0) Handles++;
            }

            setAX(1);
            setBH(HandleEntry->LockCount);
            setBL(Handles);
            setDX(HandleEntry->Size);
            break;
        }

        /* Reallocate Extended Memory Block */
        case 0x0F:
        {
            UCHAR Result = XmsRealloc(getDX(), getBX());

            setAX(Result == XMS_STATUS_SUCCESS);
            setBL(Result);
            break;
        }

        /* Request UMB */
        case 0x10:
        {
            BOOLEAN Result;
            USHORT Segment = 0x0000; /* No preferred segment  */
            USHORT Size = getDX();   /* Size is in paragraphs */

            Result = UmaDescReserve(&Segment, &Size);
            if (Result)
                setBX(Segment);
            else
                setBL(Size > 0 ? XMS_STATUS_SMALLER_UMB : XMS_STATUS_OUT_OF_UMBS);

            setDX(Size);
            setAX(Result);
            break;
        }

        /* Release UMB */
        case 0x11:
        {
            BOOLEAN Result;
            USHORT Segment = getDX();

            Result = UmaDescRelease(Segment);
            if (!Result)
                setBL(XMS_STATUS_INVALID_UMB);

            setAX(Result);
            break;
        }

        /* Reallocate UMB */
        case 0x12:
        {
            BOOLEAN Result;
            USHORT Segment = getDX();
            USHORT Size = getBX(); /* Size is in paragraphs */

            Result = UmaDescReallocate(Segment, &Size);
            if (!Result)
            {
                if (Size > 0)
                {
                    setBL(XMS_STATUS_SMALLER_UMB);
                    setDX(Size);
                }
                else
                {
                    setBL(XMS_STATUS_INVALID_UMB);
                }
            }

            setAX(Result);
            break;
        }

        default:
        {
            DPRINT1("XMS command AH = 0x%02X NOT IMPLEMENTED\n", getAH());
            setBL(XMS_STATUS_NOT_IMPLEMENTED);
        }
    }
}
示例#9
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;
}
示例#10
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;
}
示例#11
0
文件: dem.c 项目: staring/RosFE
static VOID WINAPI DosInitialize(LPWORD Stack)
{
    BOOLEAN Success = FALSE;

    /* Get the DOS kernel file name (NULL-terminated) */
    // FIXME: Isn't it possible to use some DS:SI instead??
    LPCSTR DosKernelFileName = (LPCSTR)SEG_OFF_TO_PTR(getCS(), getIP());
    setIP(getIP() + strlen(DosKernelFileName) + 1); // Skip it

    DPRINT("DosInitialize('%s')\n", DosKernelFileName);

    /* Register the DOS BOPs */
    RegisterBop(BOP_DOS, DosSystemBop        );
    RegisterBop(BOP_CMD, DosCmdInterpreterBop);

    if (DosKernelFileName && DosKernelFileName[0] != '\0')
    {
        HANDLE  hDosBios;
        ULONG   ulDosBiosSize = 0;

        /* Open the DOS BIOS file */
        hDosBios = FileOpen(DosKernelFileName, &ulDosBiosSize);

        /* If we failed, bail out */
        if (hDosBios == NULL) goto QuitCustom;

        /* Attempt to load the DOS BIOS into memory */
        Success = FileLoadByHandle(hDosBios,
                                   REAL_TO_PHYS(TO_LINEAR(0x0070, 0x0000)),
                                   ulDosBiosSize,
                                   &ulDosBiosSize);

        DPRINT1("DOS BIOS loading %s at %04X:%04X, size 0x%X ; GetLastError() = %u\n",
                (Success ? "succeeded" : "failed"),
                0x0070, 0x0000,
                ulDosBiosSize,
                GetLastError());

        /* Close the DOS BIOS file */
        FileClose(hDosBios);

        if (!Success) goto QuitCustom;

        /* Position execution pointers and return */
        setCS(0x0070);
        setIP(0x0000);

        /* Return control */
QuitCustom:
        if (!Success)
            DisplayMessage(L"Custom DOS '%S' loading failed, what to do??", DosKernelFileName);
    }
    else
    {
        Success = DosBIOSInitialize();
        // Success &= DosKRNLInitialize();

        if (!Success) goto Quit32;

        /* Write the "bootsector" */
        RtlCopyMemory(SEG_OFF_TO_PTR(0x0070, 0x0000), Startup, sizeof(Startup));

        /* Register the DOS Starting BOP */
        RegisterBop(BOP_START_DOS, DosStart);

        /* Position execution pointers and return */
        setCS(0x0070);
        setIP(0x0000);

        /* Return control */
Quit32:
        if (!Success)
            DisplayMessage(L"DOS32 loading failed, what to do??");
    }

    if (Success)
    {
        /*
         * We succeeded, deregister the DOS Loading BOP
         * so that no app will be able to call us back.
         */
        RegisterBop(BOP_LOAD_DOS, NULL);
    }
}