[USETUP]: Instead of defining a special function "DrawInputField" just to draw an...
[reactos.git] / reactos / base / setup / usetup / interface / usetup.c
index 58976c4..e223f5a 100644 (file)
@@ -392,7 +392,7 @@ ConfirmQuit(PINPUT_RECORD Ir)
             Result = TRUE;
             break;
         }
-        else if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D)   /* ENTER */
+        else if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D)  /* ENTER */
         {
             Result = FALSE;
             break;
@@ -701,7 +701,7 @@ LanguagePage(PINPUT_RECORD Ir)
         else if ((Ir->Event.KeyEvent.uChar.AsciiChar > 0x60) && (Ir->Event.KeyEvent.uChar.AsciiChar < 0x7b))
         {
             /* a-z */
-            GenericListKeyPress (LanguageList, Ir->Event.KeyEvent.uChar.AsciiChar);
+            GenericListKeyPress(LanguageList, Ir->Event.KeyEvent.uChar.AsciiChar);
             RefreshPage = TRUE;
         }
 
@@ -1425,28 +1425,18 @@ LayoutSettingsPage(PINPUT_RECORD Ir)
 }
 
 
-#if 0
 static BOOL
 IsDiskSizeValid(PPARTENTRY PartEntry)
 {
-    ULONGLONG m1, m2;
-
-    /*  check for unpartitioned space  */
-    m1 = PartEntry->UnpartitionedLength;
-    m1 = (m1 + (1 << 19)) >> 20;  /* in MBytes (rounded) */
+    ULONGLONG size;
 
-    if( m1 > RequiredPartitionDiskSpace)
-    {
-        return TRUE;
-    }
+    size = PartEntry->SectorCount.QuadPart * PartEntry->DiskEntry->BytesPerSector;
+    size = (size + 524288) / 1048576;  /* in MBytes */
 
-    /* check for partitioned space */
-    m2 = PartEntry->PartInfo[0].PartitionLength.QuadPart;
-    m2 = (m2 + (1 << 19)) >> 20;  /* in MBytes (rounded) */
-    if (m2 < RequiredPartitionDiskSpace)
+    if (size < RequiredPartitionDiskSpace)
     {
         /* partition is too small so ask for another partion */
-        DPRINT1("Partition is too small(unpartitioned: %I64u MB, partitioned: %I64u MB), required disk space is %lu MB\n", m1, m2, RequiredPartitionDiskSpace);
+        DPRINT1("Partition is too small (size: %I64u MB), required disk space is %lu MB\n", size, RequiredPartitionDiskSpace);
         return FALSE;
     }
     else
@@ -1454,7 +1444,6 @@ IsDiskSizeValid(PPARTENTRY PartEntry)
         return TRUE;
     }
 }
-#endif
 
 
 static PAGE_NUMBER
@@ -1513,16 +1502,16 @@ SelectPartitionPage(PINPUT_RECORD Ir)
         {
             if (AutoPartition)
             {
-#if 0
+                CreatePrimaryPartition(PartitionList,
+                                       PartitionList->CurrentPartition->SectorCount.QuadPart,
+                                       TRUE);
+
                 if (!IsDiskSizeValid(PartitionList->CurrentPartition))
                 {
-                    MUIDisplayError(ERROR_INSUFFICIENT_DISKSPACE, Ir, POPUP_WAIT_ANY_KEY);
+                    MUIDisplayError(ERROR_INSUFFICIENT_PARTITION_SIZE, Ir, POPUP_WAIT_ANY_KEY,
+                                    RequiredPartitionDiskSpace);
                     return SELECT_PARTITION_PAGE; /* let the user select another partition */
                 }
-#endif
-                CreatePrimaryPartition(PartitionList,
-                                       PartitionList->CurrentPartition->SectorCount.QuadPart,
-                                       TRUE);
 
                 DestinationDriveLetter = (WCHAR)PartitionList->CurrentPartition->DriveLetter;
 
@@ -1531,13 +1520,13 @@ SelectPartitionPage(PINPUT_RECORD Ir)
         }
         else
         {
-#if 0
             if (!IsDiskSizeValid(PartitionList->CurrentPartition))
             {
-                MUIDisplayError(ERROR_INSUFFICIENT_DISKSPACE, Ir, POPUP_WAIT_ANY_KEY);
+                MUIDisplayError(ERROR_INSUFFICIENT_PARTITION_SIZE, Ir, POPUP_WAIT_ANY_KEY,
+                                RequiredPartitionDiskSpace);
                 return SELECT_PARTITION_PAGE; /* let the user select another partition */
             }
-#endif
+
             DestinationDriveLetter = (WCHAR)PartitionList->CurrentPartition->DriveLetter;
 
             return SELECT_FILE_SYSTEM_PAGE;
@@ -1609,13 +1598,6 @@ SelectPartitionPage(PINPUT_RECORD Ir)
         }
         else if (Ir->Event.KeyEvent.wVirtualKeyCode == VK_RETURN)  /* ENTER */
         {
-#if 0
-            if (!IsDiskSizeValid(PartitionList->CurrentPartition))
-            {
-                MUIDisplayError(ERROR_INSUFFICIENT_DISKSPACE, Ir, POPUP_WAIT_ANY_KEY);
-                return SELECT_PARTITION_PAGE; /* let the user select another partition */
-            }
-#endif
             if (IsContainerPartition(PartitionList->CurrentPartition->PartitionType))
                 continue; //return SELECT_PARTITION_PAGE;
 
@@ -1627,6 +1609,13 @@ SelectPartitionPage(PINPUT_RECORD Ir)
                                        TRUE);
             }
 
