winedos / Move create/open file routines to winedos

Jukka Heinonen jhei at iki.fi
Sat Jun 14 14:34:58 CDT 2003


Changelog:
    Migrate create/open file functions to winedos.
    Some fixes based on patch by Ferenc Wagner.




Index: dlls/winedos/int21.c
===================================================================
RCS file: /home/wine/wine/dlls/winedos/int21.c,v
retrieving revision 1.37
diff -u -r1.37 int21.c
--- dlls/winedos/int21.c	13 Jun 2003 18:05:18 -0000	1.37
+++ dlls/winedos/int21.c	14 Jun 2003 19:06:15 -0000
@@ -519,6 +519,209 @@
 
 
 /***********************************************************************
+ *           INT21_CreateFile
+ *
+ * Handler for:
+ * - function 0x3c
+ * - function 0x3d
+ * - function 0x5b
+ * - function 0x6c
+ * - subfunction 0x6c of function 0x71
+ */
+static BOOL INT21_CreateFile( CONTEXT86 *context, 
+                              DWORD      pathSegOff,
+                              BOOL       returnStatus,
+                              WORD       dosAccessShare,
+                              BYTE       dosAction )
+{
+    WORD   dosStatus;
+    char  *pathA = CTX_SEG_OFF_TO_LIN(context, context->SegDs, pathSegOff);
+    WCHAR  pathW[MAX_PATH];   
+    DWORD  winAccess;
+    DWORD  winAttributes;
+    HANDLE winHandle;
+    DWORD  winMode;
+    DWORD  winSharing;
+
+    TRACE( "CreateFile called: function=%02x, action=%02x, access/share=%04x, "
+           "create flags=%04x, file=%s.\n",
+           AH_reg(context), dosAction, dosAccessShare, CX_reg(context), pathA );
+
+    /*
+     * Application tried to create/open a file whose name 
+     * ends with a backslash. This is not allowed.
+     *
+     * FIXME: This needs to be validated, especially the return value.
+     */
+    if (pathA[strlen(pathA) - 1] == '/')
+    {
+        SetLastError( ERROR_FILE_NOT_FOUND );
+        return FALSE;
+    }
+
+    /*
+     * Convert DOS action flags into Win32 creation disposition parameter.
+     */ 
+    switch(dosAction)
+    {
+    case 0x01:
+        winMode = OPEN_EXISTING;
+        break;
+    case 0x02:
+        winMode = TRUNCATE_EXISTING;
+        break;
+    case 0x10:
+        winMode = CREATE_NEW;
+        break;
+    case 0x11:
+        winMode = OPEN_ALWAYS;
+        break;
+    case 0x12:
+        winMode = CREATE_ALWAYS;
+        break;
+    default:
+        SetLastError( ERROR_INVALID_PARAMETER );
+        return FALSE;
+    }
+
+    /*
+     * Convert DOS access/share flags into Win32 desired access parameter.
+     */ 
+    switch(dosAccessShare & 0x07)
+    {
+    case OF_READ:
+        winAccess = GENERIC_READ;
+        break;
+    case OF_WRITE:
+        winAccess = GENERIC_WRITE;
+        break;
+    case OF_READWRITE:
+        winAccess = GENERIC_READ | GENERIC_WRITE;
+        break;
+    case 0x04:
+        /*
+         * Read-only, do not modify file's last-access time (DOS7).
+         *
+         * FIXME: How to prevent modification of last-access time?
+         */
+        winAccess = GENERIC_READ;
+        break;
+    default:
+        winAccess = 0;
+    }
+
+    /*
+     * Convert DOS access/share flags into Win32 share mode parameter.
+     */ 
+    switch(dosAccessShare & 0x70)
+    {
+    case OF_SHARE_EXCLUSIVE:  
+        winSharing = 0; 
+        break;
+    case OF_SHARE_DENY_WRITE: 
+        winSharing = FILE_SHARE_READ; 
+        break;
+    case OF_SHARE_DENY_READ:  
+        winSharing = FILE_SHARE_WRITE; 
+        break;
+    case OF_SHARE_DENY_NONE:
+    case OF_SHARE_COMPAT:
+    default:
+        winSharing = FILE_SHARE_READ | FILE_SHARE_WRITE;
+    }
+
+    /*
+     * FIXME: Bit (dosAccessShare & 0x80) represents inheritance.
+     *        What to do with this bit?
+     * FIXME: Bits in the high byte of dosAccessShare are not supported.
+     *        See both function 0x6c and subfunction 0x6c of function 0x71 for
+     *        definition of these bits.
+     */
+
+    /*
+     * Convert DOS create attributes into Win32 flags and attributes parameter.
+     */
+    if (winMode == OPEN_EXISTING || winMode == TRUNCATE_EXISTING)
+    {
+        winAttributes = 0;
+    }
+    else
+    {        
+        WORD dosAttributes = CX_reg(context);
+
+        if (dosAttributes & FILE_ATTRIBUTE_LABEL)
+        {
+            /*
+             * Application tried to create volume label entry.
+             * This is difficult to support so we do not allow it.
+             *
+             * FIXME: If volume does not already have a label, 
+             *        this function is supposed to succeed.
+             */
+            SetLastError( ERROR_ACCESS_DENIED );
+            return TRUE;
+        }
+
+        winAttributes = dosAttributes & 
+            (FILE_ATTRIBUTE_READONLY | FILE_ATTRIBUTE_HIDDEN | 
+             FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_ARCHIVE);
+    }
+
+    /*
+     * Open the file.
+     */
+    MultiByteToWideChar(CP_OEMCP, 0, pathA, -1, pathW, MAX_PATH);
+
+    winHandle = CreateFileW( pathW, winAccess, winSharing, NULL, 
+                             winMode, winAttributes, 0 );
+
+    if (winHandle == INVALID_HANDLE_VALUE)
+        return FALSE;
+
+    /*
+     * Determine DOS file status.
+     *
+     * 1 = file opened
+     * 2 = file created
+     * 3 = file replaced
+     */
+    switch(winMode)
+    {
+    case OPEN_EXISTING:
+        dosStatus = 1;
+        break;
+    case TRUNCATE_EXISTING:
+        dosStatus = 3; 
+        break;
+    case CREATE_NEW:
+        dosStatus = 2;
+        break;
+    case OPEN_ALWAYS:
+        dosStatus = (GetLastError() == ERROR_ALREADY_EXISTS) ? 1 : 2;
+        break;
+    case CREATE_ALWAYS:
+        dosStatus = (GetLastError() == ERROR_ALREADY_EXISTS) ? 3 : 2;
+        break;
+    default:
+        dosStatus = 0;
+    }
+
+    /*
+     * Return DOS file handle and DOS status.
+     */
+    SET_AX( context, Win32HandleToDosFileHandle(winHandle) );
+
+    if (returnStatus)
+        SET_CX( context, dosStatus );
+
+    TRACE( "CreateFile finished: handle=%d, status=%d.\n", 
+           AX_reg(context), dosStatus );
+
+    return TRUE;
+}
+
+
+/***********************************************************************
  *           INT21_BufferedInput
  *
  * Handler for function 0x0a and reading from console using
@@ -2156,7 +2359,15 @@
         break;
 
     case 0x60: /* LONG FILENAME - CONVERT PATH */
