mirror of
https://github.com/reactos/reactos.git
synced 2025-05-13 14:20:31 +00:00
[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. svn path=/trunk/; revision=67444
This commit is contained in:
parent
71a0dd0f0e
commit
12dff944a2
10 changed files with 1126 additions and 926 deletions
|
@ -33,6 +33,7 @@ list(APPEND SOURCE
|
||||||
dos/dos32krnl/dos.c
|
dos/dos32krnl/dos.c
|
||||||
dos/dos32krnl/dosfiles.c
|
dos/dos32krnl/dosfiles.c
|
||||||
dos/dos32krnl/emsdrv.c
|
dos/dos32krnl/emsdrv.c
|
||||||
|
dos/dos32krnl/handle.c
|
||||||
dos/dos32krnl/himem.c
|
dos/dos32krnl/himem.c
|
||||||
dos/dos32krnl/memory.c
|
dos/dos32krnl/memory.c
|
||||||
dos/mouse32.c
|
dos/mouse32.c
|
||||||
|
|
|
@ -15,6 +15,7 @@
|
||||||
#include "int32.h"
|
#include "int32.h"
|
||||||
|
|
||||||
#include "dos.h"
|
#include "dos.h"
|
||||||
|
#include "dosfiles.h"
|
||||||
#include "memory.h"
|
#include "memory.h"
|
||||||
#include "bios/bios.h"
|
#include "bios/bios.h"
|
||||||
|
|
||||||
|
@ -56,43 +57,33 @@ CHAR DosReadCharacter(WORD FileHandle)
|
||||||
|
|
||||||
BOOLEAN DosCheckInput(VOID)
|
BOOLEAN DosCheckInput(VOID)
|
||||||
{
|
{
|
||||||
PDOS_SFT_ENTRY SftEntry = DosGetSftEntry(DOS_INPUT_HANDLE);
|
PDOS_FILE_DESCRIPTOR Descriptor = DosGetHandleFileDescriptor(DOS_INPUT_HANDLE);
|
||||||
|
|
||||||
if (SftEntry == NULL)
|
if (Descriptor == NULL)
|
||||||
{
|
{
|
||||||
/* Invalid handle */
|
/* Invalid handle */
|
||||||
DosLastError = ERROR_INVALID_HANDLE; // ERROR_FILE_NOT_FOUND
|
DosLastError = ERROR_INVALID_HANDLE; // ERROR_FILE_NOT_FOUND
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (SftEntry->Type)
|
if (Descriptor->DeviceInfo & (1 << 7))
|
||||||
{
|
|
||||||
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;
|
WORD Result;
|
||||||
|
PDOS_DEVICE_NODE Node = DosGetDriverNode(Descriptor->DevicePointer);
|
||||||
|
|
||||||
if (!SftEntry->DeviceNode->InputStatusRoutine) return FALSE;
|
if (!Node->InputStatusRoutine) return FALSE;
|
||||||
|
|
||||||
Result = SftEntry->DeviceNode->InputStatusRoutine(SftEntry->DeviceNode);
|
Result = Node->InputStatusRoutine(Node);
|
||||||
return !(Result & DOS_DEVSTAT_BUSY);
|
return !(Result & DOS_DEVSTAT_BUSY);
|
||||||
}
|
}
|
||||||
|
else
|
||||||
default:
|
|
||||||
{
|
{
|
||||||
/* Invalid handle */
|
DWORD FileSizeHigh;
|
||||||
DosLastError = ERROR_INVALID_HANDLE;
|
DWORD FileSize = GetFileSize(Descriptor->Win32Handle, &FileSizeHigh);
|
||||||
return FALSE;
|
LONG LocationHigh = 0;
|
||||||
}
|
DWORD Location = SetFilePointer(Descriptor->Win32Handle, 0, &LocationHigh, FILE_CURRENT);
|
||||||
|
|
||||||
|
return ((Location != FileSize) || (LocationHigh != FileSizeHigh));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -40,7 +40,6 @@ static const BYTE InterruptRoutine[] = {
|
||||||
C_ASSERT((sizeof(StrategyRoutine) + sizeof(InterruptRoutine)) == DEVICE_CODE_SIZE);
|
C_ASSERT((sizeof(StrategyRoutine) + sizeof(InterruptRoutine)) == DEVICE_CODE_SIZE);
|
||||||
|
|
||||||
static LIST_ENTRY DeviceList = { &DeviceList, &DeviceList };
|
static LIST_ENTRY DeviceList = { &DeviceList, &DeviceList };
|
||||||
static DWORD FirstDriver = 0xFFFFFFFF;
|
|
||||||
static PDOS_REQUEST_HEADER DeviceRequest;
|
static PDOS_REQUEST_HEADER DeviceRequest;
|
||||||
|
|
||||||
/* PRIVATE FUNCTIONS **********************************************************/
|
/* PRIVATE FUNCTIONS **********************************************************/
|
||||||
|
@ -213,17 +212,9 @@ static WORD NTAPI DosDriverDispatchOutputUntilBusy(PDOS_DEVICE_NODE DeviceNode,
|
||||||
|
|
||||||
static VOID DosAddDriver(DWORD Driver)
|
static VOID DosAddDriver(DWORD Driver)
|
||||||
{
|
{
|
||||||
PDOS_DRIVER LastDriver;
|
PDOS_DRIVER LastDriver = &SysVars->NullDevice;
|
||||||
|
|
||||||
if (LOWORD(FirstDriver) == 0xFFFF)
|
/* Find the last driver in the list */
|
||||||
{
|
|
||||||
/* 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);
|
|
||||||
while (LOWORD(LastDriver->Link) != 0xFFFF)
|
while (LOWORD(LastDriver->Link) != 0xFFFF)
|
||||||
{
|
{
|
||||||
LastDriver = (PDOS_DRIVER)FAR_POINTER(LastDriver->Link);
|
LastDriver = (PDOS_DRIVER)FAR_POINTER(LastDriver->Link);
|
||||||
|
@ -231,18 +222,25 @@ static VOID DosAddDriver(DWORD Driver)
|
||||||
|
|
||||||
/* Add the new driver to the list */
|
/* Add the new driver to the list */
|
||||||
LastDriver->Link = Driver;
|
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)
|
static VOID DosRemoveDriver(DWORD Driver)
|
||||||
{
|
{
|
||||||
DWORD CurrentDriver = FirstDriver;
|
DWORD CurrentDriver = MAKELONG(FIELD_OFFSET(DOS_SYSVARS, NullDevice), DOS_DATA_SEGMENT);
|
||||||
|
|
||||||
if (FirstDriver == Driver)
|
|
||||||
{
|
|
||||||
/* Update the first driver */
|
|
||||||
FirstDriver = ((PDOS_DRIVER)FAR_POINTER(FirstDriver))->Link;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
while (LOWORD(CurrentDriver) != 0xFFFF)
|
while (LOWORD(CurrentDriver) != 0xFFFF)
|
||||||
{
|
{
|
||||||
|
@ -289,35 +287,26 @@ static PDOS_DEVICE_NODE DosCreateDeviceNode(DWORD Driver)
|
||||||
|
|
||||||
/* PUBLIC FUNCTIONS ***********************************************************/
|
/* PUBLIC FUNCTIONS ***********************************************************/
|
||||||
|
|
||||||
PDOS_DEVICE_NODE DosGetDevice(LPCSTR DeviceName)
|
PDOS_DEVICE_NODE DosGetDriverNode(DWORD Driver)
|
||||||
{
|
{
|
||||||
PLIST_ENTRY i;
|
PLIST_ENTRY i;
|
||||||
DWORD CurrentDriver = FirstDriver;
|
|
||||||
ANSI_STRING DeviceNameString;
|
|
||||||
|
|
||||||
RtlInitAnsiString(&DeviceNameString, DeviceName);
|
|
||||||
|
|
||||||
while (LOWORD(CurrentDriver) != 0xFFFF)
|
|
||||||
{
|
|
||||||
PDOS_DEVICE_NODE Node;
|
PDOS_DEVICE_NODE Node;
|
||||||
PDOS_DRIVER DriverHeader = (PDOS_DRIVER)FAR_POINTER(CurrentDriver);
|
|
||||||
|
|
||||||
/* Get the device node for this driver */
|
|
||||||
for (i = DeviceList.Flink; i != &DeviceList; i = i->Flink)
|
for (i = DeviceList.Flink; i != &DeviceList; i = i->Flink)
|
||||||
{
|
{
|
||||||
Node = CONTAINING_RECORD(i, DOS_DEVICE_NODE, Entry);
|
Node = CONTAINING_RECORD(i, DOS_DEVICE_NODE, Entry);
|
||||||
if (Node->Driver == CurrentDriver) break;
|
if (Node->Driver == Driver) break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (i == &DeviceList)
|
if (i == &DeviceList)
|
||||||
{
|
{
|
||||||
DPRINT1("The driver at %04X:%04X has no associated device node. "
|
DPRINT1("The driver at %04X:%04X has no associated device node. "
|
||||||
"Installing automagically.\n",
|
"Installing automagically.\n",
|
||||||
HIWORD(CurrentDriver),
|
HIWORD(Driver),
|
||||||
LOWORD(CurrentDriver));
|
LOWORD(Driver));
|
||||||
|
|
||||||
/* Create the device node */
|
/* Create the device node */
|
||||||
Node = DosCreateDeviceNode(CurrentDriver);
|
Node = DosCreateDeviceNode(Driver);
|
||||||
Node->IoctlReadRoutine = DosDriverDispatchIoctlRead;
|
Node->IoctlReadRoutine = DosDriverDispatchIoctlRead;
|
||||||
Node->ReadRoutine = DosDriverDispatchRead;
|
Node->ReadRoutine = DosDriverDispatchRead;
|
||||||
Node->PeekRoutine = DosDriverDispatchPeek;
|
Node->PeekRoutine = DosDriverDispatchPeek;
|
||||||
|
@ -332,6 +321,21 @@ PDOS_DEVICE_NODE DosGetDevice(LPCSTR DeviceName)
|
||||||
Node->OutputUntilBusyRoutine = DosDriverDispatchOutputUntilBusy;
|
Node->OutputUntilBusyRoutine = DosDriverDispatchOutputUntilBusy;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return Node;
|
||||||
|
}
|
||||||
|
|
||||||
|
PDOS_DEVICE_NODE DosGetDevice(LPCSTR DeviceName)
|
||||||
|
{
|
||||||
|
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 = DosGetDriverNode(CurrentDriver);
|
||||||
|
PDOS_DRIVER DriverHeader = (PDOS_DRIVER)FAR_POINTER(CurrentDriver);
|
||||||
|
|
||||||
if (RtlEqualString(&Node->Name, &DeviceNameString, TRUE)) return Node;
|
if (RtlEqualString(&Node->Name, &DeviceNameString, TRUE)) return Node;
|
||||||
CurrentDriver = DriverHeader->Link;
|
CurrentDriver = DriverHeader->Link;
|
||||||
}
|
}
|
||||||
|
|
|
@ -194,6 +194,7 @@ typedef struct _DOS_OUTPUT_BUSY_REQUEST
|
||||||
|
|
||||||
/* FUNCTIONS ******************************************************************/
|
/* FUNCTIONS ******************************************************************/
|
||||||
|
|
||||||
|
PDOS_DEVICE_NODE DosGetDriverNode(DWORD Driver);
|
||||||
PDOS_DEVICE_NODE DosGetDevice(LPCSTR DeviceName);
|
PDOS_DEVICE_NODE DosGetDevice(LPCSTR DeviceName);
|
||||||
PDOS_DEVICE_NODE DosCreateDevice(WORD Attributes, PCHAR DeviceName);
|
PDOS_DEVICE_NODE DosCreateDevice(WORD Attributes, PCHAR DeviceName);
|
||||||
PDOS_DEVICE_NODE DosCreateDeviceEx
|
PDOS_DEVICE_NODE DosCreateDeviceEx
|
||||||
|
|
|
@ -19,6 +19,8 @@
|
||||||
#include "dos.h"
|
#include "dos.h"
|
||||||
#include "dos/dem.h"
|
#include "dos/dem.h"
|
||||||
#include "device.h"
|
#include "device.h"
|
||||||
|
#include "handle.h"
|
||||||
|
#include "dosfiles.h"
|
||||||
#include "memory.h"
|
#include "memory.h"
|
||||||
#include "himem.h"
|
#include "himem.h"
|
||||||
|
|
||||||
|
@ -39,12 +41,13 @@ static DWORD DiskTransferArea;
|
||||||
/*static*/ BYTE CurrentDrive;
|
/*static*/ BYTE CurrentDrive;
|
||||||
static CHAR LastDrive = 'E';
|
static CHAR LastDrive = 'E';
|
||||||
static CHAR CurrentDirectories[NUM_DRIVES][DOS_DIR_LENGTH];
|
static CHAR CurrentDirectories[NUM_DRIVES][DOS_DIR_LENGTH];
|
||||||
static DOS_SFT_ENTRY DosSystemFileTable[DOS_SFT_SIZE];
|
|
||||||
static WORD DosErrorLevel = 0x0000;
|
static WORD DosErrorLevel = 0x0000;
|
||||||
static PBYTE InDos;
|
static PBYTE InDos;
|
||||||
|
|
||||||
/* PUBLIC VARIABLES ***********************************************************/
|
/* PUBLIC VARIABLES ***********************************************************/
|
||||||
|
|
||||||
|
PDOS_SYSVARS SysVars;
|
||||||
|
|
||||||
/* Echo state for INT 21h, AH = 01h and AH = 3Fh */
|
/* Echo state for INT 21h, AH = 01h and AH = 3Fh */
|
||||||
BOOLEAN DoEcho = FALSE;
|
BOOLEAN DoEcho = FALSE;
|
||||||
WORD CurrentPsp = SYSTEM_PSP;
|
WORD CurrentPsp = SYSTEM_PSP;
|
||||||
|
@ -120,456 +123,6 @@ static WORD DosCopyEnvironmentBlock(LPCSTR Environment OPTIONAL,
|
||||||
return DestSegment;
|
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)
|
static BOOLEAN DosChangeDrive(BYTE Drive)
|
||||||
{
|
{
|
||||||
WCHAR DirectoryPath[DOS_CMDLINE_LENGTH];
|
WCHAR DirectoryPath[DOS_CMDLINE_LENGTH];
|
||||||
|
@ -675,25 +228,6 @@ static BOOLEAN DosControlBreak(VOID)
|
||||||
|
|
||||||
/* PUBLIC FUNCTIONS ***********************************************************/
|
/* 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,
|
VOID DosInitializePsp(WORD PspSegment,
|
||||||
LPCSTR CommandLine,
|
LPCSTR CommandLine,
|
||||||
WORD ProgramSize,
|
WORD ProgramSize,
|
||||||
|
@ -1279,110 +813,6 @@ Done:
|
||||||
LOWORD(PspBlock->TerminateAddress));
|
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)
|
VOID WINAPI DosInt20h(LPWORD Stack)
|
||||||
{
|
{
|
||||||
/* This is the exit interrupt */
|
/* This is the exit interrupt */
|
||||||
|
@ -2196,20 +1626,8 @@ VOID WINAPI DosInt21h(LPWORD Stack)
|
||||||
case 0x3D:
|
case 0x3D:
|
||||||
{
|
{
|
||||||
WORD FileHandle;
|
WORD FileHandle;
|
||||||
WORD ErrorCode;
|
|
||||||
LPCSTR FileName = (LPCSTR)SEG_OFF_TO_PTR(getDS(), getDX());
|
LPCSTR FileName = (LPCSTR)SEG_OFF_TO_PTR(getDS(), getDX());
|
||||||
PDOS_DEVICE_NODE Device = DosGetDevice(FileName);
|
WORD ErrorCode = DosOpenFile(&FileHandle, FileName, getAL());
|
||||||
|
|
||||||
if (Device)
|
|
||||||
{
|
|
||||||
FileHandle = DosOpenDevice(Device);
|
|
||||||
ErrorCode = (FileHandle != INVALID_DOS_HANDLE)
|
|
||||||
? ERROR_SUCCESS : ERROR_TOO_MANY_OPEN_FILES;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
ErrorCode = DosOpenFile(&FileHandle, FileName, getAL());
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ErrorCode == ERROR_SUCCESS)
|
if (ErrorCode == ERROR_SUCCESS)
|
||||||
{
|
{
|
||||||
|
@ -2391,9 +1809,12 @@ VOID WINAPI DosInt21h(LPWORD Stack)
|
||||||
/* IOCTL */
|
/* IOCTL */
|
||||||
case 0x44:
|
case 0x44:
|
||||||
{
|
{
|
||||||
if (DosHandleIoctl(getAL(), getBX()))
|
WORD Length = getCX();
|
||||||
|
|
||||||
|
if (DosDeviceIoControl(getBX(), getAL(), MAKELONG(getDX(), getDS()), &Length))
|
||||||
{
|
{
|
||||||
Stack[STACK_FLAGS] &= ~EMULATOR_FLAG_CF;
|
Stack[STACK_FLAGS] &= ~EMULATOR_FLAG_CF;
|
||||||
|
setAX(Length);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -2407,57 +1828,26 @@ VOID WINAPI DosInt21h(LPWORD Stack)
|
||||||
/* Duplicate Handle */
|
/* Duplicate Handle */
|
||||||
case 0x45:
|
case 0x45:
|
||||||
{
|
{
|
||||||
WORD NewHandle;
|
WORD NewHandle = DosDuplicateHandle(getBX());
|
||||||
PDOS_SFT_ENTRY SftEntry = DosGetSftEntry(getBX());
|
|
||||||
|
|
||||||
if (SftEntry == NULL || SftEntry->Type == DOS_SFT_ENTRY_NONE)
|
if (NewHandle != INVALID_DOS_HANDLE)
|
||||||
{
|
{
|
||||||
/* 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);
|
setAX(NewHandle);
|
||||||
|
Stack[STACK_FLAGS] &= ~EMULATOR_FLAG_CF;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Stack[STACK_FLAGS] |= EMULATOR_FLAG_CF;
|
||||||
|
setAX(DosLastError);
|
||||||
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Force Duplicate Handle */
|
/* Force Duplicate Handle */
|
||||||
case 0x46:
|
case 0x46:
|
||||||
{
|
{
|
||||||
if (DosDuplicateHandle(getBX(), getCX()))
|
if (DosForceDuplicateHandle(getBX(), getCX()))
|
||||||
{
|
{
|
||||||
Stack[STACK_FLAGS] &= ~EMULATOR_FLAG_CF;
|
Stack[STACK_FLAGS] &= ~EMULATOR_FLAG_CF;
|
||||||
}
|
}
|
||||||
|
@ -2686,10 +2076,9 @@ VOID WINAPI DosInt21h(LPWORD Stack)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* Return the DOS "list of lists" in ES:BX */
|
/* Return the DOS "list of lists" in ES:BX */
|
||||||
setES(0x0000);
|
setES(DOS_DATA_SEGMENT);
|
||||||
setBX(0x0000);
|
setBX(FIELD_OFFSET(DOS_SYSVARS, FirstDpb));
|
||||||
|
|
||||||
DPRINT1("INT 21h, AH=52h: This application requires the internal DOS List of lists (SYSVARS). UNIMPLEMENTED\n");
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2850,44 +2239,30 @@ VOID WINAPI DosInt21h(LPWORD Stack)
|
||||||
/* Lock/Unlock Region of File */
|
/* Lock/Unlock Region of File */
|
||||||
case 0x5C:
|
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)
|
if (getAL() == 0x00)
|
||||||
{
|
{
|
||||||
/* Lock region of file */
|
/* Lock region of file */
|
||||||
if (LockFile(SftEntry->Handle,
|
if (DosLockFile(getBX(), MAKELONG(getCX(), getDX()), MAKELONG(getSI(), getDI())))
|
||||||
MAKELONG(getCX(), getDX()), 0,
|
|
||||||
MAKELONG(getSI(), getDI()), 0))
|
|
||||||
{
|
{
|
||||||
Stack[STACK_FLAGS] &= ~EMULATOR_FLAG_CF;
|
Stack[STACK_FLAGS] &= ~EMULATOR_FLAG_CF;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Stack[STACK_FLAGS] |= EMULATOR_FLAG_CF;
|
Stack[STACK_FLAGS] |= EMULATOR_FLAG_CF;
|
||||||
setAX(GetLastError());
|
setAX(DosLastError);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (getAL() == 0x01)
|
else if (getAL() == 0x01)
|
||||||
{
|
{
|
||||||
/* Unlock region of file */
|
/* Unlock region of file */
|
||||||
if (UnlockFile(SftEntry->Handle,
|
if (DosUnlockFile(getBX(), MAKELONG(getCX(), getDX()), MAKELONG(getSI(), getDI())))
|
||||||
MAKELONG(getCX(), getDX()), 0,
|
|
||||||
MAKELONG(getSI(), getDI()), 0))
|
|
||||||
{
|
{
|
||||||
Stack[STACK_FLAGS] &= ~EMULATOR_FLAG_CF;
|
Stack[STACK_FLAGS] &= ~EMULATOR_FLAG_CF;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Stack[STACK_FLAGS] |= EMULATOR_FLAG_CF;
|
Stack[STACK_FLAGS] |= EMULATOR_FLAG_CF;
|
||||||
setAX(GetLastError());
|
setAX(DosLastError);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -3109,13 +2484,26 @@ VOID WINAPI DosInt2Fh(LPWORD Stack)
|
||||||
|
|
||||||
BOOLEAN DosKRNLInitialize(VOID)
|
BOOLEAN DosKRNLInitialize(VOID)
|
||||||
{
|
{
|
||||||
|
|
||||||
#if 1
|
#if 1
|
||||||
|
|
||||||
UCHAR i;
|
UCHAR i;
|
||||||
CHAR CurrentDirectory[MAX_PATH];
|
CHAR CurrentDirectory[MAX_PATH];
|
||||||
CHAR DosDirectory[DOS_DIR_LENGTH];
|
CHAR DosDirectory[DOS_DIR_LENGTH];
|
||||||
LPSTR Path;
|
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;
|
FILE *Stream;
|
||||||
WCHAR Buffer[256];
|
WCHAR Buffer[256];
|
||||||
|
@ -3169,11 +2557,34 @@ BOOLEAN DosKRNLInitialize(VOID)
|
||||||
fclose(Stream);
|
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 */
|
/* Initialize the SFT */
|
||||||
for (i = 0; i < DOS_SFT_SIZE; i++)
|
Sft = (PDOS_SFT)FAR_POINTER(SysVars->FirstSft);
|
||||||
|
Sft->Link = 0xFFFFFFFF;
|
||||||
|
Sft->NumDescriptors = DOS_SFT_SIZE;
|
||||||
|
|
||||||
|
for (i = 0; i < Sft->NumDescriptors; i++)
|
||||||
{
|
{
|
||||||
DosSystemFileTable[i].Type = DOS_SFT_ENTRY_NONE;
|
/* Clear the file descriptor entry */
|
||||||
DosSystemFileTable[i].RefCount = 0;
|
RtlZeroMemory(&Sft->FileDescriptors[i], sizeof(DOS_FILE_DESCRIPTOR));
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -30,6 +30,8 @@
|
||||||
#define USER_MEMORY_SIZE (0x9FFE - FIRST_MCB_SEGMENT)
|
#define USER_MEMORY_SIZE (0x9FFE - FIRST_MCB_SEGMENT)
|
||||||
#define SYSTEM_PSP 0x08
|
#define SYSTEM_PSP 0x08
|
||||||
#define SYSTEM_ENV_BLOCK 0x800
|
#define SYSTEM_ENV_BLOCK 0x800
|
||||||
|
#define DOS_DATA_SEGMENT 0xA0
|
||||||
|
#define MASTER_SFT_OFFSET 0x100
|
||||||
|
|
||||||
#define INVALID_DOS_HANDLE 0xFFFF
|
#define INVALID_DOS_HANDLE 0xFFFF
|
||||||
#define DOS_INPUT_HANDLE 0
|
#define DOS_INPUT_HANDLE 0
|
||||||
|
@ -48,7 +50,6 @@
|
||||||
#define NUM_DRIVES ('Z' - 'A' + 1)
|
#define NUM_DRIVES ('Z' - 'A' + 1)
|
||||||
#define DOS_CHAR_ATTRIBUTE 0x07
|
#define DOS_CHAR_ATTRIBUTE 0x07
|
||||||
#define DOS_PROGRAM_NAME_TAG 0x0001
|
#define DOS_PROGRAM_NAME_TAG 0x0001
|
||||||
#define DEFAULT_JFT_SIZE 20
|
|
||||||
|
|
||||||
/* 16 MB of EMS memory */
|
/* 16 MB of EMS memory */
|
||||||
#define EMS_TOTAL_PAGES 1024
|
#define EMS_TOTAL_PAGES 1024
|
||||||
|
@ -60,25 +61,6 @@ typedef enum
|
||||||
DOS_LOAD_OVERLAY = 0x03
|
DOS_LOAD_OVERLAY = 0x03
|
||||||
} DOS_EXEC_TYPE;
|
} 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)
|
#pragma pack(push, 1)
|
||||||
|
|
||||||
typedef struct _DOS_FCB
|
typedef struct _DOS_FCB
|
||||||
|
@ -96,6 +78,30 @@ typedef struct _DOS_FCB
|
||||||
BYTE RecordNumber[3];
|
BYTE RecordNumber[3];
|
||||||
} DOS_FCB, *PDOS_FCB;
|
} 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
|
typedef struct _DOS_PSP
|
||||||
{
|
{
|
||||||
BYTE Exit[2];
|
BYTE Exit[2];
|
||||||
|
@ -128,15 +134,6 @@ typedef struct _DOS_INPUT_BUFFER
|
||||||
CHAR Buffer[ANYSIZE_ARRAY];
|
CHAR Buffer[ANYSIZE_ARRAY];
|
||||||
} DOS_INPUT_BUFFER, *PDOS_INPUT_BUFFER;
|
} 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
|
typedef struct _DOS_FIND_FILE_BLOCK
|
||||||
{
|
{
|
||||||
CHAR DriveLetter;
|
CHAR DriveLetter;
|
||||||
|
@ -181,6 +178,7 @@ typedef struct _DOS_COUNTRY_CODE_BUFFER
|
||||||
extern BOOLEAN DoEcho;
|
extern BOOLEAN DoEcho;
|
||||||
extern WORD CurrentPsp;
|
extern WORD CurrentPsp;
|
||||||
extern WORD DosLastError;
|
extern WORD DosLastError;
|
||||||
|
extern PDOS_SYSVARS SysVars;
|
||||||
|
|
||||||
/* FUNCTIONS ******************************************************************/
|
/* FUNCTIONS ******************************************************************/
|
||||||
|
|
||||||
|
@ -208,35 +206,6 @@ VOID ConDrvCleanup(VOID);
|
||||||
* DOS Kernel Functions
|
* DOS Kernel Functions
|
||||||
* See dos.c
|
* 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(
|
VOID DosInitializePsp(
|
||||||
WORD PspSegment,
|
WORD PspSegment,
|
||||||
|
|
|
@ -17,11 +17,125 @@
|
||||||
|
|
||||||
#include "dos.h"
|
#include "dos.h"
|
||||||
#include "dos/dem.h"
|
#include "dos/dem.h"
|
||||||
|
#include "dosfiles.h"
|
||||||
|
#include "handle.h"
|
||||||
|
|
||||||
#include "bios/bios.h"
|
#include "bios/bios.h"
|
||||||
|
|
||||||
/* PUBLIC FUNCTIONS ***********************************************************/
|
/* 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,
|
WORD DosCreateFileEx(LPWORD Handle,
|
||||||
LPWORD CreationStatus,
|
LPWORD CreationStatus,
|
||||||
LPCSTR FilePath,
|
LPCSTR FilePath,
|
||||||
|
@ -37,6 +151,8 @@ WORD DosCreateFileEx(LPWORD Handle,
|
||||||
DWORD CreationDisposition = 0;
|
DWORD CreationDisposition = 0;
|
||||||
BOOL InheritableFile = FALSE;
|
BOOL InheritableFile = FALSE;
|
||||||
SECURITY_ATTRIBUTES SecurityAttributes;
|
SECURITY_ATTRIBUTES SecurityAttributes;
|
||||||
|
BYTE DescriptorId;
|
||||||
|
PDOS_FILE_DESCRIPTOR Descriptor;
|
||||||
|
|
||||||
DPRINT1("DosCreateFileEx: FilePath \"%s\", AccessShareModes 0x%04X, CreateActionFlags 0x%04X, Attributes 0x%04X\n",
|
DPRINT1("DosCreateFileEx: FilePath \"%s\", AccessShareModes 0x%04X, CreateActionFlags 0x%04X, Attributes 0x%04X\n",
|
||||||
FilePath, AccessShareModes, CreateActionFlags, Attributes);
|
FilePath, AccessShareModes, CreateActionFlags, Attributes);
|
||||||
|
@ -228,8 +344,26 @@ WORD DosCreateFileEx(LPWORD 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->OpenMode = AccessShareModes;
|
||||||
|
Descriptor->Attributes = LOBYTE(GetFileAttributesA(FilePath));
|
||||||
|
Descriptor->Size = GetFileSize(FileHandle, NULL);
|
||||||
|
Descriptor->OwnerPsp = CurrentPsp;
|
||||||
|
Descriptor->Win32Handle = FileHandle;
|
||||||
|
|
||||||
/* Open the DOS handle */
|
/* Open the DOS handle */
|
||||||
DosHandle = DosOpenHandle(FileHandle);
|
DosHandle = DosOpenHandle(DescriptorId);
|
||||||
if (DosHandle == INVALID_DOS_HANDLE)
|
if (DosHandle == INVALID_DOS_HANDLE)
|
||||||
{
|
{
|
||||||
/* Close the file and return the error code */
|
/* Close the file and return the error code */
|
||||||
|
@ -249,6 +383,8 @@ WORD DosCreateFile(LPWORD Handle,
|
||||||
{
|
{
|
||||||
HANDLE FileHandle;
|
HANDLE FileHandle;
|
||||||
WORD DosHandle;
|
WORD DosHandle;
|
||||||
|
BYTE DescriptorId;
|
||||||
|
PDOS_FILE_DESCRIPTOR Descriptor;
|
||||||
|
|
||||||
DPRINT("DosCreateFile: FilePath \"%s\", CreationDisposition 0x%04X, Attributes 0x%04X\n",
|
DPRINT("DosCreateFile: FilePath \"%s\", CreationDisposition 0x%04X, Attributes 0x%04X\n",
|
||||||
FilePath, CreationDisposition, Attributes);
|
FilePath, CreationDisposition, Attributes);
|
||||||
|
@ -267,8 +403,25 @@ WORD DosCreateFile(LPWORD Handle,
|
||||||
return (WORD)GetLastError();
|
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));
|
||||||
|
|
||||||
|
Descriptor->Attributes = LOBYTE(GetFileAttributesA(FilePath));
|
||||||
|
Descriptor->Size = GetFileSize(FileHandle, NULL);
|
||||||
|
Descriptor->OwnerPsp = CurrentPsp;
|
||||||
|
Descriptor->Win32Handle = FileHandle;
|
||||||
|
|
||||||
/* Open the DOS handle */
|
/* Open the DOS handle */
|
||||||
DosHandle = DosOpenHandle(FileHandle);
|
DosHandle = DosOpenHandle(DescriptorId);
|
||||||
if (DosHandle == INVALID_DOS_HANDLE)
|
if (DosHandle == INVALID_DOS_HANDLE)
|
||||||
{
|
{
|
||||||
/* Close the file and return the error code */
|
/* Close the file and return the error code */
|
||||||
|
@ -285,12 +438,11 @@ WORD DosOpenFile(LPWORD Handle,
|
||||||
LPCSTR FilePath,
|
LPCSTR FilePath,
|
||||||
BYTE AccessShareModes)
|
BYTE AccessShareModes)
|
||||||
{
|
{
|
||||||
HANDLE FileHandle;
|
HANDLE FileHandle = NULL;
|
||||||
ACCESS_MASK AccessMode = 0;
|
PDOS_DEVICE_NODE Node;
|
||||||
DWORD ShareMode = 0;
|
|
||||||
BOOL InheritableFile = FALSE;
|
|
||||||
SECURITY_ATTRIBUTES SecurityAttributes;
|
|
||||||
WORD DosHandle;
|
WORD DosHandle;
|
||||||
|
BYTE DescriptorId;
|
||||||
|
PDOS_FILE_DESCRIPTOR Descriptor;
|
||||||
|
|
||||||
DPRINT("DosOpenFile: FilePath \"%s\", AccessShareModes 0x%04X\n",
|
DPRINT("DosOpenFile: FilePath \"%s\", AccessShareModes 0x%04X\n",
|
||||||
FilePath, AccessShareModes);
|
FilePath, AccessShareModes);
|
||||||
|
@ -300,6 +452,18 @@ WORD DosOpenFile(LPWORD Handle,
|
||||||
// explains what those AccessShareModes are (see the uStyle flag).
|
// explains what those AccessShareModes are (see the uStyle flag).
|
||||||
//
|
//
|
||||||
|
|
||||||
|
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 */
|
/* Parse the access mode */
|
||||||
switch (AccessShareModes & 0x03)
|
switch (AccessShareModes & 0x03)
|
||||||
{
|
{
|
||||||
|
@ -377,9 +541,36 @@ WORD DosOpenFile(LPWORD Handle,
|
||||||
/* Return the error code */
|
/* Return the error code */
|
||||||
return (WORD)GetLastError();
|
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 */
|
/* Open the DOS handle */
|
||||||
DosHandle = DosOpenHandle(FileHandle);
|
DosHandle = DosOpenHandle(DescriptorId);
|
||||||
if (DosHandle == INVALID_DOS_HANDLE)
|
if (DosHandle == INVALID_DOS_HANDLE)
|
||||||
{
|
{
|
||||||
/* Close the file and return the error code */
|
/* Close the file and return the error code */
|
||||||
|
@ -398,27 +589,39 @@ WORD DosReadFile(WORD FileHandle,
|
||||||
LPWORD BytesRead)
|
LPWORD BytesRead)
|
||||||
{
|
{
|
||||||
WORD Result = ERROR_SUCCESS;
|
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);
|
DPRINT("DosReadFile: FileHandle 0x%04X, Count 0x%04X\n", FileHandle, Count);
|
||||||
|
|
||||||
if (SftEntry == NULL)
|
if (Descriptor == NULL)
|
||||||
{
|
{
|
||||||
/* Invalid handle */
|
/* Invalid handle */
|
||||||
return ERROR_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;
|
DWORD BytesRead32 = 0;
|
||||||
LPVOID LocalBuffer = RtlAllocateHeap(RtlGetProcessHeap(), 0, Count);
|
LPVOID LocalBuffer = RtlAllocateHeap(RtlGetProcessHeap(), 0, Count);
|
||||||
ASSERT(LocalBuffer != NULL);
|
ASSERT(LocalBuffer != NULL);
|
||||||
|
|
||||||
/* Read the file */
|
/* Read the file */
|
||||||
if (ReadFile(SftEntry->Handle, LocalBuffer, Count, &BytesRead32, NULL))
|
if (ReadFile(Descriptor->Win32Handle, LocalBuffer, Count, &BytesRead32, NULL))
|
||||||
{
|
{
|
||||||
/* Write to the memory */
|
/* Write to the memory */
|
||||||
MemWrite(TO_LINEAR(HIWORD(Buffer), LOWORD(Buffer)), LocalBuffer, LOWORD(BytesRead32));
|
MemWrite(TO_LINEAR(HIWORD(Buffer), LOWORD(Buffer)), LocalBuffer, LOWORD(BytesRead32));
|
||||||
|
|
||||||
|
/* Update the position */
|
||||||
|
Descriptor->Position += BytesRead32;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -430,19 +633,6 @@ WORD DosReadFile(WORD FileHandle,
|
||||||
*BytesRead = LOWORD(BytesRead32);
|
*BytesRead = LOWORD(BytesRead32);
|
||||||
RtlFreeHeap(RtlGetProcessHeap(), 0, LocalBuffer);
|
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 */
|
/* Return the error code */
|
||||||
return Result;
|
return Result;
|
||||||
|
@ -454,17 +644,26 @@ WORD DosWriteFile(WORD FileHandle,
|
||||||
LPWORD BytesWritten)
|
LPWORD BytesWritten)
|
||||||
{
|
{
|
||||||
WORD Result = ERROR_SUCCESS;
|
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);
|
DPRINT("DosWriteFile: FileHandle 0x%04X, Count 0x%04X\n", FileHandle, Count);
|
||||||
|
|
||||||
if (SftEntry == NULL)
|
if (Descriptor == NULL)
|
||||||
{
|
{
|
||||||
/* Invalid handle */
|
/* Invalid handle */
|
||||||
return ERROR_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;
|
DWORD BytesWritten32 = 0;
|
||||||
LPVOID LocalBuffer = RtlAllocateHeap(RtlGetProcessHeap(), 0, Count);
|
LPVOID LocalBuffer = RtlAllocateHeap(RtlGetProcessHeap(), 0, Count);
|
||||||
|
@ -474,7 +673,13 @@ WORD DosWriteFile(WORD FileHandle,
|
||||||
MemRead(TO_LINEAR(HIWORD(Buffer), LOWORD(Buffer)), LocalBuffer, Count);
|
MemRead(TO_LINEAR(HIWORD(Buffer), LOWORD(Buffer)), LocalBuffer, Count);
|
||||||
|
|
||||||
/* Write the file */
|
/* 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 */
|
/* Store the error code */
|
||||||
Result = (WORD)GetLastError();
|
Result = (WORD)GetLastError();
|
||||||
|
@ -484,19 +689,6 @@ WORD DosWriteFile(WORD FileHandle,
|
||||||
*BytesWritten = LOWORD(BytesWritten32);
|
*BytesWritten = LOWORD(BytesWritten32);
|
||||||
RtlFreeHeap(RtlGetProcessHeap(), 0, LocalBuffer);
|
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 */
|
/* Return the error code */
|
||||||
return Result;
|
return Result;
|
||||||
|
@ -509,25 +701,20 @@ WORD DosSeekFile(WORD FileHandle,
|
||||||
{
|
{
|
||||||
WORD Result = ERROR_SUCCESS;
|
WORD Result = ERROR_SUCCESS;
|
||||||
DWORD FilePointer;
|
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",
|
DPRINT("DosSeekFile: FileHandle 0x%04X, Offset 0x%08X, Origin 0x%02X\n",
|
||||||
FileHandle,
|
FileHandle,
|
||||||
Offset,
|
Offset,
|
||||||
Origin);
|
Origin);
|
||||||
|
|
||||||
if (SftEntry == NULL)
|
if (Descriptor == NULL)
|
||||||
{
|
{
|
||||||
/* Invalid handle */
|
/* Invalid handle */
|
||||||
return ERROR_INVALID_HANDLE;
|
return ERROR_INVALID_HANDLE;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (SftEntry->Type == DOS_SFT_ENTRY_NONE)
|
if (Descriptor->DeviceInfo & (1 << 7))
|
||||||
{
|
|
||||||
/* Invalid handle */
|
|
||||||
return ERROR_INVALID_HANDLE;
|
|
||||||
}
|
|
||||||
else if (SftEntry->Type == DOS_SFT_ENTRY_DEVICE)
|
|
||||||
{
|
{
|
||||||
/* For character devices, always return success */
|
/* For character devices, always return success */
|
||||||
return ERROR_SUCCESS;
|
return ERROR_SUCCESS;
|
||||||
|
@ -539,7 +726,7 @@ WORD DosSeekFile(WORD FileHandle,
|
||||||
return ERROR_INVALID_FUNCTION;
|
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 */
|
/* Check if there's a possibility the operation failed */
|
||||||
if (FilePointer == INVALID_SET_FILE_POINTER)
|
if (FilePointer == INVALID_SET_FILE_POINTER)
|
||||||
|
@ -554,6 +741,9 @@ WORD DosSeekFile(WORD FileHandle,
|
||||||
return Result;
|
return Result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Update the descriptor */
|
||||||
|
Descriptor->Position = FilePointer;
|
||||||
|
|
||||||
/* Return the file pointer, if requested */
|
/* Return the file pointer, if requested */
|
||||||
if (NewOffset) *NewOffset = FilePointer;
|
if (NewOffset) *NewOffset = FilePointer;
|
||||||
|
|
||||||
|
@ -563,38 +753,164 @@ WORD DosSeekFile(WORD FileHandle,
|
||||||
|
|
||||||
BOOL DosFlushFileBuffers(WORD FileHandle)
|
BOOL DosFlushFileBuffers(WORD FileHandle)
|
||||||
{
|
{
|
||||||
PDOS_SFT_ENTRY SftEntry = DosGetSftEntry(FileHandle);
|
PDOS_FILE_DESCRIPTOR Descriptor = DosGetHandleFileDescriptor(FileHandle);
|
||||||
|
|
||||||
if (SftEntry == NULL)
|
if (Descriptor == NULL)
|
||||||
{
|
{
|
||||||
/* Invalid handle */
|
/* Invalid handle */
|
||||||
return ERROR_INVALID_HANDLE;
|
DosLastError = ERROR_INVALID_HANDLE;
|
||||||
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (SftEntry->Type)
|
if (Descriptor->DeviceInfo & (1 << 7))
|
||||||
{
|
{
|
||||||
case DOS_SFT_ENTRY_WIN32:
|
PDOS_DEVICE_NODE Node = DosGetDriverNode(Descriptor->DevicePointer);
|
||||||
{
|
|
||||||
return FlushFileBuffers(SftEntry->Handle);
|
|
||||||
}
|
|
||||||
|
|
||||||
case DOS_SFT_ENTRY_DEVICE:
|
if (Node->FlushInputRoutine) Node->FlushInputRoutine(Node);
|
||||||
{
|
if (Node->FlushOutputRoutine) Node->FlushOutputRoutine(Node);
|
||||||
if (SftEntry->DeviceNode->FlushInputRoutine)
|
|
||||||
SftEntry->DeviceNode->FlushInputRoutine(SftEntry->DeviceNode);
|
|
||||||
|
|
||||||
if (SftEntry->DeviceNode->FlushOutputRoutine)
|
|
||||||
SftEntry->DeviceNode->FlushOutputRoutine(SftEntry->DeviceNode);
|
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return FlushFileBuffers(Descriptor->Win32Handle);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
default:
|
BOOLEAN DosLockFile(WORD DosHandle, DWORD Offset, DWORD Size)
|
||||||
|
{
|
||||||
|
PDOS_FILE_DESCRIPTOR Descriptor = DosGetHandleFileDescriptor(DosHandle);
|
||||||
|
|
||||||
|
if (Descriptor == NULL)
|
||||||
{
|
{
|
||||||
/* Invalid handle */
|
/* 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:
|
||||||
|
{
|
||||||
|
DPRINT1("Unsupported IOCTL: 0x%02X\n", ControlCode);
|
||||||
|
|
||||||
|
DosLastError = ERROR_INVALID_PARAMETER;
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* EOF */
|
/* EOF */
|
||||||
|
|
108
reactos/subsystems/mvdm/ntvdm/dos/dos32krnl/dosfiles.h
Normal file
108
reactos/subsystems/mvdm/ntvdm/dos/dos32krnl/dosfiles.h
Normal file
|
@ -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)
|
378
reactos/subsystems/mvdm/ntvdm/dos/dos32krnl/handle.c
Normal file
378
reactos/subsystems/mvdm/ntvdm/dos/dos32krnl/handle.c
Normal file
|
@ -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;
|
||||||
|
}
|
21
reactos/subsystems/mvdm/ntvdm/dos/dos32krnl/handle.h
Normal file
21
reactos/subsystems/mvdm/ntvdm/dos/dos32krnl/handle.h
Normal file
|
@ -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);
|
Loading…
Reference in a new issue