Move get current directory and set current directory int21

subfunctions into winedos. Fix quite a few bugs in the implementation
of these functions.
This commit is contained in:
Jukka Heinonen 2003-06-13 18:05:18 +00:00 committed by Alexandre Julliard
parent 6f27b3bc06
commit 4cbc69a223
2 changed files with 163 additions and 70 deletions

View File

@ -147,8 +147,19 @@ static BYTE INT21_GetCurrentDrive()
static BYTE INT21_MapDrive( BYTE drive )
{
if (drive)
{
WCHAR drivespec[3] = {'A', ':', 0};
UINT drivetype;
drivespec[0] += drive - 1;
drivetype = GetDriveTypeW( drivespec );
if (drivetype == DRIVE_UNKNOWN || drivetype == DRIVE_NO_ROOT_DIR)
return MAX_DOS_DRIVES;
return drive - 1;
}
return INT21_GetCurrentDrive();
}
@ -208,7 +219,7 @@ static BOOL INT21_ReadChar( BYTE *input, CONTEXT86 *waitctx )
*
* Return DOS country code for default system locale.
*/
static WORD INT21_GetSystemCountryCode()
static WORD INT21_GetSystemCountryCode( void )
{
/*
* FIXME: Determine country code. We should probably use
@ -369,6 +380,144 @@ static WORD INT21_GetHeapSelector( CONTEXT86 *context )
}
/***********************************************************************
* INT21_GetCurrentDirectory
*
* Handler for:
* - function 0x47
* - subfunction 0x47 of function 0x71
*/
static BOOL INT21_GetCurrentDirectory( CONTEXT86 *context, BOOL islong )
{
char *buffer = CTX_SEG_OFF_TO_LIN(context, context->SegDs, context->Esi);
BYTE new_drive = INT21_MapDrive( DL_reg(context) );
BYTE old_drive = INT21_GetCurrentDrive();
WCHAR pathW[MAX_PATH];
char pathA[MAX_PATH];
WCHAR *ptr = pathW;
TRACE( "drive %d\n", DL_reg(context) );
if (new_drive == MAX_DOS_DRIVES)
{
SetLastError(ERROR_INVALID_DRIVE);
return FALSE;
}
/*
* Grab current directory.
*/
INT21_SetCurrentDrive( new_drive );
if (!GetCurrentDirectoryW( MAX_PATH, pathW ))
{
INT21_SetCurrentDrive( old_drive );
return FALSE;
}
INT21_SetCurrentDrive( old_drive );
/*
* Convert into short format.
*/
if (!islong)
{
DWORD result = GetShortPathNameW( pathW, pathW, MAX_PATH );
if (!result)
return FALSE;
if (result > MAX_PATH)
{
WARN( "Short path too long!\n" );
SetLastError(ERROR_NETWORK_BUSY); /* Internal Wine error. */
return FALSE;
}
}
/*
* The returned pathname does not include
* the drive letter, colon or leading backslash.
*/
if (ptr[0] == '\\')
{
/*
* FIXME: We should probably just strip host part from name...
*/
FIXME( "UNC names are not supported.\n" );
SetLastError(ERROR_NETWORK_BUSY); /* Internal Wine error. */
return FALSE;
}
else if (!ptr[0] || ptr[1] != ':' || ptr[2] != '\\')
{
WARN( "Path is neither UNC nor DOS path: %s\n",
wine_dbgstr_w(ptr) );
SetLastError(ERROR_NETWORK_BUSY); /* Internal Wine error. */
return FALSE;
}
else
{
/* Remove drive letter, colon and leading backslash. */
ptr += 3;
}
/*
* Convert into OEM string.
*/
if (!WideCharToMultiByte(CP_OEMCP, 0, ptr, -1, pathA,
MAX_PATH, NULL, NULL))
{
WARN( "Cannot convert path!\n" );
SetLastError(ERROR_NETWORK_BUSY); /* Internal Wine error. */
return FALSE;
}
/*
* Success.
*/
if (!islong)
{
/* Undocumented success code. */
SET_AX( context, 0x0100 );
/* Truncate buffer to 64 bytes. */
pathA[63] = 0;
}
TRACE( "%c:=%s\n", 'A' + new_drive, pathA );
strcpy( buffer, pathA );
return TRUE;
}
/***********************************************************************
* INT21_SetCurrentDirectory
*
* Handler for:
* - function 0x3b
* - subfunction 0x3b of function 0x71
*/
static BOOL INT21_SetCurrentDirectory( CONTEXT86 *context )
{
WCHAR dirW[MAX_PATH];
char *dirA = CTX_SEG_OFF_TO_LIN(context, context->SegDs, context->Edx);
BYTE drive = INT21_GetCurrentDrive();
BOOL result;
TRACE( "SET CURRENT DIRECTORY %s\n", dirA );
MultiByteToWideChar(CP_OEMCP, 0, dirA, -1, dirW, MAX_PATH);
result = SetCurrentDirectoryW( dirW );
/* This function must not change current drive. */
INT21_SetCurrentDrive( drive );
return result;
}
/***********************************************************************
* INT21_BufferedInput
*
@ -1968,7 +2117,8 @@ static void INT21_LongFilename( CONTEXT86 *context )
break;
case 0x3b: /* LONG FILENAME - CHANGE DIRECTORY */
INT_Int21Handler( context );
if (!INT21_SetCurrentDirectory( context ))
bSetDOSExtendedError = TRUE;
break;
case 0x41: /* LONG FILENAME - DELETE FILE */
@ -1991,6 +2141,10 @@ static void INT21_LongFilename( CONTEXT86 *context )
break;
case 0x47: /* LONG FILENAME - GET CURRENT DIRECTORY */
if (!INT21_GetCurrentDirectory( context, TRUE ))
bSetDOSExtendedError = TRUE;
break;
case 0x4e: /* LONG FILENAME - FIND FIRST MATCHING FILE */
case 0x4f: /* LONG FILENAME - FIND NEXT MATCHING FILE */
INT_Int21Handler( context );
@ -2758,6 +2912,10 @@ void WINAPI DOSVM_Int21Handler( CONTEXT86 *context )
break;
case 0x3b: /* "CHDIR" - SET CURRENT DIRECTORY */
if (!INT21_SetCurrentDirectory( context ))
bSetDOSExtendedError = TRUE;
break;
case 0x3c: /* "CREAT" - CREATE OR TRUNCATE FILE */
case 0x3d: /* "OPEN" - OPEN EXISTING FILE */
INT_Int21Handler( context );
@ -2910,7 +3068,8 @@ void WINAPI DOSVM_Int21Handler( CONTEXT86 *context )
break;
case 0x47: /* "CWD" - GET CURRENT DIRECTORY */
INT_Int21Handler( context );
if (!INT21_GetCurrentDirectory( context, FALSE ))
bSetDOSExtendedError = TRUE;
break;
case 0x48: /* ALLOCATE MEMORY */

View File

@ -532,24 +532,6 @@ static BOOL INT21_ExtendedOpenCreateFile(CONTEXT86 *context )
}
static BOOL INT21_ChangeDir( CONTEXT86 *context )
{
int drive;
char *dirname = CTX_SEG_OFF_TO_LIN(context, context->SegDs,context->Edx);
WCHAR dirnameW[MAX_PATH];
TRACE("changedir %s\n", dirname);
if (dirname[0] && (dirname[1] == ':'))
{
drive = toupper(dirname[0]) - 'A';
dirname += 2;
}
else drive = DRIVE_GetCurrentDrive();
MultiByteToWideChar(CP_OEMCP, 0, dirname, -1, dirnameW, MAX_PATH);
return DRIVE_Chdir( drive, dirnameW );
}
static int INT21_FindFirst( CONTEXT86 *context )
{
char *p;
@ -661,23 +643,6 @@ static BOOL INT21_CreateTempFile( CONTEXT86 *context )
}
static BOOL INT21_GetCurrentDirectory( CONTEXT86 *context )
{
int drive = DOS_GET_DRIVE( DL_reg(context) );
char *ptr = (char *)CTX_SEG_OFF_TO_LIN(context, context->SegDs, context->Esi );
if (!DRIVE_IsValid(drive))
{
SetLastError( ERROR_INVALID_DRIVE );
return FALSE;
}
WideCharToMultiByte(CP_OEMCP, 0, DRIVE_GetDosCwd(drive), -1, ptr, 64, NULL, NULL);
ptr[63] = 0; /* ensure 0 termination */
SET_AX( context, 0x0100 ); /* success return code */
return TRUE;
}
static int INT21_GetDiskSerialNumber( CONTEXT86 *context )
{
BYTE *dataptr = CTX_SEG_OFF_TO_LIN(context, context->SegDs, context->Edx);
@ -893,12 +858,6 @@ void WINAPI INT_Int21Handler( CONTEXT86 *context )
if (!INT21_GetFreeDiskSpace(context)) SET_AX( context, 0xffff );
break;
case 0x3b: /* "CHDIR" - SET CURRENT DIRECTORY */
TRACE("CHDIR %s\n",
(LPCSTR)CTX_SEG_OFF_TO_LIN(context, context->SegDs, context->Edx));
bSetDOSExtendedError = !INT21_ChangeDir(context);
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));
@ -936,12 +895,6 @@ void WINAPI INT_Int21Handler( CONTEXT86 *context )
}
break;
case 0x47: /* "CWD" - GET CURRENT DIRECTORY */
TRACE("CWD - GET CURRENT DIRECTORY for drive %s\n",
INT21_DriveName( DL_reg(context)));
bSetDOSExtendedError = !INT21_GetCurrentDirectory(context);
break;
case 0x4e: /* "FINDFIRST" - FIND FIRST MATCHING FILE */
TRACE("FINDFIRST mask 0x%04x spec %s\n",CX_reg(context),
(LPCSTR)CTX_SEG_OFF_TO_LIN(context, context->SegDs, context->Edx));
@ -1048,12 +1001,6 @@ void WINAPI INT_Int21Handler( CONTEXT86 *context )
case 0x71: /* MS-DOS 7 (Windows95) - LONG FILENAME FUNCTIONS */
switch(AL_reg(context))
{
case 0x47: /* Get current directory */
TRACE(" LONG FILENAME - GET CURRENT DIRECTORY for drive %s\n",
INT21_DriveName(DL_reg(context)));
bSetDOSExtendedError = !INT21_GetCurrentDirectory(context);
break;
case 0x4e: /* Find first file */
TRACE(" LONG FILENAME - FIND FIRST MATCHING FILE for %s\n",
(LPCSTR)CTX_SEG_OFF_TO_LIN(context, context->SegDs,context->Edx));
@ -1134,19 +1081,6 @@ void WINAPI INT_Int21Handler( CONTEXT86 *context )
bSetDOSExtendedError = INT21_ExtendedOpenCreateFile(context);
break;
case 0x3b: /* Change directory */
TRACE("LONG FILENAME - CHANGE DIRECTORY %s\n",
(LPCSTR)CTX_SEG_OFF_TO_LIN(context, context->SegDs, context->Edx));
if (!SetCurrentDirectoryA(CTX_SEG_OFF_TO_LIN(context,
context->SegDs,
context->Edx
))
) {
SET_CFLAG(context);
SET_AL( context, GetLastError() );
}
break;
default:
FIXME("Unimplemented long file name function:\n");
INT_BARF( context, 0x21 );