+        INT_Int21Handler( context );
+        break;
+
     case 0x6c: /* LONG FILENAME - CREATE OR OPEN FILE */
+        if (!INT21_CreateFile( context, context->Esi, TRUE,
+                               BX_reg(context), DL_reg(context) ))
+            bSetDOSExtendedError = TRUE;
+        break;
+
     case 0xa0: /* LONG FILENAME - GET VOLUME INFORMATION */
     case 0xa1: /* LONG FILENAME - "FindClose" - TERMINATE DIRECTORY SEARCH */
         INT_Int21Handler( context );
@@ -2917,8 +3128,15 @@
         break;
 
     case 0x3c: /* "CREAT" - CREATE OR TRUNCATE FILE */
+        if (!INT21_CreateFile( context, context->Edx, FALSE, 
+                               OF_READWRITE | OF_SHARE_COMPAT, 0x12 ))
+            bSetDOSExtendedError = TRUE;
+        break;
+
     case 0x3d: /* "OPEN" - OPEN EXISTING FILE */
-        INT_Int21Handler( context );
+        if (!INT21_CreateFile( context, context->Edx, FALSE, 
+                               AL_reg(context), 0x01 ))
+            bSetDOSExtendedError = TRUE;
         break;
 
     case 0x3e: /* "CLOSE" - CLOSE FILE */
