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);