[NTVDM]: Fix current directory stuff.
[reactos.git] / reactos / subsystems / mvdm / ntvdm / dos / dos32krnl / dos.c
index 54d8b53..fa8f14f 100644 (file)
@@ -38,8 +38,8 @@
 
 CALLBACK16 DosContext;
 
-/*static*/ BYTE CurrentDrive;
-static CHAR LastDrive = 'E';
+/*static*/ BYTE CurrentDrive = 0x00;
+static CHAR LastDrive = 'Z'; // The last drive can be redefined with the LASTDRIVE command. At the moment, set the real maximum possible, 'Z'.
 static CHAR CurrentDirectories[NUM_DRIVES][DOS_DIR_LENGTH];
 static PBYTE InDos;
 
@@ -81,6 +81,8 @@ static BOOLEAN DosChangeDirectory(LPSTR Directory)
     BYTE DriveNumber;
     DWORD Attributes;
     LPSTR Path;
+    CHAR CurrentDirectory[MAX_PATH];
+    CHAR DosDirectory[DOS_DIR_LENGTH];
 
     /* Make sure the directory path is not too long */
     if (strlen(Directory) >= DOS_DIR_LENGTH)
@@ -89,14 +91,23 @@ static BOOLEAN DosChangeDirectory(LPSTR Directory)
         return FALSE;
     }
 
-    /* Get the drive number */
-    DriveNumber = Directory[0] - 'A';
+    /* Check whether the directory string is of format "?:..." */
+    if (strlen(Directory) >= 2 && Directory[1] == ':')
+    {
+        /* Get the drive number */
+        DriveNumber = RtlUpperChar(Directory[0]) - 'A';
 
-    /* Make sure the drive exists */
-    if (DriveNumber > (LastDrive - 'A'))
+        /* Make sure the drive exists */
+        if (DriveNumber > (LastDrive - 'A'))
+        {
+            DosLastError = ERROR_PATH_NOT_FOUND;
+            return FALSE;
+        }
+    }
+    else
     {
-        DosLastError = ERROR_PATH_NOT_FOUND;
-        return FALSE;
+        /* Keep the current drive number */
+        DriveNumber = CurrentDrive;
     }
 
     /* Get the file attributes */
@@ -120,9 +131,23 @@ static BOOLEAN DosChangeDirectory(LPSTR Directory)
             return FALSE;
         }
     }
+    
+    /* Get the (possibly new) current directory (needed if we specified a relative directory) */
+    if (!GetCurrentDirectoryA(sizeof(CurrentDirectory), CurrentDirectory))
+    {
+        // TODO: Use some kind of default path?
+        return FALSE;
+    }
+
+    /* Convert it to a DOS path */
+    if (!GetShortPathNameA(CurrentDirectory, DosDirectory, sizeof(DosDirectory)))
+    {
+        // TODO: Use some kind of default path?
+        return FALSE;
+    }
 
     /* Get the directory part of the path */
-    Path = strchr(Directory, '\\');
+    Path = strchr(DosDirectory, '\\');
     if (Path != NULL)
     {
         /* Skip the backslash */
@@ -178,6 +203,10 @@ VOID WINAPI DosInt21h(LPWORD Stack)
 
     (*InDos)++;
 
+    /* Save the value of SS:SP on entry in the PSP */
+    SEGMENT_TO_PSP(CurrentPsp)->LastStack =
+    MAKELONG(getSP() + (STACK_FLAGS + 1) * 2, getSS());
+
     /* Check the value in the AH register */
     switch (getAH())
     {
@@ -398,6 +427,7 @@ VOID WINAPI DosInt21h(LPWORD Stack)
                 }
 
                 if (Character == '\r') break;
+                if (Character == '\b') continue;
                 Count++; /* Carriage returns are NOT counted */
             }
 
@@ -764,14 +794,13 @@ VOID WINAPI DosInt21h(LPWORD Stack)
         {
             setES(HIWORD(INDOS_POINTER));
             setBX(LOWORD(INDOS_POINTER));
-
             break;
         }
 
         /* Get Interrupt Vector */
         case 0x35:
         {
-            DWORD FarPointer = ((PDWORD)BaseAddress)[getAL()];
+            ULONG FarPointer = ((PULONG)BaseAddress)[getAL()];
 
             /* Read the address from the IDT into ES:BX */
             setES(HIWORD(FarPointer));
@@ -782,7 +811,7 @@ VOID WINAPI DosInt21h(LPWORD Stack)
         /* Get Free Disk Space */
         case 0x36:
         {
-            CHAR RootPath[3] = "X:\\";
+            CHAR RootPath[3] = "?:\\";
             DWORD SectorsPerCluster;
             DWORD BytesPerSector;
             DWORD NumberOfFreeClusters;
@@ -1338,7 +1367,6 @@ VOID WINAPI DosInt21h(LPWORD Stack)
             BYTE OrgAL = getAL();
             LPSTR ProgramName = SEG_OFF_TO_PTR(getDS(), getDX());
             PDOS_EXEC_PARAM_BLOCK ParamBlock = SEG_OFF_TO_PTR(getES(), getBX());
-            DWORD ReturnAddress = MAKELONG(Stack[STACK_IP], Stack[STACK_CS]);
             WORD ErrorCode;
 
             if (OrgAL <= DOS_LOAD_OVERLAY)
@@ -1349,9 +1377,7 @@ VOID WINAPI DosInt21h(LPWORD Stack)
                 if (LoadType == DOS_LOAD_AND_EXECUTE)
                 {
                     /* Create a new process */
-                    ErrorCode = DosCreateProcess(ProgramName,
-                                                 ParamBlock,
-                                                 ReturnAddress);
+                    ErrorCode = DosCreateProcess(ProgramName, ParamBlock);
                 }
                 else
 #endif
@@ -1361,8 +1387,7 @@ VOID WINAPI DosInt21h(LPWORD Stack)
                                                   ProgramName,
                                                   ParamBlock,
                                                   NULL,
-                                                  NULL,
-                                                  ReturnAddress);
+                                                  NULL);
                 }
             }
             else if (OrgAL == 0x05)
