[SYSSETUP] Add Lunar theme option to 2nd setup stage
[reactos.git] / dll / win32 / syssetup / wizard.c
index 9c57f6b..45f1394 100644 (file)
@@ -50,9 +50,6 @@ typedef struct _REGISTRATIONDATA
 
 extern void WINAPI Control_RunDLLW(HWND hWnd, HINSTANCE hInst, LPCWSTR cmd, DWORD nCmdShow);
 
-BOOL
-GetRosInstallCD(WCHAR *pwszPath, DWORD cchPathMax);
-
 
 static VOID
 CenterWindow(HWND hWnd)
@@ -296,7 +293,7 @@ AckPageDlgProc(HWND hwndDlg,
 
             Projects = NULL;
             ProjectsSize = 256;
-            do
+            while (TRUE)
             {
                 Projects = HeapAlloc(GetProcessHeap(), 0, ProjectsSize * sizeof(WCHAR));
                 if (NULL == Projects)
@@ -316,9 +313,9 @@ AckPageDlgProc(HWND hwndDlg,
                 HeapFree(GetProcessHeap(), 0, Projects);
                 ProjectsSize *= 2;
             }
-            while (1);
+
             CurrentProject = Projects;
-            while (L'\0' != *CurrentProject)
+            while (*CurrentProject != L'\0')
             {
                 End = wcschr(CurrentProject, L'\n');
                 if (NULL != End)
@@ -388,8 +385,6 @@ WriteOwnerSettings(WCHAR * OwnerName,
     HKEY hKey;
     LONG res;
 
-
-
     res = RegOpenKeyExW(HKEY_LOCAL_MACHINE,
                         L"Software\\Microsoft\\Windows NT\\CurrentVersion",
                         0,
@@ -490,11 +485,11 @@ OwnerPageDlgProc(HWND hwndDlg,
                     OwnerName[0] = 0;
                     if (GetDlgItemTextW(hwndDlg, IDC_OWNERNAME, OwnerName, 50) == 0)
                     {
-                        if (0 == LoadStringW(hDllInstance, IDS_REACTOS_SETUP, Title, sizeof(Title) / sizeof(Title[0])))
+                        if (0 == LoadStringW(hDllInstance, IDS_REACTOS_SETUP, Title, ARRAYSIZE(Title)))
                         {
                             wcscpy(Title, L"ReactOS Setup");
                         }
-                        if (0 == LoadStringW(hDllInstance, IDS_WZD_NAME, ErrorName, sizeof(ErrorName) / sizeof(ErrorName[0])))
+                        if (0 == LoadStringW(hDllInstance, IDS_WZD_NAME, ErrorName, ARRAYSIZE(ErrorName)))
                         {
                             wcscpy(ErrorName, L"Setup cannot continue until you enter your name.");
                         }
@@ -544,12 +539,12 @@ WriteComputerSettings(WCHAR * ComputerName, HWND hwndDlg)
     {
         if (hwndDlg != NULL)
         {
-            if (0 == LoadStringW(hDllInstance, IDS_REACTOS_SETUP, Title, sizeof(Title) / sizeof(Title[0])))
+            if (0 == LoadStringW(hDllInstance, IDS_REACTOS_SETUP, Title, ARRAYSIZE(Title)))
             {
                 wcscpy(Title, L"ReactOS Setup");
             }
             if (0 == LoadStringW(hDllInstance, IDS_WZD_SETCOMPUTERNAME, ErrorComputerName,
-                                 sizeof(ErrorComputerName) / sizeof(ErrorComputerName[0])))
+                                 ARRAYSIZE(ErrorComputerName)))
             {
                 wcscpy(ErrorComputerName, L"Setup failed to set the computer name.");
             }
@@ -580,7 +575,7 @@ WriteDefaultLogonData(LPWSTR Domain)
     if (LoadStringW(hDllInstance,
                     IDS_ADMINISTRATOR_NAME,
                     szAdministratorName,
-                    sizeof(szAdministratorName) / sizeof(WCHAR)) == 0)
+                    ARRAYSIZE(szAdministratorName)) == 0)
     {
         wcscpy(szAdministratorName, L"Administrator");
     }
@@ -594,14 +589,14 @@ WriteDefaultLogonData(LPWSTR Domain)
         return FALSE;
 
     lError = RegSetValueEx(hKey,
-                           L"DefaultDomain",
+                           L"DefaultDomainName",
                            0,
                            REG_SZ,
                            (LPBYTE)Domain,
                            (wcslen(Domain)+ 1) * sizeof(WCHAR));
     if (lError != ERROR_SUCCESS)
     {
-        DPRINT1("RegSetValueEx(\"DefaultDomain\") failed!\n");
+        DPRINT1("RegSetValueEx(\"DefaultDomainName\") failed!\n");
     }
 
     lError = RegSetValueEx(hKey,
@@ -657,7 +652,7 @@ ComputerPageDlgProc(HWND hwndDlg,
 
     pSetupData = (PSETUPDATA)GetWindowLongPtr(hwndDlg, DWLP_USER);
 
-    if (0 == LoadStringW(hDllInstance, IDS_REACTOS_SETUP, Title, sizeof(Title) / sizeof(Title[0])))
+    if (0 == LoadStringW(hDllInstance, IDS_REACTOS_SETUP, Title, ARRAYSIZE(Title)))
     {
         wcscpy(Title, L"ReactOS Setup");
     }
@@ -715,7 +710,7 @@ ComputerPageDlgProc(HWND hwndDlg,
                     if (0 == GetDlgItemTextW(hwndDlg, IDC_COMPUTERNAME, ComputerName, MAX_COMPUTERNAME_LENGTH + 1))
                     {
                         if (0 == LoadStringW(hDllInstance, IDS_WZD_COMPUTERNAME, EmptyComputerName,
-                                             sizeof(EmptyComputerName) / sizeof(EmptyComputerName[0])))
+                                             ARRAYSIZE(EmptyComputerName)))
                         {
                             wcscpy(EmptyComputerName, L"Setup cannot continue until you enter the name of your computer.");
                         }
@@ -741,7 +736,7 @@ ComputerPageDlgProc(HWND hwndDlg,
                         (GetDlgItemText(hwndDlg, IDC_ADMINPASSWORD2, Password2, 128) == 0))
                     {
                         if (0 == LoadStringW(hDllInstance, IDS_WZD_PASSWORDEMPTY, EmptyPassword,
-                                             sizeof(EmptyPassword) / sizeof(EmptyPassword[0])))
+                                             ARRAYSIZE(EmptyPassword)))
                         {
                             wcscpy(EmptyPassword, L"You must enter a password !");
                         }
@@ -757,7 +752,7 @@ ComputerPageDlgProc(HWND hwndDlg,
                     if (wcscmp(Password1, Password2))
                     {
                         if (0 == LoadStringW(hDllInstance, IDS_WZD_PASSWORDMATCH, NotMatchPassword,
-                                             sizeof(NotMatchPassword) / sizeof(NotMatchPassword[0])))
+                                             ARRAYSIZE(NotMatchPassword)))
                         {
                             wcscpy(NotMatchPassword, L"The passwords you entered do not match. Please enter the desired password again.");
                         }
@@ -773,7 +768,7 @@ ComputerPageDlgProc(HWND hwndDlg,
                         if (!isprint(*Password))
                         {
                             if (0 == LoadStringW(hDllInstance, IDS_WZD_PASSWORDCHAR, WrongPassword,
-                                                 sizeof(WrongPassword) / sizeof(WrongPassword[0])))
+                                                 ARRAYSIZE(WrongPassword)))
                             {
                                 wcscpy(WrongPassword, L"The password you entered contains invalid characters. Please enter a cleaned password.");
                             }
@@ -867,50 +862,49 @@ static BOOL
 RunControlPanelApplet(HWND hwnd, PCWSTR pwszCPLParameters)
 {
     MSG msg;
-    if (pwszCPLParameters)
+    STARTUPINFOW StartupInfo;
+    PROCESS_INFORMATION ProcessInformation;
+    WCHAR CmdLine[MAX_PATH] = L"rundll32.exe shell32.dll,Control_RunDLL ";
+
+    if (!pwszCPLParameters)
     {
-        STARTUPINFOW StartupInfo;
-        PROCESS_INFORMATION ProcessInformation;
-        WCHAR CmdLine[MAX_PATH] = L"rundll32.exe shell32.dll,Control_RunDLL ";
+        MessageBoxW(hwnd, L"Error: Failed to launch the Control Panel Applet.", NULL, MB_ICONERROR);
+        return FALSE;
+    }
 
-        ZeroMemory(&StartupInfo, sizeof(StartupInfo));
-        StartupInfo.cb = sizeof(StartupInfo);
+    ZeroMemory(&StartupInfo, sizeof(StartupInfo));
+    StartupInfo.cb = sizeof(StartupInfo);
+    ZeroMemory(&ProcessInformation, sizeof(ProcessInformation));
 
-        ASSERT(_countof(CmdLine) > wcslen(CmdLine) + wcslen(pwszCPLParameters));
-        wcscat(CmdLine, pwszCPLParameters);
+    ASSERT(_countof(CmdLine) > wcslen(CmdLine) + wcslen(pwszCPLParameters));
+    wcscat(CmdLine, pwszCPLParameters);
 
-        if (!CreateProcessW(NULL,
-                            CmdLine,
-                            NULL,
-                            NULL,
-                            FALSE,
-                            0,
-                            NULL,
-                            NULL,
-                            &StartupInfo,
-                            &ProcessInformation))
-        {
-            MessageBoxW(hwnd, L"Error: Failed to launch the Control Panel Applet.", NULL, MB_ICONERROR);
-            return FALSE;
-        }
-
-        while((MsgWaitForMultipleObjects(1, &ProcessInformation.hProcess, FALSE, INFINITE, QS_ALLINPUT|QS_ALLPOSTMESSAGE )) != WAIT_OBJECT_0)
-        { 
-           while(PeekMessageW(&msg, NULL, 0, 0, PM_REMOVE))
-           {
-               TranslateMessage(&msg);
-               DispatchMessageW(&msg);
-           }
-        }
-        CloseHandle(ProcessInformation.hThread);
-        CloseHandle(ProcessInformation.hProcess);
-        return TRUE;
-    }
-    else
+    if (!CreateProcessW(NULL,
+                        CmdLine,
+                        NULL,
+                        NULL,
+                        FALSE,
+                        0,
+                        NULL,
+                        NULL,
+                        &StartupInfo,
+                        &ProcessInformation))
     {
         MessageBoxW(hwnd, L"Error: Failed to launch the Control Panel Applet.", NULL, MB_ICONERROR);
         return FALSE;
     }
+
+    while ((MsgWaitForMultipleObjects(1, &ProcessInformation.hProcess, FALSE, INFINITE, QS_ALLINPUT|QS_ALLPOSTMESSAGE )) != WAIT_OBJECT_0)
+    { 
+       while (PeekMessageW(&msg, NULL, 0, 0, PM_REMOVE))
+       {
+           TranslateMessage(&msg);
+           DispatchMessageW(&msg);
+       }
+    }
+    CloseHandle(ProcessInformation.hThread);
+    CloseHandle(ProcessInformation.hProcess);
+    return TRUE;
 }
 
 static VOID
@@ -922,7 +916,7 @@ WriteUserLocale(VOID)
 
     lcid = GetSystemDefaultLCID();
 
-    if (GetLocaleInfoW(MAKELCID(lcid, SORT_DEFAULT), LOCALE_ILANGUAGE, Locale, sizeof(Locale) / sizeof(Locale[0])) != 0)
+    if (GetLocaleInfoW(MAKELCID(lcid, SORT_DEFAULT), LOCALE_ILANGUAGE, Locale, ARRAYSIZE(Locale)) != 0)
     {
         if (RegCreateKeyExW(HKEY_CURRENT_USER, L"Control Panel\\International",
                             0, NULL, REG_OPTION_NON_VOLATILE,
@@ -986,16 +980,9 @@ LocalePageDlgProc(HWND hwndDlg,
                     PropSheet_SetWizButtons(GetParent(hwndDlg), PSWIZB_BACK | PSWIZB_NEXT);
                     if (SetupData->UnattendSetup)
                     {
-                        WCHAR wszPath[MAX_PATH];
-                        if (GetRosInstallCD(wszPath, _countof(wszPath)))
+                        // if (!*SetupData->SourcePath)
                         {
-                            WCHAR wszParams[1024];
-                            swprintf(wszParams, L"intl.cpl,,/f:\"%sreactos\\unattend.inf\"", wszPath);
-                            RunControlPanelApplet(hwndDlg, wszParams);
-                        }
-                        else
-                        {
-                            RunControlPanelApplet(hwndDlg, L"intl.cpl,,/f:\"unattend.inf\"");
+                            RunControlPanelApplet(hwndDlg, L"intl.cpl,,/f:\"$winnt$.inf\""); // Should be in System32
                         }
 
                         SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, IDD_OWNERPAGE);
@@ -1501,14 +1488,14 @@ WriteDateTimeSettings(HWND hwndDlg, PSETUPDATA SetupData)
                      SetupData);
 
     SetAutoDaylightInfo(GetDlgItem(hwndDlg, IDC_AUTODAYLIGHT));
-    if(!SetSystemLocalTime(hwndDlg, SetupData))
+    if (!SetSystemLocalTime(hwndDlg, SetupData))
     {
-        if (0 == LoadStringW(hDllInstance, IDS_REACTOS_SETUP, Title, sizeof(Title) / sizeof(Title[0])))
+        if (0 == LoadStringW(hDllInstance, IDS_REACTOS_SETUP, Title, ARRAYSIZE(Title)))
         {
             wcscpy(Title, L"ReactOS Setup");
         }
         if (0 == LoadStringW(hDllInstance, IDS_WZD_LOCALTIME, ErrorLocalTime,
-                             sizeof(ErrorLocalTime) / sizeof(ErrorLocalTime[0])))
+                             ARRAYSIZE(ErrorLocalTime)))
         {
             wcscpy(ErrorLocalTime, L"Setup was unable to set the local time.");
         }
@@ -1606,6 +1593,17 @@ DateTimePageDlgProc(HWND hwndDlg,
     return FALSE;
 }
 
+static struct ThemeInfo
+{
+    LPCWSTR PreviewBitmap;
+    UINT DisplayName;
+    LPCWSTR ThemeFile;
+
+} Themes[] = {
+    { MAKEINTRESOURCE(IDB_CLASSIC), IDS_CLASSIC, NULL },
+    { MAKEINTRESOURCE(IDB_LAUTUS), IDS_LAUTUS, L"themes\\lautus\\lautus.msstyles" },
+    { MAKEINTRESOURCE(IDB_LUNAR), IDS_LUNAR, L"themes\\lunar\\lunar.msstyles" },
+};
 
 static INT_PTR CALLBACK
 ThemePageDlgProc(HWND hwndDlg,
@@ -1614,6 +1612,7 @@ ThemePageDlgProc(HWND hwndDlg,
                     LPARAM lParam)
 {
     PSETUPDATA SetupData;
+    LPNMLISTVIEW pnmv;
 
     /* Retrieve pointer to the global setup data */
     SetupData = (PSETUPDATA)GetWindowLongPtr(hwndDlg, GWLP_USERDATA);
@@ -1622,45 +1621,75 @@ ThemePageDlgProc(HWND hwndDlg,
     {
         case WM_INITDIALOG:
         {
-            BUTTON_IMAGELIST imldata = {0, {0,10,0,10}, BUTTON_IMAGELIST_ALIGN_TOP};
+            HWND hListView;
+            HIMAGELIST himl;
+            DWORD n;
+            LVITEM lvi = {0};
 
             /* Save pointer to the global setup data */
             SetupData = (PSETUPDATA)((LPPROPSHEETPAGE)lParam)->lParam;
             SetWindowLongPtr(hwndDlg, GWLP_USERDATA, (DWORD_PTR)SetupData);
 
-            imldata.himl = ImageList_LoadImage(hDllInstance, MAKEINTRESOURCE(IDB_CLASSIC), 0, 0, 0x00FF00FF, IMAGE_BITMAP, LR_CREATEDIBSECTION);
-            SendDlgItemMessage(hwndDlg, IDC_CLASSICSTYLE, BCM_SETIMAGELIST, 0, (LPARAM)&imldata);
+            hListView = GetDlgItem(hwndDlg, IDC_THEMEPICKER);
 
-            imldata.himl = ImageList_LoadImage(hDllInstance, MAKEINTRESOURCE(IDB_LAUTUS), 0, 0, 0x00FF00FF , IMAGE_BITMAP, LR_CREATEDIBSECTION);
-            SendDlgItemMessage(hwndDlg, IDC_THEMEDSTYLE, BCM_SETIMAGELIST, 0, (LPARAM)&imldata);
+            /* Common */
+            himl = ImageList_Create(180, 163, ILC_COLOR32 | ILC_MASK, ARRAYSIZE(Themes), 1);
+            lvi.mask = LVIF_TEXT | LVIF_IMAGE |LVIF_STATE;
 
-            SendDlgItemMessage(hwndDlg, IDC_CLASSICSTYLE, BM_SETCHECK, BST_CHECKED, 0);
+            for (n = 0; n < ARRAYSIZE(Themes); ++n)
+            {
+                WCHAR DisplayName[100] = {0};
+                /* Load the bitmap */
+                HANDLE image = LoadImageW(hDllInstance, Themes[n].PreviewBitmap, IMAGE_BITMAP, 0, 0, LR_CREATEDIBSECTION);
+                ImageList_AddMasked(himl, image, RGB(255,0,255));
+
+                /* Load the string */
+                LoadStringW(hDllInstance, Themes[n].DisplayName, DisplayName, ARRAYSIZE(DisplayName));
+                DisplayName[ARRAYSIZE(DisplayName)-1] = UNICODE_NULL;
+
+                /* Add the listview item */
+                lvi.iItem  = n;
+                lvi.iImage = n;
+                lvi.pszText = DisplayName;
+                ListView_InsertItem(hListView, &lvi);
+            }
+
+            /* Register the imagelist */
+            ListView_SetImageList(hListView, himl, LVSIL_NORMAL);
+            /* Transparant background */
+            ListView_SetBkColor(hListView, CLR_NONE);
+            ListView_SetTextBkColor(hListView, CLR_NONE);
+            /* Reduce the size between the items */
+            ListView_SetIconSpacing(hListView, 190, 173);
             break;
         }
-        case WM_COMMAND:
-            if (HIWORD(wParam) == BN_CLICKED)
+        case WM_NOTIFY:
+            switch (((LPNMHDR)lParam)->code)
             {
-                switch (LOWORD(wParam))
-                {
-                    case IDC_THEMEDSTYLE:
+                //case LVN_ITEMCHANGING:
+                case LVN_ITEMCHANGED:
+                    pnmv = (LPNMLISTVIEW)lParam;
+                    if ((pnmv->uChanged & LVIF_STATE) && (pnmv->uNewState & LVIS_SELECTED))
                     {
-                        WCHAR wszParams[1024];
-                        WCHAR wszTheme[MAX_PATH];
-                        WCHAR* format = L"desk.cpl desk,@Appearance /Action:ActivateMSTheme /file:\"%s\"";
+                        int iTheme = pnmv->iItem;
+                        DPRINT1("Selected theme: %S\n", Themes[iTheme].DisplayName);
 
-                        SHGetFolderPathAndSubDirW(0, CSIDL_RESOURCES, NULL, SHGFP_TYPE_DEFAULT, L"themes\\lautus\\lautus.msstyles", wszTheme);
-                        swprintf(wszParams, format, wszTheme);
-                        RunControlPanelApplet(hwndDlg, wszParams);
-                        break;
+                        if (Themes[iTheme].ThemeFile)
+                        {
+                            WCHAR wszParams[1024];
+                            WCHAR wszTheme[MAX_PATH];
+                            WCHAR* format = L"desk.cpl desk,@Appearance /Action:ActivateMSTheme /file:\"%s\"";
+
+                            SHGetFolderPathAndSubDirW(0, CSIDL_RESOURCES, NULL, SHGFP_TYPE_DEFAULT, Themes[iTheme].ThemeFile, wszTheme);
+                            swprintf(wszParams, format, wszTheme);
+                            RunControlPanelApplet(hwndDlg, wszParams);
+                        }
+                        else
+                        {
+                            RunControlPanelApplet(hwndDlg, L"desk.cpl desk,@Appearance /Action:ActivateMSTheme");
+                        }
                     }
-                    case IDC_CLASSICSTYLE:
-                        RunControlPanelApplet(hwndDlg, L"desk.cpl desk,@Appearance /Action:ActivateMSTheme");
-                        break;
-                }
-            }
-        case WM_NOTIFY:
-            switch (((LPNMHDR)lParam)->code)
-            {
+                    break;
                 case PSN_SETACTIVE:
                     /* Enable the Back and Next buttons */
                     PropSheet_SetWizButtons(GetParent(hwndDlg), PSWIZB_BACK | PSWIZB_NEXT);
@@ -1756,8 +1785,7 @@ RegistrationNotificationProc(PVOID Context,
                 }
                 if (0 == LoadStringW(hDllInstance, MessageID,
                                      ErrorMessage,
-                                     sizeof(ErrorMessage) /
-                                     sizeof(ErrorMessage[0])))
+                                     ARRAYSIZE(ErrorMessage)))
                 {
                     ErrorMessage[0] = L'\0';
                 }
@@ -1766,8 +1794,8 @@ RegistrationNotificationProc(PVOID Context,
                     FormatMessageW(FORMAT_MESSAGE_FROM_SYSTEM, NULL,
                                    StatusInfo->Win32Error, 0,
                                    ErrorMessage + wcslen(ErrorMessage),
-                                   sizeof(ErrorMessage) / sizeof(ErrorMessage[0]) -
-                                   wcslen(ErrorMessage), NULL);
+                                   ARRAYSIZE(ErrorMessage) - wcslen(ErrorMessage),
+                                   NULL);
                 }
                 RegistrationNotify.ErrorMessage = ErrorMessage;
             }
@@ -1850,8 +1878,7 @@ RegistrationProc(LPVOID Parameter)
         {
             if (0 == LoadStringW(hDllInstance, IDS_UNKNOWN_ERROR,
                                  UnknownError,
-                                 sizeof(UnknownError) / sizeof(UnknownError[0]) -
-                                 20))
+                                 ARRAYSIZE(UnknownError) - 20))
             {
                 wcscpy(UnknownError, L"Unknown error");
             }
@@ -1894,15 +1921,15 @@ StartComponentRegistration(HWND hwndDlg, PULONG MaxProgress)
     PREGISTRATIONDATA RegistrationData;
 
     DllCount = -1;
-    if (! SetupFindFirstLineW(hSysSetupInf, L"RegistrationPhase2",
-                              L"RegisterDlls", &Context))
+    if (!SetupFindFirstLineW(hSysSetupInf, L"RegistrationPhase2",
+                             L"RegisterDlls", &Context))
     {
         DPRINT1("No RegistrationPhase2 section found\n");
         return FALSE;
     }
-    if (! SetupGetStringFieldW(&Context, 1, SectionName,
-                               sizeof(SectionName) / sizeof(SectionName[0]),
-                               NULL))
+    if (!SetupGetStringFieldW(&Context, 1, SectionName,
+                              ARRAYSIZE(SectionName),
+                              NULL))
     {
         DPRINT1("Unable to retrieve section name\n");
         return FALSE;
@@ -2016,7 +2043,7 @@ ProcessPageDlgProc(HWND hwndDlg,
             {
                 if (0 != LoadStringW(hDllInstance, RegistrationNotify->ActivityID,
                                      Activity,
-                                     sizeof(Activity) / sizeof(Activity[0])))
+                                     ARRAYSIZE(Activity)))
                 {
                     SendDlgItemMessageW(hwndDlg, IDC_ACTIVITY, WM_SETTEXT,
                                         0, (LPARAM) Activity);
@@ -2031,7 +2058,7 @@ ProcessPageDlgProc(HWND hwndDlg,
             if (NULL != RegistrationNotify->ErrorMessage)
             {
                 if (0 == LoadStringW(hDllInstance, IDS_REACTOS_SETUP,
-                                     Title, sizeof(Title) / sizeof(Title[0])))
+                                     Title, ARRAYSIZE(Title)))
                 {
                     wcscpy(Title, L"ReactOS Setup");
                 }
@@ -2181,9 +2208,70 @@ FinishDlgProc(HWND hwndDlg,
 }
 
 
+/*
+ * GetInstallSourceWin32 retrieves the path to the ReactOS installation medium
+ * in Win32 format, for later use by syssetup and storage in the registry.
+ */
+static BOOL
+GetInstallSourceWin32(
+    OUT PWSTR pwszPath,
+    IN DWORD cchPathMax,
+    IN PCWSTR pwszNTPath)
+{
+    WCHAR wszDrives[512];
+    WCHAR wszNTPath[512]; // MAX_PATH ?
+    DWORD cchDrives;
+    PWCHAR pwszDrive;
+
+    *pwszPath = UNICODE_NULL;
+
+    cchDrives = GetLogicalDriveStringsW(_countof(wszDrives) - 1, wszDrives);
+    if (cchDrives == 0 || cchDrives >= _countof(wszDrives))
+    {
+        /* Buffer too small or failure */
+        LogItem(NULL, L"GetLogicalDriveStringsW failed");
+        return FALSE;
+    }
+
+    for (pwszDrive = wszDrives; *pwszDrive; pwszDrive += wcslen(pwszDrive) + 1)
+    {
+        WCHAR wszBuf[MAX_PATH];
+
+        /* Retrieve the NT path corresponding to the current Win32 DOS path */
+        pwszDrive[2] = UNICODE_NULL; // Temporarily remove the backslash
+        QueryDosDeviceW(pwszDrive, wszNTPath, _countof(wszNTPath));
+        pwszDrive[2] = L'\\';        // Restore the backslash
+
+        wcscat(wszNTPath, L"\\");    // Concat a backslash
+
+        /* Logging */
+        wsprintf(wszBuf, L"Testing '%s' --> '%s' %s a CD",
+                 pwszDrive, wszNTPath,
+                 (GetDriveTypeW(pwszDrive) == DRIVE_CDROM) ? L"is" : L"is not");
+        LogItem(NULL, wszBuf);
+
+        /* Check whether the NT path corresponds to the NT installation source path */
+        if (!_wcsicmp(wszNTPath, pwszNTPath))
+        {
+            /* Found it! */
+            wcscpy(pwszPath, pwszDrive); // cchPathMax
+
+            /* Logging */
+            wsprintf(wszBuf, L"GetInstallSourceWin32: %s", pwszPath);
+            LogItem(NULL, wszBuf);
+            wcscat(wszBuf, L"\n");
+            OutputDebugStringW(wszBuf);
+
+            return TRUE;
+        }
+    }
+
+    return FALSE;
+}
+
 VOID
-ProcessUnattendInf(
-    PSETUPDATA pSetupData)
+ProcessUnattendSection(
+    IN OUT PSETUPDATA pSetupData)
 {
     INFCONTEXT InfContext;
     WCHAR szName[256];
@@ -2191,26 +2279,26 @@ ProcessUnattendInf(
     DWORD LineLength;
     HKEY hKey;
 
-    if (!SetupFindFirstLineW(pSetupData->hUnattendedInf,
+    if (!SetupFindFirstLineW(pSetupData->hSetupInf,
                              L"Unattend",
                              L"UnattendSetupEnabled",
                              &InfContext))
     {
-        DPRINT1("Error: Cant find UnattendSetupEnabled Key! %d\n", GetLastError());
+        DPRINT1("Error: Cannot find UnattendSetupEnabled Key! %d\n", GetLastError());
         return;
     }
 
     if (!SetupGetStringFieldW(&InfContext,
                               1,
                               szValue,
-                              sizeof(szValue) / sizeof(WCHAR),
+                              ARRAYSIZE(szValue),
                               &LineLength))
     {
         DPRINT1("Error: SetupGetStringField failed with %d\n", GetLastError());
         return;
     }
 
-    if (wcscmp(szValue, L"yes") != 0)
+    if (_wcsicmp(szValue, L"yes") != 0)
     {
         DPRINT("Unattend setup was disabled by UnattendSetupEnabled key.\n");
         return;
@@ -2218,7 +2306,7 @@ ProcessUnattendInf(
 
     pSetupData->UnattendSetup = TRUE;
 
-    if (!SetupFindFirstLineW(pSetupData->hUnattendedInf,
+    if (!SetupFindFirstLineW(pSetupData->hSetupInf,
                              L"Unattend",
                              NULL,
                              &InfContext))
@@ -2232,7 +2320,7 @@ ProcessUnattendInf(
         if (!SetupGetStringFieldW(&InfContext,
                                   0,
                                   szName,
-                                  sizeof(szName) / sizeof(WCHAR),
+                                  ARRAYSIZE(szName),
                                   &LineLength))
         {
             DPRINT1("Error: SetupGetStringField failed with %d\n", GetLastError());
@@ -2242,61 +2330,60 @@ ProcessUnattendInf(
         if (!SetupGetStringFieldW(&InfContext,
                                   1,
                                   szValue,
-                                  sizeof(szValue) / sizeof(WCHAR),
+                                  ARRAYSIZE(szValue),
                                   &LineLength))
         {
             DPRINT1("Error: SetupGetStringField failed with %d\n", GetLastError());
             return;
         }
         DPRINT1("Name %S Value %S\n", szName, szValue);
-        if (!wcscmp(szName, L"FullName"))
+        if (!_wcsicmp(szName, L"FullName"))
         {
-            if ((sizeof(pSetupData->OwnerName) / sizeof(TCHAR)) > LineLength)
+            if (ARRAYSIZE(pSetupData->OwnerName) > LineLength)
             {
                 wcscpy(pSetupData->OwnerName, szValue);
             }
         }
-        else if (!wcscmp(szName, L"OrgName"))
+        else if (!_wcsicmp(szName, L"OrgName"))
         {
-            if ((sizeof(pSetupData->OwnerOrganization) / sizeof(WCHAR)) > LineLength)
+            if (ARRAYSIZE(pSetupData->OwnerOrganization) > LineLength)
             {
                 wcscpy(pSetupData->OwnerOrganization, szValue);
             }
         }
-        else if (!wcscmp(szName, L"ComputerName"))
+        else if (!_wcsicmp(szName, L"ComputerName"))
         {
-            if ((sizeof(pSetupData->ComputerName) / sizeof(WCHAR)) > LineLength)
+            if (ARRAYSIZE(pSetupData->ComputerName) > LineLength)
             {
                 wcscpy(pSetupData->ComputerName, szValue);
             }
         }
-        else if (!wcscmp(szName, L"AdminPassword"))
+        else if (!_wcsicmp(szName, L"AdminPassword"))
         {
-            if ((sizeof(pSetupData->AdminPassword) / sizeof(WCHAR)) > LineLength)
+            if (ARRAYSIZE(pSetupData->AdminPassword) > LineLength)
             {
                 wcscpy(pSetupData->AdminPassword, szValue);
             }
         }
-        else if (!wcscmp(szName, L"TimeZoneIndex"))
+        else if (!_wcsicmp(szName, L"TimeZoneIndex"))
         {
             pSetupData->TimeZoneIndex = _wtoi(szValue);
         }
-        else if (!wcscmp(szName, L"DisableAutoDaylightTimeSet"))
+        else if (!_wcsicmp(szName, L"DisableAutoDaylightTimeSet"))
         {
             pSetupData->DisableAutoDaylightTimeSet = _wtoi(szValue);
         }
-        else if (!wcscmp(szName, L"DisableGeckoInst"))
+        else if (!_wcsicmp(szName, L"DisableGeckoInst"))
         {
-            if(!wcscmp(szValue, L"yes"))
-                pSetupData->DisableGeckoInst = 1;
+            if (!_wcsicmp(szValue, L"yes"))
+                pSetupData->DisableGeckoInst = TRUE;
             else
-                pSetupData->DisableGeckoInst = 0;
+                pSetupData->DisableGeckoInst = FALSE;
         }
 
-    }
-    while (SetupFindNextLine(&InfContext, &InfContext));
+    } while (SetupFindNextLine(&InfContext, &InfContext));
 
-    if (SetupFindFirstLineW(pSetupData->hUnattendedInf,
+    if (SetupFindFirstLineW(pSetupData->hSetupInf,
                             L"Display",
                             NULL,
                             &InfContext))
@@ -2311,7 +2398,7 @@ ProcessUnattendInf(
                 if (!SetupGetStringFieldW(&InfContext,
                                           0,
                                           szName,
-                                          sizeof(szName) / sizeof(WCHAR),
+                                          ARRAYSIZE(szName),
                                           &LineLength))
                 {
                     DPRINT1("Error: SetupGetStringField failed with %d\n", GetLastError());
@@ -2321,7 +2408,7 @@ ProcessUnattendInf(
                 if (!SetupGetStringFieldW(&InfContext,
                                           1,
                                           szValue,
-                                          sizeof(szValue) / sizeof(WCHAR),
+                                          ARRAYSIZE(szValue),
                                           &LineLength))
                 {
                     DPRINT1("Error: SetupGetStringField failed with %d\n", GetLastError());
@@ -2333,28 +2420,27 @@ ProcessUnattendInf(
                 if (!iValue)
                     continue;
 
-                if (!wcscmp(szName, L"BitsPerPel"))
+                if (!_wcsicmp(szName, L"BitsPerPel"))
                 {
                     dm.dmFields |= DM_BITSPERPEL;
                     dm.dmBitsPerPel = iValue;
                 }
-                else if (!wcscmp(szName, L"XResolution"))
+                else if (!_wcsicmp(szName, L"XResolution"))
                 {
                     dm.dmFields |= DM_PELSWIDTH;
                     dm.dmPelsWidth = iValue;
                 }
-                else if (!wcscmp(szName, L"YResolution"))
+                else if (!_wcsicmp(szName, L"YResolution"))
                 {
                     dm.dmFields |= DM_PELSHEIGHT;
                     dm.dmPelsHeight = iValue;
                 }
-                else if (!wcscmp(szName, L"VRefresh"))
+                else if (!_wcsicmp(szName, L"VRefresh"))
                 {
                     dm.dmFields |= DM_DISPLAYFREQUENCY;
                     dm.dmDisplayFrequency = iValue;
                 }
-            }
-            while (SetupFindNextLine(&InfContext, &InfContext));
+            } while (SetupFindNextLine(&InfContext, &InfContext));
 
             ChangeDisplaySettingsW(&dm, CDS_UPDATEREGISTRY);
         }
@@ -2370,20 +2456,19 @@ ProcessUnattendInf(
         return;
     }
 
-    if (SetupFindFirstLineW(pSetupData->hUnattendedInf,
+    if (SetupFindFirstLineW(pSetupData->hSetupInf,
                             L"GuiRunOnce",
                             NULL,
                             &InfContext))
     {
-
         int i = 0;
         do
         {
-            if(SetupGetStringFieldW(&InfContext,
-                                    0,
-                                    szValue,
-                                    sizeof(szValue) / sizeof(WCHAR),
-                                    NULL))
+            if (SetupGetStringFieldW(&InfContext,
+                                     0,
+                                     szValue,
+                                     ARRAYSIZE(szValue),
+                                     NULL))
             {
                 WCHAR szPath[MAX_PATH];
                 swprintf(szName, L"%d", i);
@@ -2403,90 +2488,141 @@ ProcessUnattendInf(
                     }
                 }
             }
-        } while(SetupFindNextLine(&InfContext, &InfContext));
+        } while (SetupFindNextLine(&InfContext, &InfContext));
     }
 
     RegCloseKey(hKey);
 }
 
-/*
- * GetRosInstallCD should find the path to ros installation medium
- * BUG 1
- * If there are more than one CDDrive in it containing a ReactOS
- * installation cd, then it will pick the first one regardless if
- * it is really the installation cd
- *
- * The best way to implement this is to set the key
- * HKLM\Software\Microsoft\Windows NT\CurrentVersion\SourcePath (REG_SZ)
- */
-
-BOOL
-GetRosInstallCD(WCHAR *pwszPath, DWORD cchPathMax)
+VOID
+ProcessSetupInf(
+    IN OUT PSETUPDATA pSetupData)
 {
-    WCHAR wszDrives[512];
-    DWORD cchDrives;
-    WCHAR *pwszDrive;
+    WCHAR szPath[MAX_PATH];
+    WCHAR szValue[MAX_PATH];
+    INFCONTEXT InfContext;
+    DWORD LineLength;
+    HKEY hKey;
+    LONG res;
 
-    cchDrives = GetLogicalDriveStringsW(_countof(wszDrives) - 1, wszDrives);
-    if (cchDrives == 0 || cchDrives >= _countof(wszDrives))
+    pSetupData->hSetupInf = INVALID_HANDLE_VALUE;
+
+    /* Retrieve the path of the setup INF */
+    GetSystemDirectoryW(szPath, _countof(szPath));
+    wcscat(szPath, L"\\$winnt$.inf");
+
+    /* Open the setup INF */
+    pSetupData->hSetupInf = SetupOpenInfFileW(szPath,
+                                              NULL,
+                                              INF_STYLE_OLDNT,
+                                              NULL);
+    if (pSetupData->hSetupInf == INVALID_HANDLE_VALUE)
     {
-        /* buffer too small or failure */
-        LogItem(NULL, L"GetLogicalDriveStringsW failed");
-        return FALSE;
+        DPRINT1("Error: Cannot open the setup information file %S with error %d\n", szPath, GetLastError());
+        return;
     }
 
-    for (pwszDrive = wszDrives; pwszDrive[0]; pwszDrive += wcslen(pwszDrive) + 1)
+
+    /* Retrieve the NT source path from which the 1st-stage installer was run */
+    if (!SetupFindFirstLineW(pSetupData->hSetupInf,
+                             L"data",
+                             L"sourcepath",
+                             &InfContext))
     {
-        if (GetDriveTypeW(pwszDrive) == DRIVE_CDROM)
-        {
-            WCHAR wszBuf[MAX_PATH];
-            wsprintf(wszBuf, L"%sreactos\\system32\\ntoskrnl.exe", pwszDrive);
-            LogItem(NULL, wszBuf);
-            if (GetFileAttributesW(wszBuf) != INVALID_FILE_ATTRIBUTES)
-            {
-                /* the file exists, so this is the right drive */
-                wcsncpy(pwszPath, pwszDrive, cchPathMax);
-                OutputDebugStringW(L"GetRosInstallCD: ");OutputDebugStringW(pwszPath);OutputDebugStringW(L"\n");
-                return TRUE;
-            }
-        }
+        DPRINT1("Error: Cannot find sourcepath Key! %d\n", GetLastError());
+        return;
     }
-    return FALSE;
-}
 
+    if (!SetupGetStringFieldW(&InfContext,
+                              1,
+                              szValue,
+                              ARRAYSIZE(szValue),
+                              &LineLength))
+    {
+        DPRINT1("Error: SetupGetStringField failed with %d\n", GetLastError());
+        return;
+    }
 
-VOID
-ProcessUnattendSetup(
-    PSETUPDATA pSetupData)
-{
-    WCHAR szPath[MAX_PATH];
-    DWORD dwLength;
+    *pSetupData->SourcePath = UNICODE_NULL;
 
-    if (!GetRosInstallCD(szPath, MAX_PATH))
+    /* Close the setup INF as we are going to modify it manually */
+    if (pSetupData->hSetupInf != INVALID_HANDLE_VALUE)
+        SetupCloseInfFile(pSetupData->hSetupInf);
+
+
+    /* Find the installation source path in Win32 format */
+    if (!GetInstallSourceWin32(pSetupData->SourcePath,
+                               _countof(pSetupData->SourcePath),
+                               szValue))
     {
-        /* no cd drive found */
-        return;
+        *pSetupData->SourcePath = UNICODE_NULL;
     }
 
-    dwLength = wcslen(szPath);
-    if (dwLength + 21 > MAX_PATH)
+    /* Save the path in Win32 format in the setup INF */
+    swprintf(szValue, L"\"%s\"", pSetupData->SourcePath);
+    WritePrivateProfileStringW(L"data", L"dospath", szValue, szPath);
+
+    /*
+     * Save it also in the registry, in the following keys:
+     * - HKLM\Software\Microsoft\Windows\CurrentVersion\Setup ,
+     *   values "SourcePath" and "ServicePackSourcePath" (REG_SZ);
+     * - HKLM\Software\Microsoft\Windows NT\CurrentVersion ,
+     *   value "SourcePath" (REG_SZ); set to the full path (e.g. D:\I386).
+     */
+#if 0
+    res = RegOpenKeyExW(HKEY_LOCAL_MACHINE,
+                        L"Software\\Microsoft\\Windows NT\\CurrentVersion",
+                        0,
+                        KEY_ALL_ACCESS,
+                        &hKey);
+
+    if (res != ERROR_SUCCESS)
     {
-        /* FIXME
-         * allocate bigger buffer
-         */
-        return;
+        return FALSE;
+    }
+#endif
+
+    res = RegCreateKeyExW(HKEY_LOCAL_MACHINE,
+                          L"Software\\Microsoft\\Windows\\CurrentVersion\\Setup",
+                          0, NULL,
+                          REG_OPTION_NON_VOLATILE,
+                          KEY_ALL_ACCESS, // KEY_WRITE
+                          NULL,
+                          &hKey,
+                          NULL);
+    if (res == ERROR_SUCCESS)
+    {
+        res = RegSetValueExW(hKey,
+                             L"SourcePath",
+                             0,
+                             REG_SZ,
+                             (LPBYTE)pSetupData->SourcePath,
+                             (wcslen(pSetupData->SourcePath) + 1) * sizeof(WCHAR));
+
+        res = RegSetValueExW(hKey,
+                             L"ServicePackSourcePath",
+                             0,
+                             REG_SZ,
+                             (LPBYTE)pSetupData->SourcePath,
+                             (wcslen(pSetupData->SourcePath) + 1) * sizeof(WCHAR));
+
+        RegCloseKey(hKey);
     }
 
-    wcscat(szPath, L"reactos\\unattend.inf");
 
-    pSetupData->hUnattendedInf = SetupOpenInfFileW(szPath,
-                                                   NULL,
-                                                   INF_STYLE_OLDNT,
-                                                   NULL);
-    if (pSetupData->hUnattendedInf != INVALID_HANDLE_VALUE)
+    /* Now, re-open the setup INF (this must succeed) */
+    pSetupData->hSetupInf = SetupOpenInfFileW(szPath,
+                                              NULL,
+                                              INF_STYLE_OLDNT,
+                                              NULL);
+    if (pSetupData->hSetupInf == INVALID_HANDLE_VALUE)
     {
-        ProcessUnattendInf(pSetupData);
+        DPRINT1("Error: Cannot open the setup information file %S with error %d\n", szPath, GetLastError());
+        return;
     }
+
+    /* Process the unattended section of the setup file */
+    ProcessUnattendSection(pSetupData);
 }
 
 typedef DWORD(WINAPI *PFNREQUESTWIZARDPAGES)(PDWORD, HPROPSHEETPAGE *, PSETUPDATA);
@@ -2503,7 +2639,7 @@ InstallWizard(VOID)
     PSETUPDATA pSetupData = NULL;
     HMODULE hNetShell = NULL;
     PFNREQUESTWIZARDPAGES pfn = NULL;
-    DWORD dwPageCount = 8, dwNetworkPageCount = 0;
+    DWORD dwPageCount = 9, dwNetworkPageCount = 0;
 
     LogItem(L"BEGIN_SECTION", L"InstallWizard");
 
@@ -2550,8 +2686,8 @@ InstallWizard(VOID)
         goto done;
     }
 
-    pSetupData->hUnattendedInf = INVALID_HANDLE_VALUE;
-    ProcessUnattendSetup(pSetupData);
+    /* Process the $winnt$.inf setup file */
+    ProcessSetupInf(pSetupData);
 
     /* Create the Welcome page */
     psp.dwSize = sizeof(PROPSHEETPAGE);
@@ -2578,7 +2714,6 @@ InstallWizard(VOID)
     psp.pszTemplate = MAKEINTRESOURCE(IDD_LOCALEPAGE);
     phpage[nPages++] = CreatePropertySheetPage(&psp);
 
-
     /* Create the Owner page */
     psp.dwFlags = PSP_DEFAULT | PSP_USEHEADERTITLE | PSP_USEHEADERSUBTITLE;
     psp.pszHeaderTitle = MAKEINTRESOURCE(IDS_OWNERTITLE);
@@ -2595,7 +2730,6 @@ InstallWizard(VOID)
     psp.pszTemplate = MAKEINTRESOURCE(IDD_COMPUTERPAGE);
     phpage[nPages++] = CreatePropertySheetPage(&psp);
 
-
     /* Create the DateTime page */
     psp.dwFlags = PSP_DEFAULT | PSP_USEHEADERTITLE | PSP_USEHEADERSUBTITLE;
     psp.pszHeaderTitle = MAKEINTRESOURCE(IDS_DATETIMETITLE);
@@ -2629,13 +2763,14 @@ InstallWizard(VOID)
     psp.pszTemplate = MAKEINTRESOURCE(IDD_PROCESSPAGE);
     phpage[nPages++] = CreatePropertySheetPage(&psp);
 
-
     /* Create the Finish page */
     psp.dwFlags = PSP_DEFAULT | PSP_HIDEHEADER;
     psp.pfnDlgProc = FinishDlgProc;
     psp.pszTemplate = MAKEINTRESOURCE(IDD_FINISHPAGE);
     phpage[nPages++] = CreatePropertySheetPage(&psp);
 
+    ASSERT(nPages == dwPageCount);
+
     /* Create the property sheet */
     psh.dwSize = sizeof(PROPSHEETHEADER);
     psh.dwFlags = PSH_WIZARD97 | PSH_WATERMARK | PSH_HEADER | PSH_MODELESS;
@@ -2649,7 +2784,7 @@ InstallWizard(VOID)
 
     /* Create title font */
     pSetupData->hTitleFont = CreateTitleFont();
-    pSetupData->hBoldFont = CreateBoldFont();
+    pSetupData->hBoldFont  = CreateBoldFont();
 
     /* Display the wizard */
     hWnd = (HWND)PropertySheet(&psh);
@@ -2664,8 +2799,11 @@ InstallWizard(VOID)
         }
     }
 
-    if (pSetupData->hUnattendedInf != INVALID_HANDLE_VALUE)
-        SetupCloseInfFile(pSetupData->hUnattendedInf);
+    DeleteObject(pSetupData->hBoldFont);
+    DeleteObject(pSetupData->hTitleFont);
+
+    if (pSetupData->hSetupInf != INVALID_HANDLE_VALUE)
+        SetupCloseInfFile(pSetupData->hSetupInf);
 
 done:
     if (phpage != NULL)
@@ -2675,11 +2813,7 @@ done:
         FreeLibrary(hNetShell);
 
     if (pSetupData != NULL)
-    {
-        DeleteObject(pSetupData->hBoldFont);
-        DeleteObject(pSetupData->hTitleFont);
         HeapFree(GetProcessHeap(), 0, pSetupData);
-    }
 
     LogItem(L"END_SECTION", L"InstallWizard");
 }