[SETUP:REACTOS] Adapt the 1st-stage GUI setup to compile with the setuplib.
[reactos.git] / base / setup / reactos / reactos.c
index 416c2f3..13cdd88 100644 (file)
  * COPYRIGHT:   See COPYING in the top level directory
  * PROJECT:     ReactOS GUI first stage setup application
  * FILE:        base/setup/reactos/reactos.c
- * PROGRAMMERS: Eric Kohl
- *              Matthias Kupfer
+ * PROGRAMMERS: Matthias Kupfer
  *              Dmitry Chapyshev (dmitry@reactos.org)
  */
 
-#include <stdarg.h>
-#include <windef.h>
-#include <winbase.h>
-#include <winreg.h>
-#include <wingdi.h>
-#include <winuser.h>
-#include <tchar.h>
-#include <setupapi.h>
-#include <devguid.h>
-#include <wine/unicode.h>
-
+#include "reactos.h"
 #include "resource.h"
 
-/* GLOBALS ******************************************************************/
-
-HFONT hTitleFont;
-
-typedef struct _LANG
-{
-    TCHAR LangId[9];
-    TCHAR LangName[128];
-} LANG, *PLANG;
-
-typedef struct _KBLAYOUT
-{
-    TCHAR LayoutId[9];
-    TCHAR LayoutName[128];
-    TCHAR DllName[128];
-} KBLAYOUT, *PKBLAYOUT;
+#define NDEBUG
+#include <debug.h>
 
+/* GLOBALS ******************************************************************/
 
-// generic entries with simple 1:1 mapping
-typedef struct _GENENTRY
-{
-    TCHAR Id[24];
-    TCHAR Value[128];
-} GENENTRY, *PGENENTRY;
+HANDLE ProcessHeap;
+BOOLEAN IsUnattendedSetup = FALSE;
+SETUPDATA SetupData;
 
-struct
-{
-    // Settings
-    LONG DestDiskNumber; // physical disk
-    LONG DestPartNumber; // partition on disk
-    LONG DestPartSize; // if partition doesn't exist, size of partition
-    LONG FSType; // file system type on partition 
-    LONG MBRInstallType; // install bootloader
-    LONG FormatPart; // type of format the partition
-    LONG SelectedLangId; // selected language (table index)
-    LONG SelectedKBLayout; // selected keyboard layout (table index)
-    TCHAR InstallDir[MAX_PATH]; // installation directory on hdd
-    LONG SelectedComputer; // selected computer type (table index)
-    LONG SelectedDisplay; // selected display type (table index)
-    LONG SelectedKeyboard; // selected keyboard type (table index)
-    BOOLEAN RepairUpdateFlag; // flag for update/repair an installed reactos
-    // txtsetup.sif data
-    LONG DefaultLang; // default language (table index)
-    PLANG pLanguages;
-    LONG LangCount;
-    LONG DefaultKBLayout; // default keyboard layout (table index)
-    PKBLAYOUT pKbLayouts;
-    LONG KbLayoutCount;
-    PGENENTRY pComputers;
-    LONG CompCount;
-    PGENENTRY pDisplays;
-    LONG DispCount;
-    PGENENTRY pKeyboards;
-    LONG KeybCount;
-} SetupData;
-
-typedef struct _IMGINFO
-{
-    HBITMAP hBitmap;
-    INT cxSource;
-    INT cySource;
-} IMGINFO, *PIMGINFO;
 
-TCHAR abort_msg[512], abort_title[64];
-HINSTANCE hInstance;
-BOOL isUnattend;
+/* FUNCTIONS ****************************************************************/
 
 LONG LoadGenentry(HINF hinf,PCTSTR name,PGENENTRY *gen,PINFCONTEXT context);
 
-/* FUNCTIONS ****************************************************************/
-
 static VOID
 CenterWindow(HWND hWnd)
 {
@@ -157,27 +89,17 @@ CreateTitleFont(VOID)
     return hFont;
 }
 
-static VOID
-InitImageInfo(PIMGINFO ImgInfo)
+INT DisplayError(
+    IN HWND hParentWnd OPTIONAL,
+    IN UINT uIDTitle,
+    IN UINT uIDMessage)
 {
-    BITMAP bitmap;
+    WCHAR message[512], caption[64];
 
-    ZeroMemory(ImgInfo, sizeof(*ImgInfo));
+    LoadStringW(SetupData.hInstance, uIDMessage, message, ARRAYSIZE(message));
+    LoadStringW(SetupData.hInstance, uIDTitle, caption, ARRAYSIZE(caption));
 
-    ImgInfo->hBitmap = LoadImage(hInstance,
-                                 MAKEINTRESOURCE(IDB_ROSLOGO),
-                                 IMAGE_BITMAP,
-                                 0,
-                                 0,
-                                 LR_DEFAULTCOLOR);
-
-    if (ImgInfo->hBitmap != NULL)
-    {
-        GetObject(ImgInfo->hBitmap, sizeof(BITMAP), &bitmap);
-
-        ImgInfo->cxSource = bitmap.bmWidth;
-        ImgInfo->cySource = bitmap.bmHeight;
-    }
+    return MessageBoxW(hParentWnd, message, caption, MB_OK | MB_ICONERROR);
 }
 
 static INT_PTR CALLBACK