@@ -3267,10 +3485,15 @@
         break;
 
     case 0x5a: /* CREATE TEMPORARY FILE */
-    case 0x5b: /* CREATE NEW FILE */ 
         INT_Int21Handler( context );
         break;
 
+    case 0x5b: /* CREATE NEW FILE */ 
+        if (!INT21_CreateFile( context, context->Edx, FALSE,
+                               OF_READWRITE | OF_SHARE_COMPAT, 0x10 ))
+            bSetDOSExtendedError = TRUE;
+        break;
+
     case 0x5c: /* "FLOCK" - RECORD LOCKING */
         {
             DWORD  offset = MAKELONG(DX_reg(context), CX_reg(context));
@@ -3381,7 +3604,9 @@
         break;
 
     case 0x6c: /* EXTENDED OPEN/CREATE */
-        INT_Int21Handler( context );
+        if (!INT21_CreateFile( context, context->Esi, TRUE,
+                               BX_reg(context), DL_reg(context) ))
+            bSetDOSExtendedError = TRUE;
         break;
 
     case 0x70: /* MSDOS 7 - GET/SET INTERNATIONALIZATION INFORMATION */




Index: msdos/int21.c
===================================================================
RCS file: /home/wine/wine/msdos/int21.c,v
retrieving revision 1.95
diff -u -r1.95 int21.c
--- msdos/int21.c	13 Jun 2003 18:05:18 -0000	1.95
+++ msdos/int21.c	14 Jun 2003 19:06:17 -0000
@@ -411,12 +411,6 @@
       }
     return drivestring;
 }
-static BOOL INT21_CreateFile( CONTEXT86 *context )
-{
-    SET_AX( context, _lcreat16( CTX_SEG_OFF_TO_LIN(context, context->SegDs,
-                                                   context->Edx ), CX_reg(context) ) );
-    return (AX_reg(context) == (WORD)HFILE_ERROR16);
-}
 
 static HFILE16 _lcreat16_uniq( LPCSTR path, INT attr )
 {
@@ -427,110 +421,6 @@
                                              CREATE_NEW, attr, 0 ));
 }
 
