* Fast486 386/486 CPU Emulation Library
* common.c
*
- * Copyright (C) 2014 Aleksandar Andrejevic <theflash AT sdf DOT lonestar DOT org>
+ * Copyright (C) 2015 Aleksandar Andrejevic <theflash AT sdf DOT lonestar DOT org>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
static inline BOOLEAN
FASTCALL
Fast486InterruptInternal(PFAST486_STATE State,
- PFAST486_IDT_ENTRY IdtEntry)
+ PFAST486_IDT_ENTRY IdtEntry,
+ BOOLEAN PushErrorCode,
+ ULONG ErrorCode)
{
USHORT SegmentSelector = IdtEntry->Selector;
ULONG Offset = MAKELONG(IdtEntry->Offset, IdtEntry->OffsetHigh);
/* Push the instruction pointer */
if (!Fast486StackPush(State, State->InstPtr.Long)) goto Cleanup;
+ if (PushErrorCode)
+ {
+ /* Push the error code */
+ if (!Fast486StackPush(State, ErrorCode))
+ {
+ /* An exception occurred */
+ goto Cleanup;
+ }
+ }
+
if ((GateType == FAST486_IDT_INT_GATE) || (GateType == FAST486_IDT_INT_GATE_32))
{
/* Disable interrupts after a jump to an interrupt gate handler */
}
/* Perform the interrupt */
- if (!Fast486InterruptInternal(State, &IdtEntry))
+ if (!Fast486InterruptInternal(State, &IdtEntry, FALSE, 0))
{
/* Exception occurred */
return FALSE;
FAST486_EXCEPTIONS ExceptionCode,
ULONG ErrorCode)
{
+ FAST486_IDT_ENTRY IdtEntry;
+
/* Increment the exception count */
State->ExceptionCount++;
/* Restore the IP to the saved IP */
State->InstPtr = State->SavedInstPtr;
- /* Perform the interrupt */
- if (!Fast486PerformInterrupt(State, ExceptionCode))
+ /* Get the interrupt vector */
+ if (!Fast486GetIntVector(State, ExceptionCode, &IdtEntry))
{
/*
* If this function failed, that means Fast486Exception
return;
}
- if (EXCEPTION_HAS_ERROR_CODE(ExceptionCode)
- && (State->ControlRegisters[FAST486_REG_CR0] & FAST486_CR0_PE))
+ /* Perform the interrupt */
+ if (!Fast486InterruptInternal(State,
+ &IdtEntry,
+ EXCEPTION_HAS_ERROR_CODE(ExceptionCode)
+ && (State->ControlRegisters[FAST486_REG_CR0] & FAST486_CR0_PE),
+ ErrorCode))
{
- /* Push the error code */
- if (!Fast486StackPush(State, ErrorCode))
- {
- /*
- * If this function failed, that means Fast486Exception
- * was called again, so just return in this case.
- */
- return;
- }
+ /*
+ * If this function failed, that means Fast486Exception
+ * was called again, so just return in this case.
+ */
+ return;
}
/* Reset the exception count */
/* Flush the TLB */
if (State->Tlb) RtlZeroMemory(State->Tlb, NUM_TLB_ENTRIES * sizeof(ULONG));
+ /* Update the CPL */
+ State->Cpl = GET_SEGMENT_RPL(NewTss.Cs);
+
#ifndef FAST486_NO_PREFETCH
/* Context switching invalidates the prefetch */
State->PrefetchValid = FALSE;
#endif
+ /* Update the CPL */
+ State->Cpl = GET_SEGMENT_RPL(NewTss.Cs);
+
/* Load the registers */
State->InstPtr.Long = State->SavedInstPtr.Long = NewTss.Eip;
State->Flags.Long = NewTss.Eflags;
{
WORD LastError;
HANDLE FileHandle;
+ PDOS_DEVICE_NODE Node;
WORD DosHandle;
ACCESS_MASK AccessMode = 0;
DWORD ShareMode = 0;
// explains what those AccessShareModes are (see the uStyle flag).
//
- /* Parse the access mode */
- switch (AccessShareModes & 0x03)
+ Node = DosGetDevice(FilePath);
+ if (Node != NULL)
{
- /* 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;
+ if (Node->OpenRoutine) Node->OpenRoutine(Node);
}
-
- /* Parse the share mode */
- switch ((AccessShareModes >> 4) & 0x07)
+ else
{
- /* Compatibility mode */
- case 0:
- ShareMode = FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE;
- break;
+ /* Parse the access mode */
+ switch (AccessShareModes & 0x03)
+ {
+ /* Read-only */
+ case 0:
+ AccessMode = GENERIC_READ;
+ break;
- /* No sharing "DenyAll" */
- case 1:
- ShareMode = 0;
- break;
+ /* Write only */
+ case 1:
+ AccessMode = GENERIC_WRITE;
+ break;
- /* No write share "DenyWrite" */
- case 2:
- ShareMode = FILE_SHARE_READ;
- break;
+ /* Read and write */
+ case 2:
+ AccessMode = GENERIC_READ | GENERIC_WRITE;
+ break;
- /* No read share "DenyRead" */
- case 3:
- ShareMode = FILE_SHARE_WRITE;
- break;
+ /* Invalid */
+ default:
+ return ERROR_INVALID_PARAMETER;
+ }
- /* Full share "DenyNone" */
- case 4:
- ShareMode = FILE_SHARE_READ | FILE_SHARE_WRITE;
- break;
+ /* Parse the share mode */
+ switch ((AccessShareModes >> 4) & 0x07)
+ {
+ /* Compatibility mode */
+ case 0:
+ ShareMode = FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE;
+ break;
- /* Invalid */
- default:
- return ERROR_INVALID_PARAMETER;
- }
-
- /*
- * Parse the creation action flags:
- *
- * Bitfields for action:
- * Bit(s) Description
- *
- * 7-4 Action if file does not exist.
- * 0000 Fail
- * 0001 Create
- *
- * 3-0 Action if file exists.
- * 0000 Fail
- * 0001 Open
- * 0010 Replace/open
- */
- switch (CreateActionFlags)
- {
- /* If the file exists, fail, otherwise, fail also */
- case 0x00:
- // A special case is used after the call to CreateFileA if it succeeds,
- // in order to close the opened handle and return an adequate error.
- CreationDisposition = OPEN_EXISTING;
- break;
+ /* No sharing "DenyAll" */
+ case 1:
+ ShareMode = 0;
+ break;
- /* If the file exists, open it, otherwise, fail */
- case 0x01:
- CreationDisposition = OPEN_EXISTING;
- break;
+ /* No write share "DenyWrite" */
+ case 2:
+ ShareMode = FILE_SHARE_READ;
+ break;
- /* If the file exists, replace it, otherwise, fail */
- case 0x02:
- CreationDisposition = TRUNCATE_EXISTING;
- break;
+ /* No read share "DenyRead" */
+ case 3:
+ ShareMode = FILE_SHARE_WRITE;
+ break;
- /* If the file exists, fail, otherwise, create it */
- case 0x10:
- CreationDisposition = CREATE_NEW;
- break;
+ /* Full share "DenyNone" */
+ case 4:
+ ShareMode = FILE_SHARE_READ | FILE_SHARE_WRITE;
+ break;
- /* If the file exists, open it, otherwise, create it */
- case 0x11:
- CreationDisposition = OPEN_ALWAYS;
- break;
+ /* Invalid */
+ default:
+ return ERROR_INVALID_PARAMETER;
+ }
- /* If the file exists, replace it, otherwise, create it */
- case 0x12:
- CreationDisposition = CREATE_ALWAYS;
- break;
+ /*
+ * Parse the creation action flags:
+ *
+ * Bitfields for action:
+ * Bit(s) Description
+ *
+ * 7-4 Action if file does not exist.
+ * 0000 Fail
+ * 0001 Create
+ *
+ * 3-0 Action if file exists.
+ * 0000 Fail
+ * 0001 Open
+ * 0010 Replace/open
+ */
+ switch (CreateActionFlags)
+ {
+ /* If the file exists, fail, otherwise, fail also */
+ case 0x00:
+ // A special case is used after the call to CreateFileA if it succeeds,
+ // in order to close the opened handle and return an adequate error.
+ CreationDisposition = OPEN_EXISTING;
+ break;
- /* Invalid */
- default:
- return ERROR_INVALID_PARAMETER;
- }
+ /* If the file exists, open it, otherwise, fail */
+ case 0x01:
+ CreationDisposition = OPEN_EXISTING;
+ break;
- /* Check for inheritance */
- InheritableFile = ((AccessShareModes & 0x80) == 0);
+ /* If the file exists, replace it, otherwise, fail */
+ case 0x02:
+ CreationDisposition = TRUNCATE_EXISTING;
+ break;
- /* Assign default security attributes to the file, and set the inheritance flag */
- SecurityAttributes.nLength = sizeof(SecurityAttributes);
- SecurityAttributes.lpSecurityDescriptor = NULL;
- SecurityAttributes.bInheritHandle = InheritableFile;
+ /* If the file exists, fail, otherwise, create it */
+ case 0x10:
+ CreationDisposition = CREATE_NEW;
+ break;
- /* Open the file */
- FileHandle = CreateFileA(FilePath,
- AccessMode,
- ShareMode,
- &SecurityAttributes,
- CreationDisposition,
- Attributes,
- NULL);
+ /* If the file exists, open it, otherwise, create it */
+ case 0x11:
+ CreationDisposition = OPEN_ALWAYS;
+ break;
- LastError = (WORD)GetLastError();
+ /* If the file exists, replace it, otherwise, create it */
+ case 0x12:
+ CreationDisposition = CREATE_ALWAYS;
+ break;
- if (FileHandle == INVALID_HANDLE_VALUE)
- {
- /* Return the error code */
- return LastError;
- }
+ /* Invalid */
+ default:
+ return ERROR_INVALID_PARAMETER;
+ }
- /*
- * Special case: CreateActionFlags == 0, we must fail because
- * the file exists (if it didn't exist we already failed).
- */
- if (CreateActionFlags == 0)
- {
- /* Close the file and return the error code */
- CloseHandle(FileHandle);
- return ERROR_FILE_EXISTS;
- }
+ /* Check for inheritance */
+ InheritableFile = ((AccessShareModes & 0x80) == 0);
- /* Set the creation status */
- switch (CreateActionFlags)
- {
- case 0x01:
- *CreationStatus = 0x01; // The file was opened
- break;
+ /* Assign default security attributes to the file, and set the inheritance flag */
+ SecurityAttributes.nLength = sizeof(SecurityAttributes);
+ SecurityAttributes.lpSecurityDescriptor = NULL;
+ SecurityAttributes.bInheritHandle = InheritableFile;
- case 0x02:
- *CreationStatus = 0x03; // The file was replaced
- break;
+ /* Open the file */
+ FileHandle = CreateFileA(FilePath,
+ AccessMode,
+ ShareMode,
+ &SecurityAttributes,
+ CreationDisposition,
+ Attributes,
+ NULL);
- case 0x10:
- *CreationStatus = 0x02; // The file was created
- break;
+ LastError = (WORD)GetLastError();
- case 0x11:
+ if (FileHandle == INVALID_HANDLE_VALUE)
{
- if (LastError == ERROR_ALREADY_EXISTS)
- *CreationStatus = 0x01; // The file was opened
- else
- *CreationStatus = 0x02; // The file was created
+ /* Return the error code */
+ return LastError;
+ }
- break;
+ /*
+ * Special case: CreateActionFlags == 0, we must fail because
+ * the file exists (if it didn't exist we already failed).
+ */
+ if (CreateActionFlags == 0)
+ {
+ /* Close the file and return the error code */
+ CloseHandle(FileHandle);
+ return ERROR_FILE_EXISTS;
}
- case 0x12:
+ /* Set the creation status */
+ switch (CreateActionFlags)
{
- if (LastError == ERROR_ALREADY_EXISTS)
+ case 0x01:
+ *CreationStatus = 0x01; // The file was opened
+ break;
+
+ case 0x02:
*CreationStatus = 0x03; // The file was replaced
- else
+ break;
+
+ case 0x10:
*CreationStatus = 0x02; // The file was created
+ break;
- break;
+ case 0x11:
+ {
+ if (LastError == ERROR_ALREADY_EXISTS)
+ *CreationStatus = 0x01; // The file was opened
+ else
+ *CreationStatus = 0x02; // The file was created
+
+ break;
+ }
+
+ case 0x12:
+ {
+ if (LastError == ERROR_ALREADY_EXISTS)
+ *CreationStatus = 0x03; // The file was replaced
+ else
+ *CreationStatus = 0x02; // The file was created
+
+ break;
+ }
}
}
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;
+ 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(DescriptorId);
WORD Attributes)
{
HANDLE FileHandle;
+ PDOS_DEVICE_NODE Node;
WORD DosHandle;
BYTE DescriptorId;
PDOS_FILE_DESCRIPTOR Descriptor;
DPRINT("DosCreateFile: FilePath \"%s\", CreationDisposition 0x%04X, Attributes 0x%04X\n",
FilePath, CreationDisposition, Attributes);
- /* Create the file */
- FileHandle = CreateFileA(FilePath,
- GENERIC_READ | GENERIC_WRITE,
- FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
- NULL,
- CreationDisposition,
- Attributes,
- NULL);
- if (FileHandle == INVALID_HANDLE_VALUE)
+ Node = DosGetDevice(FilePath);
+ if (Node != NULL)
+ {
+ if (Node->OpenRoutine) Node->OpenRoutine(Node);
+ }
+ else
{
- /* Return the error code */
- return (WORD)GetLastError();
+ /* Create the file */
+ FileHandle = CreateFileA(FilePath,
+ GENERIC_READ | GENERIC_WRITE,
+ FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
+ NULL,
+ CreationDisposition,
+ Attributes,
+ NULL);
+ if (FileHandle == INVALID_HANDLE_VALUE)
+ {
+ /* Return the error code */
+ return (WORD)GetLastError();
+ }
}
DescriptorId = DosFindFreeDescriptor();
Descriptor = DosGetFileDescriptor(DescriptorId);
RtlZeroMemory(Descriptor, sizeof(*Descriptor));
- Descriptor->Attributes = LOBYTE(GetFileAttributesA(FilePath));
- Descriptor->Size = GetFileSize(FileHandle, NULL);
- Descriptor->OwnerPsp = CurrentPsp;
- Descriptor->Win32Handle = FileHandle;
+ if (Node != NULL)
+ {
+ Descriptor->DevicePointer = Node->Driver;
+ Descriptor->DeviceInfo = Node->DeviceAttributes | (1 << 7);
+ }
+ else
+ {
+ Descriptor->Attributes = LOBYTE(GetFileAttributesA(FilePath));
+ Descriptor->Size = GetFileSize(FileHandle, NULL);
+ Descriptor->OwnerPsp = CurrentPsp;
+ Descriptor->Win32Handle = FileHandle;
+ }
/* Open the DOS handle */
DosHandle = DosOpenHandle(DescriptorId);