Commit e827269a authored by Jukka Heinonen's avatar Jukka Heinonen Committed by Alexandre Julliard

Migrate create/open file functions to winedos.

Some fixes based on patch by Ferenc Wagner.
parent 0b79a6e7
......@@ -519,6 +519,209 @@ static BOOL INT21_SetCurrentDirectory( CONTEXT86 *context )
/***********************************************************************
* 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 @@ static void INT21_LongFilename( CONTEXT86 *context )
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 @@ void WINAPI DOSVM_Int21Handler( CONTEXT86 *context )
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 @@ void WINAPI DOSVM_Int21Handler( CONTEXT86 *context )
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 @@ void WINAPI DOSVM_Int21Handler( CONTEXT86 *context )
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 */
......
......@@ -411,12 +411,6 @@ char *INT21_DriveName(int drive)
}
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 @@ static HFILE16 _lcreat16_uniq( LPCSTR path, INT attr )
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 @@ void WINAPI INT_Int21Handler( CONTEXT86 *context )
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 @@ void WINAPI INT_Int21Handler( CONTEXT86 *context )
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 @@ void WINAPI INT_Int21Handler( CONTEXT86 *context )
}
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 @@ void WINAPI INT_Int21Handler( CONTEXT86 *context )
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");
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment