[NTVDM]
authorHermès Bélusca-Maïto <hermes.belusca-maito@reactos.org>
Thu, 2 Oct 2014 00:26:13 +0000 (00:26 +0000)
committerHermès Bélusca-Maïto <hermes.belusca-maito@reactos.org>
Thu, 2 Oct 2014 00:26:13 +0000 (00:26 +0000)
- INT 21h, AH=59h (Get Extended Error Information) is unimplemented but is used by many applications. DPRINT a special message to remind that we need to implement it.
- Implement INT 21h, AH=6Ch "Extended Open/Create".

svn path=/trunk/; revision=64447

reactos/subsystems/ntvdm/dos/dos32krnl/dos.c
reactos/subsystems/ntvdm/dos/dos32krnl/dos.h
reactos/subsystems/ntvdm/dos/dos32krnl/dosfiles.c

index 0023d7c..d66b3d0 100644 (file)
@@ -2579,6 +2579,14 @@ VOID WINAPI DosInt21h(LPWORD Stack)
             break;
         }
 
+        /* Get Extended Error Information */
+        case 0x59:
+        {
+            DPRINT1("INT 21h, AH = 59h, BX = %04Xh - Get Extended Error Information is UNIMPLEMENTED\n",
+                    getBX());
+            break;
+        }
+
         /* Create Temporary File */
         case 0x5A:
         {
@@ -2775,6 +2783,10 @@ VOID WINAPI DosInt21h(LPWORD Stack)
         /* Extended Open/Create */
         case 0x6C:
         {
+            WORD FileHandle;
+            WORD CreationStatus;
+            WORD ErrorCode;
+
             /* Check for AL == 00 */
             if (getAL() != 0x00)
             {
@@ -2783,10 +2795,31 @@ VOID WINAPI DosInt21h(LPWORD Stack)
                 break;
             }
 
-            // TODO!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
-            // FIXME: Extend and merge DosOpenFile and DosCreateFile into
-            // a single wrapper around CreateFileA, which acts as:
-            // http://www.ctyme.com/intr/rb-3179.htm
+            /*
+             * See Ralf Brown: http://www.ctyme.com/intr/rb-3179.htm
+             * for the full detailed description.
+             *
+             * WARNING: BH contains some extended flags that are NOT SUPPORTED.
+             */
+
+            ErrorCode = DosCreateFileEx(&FileHandle,
+                                        &CreationStatus,
+                                        (LPCSTR)SEG_OFF_TO_PTR(getDS(), getSI()),
+                                        getBL(),
+                                        getDL(),
+                                        getCX());
+
+            if (ErrorCode == ERROR_SUCCESS)
+            {
+                Stack[STACK_FLAGS] &= ~EMULATOR_FLAG_CF;
+                setCX(CreationStatus);
+                setAX(FileHandle);
+            }
+            else
+            {
+                Stack[STACK_FLAGS] |= EMULATOR_FLAG_CF;
+                setAX(ErrorCode);
+            }
 
             break;
         }
index 7e6e3c4..0a01817 100644 (file)
@@ -192,11 +192,31 @@ BOOL IsConsoleHandle(HANDLE hHandle);
 WORD DosOpenHandle(HANDLE Handle);
 HANDLE DosGetRealHandle(WORD DosHandle);
 
-WORD DosCreateFile(LPWORD Handle, LPCSTR FilePath, WORD CreationFlags, WORD Attributes);
-WORD DosOpenFile(LPWORD Handle, LPCSTR FilePath, BYTE AccessShareModes);
-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);
+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,
+                 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);
 BOOL DosFlushFileBuffers(WORD FileHandle);
 
 VOID DosInitializePsp(WORD PspSegment, LPCSTR CommandLine, WORD ProgramSize, WORD Environment);
index e5560b2..9bf4d08 100644 (file)
 #define NDEBUG
 
 #include "emulator.h"
-// #include "callback.h"
 
 #include "dos.h"
 #include "dos/dem.h"
 
 #include "bios/bios.h"
 
-/* PRIVATE VARIABLES **********************************************************/
-
 /* PUBLIC FUNCTIONS ***********************************************************/
 
