[REACTOS] Diverse UI improvements.

- Improve UI usage and wizard transitions (Work In Progress).
- Add interfacing code that display installation status.
- When the user attempts to cancel the installation during file copying,
  pause the file copying, and restart it if the user changes it mind and
  wants to continue the installation. Otherwise file copying is properly
  halted.
This commit is contained in:
Hermès Bélusca-Maïto 2018-01-07 01:35:48 +01:00
parent 86f31289ef
commit dd2fe4e126
No known key found for this signature in database
GPG key ID: 3B2539C65E7B93D0
5 changed files with 551 additions and 75 deletions

View file

@ -48,33 +48,37 @@ MoreOptDlgProc(HWND hwndDlg,
PSETUPDATA pSetupData;
/* Retrieve pointer to the global setup data */
pSetupData = (PSETUPDATA)GetWindowLongPtr(hwndDlg, GWLP_USERDATA);
pSetupData = (PSETUPDATA)GetWindowLongPtrW(hwndDlg, GWLP_USERDATA);
switch (uMsg)
{
case WM_INITDIALOG:
{
/* Save pointer to the global setup data */
pSetupData = (PSETUPDATA)((LPPROPSHEETPAGE)lParam)->lParam;
SetWindowLongPtr(hwndDlg, GWLP_USERDATA, (DWORD_PTR)pSetupData);
pSetupData = (PSETUPDATA)lParam;
SetWindowLongPtrW(hwndDlg, GWLP_USERDATA, (DWORD_PTR)pSetupData);
CheckDlgButton(hwndDlg, IDC_INSTFREELDR, BST_CHECKED);
SendMessage(GetDlgItem(hwndDlg, IDC_PATH),
WM_SETTEXT,
(WPARAM)0,
(LPARAM)pSetupData->USetupData.InstallationDirectory);
SendMessageW(GetDlgItem(hwndDlg, IDC_PATH),
WM_SETTEXT,
(WPARAM)0,
(LPARAM)pSetupData->USetupData.InstallationDirectory);
break;
}
case WM_COMMAND:
switch(LOWORD(wParam))
{
case IDOK:
SendMessage(GetDlgItem(hwndDlg, IDC_PATH),
WM_GETTEXT,
(WPARAM)ARRAYSIZE(pSetupData->USetupData.InstallationDirectory),
(LPARAM)pSetupData->USetupData.InstallationDirectory);
{
SendMessageW(GetDlgItem(hwndDlg, IDC_PATH),
WM_GETTEXT,
(WPARAM)ARRAYSIZE(pSetupData->USetupData.InstallationDirectory),
(LPARAM)pSetupData->USetupData.InstallationDirectory);
EndDialog(hwndDlg, IDOK);
return TRUE;
}
case IDCANCEL:
EndDialog(hwndDlg, IDCANCEL);
@ -164,7 +168,7 @@ DriveDlgProc(
#endif
/* Retrieve pointer to the global setup data */
pSetupData = (PSETUPDATA)GetWindowLongPtr(hwndDlg, GWLP_USERDATA);
pSetupData = (PSETUPDATA)GetWindowLongPtrW(hwndDlg, GWLP_USERDATA);
switch (uMsg)
{
@ -172,7 +176,7 @@ DriveDlgProc(
{
/* Save pointer to the global setup data */
pSetupData = (PSETUPDATA)((LPPROPSHEETPAGE)lParam)->lParam;
SetWindowLongPtr(hwndDlg, GWLP_USERDATA, (DWORD_PTR)pSetupData);
SetWindowLongPtrW(hwndDlg, GWLP_USERDATA, (DWORD_PTR)pSetupData);
CreateListViewColumns(pSetupData->hInstance,
GetDlgItem(hwndDlg, IDC_PARTITION),
@ -211,7 +215,7 @@ DriveDlgProc(
}
if (buffer)
{
SendMessage(hList, LB_ADDSTRING, (WPARAM) 0, (LPARAM) buffer);
SendMessageW(hList, LB_ADDSTRING, (WPARAM) 0, (LPARAM) buffer);
LocalFree(buffer);
}
}
@ -251,17 +255,24 @@ DriveDlgProc(
switch (lpnm->code)
{
case PSN_SETACTIVE:
PropSheet_SetWizButtons(GetParent(hwndDlg), PSWIZB_NEXT | PSWIZB_BACK);
PropSheet_SetWizButtons(GetParent(hwndDlg), PSWIZB_BACK | PSWIZB_NEXT);
break;
case PSN_QUERYCANCEL:
SetWindowLongPtr(hwndDlg,
DWLP_MSGRESULT,
MessageBox(GetParent(hwndDlg),
pSetupData->szAbortMessage,
pSetupData->szAbortTitle,
MB_YESNO | MB_ICONQUESTION) != IDYES);
{
if (MessageBoxW(GetParent(hwndDlg),
pSetupData->szAbortMessage,
pSetupData->szAbortTitle,
MB_YESNO | MB_ICONQUESTION) == IDYES)
{
/* Go to the Terminate page */
PropSheet_SetCurSelByID(GetParent(hwndDlg), IDD_RESTARTPAGE);
}
/* Do not close the wizard too soon */
SetWindowLongPtrW(hwndDlg, DWLP_MSGRESULT, TRUE);
return TRUE;
}
default:
break;

View file

@ -25,6 +25,10 @@
*/
#include "reactos.h"
#define NTOS_MODE_USER
#include <ndk/obfuncs.h>
#include "resource.h"
#define NDEBUG
@ -115,6 +119,7 @@ StartDlgProc(
switch (uMsg)
{
case WM_INITDIALOG:
{
/* Save pointer to the global setup data */
pSetupData = (PSETUPDATA)((LPPROPSHEETPAGE)lParam)->lParam;
SetWindowLongPtrW(hwndDlg, GWLP_USERDATA, (DWORD_PTR)pSetupData);
@ -129,6 +134,7 @@ StartDlgProc(
(WPARAM)pSetupData->hTitleFont,
(LPARAM)TRUE);
break;
}
case WM_NOTIFY:
{
@ -203,17 +209,24 @@ TypeDlgProc(
switch (lpnm->code)
{
case PSN_SETACTIVE:
PropSheet_SetWizButtons(GetParent(hwndDlg), PSWIZB_NEXT | PSWIZB_BACK);
PropSheet_SetWizButtons(GetParent(hwndDlg), PSWIZB_BACK | PSWIZB_NEXT);
break;
case PSN_QUERYCANCEL:
SetWindowLongPtrW(hwndDlg,
DWLP_MSGRESULT,
MessageBoxW(GetParent(hwndDlg),
pSetupData->szAbortMessage,
pSetupData->szAbortTitle,
MB_YESNO | MB_ICONQUESTION) != IDYES);
{
if (MessageBoxW(GetParent(hwndDlg),
pSetupData->szAbortMessage,
pSetupData->szAbortTitle,
MB_YESNO | MB_ICONQUESTION) == IDYES)
{
/* Go to the Terminate page */
PropSheet_SetCurSelByID(GetParent(hwndDlg), IDD_RESTARTPAGE);
}
/* Do not close the wizard too soon */
SetWindowLongPtrW(hwndDlg, DWLP_MSGRESULT, TRUE);
return TRUE;
}
case PSN_WIZNEXT: /* Set the selected data */
{
@ -501,17 +514,24 @@ UpgradeRepairDlgProc(
switch (lpnm->code)
{
case PSN_SETACTIVE:
PropSheet_SetWizButtons(GetParent(hwndDlg), PSWIZB_NEXT | PSWIZB_BACK);
PropSheet_SetWizButtons(GetParent(hwndDlg), PSWIZB_BACK | PSWIZB_NEXT);
break;
case PSN_QUERYCANCEL:
SetWindowLongPtrW(hwndDlg,
DWLP_MSGRESULT,
MessageBoxW(GetParent(hwndDlg),
pSetupData->szAbortMessage,
pSetupData->szAbortTitle,
MB_YESNO | MB_ICONQUESTION) != IDYES);
{
if (MessageBoxW(GetParent(hwndDlg),
pSetupData->szAbortMessage,
pSetupData->szAbortTitle,
MB_YESNO | MB_ICONQUESTION) == IDYES)
{
/* Go to the Terminate page */
PropSheet_SetCurSelByID(GetParent(hwndDlg), IDD_RESTARTPAGE);
}
/* Do not close the wizard too soon */
SetWindowLongPtrW(hwndDlg, DWLP_MSGRESULT, TRUE);
return TRUE;
}
case PSN_WIZNEXT: /* Set the selected data */
pSetupData->RepairUpdateFlag =
@ -576,17 +596,24 @@ DeviceDlgProc(
switch (lpnm->code)
{
case PSN_SETACTIVE:
PropSheet_SetWizButtons(GetParent(hwndDlg), PSWIZB_NEXT | PSWIZB_BACK);
PropSheet_SetWizButtons(GetParent(hwndDlg), PSWIZB_BACK | PSWIZB_NEXT);
break;
case PSN_QUERYCANCEL:
SetWindowLongPtrW(hwndDlg,
DWLP_MSGRESULT,
MessageBoxW(GetParent(hwndDlg),
pSetupData->szAbortMessage,
pSetupData->szAbortTitle,
MB_YESNO | MB_ICONQUESTION) != IDYES);
{
if (MessageBoxW(GetParent(hwndDlg),
pSetupData->szAbortMessage,
pSetupData->szAbortTitle,
MB_YESNO | MB_ICONQUESTION) == IDYES)
{
/* Go to the Terminate page */
PropSheet_SetCurSelByID(GetParent(hwndDlg), IDD_RESTARTPAGE);
}
/* Do not close the wizard too soon */
SetWindowLongPtrW(hwndDlg, DWLP_MSGRESULT, TRUE);
return TRUE;
}
case PSN_WIZNEXT: /* Set the selected data */
{
@ -642,17 +669,24 @@ SummaryDlgProc(
switch (lpnm->code)
{
case PSN_SETACTIVE:
PropSheet_SetWizButtons(GetParent(hwndDlg), PSWIZB_NEXT | PSWIZB_BACK);
PropSheet_SetWizButtons(GetParent(hwndDlg), PSWIZB_BACK | PSWIZB_NEXT);
break;
case PSN_QUERYCANCEL:
SetWindowLongPtrW(hwndDlg,
DWLP_MSGRESULT,
MessageBoxW(GetParent(hwndDlg),
pSetupData->szAbortMessage,
pSetupData->szAbortTitle,
MB_YESNO | MB_ICONQUESTION) != IDYES);
{
if (MessageBoxW(GetParent(hwndDlg),
pSetupData->szAbortMessage,
pSetupData->szAbortTitle,
MB_YESNO | MB_ICONQUESTION) == IDYES)
{
/* Go to the Terminate page */
PropSheet_SetCurSelByID(GetParent(hwndDlg), IDD_RESTARTPAGE);
}
/* Do not close the wizard too soon */
SetWindowLongPtrW(hwndDlg, DWLP_MSGRESULT, TRUE);
return TRUE;
}
default:
break;
@ -667,6 +701,221 @@ SummaryDlgProc(
return FALSE;
}
typedef struct _COPYCONTEXT
{
PSETUPDATA pSetupData;
HWND hWndItem;
HWND hWndProgress;
ULONG TotalOperations;
ULONG CompletedOperations;
} COPYCONTEXT, *PCOPYCONTEXT;
static UINT
CALLBACK
FileCopyCallback(PVOID Context,
UINT Notification,
UINT_PTR Param1,
UINT_PTR Param2)
{
PCOPYCONTEXT CopyContext = (PCOPYCONTEXT)Context;
PFILEPATHS_W FilePathInfo;
PCWSTR SrcFileName, DstFileName;
WCHAR Status[1024];
WaitForSingleObject(CopyContext->pSetupData->hHaltInstallEvent, INFINITE);
if (CopyContext->pSetupData->bStopInstall)
return FILEOP_ABORT; // Stop committing files
switch (Notification)
{
case SPFILENOTIFY_STARTSUBQUEUE:
{
CopyContext->TotalOperations = (ULONG)Param2;
CopyContext->CompletedOperations = 0;
SendMessageW(CopyContext->hWndProgress,
PBM_SETRANGE, 0,
MAKELPARAM(0, CopyContext->TotalOperations));
SendMessageW(CopyContext->hWndProgress,
PBM_SETSTEP, 1, 0);
break;
}
case SPFILENOTIFY_STARTDELETE:
case SPFILENOTIFY_STARTRENAME:
case SPFILENOTIFY_STARTCOPY:
{
FilePathInfo = (PFILEPATHS_W)Param1;
if (Notification == SPFILENOTIFY_STARTDELETE)
{
/* Display delete message */
ASSERT(Param2 == FILEOP_DELETE);
DstFileName = wcsrchr(FilePathInfo->Target, L'\\');
if (DstFileName) ++DstFileName;
else DstFileName = FilePathInfo->Target;
// STRING_DELETING
StringCchPrintfW(Status, ARRAYSIZE(Status), L"Deleting %s", DstFileName);
SetWindowTextW(CopyContext->hWndItem, Status);
}
else if (Notification == SPFILENOTIFY_STARTRENAME)
{
/* Display move/rename message */
ASSERT(Param2 == FILEOP_RENAME);
SrcFileName = wcsrchr(FilePathInfo->Source, L'\\');
if (SrcFileName) ++SrcFileName;
else SrcFileName = FilePathInfo->Source;
DstFileName = wcsrchr(FilePathInfo->Target, L'\\');
if (DstFileName) ++DstFileName;
else DstFileName = FilePathInfo->Target;
// STRING_MOVING or STRING_RENAMING
if (!wcsicmp(SrcFileName, DstFileName))
StringCchPrintfW(Status, ARRAYSIZE(Status), L"Moving %s to %s", SrcFileName, DstFileName);
else
StringCchPrintfW(Status, ARRAYSIZE(Status), L"Renaming %s to %s", SrcFileName, DstFileName);
SetWindowTextW(CopyContext->hWndItem, Status);
}
else if (Notification == SPFILENOTIFY_STARTCOPY)
{
/* Display copy message */
ASSERT(Param2 == FILEOP_COPY);
DstFileName = wcsrchr(FilePathInfo->Target, L'\\');
if (DstFileName) ++DstFileName;
else DstFileName = FilePathInfo->Target;
// STRING_COPYING
StringCchPrintfW(Status, ARRAYSIZE(Status), L"Copying %s", DstFileName);
SetWindowTextW(CopyContext->hWndItem, Status);
}
break;
}
case SPFILENOTIFY_ENDDELETE:
case SPFILENOTIFY_ENDRENAME:
case SPFILENOTIFY_ENDCOPY:
{
CopyContext->CompletedOperations++;
/* SYSREG checkpoint */
if (CopyContext->TotalOperations >> 1 == CopyContext->CompletedOperations)
DPRINT1("CHECKPOINT:HALF_COPIED\n");
SendMessageW(CopyContext->hWndProgress, PBM_STEPIT, 0, 0);
break;
}
}
return FILEOP_DOIT;
}
static DWORD
WINAPI
PrepareAndDoCopyThread(
IN LPVOID Param)
{
PSETUPDATA pSetupData;
HWND hwndDlg = (HWND)Param;
HWND hWndProgress;
LONG_PTR dwStyle;
// ERROR_NUMBER ErrorNumber;
BOOLEAN Success;
COPYCONTEXT CopyContext;
/* Retrieve pointer to the global setup data */
pSetupData = (PSETUPDATA)GetWindowLongPtrW(hwndDlg, GWLP_USERDATA);
/* Set status text */
SetDlgItemTextW(hwndDlg, IDC_ACTIVITY, L"Preparing the list of files to be copied, please wait...");
SetDlgItemTextW(hwndDlg, IDC_ITEM, L"");
/* Get the progress handle */
hWndProgress = GetDlgItem(hwndDlg, IDC_PROCESSPROGRESS);
/* Set progress marquee style */
dwStyle = GetWindowLongPtrW(hWndProgress, GWL_STYLE);
SetWindowLongPtrW(hWndProgress, GWL_STYLE, dwStyle | PBS_MARQUEE);
/* Start it up */
SendMessageW(hWndProgress, PBM_SETMARQUEE, TRUE, 0);
/* Prepare the list of files */
/* ErrorNumber = */ Success = PrepareFileCopy(&pSetupData->USetupData, NULL);
if (/*ErrorNumber != ERROR_SUCCESS*/ !Success)
{
/* Display an error only if an unexpected failure happened, and not because the user cancelled the installation */
if (!pSetupData->bStopInstall)
MessageBoxW(GetParent(hwndDlg), L"Failed to prepare the list of files!", L"Error", MB_ICONERROR);
/* Stop it */
SendMessageW(hWndProgress, PBM_SETMARQUEE, FALSE, 0);
/* Restore progress style */
SetWindowLongPtrW(hWndProgress, GWL_STYLE, dwStyle);
/*
* If we failed due to an unexpected error, keep on the copy page to view the current state,
* but enable the "Next" button to allow the user to continue to the terminate page.
* Otherwise we have been cancelled by the user, who has already switched to the Terminate page.
*/
if (!pSetupData->bStopInstall)
PropSheet_SetWizButtons(GetParent(hwndDlg), PSWIZB_NEXT);
return 1;
}
/* Stop it */
SendMessageW(hWndProgress, PBM_SETMARQUEE, FALSE, 0);
/* Restore progress style */
SetWindowLongPtrW(hWndProgress, GWL_STYLE, dwStyle);
/* Set status text */
SetDlgItemTextW(hwndDlg, IDC_ACTIVITY, L"Copying the files...");
/* Create context for the copy process */
CopyContext.pSetupData = pSetupData;
CopyContext.hWndItem = GetDlgItem(hwndDlg, IDC_ITEM);
CopyContext.hWndProgress = hWndProgress;
CopyContext.TotalOperations = 0;
CopyContext.CompletedOperations = 0;
/* Do the file copying - The callback handles whether or not we should stop file copying */
if (!DoFileCopy(&pSetupData->USetupData, FileCopyCallback, &CopyContext))
{
/* Display an error only if an unexpected failure happened, and not because the user cancelled the installation */
if (!pSetupData->bStopInstall)
MessageBoxW(GetParent(hwndDlg), L"Failed to copy the files!", L"Error", MB_ICONERROR);
/*
* If we failed due to an unexpected error, keep on the copy page to view the current state,
* but enable the "Next" button to allow the user to continue to the terminate page.
* Otherwise we have been cancelled by the user, who has already switched to the Terminate page.
*/
if (!pSetupData->bStopInstall)
PropSheet_SetWizButtons(GetParent(hwndDlg), PSWIZB_NEXT);
return 1;
}
/* Set status text */
SetDlgItemTextW(hwndDlg, IDC_ACTIVITY, L"Finalizing the installation...");
SetDlgItemTextW(hwndDlg, IDC_ITEM, L"");
/* Create the $winnt$.inf file */
InstallSetupInfFile(&pSetupData->USetupData);
/* We are done! Switch to the Terminate page */
PropSheet_SetCurSelByID(GetParent(hwndDlg), IDD_RESTARTPAGE);
return 0;
}
static INT_PTR CALLBACK
ProcessDlgProc(
IN HWND hwndDlg,
@ -682,10 +931,31 @@ ProcessDlgProc(
switch (uMsg)
{
case WM_INITDIALOG:
{
NTSTATUS Status;
/****/
// FIXME: This is my disk encoding!
DISKENTRY DiskEntry;
PARTENTRY PartEntry;
DiskEntry.DiskNumber = 1;
DiskEntry.BiosDiskNumber = 1;
PartEntry.PartitionNumber = 4;
/****/
/* Save pointer to the global setup data */
pSetupData = (PSETUPDATA)((LPPROPSHEETPAGE)lParam)->lParam;
SetWindowLongPtrW(hwndDlg, GWLP_USERDATA, (DWORD_PTR)pSetupData);
/* Reset status text */
SetDlgItemTextW(hwndDlg, IDC_ACTIVITY, L"");
SetDlgItemTextW(hwndDlg, IDC_ITEM, L"");
Status = InitDestinationPaths(&pSetupData->USetupData, NULL /*InstallDir*/, &DiskEntry, &PartEntry);
// TODO: Check Status
UNREFERENCED_PARAMETER(Status);
break;
}
case WM_NOTIFY:
{
@ -694,21 +964,79 @@ ProcessDlgProc(
switch (lpnm->code)
{
case PSN_SETACTIVE:
PropSheet_SetWizButtons(GetParent(hwndDlg), PSWIZB_NEXT);
// disable all buttons during installation process
// PropSheet_SetWizButtons(GetParent(hwndDlg), 0 );
break;
{
/* Create the file-copy halt (manual-reset) event */
pSetupData->hHaltInstallEvent = CreateEventW(NULL, TRUE, TRUE, NULL);
if (!pSetupData->hHaltInstallEvent)
break;
pSetupData->bStopInstall = FALSE;
/* Start the prepare-and-copy files thread */
pSetupData->hInstallThread =
CreateThread(NULL, 0,
PrepareAndDoCopyThread,
(PVOID)hwndDlg,
CREATE_SUSPENDED,
NULL);
if (!pSetupData->hInstallThread)
{
CloseHandle(pSetupData->hHaltInstallEvent);
pSetupData->hHaltInstallEvent = NULL;
MessageBoxW(GetParent(hwndDlg), L"Cannot create the prepare-and-copy files thread!", L"Error", MB_ICONERROR);
break;
}
/* Disable all buttons during installation process - buttons will be reenabled by the installation thread */
PropSheet_SetWizButtons(GetParent(hwndDlg), 0);
/* Resume the installation thread */
ResumeThread(pSetupData->hInstallThread);
break;
}
case PSN_QUERYCANCEL:
SetWindowLongPtrW(hwndDlg,
DWLP_MSGRESULT,
MessageBoxW(GetParent(hwndDlg),
pSetupData->szAbortMessage,
pSetupData->szAbortTitle,
MB_YESNO | MB_ICONQUESTION) != IDYES);
{
/* Halt the on-going file copy */
ResetEvent(pSetupData->hHaltInstallEvent);
if (MessageBoxW(GetParent(hwndDlg),
pSetupData->szAbortMessage,
pSetupData->szAbortTitle,
MB_YESNO | MB_ICONQUESTION) == IDYES)
{
/* Stop the file copy thread */
pSetupData->bStopInstall = TRUE;
SetEvent(pSetupData->hHaltInstallEvent);
#if 0
/* Wait for any pending installation */
WaitForSingleObject(pSetupData->hInstallThread, INFINITE);
CloseHandle(pSetupData->hInstallThread);
pSetupData->hInstallThread = NULL;
CloseHandle(pSetupData->hHaltInstallEvent);
pSetupData->hHaltInstallEvent = NULL;
#endif
// TODO: Unwind installation?!
/* Go to the Terminate page */
PropSheet_SetCurSelByID(GetParent(hwndDlg), IDD_RESTARTPAGE);
}
else
{
/* We don't stop installation, resume file copy */
SetEvent(pSetupData->hHaltInstallEvent);
}
/* Do not close the wizard too soon */
SetWindowLongPtrW(hwndDlg, DWLP_MSGRESULT, TRUE);
return TRUE;
}
default:
break;
break;
}
}
break;
@ -874,13 +1202,17 @@ ConvertNtPathToWin32Path(
IN DWORD cchPathMax,
IN PCWSTR pwszNTPath)
{
WCHAR wszDrives[512];
WCHAR wszNTPath[512]; // MAX_PATH ?
BOOL FoundDrive = FALSE, RetryOnce = FALSE;
DWORD cchDrives;
PWCHAR pwszDrive;
PCWSTR pwszRemaining = NULL;
WCHAR wszDrives[512];
WCHAR wszNTPath[MAX_PATH];
WCHAR TargetPath[MAX_PATH] = L"";
*pwszPath = UNICODE_NULL;
/* Retrieve the mounted drives (available drive letters) */
cchDrives = GetLogicalDriveStringsW(_countof(wszDrives) - 1, wszDrives);
if (cchDrives == 0 || cchDrives >= _countof(wszDrives))
{
@ -889,6 +1221,10 @@ ConvertNtPathToWin32Path(
return FALSE;
}
Retry: // We go back there once if RetryOnce == TRUE
/* Enumerate the mounted drives */
for (pwszDrive = wszDrives; *pwszDrive; pwszDrive += wcslen(pwszDrive) + 1)
{
/* Retrieve the NT path corresponding to the current Win32 DOS path */
@ -896,21 +1232,110 @@ ConvertNtPathToWin32Path(
QueryDosDeviceW(pwszDrive, wszNTPath, _countof(wszNTPath));
pwszDrive[2] = L'\\'; // Restore the backslash
wcscat(wszNTPath, L"\\"); // Concat a backslash
DPRINT("Testing '%S' --> '%S'\n", pwszDrive, wszNTPath);
DPRINT1("Testing '%S' --> '%S'\n", pwszDrive, wszNTPath);
/* Check whether the NT path corresponds to the NT installation source path */
/* Check whether the queried NT path prefixes the user-provided NT path */
if (!_wcsnicmp(wszNTPath, pwszNTPath, wcslen(wszNTPath)))
{
/* Found it! */
wsprintf(pwszPath, L"%s%s", // cchPathMax
pwszDrive, pwszNTPath + wcslen(wszNTPath));
DPRINT1("ConvertNtPathToWin32Path: %S\n", pwszPath);
return TRUE;
FoundDrive = TRUE;
if (!RetryOnce && pwszNTPath != TargetPath)
pwszRemaining = pwszNTPath + wcslen(wszNTPath);
break;
}
}
if (FoundDrive)
{
pwszDrive[2] = UNICODE_NULL; // Remove the backslash
StringCchPrintfW(pwszPath, cchPathMax,
L"%s%s",
pwszDrive,
pwszRemaining);
DPRINT1("ConvertNtPathToWin32Path: %S\n", pwszPath);
return TRUE;
}
/*
* We failed, perhaps because the beginning of the NT path used a symlink.
* Try to see whether this is the case by attempting to resolve it.
* If the symlink resolution gives nothing, or we already failed once,
* there is no hope in converting the path to Win32.
* Otherwise, symlink resolution succeeds but we need to recheck again
* the drives list.
*/
/*
* In theory we would have to parse each element in the NT path and going
* until finding a symlink object (otherwise we would fail straight away).
* However here we can use guessing instead, since we know which kind of
* NT paths we are likely to manipulate: \Device\HarddiskX\PartitionY\ and
* the like (including \Device\HarddiskVolumeX\) and the other ones that
* are supported in setuplib\utils\arcname.c .
*
* But actually, all the supported names in arcname.c are real devices,
* and only \Device\HarddiskX\PartitionY\ may refer to a symlink, so we
* just check for it.
*/
if (!RetryOnce && !FoundDrive)
{
ULONG DiskNumber, PartitionNumber;
INT Length;
NTSTATUS Status;
OBJECT_ATTRIBUTES ObjectAttributes;
HANDLE LinkHandle;
UNICODE_STRING SymLink, Target;
if (swscanf(pwszNTPath, L"\\Device\\Harddisk%lu\\Partition%lu%n",
&DiskNumber, &PartitionNumber, &Length) != 2)
{
/* Definitively not a recognized path, bail out */
return FALSE;
}
/* Check whether \Device\HarddiskX\PartitionY is a symlink */
RtlInitEmptyUnicodeString(&SymLink, (PWCHAR)pwszNTPath, Length * sizeof(WCHAR));
SymLink.Length = SymLink.MaximumLength;
InitializeObjectAttributes(&ObjectAttributes,
&SymLink,
OBJ_CASE_INSENSITIVE,
NULL,
NULL);
Status = NtOpenSymbolicLinkObject(&LinkHandle,
SYMBOLIC_LINK_QUERY,
&ObjectAttributes);
if (!NT_SUCCESS(Status))
{
/* Not a symlink, or something else happened: bail out */
DPRINT1("NtOpenSymbolicLinkObject(%wZ) failed, Status 0x%08lx\n", &SymLink, Status);
return FALSE;
}
RtlInitEmptyUnicodeString(&Target, TargetPath, sizeof(TargetPath));
/* Resolve the link and close its handle */
Status = NtQuerySymbolicLinkObject(LinkHandle, &Target, NULL);
NtClose(LinkHandle);
/* Check for success */
if (!NT_SUCCESS(Status))
{
/* Not a symlink, or something else happened: bail out */
DPRINT1("NtQuerySymbolicLinkObject(%wZ) failed, Status 0x%08lx\n", &SymLink, Status);
return FALSE;
}
/* Set pointers */
pwszRemaining = pwszNTPath + Length;
pwszNTPath = TargetPath;
/* Retry once */
RetryOnce = TRUE;
goto Retry;
}
return FALSE;
}
@ -982,6 +1407,9 @@ _tWinMain(HINSTANCE hInst,
goto Quit;
SetupData.hInstance = hInst;
SetupData.hInstallThread = NULL;
SetupData.hHaltInstallEvent = NULL;
SetupData.bStopInstall = FALSE;
CheckUnattendedSetup(&SetupData.USetupData);
SetupData.bUnattend = IsUnattendedSetup; // FIXME :-)
@ -994,7 +1422,7 @@ _tWinMain(HINSTANCE hInst,
* you must call InitCommonControlsEx() to register the classes
* for those controls. */
iccx.dwSize = sizeof(iccx);
iccx.dwICC = ICC_LISTVIEW_CLASSES | ICC_TREEVIEW_CLASSES /* | ICC_PROGRESS_CLASS */;
iccx.dwICC = ICC_LISTVIEW_CLASSES | ICC_TREEVIEW_CLASSES | ICC_PROGRESS_CLASS;
InitCommonControlsEx(&iccx);
/* Create title font */
@ -1106,6 +1534,13 @@ _tWinMain(HINSTANCE hInst,
DeleteObject(SetupData.hTitleFont);
Quit:
/* Wait for any pending installation */
WaitForSingleObject(SetupData.hInstallThread, INFINITE);
CloseHandle(SetupData.hInstallThread);
SetupData.hInstallThread = NULL;
CloseHandle(SetupData.hHaltInstallEvent);
SetupData.hHaltInstallEvent = NULL;
/* Setup has finished */
FinishSetup(&SetupData.USetupData);

View file

@ -0,0 +1,26 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
<description>ReactOS Setup</description>
<dependency>
<dependentAssembly>
<assemblyIdentity
type="win32"
name="Microsoft.Windows.Common-Controls"
version="6.0.0.0"
publicKeyToken="6595b64144ccf1df"
processorArchitecture="*"
language="*"
/>
</dependentAssembly>
</dependency>
<trustInfo xmlns="urn:schemas-microsoft-com:asm.v3">
<security>
<requestedPrivileges>
<requestedExecutionLevel
level="requireAdministrator"
uiAccess="false"
/>
</requestedPrivileges>
</security>
</trustInfo>
</assembly>

View file

@ -74,6 +74,10 @@ typedef struct _SETUPDATA
HFONT hTitleFont;
HANDLE hInstallThread;
HANDLE hHaltInstallEvent;
BOOL bStopInstall;
TCHAR szAbortMessage[512];
TCHAR szAbortTitle[64];

View file

@ -4,9 +4,9 @@
#include "resource.h"
#define REACTOS_STR_FILE_DESCRIPTION "ReactOS Setup"
#define REACTOS_STR_INTERNAL_NAME "reactos"
#define REACTOS_STR_ORIGINAL_FILENAME "reactos.exe"
#define REACTOS_STR_FILE_DESCRIPTION "ReactOS Setup"
#define REACTOS_STR_INTERNAL_NAME "reactos"
#define REACTOS_STR_ORIGINAL_FILENAME "reactos.exe"
#include <reactos/version.rc>
LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL
@ -20,7 +20,7 @@ IDI_WINICON ICON "res/winlogo.ico"
IDB_WATERMARK BITMAP "res/watermark.bmp"
IDB_HEADER BITMAP "res/header.bmp"
#include <reactos/manifest_exe.rc>
CREATEPROCESS_MANIFEST_RESOURCE_ID RT_MANIFEST "reactos.exe.manifest"
/* UTF-8 */
#pragma code_page(65001)