+            if (!IsDiskSizeValid(PartitionList->CurrentPartition))
+            {
+                MUIDisplayError(ERROR_INSUFFICIENT_PARTITION_SIZE, Ir, POPUP_WAIT_ANY_KEY,
+                                RequiredPartitionDiskSpace);
+                return SELECT_PARTITION_PAGE; /* let the user select another partition */
+            }
+
             DestinationDriveLetter = (WCHAR)PartitionList->CurrentPartition->DriveLetter;
 
             return SELECT_FILE_SYSTEM_PAGE;
@@ -1689,30 +1678,6 @@ SelectPartitionPage(PINPUT_RECORD Ir)
 }
 
 
-static VOID
-DrawInputField(ULONG FieldLength,
-               SHORT Left,
-               SHORT Top,
-               PCHAR FieldContent)
-{
-    CHAR buf[100];
-    COORD coPos;
-    DWORD Written;
-
-    coPos.X = Left;
-    coPos.Y = Top;
-    memset(buf, '_', sizeof(buf));
-    buf[FieldLength - strlen(FieldContent)] = 0;
-    strcat(buf, FieldContent);
-
-    WriteConsoleOutputCharacterA(StdOutput,
-                                 buf,
-                                 strlen(buf),
-                                 coPos,
-                                 &Written);
-}
-
-
 #define PARTITION_SIZE_INPUT_FIELD_LENGTH 6
 /* Restriction for MaxSize: pow(10, PARTITION_SIZE_INPUT_FIELD_LENGTH)-1 */
 #define PARTITION_MAXSIZE 999999
