Changelog: Move get current directory and set current directory int21 subfunctions into winedos. Fix quite a few bugs in the implementation of these functions. Index: dlls/winedos/int21.c =================================================================== RCS file: /home/wine/wine/dlls/winedos/int21.c,v retrieving revision 1.36 diff -u -r1.36 int21.c --- dlls/winedos/int21.c 4 Jun 2003 20:17:52 -0000 1.36 +++ dlls/winedos/int21.c 8 Jun 2003 09:19:17 -0000 @@ -147,8 +147,19 @@ 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 @@ * * 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 @@ -370,6 +381,144 @@ /*********************************************************************** + * 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 * * Handler for function 0x0a and reading from console using @@ -1968,7 +2117,8 @@ 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 @@ 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 @@ 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 @@ break; case 0x47: /* "CWD" - GET CURRENT DIRECTORY */ - INT_Int21Handler( context ); + if (!INT21_GetCurrentDirectory( context, FALSE )) + bSetDOSExtendedError = TRUE; break; case 0x48: /* ALLOCATE MEMORY */ Index: msdos/int21.c =================================================================== RCS file: /home/wine/wine/msdos/int21.c,v retrieving revision 1.94 diff -u -r1.94 int21.c --- msdos/int21.c 4 Jun 2003 20:17:52 -0000 1.94 +++ msdos/int21.c 8 Jun 2003 09:19:23 -0000 @@ -532,24 +532,6 @@ } -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_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 @@ 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 @@ } 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 @@ 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)); @@ -1132,19 +1079,6 @@ (LPCSTR)CTX_SEG_OFF_TO_LIN(context, context->SegDs, context->Esi)); /* translate Dos 7 action to Dos 6 action */ 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: -- Jukka Heinonen <http://www.iki.fi/jhei/>