Implement several INT 21h functions.


svn path=/branches/ntvdm/; revision=59563
This commit is contained in:
Aleksandar Andrejevic 2013-07-23 14:43:03 +00:00
parent be2e1f0907
commit 7bcfe7b2a8
2 changed files with 241 additions and 0 deletions

View file

@ -704,6 +704,87 @@ WORD DosWriteFile(WORD FileHandle, LPVOID Buffer, WORD Count, LPWORD BytesWritte
return Result;
}
WORD DosSeekFile(WORD FileHandle, LONG Offset, BYTE Origin, LPDWORD NewOffset)
{
WORD Result = ERROR_SUCCESS;
DWORD FilePointer;
HANDLE Handle = DosGetRealHandle(FileHandle);
DPRINT("DosSeekFile: FileHandle 0x%04X, Offset 0x%08X, Origin 0x%02X\n",
FileHandle,
Offset,
Origin);
/* Make sure the handle is valid */
if (Handle == INVALID_HANDLE_VALUE) return ERROR_INVALID_HANDLE;
/* Check if the origin is valid */
if (Origin != FILE_BEGIN && Origin != FILE_CURRENT && Origin != FILE_END)
{
return ERROR_INVALID_FUNCTION;
}
/* Move the file pointer */
FilePointer = SetFilePointer(Handle, Offset, NULL, Origin);
/* Check if there's a possibility the operation failed */
if (FilePointer == INVALID_SET_FILE_POINTER)
{
/* Get the real error code */
Result = GetLastError();
}
if (Result != ERROR_SUCCESS)
{
/* The operation did fail */
return Result;
}
/* Return the file pointer, if requested */
if (NewOffset) *NewOffset = FilePointer;
/* Return success */
return ERROR_SUCCESS;
}
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];
DosSftRefCount[SftIndex]++;
/* Make the new handle point to that SFT entry */
HandleTable[NewHandle] = SftIndex;
/* Return success */
return TRUE;
}
BOOLEAN DosCloseHandle(WORD DosHandle)
{
BYTE SftIndex;
@ -736,6 +817,9 @@ BOOLEAN DosCloseHandle(WORD DosHandle)
DosSystemFileTable[SftIndex] = INVALID_HANDLE_VALUE;
}
/* Clear the entry in the JFT */
HandleTable[DosHandle] = 0xFF;
return TRUE;
}
@ -1547,6 +1631,102 @@ VOID DosInt21h(WORD CodeSegment)
break;
}
/* Delete File */
case 0x41:
{
LPSTR FileName = (LPSTR)((ULONG_PTR)BaseAddress + TO_LINEAR(DataSegment, Edx));
/* Call the API function */
if (DeleteFileA(FileName)) EmulatorClearFlag(EMULATOR_FLAG_CF);
else
{
EmulatorSetFlag(EMULATOR_FLAG_CF);
EmulatorSetRegister(EMULATOR_REG_AX, GetLastError());
}
break;
}
/* Seek File */
case 0x42:
{
DWORD NewLocation;
WORD ErrorCode = DosSeekFile(LOWORD(Ebx),
MAKELONG(LOWORD(Edx), LOWORD(Ecx)),
LOBYTE(Eax),
&NewLocation);
if (ErrorCode == 0)
{
/* Clear CF */
EmulatorClearFlag(EMULATOR_FLAG_CF);
/* Return the new offset in DX:AX */
EmulatorSetRegister(EMULATOR_REG_DX,
(Edx & 0xFFFF0000) | HIWORD(NewLocation));
EmulatorSetRegister(EMULATOR_REG_AX,
(Eax & 0xFFFF0000) | LOWORD(NewLocation));
}
else
{
/* Set CF */
EmulatorSetFlag(EMULATOR_FLAG_CF);
/* Return the error code in AX */
EmulatorSetRegister(EMULATOR_REG_AX,
(Eax & 0xFFFF0000) | ErrorCode);
}
break;
}
/* Get/Set File Attributes */
case 0x43:
{
DWORD Attributes;
LPSTR FileName = (LPSTR)((ULONG_PTR)BaseAddress + TO_LINEAR(DataSegment, Edx));
if (LOBYTE(Eax) == 0x00)
{
/* Get the attributes */
Attributes = GetFileAttributesA(FileName);
/* Check if it failed */
if (Attributes == INVALID_FILE_ATTRIBUTES)
{
EmulatorSetFlag(EMULATOR_FLAG_CF);
EmulatorSetRegister(EMULATOR_REG_AX, GetLastError());
break;
}
/* Return the attributes that DOS can understand */
EmulatorClearFlag(EMULATOR_FLAG_CF);
EmulatorSetRegister(EMULATOR_REG_CX,
(Ecx & 0xFFFFFF00) | LOBYTE(Attributes));
}
else if (LOBYTE(Eax) == 0x01)
{
/* Try to set the attributes */
if (SetFileAttributesA(FileName, LOBYTE(Ecx)))
{
EmulatorClearFlag(EMULATOR_FLAG_CF);
}
else
{
EmulatorSetFlag(EMULATOR_FLAG_CF);
EmulatorSetRegister(EMULATOR_REG_AX, GetLastError());
}
}
else
{
EmulatorSetFlag(EMULATOR_FLAG_CF);
EmulatorSetRegister(EMULATOR_REG_AX, ERROR_INVALID_FUNCTION);
}
break;
}
/* IOCTL */
case 0x44:
{
@ -1555,6 +1735,56 @@ VOID DosInt21h(WORD CodeSegment)
break;
}
/* Duplicate Handle */
case 0x45:
{
WORD NewHandle;
HANDLE Handle = DosGetRealHandle(LOWORD(Ebx));
if (Handle != INVALID_HANDLE_VALUE)
{
/* The handle is invalid */
EmulatorSetFlag(EMULATOR_FLAG_CF);
EmulatorSetRegister(EMULATOR_REG_AX, ERROR_INVALID_HANDLE);
break;
}
/* Open a new handle to the same entry */
NewHandle = DosOpenHandle(Handle);
if (NewHandle == INVALID_DOS_HANDLE)
{
/* Too many files open */
EmulatorSetFlag(EMULATOR_FLAG_CF);
EmulatorSetRegister(EMULATOR_REG_AX, ERROR_TOO_MANY_OPEN_FILES);
break;
}
/* Return the result */
EmulatorClearFlag(EMULATOR_FLAG_CF);
EmulatorSetRegister(EMULATOR_REG_AX, NewHandle);
break;
}
/* Force Duplicate Handle */
case 0x46:
{
if (DosDuplicateHandle(LOWORD(Ebx), LOWORD(Ecx)))
{
EmulatorClearFlag(EMULATOR_FLAG_CF);
}
else
{
EmulatorSetFlag(EMULATOR_FLAG_CF);
EmulatorSetRegister(EMULATOR_REG_AX, ERROR_INVALID_HANDLE);
}
break;
}
/* Allocate Memory */
case 0x48:
{
@ -1618,6 +1848,14 @@ VOID DosInt21h(WORD CodeSegment)
break;
}
/* Get Current Process */
case 0x51:
{
EmulatorSetRegister(EMULATOR_REG_BX, CurrentPsp);
break;
}
/* Get/Set Memory Management Options */
case 0x58:
{

View file

@ -109,6 +109,9 @@ WORD DosCreateFile(LPWORD Handle, LPCSTR FilePath, WORD Attributes);
WORD DosOpenFile(LPWORD Handle, LPCSTR FilePath, BYTE AccessMode);
WORD DosReadFile(WORD FileHandle, LPVOID Buffer, WORD Count, LPWORD BytesRead);
WORD DosWriteFile(WORD FileHandle, LPVOID Buffer, WORD Count, LPWORD BytesWritten);
WORD DosSeekFile(WORD FileHandle, LONG Offset, BYTE Origin, LPDWORD NewOffset);
BOOLEAN DosDuplicateHandle(WORD OldHandle, WORD NewHandle);
BOOLEAN DosCloseHandle(WORD DosHandle);
VOID DosInitializePsp(WORD PspSegment, LPCSTR CommandLine, WORD ProgramSize, WORD Environment);
BOOLEAN DosCreateProcess(LPCSTR CommandLine, WORD EnvBlock);
VOID DosTerminateProcess(WORD Psp, BYTE ReturnCode);