-WORD DosCreateFile(LPWORD Handle, LPCSTR FilePath, WORD CreationFlags, WORD Attributes)
+WORD DosCreateFileEx(LPWORD Handle,
+                     LPWORD CreationStatus,
+                     LPCSTR FilePath,
+                     BYTE AccessShareModes,
+                     WORD CreateActionFlags,
+                     WORD Attributes)
 {
+    WORD LastError;
     HANDLE FileHandle;
     WORD DosHandle;
+    ACCESS_MASK AccessMode = 0;
+    DWORD ShareMode = 0;
+    DWORD CreationDisposition = 0;
+    BOOL InheritableFile = FALSE;
+    SECURITY_ATTRIBUTES SecurityAttributes;
+
+    DPRINT1("DosCreateFileEx: FilePath \"%s\", AccessShareModes 0x%04X, CreateActionFlags 0x%04X, Attributes 0x%04X\n",
+           FilePath, AccessShareModes, CreateActionFlags, Attributes);
+
+    //
+    // The article about OpenFile API: http://msdn.microsoft.com/en-us/library/windows/desktop/aa365430(v=vs.85).aspx
+    // explains what are those AccessShareModes (see the uStyle flag).
+    //
+
+    /* Parse the access mode */
+    switch (AccessShareModes & 0x03)
+    {
+        /* 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;
+    }
+
+    /* Parse the share mode */
+    switch ((AccessShareModes >> 4) & 0x07)
+    {
+        /* Compatibility mode */
+        case 0:
+            ShareMode = FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE;
+            break;
+
+        /* No sharing "DenyAll" */
+        case 1:
+            ShareMode = 0;
+            break;
+
+        /* No write share "DenyWrite" */
+        case 2:
+            ShareMode = FILE_SHARE_READ;
+            break;
 
-    DPRINT("DosCreateFile: FilePath \"%s\", CreationFlags 0x%04X, Attributes 0x%04X\n",
-            FilePath,
-            CreationFlags,
-            Attributes);
+        /* No read share "DenyRead" */
+        case 3:
+            ShareMode = FILE_SHARE_WRITE;
+            break;
+
+        /* Full share "DenyNone" */
+        case 4:
+            ShareMode = FILE_SHARE_READ | FILE_SHARE_WRITE;
+            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;
+
+        /* If the file exists, open it, otherwise, fail */
+        case 0x01:
+            CreationDisposition = OPEN_EXISTING;
+            break;
+
+        /* If the file exists, replace it, otherwise, fail */
+        case 0x02:
+            CreationDisposition = TRUNCATE_EXISTING;
+            break;
+
+        /* If the file exists, fail, otherwise, create it */
+        case 0x10:
+            CreationDisposition = CREATE_NEW;
+            break;
+
+        /* If the file exists, open it, otherwise, create it */
+        case 0x11:
+            CreationDisposition = OPEN_ALWAYS;
+            break;
+
+        /* If the file exists, replace it, otherwise, create it */
+        case 0x12:
+            CreationDisposition = CREATE_ALWAYS;
+            break;
+
+        /* Invalid */
+        default:
+            return ERROR_INVALID_PARAMETER;
+    }
+
+    /* Check for inheritance */
+    InheritableFile = ((AccessShareModes & 0x80) == 0);
+
+    /* Assign default security attributes to the file, and set the inheritance flag */
+    SecurityAttributes.nLength = sizeof(SecurityAttributes);
+    SecurityAttributes.lpSecurityDescriptor = NULL;
+    SecurityAttributes.bInheritHandle = InheritableFile;
+
+    /* Open the file */
+    FileHandle = CreateFileA(FilePath,
+                             AccessMode,
+                             ShareMode,
+                             &SecurityAttributes,
+                             CreationDisposition,
+                             Attributes,
+                             NULL);
+
+    LastError = (WORD)GetLastError();
+
+    if (FileHandle == INVALID_HANDLE_VALUE)
+    {
+        /* Return the error code */
+        return LastError;
+    }
+
+    /*
+     * 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;
+    }
+
+    /* Set the creation status */
+    switch (CreateActionFlags)
+    {
+        case 0x01:
+            *CreationStatus = 0x01; // The file was opened
+            break;
+
+        case 0x02:
+            *CreationStatus = 0x03; // The file was replaced
+            break;
+
+        case 0x10:
+            *CreationStatus = 0x02; // The file was created
+            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;
+        }
+    }
+
+    /* Open the DOS handle */
+    DosHandle = DosOpenHandle(FileHandle);
+
+    if (DosHandle == INVALID_DOS_HANDLE)
+    {
+        /* Close the file and return the error code */
+        CloseHandle(FileHandle);
+        return ERROR_TOO_MANY_OPEN_FILES;
+    }
+
+    /* It was successful */
+    *Handle = DosHandle;
+    return ERROR_SUCCESS;
+}
+
+WORD DosCreateFile(LPWORD Handle,
+                   LPCSTR FilePath,
+                   DWORD CreationDisposition,
+                   WORD Attributes)
+{
+    HANDLE FileHandle;
+    WORD DosHandle;
+
+    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,
-                             CreationFlags,
+                             CreationDisposition,
                              Attributes,
                              NULL);
