From 4cbc69a223800c088f1fb46fa8fa0bf937c75599 Mon Sep 17 00:00:00 2001 From: Jukka Heinonen <jhei@iki.fi> Date: Fri, 13 Jun 2003 18:05:18 +0000 Subject: [PATCH] Move get current directory and set current directory int21 subfunctions into winedos. Fix quite a few bugs in the implementation of these functions. --- dlls/winedos/int21.c | 167 +++++++++++++++++++++++++++++++++++++++++-- msdos/int21.c | 66 ----------------- 2 files changed, 163 insertions(+), 70 deletions(-) diff --git a/dlls/winedos/int21.c b/dlls/winedos/int21.c index c1c4198b354..03c3b789223 100644 --- a/dlls/winedos/int21.c +++ b/dlls/winedos/int21.c @@ -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 */ diff --git a/msdos/int21.c b/msdos/int21.c index 4f3c94fee60..d38d9cf7619 100644 --- a/msdos/int21.c +++ b/msdos/int21.c @@ -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 ); -- GitLab