Migrate create/open file functions to winedos.
Some fixes based on patch by Ferenc Wagner.
This commit is contained in:
parent
0b79a6e7c3
commit
e827269a99
|
@ -518,6 +518,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
|
||||
*
|
||||
|
@ -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 */
|
||||
|
|
143
msdos/int21.c
143
msdos/int21.c
|
@ -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");
|
||||
|
|
Loading…
Reference in New Issue