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