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/CMake... ============================================================================== --- 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/d... ============================================================================== --- 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/d... ============================================================================== --- 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/d... ============================================================================== --- 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/d... ============================================================================== --- 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/d... ============================================================================== --- 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/d... ============================================================================== --- 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/d... ============================================================================== --- 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/d... ============================================================================== --- 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/d... ============================================================================== --- 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