@@ -1646,7 +1671,7 @@ VOID WINAPI DosInt21h(LPWORD Stack)
             if (getAL() == 0x00)
             {
                 /* Lock region of file */
-                if (DosLockFile(getBX(), MAKELONG(getCX(), getDX()), MAKELONG(getSI(), getDI())))
+                if (DosLockFile(getBX(), MAKELONG(getDX(), getCX()), MAKELONG(getDI(), getSI())))
                 {
                     Stack[STACK_FLAGS] &= ~EMULATOR_FLAG_CF;
                 }
@@ -1659,7 +1684,7 @@ VOID WINAPI DosInt21h(LPWORD Stack)
             else if (getAL() == 0x01)
             {
                 /* Unlock region of file */
-                if (DosUnlockFile(getBX(), MAKELONG(getCX(), getDX()), MAKELONG(getSI(), getDI())))
+                if (DosUnlockFile(getBX(), MAKELONG(getDX(), getCX()), MAKELONG(getDI(), getSI())))
                 {
                     Stack[STACK_FLAGS] &= ~EMULATOR_FLAG_CF;
                 }
@@ -1817,6 +1842,11 @@ VOID WINAPI DosBreakInterrupt(LPWORD Stack)
     Stack[STACK_FLAGS] |= EMULATOR_FLAG_CF;
 }
 
+VOID WINAPI DosInt27h(LPWORD Stack)
+{
+    DosTerminateProcess(getCS(), 0, (getDX() + 0x0F) >> 4);
+}
+
 VOID WINAPI DosFastConOut(LPWORD Stack)
 {
     /*
@@ -1891,10 +1921,10 @@ BOOLEAN DosKRNLInitialize(VOID)
 #if 1
 
     UCHAR i;
+    PDOS_SFT Sft;
+    LPSTR Path;
     CHAR CurrentDirectory[MAX_PATH];
     CHAR DosDirectory[DOS_DIR_LENGTH];
-    LPSTR Path;
-    PDOS_SFT Sft;
 
     const BYTE NullDriverRoutine[] = {
         /* Strategy routine entry */
@@ -1920,21 +1950,21 @@ BOOLEAN DosKRNLInitialize(VOID)
     RtlZeroMemory(CurrentDirectories, sizeof(CurrentDirectories));
 
     /* Get the current directory */
-    if (!GetCurrentDirectoryA(MAX_PATH, CurrentDirectory))
+    if (!GetCurrentDirectoryA(sizeof(CurrentDirectory), CurrentDirectory))
     {
         // TODO: Use some kind of default path?
         return FALSE;
     }
 
-    /* Convert that to a DOS path */
-    if (!GetShortPathNameA(CurrentDirectory, DosDirectory, DOS_DIR_LENGTH))
+    /* Convert it to a DOS path */
+    if (!GetShortPathNameA(CurrentDirectory, DosDirectory, sizeof(DosDirectory)))
     {
         // TODO: Use some kind of default path?
         return FALSE;
     }
 
     /* Set the drive */
-    CurrentDrive = DosDirectory[0] - 'A';
+    CurrentDrive = RtlUpperChar(DosDirectory[0]) - 'A';
 
     /* Get the directory part of the path */
     Path = strchr(DosDirectory, '\\');
@@ -1994,7 +2024,7 @@ BOOLEAN DosKRNLInitialize(VOID)
 #endif
 
     /* Initialize the callback context */
-    InitializeContext(&DosContext, 0x0070, 0x0000);
+    InitializeContext(&DosContext, DOS_CODE_SEGMENT, 0x0000);
 
     /* Register the DOS 32-bit Interrupts */
     RegisterDosInt32(0x20, DosInt20h        );
@@ -2002,9 +2032,19 @@ BOOLEAN DosKRNLInitialize(VOID)
 //  RegisterDosInt32(0x22, DosInt22h        ); // Termination
     RegisterDosInt32(0x23, DosBreakInterrupt); // Ctrl-C / Ctrl-Break
 //  RegisterDosInt32(0x24, DosInt24h        ); // Critical Error
+    RegisterDosInt32(0x27, DosInt27h        ); // Terminate and Stay Resident
     RegisterDosInt32(0x29, DosFastConOut    ); // DOS 2+ Fast Console Output
     RegisterDosInt32(0x2F, DosInt2Fh        );
 
+    /* Unimplemented DOS interrupts */
+    RegisterDosInt32(0x2A, NULL); // Network - Installation Check
+
+    /* Load the CON driver */
+    ConDrvInitialize();
+
+    /* Load the XMS driver (HIMEM) */
+    XmsInitialize();
+
     /* Load the EMS driver */
     if (!EmsDrvInitialize(EMS_TOTAL_PAGES))
     {
@@ -2012,12 +2052,6 @@ BOOLEAN DosKRNLInitialize(VOID)
                 "Try reducing the number of EMS pages.\n");
     }
 
-    /* Load the XMS driver (HIMEM) */
-    XmsInitialize();
-
-    /* Load the CON driver */
-    ConDrvInitialize();
-
     return TRUE;
 }