Author: aandrejevic
Date: Tue Jul 23 14:43:03 2013
New Revision: 59563
URL:
http://svn.reactos.org/svn/reactos?rev=59563&view=rev
Log:
[NTVDM]
Implement several INT 21h functions.
Modified:
branches/ntvdm/subsystems/ntvdm/dos.c
branches/ntvdm/subsystems/ntvdm/dos.h
Modified: branches/ntvdm/subsystems/ntvdm/dos.c
URL:
http://svn.reactos.org/svn/reactos/branches/ntvdm/subsystems/ntvdm/dos.c?re…
==============================================================================
--- branches/ntvdm/subsystems/ntvdm/dos.c [iso-8859-1] (original)
+++ branches/ntvdm/subsystems/ntvdm/dos.c [iso-8859-1] Tue Jul 23 14:43:03 2013
@@ -704,13 +704,58 @@
return Result;
}
-BOOLEAN DosCloseHandle(WORD DosHandle)
+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("DosCloseHandle: DosHandle 0x%04X\n", DosHandle);
+ DPRINT("DosDuplicateHandle: OldHandle 0x%04X, NewHandle 0x%04X\n",
+ OldHandle,
+ NewHandle);
/* The system PSP has no handle table */
if (CurrentPsp == SYSTEM_PSP) return FALSE;
@@ -719,6 +764,42 @@
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;
+ PDOS_PSP PspBlock;
+ LPBYTE HandleTable;
+
+ 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;
@@ -735,6 +816,9 @@
/* Clear the handle */
DosSystemFileTable[SftIndex] = INVALID_HANDLE_VALUE;
}
+
+ /* Clear the entry in the JFT */
+ HandleTable[DosHandle] = 0xFF;
return TRUE;
}
@@ -1547,10 +1631,156 @@
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:
{
DosHandleIoctl(LOBYTE(Eax), LOWORD(Ebx));
+
+ 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;
}
@@ -1615,6 +1845,14 @@
case 0x4C:
{
DosTerminateProcess(CurrentPsp, LOBYTE(Eax));
+ break;
+ }
+
+ /* Get Current Process */
+ case 0x51:
+ {
+ EmulatorSetRegister(EMULATOR_REG_BX, CurrentPsp);
+
break;
}
Modified: branches/ntvdm/subsystems/ntvdm/dos.h
URL:
http://svn.reactos.org/svn/reactos/branches/ntvdm/subsystems/ntvdm/dos.h?re…
==============================================================================
--- branches/ntvdm/subsystems/ntvdm/dos.h [iso-8859-1] (original)
+++ branches/ntvdm/subsystems/ntvdm/dos.h [iso-8859-1] Tue Jul 23 14:43:03 2013
@@ -109,6 +109,9 @@
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);