@@ -1731,8 +1696,9 @@ ShowPartitionSizeInputBox(SHORT Left,
     COORD coPos;
     DWORD Written;
     CHAR Buffer[100];
+    WCHAR PartitionSizeBuffer[100];
     ULONG Index;
-    CHAR ch;
+    WCHAR ch;
     SHORT iLeft;
     SHORT iTop;
 
@@ -1753,7 +1719,7 @@ ShowPartitionSizeInputBox(SHORT Left,
 
     WriteConsoleOutputCharacterA(StdOutput,
                                  Buffer,
-                                 strlen (Buffer),
+                                 strlen(Buffer),
                                  coPos,
                                  &Written);
 
@@ -1762,16 +1728,16 @@ ShowPartitionSizeInputBox(SHORT Left,
     coPos.Y = iTop;
     WriteConsoleOutputCharacterA(StdOutput,
                                  Buffer,
-                                 strlen (Buffer),
+                                 strlen(Buffer),
                                  coPos,
                                  &Written);
 
-    sprintf(Buffer, "%lu", MaxSize);
-    Index = strlen(Buffer);
-    DrawInputField(PARTITION_SIZE_INPUT_FIELD_LENGTH,
-                   iLeft,
-                   iTop,
-                   Buffer);
+    swprintf(PartitionSizeBuffer, L"%lu", MaxSize);
+    Index = wcslen(PartitionSizeBuffer);
+    CONSOLE_SetInputTextXY(iLeft,
+                           iTop,
+                           PARTITION_SIZE_INPUT_FIELD_LENGTH,
+                           PartitionSizeBuffer);
 
     while (TRUE)
     {
@@ -1783,52 +1749,53 @@ ShowPartitionSizeInputBox(SHORT Left,
             if (Quit != NULL)
                 *Quit = TRUE;
 
-            Buffer[0] = 0;
+            PartitionSizeBuffer[0] = 0;
             break;
         }
-        else if (Ir.Event.KeyEvent.wVirtualKeyCode == VK_RETURN)       /* ENTER */
+        else if (Ir.Event.KeyEvent.wVirtualKeyCode == VK_RETURN)    /* ENTER */
         {
             break;
         }
-        else if (Ir.Event.KeyEvent.wVirtualKeyCode == VK_ESCAPE)       /* ESCAPE */
+        else if (Ir.Event.KeyEvent.wVirtualKeyCode == VK_ESCAPE)    /* ESCAPE */
         {
             if (Cancel != NULL)
                 *Cancel = TRUE;
 
-            Buffer[0] = 0;
+            PartitionSizeBuffer[0] = 0;
             break;
         }
         else if ((Ir.Event.KeyEvent.wVirtualKeyCode == VK_BACK) &&  /* BACKSPACE */
                  (Index > 0))
         {
             Index--;
-            Buffer[Index] = 0;
+            PartitionSizeBuffer[Index] = 0;
 
-            DrawInputField(PARTITION_SIZE_INPUT_FIELD_LENGTH,
-                           iLeft,
-                           iTop,
-                           Buffer);
+            CONSOLE_SetInputTextXY(iLeft,
+                                   iTop,
+                                   PARTITION_SIZE_INPUT_FIELD_LENGTH,
+                                   PartitionSizeBuffer);
         }
         else if ((Ir.Event.KeyEvent.uChar.AsciiChar != 0x00) &&
                  (Index < PARTITION_SIZE_INPUT_FIELD_LENGTH))
         {
-            ch = Ir.Event.KeyEvent.uChar.AsciiChar;
+            ch = (WCHAR)Ir.Event.KeyEvent.uChar.AsciiChar;
 
-            if ((ch >= '0') && (ch <= '9'))
+            if ((ch >= L'0') && (ch <= L'9'))
             {
-                Buffer[Index] = ch;
+                PartitionSizeBuffer[Index] = ch;
                 Index++;
-                Buffer[Index] = 0;
+                PartitionSizeBuffer[Index] = 0;
 
-                DrawInputField(PARTITION_SIZE_INPUT_FIELD_LENGTH,
-                               iLeft,
-                               iTop,
-                               Buffer);
+                CONSOLE_SetInputTextXY(iLeft,
+                                       iTop,
+                                       PARTITION_SIZE_INPUT_FIELD_LENGTH,
+                                       PartitionSizeBuffer);
             }
         }
     }
 
-    strcpy(InputBuffer, Buffer);
+    /* Convert UNICODE --> ANSI the poor man's way */
+    sprintf(InputBuffer, "%S", PartitionSizeBuffer);
 }
 
 
@@ -2994,6 +2961,10 @@ InstallDirectoryPage(PINPUT_RECORD Ir)
     CONSOLE_SetInputTextXY(8, 11, 51, InstallDir);
     MUIDisplayPage(INSTALL_DIRECTORY_PAGE);
 
+    // FIXME: Check the validity of the InstallDir; however what to do
+    // if it is invalid but we are in unattended setup? (case of somebody
+    // specified an invalid installation directory in the unattended file).
+
     if (IsUnattendedSetup)
     {
         return InstallDirectoryPage1(InstallDir,
@@ -3015,6 +2986,15 @@ InstallDirectoryPage(PINPUT_RECORD Ir)
         }
         else if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
         {
+            /*
+             * Check for the validity of the installation directory and pop up
+             * an error if it is not the case. Then the user can fix its input.
+             */
+            if (!IsValidPath(InstallDir, Length))
+            {
+                MUIDisplayError(ERROR_DIRECTORY_NAME, Ir, POPUP_WAIT_ENTER);
+                return INSTALL_DIRECTORY_PAGE;
+            }
             return InstallDirectoryPage1(InstallDir,
                                          DiskEntry,
                                          PartEntry);
@@ -3132,7 +3112,8 @@ AddSectionToCopyQueue(HINF InfFile,
     PWCHAR FileKeyValue;
     PWCHAR DirKeyValue;
     PWCHAR TargetFileName;
-    WCHAR CompleteOrigFileName[512];
+    ULONG Length;
+    WCHAR CompleteOrigDirName[512];
 
     if (SourceCabinet)
         return AddSectionToCopyQueueCab(InfFile, L"SourceFiles", SourceCabinet, DestinationPath, Ir);
@@ -3191,14 +3172,35 @@ AddSectionToCopyQueue(HINF InfFile,
             break;
         }
 
-        wcscpy(CompleteOrigFileName, SourceRootDir.Buffer);
-        wcscat(CompleteOrigFileName, L"\\");
-        wcscat(CompleteOrigFileName, DirKeyValue);
+        if ((DirKeyValue[0] == 0) || (DirKeyValue[0] == L'\\' && DirKeyValue[1] == 0))
+        {
+            /* Installation path */
+            wcscpy(CompleteOrigDirName, SourceRootDir.Buffer);
+        }
+        else if (DirKeyValue[0] == L'\\')
+        {
+            /* Absolute path */
+            wcscpy(CompleteOrigDirName, DirKeyValue);
+        }
+        else // if (DirKeyValue[0] != L'\\')
+        {
+            /* Path relative to the installation path */
+            wcscpy(CompleteOrigDirName, SourceRootDir.Buffer);
+            wcscat(CompleteOrigDirName, L"\\");
+            wcscat(CompleteOrigDirName, DirKeyValue);
+        }
+
+        /* Remove trailing backslash */
+        Length = wcslen(CompleteOrigDirName);
+        if ((Length > 0) && (CompleteOrigDirName[Length - 1] == L'\\'))
+        {
+            CompleteOrigDirName[Length - 1] = 0;
+        }
 
         if (!SetupQueueCopy(SetupFileQueue,
                             SourceCabinet,
                             SourceRootPath.Buffer,
-                            CompleteOrigFileName,
+                            CompleteOrigDirName,
                             FileKeyName,
                             DirKeyValue,
                             TargetFileName))
@@ -3220,7 +3222,7 @@ PrepareCopyPageInfFile(HINF InfFile,
     WCHAR PathBuffer[MAX_PATH];
     INFCONTEXT DirContext;
     PWCHAR AdditionalSectionName = NULL;
-    PWCHAR KeyValue;
+    PWCHAR DirKeyValue;
     ULONG Length;
     NTSTATUS Status;
 
@@ -3244,16 +3246,20 @@ PrepareCopyPageInfFile(HINF InfFile,
     /* Create directories */
 
     /*
-    * FIXME:
-    * Install directories like '\reactos\test' are not handled yet.
-    */
+     * FIXME:
+     * - Install directories like '\reactos\test' are not handled yet.
+     * - Copying files to DestinationRootPath should be done from within
+     *   the SystemPartitionFiles section.
+     *   At the moment we check whether we specify paths like '\foo' or '\\' for that.
+     *   For installing to DestinationPath specify just '\' .
+     */
 
     /* Get destination path */
     wcscpy(PathBuffer, DestinationPath.Buffer);
 
     /* Remove trailing backslash */
     Length = wcslen(PathBuffer);
-    if ((Length > 0) && (PathBuffer[Length - 1] == '\\'))
+    if ((Length > 0) && (PathBuffer[Length - 1] == L'\\'))
     {
         PathBuffer[Length - 1] = 0;
     }
@@ -3285,27 +3291,61 @@ PrepareCopyPageInfFile(HINF InfFile,
     /* Enumerate the directory values and create the subdirectories */
     do
     {
-        if (!INF_GetData(&DirContext, NULL, &KeyValue))
+        if (!INF_GetData(&DirContext, NULL, &DirKeyValue))
         {
             DPRINT1("break\n");
             break;
         }
 
-        if (KeyValue[0] == L'\\' && KeyValue[1] != 0)
+        if ((DirKeyValue[0] == 0) || (DirKeyValue[0] == L'\\' && DirKeyValue[1] == 0))
         {
-            DPRINT("Absolute Path: '%S'\n", KeyValue);
+            /* Installation path */
+            DPRINT("InstallationPath: '%S'\n", DirKeyValue);
+
+            wcscpy(PathBuffer, DestinationPath.Buffer);
+
+            DPRINT("FullPath: '%S'\n", PathBuffer);
+        }
+        else if (DirKeyValue[0] == L'\\')
+        {
+            /* Absolute path */
+            DPRINT("Absolute Path: '%S'\n", DirKeyValue);
 
             wcscpy(PathBuffer, DestinationRootPath.Buffer);
-            wcscat(PathBuffer, KeyValue);
+            wcscat(PathBuffer, DirKeyValue);
+
+            /* Remove trailing backslash */
+            Length = wcslen(PathBuffer);
+            if ((Length > 0) && (PathBuffer[Length - 1] == L'\\'))
+            {
+                PathBuffer[Length - 1] = 0;
+            }
 
             DPRINT("FullPath: '%S'\n", PathBuffer);
+
+            Status = SetupCreateDirectory(PathBuffer);
+            if (!NT_SUCCESS(Status) && Status != STATUS_OBJECT_NAME_COLLISION)
+            {
+                DPRINT("Creating directory '%S' failed: Status = 0x%08lx", PathBuffer, Status);
+                MUIDisplayError(ERROR_CREATE_DIR, Ir, POPUP_WAIT_ENTER);
+                return FALSE;
+            }
         }
-        else if (KeyValue[0] != L'\\')
+        else // if (DirKeyValue[0] != L'\\')
         {
-            DPRINT("RelativePath: '%S'\n", KeyValue);
+            /* Path relative to the installation path */
+            DPRINT("RelativePath: '%S'\n", DirKeyValue);
+
             wcscpy(PathBuffer, DestinationPath.Buffer);
             wcscat(PathBuffer, L"\\");
-            wcscat(PathBuffer, KeyValue);
+            wcscat(PathBuffer, DirKeyValue);
+
+            /* Remove trailing backslash */
+            Length = wcslen(PathBuffer);
+            if ((Length > 0) && (PathBuffer[Length - 1] == L'\\'))
+            {
+                PathBuffer[Length - 1] = 0;
+            }
 
             DPRINT("FullPath: '%S'\n", PathBuffer);
 
@@ -3317,7 +3357,7 @@ PrepareCopyPageInfFile(HINF InfFile,
                 return FALSE;
             }
         }
-    } while (SetupFindNextLine (&DirContext, &DirContext));
+    } while (SetupFindNextLine(&DirContext, &DirContext));
 
     return TRUE;
 }
@@ -3584,7 +3624,7 @@ RegistryPage(PINPUT_RECORD Ir)
 
     if (!SetInstallPathValue(&DestinationPath))
     {
-        DPRINT("SetInstallPathValue() failed\n");
+        DPRINT1("SetInstallPathValue() failed\n");
         MUIDisplayError(ERROR_INITIALIZE_REGISTRY, Ir, POPUP_WAIT_ENTER);
         return QUIT_PAGE;
     }
@@ -3594,7 +3634,7 @@ RegistryPage(PINPUT_RECORD Ir)
     Status = NtInitializeRegistry(CM_BOOT_FLAG_SETUP);
     if (!NT_SUCCESS(Status))
     {
-        DPRINT("NtInitializeRegistry() failed (Status %lx)\n", Status);
+        DPRINT1("NtInitializeRegistry() failed (Status %lx)\n", Status);
         MUIDisplayError(ERROR_CREATE_HIVE, Ir, POPUP_WAIT_ENTER);
         return QUIT_PAGE;
     }
@@ -3640,7 +3680,7 @@ RegistryPage(PINPUT_RECORD Ir)
 
         if (!ImportRegistryFile(File, Section, LanguageId, Delete))
         {
-            DPRINT("Importing %S failed\n", File);
+            DPRINT1("Importing %S failed\n", File);
 
             MUIDisplayError(ERROR_IMPORT_HIVE, Ir, POPUP_WAIT_ENTER);
             return QUIT_PAGE;
@@ -3848,7 +3888,7 @@ BootLoaderPage(PINPUT_RECORD Ir)
 
             break;
         }
-        else if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D)   /* ENTER */
+        else if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D)    /* ENTER */
         {
             if (Line == 12)
             {
@@ -3896,7 +3936,7 @@ BootLoaderFloppyPage(PINPUT_RECORD Ir)
 
             break;
         }
-        else if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D)   /* ENTER */
+        else if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D)    /* ENTER */
         {
             if (DoesFileExist(L"\\Device\\Floppy0", L"\\") == FALSE)
             {