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