Author: aandrejevic
Date: Sun Apr 26 18:09:57 2015
New Revision: 67444
URL:
http://svn.reactos.org/svn/reactos?rev=67444&view=rev
Log:
[NTVDM]
Implement INT 21h, AH = 52h (Get List of Lists - SYSVARS).
Rewrite the SFT code to keep the SFT in guest memory.
Implement the NUL device driver.
Added:
trunk/reactos/subsystems/mvdm/ntvdm/dos/dos32krnl/dosfiles.h (with props)
trunk/reactos/subsystems/mvdm/ntvdm/dos/dos32krnl/handle.c (with props)
trunk/reactos/subsystems/mvdm/ntvdm/dos/dos32krnl/handle.h (with props)
Modified:
trunk/reactos/subsystems/mvdm/ntvdm/CMakeLists.txt
trunk/reactos/subsystems/mvdm/ntvdm/dos/dos32krnl/bios.c
trunk/reactos/subsystems/mvdm/ntvdm/dos/dos32krnl/device.c
trunk/reactos/subsystems/mvdm/ntvdm/dos/dos32krnl/device.h
trunk/reactos/subsystems/mvdm/ntvdm/dos/dos32krnl/dos.c
trunk/reactos/subsystems/mvdm/ntvdm/dos/dos32krnl/dos.h
trunk/reactos/subsystems/mvdm/ntvdm/dos/dos32krnl/dosfiles.c
Modified: trunk/reactos/subsystems/mvdm/ntvdm/CMakeLists.txt
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/subsystems/mvdm/ntvdm/CMak…
==============================================================================
--- trunk/reactos/subsystems/mvdm/ntvdm/CMakeLists.txt [iso-8859-1] (original)
+++ trunk/reactos/subsystems/mvdm/ntvdm/CMakeLists.txt [iso-8859-1] Sun Apr 26 18:09:57
2015
@@ -33,6 +33,7 @@
dos/dos32krnl/dos.c
dos/dos32krnl/dosfiles.c
dos/dos32krnl/emsdrv.c
+ dos/dos32krnl/handle.c
dos/dos32krnl/himem.c
dos/dos32krnl/memory.c
dos/mouse32.c
Modified: trunk/reactos/subsystems/mvdm/ntvdm/dos/dos32krnl/bios.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/subsystems/mvdm/ntvdm/dos/…
==============================================================================
--- trunk/reactos/subsystems/mvdm/ntvdm/dos/dos32krnl/bios.c [iso-8859-1] (original)
+++ trunk/reactos/subsystems/mvdm/ntvdm/dos/dos32krnl/bios.c [iso-8859-1] Sun Apr 26
18:09:57 2015
@@ -15,6 +15,7 @@
#include "int32.h"
#include "dos.h"
+#include "dosfiles.h"
#include "memory.h"
#include "bios/bios.h"
@@ -56,43 +57,33 @@
BOOLEAN DosCheckInput(VOID)
{
- PDOS_SFT_ENTRY SftEntry = DosGetSftEntry(DOS_INPUT_HANDLE);
-
- if (SftEntry == NULL)
+ PDOS_FILE_DESCRIPTOR Descriptor = DosGetHandleFileDescriptor(DOS_INPUT_HANDLE);
+
+ if (Descriptor == NULL)
{
/* Invalid handle */
DosLastError = ERROR_INVALID_HANDLE; // ERROR_FILE_NOT_FOUND
return FALSE;
}
- switch (SftEntry->Type)
- {
- case DOS_SFT_ENTRY_WIN32:
- {
- DWORD FileSizeHigh;
- DWORD FileSize = GetFileSize(SftEntry->Handle, &FileSizeHigh);
- LONG LocationHigh = 0;
- DWORD Location = SetFilePointer(SftEntry->Handle, 0, &LocationHigh,
FILE_CURRENT);
-
- return ((Location != FileSize) || (LocationHigh != FileSizeHigh));
- }
-
- case DOS_SFT_ENTRY_DEVICE:
- {
- WORD Result;
-
- if (!SftEntry->DeviceNode->InputStatusRoutine) return FALSE;
-
- Result =
SftEntry->DeviceNode->InputStatusRoutine(SftEntry->DeviceNode);
- return !(Result & DOS_DEVSTAT_BUSY);
- }
-
- default:
- {
- /* Invalid handle */
- DosLastError = ERROR_INVALID_HANDLE;
- return FALSE;
- }
+ if (Descriptor->DeviceInfo & (1 << 7))
+ {
+ WORD Result;
+ PDOS_DEVICE_NODE Node = DosGetDriverNode(Descriptor->DevicePointer);
+
+ if (!Node->InputStatusRoutine) return FALSE;
+
+ Result = Node->InputStatusRoutine(Node);
+ return !(Result & DOS_DEVSTAT_BUSY);
+ }
+ else
+ {
+ DWORD FileSizeHigh;
+ DWORD FileSize = GetFileSize(Descriptor->Win32Handle, &FileSizeHigh);
+ LONG LocationHigh = 0;
+ DWORD Location = SetFilePointer(Descriptor->Win32Handle, 0, &LocationHigh,
FILE_CURRENT);
+
+ return ((Location != FileSize) || (LocationHigh != FileSizeHigh));
}
}
Modified: trunk/reactos/subsystems/mvdm/ntvdm/dos/dos32krnl/device.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/subsystems/mvdm/ntvdm/dos/…
==============================================================================
--- trunk/reactos/subsystems/mvdm/ntvdm/dos/dos32krnl/device.c [iso-8859-1] (original)
+++ trunk/reactos/subsystems/mvdm/ntvdm/dos/dos32krnl/device.c [iso-8859-1] Sun Apr 26
18:09:57 2015
@@ -40,7 +40,6 @@
C_ASSERT((sizeof(StrategyRoutine) + sizeof(InterruptRoutine)) == DEVICE_CODE_SIZE);
static LIST_ENTRY DeviceList = { &DeviceList, &DeviceList };
-static DWORD FirstDriver = 0xFFFFFFFF;
static PDOS_REQUEST_HEADER DeviceRequest;
/* PRIVATE FUNCTIONS **********************************************************/
@@ -213,17 +212,9 @@
static VOID DosAddDriver(DWORD Driver)
{
- PDOS_DRIVER LastDriver;
-
- if (LOWORD(FirstDriver) == 0xFFFF)
- {
- /* This is the first driver */
- FirstDriver = Driver;
- return;
- }
-
- /* The list isn't empty, so find the last driver in it */
- LastDriver = (PDOS_DRIVER)FAR_POINTER(FirstDriver);
+ PDOS_DRIVER LastDriver = &SysVars->NullDevice;
+
+ /* Find the last driver in the list */
while (LOWORD(LastDriver->Link) != 0xFFFF)
{
LastDriver = (PDOS_DRIVER)FAR_POINTER(LastDriver->Link);
@@ -231,18 +222,25 @@
/* Add the new driver to the list */
LastDriver->Link = Driver;
+ LastDriver = (PDOS_DRIVER)FAR_POINTER(Driver);
+
+ if (LastDriver->DeviceAttributes & DOS_DEVATTR_CLOCK)
+ {
+ /* Update the active CLOCK driver */
+ SysVars->ActiveClock = Driver;
+ }
+
+ if (LastDriver->DeviceAttributes
+ & (DOS_DEVATTR_STDIN | DOS_DEVATTR_STDOUT | DOS_DEVATTR_CON))
+ {
+ /* Update the active CON driver */
+ SysVars->ActiveCon = Driver;
+ }
}
static VOID DosRemoveDriver(DWORD Driver)
{
- DWORD CurrentDriver = FirstDriver;
-
- if (FirstDriver == Driver)
- {
- /* Update the first driver */
- FirstDriver = ((PDOS_DRIVER)FAR_POINTER(FirstDriver))->Link;
- return;
- }
+ DWORD CurrentDriver = MAKELONG(FIELD_OFFSET(DOS_SYSVARS, NullDevice),
DOS_DATA_SEGMENT);
while (LOWORD(CurrentDriver) != 0xFFFF)
{
@@ -289,48 +287,54 @@
/* PUBLIC FUNCTIONS ***********************************************************/
+PDOS_DEVICE_NODE DosGetDriverNode(DWORD Driver)
+{
+ PLIST_ENTRY i;
+ PDOS_DEVICE_NODE Node;
+
+ for (i = DeviceList.Flink; i != &DeviceList; i = i->Flink)
+ {
+ Node = CONTAINING_RECORD(i, DOS_DEVICE_NODE, Entry);
+ if (Node->Driver == Driver) break;
+ }
+
+ if (i == &DeviceList)
+ {
+ DPRINT1("The driver at %04X:%04X has no associated device node. "
+ "Installing automagically.\n",
+ HIWORD(Driver),
+ LOWORD(Driver));
+
+ /* Create the device node */
+ Node = DosCreateDeviceNode(Driver);
+ Node->IoctlReadRoutine = DosDriverDispatchIoctlRead;
+ Node->ReadRoutine = DosDriverDispatchRead;
+ Node->PeekRoutine = DosDriverDispatchPeek;
+ Node->InputStatusRoutine = DosDriverDispatchInputStatus;
+ Node->FlushInputRoutine = DosDriverDispatchFlushInput;
+ Node->IoctlWriteRoutine = DosDriverDispatchIoctlWrite;
+ Node->WriteRoutine = DosDriverDispatchWrite;
+ Node->OutputStatusRoutine = DosDriverDispatchOutputStatus;
+ Node->FlushOutputRoutine = DosDriverDispatchFlushOutput;
+ Node->OpenRoutine = DosDriverDispatchOpen;
+ Node->CloseRoutine = DosDriverDispatchClose;
+ Node->OutputUntilBusyRoutine = DosDriverDispatchOutputUntilBusy;
+ }
+
+ return Node;
+}
+
PDOS_DEVICE_NODE DosGetDevice(LPCSTR DeviceName)
{
- PLIST_ENTRY i;
- DWORD CurrentDriver = FirstDriver;
+ DWORD CurrentDriver = MAKELONG(FIELD_OFFSET(DOS_SYSVARS, NullDevice),
DOS_DATA_SEGMENT);
ANSI_STRING DeviceNameString;
RtlInitAnsiString(&DeviceNameString, DeviceName);
while (LOWORD(CurrentDriver) != 0xFFFF)
{
- PDOS_DEVICE_NODE Node;
+ PDOS_DEVICE_NODE Node = DosGetDriverNode(CurrentDriver);
PDOS_DRIVER DriverHeader = (PDOS_DRIVER)FAR_POINTER(CurrentDriver);
-
- /* Get the device node for this driver */
- for (i = DeviceList.Flink; i != &DeviceList; i = i->Flink)
- {
- Node = CONTAINING_RECORD(i, DOS_DEVICE_NODE, Entry);
- if (Node->Driver == CurrentDriver) break;
- }
-
- if (i == &DeviceList)
- {
- DPRINT1("The driver at %04X:%04X has no associated device node. "
- "Installing automagically.\n",
- HIWORD(CurrentDriver),
- LOWORD(CurrentDriver));
-
- /* Create the device node */
- Node = DosCreateDeviceNode(CurrentDriver);
- Node->IoctlReadRoutine = DosDriverDispatchIoctlRead;
- Node->ReadRoutine = DosDriverDispatchRead;
- Node->PeekRoutine = DosDriverDispatchPeek;
- Node->InputStatusRoutine = DosDriverDispatchInputStatus;
- Node->FlushInputRoutine = DosDriverDispatchFlushInput;
- Node->IoctlWriteRoutine = DosDriverDispatchIoctlWrite;
- Node->WriteRoutine = DosDriverDispatchWrite;
- Node->OutputStatusRoutine = DosDriverDispatchOutputStatus;
- Node->FlushOutputRoutine = DosDriverDispatchFlushOutput;
- Node->OpenRoutine = DosDriverDispatchOpen;
- Node->CloseRoutine = DosDriverDispatchClose;
- Node->OutputUntilBusyRoutine = DosDriverDispatchOutputUntilBusy;
- }
if (RtlEqualString(&Node->Name, &DeviceNameString, TRUE)) return
Node;
CurrentDriver = DriverHeader->Link;
Modified: trunk/reactos/subsystems/mvdm/ntvdm/dos/dos32krnl/device.h
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/subsystems/mvdm/ntvdm/dos/…
==============================================================================
--- trunk/reactos/subsystems/mvdm/ntvdm/dos/dos32krnl/device.h [iso-8859-1] (original)
+++ trunk/reactos/subsystems/mvdm/ntvdm/dos/dos32krnl/device.h [iso-8859-1] Sun Apr 26
18:09:57 2015
@@ -194,6 +194,7 @@
/* FUNCTIONS ******************************************************************/
+PDOS_DEVICE_NODE DosGetDriverNode(DWORD Driver);
PDOS_DEVICE_NODE DosGetDevice(LPCSTR DeviceName);
PDOS_DEVICE_NODE DosCreateDevice(WORD Attributes, PCHAR DeviceName);
PDOS_DEVICE_NODE DosCreateDeviceEx
Modified: trunk/reactos/subsystems/mvdm/ntvdm/dos/dos32krnl/dos.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/subsystems/mvdm/ntvdm/dos/…
==============================================================================
--- trunk/reactos/subsystems/mvdm/ntvdm/dos/dos32krnl/dos.c [iso-8859-1] (original)
+++ trunk/reactos/subsystems/mvdm/ntvdm/dos/dos32krnl/dos.c [iso-8859-1] Sun Apr 26
18:09:57 2015
@@ -19,6 +19,8 @@
#include "dos.h"
#include "dos/dem.h"
#include "device.h"
+#include "handle.h"
+#include "dosfiles.h"
#include "memory.h"
#include "himem.h"
@@ -39,11 +41,12 @@
/*static*/ BYTE CurrentDrive;
static CHAR LastDrive = 'E';
static CHAR CurrentDirectories[NUM_DRIVES][DOS_DIR_LENGTH];
-static DOS_SFT_ENTRY DosSystemFileTable[DOS_SFT_SIZE];
static WORD DosErrorLevel = 0x0000;
static PBYTE InDos;
/* PUBLIC VARIABLES ***********************************************************/
+
+PDOS_SYSVARS SysVars;
/* Echo state for INT 21h, AH = 01h and AH = 3Fh */
BOOLEAN DoEcho = FALSE;
@@ -120,456 +123,6 @@
return DestSegment;
}
-/* Taken from base/shell/cmd/console.c */
-static BOOL IsConsoleHandle(HANDLE hHandle)
-{
- DWORD dwMode;
-
- /* Check whether the handle may be that of a console... */
- if ((GetFileType(hHandle) & FILE_TYPE_CHAR) == 0) return FALSE;
-
- /*
- * It may be. Perform another test... The idea comes from the
- * MSDN description of the WriteConsole API:
- *
- * "WriteConsole fails if it is used with a standard handle
- * that is redirected to a file. If an application processes
- * multilingual output that can be redirected, determine whether
- * the output handle is a console handle (one method is to call
- * the GetConsoleMode function and check whether it succeeds).
- * If the handle is a console handle, call WriteConsole. If the
- * handle is not a console handle, the output is redirected and
- * you should call WriteFile to perform the I/O."
- */
- return GetConsoleMode(hHandle, &dwMode);
-}
-
-static inline PDOS_SFT_ENTRY DosFindFreeSftEntry(VOID)
-{
- UINT i;
-
- for (i = 0; i < DOS_SFT_SIZE; i++)
- {
- if (DosSystemFileTable[i].Type == DOS_SFT_ENTRY_NONE)
- {
- return &DosSystemFileTable[i];
- }
- }
-
- return NULL;
-}
-
-static inline PDOS_SFT_ENTRY DosFindWin32SftEntry(HANDLE Handle)
-{
- UINT i;
-
- for (i = 0; i < DOS_SFT_SIZE; i++)
- {
- if (DosSystemFileTable[i].Type == DOS_SFT_ENTRY_WIN32
- && DosSystemFileTable[i].Handle == Handle)
- {
- return &DosSystemFileTable[i];
- }
- }
-
- return NULL;
-}
-
-static inline PDOS_SFT_ENTRY DosFindDeviceSftEntry(PDOS_DEVICE_NODE Device)
-{
- UINT i;
-
- for (i = 0; i < DOS_SFT_SIZE; i++)
- {
- if (DosSystemFileTable[i].Type == DOS_SFT_ENTRY_DEVICE
- && DosSystemFileTable[i].DeviceNode == Device)
- {
- return &DosSystemFileTable[i];
- }
- }
-
- return NULL;
-}
-
-WORD DosOpenHandle(HANDLE Handle)
-{
- WORD DosHandle;
- PDOS_PSP PspBlock;
- LPBYTE HandleTable;
- PDOS_SFT_ENTRY SftEntry;
-
- /* The system PSP has no handle table */
- if (CurrentPsp == SYSTEM_PSP) return INVALID_DOS_HANDLE;
-
- /* Get a pointer to the handle table */
- PspBlock = SEGMENT_TO_PSP(CurrentPsp);
- HandleTable = (LPBYTE)FAR_POINTER(PspBlock->HandleTablePtr);
-
- /* Find a free entry in the JFT */
- for (DosHandle = 0; DosHandle < PspBlock->HandleTableSize; DosHandle++)
- {
- if (HandleTable[DosHandle] == 0xFF) break;
- }
-
- /* If there are no free entries, fail */
- if (DosHandle == PspBlock->HandleTableSize) return INVALID_DOS_HANDLE;
-
- /* Check if the handle is already in the SFT */
- SftEntry = DosFindWin32SftEntry(Handle);
- if (SftEntry != NULL)
- {
- /* Already in the table, reference it */
- SftEntry->RefCount++;
- goto Finish;
- }
-
- /* Find a free SFT entry to use */
- SftEntry = DosFindFreeSftEntry();
- if (SftEntry == NULL)
- {
- /* The SFT is full */
- return INVALID_DOS_HANDLE;
- }
-
- /* Initialize the empty table entry */
- SftEntry->Type = DOS_SFT_ENTRY_WIN32;
- SftEntry->Handle = Handle;
- SftEntry->RefCount = 1;
-
-Finish:
-
- /* Set the JFT entry to that SFT index */
- HandleTable[DosHandle] = ARRAY_INDEX(SftEntry, DosSystemFileTable);
-
- /* Return the new handle */
- return DosHandle;
-}
-
-WORD DosOpenDevice(PDOS_DEVICE_NODE Device)
-{
- WORD DosHandle;
- PDOS_PSP PspBlock;
- LPBYTE HandleTable;
- PDOS_SFT_ENTRY SftEntry;
-
- DPRINT("DosOpenDevice(\"%Z\")\n", &Device->Name);
-
- /* The system PSP has no handle table */
- if (CurrentPsp == SYSTEM_PSP) return INVALID_DOS_HANDLE;
-
- /* Get a pointer to the handle table */
- PspBlock = SEGMENT_TO_PSP(CurrentPsp);
- HandleTable = (LPBYTE)FAR_POINTER(PspBlock->HandleTablePtr);
-
- /* Find a free entry in the JFT */
- for (DosHandle = 0; DosHandle < PspBlock->HandleTableSize; DosHandle++)
- {
- if (HandleTable[DosHandle] == 0xFF) break;
- }
-
- /* If there are no free entries, fail */
- if (DosHandle == PspBlock->HandleTableSize) return INVALID_DOS_HANDLE;
-
- /* Check if the device is already in the SFT */
- SftEntry = DosFindDeviceSftEntry(Device);
- if (SftEntry != NULL)
- {
- /* Already in the table, reference it */
- SftEntry->RefCount++;
- goto Finish;
- }
-
- /* Find a free SFT entry to use */
- SftEntry = DosFindFreeSftEntry();
- if (SftEntry == NULL)
- {
- /* The SFT is full */
- return INVALID_DOS_HANDLE;
- }
-
- /* Initialize the empty table entry */
- SftEntry->Type = DOS_SFT_ENTRY_DEVICE;
- SftEntry->DeviceNode = Device;
- SftEntry->RefCount = 1;
-
-Finish:
-
- /* Call the open routine, if it exists */
- if (Device->OpenRoutine) Device->OpenRoutine(Device);
-
- /* Set the JFT entry to that SFT index */
- HandleTable[DosHandle] = ARRAY_INDEX(SftEntry, DosSystemFileTable);
-
- /* Return the new handle */
- return DosHandle;
-}
-
-static VOID DosCopyHandleTable(LPBYTE DestinationTable)
-{
- UINT i;
- PDOS_PSP PspBlock;
- LPBYTE SourceTable;
-
- /* Clear the table first */
- for (i = 0; i < 20; i++) DestinationTable[i] = 0xFF;
-
- /* Check if this is the initial process */
- if (CurrentPsp == SYSTEM_PSP)
- {
- PDOS_SFT_ENTRY SftEntry;
- HANDLE StandardHandles[3];
- PDOS_DEVICE_NODE Con = DosGetDevice("CON");
- ASSERT(Con != NULL);
-
- /* Get the native standard handles */
- StandardHandles[0] = GetStdHandle(STD_INPUT_HANDLE);
- StandardHandles[1] = GetStdHandle(STD_OUTPUT_HANDLE);
- StandardHandles[2] = GetStdHandle(STD_ERROR_HANDLE);
-
- for (i = 0; i < 3; i++)
- {
- /* Find the corresponding SFT entry */
- if (IsConsoleHandle(StandardHandles[i]))
- {
- SftEntry = DosFindDeviceSftEntry(Con);
- }
- else
- {
- SftEntry = DosFindWin32SftEntry(StandardHandles[i]);
- }
-
- if (SftEntry == NULL)
- {
- /* Create a new SFT entry for it */
- SftEntry = DosFindFreeSftEntry();
- if (SftEntry == NULL)
- {
- DPRINT1("Cannot create standard handle %d, the SFT is
full!\n", i);
- continue;
- }
-
- SftEntry->RefCount = 0;
-
- if (IsConsoleHandle(StandardHandles[i]))
- {
- SftEntry->Type = DOS_SFT_ENTRY_DEVICE;
- SftEntry->DeviceNode = Con;
-
- /* Call the open routine */
- if (Con->OpenRoutine) Con->OpenRoutine(Con);
- }
- else
- {
- SftEntry->Type = DOS_SFT_ENTRY_WIN32;
- SftEntry->Handle = StandardHandles[i];
- }
- }
-
- SftEntry->RefCount++;
- DestinationTable[i] = ARRAY_INDEX(SftEntry, DosSystemFileTable);
- }
- }
- else
- {
- /* Get the parent PSP block and handle table */
- PspBlock = SEGMENT_TO_PSP(CurrentPsp);
- SourceTable = (LPBYTE)FAR_POINTER(PspBlock->HandleTablePtr);
-
- /* Copy the first 20 handles into the new table */
- for (i = 0; i < DEFAULT_JFT_SIZE; i++)
- {
- DestinationTable[i] = SourceTable[i];
-
- /* Increase the reference count */
- DosSystemFileTable[SourceTable[i]].RefCount++;
- }
- }
-}
-
-static BOOLEAN DosResizeHandleTable(WORD NewSize)
-{
- PDOS_PSP PspBlock;
- LPBYTE HandleTable;
- WORD Segment;
-
- /* Get the PSP block */
- PspBlock = SEGMENT_TO_PSP(CurrentPsp);
-
- if (NewSize == PspBlock->HandleTableSize)
- {
- /* No change */
- return TRUE;
- }
-
- if (PspBlock->HandleTableSize > DEFAULT_JFT_SIZE)
- {
- /* Get the segment of the current table */
- Segment = (LOWORD(PspBlock->HandleTablePtr) >> 4) +
HIWORD(PspBlock->HandleTablePtr);
-
- if (NewSize <= DEFAULT_JFT_SIZE)
- {
- /* Get the current handle table */
- HandleTable = FAR_POINTER(PspBlock->HandleTablePtr);
-
- /* Copy it to the PSP */
- RtlCopyMemory(PspBlock->HandleTable, HandleTable, NewSize);
-
- /* Free the memory */
- DosFreeMemory(Segment);
-
- /* Update the handle table pointer and size */
- PspBlock->HandleTableSize = NewSize;
- PspBlock->HandleTablePtr = MAKELONG(0x18, CurrentPsp);
- }
- else
- {
- /* Resize the memory */
- if (!DosResizeMemory(Segment, NewSize, NULL))
- {
- /* Unable to resize, try allocating it somewhere else */
- Segment = DosAllocateMemory(NewSize, NULL);
- if (Segment == 0) return FALSE;
-
- /* Get the new handle table */
- HandleTable = SEG_OFF_TO_PTR(Segment, 0);
-
- /* Copy the handles to the new table */
- RtlCopyMemory(HandleTable,
- FAR_POINTER(PspBlock->HandleTablePtr),
- PspBlock->HandleTableSize);
-
- /* Update the handle table pointer */
- PspBlock->HandleTablePtr = MAKELONG(0, Segment);
- }
-
- /* Update the handle table size */
- PspBlock->HandleTableSize = NewSize;
- }
- }
- else if (NewSize > DEFAULT_JFT_SIZE)
- {
- Segment = DosAllocateMemory(NewSize, NULL);
- if (Segment == 0) return FALSE;
-
- /* Get the new handle table */
- HandleTable = SEG_OFF_TO_PTR(Segment, 0);
-
- /* Copy the handles from the PSP to the new table */
- RtlCopyMemory(HandleTable,
- FAR_POINTER(PspBlock->HandleTablePtr),
- PspBlock->HandleTableSize);
-
- /* Update the handle table pointer and size */
- PspBlock->HandleTableSize = NewSize;
- PspBlock->HandleTablePtr = MAKELONG(0, Segment);
- }
-
- return TRUE;
-}
-
-static BOOLEAN DosCloseHandle(WORD DosHandle)
-{
- PDOS_PSP PspBlock;
- LPBYTE HandleTable;
- PDOS_SFT_ENTRY SftEntry;
-
- DPRINT("DosCloseHandle: DosHandle 0x%04X\n", DosHandle);
-
- /* The system PSP has no handle table */
- if (CurrentPsp == SYSTEM_PSP) return FALSE;
-
- /* Get a pointer to the handle table */
- PspBlock = SEGMENT_TO_PSP(CurrentPsp);
- HandleTable = (LPBYTE)FAR_POINTER(PspBlock->HandleTablePtr);
-
- /* Make sure the handle is open */
- if (HandleTable[DosHandle] == 0xFF) return FALSE;
-
- /* Make sure the SFT entry is valid */
- SftEntry = &DosSystemFileTable[HandleTable[DosHandle]];
- if (SftEntry->Type == DOS_SFT_ENTRY_NONE) return FALSE;
-
- /* Decrement the reference count of the SFT entry */
- SftEntry->RefCount--;
-
- /* Check if the reference count fell to zero */
- if (!SftEntry->RefCount)
- {
- switch (SftEntry->Type)
- {
- case DOS_SFT_ENTRY_WIN32:
- {
- /* Close the win32 handle and clear it */
- CloseHandle(SftEntry->Handle);
-
- break;
- }
-
- case DOS_SFT_ENTRY_DEVICE:
- {
- PDOS_DEVICE_NODE Node = SftEntry->DeviceNode;
-
- /* Call the close routine, if it exists */
- if (Node->CloseRoutine)
SftEntry->DeviceNode->CloseRoutine(SftEntry->DeviceNode);
-
- break;
- }
-
- default:
- {
- /* Shouldn't happen */
- ASSERT(FALSE);
- }
- }
-
- /* Invalidate the SFT entry */
- SftEntry->Type = DOS_SFT_ENTRY_NONE;
- }
-
- /* Clear the entry in the JFT */
- HandleTable[DosHandle] = 0xFF;
-
- return TRUE;
-}
-
-static BOOLEAN DosDuplicateHandle(WORD OldHandle, WORD NewHandle)
-{
- BYTE SftIndex;
- PDOS_PSP PspBlock;
- LPBYTE HandleTable;
-
- DPRINT("DosDuplicateHandle: OldHandle 0x%04X, NewHandle 0x%04X\n",
- OldHandle,
- NewHandle);
-
- /* The system PSP has no handle table */
- if (CurrentPsp == SYSTEM_PSP) return FALSE;
-
- /* Get a pointer to the handle table */
- PspBlock = SEGMENT_TO_PSP(CurrentPsp);
- HandleTable = (LPBYTE)FAR_POINTER(PspBlock->HandleTablePtr);
-
- /* Make sure the old handle is open */
- if (HandleTable[OldHandle] == 0xFF) return FALSE;
-
- /* Check if the new handle is open */
- if (HandleTable[NewHandle] != 0xFF)
- {
- /* Close it */
- DosCloseHandle(NewHandle);
- }
-
- /* Increment the reference count of the SFT entry */
- SftIndex = HandleTable[OldHandle];
- DosSystemFileTable[SftIndex].RefCount++;
-
- /* Make the new handle point to that SFT entry */
- HandleTable[NewHandle] = SftIndex;
-
- /* Return success */
- return TRUE;
-}
-
static BOOLEAN DosChangeDrive(BYTE Drive)
{
WCHAR DirectoryPath[DOS_CMDLINE_LENGTH];
@@ -674,25 +227,6 @@
}
/* PUBLIC FUNCTIONS ***********************************************************/
-
-PDOS_SFT_ENTRY DosGetSftEntry(WORD DosHandle)
-{
- PDOS_PSP PspBlock;
- LPBYTE HandleTable;
-
- /* The system PSP has no handle table */
- if (CurrentPsp == SYSTEM_PSP) return NULL;
-
- /* Get a pointer to the handle table */
- PspBlock = SEGMENT_TO_PSP(CurrentPsp);
- HandleTable = (LPBYTE)FAR_POINTER(PspBlock->HandleTablePtr);
-
- /* Make sure the handle is open */
- if (HandleTable[DosHandle] == 0xFF) return NULL;
-
- /* Return a pointer to the SFT entry */
- return &DosSystemFileTable[HandleTable[DosHandle]];
-}
VOID DosInitializePsp(WORD PspSegment,
LPCSTR CommandLine,
@@ -1279,110 +813,6 @@
LOWORD(PspBlock->TerminateAddress));
}
-BOOLEAN DosHandleIoctl(BYTE ControlCode, WORD FileHandle)
-{
- PDOS_SFT_ENTRY SftEntry = DosGetSftEntry(FileHandle);
- PDOS_DEVICE_NODE Node = NULL;
-
- /* Make sure it exists */
- if (!SftEntry)
- {
- DosLastError = ERROR_FILE_NOT_FOUND;
- return FALSE;
- }
-
- if (SftEntry->Type == DOS_SFT_ENTRY_DEVICE) Node = SftEntry->DeviceNode;
-
- switch (ControlCode)
- {
- /* Get Device Information */
- case 0x00:
- {
- WORD InfoWord = 0;
-
- /*
- * See Ralf Brown:
http://www.ctyme.com/intr/rb-2820.htm
- * for a list of possible flags.
- */
-
- if (Node)
- {
- /* Return the device attributes with bit 7 set */
- InfoWord = Node->DeviceAttributes | (1 << 7);
- }
-
- setDX(InfoWord);
- return TRUE;
- }
-
- /* Set Device Information */
- case 0x01:
- {
- // TODO: NOT IMPLEMENTED
- UNIMPLEMENTED;
-
- return FALSE;
- }
-
- /* Read From Device I/O Control Channel */
- case 0x02:
- {
- WORD Length = getCX();
-
- if (Node == NULL || !(Node->DeviceAttributes & DOS_DEVATTR_IOCTL))
- {
- DosLastError = ERROR_INVALID_FUNCTION;
- return FALSE;
- }
-
- /* Do nothing if there is no IOCTL routine */
- if (!Node->IoctlReadRoutine)
- {
- setAX(0);
- return TRUE;
- }
-
- Node->IoctlReadRoutine(Node, MAKELONG(getDX(), getDS()), &Length);
-
- setAX(Length);
- return TRUE;
- }
-
- /* Write To Device I/O Control Channel */
- case 0x03:
- {
- WORD Length = getCX();
-
- if (Node == NULL || !(Node->DeviceAttributes & DOS_DEVATTR_IOCTL))
- {
- DosLastError = ERROR_INVALID_FUNCTION;
- return FALSE;
- }
-
- /* Do nothing if there is no IOCTL routine */
- if (!Node->IoctlWriteRoutine)
- {
- setAX(0);
- return TRUE;
- }
-
- Node->IoctlWriteRoutine(Node, MAKELONG(getDX(), getDS()), &Length);
-
- setAX(Length);
- return TRUE;
- }
-
- /* Unsupported control code */
- default:
- {
- DPRINT1("Unsupported IOCTL: 0x%02X\n", ControlCode);
-
- DosLastError = ERROR_INVALID_PARAMETER;
- return FALSE;
- }
- }
-}
-
VOID WINAPI DosInt20h(LPWORD Stack)
{
/* This is the exit interrupt */
@@ -2196,20 +1626,8 @@
case 0x3D:
{
WORD FileHandle;
- WORD ErrorCode;
LPCSTR FileName = (LPCSTR)SEG_OFF_TO_PTR(getDS(), getDX());
- PDOS_DEVICE_NODE Device = DosGetDevice(FileName);
-
- if (Device)
- {
- FileHandle = DosOpenDevice(Device);
- ErrorCode = (FileHandle != INVALID_DOS_HANDLE)
- ? ERROR_SUCCESS : ERROR_TOO_MANY_OPEN_FILES;
- }
- else
- {
- ErrorCode = DosOpenFile(&FileHandle, FileName, getAL());
- }
+ WORD ErrorCode = DosOpenFile(&FileHandle, FileName, getAL());
if (ErrorCode == ERROR_SUCCESS)
{
@@ -2391,9 +1809,12 @@
/* IOCTL */
case 0x44:
{
- if (DosHandleIoctl(getAL(), getBX()))
- {
- Stack[STACK_FLAGS] &= ~EMULATOR_FLAG_CF;
+ WORD Length = getCX();
+
+ if (DosDeviceIoControl(getBX(), getAL(), MAKELONG(getDX(), getDS()),
&Length))
+ {
+ Stack[STACK_FLAGS] &= ~EMULATOR_FLAG_CF;
+ setAX(Length);
}
else
{
@@ -2407,57 +1828,26 @@
/* Duplicate Handle */
case 0x45:
{
- WORD NewHandle;
- PDOS_SFT_ENTRY SftEntry = DosGetSftEntry(getBX());
-
- if (SftEntry == NULL || SftEntry->Type == DOS_SFT_ENTRY_NONE)
- {
- /* The handle is invalid */
- Stack[STACK_FLAGS] |= EMULATOR_FLAG_CF;
- setAX(ERROR_INVALID_HANDLE);
- break;
- }
-
- /* Open a new handle to the same entry */
- switch (SftEntry->Type)
- {
- case DOS_SFT_ENTRY_WIN32:
- {
- NewHandle = DosOpenHandle(SftEntry->Handle);
- break;
- }
-
- case DOS_SFT_ENTRY_DEVICE:
- {
- NewHandle = DosOpenDevice(SftEntry->DeviceNode);
- break;
- }
-
- default:
- {
- /* Shouldn't happen */
- ASSERT(FALSE);
- }
- }
-
- if (NewHandle == INVALID_DOS_HANDLE)
- {
- /* Too many files open */
- Stack[STACK_FLAGS] |= EMULATOR_FLAG_CF;
- setAX(ERROR_TOO_MANY_OPEN_FILES);
- break;
- }
-
- /* Return the result */
- Stack[STACK_FLAGS] &= ~EMULATOR_FLAG_CF;
- setAX(NewHandle);
+ WORD NewHandle = DosDuplicateHandle(getBX());
+
+ if (NewHandle != INVALID_DOS_HANDLE)
+ {
+ setAX(NewHandle);
+ Stack[STACK_FLAGS] &= ~EMULATOR_FLAG_CF;
+ }
+ else
+ {
+ Stack[STACK_FLAGS] |= EMULATOR_FLAG_CF;
+ setAX(DosLastError);
+ }
+
break;
}
/* Force Duplicate Handle */
case 0x46:
{
- if (DosDuplicateHandle(getBX(), getCX()))
+ if (DosForceDuplicateHandle(getBX(), getCX()))
{
Stack[STACK_FLAGS] &= ~EMULATOR_FLAG_CF;
}
@@ -2686,10 +2076,9 @@
*/
/* Return the DOS "list of lists" in ES:BX */
- setES(0x0000);
- setBX(0x0000);
-
- DPRINT1("INT 21h, AH=52h: This application requires the internal DOS
List of lists (SYSVARS). UNIMPLEMENTED\n");
+ setES(DOS_DATA_SEGMENT);
+ setBX(FIELD_OFFSET(DOS_SYSVARS, FirstDpb));
+
break;
}
@@ -2850,44 +2239,30 @@
/* Lock/Unlock Region of File */
case 0x5C:
{
- PDOS_SFT_ENTRY SftEntry = DosGetSftEntry(getBX());
-
- if (SftEntry == NULL || SftEntry->Type != DOS_SFT_ENTRY_WIN32)
- {
- /* The handle is invalid */
- Stack[STACK_FLAGS] |= EMULATOR_FLAG_CF;
- setAX(ERROR_INVALID_HANDLE);
- break;
- }
-
if (getAL() == 0x00)
{
/* Lock region of file */
- if (LockFile(SftEntry->Handle,
- MAKELONG(getCX(), getDX()), 0,
- MAKELONG(getSI(), getDI()), 0))
+ if (DosLockFile(getBX(), MAKELONG(getCX(), getDX()), MAKELONG(getSI(),
getDI())))
{
Stack[STACK_FLAGS] &= ~EMULATOR_FLAG_CF;
}
else
{
Stack[STACK_FLAGS] |= EMULATOR_FLAG_CF;
- setAX(GetLastError());
+ setAX(DosLastError);
}
}
else if (getAL() == 0x01)
{
/* Unlock region of file */
- if (UnlockFile(SftEntry->Handle,
- MAKELONG(getCX(), getDX()), 0,
- MAKELONG(getSI(), getDI()), 0))
+ if (DosUnlockFile(getBX(), MAKELONG(getCX(), getDX()), MAKELONG(getSI(),
getDI())))
{
Stack[STACK_FLAGS] &= ~EMULATOR_FLAG_CF;
}
else
{
Stack[STACK_FLAGS] |= EMULATOR_FLAG_CF;
- setAX(GetLastError());
+ setAX(DosLastError);
}
}
else
@@ -3109,13 +2484,26 @@
BOOLEAN DosKRNLInitialize(VOID)
{
-
#if 1
UCHAR i;
CHAR CurrentDirectory[MAX_PATH];
CHAR DosDirectory[DOS_DIR_LENGTH];
LPSTR Path;
+ PDOS_SFT Sft;
+
+ const BYTE NullDriverRoutine[] = {
+ /* Strategy routine entry */
+ 0x26, // mov [Request.Status], DOS_DEVSTAT_DONE
+ 0xC7,
+ 0x47,
+ FIELD_OFFSET(DOS_REQUEST_HEADER, Status),
+ LOBYTE(DOS_DEVSTAT_DONE),
+ HIBYTE(DOS_DEVSTAT_DONE),
+
+ /* Interrupt routine entry */
+ 0xCB, // retf
+ };
FILE *Stream;
WCHAR Buffer[256];
@@ -3169,11 +2557,34 @@
fclose(Stream);
}
+ /* Initialize the list of lists */
+ SysVars = (PDOS_SYSVARS)SEG_OFF_TO_PTR(DOS_DATA_SEGMENT, 0);
+ RtlZeroMemory(SysVars, sizeof(DOS_SYSVARS));
+ SysVars->FirstMcb = FIRST_MCB_SEGMENT;
+ SysVars->FirstSft = MAKELONG(MASTER_SFT_OFFSET, DOS_DATA_SEGMENT);
+
+ /* Initialize the NUL device driver */
+ SysVars->NullDevice.Link = 0xFFFFFFFF;
+ SysVars->NullDevice.DeviceAttributes = DOS_DEVATTR_NUL | DOS_DEVATTR_CHARACTER;
+ SysVars->NullDevice.StrategyRoutine = FIELD_OFFSET(DOS_SYSVARS,
NullDriverRoutine);
+ SysVars->NullDevice.InterruptRoutine = SysVars->NullDevice.StrategyRoutine +
6;
+ RtlFillMemory(SysVars->NullDevice.DeviceName,
+ sizeof(SysVars->NullDevice.DeviceName),
+ ' ');
+ RtlCopyMemory(SysVars->NullDevice.DeviceName, "NUL",
strlen("NUL"));
+ RtlCopyMemory(SysVars->NullDriverRoutine,
+ NullDriverRoutine,
+ sizeof(NullDriverRoutine));
+
/* Initialize the SFT */
- for (i = 0; i < DOS_SFT_SIZE; i++)
- {
- DosSystemFileTable[i].Type = DOS_SFT_ENTRY_NONE;
- DosSystemFileTable[i].RefCount = 0;
+ Sft = (PDOS_SFT)FAR_POINTER(SysVars->FirstSft);
+ Sft->Link = 0xFFFFFFFF;
+ Sft->NumDescriptors = DOS_SFT_SIZE;
+
+ for (i = 0; i < Sft->NumDescriptors; i++)
+ {
+ /* Clear the file descriptor entry */
+ RtlZeroMemory(&Sft->FileDescriptors[i], sizeof(DOS_FILE_DESCRIPTOR));
}
#endif
Modified: trunk/reactos/subsystems/mvdm/ntvdm/dos/dos32krnl/dos.h
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/subsystems/mvdm/ntvdm/dos/…
==============================================================================
--- trunk/reactos/subsystems/mvdm/ntvdm/dos/dos32krnl/dos.h [iso-8859-1] (original)
+++ trunk/reactos/subsystems/mvdm/ntvdm/dos/dos32krnl/dos.h [iso-8859-1] Sun Apr 26
18:09:57 2015
@@ -30,6 +30,8 @@
#define USER_MEMORY_SIZE (0x9FFE - FIRST_MCB_SEGMENT)
#define SYSTEM_PSP 0x08
#define SYSTEM_ENV_BLOCK 0x800
+#define DOS_DATA_SEGMENT 0xA0
+#define MASTER_SFT_OFFSET 0x100
#define INVALID_DOS_HANDLE 0xFFFF
#define DOS_INPUT_HANDLE 0
@@ -48,7 +50,6 @@
#define NUM_DRIVES ('Z' - 'A' + 1)
#define DOS_CHAR_ATTRIBUTE 0x07
#define DOS_PROGRAM_NAME_TAG 0x0001
-#define DEFAULT_JFT_SIZE 20
/* 16 MB of EMS memory */
#define EMS_TOTAL_PAGES 1024
@@ -59,25 +60,6 @@
DOS_LOAD_ONLY = 0x01,
DOS_LOAD_OVERLAY = 0x03
} DOS_EXEC_TYPE;
-
-typedef enum
-{
- DOS_SFT_ENTRY_NONE,
- DOS_SFT_ENTRY_WIN32,
- DOS_SFT_ENTRY_DEVICE
-} DOS_SFT_ENTRY_TYPE;
-
-typedef struct _DOS_SFT_ENTRY
-{
- DOS_SFT_ENTRY_TYPE Type;
- WORD RefCount;
-
- union
- {
- HANDLE Handle;
- PDOS_DEVICE_NODE DeviceNode;
- };
-} DOS_SFT_ENTRY, *PDOS_SFT_ENTRY;
#pragma pack(push, 1)
@@ -95,6 +77,30 @@
BYTE BlockRecord;
BYTE RecordNumber[3];
} DOS_FCB, *PDOS_FCB;
+
+typedef struct _DOS_SYSVARS
+{
+ DWORD OemHandler;
+ WORD Int21hReturn;
+ WORD ShareRetryCount;
+ WORD ShareRetryDelay;
+ DWORD DiskBuffer;
+ WORD UnreadConInput;
+ WORD FirstMcb;
+
+ /* This is where the SYSVARS really start */
+ DWORD FirstDpb;
+ DWORD FirstSft;
+ DWORD ActiveClock;
+ DWORD ActiveCon;
+ BYTE Reserved0[6];
+ DWORD CurrentDirs;
+ BYTE Reserved1[6];
+ BYTE NumBlockDevices;
+ BYTE NumLocalDrives;
+ DOS_DRIVER NullDevice;
+ BYTE NullDriverRoutine[7];
+} DOS_SYSVARS, *PDOS_SYSVARS;
typedef struct _DOS_PSP
{
@@ -128,15 +134,6 @@
CHAR Buffer[ANYSIZE_ARRAY];
} DOS_INPUT_BUFFER, *PDOS_INPUT_BUFFER;
-typedef struct _DOS_DRIVER_HEADER
-{
- DWORD NextDriver;
- WORD Attributes;
- WORD StrategyEntry;
- WORD InterruptEntry;
- CHAR DeviceName[8];
-} DOS_DRIVER_HEADER, *PDOS_DRIVER_HEADER;
-
typedef struct _DOS_FIND_FILE_BLOCK
{
CHAR DriveLetter;
@@ -181,6 +178,7 @@
extern BOOLEAN DoEcho;
extern WORD CurrentPsp;
extern WORD DosLastError;
+extern PDOS_SYSVARS SysVars;
/* FUNCTIONS ******************************************************************/
@@ -208,35 +206,6 @@
* DOS Kernel Functions
* See dos.c
*/
-WORD DosOpenHandle(HANDLE Handle);
-PDOS_SFT_ENTRY DosGetSftEntry(WORD DosHandle);
-
-WORD DosCreateFileEx(LPWORD Handle,
- LPWORD CreationStatus,
- LPCSTR FilePath,
- BYTE AccessShareModes,
- WORD CreateActionFlags,
- WORD Attributes);
-WORD DosCreateFile(LPWORD Handle,
- LPCSTR FilePath,
- DWORD CreationDisposition,
- WORD Attributes);
-WORD DosOpenFile(LPWORD Handle,
- LPCSTR FilePath,
- BYTE AccessShareModes);
-WORD DosReadFile(WORD FileHandle,
- DWORD Buffer,
- WORD Count,
- LPWORD BytesRead);
-WORD DosWriteFile(WORD FileHandle,
- DWORD Buffer,
- WORD Count,
- LPWORD BytesWritten);
-WORD DosSeekFile(WORD FileHandle,
- LONG Offset,
- BYTE Origin,
- LPDWORD NewOffset);
-BOOL DosFlushFileBuffers(WORD FileHandle);
VOID DosInitializePsp(
WORD PspSegment,
Modified: trunk/reactos/subsystems/mvdm/ntvdm/dos/dos32krnl/dosfiles.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/subsystems/mvdm/ntvdm/dos/…
==============================================================================
--- trunk/reactos/subsystems/mvdm/ntvdm/dos/dos32krnl/dosfiles.c [iso-8859-1] (original)
+++ trunk/reactos/subsystems/mvdm/ntvdm/dos/dos32krnl/dosfiles.c [iso-8859-1] Sun Apr 26
18:09:57 2015
@@ -17,10 +17,124 @@
#include "dos.h"
#include "dos/dem.h"
+#include "dosfiles.h"
+#include "handle.h"
#include "bios/bios.h"
/* PUBLIC FUNCTIONS ***********************************************************/
+
+BYTE DosFindFreeDescriptor(VOID)
+{
+ UINT i;
+ BYTE Count = 0;
+ DWORD CurrentSft = SysVars->FirstSft;
+
+ while (LOWORD(CurrentSft) != 0xFFFF)
+ {
+ PDOS_SFT Sft = (PDOS_SFT)FAR_POINTER(CurrentSft);
+
+ for (i = 0; i < Sft->NumDescriptors; i++)
+ {
+ if (Sft->FileDescriptors[i].RefCount == 0) return Count;
+ Count++;
+ }
+
+ /* Go to the next table */
+ CurrentSft = Sft->Link;
+ }
+
+ /* Invalid ID */
+ return 0xFF;
+}
+
+BYTE DosFindWin32Descriptor(HANDLE Win32Handle)
+{
+ UINT i;
+ BYTE Count = 0;
+ DWORD CurrentSft = SysVars->FirstSft;
+
+ while (LOWORD(CurrentSft) != 0xFFFF)
+ {
+ PDOS_SFT Sft = (PDOS_SFT)FAR_POINTER(CurrentSft);
+
+ for (i = 0; i < Sft->NumDescriptors; i++)
+ {
+ if ((Sft->FileDescriptors[i].RefCount > 0)
+ && !(Sft->FileDescriptors[i].DeviceInfo & (1 << 7))
+ && (Sft->FileDescriptors[i].Win32Handle == Win32Handle))
+ {
+ return Count;
+ }
+
+ Count++;
+ }
+
+ /* Go to the next table */
+ CurrentSft = Sft->Link;
+ }
+
+ /* Invalid ID */
+ return 0xFF;
+}
+
+BYTE DosFindDeviceDescriptor(DWORD DevicePointer)
+{
+ UINT i;
+ BYTE Count = 0;
+ DWORD CurrentSft = SysVars->FirstSft;
+
+ while (LOWORD(CurrentSft) != 0xFFFF)
+ {
+ PDOS_SFT Sft = (PDOS_SFT)FAR_POINTER(CurrentSft);
+
+ for (i = 0; i < Sft->NumDescriptors; i++)
+ {
+ if ((Sft->FileDescriptors[i].RefCount > 0)
+ && (Sft->FileDescriptors[i].DeviceInfo & (1 << 7))
+ && (Sft->FileDescriptors[i].DevicePointer == DevicePointer))
+ {
+ return Count;
+ }
+
+ Count++;
+ }
+
+ /* Go to the next table */
+ CurrentSft = Sft->Link;
+ }
+
+ /* Invalid ID */
+ return 0xFF;
+}
+
+PDOS_FILE_DESCRIPTOR DosGetFileDescriptor(BYTE Id)
+{
+ DWORD CurrentSft = SysVars->FirstSft;
+
+ while (LOWORD(CurrentSft) != 0xFFFF)
+ {
+ PDOS_SFT Sft = (PDOS_SFT)FAR_POINTER(CurrentSft);
+
+ /* Return it if it's in this table */
+ if (Id <= Sft->NumDescriptors) return &Sft->FileDescriptors[Id];
+
+ /* Go to the next table */
+ Id -= Sft->NumDescriptors;
+ CurrentSft = Sft->Link;
+ }
+
+ /* Invalid ID */
+ return NULL;
+}
+
+PDOS_FILE_DESCRIPTOR DosGetHandleFileDescriptor(WORD DosHandle)
+{
+ BYTE DescriptorId = DosQueryHandle(DosHandle);
+ if (DescriptorId == 0xFF) return NULL;
+
+ return DosGetFileDescriptor(DescriptorId);
+}
WORD DosCreateFileEx(LPWORD Handle,
LPWORD CreationStatus,
@@ -37,6 +151,8 @@
DWORD CreationDisposition = 0;
BOOL InheritableFile = FALSE;
SECURITY_ATTRIBUTES SecurityAttributes;
+ BYTE DescriptorId;
+ PDOS_FILE_DESCRIPTOR Descriptor;
DPRINT1("DosCreateFileEx: FilePath \"%s\", AccessShareModes 0x%04X,
CreateActionFlags 0x%04X, Attributes 0x%04X\n",
FilePath, AccessShareModes, CreateActionFlags, Attributes);
@@ -228,8 +344,26 @@
}
}
+ DescriptorId = DosFindFreeDescriptor();
+ if (DescriptorId == 0xFF)
+ {
+ /* Close the file and return the error code */
+ CloseHandle(FileHandle);
+ return ERROR_TOO_MANY_OPEN_FILES;
+ }
+
+ /* Set up the new descriptor */
+ Descriptor = DosGetFileDescriptor(DescriptorId);
+ RtlZeroMemory(Descriptor, sizeof(*Descriptor));
+
+ Descriptor->OpenMode = AccessShareModes;
+ Descriptor->Attributes = LOBYTE(GetFileAttributesA(FilePath));
+ Descriptor->Size = GetFileSize(FileHandle, NULL);
+ Descriptor->OwnerPsp = CurrentPsp;
+ Descriptor->Win32Handle = FileHandle;
+
/* Open the DOS handle */
- DosHandle = DosOpenHandle(FileHandle);
+ DosHandle = DosOpenHandle(DescriptorId);
if (DosHandle == INVALID_DOS_HANDLE)
{
/* Close the file and return the error code */
@@ -249,6 +383,8 @@
{
HANDLE FileHandle;
WORD DosHandle;
+ BYTE DescriptorId;
+ PDOS_FILE_DESCRIPTOR Descriptor;
DPRINT("DosCreateFile: FilePath \"%s\", CreationDisposition 0x%04X,
Attributes 0x%04X\n",
FilePath, CreationDisposition, Attributes);
@@ -267,15 +403,32 @@
return (WORD)GetLastError();
}
- /* Open the DOS handle */
- DosHandle = DosOpenHandle(FileHandle);
- if (DosHandle == INVALID_DOS_HANDLE)
+ DescriptorId = DosFindFreeDescriptor();
+ if (DescriptorId == 0xFF)
{
/* Close the file and return the error code */
CloseHandle(FileHandle);
return ERROR_TOO_MANY_OPEN_FILES;
}
+ /* Set up the new descriptor */
+ Descriptor = DosGetFileDescriptor(DescriptorId);
+ RtlZeroMemory(Descriptor, sizeof(*Descriptor));
+
+ Descriptor->Attributes = LOBYTE(GetFileAttributesA(FilePath));
+ Descriptor->Size = GetFileSize(FileHandle, NULL);
+ Descriptor->OwnerPsp = CurrentPsp;
+ Descriptor->Win32Handle = FileHandle;
+
+ /* Open the DOS handle */
+ DosHandle = DosOpenHandle(DescriptorId);
+ if (DosHandle == INVALID_DOS_HANDLE)
+ {
+ /* Close the file and return the error code */
+ CloseHandle(FileHandle);
+ return ERROR_TOO_MANY_OPEN_FILES;
+ }
+
/* It was successful */
*Handle = DosHandle;
return ERROR_SUCCESS;
@@ -285,12 +438,11 @@
LPCSTR FilePath,
BYTE AccessShareModes)
{
- HANDLE FileHandle;
- ACCESS_MASK AccessMode = 0;
- DWORD ShareMode = 0;
- BOOL InheritableFile = FALSE;
- SECURITY_ATTRIBUTES SecurityAttributes;
+ HANDLE FileHandle = NULL;
+ PDOS_DEVICE_NODE Node;
WORD DosHandle;
+ BYTE DescriptorId;
+ PDOS_FILE_DESCRIPTOR Descriptor;
DPRINT("DosOpenFile: FilePath \"%s\", AccessShareModes
0x%04X\n",
FilePath, AccessShareModes);
@@ -300,86 +452,125 @@
// explains what those AccessShareModes are (see the uStyle flag).
//
- /* Parse the access mode */
- switch (AccessShareModes & 0x03)
- {
- /* Read-only */
- case 0:
- AccessMode = GENERIC_READ;
- break;
-
- /* Write only */
- case 1:
- AccessMode = GENERIC_WRITE;
- break;
-
- /* Read and write */
- case 2:
- AccessMode = GENERIC_READ | GENERIC_WRITE;
- break;
-
- /* Invalid */
- default:
- return ERROR_INVALID_PARAMETER;
- }
-
- /* Parse the share mode */
- switch ((AccessShareModes >> 4) & 0x07)
- {
- /* Compatibility mode */
- case 0:
- ShareMode = FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE;
- break;
-
- /* No sharing "DenyAll" */
- case 1:
- ShareMode = 0;
- break;
-
- /* No write share "DenyWrite" */
- case 2:
- ShareMode = FILE_SHARE_READ;
- break;
-
- /* No read share "DenyRead" */
- case 3:
- ShareMode = FILE_SHARE_WRITE;
- break;
-
- /* Full share "DenyNone" */
- case 4:
- ShareMode = FILE_SHARE_READ | FILE_SHARE_WRITE;
- break;
-
- /* Invalid */
- default:
- return ERROR_INVALID_PARAMETER;
- }
-
- /* Check for inheritance */
- InheritableFile = ((AccessShareModes & 0x80) == 0);
-
- /* Assign default security attributes to the file, and set the inheritance flag */
- SecurityAttributes.nLength = sizeof(SecurityAttributes);
- SecurityAttributes.lpSecurityDescriptor = NULL;
- SecurityAttributes.bInheritHandle = InheritableFile;
-
- /* Open the file */
- FileHandle = CreateFileA(FilePath,
- AccessMode,
- ShareMode,
- &SecurityAttributes,
- OPEN_EXISTING,
- FILE_ATTRIBUTE_NORMAL,
- NULL);
- if (FileHandle == INVALID_HANDLE_VALUE)
- {
- /* Return the error code */
- return (WORD)GetLastError();
+ Node = DosGetDevice(FilePath);
+ if (Node != NULL)
+ {
+ if (Node->OpenRoutine) Node->OpenRoutine(Node);
+ }
+ else
+ {
+ ACCESS_MASK AccessMode = 0;
+ DWORD ShareMode = 0;
+ BOOL InheritableFile = FALSE;
+ SECURITY_ATTRIBUTES SecurityAttributes;
+
+ /* Parse the access mode */
+ switch (AccessShareModes & 0x03)
+ {
+ /* Read-only */
+ case 0:
+ AccessMode = GENERIC_READ;
+ break;
+
+ /* Write only */
+ case 1:
+ AccessMode = GENERIC_WRITE;
+ break;
+
+ /* Read and write */
+ case 2:
+ AccessMode = GENERIC_READ | GENERIC_WRITE;
+ break;
+
+ /* Invalid */
+ default:
+ return ERROR_INVALID_PARAMETER;
+ }
+
+ /* Parse the share mode */
+ switch ((AccessShareModes >> 4) & 0x07)
+ {
+ /* Compatibility mode */
+ case 0:
+ ShareMode = FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE;
+ break;
+
+ /* No sharing "DenyAll" */
+ case 1:
+ ShareMode = 0;
+ break;
+
+ /* No write share "DenyWrite" */
+ case 2:
+ ShareMode = FILE_SHARE_READ;
+ break;
+
+ /* No read share "DenyRead" */
+ case 3:
+ ShareMode = FILE_SHARE_WRITE;
+ break;
+
+ /* Full share "DenyNone" */
+ case 4:
+ ShareMode = FILE_SHARE_READ | FILE_SHARE_WRITE;
+ break;
+
+ /* Invalid */
+ default:
+ return ERROR_INVALID_PARAMETER;
+ }
+
+ /* Check for inheritance */
+ InheritableFile = ((AccessShareModes & 0x80) == 0);
+
+ /* Assign default security attributes to the file, and set the inheritance flag
*/
+ SecurityAttributes.nLength = sizeof(SecurityAttributes);
+ SecurityAttributes.lpSecurityDescriptor = NULL;
+ SecurityAttributes.bInheritHandle = InheritableFile;
+
+ /* Open the file */
+ FileHandle = CreateFileA(FilePath,
+ AccessMode,
+ ShareMode,
+ &SecurityAttributes,
+ OPEN_EXISTING,
+ FILE_ATTRIBUTE_NORMAL,
+ NULL);
+ if (FileHandle == INVALID_HANDLE_VALUE)
+ {
+ /* Return the error code */
+ return (WORD)GetLastError();
+ }
+ }
+
+ DescriptorId = DosFindFreeDescriptor();
+ if (DescriptorId == 0xFF)
+ {
+ /* Close the file and return the error code */
+ CloseHandle(FileHandle);
+ return ERROR_TOO_MANY_OPEN_FILES;
+ }
+
+ /* Set up the new descriptor */
+ Descriptor = DosGetFileDescriptor(DescriptorId);
+ RtlZeroMemory(Descriptor, sizeof(*Descriptor));
+
+ if (Node != NULL)
+ {
+ Descriptor->DevicePointer = Node->Driver;
+ Descriptor->DeviceInfo = Node->DeviceAttributes | (1 << 7);
+ }
+ else
+ {
+ Descriptor->OpenMode = AccessShareModes;
+ Descriptor->Attributes = LOBYTE(GetFileAttributesA(FilePath));
+ Descriptor->Size = GetFileSize(FileHandle, NULL);
+ Descriptor->OwnerPsp = CurrentPsp;
+ Descriptor->Win32Handle = FileHandle;
}
/* Open the DOS handle */
- DosHandle = DosOpenHandle(FileHandle);
+ DosHandle = DosOpenHandle(DescriptorId);
if (DosHandle == INVALID_DOS_HANDLE)
{
/* Close the file and return the error code */
@@ -398,27 +589,39 @@
LPWORD BytesRead)
{
WORD Result = ERROR_SUCCESS;
- PDOS_SFT_ENTRY SftEntry = DosGetSftEntry(FileHandle);
+ PDOS_FILE_DESCRIPTOR Descriptor = DosGetHandleFileDescriptor(FileHandle);
DPRINT("DosReadFile: FileHandle 0x%04X, Count 0x%04X\n", FileHandle,
Count);
- if (SftEntry == NULL)
+ if (Descriptor == NULL)
{
/* Invalid handle */
return ERROR_INVALID_HANDLE;
}
- if (SftEntry->Type == DOS_SFT_ENTRY_WIN32)
+ if (Descriptor->DeviceInfo & (1 << 7))
+ {
+ PDOS_DEVICE_NODE Node = DosGetDriverNode(Descriptor->DevicePointer);
+ if (!Node->ReadRoutine) return ERROR_INVALID_FUNCTION;
+
+ /* Read the device */
+ Node->ReadRoutine(Node, Buffer, &Count);
+ *BytesRead = Count;
+ }
+ else
{
DWORD BytesRead32 = 0;
LPVOID LocalBuffer = RtlAllocateHeap(RtlGetProcessHeap(), 0, Count);
ASSERT(LocalBuffer != NULL);
/* Read the file */
- if (ReadFile(SftEntry->Handle, LocalBuffer, Count, &BytesRead32, NULL))
+ if (ReadFile(Descriptor->Win32Handle, LocalBuffer, Count, &BytesRead32,
NULL))
{
/* Write to the memory */
MemWrite(TO_LINEAR(HIWORD(Buffer), LOWORD(Buffer)), LocalBuffer,
LOWORD(BytesRead32));
+
+ /* Update the position */
+ Descriptor->Position += BytesRead32;
}
else
{
@@ -429,19 +632,6 @@
/* The number of bytes read is always 16-bit */
*BytesRead = LOWORD(BytesRead32);
RtlFreeHeap(RtlGetProcessHeap(), 0, LocalBuffer);
- }
- else if (SftEntry->Type == DOS_SFT_ENTRY_DEVICE)
- {
- if (!SftEntry->DeviceNode->ReadRoutine) return ERROR_INVALID_FUNCTION;
-
- /* Read the device */
- SftEntry->DeviceNode->ReadRoutine(SftEntry->DeviceNode, Buffer,
&Count);
- *BytesRead = Count;
- }
- else
- {
- /* Invalid handle */
- return ERROR_INVALID_HANDLE;
}
/* Return the error code */
@@ -454,17 +644,26 @@
LPWORD BytesWritten)
{
WORD Result = ERROR_SUCCESS;
- PDOS_SFT_ENTRY SftEntry = DosGetSftEntry(FileHandle);
+ PDOS_FILE_DESCRIPTOR Descriptor = DosGetHandleFileDescriptor(FileHandle);
DPRINT("DosWriteFile: FileHandle 0x%04X, Count 0x%04X\n", FileHandle,
Count);
- if (SftEntry == NULL)
+ if (Descriptor == NULL)
{
/* Invalid handle */
return ERROR_INVALID_HANDLE;
}
- if (SftEntry->Type == DOS_SFT_ENTRY_WIN32)
+ if (Descriptor->DeviceInfo & (1 << 7))
+ {
+ PDOS_DEVICE_NODE Node = DosGetDriverNode(Descriptor->DevicePointer);
+ if (!Node->WriteRoutine) return ERROR_INVALID_FUNCTION;
+
+ /* Read the device */
+ Node->WriteRoutine(Node, Buffer, &Count);
+ *BytesWritten = Count;
+ }
+ else
{
DWORD BytesWritten32 = 0;
LPVOID LocalBuffer = RtlAllocateHeap(RtlGetProcessHeap(), 0, Count);
@@ -474,7 +673,13 @@
MemRead(TO_LINEAR(HIWORD(Buffer), LOWORD(Buffer)), LocalBuffer, Count);
/* Write the file */
- if (!WriteFile(SftEntry->Handle, LocalBuffer, Count, &BytesWritten32,
NULL))
+ if (WriteFile(Descriptor->Win32Handle, LocalBuffer, Count,
&BytesWritten32, NULL))
+ {
+ /* Update the position and size */
+ Descriptor->Position += BytesWritten32;
+ if (Descriptor->Position > Descriptor->Size) Descriptor->Size =
Descriptor->Position;
+ }
+ else
{
/* Store the error code */
Result = (WORD)GetLastError();
@@ -483,19 +688,6 @@
/* The number of bytes written is always 16-bit */
*BytesWritten = LOWORD(BytesWritten32);
RtlFreeHeap(RtlGetProcessHeap(), 0, LocalBuffer);
- }
- else if (SftEntry->Type == DOS_SFT_ENTRY_DEVICE)
- {
- if (!SftEntry->DeviceNode->WriteRoutine) return ERROR_INVALID_FUNCTION;
-
- /* Read the device */
- SftEntry->DeviceNode->WriteRoutine(SftEntry->DeviceNode, Buffer,
&Count);
- *BytesWritten = Count;
- }
- else
- {
- /* Invalid handle */
- return ERROR_INVALID_HANDLE;
}
/* Return the error code */
@@ -509,25 +701,20 @@
{
WORD Result = ERROR_SUCCESS;
DWORD FilePointer;
- PDOS_SFT_ENTRY SftEntry = DosGetSftEntry(FileHandle);
+ PDOS_FILE_DESCRIPTOR Descriptor = DosGetHandleFileDescriptor(FileHandle);
DPRINT("DosSeekFile: FileHandle 0x%04X, Offset 0x%08X, Origin 0x%02X\n",
FileHandle,
Offset,
Origin);
- if (SftEntry == NULL)
+ if (Descriptor == NULL)
{
/* Invalid handle */
return ERROR_INVALID_HANDLE;
}
- if (SftEntry->Type == DOS_SFT_ENTRY_NONE)
- {
- /* Invalid handle */
- return ERROR_INVALID_HANDLE;
- }
- else if (SftEntry->Type == DOS_SFT_ENTRY_DEVICE)
+ if (Descriptor->DeviceInfo & (1 << 7))
{
/* For character devices, always return success */
return ERROR_SUCCESS;
@@ -539,7 +726,7 @@
return ERROR_INVALID_FUNCTION;
}
- FilePointer = SetFilePointer(SftEntry->Handle, Offset, NULL, Origin);
+ FilePointer = SetFilePointer(Descriptor->Win32Handle, Offset, NULL, Origin);
/* Check if there's a possibility the operation failed */
if (FilePointer == INVALID_SET_FILE_POINTER)
@@ -554,6 +741,9 @@
return Result;
}
+ /* Update the descriptor */
+ Descriptor->Position = FilePointer;
+
/* Return the file pointer, if requested */
if (NewOffset) *NewOffset = FilePointer;
@@ -563,38 +753,164 @@
BOOL DosFlushFileBuffers(WORD FileHandle)
{
- PDOS_SFT_ENTRY SftEntry = DosGetSftEntry(FileHandle);
-
- if (SftEntry == NULL)
+ PDOS_FILE_DESCRIPTOR Descriptor = DosGetHandleFileDescriptor(FileHandle);
+
+ if (Descriptor == NULL)
{
/* Invalid handle */
- return ERROR_INVALID_HANDLE;
- }
-
- switch (SftEntry->Type)
- {
- case DOS_SFT_ENTRY_WIN32:
- {
- return FlushFileBuffers(SftEntry->Handle);
- }
-
- case DOS_SFT_ENTRY_DEVICE:
- {
- if (SftEntry->DeviceNode->FlushInputRoutine)
- SftEntry->DeviceNode->FlushInputRoutine(SftEntry->DeviceNode);
-
- if (SftEntry->DeviceNode->FlushOutputRoutine)
- SftEntry->DeviceNode->FlushOutputRoutine(SftEntry->DeviceNode);
-
+ DosLastError = ERROR_INVALID_HANDLE;
+ return FALSE;
+ }
+
+ if (Descriptor->DeviceInfo & (1 << 7))
+ {
+ PDOS_DEVICE_NODE Node = DosGetDriverNode(Descriptor->DevicePointer);
+
+ if (Node->FlushInputRoutine) Node->FlushInputRoutine(Node);
+ if (Node->FlushOutputRoutine) Node->FlushOutputRoutine(Node);
+
+ return TRUE;
+ }
+ else
+ {
+ return FlushFileBuffers(Descriptor->Win32Handle);
+ }
+}
+
+BOOLEAN DosLockFile(WORD DosHandle, DWORD Offset, DWORD Size)
+{
+ PDOS_FILE_DESCRIPTOR Descriptor = DosGetHandleFileDescriptor(DosHandle);
+
+ if (Descriptor == NULL)
+ {
+ /* Invalid handle */
+ DosLastError = ERROR_INVALID_HANDLE;
+ return FALSE;
+ }
+
+ /* Always succeed for character devices */
+ if (Descriptor->DeviceInfo & (1 << 7)) return TRUE;
+
+ if (!LockFile(Descriptor->Win32Handle, Offset, 0, Size, 0))
+ {
+ DosLastError = GetLastError();
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+BOOLEAN DosUnlockFile(WORD DosHandle, DWORD Offset, DWORD Size)
+{
+ PDOS_FILE_DESCRIPTOR Descriptor = DosGetHandleFileDescriptor(DosHandle);
+
+ if (Descriptor == NULL)
+ {
+ /* Invalid handle */
+ DosLastError = ERROR_INVALID_HANDLE;
+ return FALSE;
+ }
+
+ /* Always succeed for character devices */
+ if (Descriptor->DeviceInfo & (1 << 7)) return TRUE;
+
+ if (!UnlockFile(Descriptor->Win32Handle, Offset, 0, Size, 0))
+ {
+ DosLastError = GetLastError();
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+BOOLEAN DosDeviceIoControl(WORD FileHandle, BYTE ControlCode, DWORD Buffer, PWORD
Length)
+{
+ PDOS_FILE_DESCRIPTOR Descriptor = DosGetHandleFileDescriptor(FileHandle);
+ PDOS_DEVICE_NODE Node = NULL;
+
+ if (!Descriptor)
+ {
+ DosLastError = ERROR_INVALID_HANDLE;
+ return FALSE;
+ }
+
+ if (Descriptor->DeviceInfo & (1 << 7))
+ {
+ Node = DosGetDriverNode(Descriptor->DevicePointer);
+ }
+
+ switch (ControlCode)
+ {
+ /* Get Device Information */
+ case 0x00:
+ {
+ /*
+ * See Ralf Brown:
http://www.ctyme.com/intr/rb-2820.htm
+ * for a list of possible flags.
+ */
+ setDX(Descriptor->DeviceInfo);
return TRUE;
}
-
+
+ /* Set Device Information */
+ case 0x01:
+ {
+ // TODO: NOT IMPLEMENTED
+ UNIMPLEMENTED;
+
+ return FALSE;
+ }
+
+ /* Read From Device I/O Control Channel */
+ case 0x02:
+ {
+ if (Node == NULL || !(Node->DeviceAttributes & DOS_DEVATTR_IOCTL))
+ {
+ DosLastError = ERROR_INVALID_FUNCTION;
+ return FALSE;
+ }
+
+ /* Do nothing if there is no IOCTL routine */
+ if (!Node->IoctlReadRoutine)
+ {
+ *Length = 0;
+ return TRUE;
+ }
+
+ Node->IoctlReadRoutine(Node, Buffer, Length);
+ return TRUE;
+ }
+
+ /* Write To Device I/O Control Channel */
+ case 0x03:
+ {
+ if (Node == NULL || !(Node->DeviceAttributes & DOS_DEVATTR_IOCTL))
+ {
+ DosLastError = ERROR_INVALID_FUNCTION;
+ return FALSE;
+ }
+
+ /* Do nothing if there is no IOCTL routine */
+ if (!Node->IoctlWriteRoutine)
+ {
+ *Length = 0;
+ return TRUE;
+ }
+
+ Node->IoctlWriteRoutine(Node, Buffer, Length);
+ return TRUE;
+ }
+
+ /* Unsupported control code */
default:
{
- /* Invalid handle */
+ DPRINT1("Unsupported IOCTL: 0x%02X\n", ControlCode);
+
+ DosLastError = ERROR_INVALID_PARAMETER;
return FALSE;
}
}
}
+
/* EOF */
Added: trunk/reactos/subsystems/mvdm/ntvdm/dos/dos32krnl/dosfiles.h
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/subsystems/mvdm/ntvdm/dos/…
==============================================================================
--- trunk/reactos/subsystems/mvdm/ntvdm/dos/dos32krnl/dosfiles.h (added)
+++ trunk/reactos/subsystems/mvdm/ntvdm/dos/dos32krnl/dosfiles.h [iso-8859-1] Sun Apr 26
18:09:57 2015
@@ -0,0 +1,108 @@
+/*
+ * COPYRIGHT: GPL - See COPYING in the top level directory
+ * PROJECT: ReactOS Virtual DOS Machine
+ * FILE: dos/dos32krnl/dosfiles.h
+ * PURPOSE: DOS32 Files Support
+ * PROGRAMMERS: Aleksandar Andrejevic <theflash AT sdf DOT lonestar DOT org>
+ */
+
+/* DEFINES ********************************************************************/
+
+#pragma pack(push, 1)
+
+typedef struct _DOS_FILE_DESCRIPTOR
+{
+ WORD RefCount;
+ WORD OpenMode;
+ BYTE Attributes;
+ WORD DeviceInfo;
+ DWORD DevicePointer;
+ WORD Time;
+ WORD Date;
+ DWORD Size;
+ DWORD Position;
+ DWORD Reserved;
+ WORD OwnerPsp;
+ HANDLE Win32Handle;
+ BYTE Padding[0x1E - sizeof(HANDLE)];
+} DOS_FILE_DESCRIPTOR, *PDOS_FILE_DESCRIPTOR;
+
+C_ASSERT(sizeof(DOS_FILE_DESCRIPTOR) == 0x3B);
+
+typedef struct _DOS_SFT
+{
+ DWORD Link;
+ WORD NumDescriptors;
+ DOS_FILE_DESCRIPTOR FileDescriptors[ANYSIZE_ARRAY];
+} DOS_SFT, *PDOS_SFT;
+
+/* FUNCTIONS ******************************************************************/
+
+BYTE DosFindFreeDescriptor(VOID);
+BYTE DosFindWin32Descriptor(HANDLE Win32Handle);
+BYTE DosFindDeviceDescriptor(DWORD DevicePointer);
+PDOS_FILE_DESCRIPTOR DosGetFileDescriptor(BYTE Id);
+PDOS_FILE_DESCRIPTOR DosGetHandleFileDescriptor(WORD DosHandle);
+
+WORD DosCreateFileEx
+(
+ LPWORD Handle,
+ LPWORD CreationStatus,
+ LPCSTR FilePath,
+ BYTE AccessShareModes,
+ WORD CreateActionFlags,
+ WORD Attributes
+);
+
+WORD DosCreateFile
+(
+ LPWORD Handle,
+ LPCSTR FilePath,
+ DWORD CreationDisposition,
+ WORD Attributes
+);
+
+WORD DosOpenFile
+(
+ LPWORD Handle,
+ LPCSTR FilePath,
+ BYTE AccessShareModes
+);
+
+WORD DosReadFile
+(
+ WORD FileHandle,
+ DWORD Buffer,
+ WORD Count,
+ LPWORD BytesRead
+);
+
+WORD DosWriteFile
+(
+ WORD FileHandle,
+ DWORD Buffer,
+ WORD Count,
+ LPWORD BytesWritten
+);
+
+WORD DosSeekFile
+(
+ WORD FileHandle,
+ LONG Offset,
+ BYTE Origin,
+ LPDWORD NewOffset
+);
+
+BOOL DosFlushFileBuffers(WORD FileHandle);
+BOOLEAN DosLockFile(WORD DosHandle, DWORD Offset, DWORD Size);
+BOOLEAN DosUnlockFile(WORD DosHandle, DWORD Offset, DWORD Size);
+
+BOOLEAN DosDeviceIoControl
+(
+ WORD FileHandle,
+ BYTE ControlCode,
+ DWORD Buffer,
+ PWORD Length
+);
+
+#pragma pack(pop)
Propchange: trunk/reactos/subsystems/mvdm/ntvdm/dos/dos32krnl/dosfiles.h
------------------------------------------------------------------------------
svn:eol-style = native
Added: trunk/reactos/subsystems/mvdm/ntvdm/dos/dos32krnl/handle.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/subsystems/mvdm/ntvdm/dos/…
==============================================================================
--- trunk/reactos/subsystems/mvdm/ntvdm/dos/dos32krnl/handle.c (added)
+++ trunk/reactos/subsystems/mvdm/ntvdm/dos/dos32krnl/handle.c [iso-8859-1] Sun Apr 26
18:09:57 2015
@@ -0,0 +1,378 @@
+/*
+ * COPYRIGHT: GPLv2+ - See COPYING in the top level directory
+ * PROJECT: ReactOS Virtual DOS Machine
+ * FILE: dos/dos32krnl/handle.c
+ * PURPOSE: DOS32 Handles (Job File Table)
+ * PROGRAMMERS: Aleksandar Andrejevic <theflash AT sdf DOT lonestar DOT org>
+ */
+
+/* INCLUDES *******************************************************************/
+
+#define NDEBUG
+
+#include "ntvdm.h"
+#include "emulator.h"
+
+#include "dos.h"
+#include "dos/dem.h"
+#include "dosfiles.h"
+#include "handle.h"
+#include "memory.h"
+
+/* PRIVATE FUNCTIONS **********************************************************/
+
+/* Taken from base/shell/cmd/console.c */
+static BOOL IsConsoleHandle(HANDLE hHandle)
+{
+ DWORD dwMode;
+
+ /* Check whether the handle may be that of a console... */
+ if ((GetFileType(hHandle) & FILE_TYPE_CHAR) == 0) return FALSE;
+
+ /*
+ * It may be. Perform another test... The idea comes from the
+ * MSDN description of the WriteConsole API:
+ *
+ * "WriteConsole fails if it is used with a standard handle
+ * that is redirected to a file. If an application processes
+ * multilingual output that can be redirected, determine whether
+ * the output handle is a console handle (one method is to call
+ * the GetConsoleMode function and check whether it succeeds).
+ * If the handle is a console handle, call WriteConsole. If the
+ * handle is not a console handle, the output is redirected and
+ * you should call WriteFile to perform the I/O."
+ */
+ return GetConsoleMode(hHandle, &dwMode);
+}
+
+/* PUBLIC FUNCTIONS ***********************************************************/
+
+VOID DosCopyHandleTable(LPBYTE DestinationTable)
+{
+ UINT i;
+ PDOS_PSP PspBlock;
+ LPBYTE SourceTable;
+ PDOS_FILE_DESCRIPTOR Descriptor;
+
+ /* Clear the table first */
+ for (i = 0; i < DEFAULT_JFT_SIZE; i++) DestinationTable[i] = 0xFF;
+
+ /* Check if this is the initial process */
+ if (CurrentPsp == SYSTEM_PSP)
+ {
+ BYTE DescriptorId;
+ HANDLE StandardHandles[3];
+
+ /* Get the native standard handles */
+ StandardHandles[0] = GetStdHandle(STD_INPUT_HANDLE);
+ StandardHandles[1] = GetStdHandle(STD_OUTPUT_HANDLE);
+ StandardHandles[2] = GetStdHandle(STD_ERROR_HANDLE);
+
+ for (i = 0; i < 3; i++)
+ {
+ /* Find the corresponding SFT entry */
+ if (IsConsoleHandle(StandardHandles[i]))
+ {
+ DescriptorId = DosFindDeviceDescriptor(SysVars->ActiveCon);
+ }
+ else
+ {
+ DescriptorId = DosFindWin32Descriptor(StandardHandles[i]);
+ }
+
+ if (DescriptorId != 0xFF)
+ {
+ Descriptor = DosGetFileDescriptor(DescriptorId);
+ }
+ else
+ {
+ /* Create a new SFT entry for it */
+ DescriptorId = DosFindFreeDescriptor();
+ if (DescriptorId == 0xFF)
+ {
+ DPRINT1("Cannot create standard handle %d, the SFT is
full!\n", i);
+ continue;
+ }
+
+ Descriptor = DosGetFileDescriptor(DescriptorId);
+ ASSERT(Descriptor != NULL);
+ RtlZeroMemory(Descriptor, sizeof(*Descriptor));
+
+ if (IsConsoleHandle(StandardHandles[i]))
+ {
+ PDOS_DEVICE_NODE Node = DosGetDriverNode(SysVars->ActiveCon);
+
+ Descriptor->DeviceInfo = 1 << 7;
+ Descriptor->DevicePointer = SysVars->ActiveCon;
+
+ /* Call the open routine */
+ if (Node->OpenRoutine) Node->OpenRoutine(Node);
+ }
+ else
+ {
+ Descriptor->Win32Handle = StandardHandles[i];
+ }
+ }
+
+ Descriptor->RefCount++;
+ DestinationTable[i] = DescriptorId;
+ }
+ }
+ else
+ {
+ /* Get the parent PSP block and handle table */
+ PspBlock = SEGMENT_TO_PSP(CurrentPsp);
+ SourceTable = (LPBYTE)FAR_POINTER(PspBlock->HandleTablePtr);
+
+ /* Copy the first 20 handles into the new table */
+ for (i = 0; i < DEFAULT_JFT_SIZE; i++)
+ {
+ Descriptor = DosGetFileDescriptor(SourceTable[i]);
+ DestinationTable[i] = SourceTable[i];
+
+ /* Increase the reference count */
+ Descriptor->RefCount++;
+ }
+ }
+}
+
+BOOLEAN DosResizeHandleTable(WORD NewSize)
+{
+ PDOS_PSP PspBlock;
+ LPBYTE HandleTable;
+ WORD Segment;
+
+ /* Get the PSP block */
+ PspBlock = SEGMENT_TO_PSP(CurrentPsp);
+
+ if (NewSize == PspBlock->HandleTableSize)
+ {
+ /* No change */
+ return TRUE;
+ }
+
+ if (PspBlock->HandleTableSize > DEFAULT_JFT_SIZE)
+ {
+ /* Get the segment of the current table */
+ Segment = (LOWORD(PspBlock->HandleTablePtr) >> 4) +
HIWORD(PspBlock->HandleTablePtr);
+
+ if (NewSize <= DEFAULT_JFT_SIZE)
+ {
+ /* Get the current handle table */
+ HandleTable = FAR_POINTER(PspBlock->HandleTablePtr);
+
+ /* Copy it to the PSP */
+ RtlCopyMemory(PspBlock->HandleTable, HandleTable, NewSize);
+
+ /* Free the memory */
+ DosFreeMemory(Segment);
+
+ /* Update the handle table pointer and size */
+ PspBlock->HandleTableSize = NewSize;
+ PspBlock->HandleTablePtr = MAKELONG(0x18, CurrentPsp);
+ }
+ else
+ {
+ /* Resize the memory */
+ if (!DosResizeMemory(Segment, NewSize, NULL))
+ {
+ /* Unable to resize, try allocating it somewhere else */
+ Segment = DosAllocateMemory(NewSize, NULL);
+ if (Segment == 0) return FALSE;
+
+ /* Get the new handle table */
+ HandleTable = SEG_OFF_TO_PTR(Segment, 0);
+
+ /* Copy the handles to the new table */
+ RtlCopyMemory(HandleTable,
+ FAR_POINTER(PspBlock->HandleTablePtr),
+ PspBlock->HandleTableSize);
+
+ /* Update the handle table pointer */
+ PspBlock->HandleTablePtr = MAKELONG(0, Segment);
+ }
+
+ /* Update the handle table size */
+ PspBlock->HandleTableSize = NewSize;
+ }
+ }
+ else if (NewSize > DEFAULT_JFT_SIZE)
+ {
+ Segment = DosAllocateMemory(NewSize, NULL);
+ if (Segment == 0) return FALSE;
+
+ /* Get the new handle table */
+ HandleTable = SEG_OFF_TO_PTR(Segment, 0);
+
+ /* Copy the handles from the PSP to the new table */
+ RtlCopyMemory(HandleTable,
+ FAR_POINTER(PspBlock->HandleTablePtr),
+ PspBlock->HandleTableSize);
+
+ /* Update the handle table pointer and size */
+ PspBlock->HandleTableSize = NewSize;
+ PspBlock->HandleTablePtr = MAKELONG(0, Segment);
+ }
+
+ return TRUE;
+}
+
+
+WORD DosOpenHandle(BYTE DescriptorId)
+{
+ WORD DosHandle;
+ PDOS_PSP PspBlock;
+ LPBYTE HandleTable;
+ PDOS_FILE_DESCRIPTOR Descriptor = DosGetFileDescriptor(DescriptorId);
+
+ DPRINT("DosOpenHandle: DescriptorId 0x%02X\n", DescriptorId);
+
+ /* Make sure the descriptor ID is valid */
+ if (Descriptor == NULL) return INVALID_DOS_HANDLE;
+
+ /* The system PSP has no handle table */
+ if (CurrentPsp == SYSTEM_PSP) return INVALID_DOS_HANDLE;
+
+ /* Get a pointer to the handle table */
+ PspBlock = SEGMENT_TO_PSP(CurrentPsp);
+ HandleTable = (LPBYTE)FAR_POINTER(PspBlock->HandleTablePtr);
+
+ /* Find a free entry in the JFT */
+ for (DosHandle = 0; DosHandle < PspBlock->HandleTableSize; DosHandle++)
+ {
+ if (HandleTable[DosHandle] == 0xFF) break;
+ }
+
+ /* If there are no free entries, fail */
+ if (DosHandle == PspBlock->HandleTableSize) return INVALID_DOS_HANDLE;
+
+ /* Reference the descriptor */
+ Descriptor->RefCount++;
+
+ /* Set the JFT entry to that descriptor ID */
+ HandleTable[DosHandle] = DescriptorId;
+
+ /* Return the new handle */
+ return DosHandle;
+}
+
+BYTE DosQueryHandle(WORD DosHandle)
+{
+ PDOS_PSP PspBlock;
+ LPBYTE HandleTable;
+
+ DPRINT("DosQueryHandle: DosHandle 0x%04X\n", DosHandle);
+
+ /* The system PSP has no handle table */
+ if (CurrentPsp == SYSTEM_PSP) return 0xFF;
+
+ /* Get a pointer to the handle table */
+ PspBlock = SEGMENT_TO_PSP(CurrentPsp);
+ HandleTable = (LPBYTE)FAR_POINTER(PspBlock->HandleTablePtr);
+
+ /* Return the descriptor ID */
+ return HandleTable[DosHandle];
+}
+
+WORD DosDuplicateHandle(WORD DosHandle)
+{
+ BYTE DescriptorId = DosQueryHandle(DosHandle);
+
+ if (DescriptorId == 0xFF)
+ {
+ DosLastError = ERROR_INVALID_HANDLE;
+ return INVALID_DOS_HANDLE;
+ }
+
+ return DosOpenHandle(DescriptorId);
+}
+
+BOOLEAN DosForceDuplicateHandle(WORD OldHandle, WORD NewHandle)
+{
+ BYTE DescriptorId;
+ PDOS_PSP PspBlock;
+ LPBYTE HandleTable;
+ PDOS_FILE_DESCRIPTOR Descriptor;
+
+ DPRINT("DosForceDuplicateHandle: OldHandle 0x%04X, NewHandle 0x%04X\n",
+ OldHandle,
+ NewHandle);
+
+ /* The system PSP has no handle table */
+ if (CurrentPsp == SYSTEM_PSP) return FALSE;
+
+ /* Get a pointer to the handle table */
+ PspBlock = SEGMENT_TO_PSP(CurrentPsp);
+ HandleTable = (LPBYTE)FAR_POINTER(PspBlock->HandleTablePtr);
+
+ /* Make sure the old handle is open */
+ if (HandleTable[OldHandle] == 0xFF) return FALSE;
+
+ /* Check if the new handle is open */
+ if (HandleTable[NewHandle] != 0xFF)
+ {
+ /* Close it */
+ DosCloseHandle(NewHandle);
+ }
+
+ DescriptorId = HandleTable[OldHandle];
+ Descriptor = DosGetFileDescriptor(DescriptorId);
+ if (Descriptor == NULL) return FALSE;
+
+ /* Increment the reference count of the descriptor */
+ Descriptor->RefCount++;
+
+ /* Make the new handle point to that descriptor */
+ HandleTable[NewHandle] = DescriptorId;
+
+ /* Return success */
+ return TRUE;
+}
+
+BOOLEAN DosCloseHandle(WORD DosHandle)
+{
+ PDOS_PSP PspBlock;
+ LPBYTE HandleTable;
+ PDOS_FILE_DESCRIPTOR Descriptor;
+
+ DPRINT("DosCloseHandle: DosHandle 0x%04X\n", DosHandle);
+
+ /* The system PSP has no handle table */
+ if (CurrentPsp == SYSTEM_PSP) return FALSE;
+
+ /* Get a pointer to the handle table */
+ PspBlock = SEGMENT_TO_PSP(CurrentPsp);
+ HandleTable = (LPBYTE)FAR_POINTER(PspBlock->HandleTablePtr);
+
+ /* Make sure the handle is open */
+ if (HandleTable[DosHandle] == 0xFF) return FALSE;
+
+ /* Make sure the descriptor is valid */
+ Descriptor = DosGetFileDescriptor(HandleTable[DosHandle]);
+ if (Descriptor == NULL) return FALSE;
+
+ /* Decrement the reference count of the descriptor */
+ Descriptor->RefCount--;
+
+ /* Check if the reference count fell to zero */
+ if (!Descriptor->RefCount)
+ {
+ if (Descriptor->DeviceInfo & (1 << 7))
+ {
+ PDOS_DEVICE_NODE Node = DosGetDriverNode(Descriptor->DevicePointer);
+
+ /* Call the close routine, if it exists */
+ if (Node->CloseRoutine) Node->CloseRoutine(Node);
+ }
+ else
+ {
+ /* Close the win32 handle */
+ CloseHandle(Descriptor->Win32Handle);
+ }
+ }
+
+ /* Clear the entry in the JFT */
+ HandleTable[DosHandle] = 0xFF;
+
+ return TRUE;
+}
Propchange: trunk/reactos/subsystems/mvdm/ntvdm/dos/dos32krnl/handle.c
------------------------------------------------------------------------------
svn:eol-style = native
Added: trunk/reactos/subsystems/mvdm/ntvdm/dos/dos32krnl/handle.h
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/subsystems/mvdm/ntvdm/dos/…
==============================================================================
--- trunk/reactos/subsystems/mvdm/ntvdm/dos/dos32krnl/handle.h (added)
+++ trunk/reactos/subsystems/mvdm/ntvdm/dos/dos32krnl/handle.h [iso-8859-1] Sun Apr 26
18:09:57 2015
@@ -0,0 +1,21 @@
+/*
+ * COPYRIGHT: GPLv2+ - See COPYING in the top level directory
+ * PROJECT: ReactOS Virtual DOS Machine
+ * FILE: dos/dos32krnl/handle.h
+ * PURPOSE: DOS32 Handles (Job File Table)
+ * PROGRAMMERS: Aleksandar Andrejevic <theflash AT sdf DOT lonestar DOT org>
+ */
+
+/* DEFINITIONS ****************************************************************/
+
+#define DEFAULT_JFT_SIZE 20
+
+/* FUNCTIONS ******************************************************************/
+
+VOID DosCopyHandleTable(LPBYTE DestinationTable);
+BOOLEAN DosResizeHandleTable(WORD NewSize);
+WORD DosOpenHandle(BYTE DescriptorId);
+BYTE DosQueryHandle(WORD DosHandle);
+WORD DosDuplicateHandle(WORD DosHandle);
+BOOLEAN DosForceDuplicateHandle(WORD OldHandle, WORD NewHandle);
+BOOLEAN DosCloseHandle(WORD DosHandle);
Propchange: trunk/reactos/subsystems/mvdm/ntvdm/dos/dos32krnl/handle.h
------------------------------------------------------------------------------
svn:eol-style = native