-static void OpenExistingFile( CONTEXT86 *context )
-{
-    SET_AX( context, _lopen16( CTX_SEG_OFF_TO_LIN(context, context->SegDs,context->Edx),
-                               AL_reg(context) ));
-    if (AX_reg(context) == (WORD)HFILE_ERROR16)
-    {
-        SET_AX( context, GetLastError() );
-        SET_CFLAG(context);
-    }
-}
-
-static BOOL INT21_ExtendedOpenCreateFile(CONTEXT86 *context )
-{
-  BOOL bExtendedError = FALSE;
-  BYTE action = DL_reg(context);
-
-  /* Shuffle arguments to call OpenExistingFile */
-  SET_AL( context, BL_reg(context) );
-  SET_DX( context, SI_reg(context) );
-  /* BX,CX and DX should be preserved */
-  OpenExistingFile(context);
-
-  if ((context->EFlags & 0x0001) == 0) /* File exists */
-  {
-      UINT16	uReturnCX = 0;
-
-      /* Now decide what do do */
-
-      if ((action & 0x07) == 0)
-      {
-	  _lclose16( AX_reg(context) );
-	  SET_AX( context, 0x0050 );	/*File exists*/
-	  SET_CFLAG(context);
-	  WARN("extended open/create: failed because file exists \n");
-      }
-      else if ((action & 0x07) == 2)
-      {
-	/* Truncate it, but first check if opened for write */
-	if ((BL_reg(context) & 0x0007)== 0)
-	{
-            _lclose16( AX_reg(context) );
-            WARN("extended open/create: failed, trunc on ro file\n");
-            SET_AX( context, 0x000C );	/*Access code invalid*/
-            SET_CFLAG(context);
-	}
-	else
-	{
-		TRACE("extended open/create: Closing before truncate\n");
-                if (_lclose16( AX_reg(context) ))
-		{
-		   WARN("extended open/create: close before trunc failed\n");
-		   SET_AX( context, 0x0019 );	/*Seek Error*/
-		   SET_CX( context, 0 );
-		   SET_CFLAG(context);
-		}
-		/* Shuffle arguments to call CreateFile */
-
-		TRACE("extended open/create: Truncating\n");
-		SET_AL( context, BL_reg(context) );
-		/* CX is still the same */
-		SET_DX( context, SI_reg(context) );
-		bExtendedError = INT21_CreateFile(context);
-
-		if (context->EFlags & 0x0001) 	/*no file open, flags set */
-		{
-		    WARN("extended open/create: trunc failed\n");
-		    return bExtendedError;
-		}
-		uReturnCX = 0x3;
-	}
-      }
-      else uReturnCX = 0x1;
-
-      SET_CX( context, uReturnCX );
-  }
-  else /* file does not exist */
-  {
-      RESET_CFLAG(context); /* was set by OpenExistingFile(context) */
-      if ((action & 0xF0)== 0)
-      {
-	SET_CX( context, 0 );
-	SET_CFLAG(context);
-	WARN("extended open/create: failed, file dosen't exist\n");
-      }
-      else
-      {
-        /* Shuffle arguments to call CreateFile */
-        TRACE("extended open/create: Creating\n");
-        SET_AL( context, BL_reg(context) );
-        /* CX should still be the same */
-        SET_DX( context, SI_reg(context) );
-        bExtendedError = INT21_CreateFile(context);
-        if (context->EFlags & 0x0001)  /*no file open, flags set */
-	{
-  	    WARN("extended open/create: create failed\n");
-	    return bExtendedError;
-        }
-        SET_CX( context, 2 );
-      }
-  }
-
-  return bExtendedError;
-}
-
 
 static int INT21_FindFirst( CONTEXT86 *context )
 {
@@ -858,18 +748,6 @@
         if (!INT21_GetFreeDiskSpace(context)) SET_AX( context, 0xffff );
         break;
 
-    case 0x3c: /* "CREAT" - CREATE OR TRUNCATE FILE */
-        TRACE("CREAT flag 0x%02x %s\n",CX_reg(context),
-	      (LPCSTR)CTX_SEG_OFF_TO_LIN(context,  context->SegDs, context->Edx));
-        bSetDOSExtendedError = INT21_CreateFile( context );
-        break;
-
-    case 0x3d: /* "OPEN" - OPEN EXISTING FILE */
-        TRACE("OPEN mode 0x%02x %s\n",AL_reg(context),
-	      (LPCSTR)CTX_SEG_OFF_TO_LIN(context,  context->SegDs, context->Edx));
-        OpenExistingFile(context);
-        break;
-
     case 0x44: /* IOCTL */
         switch (AL_reg(context))
         {
@@ -917,15 +795,6 @@
         bSetDOSExtendedError = !INT21_CreateTempFile(context);
         break;
 
-    case 0x5b: /* CREATE NEW FILE */
-        TRACE("CREATE NEW FILE 0x%02x for %s\n", CX_reg(context),
-	      (LPCSTR)CTX_SEG_OFF_TO_LIN(context,  context->SegDs, context->Edx));
-        SET_AX( context,
-               _lcreat16_uniq( CTX_SEG_OFF_TO_LIN(context, context->SegDs,context->Edx),
-                               CX_reg(context) ));
-        bSetDOSExtendedError = (AX_reg(context) != 0);
-        break;
-
     case 0x5e:
 	bSetDOSExtendedError = INT21_networkfunc (context);
         break;
@@ -992,12 +861,6 @@
         }
         break;
 
-    case 0x6C: /* Extended Open/Create*/
-        TRACE("EXTENDED OPEN/CREATE %s\n",
-	      (LPCSTR)CTX_SEG_OFF_TO_LIN(context,  context->SegDs, context->Edi));
-        bSetDOSExtendedError = INT21_ExtendedOpenCreateFile(context);
-        break;
-
     case 0x71: /* MS-DOS 7 (Windows95) - LONG FILENAME FUNCTIONS */
         switch(AL_reg(context))
         {
@@ -1074,12 +937,6 @@
 	      break;
 	  }
 	  break;
-        case 0x6c:  /* Create or open file */
-            TRACE("LONG FILENAME - CREATE OR OPEN FILE %s\n",
-		 (LPCSTR)CTX_SEG_OFF_TO_LIN(context,  context->SegDs, context->Esi));
-	  /* translate Dos 7 action to Dos 6 action */
-	    bSetDOSExtendedError = INT21_ExtendedOpenCreateFile(context);
-	    break;
 
         default:
             FIXME("Unimplemented long file name function:\n");




-- 
Jukka Heinonen <http://www.iki.fi/jhei/>



More information about the wine-patches mailing list