@@ -186,205 +108,39 @@ StartDlgProc(HWND hwndDlg,
              WPARAM wParam,
              LPARAM lParam)
 {
+    PSETUPDATA pSetupData;
+
+    /* Retrieve pointer to the global setup data */
+    pSetupData = (PSETUPDATA)GetWindowLongPtr(hwndDlg, GWLP_USERDATA);
+
     switch (uMsg)
     {
         case WM_INITDIALOG:
-        {
-            HWND hwndControl;
-            DWORD dwStyle;
-
-            hwndControl = GetParent(hwndDlg);
+            /* Save pointer to the global setup data */
+            pSetupData = (PSETUPDATA)((LPPROPSHEETPAGE)lParam)->lParam;
+            SetWindowLongPtr(hwndDlg, GWLP_USERDATA, (DWORD_PTR)pSetupData);
 
             /* Center the wizard window */
-            CenterWindow (hwndControl);
-
-            dwStyle = GetWindowLongPtr(hwndControl, GWL_STYLE);
-            SetWindowLongPtr(hwndControl, GWL_STYLE, dwStyle & ~WS_SYSMENU);
-        
-            /* Hide and disable the 'Cancel' button at the moment,
-             * we use this button to cancel the setup process
-             * like F3 in usetup
-             */
-            hwndControl = GetDlgItem(GetParent(hwndDlg), IDCANCEL);
-            ShowWindow (hwndControl, SW_HIDE);
-            EnableWindow (hwndControl, FALSE);
-            
+            CenterWindow(GetParent(hwndDlg));
+
             /* Set title font */
             SendDlgItemMessage(hwndDlg,
                                IDC_STARTTITLE,
                                WM_SETFONT,
-                               (WPARAM)hTitleFont,
+                               (WPARAM)pSetupData->hTitleFont,
                                (LPARAM)TRUE);
-        }
-        break;
-
-        case WM_NOTIFY:
-        {
-            LPNMHDR lpnm = (LPNMHDR)lParam;
-
-            switch (lpnm->code)
-            {        
-                case PSN_SETACTIVE:
-                    PropSheet_SetWizButtons(GetParent(hwndDlg), PSWIZB_NEXT);
-                break;
-                default:
-                break;
-            }
-        }
-        break;
-
-        default:
             break;
 
-    }
-
-    return FALSE;
-}
-
-static INT_PTR CALLBACK
-LangSelDlgProc(HWND hwndDlg,
-               UINT uMsg,
-               WPARAM wParam,
-               LPARAM lParam)
-{
-    PIMGINFO pImgInfo;
-    LONG i;
-    LRESULT tindex;
-    HWND hList;
-
-    pImgInfo = (PIMGINFO)GetWindowLongPtr(hwndDlg, DWLP_USER);
-
-    switch (uMsg)
-    {
-        case WM_INITDIALOG:
-        {
-            HWND hwndControl;
-            DWORD dwStyle;
-
-            hwndControl = GetParent(hwndDlg);
-
-            dwStyle = GetWindowLongPtr(hwndControl, GWL_STYLE);
-            SetWindowLongPtr(hwndControl, GWL_STYLE, dwStyle & ~WS_SYSMENU);
-            
-            hwndControl = GetDlgItem(GetParent(hwndDlg), IDCANCEL);
-            ShowWindow (hwndControl, SW_SHOW);
-            EnableWindow (hwndControl, TRUE);
-
-            pImgInfo = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IMGINFO));
-            if (pImgInfo == NULL)
-            {
-                EndDialog(hwndDlg, 0);
-                return FALSE;
-            }
-
-            SetWindowLongPtr(hwndDlg, DWLP_USER, (LONG_PTR)pImgInfo);
-
-            InitImageInfo(pImgInfo);
-
-            /* Set title font */
-            /*SendDlgItemMessage(hwndDlg,
-                                 IDC_STARTTITLE,
-                                 WM_SETFONT,
-                                 (WPARAM)hTitleFont,
-                                 (LPARAM)TRUE);*/
-
-            hList = GetDlgItem(hwndDlg, IDC_LANGUAGES);
-
-            for (i=0; i < SetupData.LangCount; i++)
-            {
-                tindex = SendMessage(hList, CB_ADDSTRING, (WPARAM) 0, (LPARAM) SetupData.pLanguages[i].LangName);
-                SendMessage(hList, CB_SETITEMDATA, tindex, i);
-                if (SetupData.DefaultLang == i)
-                SendMessage(hList, CB_SETCURSEL, (WPARAM) tindex,(LPARAM) 0);
-            }
-
-            hList = GetDlgItem(hwndDlg, IDC_KEYLAYOUT);
-
-            for (i=0; i < SetupData.KbLayoutCount; i++)
-            {
-                tindex = SendMessage(hList, CB_ADDSTRING, (WPARAM) 0, (LPARAM)SetupData.pKbLayouts[i].LayoutName);
-                SendMessage(hList, CB_SETITEMDATA, tindex, i);
-                if (SetupData.DefaultKBLayout == i)
-                SendMessage(hList,CB_SETCURSEL,(WPARAM)tindex,(LPARAM)0);
-            }
-        }
-        break;
-
-        case WM_DRAWITEM:
-        {
-            LPDRAWITEMSTRUCT lpDrawItem;
-            lpDrawItem = (LPDRAWITEMSTRUCT) lParam;
-
-            if (lpDrawItem->CtlID == IDB_ROSLOGO)
-            {
-                HDC hdcMem;
-                LONG left;
-
-                /* position image in centre of dialog */
-                left = (lpDrawItem->rcItem.right - pImgInfo->cxSource) / 2;
-
-                hdcMem = CreateCompatibleDC(lpDrawItem->hDC);
-                if (hdcMem != NULL)
-                {
-                    SelectObject(hdcMem, pImgInfo->hBitmap);
-                    BitBlt(lpDrawItem->hDC,
-                           left,
-                           lpDrawItem->rcItem.top,
-                           lpDrawItem->rcItem.right - lpDrawItem->rcItem.left,
-                           lpDrawItem->rcItem.bottom - lpDrawItem->rcItem.top,
-                           hdcMem,
-                           0,
-                           0,
-                           SRCCOPY);
-                    DeleteDC(hdcMem);
-                }
-            }
-            return TRUE;
-        }
-
         case WM_NOTIFY:
         {
             LPNMHDR lpnm = (LPNMHDR)lParam;
 
             switch (lpnm->code)
-            {        
+            {
                 case PSN_SETACTIVE:
-                    PropSheet_SetWizButtons(GetParent(hwndDlg), PSWIZB_NEXT | PSWIZB_BACK);
+                    PropSheet_SetWizButtons(GetParent(hwndDlg), PSWIZB_NEXT);
                     break;
 
-                case PSN_QUERYCANCEL:
-                    SetWindowLongPtr(hwndDlg,
-                                     DWL_MSGRESULT,
-                                     MessageBox(GetParent(hwndDlg),
-                                             abort_msg,
-                                             abort_title,
-                                             MB_YESNO | MB_ICONQUESTION) != IDYES);
-                    return TRUE;
-
-                case PSN_WIZNEXT: // set the selected data
-                {
-                    hList =GetDlgItem(hwndDlg, IDC_LANGUAGES); 
-                    tindex = SendMessage(hList,CB_GETCURSEL, (WPARAM)0, (LPARAM)0);
-
-                    if (tindex != CB_ERR)
-                    {
-                        WORD LangID;
-                        SetupData.SelectedLangId = SendMessage(hList, CB_GETITEMDATA, (WPARAM) tindex, (LPARAM) 0);
-                        LangID = _tcstol(SetupData.pLanguages[SetupData.SelectedLangId].LangId, NULL, 16);
-                        SetThreadLocale(MAKELCID(LangID, SORT_DEFAULT));
-                        // FIXME: need to reload all resource to force
-                        // the new language setting
-                    }
-
-                    hList = GetDlgItem(hwndDlg, IDC_KEYLAYOUT); 
-                    tindex = SendMessage(hList,CB_GETCURSEL, (WPARAM)0, (LPARAM)0);
-                    if (tindex != CB_ERR)
-                    {
-                        SetupData.SelectedKBLayout = SendMessage(hList, CB_GETITEMDATA, (WPARAM) tindex, (LPARAM) 0);
-                    }
-                    return TRUE;
-                }
-
                 default:
                     break;
             }
@@ -395,6 +151,7 @@ LangSelDlgProc(HWND hwndDlg,
             break;
 
     }
+
     return FALSE;
 }
 
@@ -404,53 +161,50 @@ TypeDlgProc(HWND hwndDlg,
             WPARAM wParam,
             LPARAM lParam)
 {
+    PSETUPDATA pSetupData;
+
+    /* Retrieve pointer to the global setup data */
+    pSetupData = (PSETUPDATA)GetWindowLongPtr(hwndDlg, GWLP_USERDATA);
+
     switch (uMsg)
     {
         case WM_INITDIALOG:
-        {
-            HWND hwndControl;
-            DWORD dwStyle;
-
-            hwndControl = GetParent(hwndDlg);
+            /* Save pointer to the global setup data */
+            pSetupData = (PSETUPDATA)((LPPROPSHEETPAGE)lParam)->lParam;
+            SetWindowLongPtr(hwndDlg, GWLP_USERDATA, (DWORD_PTR)pSetupData);
 
-            dwStyle = GetWindowLongPtr(hwndControl, GWL_STYLE);
-            SetWindowLongPtr(hwndControl, GWL_STYLE, dwStyle & ~WS_SYSMENU);
-        
+            /* Check the 'install' radio button */
             CheckDlgButton(hwndDlg, IDC_INSTALL, BST_CHECKED);
-            
-            /* Set title font */
-            /*SendDlgItemMessage(hwndDlg,
-                                 IDC_STARTTITLE,
-                                 WM_SETFONT,
-                                 (WPARAM)hTitleFont,
-                                 (LPARAM)TRUE);*/
-        }
-        break;
+
+            /* Disable the 'update' radio button and text */
+            EnableWindow(GetDlgItem(hwndDlg, IDC_UPDATE), FALSE);
+            EnableWindow(GetDlgItem(hwndDlg, IDC_UPDATETEXT), FALSE);
+            break;
 
         case WM_NOTIFY:
         {
             LPNMHDR lpnm = (LPNMHDR)lParam;
 
             switch (lpnm->code)
-            {        
+            {
                 case PSN_SETACTIVE:
                     PropSheet_SetWizButtons(GetParent(hwndDlg), PSWIZB_NEXT | PSWIZB_BACK);
-                break;
+                    break;
 
                 case PSN_QUERYCANCEL:
                     SetWindowLongPtr(hwndDlg,
-                                     DWL_MSGRESULT,
+                                     DWLP_MSGRESULT,
                                      MessageBox(GetParent(hwndDlg),
-                                             abort_msg,
-                                             abort_title,
-                                             MB_YESNO | MB_ICONQUESTION) != IDYES);
+                                                pSetupData->szAbortMessage,
+                                                pSetupData->szAbortTitle,
+                                                MB_YESNO | MB_ICONQUESTION) != IDYES);
                     return TRUE;
 
                 case PSN_WIZNEXT: // set the selected data
-                    SetupData.RepairUpdateFlag = !(SendMessage(GetDlgItem(hwndDlg, IDC_INSTALL),
-                                                               BM_GETCHECK,
-                                                               (WPARAM) 0,
-                                                               (LPARAM) 0) == BST_CHECKED);
+                    pSetupData->RepairUpdateFlag = !(SendMessage(GetDlgItem(hwndDlg, IDC_INSTALL),
+                                                                 BM_GETCHECK,
+                                                                 (WPARAM) 0,
+                                                                 (LPARAM) 0) == BST_CHECKED);
                     return TRUE;
 
                 default:
@@ -472,74 +226,65 @@ DeviceDlgProc(HWND hwndDlg,
               WPARAM wParam,
               LPARAM lParam)
 {
+    PSETUPDATA pSetupData;
     LONG i;
     LRESULT tindex;
     HWND hList;
 
+    /* Retrieve pointer to the global setup data */
+    pSetupData = (PSETUPDATA)GetWindowLongPtr(hwndDlg, GWLP_USERDATA);
+
     switch (uMsg)
     {
         case WM_INITDIALOG:
-        {
-            HWND hwndControl;
-            DWORD dwStyle;
-
-            hwndControl = GetParent(hwndDlg);
-
-            dwStyle = GetWindowLongPtr(hwndControl, GWL_STYLE);
-            SetWindowLongPtr(hwndControl, GWL_STYLE, dwStyle & ~WS_SYSMENU);
-        
-            /* Set title font */
-            /*SendDlgItemMessage(hwndDlg,
-                                 IDC_STARTTITLE,
-                                 WM_SETFONT,
-                                 (WPARAM)hTitleFont,
-                                 (LPARAM)TRUE);*/
+            /* Save pointer to the global setup data */
+            pSetupData = (PSETUPDATA)((LPPROPSHEETPAGE)lParam)->lParam;
+            SetWindowLongPtr(hwndDlg, GWLP_USERDATA, (DWORD_PTR)pSetupData);
 
             hList = GetDlgItem(hwndDlg, IDC_COMPUTER);
 
-            for (i=0; i < SetupData.CompCount; i++)
+            for (i=0; i < pSetupData->CompCount; i++)
             {
-                tindex = SendMessage(hList, CB_ADDSTRING, (WPARAM) 0, (LPARAM) SetupData.pComputers[i].Value);
+                tindex = SendMessage(hList, CB_ADDSTRING, (WPARAM) 0, (LPARAM) pSetupData->pComputers[i].Value);
                 SendMessage(hList, CB_SETITEMDATA, tindex, i);
             }
             SendMessage(hList, CB_SETCURSEL, 0, 0); // set first as default
 
             hList = GetDlgItem(hwndDlg, IDC_DISPLAY);
 
-            for (i=0; i < SetupData.DispCount; i++)
+            for (i=0; i < pSetupData->DispCount; i++)
             {
-                tindex = SendMessage(hList, CB_ADDSTRING, (WPARAM) 0, (LPARAM) SetupData.pDisplays[i].Value);
+                tindex = SendMessage(hList, CB_ADDSTRING, (WPARAM) 0, (LPARAM) pSetupData->pDisplays[i].Value);
                 SendMessage(hList, CB_SETITEMDATA, tindex, i);
             }
             SendMessage(hList, CB_SETCURSEL, 0, 0); // set first as default
 
             hList = GetDlgItem(hwndDlg, IDC_KEYBOARD);
 
-            for (i=0; i < SetupData.KeybCount; i++)
+            for (i=0; i < pSetupData->KeybCount; i++)
             {
-                tindex = SendMessage(hList,CB_ADDSTRING,(WPARAM)0,(LPARAM)SetupData.pKeyboards[i].Value);
+                tindex = SendMessage(hList,CB_ADDSTRING,(WPARAM)0,(LPARAM)pSetupData->pKeyboards[i].Value);
                 SendMessage(hList,CB_SETITEMDATA,tindex,i);
             }
             SendMessage(hList,CB_SETCURSEL,0,0); // set first as default
-        }
-        break;
+            break;
 
         case WM_NOTIFY:
         {
             LPNMHDR lpnm = (LPNMHDR)lParam;
 
             switch (lpnm->code)
-            {        
+            {
                 case PSN_SETACTIVE:
                     PropSheet_SetWizButtons(GetParent(hwndDlg), PSWIZB_NEXT | PSWIZB_BACK);
                     break;
 
                 case PSN_QUERYCANCEL:
                     SetWindowLongPtr(hwndDlg,
-                                     DWL_MSGRESULT,
+                                     DWLP_MSGRESULT,
                                      MessageBox(GetParent(hwndDlg),
-                                             abort_msg,
-                                             abort_title,
+                                                pSetupData->szAbortMessage,
+                                                pSetupData->szAbortTitle,
                                              MB_YESNO | MB_ICONQUESTION) != IDYES);
                     return TRUE;
 
@@ -550,10 +295,10 @@ DeviceDlgProc(HWND hwndDlg,
                     tindex = SendMessage(hList, CB_GETCURSEL, (WPARAM) 0, (LPARAM) 0);
                     if (tindex != CB_ERR)
                     {
-                        SetupData.SelectedComputer = SendMessage(hList,
-                                                                 CB_GETITEMDATA,
-                                                                 (WPARAM) tindex,
-                                                                 (LPARAM) 0);
+                        pSetupData->SelectedComputer = SendMessage(hList,
+                                                                   CB_GETITEMDATA,
+                                                                   (WPARAM) tindex,
+                                                                   (LPARAM) 0);
                     }
 
                     hList = GetDlgItem(hwndDlg, IDC_DISPLAY);
@@ -561,10 +306,10 @@ DeviceDlgProc(HWND hwndDlg,
                     tindex = SendMessage(hList, CB_GETCURSEL, (WPARAM) 0, (LPARAM) 0);
                     if (tindex != CB_ERR)
                     {
-                        SetupData.SelectedDisplay = SendMessage(hList,
-                                                                CB_GETITEMDATA,
-                                                                (WPARAM) tindex,
-                                                                (LPARAM) 0);
+                        pSetupData->SelectedDisplay = SendMessage(hList,
+                                                                  CB_GETITEMDATA,
+                                                                  (WPARAM) tindex,
+                                                                  (LPARAM) 0);
                     }
 
                     hList =GetDlgItem(hwndDlg, IDC_KEYBOARD);
@@ -572,10 +317,10 @@ DeviceDlgProc(HWND hwndDlg,
                     tindex = SendMessage(hList, CB_GETCURSEL, (WPARAM) 0, (LPARAM) 0);
                     if (tindex != CB_ERR)
                     {
-                        SetupData.SelectedKeyboard = SendMessage(hList,
-                                                                 CB_GETITEMDATA,
-                                                                 (WPARAM) tindex,
-                                                                 (LPARAM) 0);
+                        pSetupData->SelectedKeyboard = SendMessage(hList,
+                                                                   CB_GETITEMDATA,
+                                                                   (WPARAM) tindex,
+                                                                   (LPARAM) 0);
                     }
                     return TRUE;
                 }
@@ -594,245 +339,41 @@ DeviceDlgProc(HWND hwndDlg,
 }
 
 static INT_PTR CALLBACK
-MoreOptDlgProc(HWND hwndDlg,
+SummaryDlgProc(HWND hwndDlg,
                UINT uMsg,
                WPARAM wParam,
                LPARAM lParam)
 {
-    switch (uMsg)
-    {
-        case WM_INITDIALOG:
-        {
-            CheckDlgButton(hwndDlg, IDC_INSTFREELDR, BST_CHECKED);
-            SendMessage(GetDlgItem(hwndDlg, IDC_PATH),
-                        WM_SETTEXT,
-                        (WPARAM) 0,
-                        (LPARAM) SetupData.InstallDir);
-        }
-        break;
+    PSETUPDATA pSetupData;
 
-        case WM_COMMAND:
-        {
-            switch(LOWORD(wParam))
-            {
-                case IDOK:
-                {
-                    SendMessage(GetDlgItem(hwndDlg, IDC_PATH),
-                                WM_GETTEXT,
-                                (WPARAM) sizeof(SetupData.InstallDir) / sizeof(TCHAR),
-                                (LPARAM) SetupData.InstallDir);
-                    
-                    EndDialog(hwndDlg, IDOK);
-                    return TRUE;
-                }
-
-                case IDCANCEL:
-                {
-                    EndDialog(hwndDlg, IDCANCEL);
-                    return TRUE;
-                }
-            }
-        }
-    }
-
-    return FALSE;
-}
+    /* Retrieve pointer to the global setup data */
+    pSetupData = (PSETUPDATA)GetWindowLongPtr(hwndDlg, GWLP_USERDATA);
 
-static INT_PTR CALLBACK
-PartitionDlgProc(HWND hwndDlg,
-                 UINT uMsg,
-                 WPARAM wParam,
-                 LPARAM lParam)
-{
     switch (uMsg)
     {
         case WM_INITDIALOG:
+            /* Save pointer to the global setup data */
+            pSetupData = (PSETUPDATA)((LPPROPSHEETPAGE)lParam)->lParam;
+            SetWindowLongPtr(hwndDlg, GWLP_USERDATA, (DWORD_PTR)pSetupData);
             break;
-        case WM_COMMAND:
-        {
-            switch(LOWORD(wParam))
-            {
-                case IDOK:
-                    EndDialog(hwndDlg, IDOK);
-                    return TRUE;
-                case IDCANCEL:
-                    EndDialog(hwndDlg, IDCANCEL);
-                    return TRUE;
-            }
-        }
-    }
-    return FALSE;
-}
-
-static INT_PTR CALLBACK
-DriveDlgProc(HWND hwndDlg,
-             UINT uMsg,
-             WPARAM wParam,
-             LPARAM lParam)
-{
-#if 1
-    HDEVINFO h;
-    HWND hList;
-    SP_DEVINFO_DATA DevInfoData;
-    DWORD i;
-#endif
-    switch (uMsg)
-    {
-        case WM_INITDIALOG:
-        {
-            HWND hwndControl;
-            DWORD dwStyle;
-
-            hwndControl = GetParent(hwndDlg);
-
-            dwStyle = GetWindowLongPtr(hwndControl, GWL_STYLE);
-            SetWindowLongPtr(hwndControl, GWL_STYLE, dwStyle & ~WS_SYSMENU);
-        
-            /* Set title font */
-            /*SendDlgItemMessage(hwndDlg,
-                                 IDC_STARTTITLE,
-                                 WM_SETFONT,
-                                 (WPARAM)hTitleFont,
-                                 (LPARAM)TRUE);*/
-#if 1
-            h = SetupDiGetClassDevs(&GUID_DEVCLASS_DISKDRIVE, NULL, NULL, DIGCF_PRESENT);
-            if (h != INVALID_HANDLE_VALUE)
-            {
-                hList =GetDlgItem(hwndDlg, IDC_PARTITION); 
-                DevInfoData.cbSize = sizeof(SP_DEVINFO_DATA);
-                for (i=0; SetupDiEnumDeviceInfo(h, i, &DevInfoData); i++)
-                {
-                    DWORD DataT;
-                    LPTSTR buffer = NULL;
-                    DWORD buffersize = 0;
-
-                    while (!SetupDiGetDeviceRegistryProperty(h,
-                                                             &DevInfoData,
-                                                             SPDRP_DEVICEDESC,
-                                                             &DataT,
-                                                             (PBYTE)buffer,
-                                                             buffersize,
-                                                             &buffersize))
-                    {
-                        if (GetLastError() == ERROR_INSUFFICIENT_BUFFER)
-                        {
-                            if (buffer) LocalFree(buffer);
-                            buffer = LocalAlloc(LPTR, buffersize * 2);
-                        }
-                        else
-                            break;
-                    }
-                    if (buffer)
-                    {
-                        SendMessage(hList, LB_ADDSTRING, (WPARAM) 0, (LPARAM) buffer);
-                        LocalFree(buffer);
-                    }
-                }
-                SetupDiDestroyDeviceInfoList(h);
-            }
-#endif
-        }
-        break;
-
-        case WM_COMMAND:
-        {
-            switch(LOWORD(wParam))
-            {
-                case IDC_PARTMOREOPTS:
-                    DialogBox(hInstance,
-                              MAKEINTRESOURCE(IDD_BOOTOPTIONS),
-                              hwndDlg,
-                              (DLGPROC) MoreOptDlgProc);
-                    break;
-                case IDC_PARTCREATE:
-                    DialogBox(hInstance,
-                              MAKEINTRESOURCE(IDD_PARTITION),
-                              hwndDlg,
-                              (DLGPROC) PartitionDlgProc);
-                    break;
-                case IDC_PARTDELETE:
-                    break;
-            }
-            break;
-        }
-
-        case WM_NOTIFY:
-        {
-            LPNMHDR lpnm = (LPNMHDR)lParam;
-
-            switch (lpnm->code)
-            {        
-                case PSN_SETACTIVE:
-                    PropSheet_SetWizButtons(GetParent(hwndDlg), PSWIZB_NEXT | PSWIZB_BACK);
-                    break;
-
-                case PSN_QUERYCANCEL:
-                    SetWindowLongPtr(hwndDlg,
-                                     DWL_MSGRESULT,
-                                     MessageBox(GetParent(hwndDlg),
-                                             abort_msg,
-                                             abort_title,
-                                             MB_YESNO | MB_ICONQUESTION) != IDYES);
-                    return TRUE;
-
-                default:
-                    break;
-            }
-        }
-        break;
-
-        default:
-            break;
-
-    }
-
-    return FALSE;
-}
-
-static INT_PTR CALLBACK
-SummaryDlgProc(HWND hwndDlg,
-               UINT uMsg,
-               WPARAM wParam,
-               LPARAM lParam)
-{
-    switch (uMsg)
-    {
-        case WM_INITDIALOG:
-        {
-            HWND hwndControl;
-            DWORD dwStyle;
-
-            hwndControl = GetParent(hwndDlg);
-
-            dwStyle = GetWindowLongPtr(hwndControl, GWL_STYLE);
-            SetWindowLongPtr(hwndControl, GWL_STYLE, dwStyle & ~WS_SYSMENU);
-        
-            /* Set title font */
-            /*SendDlgItemMessage(hwndDlg,
-                                 IDC_STARTTITLE,
-                                 WM_SETFONT,
-                                 (WPARAM)hTitleFont,
-                                 (LPARAM)TRUE);*/
-        }
-        break;
 
         case WM_NOTIFY:
         {
             LPNMHDR lpnm = (LPNMHDR)lParam;
 
             switch (lpnm->code)
-            {        
+            {
                 case PSN_SETACTIVE: 
                     PropSheet_SetWizButtons(GetParent(hwndDlg), PSWIZB_NEXT | PSWIZB_BACK);
                     break;
 
                 case PSN_QUERYCANCEL:
                     SetWindowLongPtr(hwndDlg,
-                                     DWL_MSGRESULT,
+                                     DWLP_MSGRESULT,
                                      MessageBox(GetParent(hwndDlg),
-                                             abort_msg,
-                                             abort_title,
-                                             MB_YESNO | MB_ICONQUESTION) != IDYES);
+                                                pSetupData->szAbortMessage,
+                                                pSetupData->szAbortTitle,
+                                                MB_YESNO | MB_ICONQUESTION) != IDYES);
                     return TRUE;
                 default:
                     break;
@@ -853,45 +394,37 @@ ProcessDlgProc(HWND hwndDlg,
                WPARAM wParam,
                LPARAM lParam)
 {
+    PSETUPDATA pSetupData;
+
+    /* Retrieve pointer to the global setup data */
+    pSetupData = (PSETUPDATA)GetWindowLongPtr(hwndDlg, GWLP_USERDATA);
+
     switch (uMsg)
     {
         case WM_INITDIALOG:
-        {
-            HWND hwndControl;
-            DWORD dwStyle;
-
-            hwndControl = GetParent(hwndDlg);
-
-            dwStyle = GetWindowLongPtr(hwndControl, GWL_STYLE);
-            SetWindowLongPtr(hwndControl, GWL_STYLE, dwStyle & ~WS_SYSMENU);
-        
-            /* Set title font */
-            /*SendDlgItemMessage(hwndDlg,
-                                 IDC_STARTTITLE,
-                                 WM_SETFONT,
-                                 (WPARAM)hTitleFont,
-                                 (LPARAM)TRUE);*/
-        }
-        break;
+            /* Save pointer to the global setup data */
+            pSetupData = (PSETUPDATA)((LPPROPSHEETPAGE)lParam)->lParam;
+            SetWindowLongPtr(hwndDlg, GWLP_USERDATA, (DWORD_PTR)pSetupData);
+            break;
 
         case WM_NOTIFY:
         {
             LPNMHDR lpnm = (LPNMHDR)lParam;
 
             switch (lpnm->code)
-            {        
-                case PSN_SETACTIVE: 
+            {
+                case PSN_SETACTIVE:
                     PropSheet_SetWizButtons(GetParent(hwndDlg), PSWIZB_NEXT);
                    // disable all buttons during installation process
                    // PropSheet_SetWizButtons(GetParent(hwndDlg), 0 );
                    break;
                 case PSN_QUERYCANCEL:
                     SetWindowLongPtr(hwndDlg,
-                                     DWL_MSGRESULT,
+                                     DWLP_MSGRESULT,
                                      MessageBox(GetParent(hwndDlg),
-                                             abort_msg,
-                                             abort_title,
-                                             MB_YESNO | MB_ICONQUESTION) != IDYES);
+                                                pSetupData->szAbortMessage,
+                                                pSetupData->szAbortTitle,
+                                                MB_YESNO | MB_ICONQUESTION) != IDYES);
                     return TRUE;
                 default:
                    break;
@@ -913,21 +446,17 @@ RestartDlgProc(HWND hwndDlg,
                WPARAM wParam,
                LPARAM lParam)
 {
+    PSETUPDATA pSetupData;
+
+    /* Retrieve pointer to the global setup data */
+    pSetupData = (PSETUPDATA)GetWindowLongPtr(hwndDlg, GWLP_USERDATA);
+
     switch (uMsg)
     {
         case WM_INITDIALOG:
-        {
-            HWND hwndControl;
-            DWORD dwStyle;
-
-            hwndControl = GetParent(hwndDlg);
-
-            dwStyle = GetWindowLongPtr(hwndControl, GWL_STYLE);
-            SetWindowLongPtr(hwndControl, GWL_STYLE, dwStyle & ~WS_SYSMENU);
-        
-            hwndControl = GetDlgItem(GetParent(hwndDlg), IDCANCEL);
-            ShowWindow(hwndControl, SW_HIDE);
-            EnableWindow(hwndControl, FALSE);
+            /* Save pointer to the global setup data */
+            pSetupData = (PSETUPDATA)((LPPROPSHEETPAGE)lParam)->lParam;
+            SetWindowLongPtr(hwndDlg, GWLP_USERDATA, (DWORD_PTR)pSetupData);
 
             /* Set title font */
             /*SendDlgItemMessage(hwndDlg,
@@ -935,8 +464,7 @@ RestartDlgProc(HWND hwndDlg,
                                  WM_SETFONT,
                                  (WPARAM)hTitleFont,
                                  (LPARAM)TRUE);*/
-        }
-        break;
+            break;
 
         case WM_TIMER:
         {
@@ -965,15 +493,13 @@ RestartDlgProc(HWND hwndDlg,
             LPNMHDR lpnm = (LPNMHDR)lParam;
 
             switch (lpnm->code)
-            {        
+            {
                 case PSN_SETACTIVE: // Only "Finish" for closing the App
-                {
                     PropSheet_SetWizButtons(GetParent(hwndDlg), PSWIZB_FINISH);
                     SendDlgItemMessage(hwndDlg, IDC_RESTART_PROGRESS, PBM_SETRANGE, 0, MAKELPARAM(0, 300));
                     SendDlgItemMessage(hwndDlg, IDC_RESTART_PROGRESS, PBM_SETPOS, 0, 0);
                     SetTimer(hwndDlg, 1, 50, NULL);
-                }
-                break;
+                    break;
 
                 default:
                     break;
@@ -989,133 +515,149 @@ RestartDlgProc(HWND hwndDlg,
     return FALSE;
 }
 
-void LoadSetupData()
+BOOL LoadSetupData(
+    PSETUPDATA pSetupData)
 {
-    WCHAR szPath[MAX_PATH];
-    TCHAR tmp[10];
-    WCHAR *ch;
-    HINF hTxtsetupSif;
+    BOOL ret = TRUE;
     INFCONTEXT InfContext;
+    TCHAR tmp[10];
     //TCHAR szValue[MAX_PATH];
     DWORD LineLength;
     LONG Count;
 
-    GetModuleFileNameW(NULL,szPath,MAX_PATH);
-    ch = strrchrW(szPath,L'\\');
-    if (ch != NULL)
-        *ch = L'\0';
-
-    wcscat(szPath, L"\\txtsetup.sif");
-    hTxtsetupSif = SetupOpenInfFileW(szPath, NULL, INF_STYLE_OLDNT, NULL);
-    if (hTxtsetupSif != INVALID_HANDLE_VALUE)
+    // get language list
+    pSetupData->LangCount = SetupGetLineCount(pSetupData->SetupInf, _T("Language"));
+    if (pSetupData->LangCount > 0)
     {
-        // get language list
-        SetupData.LangCount = SetupGetLineCount(hTxtsetupSif, _T("Language"));
-        if (SetupData.LangCount > 0)
+        pSetupData->pLanguages = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(LANG) * pSetupData->LangCount);
+        if (pSetupData->pLanguages == NULL)
         {
-            SetupData.pLanguages = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(LANG) * SetupData.LangCount);
-            if (SetupData.pLanguages != NULL)
+            ret = FALSE;
+            goto done;
+        }
+
+        Count = 0;
+        if (SetupFindFirstLine(pSetupData->SetupInf, _T("Language"), NULL, &InfContext))
+        {
+            do
             {
-                Count = 0;
-                if (SetupFindFirstLine(hTxtsetupSif, _T("Language"), NULL, &InfContext))
-                {
-                    do
-                    {
-                        SetupGetStringField(&InfContext,
-                                            0,
-                                            SetupData.pLanguages[Count].LangId,
-                                            sizeof(SetupData.pLanguages[Count].LangId) / sizeof(TCHAR),
-                                            &LineLength);
-
-                        SetupGetStringField(&InfContext,
-                                            1,
-                                            SetupData.pLanguages[Count].LangName,
-                                            sizeof(SetupData.pLanguages[Count].LangName) / sizeof(TCHAR),
-                                            &LineLength);
-                        ++Count;
-                    }
-                    while (SetupFindNextLine(&InfContext, &InfContext) && Count < SetupData.LangCount);
-                }
+                SetupGetStringField(&InfContext,
+                                    0,
+                                    pSetupData->pLanguages[Count].LangId,
+                                    sizeof(pSetupData->pLanguages[Count].LangId) / sizeof(TCHAR),
+                                    &LineLength);
+
+                SetupGetStringField(&InfContext,
+                                    1,
+                                    pSetupData->pLanguages[Count].LangName,
+                                    sizeof(pSetupData->pLanguages[Count].LangName) / sizeof(TCHAR),
+                                    &LineLength);
+                ++Count;
             }
+            while (SetupFindNextLine(&InfContext, &InfContext) && Count < pSetupData->LangCount);
+        }
+    }
+
+    // get keyboard layout list
+    pSetupData->KbLayoutCount = SetupGetLineCount(pSetupData->SetupInf, _T("KeyboardLayout"));
+    if (pSetupData->KbLayoutCount > 0)
+    {
+        pSetupData->pKbLayouts = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(KBLAYOUT) * pSetupData->KbLayoutCount);
+        if (pSetupData->pKbLayouts == NULL)
+        {
+            ret = FALSE;
+            goto done;
         }
 
-        // get keyboard layout list
-        SetupData.KbLayoutCount = SetupGetLineCount(hTxtsetupSif, _T("KeyboardLayout"));
-        if (SetupData.KbLayoutCount > 0)
+        Count = 0;
+        if (SetupFindFirstLine(pSetupData->SetupInf, _T("KeyboardLayout"), NULL, &InfContext))
         {
-            SetupData.pKbLayouts = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(KBLAYOUT) * SetupData.KbLayoutCount);
-            if (SetupData.pKbLayouts != NULL)
+            do
             {
-                Count = 0;
-                if (SetupFindFirstLine(hTxtsetupSif, _T("KeyboardLayout"), NULL, &InfContext))
-                {
-                    do
-                    {
-                        SetupGetStringField(&InfContext,
-                                            0,
-                                            SetupData.pKbLayouts[Count].LayoutId,
-                                            sizeof(SetupData.pKbLayouts[Count].LayoutId) / sizeof(TCHAR),
-                                            &LineLength);
-
-                        SetupGetStringField(&InfContext,
-                                            1,
-                                            SetupData.pKbLayouts[Count].LayoutName,
-                                            sizeof(SetupData.pKbLayouts[Count].LayoutName) / sizeof(TCHAR),
-                                            &LineLength);
-                        ++Count;
-                    }
-                    while (SetupFindNextLine(&InfContext, &InfContext) && Count < SetupData.KbLayoutCount);
-                }
+                SetupGetStringField(&InfContext,
+                                    0,
+                                    pSetupData->pKbLayouts[Count].LayoutId,
+                                    sizeof(pSetupData->pKbLayouts[Count].LayoutId) / sizeof(TCHAR),
+                                    &LineLength);
+
+                SetupGetStringField(&InfContext,
+                                    1,
+                                    pSetupData->pKbLayouts[Count].LayoutName,
+                                    sizeof(pSetupData->pKbLayouts[Count].LayoutName) / sizeof(TCHAR),
+                                    &LineLength);
+                ++Count;
             }
+            while (SetupFindNextLine(&InfContext, &InfContext) && Count < pSetupData->KbLayoutCount);
         }
+    }
 
-        // get default for keyboard and language
-        SetupData.DefaultKBLayout = -1;
-        SetupData.DefaultLang = -1;
+    // get default for keyboard and language
+    pSetupData->DefaultKBLayout = -1;
+    pSetupData->DefaultLang = -1;
 
-        // TODO: get defaults from underlaying running system
-        if (SetupFindFirstLine(hTxtsetupSif, _T("NLS"), _T("DefaultLayout"), &InfContext))
+    // TODO: get defaults from underlaying running system
+    if (SetupFindFirstLine(pSetupData->SetupInf, _T("NLS"), _T("DefaultLayout"), &InfContext))
+    {
+        SetupGetStringField(&InfContext, 1, tmp, sizeof(tmp) / sizeof(TCHAR), &LineLength);
+        for (Count = 0; Count < pSetupData->KbLayoutCount; Count++)
         {
-            SetupGetStringField(&InfContext, 1, tmp, sizeof(tmp) / sizeof(TCHAR), &LineLength);
-            for (Count = 0; Count < SetupData.KbLayoutCount; Count++)
-                if (_tcscmp(tmp, SetupData.pKbLayouts[Count].LayoutId) == 0)
-                {
-                    SetupData.DefaultKBLayout = Count;
-                    break;
-                }
+            if (_tcscmp(tmp, pSetupData->pKbLayouts[Count].LayoutId) == 0)
+            {
+                pSetupData->DefaultKBLayout = Count;
+                break;
+            }
         }
+    }
 
-        if (SetupFindFirstLine(hTxtsetupSif, _T("NLS"), _T("DefaultLanguage"), &InfContext))
+    if (SetupFindFirstLine(pSetupData->SetupInf, _T("NLS"), _T("DefaultLanguage"), &InfContext))
+    {
+        SetupGetStringField(&InfContext, 1, tmp, sizeof(tmp) / sizeof(TCHAR), &LineLength);
+        for (Count = 0; Count < pSetupData->LangCount; Count++)
         {
-            SetupGetStringField(&InfContext, 1, tmp, sizeof(tmp) / sizeof(TCHAR), &LineLength);
-            for (Count = 0; Count < SetupData.LangCount; Count++)
-                if (_tcscmp(tmp, SetupData.pLanguages[Count].LangId) == 0)
-                {
-                    SetupData.DefaultLang = Count;
-                    break;
-                }
+            if (_tcscmp(tmp, pSetupData->pLanguages[Count].LangId) == 0)
+            {
+                pSetupData->DefaultLang = Count;
+                break;
+            }
         }
+    }
+
+    // get computers list
+    pSetupData->CompCount = LoadGenentry(pSetupData->SetupInf,_T("Computer"),&pSetupData->pComputers,&InfContext);
 
-        // get computers list
-        SetupData.CompCount = LoadGenentry(hTxtsetupSif,_T("Computer"),&SetupData.pComputers,&InfContext);
+    // get display list
+    pSetupData->DispCount = LoadGenentry(pSetupData->SetupInf,_T("Display"),&pSetupData->pDisplays,&InfContext);
 
-        // get display list
-        SetupData.DispCount = LoadGenentry(hTxtsetupSif,_T("Display"),&SetupData.pDisplays,&InfContext);
+    // get keyboard list
+    pSetupData->KeybCount = LoadGenentry(pSetupData->SetupInf, _T("Keyboard"),&pSetupData->pKeyboards,&InfContext);
 
-        // get keyboard list
-        SetupData.KeybCount = LoadGenentry(hTxtsetupSif, _T("Keyboard"),&SetupData.pKeyboards,&InfContext);
+    // get install directory
+    if (SetupFindFirstLine(pSetupData->SetupInf, _T("SetupData"), _T("DefaultPath"), &InfContext))
+    {
+        SetupGetStringField(&InfContext,
+                            1,
+                            pSetupData->USetupData.InstallationDirectory,
+                            sizeof(pSetupData->USetupData.InstallationDirectory) / sizeof(TCHAR),
+                            &LineLength);
+    }
 
-        // get install directory
-        if (SetupFindFirstLine(hTxtsetupSif, _T("SetupData"), _T("DefaultPath"), &InfContext))
+done:
+    if (ret == FALSE)
+    {
+        if (pSetupData->pKbLayouts != NULL)
         {
-            SetupGetStringField(&InfContext,
-                                1,
-                                SetupData.InstallDir,
-                                sizeof(SetupData.InstallDir) / sizeof(TCHAR),
-                                &LineLength);
+            HeapFree(GetProcessHeap(), 0, pSetupData->pKbLayouts);
+            pSetupData->pKbLayouts = NULL;
+        }
+
+        if (pSetupData->pLanguages != NULL)
+        {
+            HeapFree(GetProcessHeap(), 0, pSetupData->pLanguages);
+            pSetupData->pLanguages = NULL;
         }
-        SetupCloseInfFile(hTxtsetupSif);
     }
+
+    return ret;
 }
 
 LONG LoadGenentry(HINF hinf,PCTSTR name,PGENENTRY *gen,PINFCONTEXT context)
@@ -1150,48 +692,87 @@ LONG LoadGenentry(HINF hinf,PCTSTR name,PGENENTRY *gen,PINFCONTEXT context)
                 while (SetupFindNextLine(context, context) && Count < TotalCount);
             }
         }
-       else return 0;
+        else return 0;
     }
     return TotalCount;
 }
 
-BOOL isUnattendSetup()
+/*
+ * Attempts to convert a pure NT file path into a corresponding Win32 path.
+ * Adapted from GetInstallSourceWin32() in dll/win32/syssetup/wizard.c
+ */
+BOOL
+ConvertNtPathToWin32Path(
+    OUT PWSTR pwszPath,
+    IN DWORD cchPathMax,
+    IN PCWSTR pwszNTPath)
 {
-    WCHAR szPath[MAX_PATH];
-    WCHAR *ch;
-    HINF hUnattendedInf;
-    INFCONTEXT InfContext;
-    TCHAR szValue[MAX_PATH];
-    DWORD LineLength;
-    //HKEY hKey;
-    BOOL result = 0;
+    WCHAR wszDrives[512];
+    WCHAR wszNTPath[512]; // MAX_PATH ?
+    DWORD cchDrives;
+    PWCHAR pwszDrive;
 
-    GetModuleFileNameW(NULL, szPath, MAX_PATH);
-    ch = strrchrW(szPath, L'\\');
-    if (ch != NULL)
-        *ch = L'\0';
+    *pwszPath = UNICODE_NULL;
 
-    wcscat(szPath, L"\\unattend.inf");
-    hUnattendedInf = SetupOpenInfFileW(szPath, NULL, INF_STYLE_OLDNT, NULL);
+    cchDrives = GetLogicalDriveStringsW(_countof(wszDrives) - 1, wszDrives);
+    if (cchDrives == 0 || cchDrives >= _countof(wszDrives))
+    {
+        /* Buffer too small or failure */
+        DPRINT1("GetLogicalDriveStringsW failed\n");
+        return FALSE;
+    }
 
-    if (hUnattendedInf != INVALID_HANDLE_VALUE)
+    for (pwszDrive = wszDrives; *pwszDrive; pwszDrive += wcslen(pwszDrive) + 1)
     {
-        if (SetupFindFirstLine(hUnattendedInf, _T("Unattend"), _T("UnattendSetupEnabled"),&InfContext))
+        /* 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
+
+        DPRINT1("Testing '%S' --> '%S'\n", pwszDrive, wszNTPath);
+
+        /* Check whether the NT path corresponds to the NT installation source path */
+        if (!_wcsnicmp(wszNTPath, pwszNTPath, wcslen(wszNTPath)))
         {
-            if (SetupGetStringField(&InfContext,
-                                    1,
-                                    szValue,
-                                    sizeof(szValue) / sizeof(TCHAR),
-                                    &LineLength) && (_tcsicmp(szValue, _T("yes")) == 0))
-            {
-                result = 1; // unattendSetup enabled
-                // read values and store in SetupData
-            }
+            /* Found it! */
+            wsprintf(pwszPath, L"%s%s", // cchPathMax
+                     pwszDrive, pwszNTPath + wcslen(wszNTPath));
+            DPRINT1("ConvertNtPathToWin32Path: %S\n", pwszPath);
+            return TRUE;
         }
-            SetupCloseInfFile(hUnattendedInf);
     }
 
-    return result;
+    return FALSE;
+}
+
+/* Used to enable and disable the shutdown privilege */
+/* static */ BOOL
+EnablePrivilege(LPCWSTR lpszPrivilegeName, BOOL bEnablePrivilege)
+{
+    BOOL   Success;
+    HANDLE hToken;
+    TOKEN_PRIVILEGES tp;
+
+    Success = OpenProcessToken(GetCurrentProcess(),
+                               TOKEN_ADJUST_PRIVILEGES,
+                               &hToken);
+    if (!Success) return Success;
+
+    Success = LookupPrivilegeValueW(NULL,
+                                    lpszPrivilegeName,
+                                    &tp.Privileges[0].Luid);
+    if (!Success) goto Quit;
+
+    tp.PrivilegeCount = 1;
+    tp.Privileges[0].Attributes = (bEnablePrivilege ? SE_PRIVILEGE_ENABLED : 0);
+
+    Success = AdjustTokenPrivileges(hToken, FALSE, &tp, 0, NULL, NULL);
+
+Quit:
+    CloseHandle(hToken);
+    return Success;
 }
 
 int WINAPI
@@ -1200,47 +781,86 @@ _tWinMain(HINSTANCE hInst,
           LPTSTR lpszCmdLine,
           int nCmdShow)
 {
+    NTSTATUS Status;
+    ULONG Error;
     PROPSHEETHEADER psh;
     HPROPSHEETPAGE ahpsp[8];
     PROPSHEETPAGE psp = {0};
     UINT nPages = 0;
-    hInstance = hInst;
-    isUnattend = isUnattendSetup();
 
-    LoadString(hInst,IDS_ABORTSETUP, abort_msg, sizeof(abort_msg)/sizeof(TCHAR));
-    LoadString(hInst,IDS_ABORTSETUP2, abort_title,sizeof(abort_title)/sizeof(TCHAR));
-    if (!isUnattend)
+    ProcessHeap = GetProcessHeap();
+
+    /* Initialize global unicode strings */
+    RtlInitUnicodeString(&SetupData.USetupData.SourcePath, NULL);
+    RtlInitUnicodeString(&SetupData.USetupData.SourceRootPath, NULL);
+    RtlInitUnicodeString(&SetupData.USetupData.SourceRootDir, NULL);
+    // RtlInitUnicodeString(&InstallPath, NULL);
+    RtlInitUnicodeString(&SetupData.USetupData.DestinationPath, NULL);
+    RtlInitUnicodeString(&SetupData.USetupData.DestinationArcPath, NULL);
+    RtlInitUnicodeString(&SetupData.USetupData.DestinationRootPath, NULL);
+    RtlInitUnicodeString(&SetupData.USetupData.SystemRootPath, NULL);
+
+    /* Get the source path and source root path */
+    //
+    // NOTE: Sometimes the source path may not be in SystemRoot !!
+    // (and this is the case when using the 1st-stage GUI setup!)
+    //
+    Status = GetSourcePaths(&SetupData.USetupData.SourcePath,
+                            &SetupData.USetupData.SourceRootPath,
+                            &SetupData.USetupData.SourceRootDir);
+    if (!NT_SUCCESS(Status))
     {
+        DPRINT1("GetSourcePaths() failed (Status 0x%08lx)", Status);
+        // MUIDisplayError(ERROR_NO_SOURCE_DRIVE, Ir, POPUP_WAIT_ENTER);
+        MessageBoxW(NULL, L"GetSourcePaths failed!", L"Error", MB_ICONERROR);
+        goto Quit;
+    }
+    DPRINT1("SourcePath: '%wZ'\n", &SetupData.USetupData.SourcePath);
+    DPRINT1("SourceRootPath: '%wZ'\n", &SetupData.USetupData.SourceRootPath);
+    DPRINT1("SourceRootDir: '%wZ'\n", &SetupData.USetupData.SourceRootDir);
 
-        LoadSetupData();
+    /* Load 'txtsetup.sif' from the installation media */
+    Error = LoadSetupInf(&SetupData.SetupInf, &SetupData.USetupData);
+    if (Error != ERROR_SUCCESS)
+    {
+        // MUIDisplayError(Error, Ir, POPUP_WAIT_ENTER);
+        DisplayError(NULL, IDS_CAPTION, IDS_NO_TXTSETUP_SIF);
+        goto Quit;
+    }
+    /* Load extra setup data (HW lists etc...) */
+    if (!LoadSetupData(&SetupData))
+        goto Quit;
 
+    SetupData.hInstance = hInst;
+
+    CheckUnattendedSetup(&SetupData.USetupData);
+    SetupData.bUnattend = IsUnattendedSetup;
+
+    LoadStringW(hInst, IDS_ABORTSETUP, SetupData.szAbortMessage, ARRAYSIZE(SetupData.szAbortMessage));
+    LoadStringW(hInst, IDS_ABORTSETUP2, SetupData.szAbortTitle, ARRAYSIZE(SetupData.szAbortTitle));
+
+    /* Create title font */
+    SetupData.hTitleFont = CreateTitleFont();
+
+    if (!SetupData.bUnattend)
+    {
         /* Create the Start page, until setup is working */
+        // NOTE: What does "until setup is working" mean??
         psp.dwSize = sizeof(PROPSHEETPAGE);
         psp.dwFlags = PSP_DEFAULT | PSP_HIDEHEADER;
         psp.hInstance = hInst;
-        psp.lParam = 0;
+        psp.lParam = (LPARAM)&SetupData;
         psp.pfnDlgProc = StartDlgProc;
         psp.pszTemplate = MAKEINTRESOURCE(IDD_STARTPAGE);
         ahpsp[nPages++] = CreatePropertySheetPage(&psp);
 
-        /* Create language selection page */
-        psp.dwSize = sizeof(PROPSHEETPAGE);
-        psp.dwFlags = PSP_DEFAULT | PSP_USEHEADERTITLE | PSP_USEHEADERSUBTITLE;
-        psp.pszHeaderTitle = MAKEINTRESOURCE(IDS_LANGTITLE);
-        psp.pszHeaderSubTitle = MAKEINTRESOURCE(IDS_LANGSUBTITLE);
-        psp.hInstance = hInst;
-        psp.lParam = 0;
-        psp.pfnDlgProc = LangSelDlgProc;
-        psp.pszTemplate = MAKEINTRESOURCE(IDD_LANGSELPAGE);
-        ahpsp[nPages++] = CreatePropertySheetPage(&psp);
-
         /* Create install type selection page */
         psp.dwSize = sizeof(PROPSHEETPAGE);
         psp.dwFlags = PSP_DEFAULT | PSP_USEHEADERTITLE | PSP_USEHEADERSUBTITLE;
         psp.pszHeaderTitle = MAKEINTRESOURCE(IDS_TYPETITLE);
         psp.pszHeaderSubTitle = MAKEINTRESOURCE(IDS_TYPESUBTITLE);
         psp.hInstance = hInst;
-        psp.lParam = 0;
+        psp.lParam = (LPARAM)&SetupData;
         psp.pfnDlgProc = TypeDlgProc;
         psp.pszTemplate = MAKEINTRESOURCE(IDD_TYPEPAGE);
         ahpsp[nPages++] = CreatePropertySheetPage(&psp);
@@ -1251,7 +871,7 @@ _tWinMain(HINSTANCE hInst,
         psp.pszHeaderTitle = MAKEINTRESOURCE(IDS_DEVICETITLE);
         psp.pszHeaderSubTitle = MAKEINTRESOURCE(IDS_DEVICESUBTITLE);
         psp.hInstance = hInst;
-        psp.lParam = 0;
+        psp.lParam = (LPARAM)&SetupData;
         psp.pfnDlgProc = DeviceDlgProc;
         psp.pszTemplate = MAKEINTRESOURCE(IDD_DEVICEPAGE);
         ahpsp[nPages++] = CreatePropertySheetPage(&psp);
@@ -1262,7 +882,7 @@ _tWinMain(HINSTANCE hInst,
         psp.pszHeaderTitle = MAKEINTRESOURCE(IDS_DRIVETITLE);
         psp.pszHeaderSubTitle = MAKEINTRESOURCE(IDS_DRIVESUBTITLE);
         psp.hInstance = hInst;
-        psp.lParam = 0;
+        psp.lParam = (LPARAM)&SetupData;
         psp.pfnDlgProc = DriveDlgProc;
         psp.pszTemplate = MAKEINTRESOURCE(IDD_DRIVEPAGE);
         ahpsp[nPages++] = CreatePropertySheetPage(&psp);
@@ -1273,7 +893,7 @@ _tWinMain(HINSTANCE hInst,
         psp.pszHeaderTitle = MAKEINTRESOURCE(IDS_SUMMARYTITLE);
         psp.pszHeaderSubTitle = MAKEINTRESOURCE(IDS_SUMMARYSUBTITLE);
         psp.hInstance = hInst;
-        psp.lParam = 0;
+        psp.lParam = (LPARAM)&SetupData;
         psp.pfnDlgProc = SummaryDlgProc;
         psp.pszTemplate = MAKEINTRESOURCE(IDD_SUMMARYPAGE);
         ahpsp[nPages++] = CreatePropertySheetPage(&psp);
@@ -1285,18 +905,16 @@ _tWinMain(HINSTANCE hInst,
     psp.pszHeaderTitle = MAKEINTRESOURCE(IDS_PROCESSTITLE);
     psp.pszHeaderSubTitle = MAKEINTRESOURCE(IDS_PROCESSSUBTITLE);
     psp.hInstance = hInst;
-    psp.lParam = 0;
+    psp.lParam = (LPARAM)&SetupData;
     psp.pfnDlgProc = ProcessDlgProc;
     psp.pszTemplate = MAKEINTRESOURCE(IDD_PROCESSPAGE);
     ahpsp[nPages++] = CreatePropertySheetPage(&psp);
 
     /* Create finish to reboot page */
     psp.dwSize = sizeof(PROPSHEETPAGE);
-    psp.dwFlags = PSP_DEFAULT | PSP_USEHEADERTITLE | PSP_USEHEADERSUBTITLE;
-    psp.pszHeaderTitle = MAKEINTRESOURCE(IDS_RESTARTTITLE);
-    psp.pszHeaderSubTitle = MAKEINTRESOURCE(IDS_RESTARTSUBTITLE);
+    psp.dwFlags = PSP_DEFAULT | PSP_HIDEHEADER;
     psp.hInstance = hInst;
-    psp.lParam = 0;
+    psp.lParam = (LPARAM)&SetupData;
     psp.pfnDlgProc = RestartDlgProc;
     psp.pszTemplate = MAKEINTRESOURCE(IDD_RESTARTPAGE);
     ahpsp[nPages++] = CreatePropertySheetPage(&psp);
@@ -1312,13 +930,21 @@ _tWinMain(HINSTANCE hInst,
     psh.pszbmWatermark = MAKEINTRESOURCE(IDB_WATERMARK);
     psh.pszbmHeader = MAKEINTRESOURCE(IDB_HEADER);
 
-    /* Create title font */
-    hTitleFont = CreateTitleFont();
-
     /* Display the wizard */
     PropertySheet(&psh);
 
-    DeleteObject(hTitleFont);
+    if (SetupData.hTitleFont)
+        DeleteObject(SetupData.hTitleFont);
+
+    SetupCloseInfFile(SetupData.SetupInf);
+
+Quit:
+
+#if 0 // NOTE: Disabled for testing purposes only!
+    EnablePrivilege(SE_SHUTDOWN_NAME, TRUE);
+    ExitWindowsEx(EWX_REBOOT, 0);
+    EnablePrivilege(SE_SHUTDOWN_NAME, FALSE);
+#endif
 
     return 0;
 }