winedos / Migrate current directory routines
Jukka Heinonen
jhei at iki.fi
Sun Jun 8 04:26:39 CDT 2003
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/>
More information about the wine-patches
mailing list