-
     if (FileHandle == INVALID_HANDLE_VALUE)
     {
         /* Return the error code */
@@ -53,10 +271,8 @@ WORD DosCreateFile(LPWORD Handle, LPCSTR FilePath, WORD CreationFlags, WORD Attr
 
     if (DosHandle == INVALID_DOS_HANDLE)
     {
-        /* Close the handle */
+        /* Close the file and return the error code */
         CloseHandle(FileHandle);
-
-        /* Return the error code */
         return ERROR_TOO_MANY_OPEN_FILES;
     }
 
@@ -65,7 +281,9 @@ WORD DosCreateFile(LPWORD Handle, LPCSTR FilePath, WORD CreationFlags, WORD Attr
     return ERROR_SUCCESS;
 }
 
-WORD DosOpenFile(LPWORD Handle, LPCSTR FilePath, BYTE AccessShareModes)
+WORD DosOpenFile(LPWORD Handle,
+                 LPCSTR FilePath,
+                 BYTE AccessShareModes)
 {
     HANDLE FileHandle;
     ACCESS_MASK AccessMode = 0;
@@ -75,83 +293,67 @@ WORD DosOpenFile(LPWORD Handle, LPCSTR FilePath, BYTE AccessShareModes)
     WORD DosHandle;
 
     DPRINT("DosOpenFile: FilePath \"%s\", AccessShareModes 0x%04X\n",
-            FilePath,
-            AccessShareModes);
+           FilePath, AccessShareModes);
+
+    //
+    // The article about OpenFile API: http://msdn.microsoft.com/en-us/library/windows/desktop/aa365430(v=vs.85).aspx
+    // explains what are those AccessShareModes (see the uStyle flag).
+    //
 
     /* Parse the access mode */
     switch (AccessShareModes & 0x03)
     {
+        /* Read-only */
         case 0:
-        {
-            /* Read-only */
             AccessMode = GENERIC_READ;
             break;
-        }
 
+        /* Write only */
         case 1:
-        {
-            /* Write only */
             AccessMode = GENERIC_WRITE;
             break;
-        }
 
+        /* Read and write */
         case 2:
-        {
-            /* Read and write */
             AccessMode = GENERIC_READ | GENERIC_WRITE;
             break;
-        }
 
+        /* Invalid */
         default:
-        {
-            /* Invalid */
             return ERROR_INVALID_PARAMETER;
-        }
     }
 
     /* Parse the share mode */
     switch ((AccessShareModes >> 4) & 0x07)
     {
+        /* Compatibility mode */
         case 0:
-        {
-            /* Compatibility mode */
             ShareMode = FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE;
             break;
-        }
 
+        /* No sharing "DenyAll" */
         case 1:
-        {
-            /* No sharing "DenyAll" */
             ShareMode = 0;
             break;
-        }
 
+        /* No write share "DenyWrite" */
         case 2:
-        {
-            /* No write share "DenyWrite" */
             ShareMode = FILE_SHARE_READ;
             break;
-        }
 
+        /* No read share "DenyRead" */
         case 3:
-        {
-            /* No read share "DenyRead" */
             ShareMode = FILE_SHARE_WRITE;
             break;
-        }
 
+        /* Full share "DenyNone" */
         case 4:
-        {
-            /* Full share "DenyNone" */
             ShareMode = FILE_SHARE_READ | FILE_SHARE_WRITE;
             break;
-        }
 
+        /* Invalid */
         default:
-        {
-            /* Invalid */
             return ERROR_INVALID_PARAMETER;
-        }
     }
 
     /* Check for inheritance */
@@ -170,7 +372,6 @@ WORD DosOpenFile(LPWORD Handle, LPCSTR FilePath, BYTE AccessShareModes)
                              OPEN_EXISTING,
                              FILE_ATTRIBUTE_NORMAL,
                              NULL);
-
     if (FileHandle == INVALID_HANDLE_VALUE)
     {
         /* Return the error code */
@@ -182,10 +383,8 @@ WORD DosOpenFile(LPWORD Handle, LPCSTR FilePath, BYTE AccessShareModes)
 
     if (DosHandle == INVALID_DOS_HANDLE)
     {
-        /* Close the handle */
+        /* Close the file and return the error code */
         CloseHandle(FileHandle);
-
-        /* Return the error code */
         return ERROR_TOO_MANY_OPEN_FILES;
     }
 
@@ -194,7 +393,10 @@ WORD DosOpenFile(LPWORD Handle, LPCSTR FilePath, BYTE AccessShareModes)
     return ERROR_SUCCESS;
 }
 
-WORD DosReadFile(WORD FileHandle, LPVOID Buffer, WORD Count, LPWORD BytesRead)
+WORD DosReadFile(WORD FileHandle,
+                 LPVOID Buffer,
+                 WORD Count,
+                 LPWORD BytesRead)
 {
     WORD Result = ERROR_SUCCESS;
     DWORD BytesRead32 = 0;
@@ -259,7 +461,10 @@ WORD DosReadFile(WORD FileHandle, LPVOID Buffer, WORD Count, LPWORD BytesRead)
     return Result;
 }
 
-WORD DosWriteFile(WORD FileHandle, LPVOID Buffer, WORD Count, LPWORD BytesWritten)
+WORD DosWriteFile(WORD FileHandle,
+                  LPVOID Buffer,
+                  WORD Count,
+                  LPWORD BytesWritten)
 {
     WORD Result = ERROR_SUCCESS;
     DWORD BytesWritten32 = 0;
@@ -317,7 +522,10 @@ WORD DosWriteFile(WORD FileHandle, LPVOID Buffer, WORD Count, LPWORD BytesWritte
     return Result;
 }
 
-WORD DosSeekFile(WORD FileHandle, LONG Offset, BYTE Origin, LPDWORD NewOffset)
+WORD DosSeekFile(WORD FileHandle,
+                 LONG Offset,
+                 BYTE Origin,
+                 LPDWORD NewOffset)
 {
     WORD Result = ERROR_SUCCESS;
     DWORD FilePointer;