windows-nt/Source/XPSP1/NT/base/ntsetup/winnt32/dll/dynsetup.c
2020-09-26 16:20:57 +08:00

1493 lines
42 KiB
C

#include "precomp.h"
#pragma hdrstop
#define SETNEXTPAGE(x) *((LONG*)lParam) = x
extern HWND BackgroundWnd;
extern HWND BackgroundWnd2;
static HANDLE g_Thread = NULL;
static HANDLE g_Event = NULL;
//
// Prototypes
//
INT_PTR DynSetup_ManualDialog( IN HWND hdlg, IN UINT msg, IN WPARAM wParam, IN LPARAM lParam );
HANDLE
pInitializeOnlineSeconds (
VOID
);
DWORD
pGetOnlineRemainingSeconds (
IN HANDLE Handle,
IN DWORD DownloadedBytes,
IN DWORD TotalBytesToDownload,
OUT PDWORD KbPerSec OPTIONAL
);
VOID
pCheckRadioButtons (
IN HWND Hdlg,
IN UINT ButtonToSelect,
...
)
{
va_list args;
UINT u;
va_start (args, ButtonToSelect);
while (u = va_arg (args, UINT)) {
CheckDlgButton (Hdlg, u, u == ButtonToSelect ? BST_CHECKED : BST_UNCHECKED);
}
va_end (args);
}
BOOL
DynSetupWizPage(
IN HWND hdlg,
IN UINT msg,
IN WPARAM wParam,
IN LPARAM lParam
)
/*++
Routine Description:
Dynamic Setup page 1 (choose to use dynamic updates) or just skip it
if this happens after a restart
Arguments:
Standard window proc arguments.
Returns:
Message-dependent value.
--*/
{
PPAGE_RUNTIME_DATA WizPage = (PPAGE_RUNTIME_DATA)GetWindowLongPtr(hdlg,DWLP_USER);
BOOL fRetVal = FALSE;
switch(msg) {
case WM_INITDIALOG:
pCheckRadioButtons (hdlg, g_DynUpdtStatus->DUStatus == DUS_INITIAL ? IDOK : IDCANCEL, IDOK, IDCANCEL);
SetFocus(GetDlgItem(hdlg,IDOK));
break;
case WM_COMMAND:
if(HIWORD(wParam) == BN_CLICKED) {
if (LOWORD(wParam) == IDOK) {
g_DynUpdtStatus->DUStatus = DUS_INITIAL;
} else if (LOWORD(wParam) == IDCANCEL) {
g_DynUpdtStatus->DUStatus = DUS_SKIP;
}
}
fRetVal = TRUE;
break;
case WMX_ACTIVATEPAGE:
fRetVal = TRUE;
if (wParam) {
//
// don't activate the page in restart mode
//
if (Winnt32Restarted ()) {
if (Winnt32RestartedWithAF ()) {
GetPrivateProfileString(
WINNT_UNATTENDED,
WINNT_U_DYNAMICUPDATESHARE,
TEXT(""),
g_DynUpdtStatus->DynamicUpdatesSource,
SIZEOFARRAY(g_DynUpdtStatus->DynamicUpdatesSource),
g_DynUpdtStatus->RestartAnswerFile
);
}
return FALSE;
}
//
// skip this step if already successfully performed
//
if (g_DynUpdtStatus->DUStatus == DUS_SUCCESSFUL) {
return FALSE;
}
if (g_DynUpdtStatus->UserSpecifiedUpdates) {
MYASSERT (!g_DynUpdtStatus->Disabled);
//
// go to the next page to start processing files
//
PropSheet_PressButton (GetParent (hdlg), PSBTN_NEXT);
} else {
if (g_DynUpdtStatus->Disabled ||
//
// skip if support is not available
//
!DynamicUpdateIsSupported (hdlg)
) {
//
// skip page(s)
//
g_DynUpdtStatus->DUStatus = DUS_SKIP;
pCheckRadioButtons (hdlg, IDCANCEL, IDOK, IDCANCEL);
// Don't do press button next, This would cause the page to paint.
return( FALSE );
}
//
// in CheckUpgradeOnly mode, ask user if they want to connect to WU
//
if (UpgradeAdvisorMode || !CheckUpgradeOnly || UnattendSwitchSpecified) {
if ((UpgradeAdvisorMode || UnattendedOperation) && !CancelPending) {
PropSheet_PressButton (GetParent (hdlg), PSBTN_NEXT);
break;
}
}
if (CheckUpgradeOnly) {
//
// disable the Back button in this case
//
PropSheet_SetWizButtons (GetParent(hdlg), WizPage->CommonData.Buttons & ~PSWIZB_BACK);
}
}
}
Animate_Open(GetDlgItem(hdlg, IDC_ANIMATE), wParam ? MAKEINTRESOURCE(IDA_COMPGLOB) : NULL);
break;
default:
break;
}
return fRetVal;
}
VOID
pUpdateInfoText (
IN UINT InfoId
)
{
#define MAX_TEXT 256
TCHAR text[MAX_TEXT];
if (!LoadString (hInst, InfoId, text, MAX_TEXT)) {
text[0] = 0;
}
BB_SetInfoText (text);
}
VOID
pUpdateProgressText (
IN HWND Hdlg,
IN UINT ProgressId,
IN PCTSTR AppendText, OPTIONAL
IN BOOL InsertNewLine
)
{
#define MAX_TEXT 256
TCHAR text[MAX_TEXT] = TEXT("");
if (Hdlg) {
if (!GetDlgItemText (Hdlg, ProgressId, text, MAX_TEXT)) {
text[0] = 0;
}
} else {
if (!LoadString (hInst, ProgressId, text, MAX_TEXT)) {
text[0] = 0;
}
}
if (AppendText) {
DWORD len = lstrlen (AppendText) + 1;
if (len < MAX_TEXT) {
if (InsertNewLine) {
if (len + 2 < MAX_TEXT) {
len += 2;
_tcsncat (text, TEXT("\r\n"), MAX_TEXT - len);
}
}
_tcsncat (text, AppendText, MAX_TEXT - len);
}
}
BB_SetProgressText (text);
UpdateWindow (GetBBMainHwnd ());
}
VOID
SetDlgItemTextBold (
IN HWND Hdlg,
IN INT DlgItemID,
IN BOOL Bold
)
{
HFONT font;
LOGFONT logFont;
LONG weight;
DWORD id = 0;
font = (HFONT) SendDlgItemMessage (Hdlg, DlgItemID, WM_GETFONT, 0, 0);
if (font && GetObject (font, sizeof(LOGFONT), &logFont)) {
weight = Bold ? FW_BOLD : FW_NORMAL;
if (weight != logFont.lfWeight) {
logFont.lfWeight = weight;
font = CreateFontIndirect (&logFont);
if (font) {
SendDlgItemMessage (Hdlg, DlgItemID, WM_SETFONT, (WPARAM)font, MAKELPARAM(TRUE,0));
}
}
}
}
BOOL
DynSetup2WizPage(
IN HWND hdlg,
IN UINT msg,
IN WPARAM wParam,
IN LPARAM lParam
)
/*++
Routine Description:
Dynamic Setup page 2
Arguments:
Standard window proc arguments.
Returns:
Message-dependent value.
--*/
{
PPAGE_RUNTIME_DATA WizPage = (PPAGE_RUNTIME_DATA)GetWindowLongPtr(hdlg,DWLP_USER);
BOOL fRetVal = FALSE;
PTSTR message;
DWORD onlineRemainingSeconds;
DWORD onlineRemainingMinutes;
DWORD kbps;
TCHAR buf[200];
DWORD estTime, estSize;
HCURSOR hc;
BOOL b;
HANDLE hBitmap, hOld;
DWORD tid;
#ifdef DOWNLOAD_DETAILS
TCHAR buf2[200];
#endif
static BOOL DownloadPageActive = FALSE;
static PTSTR msgToFormat = NULL;
static HANDLE hComp = NULL;
static BOOL CancelDownloadPending = FALSE;
static BOOL ResumeWorkerThread = FALSE;
static DWORD PrevOnlineRemainingMinutes;
static UINT_PTR timer = 0;
#define DOWNLOAD_TIMEOUT_TIMER 5
#define DOWNLOAD_NOTIFY_TIMEOUT 60000
switch(msg) {
case WM_INITDIALOG:
if (GetDlgItemText (hdlg, IDT_DYNSETUP_TIME, buf, 100)) {
msgToFormat = DupString (buf);
}
SetDlgItemText (hdlg, IDT_DYNSETUP_TIME, TEXT(""));
break;
case WMX_ACTIVATEPAGE:
fRetVal = TRUE;
if (wParam) {
if (g_DynUpdtStatus->DUStatus == DUS_SKIP ||
g_DynUpdtStatus->DUStatus == DUS_SUCCESSFUL
) {
if (g_Thread) {
MYASSERT (g_Event);
g_Thread = NULL;
CloseHandle (g_Event);
g_Event = NULL;
}
if (g_DynUpdtStatus->DUStatus == DUS_SKIP) {
if (!g_DynUpdtStatus->Disabled) {
DynUpdtDebugLog (
Winnt32LogInformation,
TEXT("DynamicUpdate is skipped"),
0
);
}
}
return FALSE;
}
//
// prepare the UI
//
if (Winnt32Restarted () || g_DynUpdtStatus->UserSpecifiedUpdates) {
hBitmap = LoadImage (hInst, MAKEINTRESOURCE(IDB_CHECK), IMAGE_BITMAP, 0, 0, LR_LOADMAP3DCOLORS);
hOld = (HANDLE) SendDlgItemMessage (hdlg, IDC_COPY_BMP, STM_SETIMAGE, IMAGE_BITMAP, (LPARAM)hBitmap);
hOld = (HANDLE) SendDlgItemMessage (hdlg, IDC_COPY_BMP2, STM_SETIMAGE, IMAGE_BITMAP, (LPARAM)hBitmap);
hBitmap = LoadImage (hInst, MAKEINTRESOURCE(IDB_ARROW), IMAGE_BITMAP, 0, 0, LR_LOADMAP3DCOLORS);
hOld = (HANDLE) SendDlgItemMessage (hdlg, IDC_COPY_BMP3, STM_SETIMAGE, IMAGE_BITMAP, (LPARAM)hBitmap);
} else {
pUpdateInfoText (IDS_ESC_TOCANCEL_DOWNLOAD);
hBitmap = LoadImage (hInst, MAKEINTRESOURCE(IDB_ARROW), IMAGE_BITMAP, 0, 0, LR_LOADMAP3DCOLORS);
hOld = (HANDLE) SendDlgItemMessage (hdlg, IDC_COPY_BMP, STM_SETIMAGE, IMAGE_BITMAP, (LPARAM)hBitmap);
hOld = (HANDLE) SendDlgItemMessage (hdlg, IDC_COPY_BMP2, STM_SETIMAGE, IMAGE_BITMAP, (LPARAM)hBitmap);
hOld = (HANDLE) SendDlgItemMessage (hdlg, IDC_COPY_BMP3, STM_SETIMAGE, IMAGE_BITMAP, (LPARAM)hBitmap);
}
if (!g_Event) {
g_Event = CreateEvent (NULL, FALSE, FALSE, S_DU_SYNC_EVENT_NAME);
if (!g_Event) {
DynUpdtDebugLog (
Winnt32LogError,
TEXT("CreateEvent(%1) failed"),
0,
S_DU_SYNC_EVENT_NAME
);
g_DynUpdtStatus->DUStatus = DUS_ERROR;
return FALSE;
}
}
if (!g_Thread) {
g_Thread = CreateThread (NULL, 0, DoDynamicUpdate, (LPVOID)hdlg, 0, &tid);
if (!g_Thread) {
DynUpdtDebugLog (
Winnt32LogError,
TEXT("CreateThread(DoDynamicUpdate) failed"),
0
);
g_DynUpdtStatus->DUStatus = DUS_ERROR;
CloseHandle (g_Event);
g_Event = NULL;
return FALSE;
}
//
// the handle is no longer needed
//
CloseHandle (g_Thread);
} else {
b = FALSE;
if (g_DynUpdtStatus->DUStatus == DUS_PREPARING_CONNECTIONUNAVAILABLE ||
g_DynUpdtStatus->DUStatus == DUS_PREPARING_INVALIDURL) {
g_DynUpdtStatus->DUStatus = DUS_PREPARING;
b = TRUE;
}
if (g_DynUpdtStatus->DUStatus == DUS_DOWNLOADING_ERROR) {
g_DynUpdtStatus->DUStatus = DUS_DOWNLOADING;
b = TRUE;
}
if (b) {
//
// page was actually reentered after some previous failure
// resume the working thread
//
MYASSERT (g_Event);
SetEvent (g_Event);
}
}
DownloadPageActive = TRUE;
//
// hide the wizard page
//
SendMessage(GetParent (hdlg), WMX_BBTEXT, (WPARAM)TRUE, 0);
} else {
if (timer) {
KillTimer (hdlg, timer);
timer = 0;
}
DownloadPageActive = FALSE;
}
Animate_Open(GetDlgItem(hdlg, IDC_ANIMATE), wParam ? MAKEINTRESOURCE(IDA_COMPGLOB) : NULL);
break;
case WMX_SETUPUPDATE_PROGRESS_NOTIFY:
//
// reset the timer
//
timer = SetTimer (hdlg, DOWNLOAD_TIMEOUT_TIMER, DOWNLOAD_NOTIFY_TIMEOUT, NULL);
//
// update UI
//
if (!hComp) {
hComp = pInitializeOnlineSeconds ();
PrevOnlineRemainingMinutes = -1;
}
onlineRemainingSeconds = pGetOnlineRemainingSeconds (hComp, (DWORD)lParam, (DWORD)wParam, &kbps);
if (onlineRemainingSeconds) {
onlineRemainingMinutes = onlineRemainingSeconds / 60 + 1;
if (msgToFormat && onlineRemainingMinutes < PrevOnlineRemainingMinutes) {
PrevOnlineRemainingMinutes = onlineRemainingMinutes;
wsprintf (buf, msgToFormat, onlineRemainingMinutes);
#ifdef DOWNLOAD_DETAILS
//
// also display kbps and remaining time in seconds
//
wsprintf (buf2, TEXT(" (%u sec. at %u kbps)"), onlineRemainingSeconds, kbps);
lstrcat (buf, buf2);
#endif
SetDlgItemText (hdlg, IDT_DYNSETUP_TIME, buf);
pUpdateProgressText (hdlg, IDT_DYNSETUP_DOWNLOADING, buf, TRUE);
}
}
break;
case WMX_SETUPUPDATE_RESULT:
if (timer) {
KillTimer (hdlg, timer);
timer = 0;
}
if (g_DynUpdtStatus->DUStatus == DUS_DOWNLOADING) {
Animate_Stop (GetDlgItem (hdlg, IDC_ANIMATE));
if (g_DynUpdtStatus->Cancelled) {
g_DynUpdtStatus->DUStatus = DUS_CANCELLED;
} else {
if (wParam == DU_STATUS_SUCCESS) {
g_DynUpdtStatus->DUStatus = DUS_PROCESSING;
} else if (wParam == DU_STATUS_FAILED) {
g_DynUpdtStatus->DUStatus = DUS_DOWNLOADING_ERROR;
} else {
g_DynUpdtStatus->DUStatus = DUS_ERROR;
MYASSERT (FALSE);
}
}
if (!CancelDownloadPending) {
//
// let the worker thread continue
//
if (g_DynUpdtStatus->DUStatus != DUS_DOWNLOADING_ERROR) {
MYASSERT (g_Event);
SetEvent (g_Event);
} else {
//
// go to the error page
//
if (DownloadPageActive) {
PropSheet_SetWizButtons (GetParent(hdlg), WizPage->CommonData.Buttons | PSWIZB_NEXT);
PropSheet_PressButton (GetParent (hdlg), PSBTN_NEXT);
DownloadPageActive = FALSE;
}
}
} else {
ResumeWorkerThread = TRUE;
}
} else {
MYASSERT (FALSE);
g_DynUpdtStatus->DUStatus = DUS_ERROR;
if (g_Event) {
SetEvent (g_Event);
}
}
break;
case WMX_SETUPUPDATE_PREPARING:
SetDlgItemTextBold (hdlg, IDT_DYNSETUP_DIALING, TRUE);
pUpdateProgressText (hdlg, IDT_DYNSETUP_DIALING, NULL, FALSE);
Animate_Play (GetDlgItem (hdlg, IDC_ANIMATE), 0, -1, -1);
break;
case WMX_SETUPUPDATE_DOWNLOADING:
//
// wParam holds the estimated download time
// lParam holds the estimated download size
//
SetDlgItemTextBold (hdlg, IDT_DYNSETUP_DIALING, FALSE);
hBitmap = LoadImage (hInst, MAKEINTRESOURCE(IDB_CHECK), IMAGE_BITMAP, 0, 0, LR_LOADMAP3DCOLORS);
hOld = (HANDLE) SendDlgItemMessage (hdlg, IDC_COPY_BMP, STM_SETIMAGE, IMAGE_BITMAP, (LPARAM)hBitmap);
SetDlgItemTextBold (hdlg, IDT_DYNSETUP_DOWNLOADING, TRUE);
pUpdateProgressText (hdlg, IDT_DYNSETUP_DOWNLOADING, NULL, FALSE);
ShowWindow (GetDlgItem (hdlg, IDT_DYNSETUP_TIME), SW_SHOW);
//
// set a timeout interval, just in case the control "forgets" to send messages
//
timer = SetTimer (hdlg, DOWNLOAD_TIMEOUT_TIMER, DOWNLOAD_NOTIFY_TIMEOUT, NULL);
if (!timer) {
DynUpdtDebugLog (
Winnt32LogWarning,
TEXT("SetTimer failed - unable to automatically abort if the control doesn't respond timely"),
0
);
}
break;
case WMX_SETUPUPDATE_PROCESSING:
g_DynUpdtStatus->DUStatus = DUS_PROCESSING;
SetDlgItemTextBold (hdlg, IDT_DYNSETUP_DOWNLOADING, FALSE);
ShowWindow (GetDlgItem (hdlg, IDT_DYNSETUP_TIME), SW_HIDE);
hBitmap = LoadImage (hInst, MAKEINTRESOURCE(IDB_CHECK), IMAGE_BITMAP, 0, 0, LR_LOADMAP3DCOLORS);
hOld = (HANDLE) SendDlgItemMessage (hdlg, IDC_COPY_BMP2, STM_SETIMAGE, IMAGE_BITMAP, (LPARAM)hBitmap);
SetDlgItemTextBold (hdlg, IDT_DYNSETUP_PROCESSING, TRUE);
pUpdateProgressText (hdlg, IDT_DYNSETUP_PROCESSING, NULL, FALSE);
pUpdateInfoText (IDS_ESC_TOCANCEL);
break;
case WMX_SETUPUPDATE_THREAD_DONE:
pUpdateProgressText (NULL, 0, NULL, FALSE);
g_Thread = NULL;
if (g_Event) {
CloseHandle (g_Event);
g_Event = NULL;
}
if (g_DynUpdtStatus->DUStatus == DUS_SUCCESSFUL) {
if (!g_DynUpdtStatus->RestartWinnt32) {
DynUpdtDebugLog (
Winnt32LogInformation,
TEXT("DynamicUpdate was completed successfully"),
0
);
}
SetDlgItemTextBold (hdlg, IDT_DYNSETUP_PROCESSING, FALSE);
hBitmap = LoadImage (hInst, MAKEINTRESOURCE(IDB_CHECK), IMAGE_BITMAP, 0, 0, LR_LOADMAP3DCOLORS);
hOld = (HANDLE) SendDlgItemMessage (hdlg, IDC_COPY_BMP3, STM_SETIMAGE, IMAGE_BITMAP, (LPARAM)hBitmap);
UpdateWindow (GetDlgItem (hdlg, IDC_COPY_BMP3));
UpdateWindow (hdlg);
} else if (g_DynUpdtStatus->DUStatus == DUS_ERROR) {
if (UnattendedScriptFile) {
//
// in the unattended case, read the answer to decide if to stop or not
//
GetPrivateProfileString (
WINNT_UNATTENDED,
WINNT_U_DYNAMICUPDATESTOPONERROR,
WINNT_A_NO,
buf,
200,
UnattendedScriptFile
);
if (!lstrcmpi (buf, WINNT_A_YES)) {
DynUpdtDebugLog (
Winnt32LogSevereError,
TEXT("Setup encountered an error during DynamicUpdate and failed as instructed in the unattend file"),
0
);
g_DynUpdtStatus->RestartWinnt32 = FALSE;
Cancelled = TRUE;
PropSheet_PressButton (GetParent (hdlg), PSBTN_CANCEL);
break;
}
}
} else if (g_DynUpdtStatus->DUStatus == DUS_FATALERROR) {
DynUpdtDebugLog (
Winnt32LogSevereError,
TEXT("Setup encountered a fatal error during DynamicUpdate and stopped"),
0
);
g_DynUpdtStatus->RestartWinnt32 = FALSE;
Cancelled = TRUE;
PropSheet_PressButton (GetParent (hdlg), PSBTN_CANCEL);
break;
}
//
// continue setup (this may actually restart winnt32)
//
if (DownloadPageActive) {
PropSheet_SetWizButtons (GetParent(hdlg), WizPage->CommonData.Buttons | PSWIZB_NEXT);
PropSheet_PressButton (GetParent (hdlg), PSBTN_NEXT);
DownloadPageActive = FALSE;
}
break;
case WMX_SETUPUPDATE_INIT_RETRY:
//
// go to the retry page
//
if (DownloadPageActive) {
PropSheet_SetWizButtons (GetParent(hdlg), WizPage->CommonData.Buttons | PSWIZB_NEXT);
PropSheet_PressButton (GetParent (hdlg), PSBTN_NEXT);
PropSheet_SetWizButtons (GetParent(hdlg), WizPage->CommonData.Buttons & ~PSWIZB_NEXT);
DownloadPageActive = FALSE;
}
break;
case WMX_QUERYCANCEL:
//
// on this page, CANCEL means "cancel download", not cancel Setup,
// but only while connecting or downloading
//
if (g_DynUpdtStatus->DUStatus != DUS_DOWNLOADING && g_DynUpdtStatus->DUStatus != DUS_PREPARING) {
break;
}
fRetVal = TRUE;
if (lParam) {
//
// don't cancel setup
//
*(BOOL*)lParam = FALSE;
}
if (!g_DynUpdtStatus->Cancelled) {
//
// ask user if they really want to cancel DU
//
DWORD rc = IDYES;
CancelDownloadPending = TRUE;
Animate_Stop (GetDlgItem (hdlg, IDC_ANIMATE));
if (!CheckUpgradeOnly) {
rc = MessageBoxFromMessage (
hdlg,
g_DynUpdtStatus->IncompatibleDriversCount ?
MSG_SURE_CANCEL_DOWNLOAD_DRIVERS : MSG_SURE_CANCEL_DOWNLOAD,
FALSE,
AppTitleStringId,
MB_YESNO | MB_ICONQUESTION | MB_TASKMODAL | MB_DEFBUTTON2,
g_DynUpdtStatus->IncompatibleDriversCount
);
}
if (rc == IDYES) {
g_DynUpdtStatus->Cancelled = TRUE;
DynamicUpdateCancel ();
} else {
Animate_Play (GetDlgItem (hdlg, IDC_ANIMATE), 0, -1, -1);
}
if (ResumeWorkerThread) {
ResumeWorkerThread = FALSE;
if (g_DynUpdtStatus->DUStatus != DUS_DOWNLOADING_ERROR) {
MYASSERT (g_Event);
SetEvent (g_Event);
}
}
CancelDownloadPending = FALSE;
}
break;
case WM_TIMER:
if (timer && (wParam == timer)) {
if (g_DynUpdtStatus->DUStatus == DUS_DOWNLOADING) {
//
// oops, the control didn't send any message in a long time now...
// abort download and continue
//
DynUpdtDebugLog (
Winnt32LogError,
TEXT("The timeout for control feedback expired (%1!u! seconds); operation will be aborted"),
0,
DOWNLOAD_NOTIFY_TIMEOUT / 1000
);
KillTimer (hdlg, timer);
timer = 0;
DynamicUpdateCancel ();
SendMessage (hdlg, WMX_SETUPUPDATE_RESULT, DU_STATUS_FAILED, ERROR_TIMEOUT);
}
}
break;
}
return fRetVal;
}
BOOL
RestartWizPage (
IN HWND hdlg,
IN UINT msg,
IN WPARAM wParam,
IN LPARAM lParam
)
/*++
Routine Description:
Dynamic Setup Restart page
Arguments:
Standard window proc arguments.
Returns:
Message-dependent value.
--*/
{
#define REBOOT_TIMEOUT_SECONDS 5
#define ID_REBOOT_TIMER 1
#define TICKS_PER_SECOND 10
static UINT Countdown;
PCTSTR RestartText;
BOOL fRetVal = FALSE;
switch(msg) {
case WM_TIMER:
if (--Countdown) {
SendDlgItemMessage (hdlg, IDC_PROGRESS1, PBM_STEPIT, 0, 0);
} else {
PropSheet_PressButton (GetParent (hdlg), PSBTN_FINISH);
}
fRetVal = TRUE;
break;
case WMX_ACTIVATEPAGE:
if (wParam) {
pUpdateInfoText (IDS_ESC_TOCANCEL);
if (Winnt32Restarted () ||
g_DynUpdtStatus->DUStatus != DUS_SUCCESSFUL ||
!g_DynUpdtStatus->RestartWinnt32
) {
return FALSE;
}
//
// Setup needs to restart with option /Restart:<path to restart file>
//
if (!DynamicUpdatePrepareRestart ()) {
DynUpdtDebugLog (
Winnt32LogError,
TEXT("DynamicUpdatePrepareRestart failed"),
0
);
g_DynUpdtStatus->DUStatus = DUS_ERROR;
return FALSE;
}
pUpdateProgressText (NULL, IDS_RESTART_SETUP, NULL, FALSE);
pUpdateInfoText (0);
EnableWindow (GetDlgItem(GetParent(hdlg), IDCANCEL), FALSE);
PropSheet_SetWizButtons (GetParent(hdlg), PSWIZB_FINISH);
RestartText = GetStringResource (MSG_RESTART);
if (RestartText) {
PropSheet_SetFinishText (GetParent (hdlg), RestartText);
FreeStringResource (RestartText);
}
Countdown = REBOOT_TIMEOUT_SECONDS * TICKS_PER_SECOND;
SendDlgItemMessage (hdlg, IDC_PROGRESS1, PBM_SETRANGE, 0, MAKELONG(0,Countdown));
SendDlgItemMessage (hdlg, IDC_PROGRESS1, PBM_SETSTEP, 1, 0);
SendDlgItemMessage (hdlg, IDC_PROGRESS1, PBM_SETPOS, 0, 0);
SetTimer (hdlg, ID_REBOOT_TIMER, 1000 / TICKS_PER_SECOND, NULL);
}
//
// Accept activation/deactivation.
//
fRetVal = TRUE;
break;
case WMX_FINISHBUTTON:
//
// Clean up the timer.
//
KillTimer (hdlg, ID_REBOOT_TIMER);
//
// Let upgrade code do its cleanup.
//
if (UpgradeSupport.CleanupRoutine) {
UpgradeSupport.CleanupRoutine ();
}
fRetVal = TRUE;
break;
}
return fRetVal;
}
BOOL
DynSetup3WizPage(
IN HWND hdlg,
IN UINT msg,
IN WPARAM wParam,
IN LPARAM lParam
)
/*++
Routine Description:
Dynamic Setup page 3 (retrying connection establish)
Arguments:
Standard window proc arguments.
Returns:
Message-dependent value.
--*/
{
TCHAR buffer[100];
BOOL cancel;
static INT iSelected = IDR_DYNSETUP_MANUAL;
static BOOL bFirstTime = TRUE;
BOOL fRetVal = FALSE;
switch(msg) {
case WM_INITDIALOG:
//
// Set radio buttons.
//
pCheckRadioButtons (hdlg, iSelected, IDR_DYNSETUP_MANUAL, IDR_DYNSETUP_SKIP);
//
// Set focus to radio buttons
//
SetFocus (GetDlgItem (hdlg, IDR_DYNSETUP_MANUAL));
break;
case WM_COMMAND:
if(HIWORD(wParam) == BN_CLICKED) {
switch (LOWORD (wParam)) {
case IDR_DYNSETUP_MANUAL:
case IDR_DYNSETUP_SKIP:
iSelected = LOWORD (wParam);
fRetVal = TRUE;
break;
}
}
break;
case WMX_ACTIVATEPAGE:
if (wParam) {
if (g_DynUpdtStatus->DUStatus != DUS_PREPARING_CONNECTIONUNAVAILABLE) {
return FALSE;
}
if (UnattendSwitchSpecified) {
//
// skip DU by default
//
iSelected = IDR_DYNSETUP_SKIP;
//
// now read the answer, if provided
//
if (UnattendedScriptFile) {
GetPrivateProfileString (
WINNT_UNATTENDED,
WINNT_U_DYNAMICUPDATESTOPONERROR,
WINNT_A_NO,
buffer,
100,
UnattendedScriptFile
);
if (!lstrcmpi (buffer, WINNT_A_YES)) {
DynUpdtDebugLog (
Winnt32LogSevereError,
TEXT("Setup encountered an error during DynamicUpdate and failed as instructed in the unattend file"),
0
);
g_DynUpdtStatus->RestartWinnt32 = FALSE;
Cancelled = TRUE;
PropSheet_PressButton (GetParent (hdlg), PSBTN_CANCEL);
break;
}
}
UNATTENDED(PSBTN_NEXT);
} else {
iSelected = bFirstTime ? IDR_DYNSETUP_MANUAL : IDR_DYNSETUP_SKIP;
bFirstTime = FALSE;
}
pCheckRadioButtons (hdlg, iSelected, IDR_DYNSETUP_MANUAL, IDR_DYNSETUP_SKIP);
SendMessage(GetParent (hdlg), WMX_BBTEXT, (WPARAM)FALSE, 0);
} else {
if (Cancelled) {
g_DynUpdtStatus->Cancelled = TRUE;
}
//
// let the worker thread continue
//
MYASSERT (g_Thread && g_Event);
SetEvent (g_Event);
}
fRetVal = TRUE;
break;
case WMX_BACKBUTTON:
MYASSERT (FALSE);
case WMX_NEXTBUTTON:
switch (iSelected) {
case IDR_DYNSETUP_MANUAL:
// do magical stuff to hide everything
ShowWindow(BackgroundWnd2, SW_MINIMIZE);
if (DialogBox(hInst, MAKEINTRESOURCE(IDD_DYNAMICSETUP_MANUAL), hdlg, DynSetup_ManualDialog)) {
DynUpdtDebugLog (
Winnt32LogInformation,
TEXT("Manual connect page: user connected manually"),
0
);
g_DynUpdtStatus->DUStatus = DUS_PREPARING;
SETNEXTPAGE(IDD_DYNAMICSETUP2);
}
// do magical stuff to unhide everything
ShowWindow(BackgroundWnd2, SW_SHOWMAXIMIZED);
break;
case IDR_DYNSETUP_SKIP:
DynUpdtDebugLog (
Winnt32LogInformation,
TEXT("Manual connect page: operation was skipped"),
0
);
g_DynUpdtStatus->DUStatus = DUS_SKIP;
break;
}
fRetVal = TRUE;
break;
}
return fRetVal;
}
BOOL
DynSetup4WizPage(
IN HWND hdlg,
IN UINT msg,
IN WPARAM wParam,
IN LPARAM lParam
)
/*++
Routine Description:
Dynamic Setup page 4 (web site inaccessible)
Arguments:
Standard window proc arguments.
Returns:
Message-dependent value.
--*/
{
TCHAR buffer[100];
BOOL cancel;
static INT iSelected = IDR_DYNSETUP_RETRY;
static BOOL bFirstTime = TRUE;
BOOL fRetVal = FALSE;
switch(msg) {
case WM_INITDIALOG:
//
// Set radio buttons.
//
pCheckRadioButtons (hdlg, iSelected, IDR_DYNSETUP_RETRY, IDR_DYNSETUP_SKIP);
//
// Set focus to radio buttons
//
SetFocus (GetDlgItem (hdlg, IDR_DYNSETUP_RETRY));
break;
case WM_COMMAND:
if(HIWORD(wParam) == BN_CLICKED) {
switch (LOWORD (wParam)) {
case IDR_DYNSETUP_RETRY:
case IDR_DYNSETUP_SKIP:
iSelected = LOWORD (wParam);
fRetVal = TRUE;
break;
}
}
break;
case WMX_ACTIVATEPAGE:
if (wParam) {
if (g_DynUpdtStatus->DUStatus != DUS_PREPARING_INVALIDURL) {
return FALSE;
}
if (UnattendSwitchSpecified) {
//
// skip DU by default
//
iSelected = IDR_DYNSETUP_SKIP;
//
// now read the answer, if provided
//
if (UnattendedScriptFile) {
GetPrivateProfileString (
WINNT_UNATTENDED,
WINNT_U_DYNAMICUPDATESTOPONERROR,
WINNT_A_NO,
buffer,
100,
UnattendedScriptFile
);
if (!lstrcmpi (buffer, WINNT_A_YES)) {
DynUpdtDebugLog (
Winnt32LogSevereError,
TEXT("Setup encountered an error during DynamicUpdate and failed as instructed in the unattend file"),
0
);
g_DynUpdtStatus->RestartWinnt32 = FALSE;
Cancelled = TRUE;
PropSheet_PressButton (GetParent (hdlg), PSBTN_CANCEL);
break;
}
}
UNATTENDED(PSBTN_NEXT);
} else {
iSelected = bFirstTime ? IDR_DYNSETUP_RETRY : IDR_DYNSETUP_SKIP;
bFirstTime = FALSE;
}
pCheckRadioButtons (hdlg, iSelected, IDR_DYNSETUP_RETRY, IDR_DYNSETUP_SKIP);
SendMessage(GetParent (hdlg), WMX_BBTEXT, (WPARAM)FALSE, 0);
} else {
if (Cancelled) {
g_DynUpdtStatus->Cancelled = TRUE;
}
//
// let the worker thread continue
//
MYASSERT (g_Thread && g_Event);
SetEvent (g_Event);
}
fRetVal = TRUE;
break;
case WMX_BACKBUTTON:
MYASSERT (FALSE);
case WMX_NEXTBUTTON:
switch (iSelected) {
case IDR_DYNSETUP_RETRY:
DynUpdtDebugLog (
Winnt32LogInformation,
TEXT("Retry connection page: user chose to retry"),
0
);
g_DynUpdtStatus->DUStatus = DUS_PREPARING;
SETNEXTPAGE(IDD_DYNAMICSETUP2);
break;
case IDR_DYNSETUP_SKIP:
DynUpdtDebugLog (
Winnt32LogInformation,
TEXT("Retry connection page: operation was skipped"),
0
);
g_DynUpdtStatus->DUStatus = DUS_SKIP;
break;
}
fRetVal = TRUE;
break;
}
return fRetVal;
}
BOOL
DynSetup5WizPage(
IN HWND hdlg,
IN UINT msg,
IN WPARAM wParam,
IN LPARAM lParam
)
/*++
Routine Description:
Dynamic Setup page 5 (error while downloading)
Arguments:
Standard window proc arguments.
Returns:
Message-dependent value.
--*/
{
TCHAR buffer[100];
BOOL cancel;
static INT iSelected = IDR_DYNSETUP_RETRY;
static BOOL bFirstTime = TRUE;
BOOL fRetVal = FALSE;
switch(msg) {
case WM_INITDIALOG:
//
// Set radio buttons.
//
pCheckRadioButtons (hdlg, iSelected, IDR_DYNSETUP_RETRY, IDR_DYNSETUP_SKIP);
//
// Set focus to radio buttons
//
SetFocus (GetDlgItem (hdlg, IDR_DYNSETUP_RETRY));
break;
case WM_COMMAND:
if(HIWORD(wParam) == BN_CLICKED) {
switch (LOWORD (wParam)) {
case IDR_DYNSETUP_RETRY:
case IDR_DYNSETUP_SKIP:
iSelected = LOWORD (wParam);
fRetVal = TRUE;
break;
}
}
break;
case WMX_ACTIVATEPAGE:
if (wParam) {
if (g_DynUpdtStatus->DUStatus != DUS_DOWNLOADING_ERROR) {
SendMessage (hdlg, WMX_DYNAMIC_UPDATE_COMPLETE, 0, 0);
return FALSE;
}
if (UnattendSwitchSpecified) {
//
// skip DU by default
//
iSelected = IDR_DYNSETUP_SKIP;
//
// now read the answer, if provided
//
if (UnattendedScriptFile) {
//
// Read answer
//
GetPrivateProfileString (
WINNT_UNATTENDED,
WINNT_U_DYNAMICUPDATESTOPONERROR,
WINNT_A_NO,
buffer,
100,
UnattendedScriptFile
);
if (!lstrcmpi (buffer, WINNT_A_YES)) {
DynUpdtDebugLog (
Winnt32LogSevereError,
TEXT("Setup encountered an error during DynamicUpdate and failed as instructed in the unattend file"),
0
);
g_DynUpdtStatus->RestartWinnt32 = FALSE;
Cancelled = TRUE;
PropSheet_PressButton (GetParent (hdlg), PSBTN_CANCEL);
break;
}
}
UNATTENDED(PSBTN_NEXT);
} else {
iSelected = bFirstTime ? IDR_DYNSETUP_RETRY : IDR_DYNSETUP_SKIP;
bFirstTime = FALSE;
}
pCheckRadioButtons (hdlg, iSelected, IDR_DYNSETUP_RETRY, IDR_DYNSETUP_SKIP);
SendMessage(GetParent (hdlg), WMX_BBTEXT, (WPARAM)FALSE, 0);
} else {
if (Cancelled) {
g_DynUpdtStatus->Cancelled = TRUE;
}
//
// let the worker thread continue
//
MYASSERT (g_Thread && g_Event);
SetEvent (g_Event);
}
SendMessage (hdlg, WMX_DYNAMIC_UPDATE_COMPLETE, 0, 0);
fRetVal = TRUE;
break;
case WMX_DYNAMIC_UPDATE_COMPLETE:
#ifdef _X86_
//
// Send upgrade report option to module. DU is
// now out of the picture.
//
switch (g_UpgradeReportMode) {
case IDC_CRITICAL_ISSUES:
AppendUpgradeOption (TEXT("ShowReport=Auto"));
break;
case IDC_ALL_ISSUES:
AppendUpgradeOption (TEXT("ShowReport=Yes"));
break;
case IDC_NO_REPORT:
AppendUpgradeOption (TEXT("ShowReport=No"));
break;
}
#endif
break;
case WMX_BACKBUTTON:
MYASSERT (FALSE);
case WMX_NEXTBUTTON:
switch (iSelected) {
case IDR_DYNSETUP_RETRY:
DynUpdtDebugLog (
Winnt32LogInformation,
TEXT("Retry download page: user chose to retry"),
0
);
g_DynUpdtStatus->DUStatus = DUS_DOWNLOADING;
SETNEXTPAGE(IDD_DYNAMICSETUP2);
break;
case IDR_DYNSETUP_SKIP:
DynUpdtDebugLog (
Winnt32LogInformation,
TEXT("Retry download page: operation was skipped"),
0
);
g_DynUpdtStatus->DUStatus = DUS_SKIP;
break;
}
fRetVal = TRUE;
break;
}
return fRetVal;
}
INT_PTR
DynSetup_ManualDialog(
IN HWND hdlg,
IN UINT msg,
IN WPARAM wParam,
IN LPARAM lParam
)
/*++
Routine Description:
Dynamic Setup manual dialog
Arguments:
Standard window proc arguments.
Returns:
Message-dependent value.
--*/
{
BOOL fRetVal = FALSE;
switch(msg)
{
case WM_INITDIALOG:
fRetVal = TRUE;
break;
case WM_COMMAND:
if(HIWORD(wParam) == BN_CLICKED) {
if (LOWORD (wParam) == IDOK)
{
EndDialog(hdlg, 1);
fRetVal = TRUE;
}
else
{
EndDialog(hdlg, 0);
fRetVal = TRUE;
}
}
}
return fRetVal;
}
//
// Time estimate stuff
//
#define MAX_INDEX 100
typedef struct {
DWORD D;
DWORD T;
ULONGLONG DT;
ULONGLONG TT;
} STDDEV_ELEM, *PSTDDEV_ELEM;
typedef struct {
STDDEV_ELEM Array[MAX_INDEX];
STDDEV_ELEM Sums;
UINT Index;
UINT Count;
DWORD T0;
} STDDEV_COMPUTATION, *PSTDDEV_COMPUTATION;
HANDLE
pInitializeOnlineSeconds (
VOID
)
{
PSTDDEV_COMPUTATION p = MALLOC (sizeof (STDDEV_COMPUTATION));
if (p) {
ZeroMemory (p, sizeof (STDDEV_COMPUTATION));
#ifdef DOWNLOAD_DETAILS
//
// table header
//
DynUpdtDebugLog (
Winnt32LogDetailedInformation,
TEXT("Count| MiliSec| Bytes| Baud|EstRemSec|\r\n")
TEXT("-----|---------|---------|---------|---------|"),
0
);
#endif
}
return (HANDLE)p;
}
DWORD
pGetOnlineRemainingSeconds (
IN HANDLE Handle,
IN DWORD DownloadedBytes,
IN DWORD TotalBytesToDownload,
OUT PDWORD KbPerSec OPTIONAL
)
{
PSTDDEV_COMPUTATION p = (PSTDDEV_COMPUTATION)Handle;
PSTDDEV_ELEM e;
DWORD r = 0;
DWORD remTimeSec;
ULONGLONG div;
if (!p) {
return 0;
}
e = &p->Array[p->Index];
if (p->Count == 0) {
//
// add the first pair
//
e->D = DownloadedBytes; // bytes
e->T = 0; // miliseconds
e->DT = 0;
e->TT = 0;
p->Sums.D = DownloadedBytes;
p->Count++;
p->Index++;
//
// initialize timer
//
p->T0 = GetTickCount ();
//
// no time estimate at this point (not enough data)
//
return 0;
}
//
// compute sum of prev pairs
//
p->Sums.D -= e->D;
p->Sums.T -= e->T;
p->Sums.DT -= e->DT;
p->Sums.TT -= e->TT;
//
// compute new values
//
e->D = DownloadedBytes; // bytes
e->T = GetTickCount () - p->T0; // miliseconds
e->DT = (ULONGLONG)e->D * (ULONGLONG)e->T;
e->TT = (ULONGLONG)e->T * (ULONGLONG)e->T;
//
// compute new sums
//
p->Sums.D += e->D;
p->Sums.T += e->T;
p->Sums.DT += e->DT;
p->Sums.TT += e->TT;
//
// adjust count and index
//
if (p->Count < MAX_INDEX) {
p->Count++;
}
p->Index++;
if (p->Index == MAX_INDEX) {
p->Index = 0;
}
//
// compute new download rate, in bytes/milisec
//
div = p->Sums.TT * (ULONGLONG)p->Count - (ULONGLONG)p->Sums.T * (ULONGLONG)p->Sums.T;
if (div) {
r = (DWORD)
((p->Sums.DT * (ULONGLONG)p->Count - (ULONGLONG)p->Sums.D * (ULONGLONG)p->Sums.T) *
1000 / div / 1024);
}
//
// now estimate remaining time based on the difference and this rate
// assume there's always something more to download (never 0)
//
remTimeSec = 1;
if (r) {
remTimeSec += (TotalBytesToDownload - DownloadedBytes) / r / 1000;
}
#ifdef DOWNLOAD_DETAILS
//
// log this for debug purposes
//
DynUpdtDebugLog (
Winnt32LogDetailedInformation,
TEXT("%1!5u!%2!10u!%3!10u!%4!10u!%5!10u!"),
0,
p->Count,
e->T,
e->D,
r * 8,
remTimeSec
);
#endif
if (KbPerSec) {
*KbPerSec = r;
}
return remTimeSec;
}