mirror of
https://github.com/rn10950/RetroZilla.git
synced 2024-11-15 04:00:12 +01:00
2440 lines
79 KiB
C
2440 lines
79 KiB
C
/* -*- Mode: C; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
|
/* ***** BEGIN LICENSE BLOCK *****
|
|
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
|
*
|
|
* The contents of this file are subject to the Mozilla Public License Version
|
|
* 1.1 (the "License"); you may not use this file except in compliance with
|
|
* the License. You may obtain a copy of the License at
|
|
* http://www.mozilla.org/MPL/
|
|
*
|
|
* Software distributed under the License is distributed on an "AS IS" basis,
|
|
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
|
* for the specific language governing rights and limitations under the
|
|
* License.
|
|
*
|
|
* The Original Code is Mozilla Communicator client code, released
|
|
* March 31, 1998.
|
|
*
|
|
* The Initial Developer of the Original Code is
|
|
* Netscape Communications Corporation.
|
|
* Portions created by the Initial Developer are Copyright (C) 1998
|
|
* the Initial Developer. All Rights Reserved.
|
|
*
|
|
* Contributor(s):
|
|
* Sean Su <ssu@netscape.com>
|
|
* Curt Patrick <curt@netscape.com>
|
|
* Ben Goodger <ben@mozilla.org>
|
|
* Masayuki Nakano <masayuki@d-toybox.com>
|
|
*
|
|
* Alternatively, the contents of this file may be used under the terms of
|
|
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
|
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
|
* in which case the provisions of the GPL or the LGPL are applicable instead
|
|
* of those above. If you wish to allow use of your version of this file only
|
|
* under the terms of either the GPL or the LGPL, and not to allow others to
|
|
* use your version of this file under the terms of the MPL, indicate your
|
|
* decision by deleting the provisions above and replace them with the notice
|
|
* and other provisions required by the GPL or the LGPL. If you do not delete
|
|
* the provisions above, a recipient may use your version of this file under
|
|
* the terms of any one of the MPL, the GPL or the LGPL.
|
|
*
|
|
* ***** END LICENSE BLOCK ***** */
|
|
|
|
// needed to build with mingw
|
|
#ifndef _WIN32_IE
|
|
#define _WIN32_IE 0x0500
|
|
#endif
|
|
|
|
#include "extern.h"
|
|
#include "extra.h"
|
|
#include "dialogs.h"
|
|
#include "ifuncns.h"
|
|
#include "xpistub.h"
|
|
#include "xpi.h"
|
|
#include "logging.h"
|
|
#include <shlobj.h>
|
|
#include <shellapi.h>
|
|
#include <objidl.h>
|
|
#include <logkeys.h>
|
|
#include <prsht.h>
|
|
|
|
// commdlg.h is needed to build with WIN32_LEAN_AND_MEAN
|
|
#include <commdlg.h>
|
|
|
|
// re-define PSH_WIZARD97 as per latest Platform SDK (below)
|
|
#ifdef PSH_WIZARD97
|
|
#undef PSH_WIZARD97
|
|
#endif
|
|
|
|
#if (_WIN32_IE >= 0x0400)
|
|
//----- New flags for wizard97 -----------
|
|
#if (_WIN32_IE < 0x0500)
|
|
#define PSH_WIZARD97 0x00002000
|
|
#else
|
|
#define PSH_WIZARD97 0x01000000
|
|
#endif
|
|
#endif
|
|
|
|
#ifndef CSIDL_PROGRAM_FILES
|
|
#define CSIDL_PROGRAM_FILES 0x0026
|
|
#endif // CSIDL_PROGRAM_FILES
|
|
|
|
// Turn off default to safe upgrade for 0.8... until we can guarantee that we won't be deleting other files.
|
|
#define DEFAULT_SAFE_UPGRADE FALSE
|
|
|
|
static WNDPROC OldListBoxWndProc;
|
|
static WNDPROC OldDialogWndProc;
|
|
static DWORD gdwACFlag;
|
|
static BOOL gDidShowUpgradePanel;
|
|
|
|
// function prototype
|
|
LRESULT CALLBACK NewDialogWndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
// INSTALL WIZARD SEQUENCER
|
|
//
|
|
|
|
void InitSequence(HINSTANCE hInstance)
|
|
{
|
|
// Wizard data structures
|
|
PROPSHEETPAGE psp;
|
|
HPROPSHEETPAGE pages[11] = {0};
|
|
PROPSHEETHEADER psh;
|
|
int count = 0;
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// Create the Wizard Sequence
|
|
//
|
|
psp.dwSize = sizeof(psp);
|
|
psp.hInstance = hSetupRscInst;
|
|
psp.lParam = 0;
|
|
|
|
// Welcome Page
|
|
if (diWelcome.bShowDialog) {
|
|
psp.dwFlags = PSP_DEFAULT|PSP_HIDEHEADER;
|
|
psp.pfnDlgProc = DlgProcWelcome;
|
|
psp.pszTemplate = MAKEINTRESOURCE(DLG_WELCOME);
|
|
|
|
pages[count++] = CreatePropertySheetPage(&psp);
|
|
}
|
|
|
|
// License Page
|
|
if (diLicense.bShowDialog) {
|
|
psp.dwFlags = PSP_DEFAULT|PSP_USEHEADERTITLE|PSP_USEHEADERSUBTITLE;
|
|
psp.pszHeaderTitle = diLicense.szTitle;
|
|
psp.pszHeaderSubTitle = diLicense.szSubTitle;
|
|
psp.pfnDlgProc = DlgProcLicense;
|
|
psp.pszTemplate = MAKEINTRESOURCE(DLG_LICENSE);
|
|
|
|
pages[count++] = CreatePropertySheetPage(&psp);
|
|
}
|
|
|
|
// License Page
|
|
if (diSetupType.bShowDialog) {
|
|
psp.dwFlags = PSP_DEFAULT|PSP_USEHEADERTITLE|PSP_USEHEADERSUBTITLE;
|
|
psp.pszHeaderTitle = diSetupType.szTitle;
|
|
psp.pszHeaderSubTitle = diSetupType.szSubTitle;
|
|
psp.pfnDlgProc = DlgProcSetupType;
|
|
psp.pszTemplate = MAKEINTRESOURCE(DLG_SETUP_TYPE);
|
|
|
|
pages[count++] = CreatePropertySheetPage(&psp);
|
|
}
|
|
|
|
if (diSelectInstallPath.bShowDialog) {
|
|
psp.dwFlags = PSP_DEFAULT|PSP_USEHEADERTITLE|PSP_USEHEADERSUBTITLE;
|
|
psp.pszHeaderTitle = diSelectInstallPath.szTitle;
|
|
psp.pszHeaderSubTitle = diSelectInstallPath.szSubTitle;
|
|
psp.pfnDlgProc = DlgProcSelectInstallPath;
|
|
psp.pszTemplate = MAKEINTRESOURCE(DLG_SELECT_INSTALL_PATH);
|
|
|
|
pages[count++] = CreatePropertySheetPage(&psp);
|
|
}
|
|
|
|
if (diUpgrade.bShowDialog) {
|
|
psp.dwFlags = PSP_DEFAULT|PSP_USEHEADERTITLE|PSP_USEHEADERSUBTITLE;
|
|
psp.pszHeaderTitle = diUpgrade.szTitle;
|
|
psp.pszHeaderSubTitle = diUpgrade.szSubTitle;
|
|
psp.pfnDlgProc = DlgProcUpgrade;
|
|
psp.pszTemplate = MAKEINTRESOURCE(DLG_UPGRADE);
|
|
|
|
pages[count++] = CreatePropertySheetPage(&psp);
|
|
}
|
|
else {
|
|
// If we're not showing the Upgrade dialog, we need to set some state to
|
|
// tell the installer to default to a Safe Install.
|
|
|
|
sgProduct.doCleanupOnUpgrade = DEFAULT_SAFE_UPGRADE;
|
|
}
|
|
|
|
if (diSelectComponents.bShowDialog) {
|
|
psp.dwFlags = PSP_DEFAULT|PSP_USEHEADERTITLE|PSP_USEHEADERSUBTITLE;
|
|
psp.pszHeaderTitle = diSelectComponents.szTitle;
|
|
psp.pszHeaderSubTitle = diSelectComponents.szSubTitle;
|
|
psp.pfnDlgProc = DlgProcSelectComponents;
|
|
psp.pszTemplate = MAKEINTRESOURCE(DLG_SELECT_COMPONENTS);
|
|
|
|
pages[count++] = CreatePropertySheetPage(&psp);
|
|
}
|
|
|
|
// Windows Integration Page
|
|
if (diWindowsIntegration.bShowDialog) {
|
|
psp.dwFlags = PSP_DEFAULT|PSP_USEHEADERTITLE|PSP_USEHEADERSUBTITLE;
|
|
psp.pszHeaderTitle = diWindowsIntegration.szTitle;
|
|
psp.pszHeaderSubTitle = diWindowsIntegration.szSubTitle;
|
|
psp.pfnDlgProc = DlgProcWindowsIntegration;
|
|
psp.pszTemplate = MAKEINTRESOURCE(DLG_WINDOWS_INTEGRATION);
|
|
|
|
pages[count++] = CreatePropertySheetPage(&psp);
|
|
}
|
|
|
|
if (diStartInstall.bShowDialog) {
|
|
psp.dwFlags = PSP_DEFAULT|PSP_USEHEADERTITLE|PSP_USEHEADERSUBTITLE;
|
|
psp.pszHeaderTitle = diStartInstall.szTitle;
|
|
psp.pszHeaderSubTitle = diStartInstall.szSubTitle;
|
|
psp.pfnDlgProc = DlgProcSummary;
|
|
psp.pszTemplate = MAKEINTRESOURCE(DLG_START_INSTALL);
|
|
|
|
pages[count++] = CreatePropertySheetPage(&psp);
|
|
}
|
|
|
|
if (diDownloading.bShowDialog) {
|
|
psp.dwFlags = PSP_DEFAULT|PSP_USEHEADERTITLE|PSP_USEHEADERSUBTITLE;
|
|
psp.pszHeaderTitle = diDownloading.szTitle;
|
|
psp.pszHeaderSubTitle = diDownloading.szSubTitle;
|
|
psp.pfnDlgProc = DlgProcDownloading;
|
|
psp.pszTemplate = MAKEINTRESOURCE(DLG_DOWNLOADING);
|
|
|
|
pages[count++] = CreatePropertySheetPage(&psp);
|
|
}
|
|
|
|
if (diInstalling.bShowDialog) {
|
|
psp.dwFlags = PSP_DEFAULT|PSP_USEHEADERTITLE|PSP_USEHEADERSUBTITLE;
|
|
psp.pszHeaderTitle = diInstalling.szTitle;
|
|
psp.pszHeaderSubTitle = diInstalling.szSubTitle;
|
|
psp.pfnDlgProc = DlgProcInstalling;
|
|
psp.pszTemplate = MAKEINTRESOURCE(DLG_EXTRACTING);
|
|
|
|
pages[count++] = CreatePropertySheetPage(&psp);
|
|
}
|
|
|
|
// Successful Install Page
|
|
if (diInstallSuccessful.bShowDialog) {
|
|
psp.dwFlags = PSP_DEFAULT|PSP_HIDEHEADER;
|
|
psp.pfnDlgProc = DlgProcInstallSuccessful;
|
|
psp.pszTemplate = MAKEINTRESOURCE(DLG_INSTALL_SUCCESSFUL);
|
|
|
|
pages[count++] = CreatePropertySheetPage(&psp);
|
|
}
|
|
|
|
// Property Sheet
|
|
psh.dwSize = sizeof(psh);
|
|
psh.hInstance = hSetupRscInst;
|
|
psh.hwndParent = NULL;
|
|
psh.phpage = pages;
|
|
psh.dwFlags = PSH_WIZARD97|PSH_HEADER;
|
|
psh.pszbmHeader = MAKEINTRESOURCE(IDB_HEADER);
|
|
psh.nStartPage = 0;
|
|
psh.nPages = count;
|
|
|
|
|
|
// Start the Wizard.
|
|
if (psh.nPages > 1) {
|
|
PropertySheet(&psh);
|
|
} else {
|
|
if (psh.nPages == 1) {
|
|
// Auto install
|
|
CreateDialog(hSetupRscInst, MAKEINTRESOURCE(DLG_EXTRACTING), NULL, DlgProcInstalling);
|
|
} else {
|
|
// Silent install
|
|
InstallFiles(NULL);
|
|
}
|
|
|
|
gbIgnoreRunAppX = TRUE;
|
|
// Apply settings and close.
|
|
if (sgProduct.bInstallFiles)
|
|
UpdateJSProxyInfo();
|
|
|
|
/* POST_SMARTUPDATE process file manipulation functions */
|
|
ProcessFileOpsForAll(T_POST_SMARTUPDATE);
|
|
|
|
if (sgProduct.bInstallFiles) {
|
|
/* PRE_LAUNCHAPP process file manipulation functions */
|
|
ProcessFileOpsForAll(T_PRE_LAUNCHAPP);
|
|
|
|
LaunchApps();
|
|
|
|
// Refresh system icons if necessary
|
|
if (gSystemInfo.bRefreshIcons)
|
|
RefreshIcons();
|
|
|
|
UnsetSetupState(); // clear setup state
|
|
if (!gbIgnoreProgramFolderX)
|
|
ProcessProgramFolderShowCmd();
|
|
|
|
CleanupArgsRegistry();
|
|
CleanupPreviousVersionRegKeys();
|
|
|
|
/* POST_LAUNCHAPP process file manipulation functions */
|
|
ProcessFileOpsForAll(T_POST_LAUNCHAPP);
|
|
/* DEPEND_REBOOT process file manipulation functions */
|
|
ProcessFileOpsForAll(T_DEPEND_REBOOT);
|
|
}
|
|
}
|
|
}
|
|
|
|
HFONT MakeFont(TCHAR* aFaceName, int aFontSize, LONG aWeight)
|
|
{
|
|
// Welcome Page Header font data
|
|
NONCLIENTMETRICS ncm = {0};
|
|
LOGFONT lf;
|
|
HDC hDC;
|
|
|
|
ncm.cbSize = sizeof(ncm);
|
|
SystemParametersInfo(SPI_GETNONCLIENTMETRICS, 0, &ncm, 0);
|
|
|
|
if (aFaceName)
|
|
lstrcpy(lf.lfFaceName, aFaceName);
|
|
|
|
lf = ncm.lfMessageFont;
|
|
lf.lfWeight = aWeight;
|
|
|
|
hDC = GetDC(NULL);
|
|
lf.lfHeight = 0 - GetDeviceCaps(hDC, LOGPIXELSY) * aFontSize / 72;
|
|
ReleaseDC(NULL, hDC);
|
|
|
|
return CreateFontIndirect(&lf);
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
// DIALOG: EXIT SETUP
|
|
//
|
|
|
|
BOOL ShouldExitSetup(HWND hDlg)
|
|
{
|
|
char szDlgQuitTitle[MAX_BUF];
|
|
char szDlgQuitMsg[MAX_BUF];
|
|
char szMsg[MAX_BUF];
|
|
BOOL rv = FALSE;
|
|
|
|
if (sgProduct.mode != SILENT && sgProduct.mode != AUTO) {
|
|
if (!GetPrivateProfileString("Messages", "DLGQUITTITLE", "", szDlgQuitTitle,
|
|
sizeof(szDlgQuitTitle), szFileIniInstall) ||
|
|
!GetPrivateProfileString("Messages", "DLGQUITMSG", "", szDlgQuitMsg,
|
|
sizeof(szDlgQuitMsg), szFileIniInstall))
|
|
PostQuitMessage(1);
|
|
|
|
|
|
rv = MessageBox(GetParent(hDlg), szDlgQuitMsg, szDlgQuitTitle,
|
|
MB_YESNO | MB_ICONQUESTION | MB_DEFBUTTON2 | MB_APPLMODAL |
|
|
MB_SETFOREGROUND) == IDYES;
|
|
}
|
|
else {
|
|
GetConfigIniProfileString("Strings", "Message Cancel Setup AUTO mode",
|
|
"", szMsg, sizeof(szMsg));
|
|
ShowMessage(szMsg, TRUE);
|
|
Delay(5);
|
|
ShowMessage(szMsg, FALSE);
|
|
rv = TRUE;
|
|
}
|
|
|
|
if (!rv)
|
|
SetWindowLong(hDlg, DWL_MSGRESULT, (LONG)TRUE);
|
|
|
|
return rv;
|
|
}
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
// DIALOG: WELCOME
|
|
//
|
|
|
|
LRESULT CALLBACK DlgProcWelcome(HWND hDlg, UINT msg, WPARAM wParam, LONG lParam)
|
|
{
|
|
char szBuf[MAX_BUF];
|
|
LPNMHDR notifyMessage;
|
|
|
|
switch(msg) {
|
|
case WM_INITDIALOG:
|
|
// UI Text, from localized config files
|
|
wsprintf(szBuf, diWelcome.szMessageWelcome, sgProduct.szProductName);
|
|
SetDlgItemText(hDlg, IDC_STATIC_TITLE, szBuf);
|
|
wsprintf(szBuf, diWelcome.szMessage0, sgProduct.szProductName);
|
|
SetDlgItemText(hDlg, IDC_STATIC0, szBuf);
|
|
SetDlgItemText(hDlg, IDC_STATIC1, diWelcome.szMessage1);
|
|
SetDlgItemText(hDlg, IDC_STATIC2, diWelcome.szMessage2);
|
|
wsprintf(szBuf, diWelcome.szMessage3, sgProduct.szProductName);
|
|
SetDlgItemText(hDlg, IDC_STATIC3, szBuf);
|
|
|
|
// The header on the welcome page uses another font.
|
|
SendDlgItemMessage(hDlg, IDC_STATIC_TITLE, WM_SETFONT, (WPARAM)sgInstallGui.welcomeTitleFont, 0L);
|
|
|
|
SendDlgItemMessage(hDlg, IDC_STATIC0, WM_SETFONT, (WPARAM)sgInstallGui.definedFont, 0L);
|
|
SendDlgItemMessage(hDlg, IDC_STATIC1, WM_SETFONT, (WPARAM)sgInstallGui.definedFont, 0L);
|
|
SendDlgItemMessage(hDlg, IDC_STATIC2, WM_SETFONT, (WPARAM)sgInstallGui.definedFont, 0L);
|
|
SendDlgItemMessage(hDlg, IDC_STATIC3, WM_SETFONT, (WPARAM)sgInstallGui.definedFont, 0L);
|
|
|
|
// Subclass dialog to paint all static controls white.
|
|
OldDialogWndProc = SubclassWindow(hDlg, (WNDPROC)NewDialogWndProc);
|
|
break;
|
|
|
|
case WM_NOTIFY:
|
|
notifyMessage = (LPNMHDR)lParam;
|
|
switch (notifyMessage->code) {
|
|
case PSN_SETACTIVE:
|
|
// Wizard dialog title
|
|
PropSheet_SetTitle(GetParent(hDlg), 0, (LPTSTR)diWelcome.szTitle);
|
|
|
|
PropSheet_SetWizButtons(GetParent(hDlg), PSWIZB_NEXT);
|
|
break;
|
|
|
|
case PSN_QUERYCANCEL:
|
|
return !ShouldExitSetup(hDlg);
|
|
}
|
|
break;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
// DIALOG: LICENSE
|
|
//
|
|
|
|
LRESULT CALLBACK DlgProcLicense(HWND hDlg, UINT msg, WPARAM wParam, LONG lParam)
|
|
{
|
|
char szBuf[MAX_BUF];
|
|
LPSTR szLicenseFilenameBuf = NULL;
|
|
WIN32_FIND_DATA wfdFindFileData;
|
|
DWORD dwFileSize;
|
|
DWORD dwBytesRead;
|
|
HANDLE hFLicense;
|
|
FILE *fLicense;
|
|
LPNMHDR notifyMessage;
|
|
|
|
switch(msg) {
|
|
case WM_INITDIALOG:
|
|
SetDlgItemText(hDlg, IDC_MESSAGE0, diLicense.szMessage0);
|
|
SetDlgItemText(hDlg, IDC_RADIO_ACCEPT, diLicense.szRadioAccept);
|
|
SetDlgItemText(hDlg, IDC_RADIO_DECLINE, diLicense.szRadioDecline);
|
|
|
|
SendDlgItemMessage(hDlg, IDC_MESSAGE0, WM_SETFONT, (WPARAM)sgInstallGui.definedFont, 0L);
|
|
SendDlgItemMessage(hDlg, IDC_RADIO_ACCEPT, WM_SETFONT, (WPARAM)sgInstallGui.definedFont, 0L);
|
|
SendDlgItemMessage(hDlg, IDC_RADIO_DECLINE, WM_SETFONT, (WPARAM)sgInstallGui.definedFont, 0L);
|
|
|
|
// Check the "Decline" Radio button by default.
|
|
CheckDlgButton(hDlg, IDC_RADIO_DECLINE, BST_CHECKED);
|
|
SendMessage(GetDlgItem(hDlg, IDC_RADIO_DECLINE), BM_SETCHECK, BST_CHECKED, 0);
|
|
SendDlgItemMessage(hDlg, IDC_RADIO_DECLINE, WM_SETFONT, (WPARAM)sgInstallGui.definedFont, 0L);
|
|
|
|
// License Text
|
|
lstrcpy(szBuf, szSetupDir);
|
|
AppendBackSlash(szBuf, sizeof(szBuf));
|
|
lstrcat(szBuf, diLicense.szLicenseFilename);
|
|
|
|
if((hFLicense = FindFirstFile(szBuf, &wfdFindFileData)) != INVALID_HANDLE_VALUE)
|
|
{
|
|
dwFileSize = (wfdFindFileData.nFileSizeHigh * MAXDWORD) + wfdFindFileData.nFileSizeLow + 1;
|
|
FindClose(hFLicense);
|
|
if((szLicenseFilenameBuf = NS_GlobalAlloc(dwFileSize)) != NULL)
|
|
{
|
|
if((fLicense = fopen(szBuf, "rb")) != NULL)
|
|
{
|
|
dwBytesRead = fread(szLicenseFilenameBuf, sizeof(char), dwFileSize, fLicense);
|
|
fclose(fLicense);
|
|
SetDlgItemText(hDlg, IDC_EDIT_LICENSE, szLicenseFilenameBuf);
|
|
}
|
|
|
|
FreeMemory(&szLicenseFilenameBuf);
|
|
}
|
|
}
|
|
SendDlgItemMessage(hDlg, IDC_EDIT_LICENSE, WM_SETFONT, (WPARAM)sgInstallGui.systemFont, 0L);
|
|
break;
|
|
|
|
case WM_COMMAND:
|
|
switch (wParam) {
|
|
case IDC_RADIO_ACCEPT:
|
|
PropSheet_SetWizButtons(GetParent(hDlg), PSWIZB_NEXT|PSWIZB_BACK);
|
|
break;
|
|
case IDC_RADIO_DECLINE:
|
|
PropSheet_SetWizButtons(GetParent(hDlg), PSWIZB_BACK);
|
|
break;
|
|
}
|
|
break;
|
|
|
|
case WM_NOTIFY:
|
|
notifyMessage = (LPNMHDR)lParam;
|
|
switch (notifyMessage->code) {
|
|
case PSN_SETACTIVE:
|
|
// Wizard dialog title
|
|
PropSheet_SetTitle(GetParent(hDlg), 0, (LPTSTR)diLicense.szTitle);
|
|
|
|
if (IsDlgButtonChecked(hDlg, IDC_RADIO_DECLINE) == BST_CHECKED)
|
|
PropSheet_SetWizButtons(GetParent(hDlg), PSWIZB_BACK);
|
|
else
|
|
PropSheet_SetWizButtons(GetParent(hDlg), PSWIZB_NEXT|PSWIZB_BACK);
|
|
|
|
SendDlgItemMessage(hDlg, IDC_EDIT_LICENSE, EM_SETSEL, 0, 0);
|
|
|
|
break;
|
|
|
|
case PSN_QUERYCANCEL:
|
|
return !ShouldExitSetup(hDlg);
|
|
}
|
|
break;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
// DIALOG: SETUP TYPE
|
|
//
|
|
|
|
LRESULT CALLBACK DlgProcSetupType(HWND hDlg, UINT msg, WPARAM wParam, LONG lParam)
|
|
{
|
|
HWND hRadioSt0, hStaticSt0, hRadioSt1, hStaticSt1;
|
|
LPNMHDR notifyMessage;
|
|
BOOL skipNext = FALSE;
|
|
static char defaultPath[MAX_BUF];
|
|
|
|
hRadioSt0 = GetDlgItem(hDlg, IDC_RADIO_ST0);
|
|
hStaticSt0 = GetDlgItem(hDlg, IDC_STATIC_ST0_DESCRIPTION);
|
|
hRadioSt1 = GetDlgItem(hDlg, IDC_RADIO_ST1);
|
|
hStaticSt1 = GetDlgItem(hDlg, IDC_STATIC_ST1_DESCRIPTION);
|
|
|
|
switch(msg) {
|
|
case WM_INITDIALOG:
|
|
lstrcpy(defaultPath, sgProduct.szPath);
|
|
|
|
SetDlgItemText(hDlg, IDC_STATIC_MSG0, diSetupType.szMessage0);
|
|
SendDlgItemMessage(hDlg, IDC_STATIC_MSG0, WM_SETFONT, (WPARAM)sgInstallGui.definedFont, 0L);
|
|
|
|
if(diSetupType.stSetupType0.bVisible) {
|
|
SetDlgItemText(hDlg, IDC_RADIO_ST0, diSetupType.stSetupType0.szDescriptionShort);
|
|
SetDlgItemText(hDlg, IDC_STATIC_ST0_DESCRIPTION, diSetupType.stSetupType0.szDescriptionLong);
|
|
SendDlgItemMessage(hDlg, IDC_RADIO_ST0, WM_SETFONT, (WPARAM)sgInstallGui.definedFont, 0L);
|
|
SendDlgItemMessage(hDlg, IDC_STATIC_ST0_DESCRIPTION, WM_SETFONT, (WPARAM)sgInstallGui.definedFont, 0L);
|
|
ShowWindow(hRadioSt0, SW_SHOW);
|
|
ShowWindow(hStaticSt0, SW_SHOW);
|
|
}
|
|
else {
|
|
ShowWindow(hRadioSt0, SW_HIDE);
|
|
ShowWindow(hStaticSt0, SW_HIDE);
|
|
}
|
|
|
|
if(diSetupType.stSetupType1.bVisible) {
|
|
SetDlgItemText(hDlg, IDC_RADIO_ST1, diSetupType.stSetupType1.szDescriptionShort);
|
|
SetDlgItemText(hDlg, IDC_STATIC_ST1_DESCRIPTION, diSetupType.stSetupType1.szDescriptionLong);
|
|
SendDlgItemMessage(hDlg, IDC_RADIO_ST1, WM_SETFONT, (WPARAM)sgInstallGui.definedFont, 0L);
|
|
SendDlgItemMessage(hDlg, IDC_STATIC_ST1_DESCRIPTION, WM_SETFONT, (WPARAM)sgInstallGui.definedFont, 0L);
|
|
ShowWindow(hRadioSt1, SW_SHOW);
|
|
ShowWindow(hStaticSt1, SW_SHOW);
|
|
}
|
|
else {
|
|
ShowWindow(hRadioSt1, SW_HIDE);
|
|
ShowWindow(hStaticSt1, SW_HIDE);
|
|
}
|
|
|
|
break;
|
|
|
|
case WM_NOTIFY:
|
|
notifyMessage = (LPNMHDR)lParam;
|
|
|
|
switch (notifyMessage->code) {
|
|
case PSN_SETACTIVE:
|
|
// Wizard dialog title
|
|
PropSheet_SetTitle(GetParent(hDlg), 0, (LPTSTR)diSetupType.szTitle);
|
|
|
|
PropSheet_SetWizButtons(GetParent(hDlg), PSWIZB_NEXT|PSWIZB_BACK);
|
|
|
|
switch(dwTempSetupType) {
|
|
case ST_RADIO0:
|
|
CheckDlgButton(hDlg, IDC_RADIO_ST0, BST_CHECKED);
|
|
SetFocus(hRadioSt0);
|
|
break;
|
|
|
|
case ST_RADIO1:
|
|
CheckDlgButton(hDlg, IDC_RADIO_ST1, BST_CHECKED);
|
|
SetFocus(hRadioSt1);
|
|
break;
|
|
}
|
|
break;
|
|
|
|
case PSN_WIZNEXT:
|
|
case PSN_WIZBACK:
|
|
// retrieve and save the state of the selected radio button
|
|
if(IsDlgButtonChecked(hDlg, IDC_RADIO_ST0) == BST_CHECKED)
|
|
dwSetupType = ST_RADIO0;
|
|
else if(IsDlgButtonChecked(hDlg, IDC_RADIO_ST1) == BST_CHECKED)
|
|
dwSetupType = ST_RADIO1;
|
|
SiCNodeSetItemsSelected(dwSetupType);
|
|
|
|
dwTempSetupType = dwSetupType;
|
|
|
|
// If the user has selected "Standard" (easy install) no further data
|
|
// collection is required, go right to the end.
|
|
if (notifyMessage->code == PSN_WIZNEXT &&
|
|
dwSetupType == ST_RADIO0) {
|
|
// Reset the path to the default value.
|
|
lstrcpy(sgProduct.szPath, defaultPath);
|
|
|
|
CheckForUpgrade(hDlg, DLG_START_INSTALL);
|
|
skipNext = TRUE;
|
|
}
|
|
|
|
break;
|
|
|
|
case PSN_QUERYCANCEL:
|
|
return !ShouldExitSetup(hDlg);
|
|
}
|
|
|
|
break;
|
|
}
|
|
|
|
return skipNext;
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
// DIALOG: SELECT INSTALL PATH
|
|
//
|
|
|
|
#ifndef BIF_USENEWUI
|
|
// BIF_USENEWUI isn't defined in the platform SDK that comes with
|
|
// MSVC6.0.
|
|
#define BIF_USENEWUI 0x50
|
|
#endif
|
|
|
|
int CALLBACK BrowseCallbackProc(HWND hwnd, UINT uMsg, LPARAM lParam, LPARAM lpData)
|
|
{
|
|
if (uMsg == BFFM_INITIALIZED)
|
|
{
|
|
char * filePath = (char *) lpData;
|
|
if (filePath)
|
|
{
|
|
SendMessage(hwnd, BFFM_SETSELECTION, TRUE /* true because lpData is a path string */, lpData);
|
|
free(filePath);
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
void BrowseForDirectory(HWND hParent)
|
|
{
|
|
LPITEMIDLIST itemIDList;
|
|
BROWSEINFO browseInfo;
|
|
char currDir[MAX_PATH];
|
|
|
|
if(SHGetSpecialFolderLocation(hParent, CSIDL_PROGRAM_FILES, &itemIDList) == S_OK)
|
|
SHGetPathFromIDList(itemIDList, (LPTSTR) currDir);
|
|
else
|
|
strncpy(currDir, "C:\\", sizeof(currDir));
|
|
|
|
browseInfo.hwndOwner = hParent;
|
|
browseInfo.pidlRoot = NULL;
|
|
browseInfo.pszDisplayName = currDir;
|
|
browseInfo.lpszTitle = sgInstallGui.szBrowseInfo;
|
|
browseInfo.ulFlags = BIF_USENEWUI | BIF_RETURNONLYFSDIRS;
|
|
browseInfo.lpfn = NULL;
|
|
browseInfo.lParam = 0;
|
|
|
|
if (currDir[0]) {
|
|
browseInfo.lParam = (LPARAM) strdup(currDir);
|
|
browseInfo.lpfn = &BrowseCallbackProc;
|
|
}
|
|
else
|
|
browseInfo.lParam = 0;
|
|
|
|
// Show the dialog
|
|
itemIDList = SHBrowseForFolder(&browseInfo);
|
|
|
|
if (itemIDList) {
|
|
if (SHGetPathFromIDList(itemIDList, currDir)) {
|
|
InitPathDisplay(hParent, currDir, IDC_FOLDER_ICON, IDC_EDIT_DESTINATION);
|
|
|
|
SetCurrentDirectory(currDir);
|
|
|
|
lstrcpy(szTempSetupPath, currDir);
|
|
}
|
|
|
|
#if 0
|
|
// XXXben LEAK!!!! but this code won't compile for some unknown reason-
|
|
// "Free is not a member of IMalloc, see objidl.h for details"
|
|
// but that's a bald-faced lie!
|
|
// The shell allocated an ITEMIDLIST, we need to free it.
|
|
// I guess we'll just leak shell objects for now :-D
|
|
LPMALLOC shellMalloc;
|
|
if (SUCCEEDED(SHGetMalloc(&shellMalloc))) {
|
|
shellMalloc->Free(itemIDList);
|
|
shellMalloc->Release();
|
|
}
|
|
#endif
|
|
}
|
|
}
|
|
|
|
void RecoverFromPathError(HWND aPanel)
|
|
{
|
|
// Reset the displayed path to the previous, valid value.
|
|
InitPathDisplay(aPanel, sgProduct.szPath, IDC_FOLDER_ICON, IDC_EDIT_DESTINATION);
|
|
|
|
// Reset the temporary path string so we don't get stuck receiving
|
|
// the error message.
|
|
lstrcpy(szTempSetupPath, sgProduct.szPath);
|
|
|
|
// Prevent the Wizard from advancing because of this error.
|
|
SetWindowLong(aPanel, DWL_MSGRESULT, -1);
|
|
}
|
|
|
|
void CheckForUpgrade(HWND aPanel, int aNextPanel)
|
|
{
|
|
char buf[MAX_BUF];
|
|
int nextPanel = aNextPanel;
|
|
|
|
// Check to see if we should show the "Safe Upgrade" dialog
|
|
// The second part of the test is to see if the flag in config.ini
|
|
// specifies whether or not this should be shown *specifically* in the
|
|
// "Easy Install" mode. If that flag is set to FALSE, the Upgrade
|
|
// panel is shown only in the "Custom"/"Advanced" pass.
|
|
if (sgProduct.checkCleanupOnUpgrade &&
|
|
!(dwSetupType == ST_RADIO0 && !diUpgrade.bShowInEasyInstall) &&
|
|
!(dwSetupType == ST_RADIO1 && !diUpgrade.bShowDialog)) {
|
|
|
|
// Found destination folder. check to see if we're upgrading ontop
|
|
// of a previous installation. If so, we need to prompt the user
|
|
// about removing the entire dir before installation happens.
|
|
MozCopyStr(sgProduct.szPath, buf, sizeof(buf));
|
|
AppendBackSlash(buf, sizeof(buf));
|
|
lstrcat(buf, sgProduct.szProgramName);
|
|
if (FileExists(buf)) {
|
|
// Prompt user if deleting target path is okay. Only show
|
|
// prompt if the setup is running in normal mode, else
|
|
// assume user wants deletion.
|
|
if(sgProduct.mode == NORMAL)
|
|
nextPanel = DLG_UPGRADE;
|
|
else {
|
|
sgProduct.doCleanupOnUpgrade = DEFAULT_SAFE_UPGRADE;
|
|
nextPanel = aNextPanel;
|
|
}
|
|
}
|
|
else
|
|
nextPanel = aNextPanel;
|
|
}
|
|
|
|
/* SiCNodeSetItemsSelected() is called from within DlgProcUpgrade().
|
|
* If DlgProcUpgrade is not called (in the case of a !NORMAL install),
|
|
* then we need to call it here. */
|
|
if (sgProduct.mode != NORMAL)
|
|
SiCNodeSetItemsSelected(dwSetupType);
|
|
|
|
gDidShowUpgradePanel = nextPanel == DLG_UPGRADE;
|
|
|
|
SetWindowLong(aPanel, DWL_MSGRESULT, nextPanel);
|
|
}
|
|
|
|
LRESULT CALLBACK DlgProcSelectInstallPath(HWND hDlg, UINT msg, WPARAM wParam, LONG lParam)
|
|
{
|
|
char szBuf[MAX_BUF];
|
|
char szBufTemp[MAX_BUF];
|
|
LPNMHDR notifyMessage;
|
|
BOOL rv = FALSE;
|
|
|
|
switch(msg) {
|
|
case WM_INITDIALOG:
|
|
SetDlgItemText(hDlg, IDC_STATIC_MSG0, diSelectInstallPath.szMessage0);
|
|
|
|
EnableWindow(GetDlgItem(hDlg, IDC_BUTTON_BROWSE), !sgProduct.bLockPath);
|
|
|
|
SetCurrentDirectory(szTempSetupPath);
|
|
|
|
InitPathDisplay(hDlg, szTempSetupPath, IDC_FOLDER_ICON, IDC_EDIT_DESTINATION);
|
|
|
|
SetDlgItemText(hDlg, IDC_BUTTON_BROWSE, sgInstallGui.szBrowse_);
|
|
|
|
SendDlgItemMessage(hDlg, IDC_STATIC_MSG0, WM_SETFONT, (WPARAM)sgInstallGui.definedFont, 0L);
|
|
SendDlgItemMessage(hDlg, IDC_EDIT_DESTINATION, WM_SETFONT, (WPARAM)sgInstallGui.definedFont, 0L);
|
|
SendDlgItemMessage(hDlg, IDC_BUTTON_BROWSE, WM_SETFONT, (WPARAM)sgInstallGui.definedFont, 0L);
|
|
|
|
break;
|
|
|
|
case WM_COMMAND:
|
|
switch(LOWORD(wParam)) {
|
|
case IDC_BUTTON_BROWSE:
|
|
BrowseForDirectory(hDlg);
|
|
break;
|
|
}
|
|
break;
|
|
|
|
case WM_NOTIFY:
|
|
notifyMessage = (LPNMHDR)lParam;
|
|
|
|
switch (notifyMessage->code) {
|
|
case PSN_SETACTIVE:
|
|
// Wizard dialog title
|
|
PropSheet_SetTitle(GetParent(hDlg), 0, (LPTSTR)diSelectInstallPath.szTitle);
|
|
|
|
PropSheet_SetWizButtons(GetParent(hDlg), PSWIZB_NEXT|PSWIZB_BACK);
|
|
|
|
break;
|
|
|
|
case PSN_WIZNEXT:
|
|
/* Make sure that the path is not within the windows dir */
|
|
if(IsPathWithinWindir(szTempSetupPath)) {
|
|
char errorMsg[MAX_BUF];
|
|
char errorMsgTitle[MAX_BUF];
|
|
|
|
GetPrivateProfileString("Messages", "ERROR_PATH_WITHIN_WINDIR",
|
|
"", errorMsg, sizeof(errorMsg), szFileIniInstall);
|
|
GetPrivateProfileString("Messages", "ERROR_MESSAGE_TITLE", "",
|
|
errorMsgTitle, sizeof(errorMsgTitle), szFileIniInstall);
|
|
MessageBox(hDlg, errorMsg, errorMsgTitle, MB_OK | MB_ICONERROR);
|
|
|
|
RecoverFromPathError(hDlg);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
lstrcpy(sgProduct.szPath, szTempSetupPath);
|
|
/* append a backslash to the path because CreateDirectoriesAll()
|
|
uses a backslash to determine directories */
|
|
lstrcpy(szBuf, sgProduct.szPath);
|
|
AppendBackSlash(szBuf, sizeof(szBuf));
|
|
|
|
CheckForUpgrade(hDlg, DLG_SELECT_COMPONENTS);
|
|
|
|
/* Create the path if it does not exist */
|
|
if (FileExists(szBuf) == FALSE) {
|
|
char szBuf2[MAX_PATH];
|
|
|
|
if (CreateDirectoriesAll(szBuf, ADD_TO_UNINSTALL_LOG) != WIZ_OK) {
|
|
char szECreateDirectory[MAX_BUF];
|
|
char szEMessageTitle[MAX_BUF];
|
|
|
|
lstrcpy(szBufTemp, "\n\n");
|
|
lstrcat(szBufTemp, sgProduct.szPath);
|
|
RemoveBackSlash(szBufTemp);
|
|
lstrcat(szBufTemp, "\n\n");
|
|
|
|
if (GetPrivateProfileString("Messages", "ERROR_CREATE_DIRECTORY", "",
|
|
szECreateDirectory, sizeof(szECreateDirectory),
|
|
szFileIniInstall))
|
|
wsprintf(szBuf, szECreateDirectory, szBufTemp);
|
|
|
|
GetPrivateProfileString("Messages", "ERROR_MESSAGE_TITLE", "",
|
|
szEMessageTitle, sizeof(szEMessageTitle),
|
|
szFileIniInstall);
|
|
|
|
MessageBox(hDlg, szBuf, szEMessageTitle, MB_OK | MB_ICONERROR);
|
|
|
|
RecoverFromPathError(hDlg);
|
|
|
|
// Prevent the page change if we failed to create the directory.
|
|
SetWindowLong(hDlg, DWL_MSGRESULT, -1);
|
|
return TRUE;
|
|
}
|
|
|
|
if(*sgProduct.szSubPath != '\0') {
|
|
/* log the subpath for uninstallation. This subpath does not normally get logged
|
|
* for uninstallation due to a chicken and egg problem with creating the log file
|
|
* and the directory its in */
|
|
lstrcpy(szBuf2, szBuf);
|
|
AppendBackSlash(szBuf2, sizeof(szBuf2));
|
|
lstrcat(szBuf2, sgProduct.szSubPath);
|
|
UpdateInstallLog(KEY_CREATE_FOLDER, szBuf2, FALSE);
|
|
}
|
|
|
|
}
|
|
|
|
// Need to return TRUE so we override the default wizard sequence.
|
|
rv = TRUE;
|
|
|
|
break;
|
|
|
|
case PSN_QUERYCANCEL:
|
|
return !ShouldExitSetup(hDlg);
|
|
}
|
|
|
|
break;
|
|
}
|
|
|
|
return rv;
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
// DIALOG: UPGRADE CONFIRMATION
|
|
//
|
|
void UpdateUpgradeModeMessage(HWND aPanel)
|
|
{
|
|
if (IsDlgButtonChecked(aPanel, IDC_CHECK_SAFE_INSTALL) == BST_CHECKED)
|
|
SetDlgItemText(aPanel, IDC_MESSAGE_INFO, diUpgrade.szSafeInstallInfo);
|
|
else
|
|
SetDlgItemText(aPanel, IDC_MESSAGE_INFO, diUpgrade.szUnsafeInstallInfo);
|
|
}
|
|
|
|
LRESULT CALLBACK DlgProcUpgrade(HWND hDlg, UINT msg, WPARAM wParam, LONG lParam)
|
|
{
|
|
LPNMHDR notifyMessage;
|
|
BOOL pathInWinDir = FALSE;
|
|
BOOL rv = FALSE;
|
|
|
|
switch (msg) {
|
|
case WM_INITDIALOG:
|
|
SetDlgItemText(hDlg, IDC_MESSAGE_UPGRADE, diUpgrade.szMessageCleanup);
|
|
SetDlgItemText(hDlg, IDC_CHECK_SAFE_INSTALL, diUpgrade.szCheckboxSafeInstall);
|
|
|
|
SendDlgItemMessage(hDlg, IDC_MESSAGE_UPGRADE, WM_SETFONT, (WPARAM)sgInstallGui.definedFont, 0L);
|
|
SendDlgItemMessage(hDlg, IDC_CHECK_SAFE_INSTALL, WM_SETFONT, (WPARAM)sgInstallGui.definedFont, 0L);
|
|
|
|
// Default to "Safe Upgrade".
|
|
CheckDlgButton(hDlg, IDC_CHECK_SAFE_INSTALL, BST_CHECKED);
|
|
|
|
break;
|
|
|
|
case WM_COMMAND:
|
|
switch (LOWORD(wParam)) {
|
|
case IDC_CHECK_SAFE_INSTALL:
|
|
UpdateUpgradeModeMessage(hDlg);
|
|
|
|
break;
|
|
}
|
|
|
|
break;
|
|
|
|
case WM_NOTIFY:
|
|
notifyMessage = (LPNMHDR)lParam;
|
|
|
|
switch (notifyMessage->code) {
|
|
case PSN_SETACTIVE:
|
|
// Wizard dialog title
|
|
PropSheet_SetTitle(GetParent(hDlg), 0, (LPTSTR)diUpgrade.szTitle);
|
|
|
|
InitPathDisplay(hDlg, sgProduct.szPath, IDC_FOLDER_ICON, IDC_EDIT_DESTINATION);
|
|
|
|
pathInWinDir = IsPathWithinWindir(sgProduct.szPath);
|
|
if(pathInWinDir) {
|
|
// Do not clean up
|
|
sgProduct.doCleanupOnUpgrade = FALSE;
|
|
|
|
// Disable UI and show an explanation.
|
|
EnableWindow(GetDlgItem(hDlg, IDC_CHECK_SAFE_INSTALL), FALSE);
|
|
SetDlgItemText(hDlg, IDC_MESSAGE_INFO, diUpgrade.szNoSafeUpgradeWindir);
|
|
}
|
|
|
|
CheckDlgButton(hDlg, IDC_CHECK_SAFE_INSTALL, sgProduct.doCleanupOnUpgrade ? BST_CHECKED : BST_UNCHECKED);
|
|
|
|
if (!pathInWinDir)
|
|
UpdateUpgradeModeMessage(hDlg);
|
|
|
|
PropSheet_SetWizButtons(GetParent(hDlg), PSWIZB_NEXT|PSWIZB_BACK);
|
|
|
|
break;
|
|
|
|
case PSN_WIZNEXT:
|
|
if (dwSetupType == ST_RADIO0) {
|
|
SetWindowLong(hDlg, DWL_MSGRESULT, DLG_START_INSTALL);
|
|
rv = TRUE;
|
|
}
|
|
|
|
sgProduct.doCleanupOnUpgrade = IsDlgButtonChecked(hDlg, IDC_CHECK_SAFE_INSTALL) == BST_CHECKED;
|
|
|
|
SiCNodeSetItemsSelected(dwSetupType);
|
|
|
|
break;
|
|
|
|
case PSN_WIZBACK:
|
|
if (dwSetupType == ST_RADIO0) {
|
|
SetWindowLong(hDlg, DWL_MSGRESULT, DLG_SETUP_TYPE);
|
|
rv = TRUE;
|
|
}
|
|
|
|
sgProduct.doCleanupOnUpgrade = IsDlgButtonChecked(hDlg, IDC_CHECK_SAFE_INSTALL) == BST_CHECKED;
|
|
|
|
SiCNodeSetItemsSelected(dwSetupType);
|
|
|
|
break;
|
|
|
|
case PSN_QUERYCANCEL:
|
|
return !ShouldExitSetup(hDlg);
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
return rv;
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
// DIALOG: SELECT COMPONENTS
|
|
//
|
|
|
|
void DrawLBText(LPDRAWITEMSTRUCT lpdis, DWORD dwACFlag)
|
|
{
|
|
siC *siCTemp = NULL;
|
|
TCHAR tchBuffer[MAX_BUF];
|
|
TEXTMETRIC tm;
|
|
DWORD y;
|
|
|
|
siCTemp = SiCNodeGetObject(lpdis->itemID, FALSE, dwACFlag);
|
|
if(siCTemp != NULL)
|
|
{
|
|
SendMessage(lpdis->hwndItem, LB_GETTEXT, lpdis->itemID, (LPARAM)tchBuffer);
|
|
|
|
if((lpdis->itemAction & ODA_FOCUS) && (lpdis->itemState & ODS_SELECTED))
|
|
{
|
|
// remove the focus rect on the previous selected item
|
|
DrawFocusRect(lpdis->hDC, &(lpdis->rcItem));
|
|
}
|
|
|
|
siCTemp = SiCNodeGetObject(lpdis->itemID, FALSE, dwACFlag);
|
|
if(lpdis->itemAction & ODA_FOCUS)
|
|
{
|
|
if((lpdis->itemState & ODS_SELECTED) &&
|
|
!(lpdis->itemState & ODS_FOCUS))
|
|
{
|
|
if(siCTemp->dwAttributes & SIC_DISABLED)
|
|
SetTextColor(lpdis->hDC, GetSysColor(COLOR_GRAYTEXT));
|
|
else
|
|
{
|
|
SetTextColor(lpdis->hDC, GetSysColor(COLOR_WINDOWTEXT));
|
|
SetBkColor(lpdis->hDC, GetSysColor(COLOR_WINDOW));
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if(siCTemp->dwAttributes & SIC_DISABLED)
|
|
SetTextColor(lpdis->hDC, GetSysColor(COLOR_GRAYTEXT));
|
|
else
|
|
{
|
|
SetTextColor(lpdis->hDC, GetSysColor(COLOR_HIGHLIGHTTEXT));
|
|
SetBkColor(lpdis->hDC, GetSysColor(COLOR_HIGHLIGHT));
|
|
}
|
|
}
|
|
}
|
|
else if(lpdis->itemAction & ODA_DRAWENTIRE)
|
|
{
|
|
if(siCTemp->dwAttributes & SIC_DISABLED)
|
|
SetTextColor(lpdis->hDC, GetSysColor(COLOR_GRAYTEXT));
|
|
else
|
|
SetTextColor(lpdis->hDC, GetSysColor(COLOR_WINDOWTEXT));
|
|
}
|
|
|
|
// If a screen reader is being used we want to redraw the text whether
|
|
// it has focus or not because the text changes whenever the checkbox
|
|
// changes.
|
|
if( gSystemInfo.bScreenReader || (lpdis->itemAction & (ODA_DRAWENTIRE | ODA_FOCUS)) )
|
|
{
|
|
// Display the text associated with the item.
|
|
GetTextMetrics(lpdis->hDC, &tm);
|
|
y = (lpdis->rcItem.bottom + lpdis->rcItem.top - tm.tmHeight) / 2;
|
|
|
|
ExtTextOut(lpdis->hDC,
|
|
CX_CHECKBOX + 5,
|
|
y,
|
|
ETO_OPAQUE | ETO_CLIPPED,
|
|
&(lpdis->rcItem),
|
|
tchBuffer,
|
|
strlen(tchBuffer),
|
|
NULL);
|
|
}
|
|
}
|
|
}
|
|
|
|
void DrawCheck(LPDRAWITEMSTRUCT lpdis, DWORD dwACFlag)
|
|
{
|
|
siC *siCTemp = NULL;
|
|
HDC hdcMem;
|
|
HBITMAP hbmpCheckBox;
|
|
|
|
siCTemp = SiCNodeGetObject(lpdis->itemID, FALSE, dwACFlag);
|
|
if(siCTemp != NULL)
|
|
{
|
|
if(!(siCTemp->dwAttributes & SIC_SELECTED))
|
|
/* Component is not selected. Use the unchecked bitmap regardless if the
|
|
* component is disabled or not. The unchecked bitmap looks the same if
|
|
* it's disabled or enabled. */
|
|
hbmpCheckBox = hbmpBoxUnChecked;
|
|
else if(siCTemp->dwAttributes & SIC_DISABLED)
|
|
/* Component is checked and disabled */
|
|
hbmpCheckBox = hbmpBoxCheckedDisabled;
|
|
else
|
|
/* Component is checked and enabled */
|
|
hbmpCheckBox = hbmpBoxChecked;
|
|
|
|
SendMessage(lpdis->hwndItem, LB_SETITEMDATA, lpdis->itemID, (LPARAM)hbmpCheckBox);
|
|
if((hdcMem = CreateCompatibleDC(lpdis->hDC)) != NULL)
|
|
{
|
|
SelectObject(hdcMem, hbmpCheckBox);
|
|
|
|
// BitBlt() is used to prepare the checkbox icon into the list box item's device context.
|
|
// The SendMessage() function using LB_SETITEMDATA performs the drawing.
|
|
BitBlt(lpdis->hDC,
|
|
lpdis->rcItem.left + 2,
|
|
lpdis->rcItem.top + 2,
|
|
lpdis->rcItem.right - lpdis->rcItem.left,
|
|
lpdis->rcItem.bottom - lpdis->rcItem.top,
|
|
hdcMem,
|
|
0,
|
|
0,
|
|
SRCCOPY);
|
|
|
|
DeleteDC(hdcMem);
|
|
}
|
|
}
|
|
}
|
|
|
|
void lbAddItem(HWND hList, siC *siCComponent)
|
|
{
|
|
DWORD dwItem;
|
|
TCHAR tchBuffer[MAX_BUF];
|
|
|
|
lstrcpy(tchBuffer, siCComponent->szDescriptionShort);
|
|
if(gSystemInfo.bScreenReader)
|
|
{
|
|
lstrcat(tchBuffer, " - ");
|
|
if(!(siCComponent->dwAttributes & SIC_SELECTED))
|
|
lstrcat(tchBuffer, sgInstallGui.szUnchecked);
|
|
else
|
|
lstrcat(tchBuffer, sgInstallGui.szChecked);
|
|
}
|
|
dwItem = SendMessage(hList, LB_ADDSTRING, 0, (LPARAM)tchBuffer);
|
|
|
|
if(siCComponent->dwAttributes & SIC_DISABLED)
|
|
SendMessage(hList, LB_SETITEMDATA, dwItem, (LPARAM)hbmpBoxCheckedDisabled);
|
|
else if(siCComponent->dwAttributes & SIC_SELECTED)
|
|
SendMessage(hList, LB_SETITEMDATA, dwItem, (LPARAM)hbmpBoxChecked);
|
|
else
|
|
SendMessage(hList, LB_SETITEMDATA, dwItem, (LPARAM)hbmpBoxUnChecked);
|
|
}
|
|
|
|
void InvalidateLBCheckbox(HWND hwndListBox)
|
|
{
|
|
RECT rcCheckArea;
|
|
|
|
// retrieve the rectangle of all list items to update.
|
|
GetClientRect(hwndListBox, &rcCheckArea);
|
|
|
|
// Set the right coordinate of the rectangle to be the same
|
|
// as the right edge of the bitmap drawn.
|
|
// But if a screen reader is being used we want to redraw the text
|
|
// as well as the checkbox so we do not set the right coordinate.
|
|
if(!gSystemInfo.bScreenReader)
|
|
rcCheckArea.right = CX_CHECKBOX;
|
|
|
|
// It then invalidates the checkbox region to be redrawn.
|
|
// Invalidating the region sends a WM_DRAWITEM message to
|
|
// the dialog, which redraws the region given the
|
|
// node attirbute, in this case it is a bitmap of a
|
|
// checked/unchecked checkbox.
|
|
InvalidateRect(hwndListBox, &rcCheckArea, TRUE);
|
|
}
|
|
|
|
void ToggleCheck(HWND hwndListBox, DWORD dwIndex, DWORD dwACFlag)
|
|
{
|
|
BOOL bMoreToResolve;
|
|
LPSTR szToggledReferenceName = NULL;
|
|
DWORD dwAttributes;
|
|
|
|
// Checks to see if the checkbox is checked or not checked, and
|
|
// toggles the node attributes appropriately.
|
|
dwAttributes = SiCNodeGetAttributes(dwIndex, FALSE, dwACFlag);
|
|
if(!(dwAttributes & SIC_DISABLED))
|
|
{
|
|
if(dwAttributes & SIC_SELECTED)
|
|
{
|
|
SiCNodeSetAttributes(dwIndex, SIC_SELECTED, FALSE, FALSE, dwACFlag, hwndListBox);
|
|
|
|
szToggledReferenceName = SiCNodeGetReferenceName(dwIndex, FALSE, dwACFlag);
|
|
ResolveDependees(szToggledReferenceName, hwndListBox);
|
|
}
|
|
else
|
|
{
|
|
SiCNodeSetAttributes(dwIndex, SIC_SELECTED, TRUE, FALSE, dwACFlag, hwndListBox);
|
|
bMoreToResolve = ResolveDependencies(dwIndex, hwndListBox);
|
|
|
|
while(bMoreToResolve)
|
|
bMoreToResolve = ResolveDependencies(-1, hwndListBox);
|
|
|
|
szToggledReferenceName = SiCNodeGetReferenceName(dwIndex, FALSE, dwACFlag);
|
|
ResolveDependees(szToggledReferenceName, hwndListBox);
|
|
}
|
|
|
|
InvalidateLBCheckbox(hwndListBox);
|
|
}
|
|
}
|
|
|
|
// ************************************************************************
|
|
// FUNCTION : SubclassWindow( HWND, WNDPROC )
|
|
// PURPOSE : Subclasses a window procedure
|
|
// COMMENTS : Returns the old window procedure
|
|
// ************************************************************************
|
|
WNDPROC SubclassWindow( HWND hWnd, WNDPROC NewWndProc)
|
|
{
|
|
WNDPROC OldWndProc;
|
|
|
|
OldWndProc = (WNDPROC)GetWindowLong(hWnd, GWL_WNDPROC);
|
|
SetWindowLong(hWnd, GWL_WNDPROC, (LONG) NewWndProc);
|
|
|
|
return OldWndProc;
|
|
}
|
|
|
|
// ************************************************************************
|
|
// FUNCTION : NewDialogWndProc( HWND, UINT, WPARAM, LPARAM )
|
|
// PURPOSE : Processes messages for the Welcome and Finish dialogs.
|
|
// COMMENTS : Paints all static control backgrounds in white.
|
|
// ************************************************************************
|
|
LRESULT CALLBACK NewDialogWndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
|
|
{
|
|
switch(uMsg)
|
|
{
|
|
case WM_CTLCOLORSTATIC:
|
|
return (HRESULT)GetStockObject(WHITE_BRUSH);
|
|
}
|
|
|
|
return(CallWindowProc(OldDialogWndProc, hWnd, uMsg, wParam, lParam));
|
|
}
|
|
|
|
// ************************************************************************
|
|
// FUNCTION : NewListBoxWndProc( HWND, UINT, WPARAM, LPARAM )
|
|
// PURPOSE : Processes messages for "LISTBOX" class.
|
|
// COMMENTS : Prevents the user from moving the window
|
|
// by dragging the titlebar.
|
|
// ************************************************************************
|
|
LRESULT CALLBACK NewListBoxWndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
|
|
{
|
|
DWORD dwPosX;
|
|
DWORD dwPosY;
|
|
DWORD dwIndex;
|
|
|
|
switch(uMsg)
|
|
{
|
|
case WM_CHAR:
|
|
/* check for the space key */
|
|
if((TCHAR)wParam == 32)
|
|
{
|
|
dwIndex = SendMessage(hWnd,
|
|
LB_GETCURSEL,
|
|
0,
|
|
0);
|
|
ToggleCheck(hWnd, dwIndex, gdwACFlag);
|
|
}
|
|
break;
|
|
|
|
case WM_LBUTTONDOWN:
|
|
if(wParam == MK_LBUTTON)
|
|
{
|
|
dwPosX = LOWORD(lParam); // x pos
|
|
dwPosY = HIWORD(lParam); // y pos
|
|
|
|
if((dwPosX > 1) && (dwPosX <= CX_CHECKBOX))
|
|
{
|
|
dwIndex = LOWORD(SendMessage(hWnd,
|
|
LB_ITEMFROMPOINT,
|
|
0,
|
|
(LPARAM)MAKELPARAM(dwPosX, dwPosY)));
|
|
ToggleCheck(hWnd, dwIndex, gdwACFlag);
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
|
|
return(CallWindowProc(OldListBoxWndProc, hWnd, uMsg, wParam, lParam));
|
|
}
|
|
|
|
LRESULT CALLBACK DlgProcSelectComponents(HWND hDlg, UINT msg, WPARAM wParam, LONG lParam)
|
|
{
|
|
siC *siCTemp;
|
|
DWORD dwIndex;
|
|
DWORD dwItems = MAX_BUF;
|
|
HWND hwndLBComponents;
|
|
LPDRAWITEMSTRUCT lpdis;
|
|
#ifdef STUB_INSTALLER
|
|
TCHAR tchBuffer[MAX_BUF];
|
|
ULONGLONG ullDSBuf;
|
|
char szBuf[MAX_BUF];
|
|
#endif
|
|
|
|
LPNMHDR notifyMessage;
|
|
|
|
hwndLBComponents = GetDlgItem(hDlg, IDC_LIST_COMPONENTS);
|
|
|
|
switch(msg) {
|
|
case WM_INITDIALOG:
|
|
SetDlgItemText(hDlg, IDC_MESSAGE0, diSelectComponents.szMessage0);
|
|
SendDlgItemMessage(hDlg, IDC_MESSAGE0, WM_SETFONT, (WPARAM)sgInstallGui.definedFont, 0L);
|
|
|
|
siCTemp = siComponents;
|
|
if(siCTemp != NULL)
|
|
{
|
|
if((!(siCTemp->dwAttributes & SIC_INVISIBLE)) && (!(siCTemp->dwAttributes & SIC_ADDITIONAL)))
|
|
lbAddItem(hwndLBComponents, siCTemp);
|
|
|
|
siCTemp = siCTemp->Next;
|
|
while((siCTemp != siComponents) && (siCTemp != NULL))
|
|
{
|
|
if((!(siCTemp->dwAttributes & SIC_INVISIBLE)) && (!(siCTemp->dwAttributes & SIC_ADDITIONAL)))
|
|
lbAddItem(hwndLBComponents, siCTemp);
|
|
|
|
siCTemp = siCTemp->Next;
|
|
}
|
|
SetFocus(hwndLBComponents);
|
|
SendMessage(hwndLBComponents, LB_SETCURSEL, 0, 0);
|
|
SetDlgItemText(hDlg, IDC_STATIC_DESCRIPTION, SiCNodeGetDescriptionLong(0, FALSE, AC_COMPONENTS));
|
|
SendDlgItemMessage(hDlg, IDC_STATIC_DESCRIPTION, WM_SETFONT, (WPARAM)sgInstallGui.definedFont, 0L);
|
|
}
|
|
|
|
SetDlgItemText(hDlg, IDC_STATIC1, sgInstallGui.szComponents_);
|
|
SetDlgItemText(hDlg, IDC_STATIC2, sgInstallGui.szDescription);
|
|
|
|
SendDlgItemMessage(hDlg, IDC_STATIC1, WM_SETFONT, (WPARAM)sgInstallGui.definedFont, 0L);
|
|
SendDlgItemMessage(hDlg, IDC_STATIC2, WM_SETFONT, (WPARAM)sgInstallGui.definedFont, 0L);
|
|
|
|
#ifdef STUB_INSTALLER
|
|
// XXXben We don't support net stub installs yet.
|
|
SetDlgItemText(hDlg, IDC_STATIC_DOWNLOAD_SIZE, sgInstallGui.szTotalDownloadSize);
|
|
SendDlgItemMessage(hDlg, IDC_STATIC_DOWNLOAD_SIZE, WM_SETFONT, (WPARAM)sgInstallGui.definedFont, 0L);
|
|
#endif
|
|
|
|
SendDlgItemMessage(hDlg, IDC_LIST_COMPONENTS, WM_SETFONT, (WPARAM)sgInstallGui.systemFont, 0L);
|
|
|
|
gdwACFlag = AC_COMPONENTS;
|
|
OldListBoxWndProc = SubclassWindow(hwndLBComponents, (WNDPROC)NewListBoxWndProc);
|
|
|
|
break;
|
|
|
|
case WM_DRAWITEM:
|
|
lpdis = (LPDRAWITEMSTRUCT)lParam;
|
|
|
|
// If there are no list box items, skip this message.
|
|
if(lpdis->itemID == -1)
|
|
break;
|
|
|
|
DrawLBText(lpdis, AC_COMPONENTS);
|
|
DrawCheck(lpdis, AC_COMPONENTS);
|
|
|
|
// draw the focus rect on the selected item
|
|
if((lpdis->itemAction & ODA_FOCUS) &&
|
|
(lpdis->itemState & ODS_FOCUS))
|
|
DrawFocusRect(lpdis->hDC, &(lpdis->rcItem));
|
|
|
|
break;
|
|
|
|
case WM_COMMAND:
|
|
switch(LOWORD(wParam)) {
|
|
case IDC_LIST_COMPONENTS:
|
|
/* to update the long description for each component the user selected */
|
|
if((dwIndex = SendMessage(hwndLBComponents, LB_GETCURSEL, 0, 0)) != LB_ERR) {
|
|
SetDlgItemText(hDlg, IDC_STATIC_DESCRIPTION, SiCNodeGetDescriptionLong(dwIndex, FALSE, AC_COMPONENTS));
|
|
|
|
#ifdef STUB_INSTALLER
|
|
// update the disk space required info in the dialog. It is already
|
|
// in Kilobytes
|
|
ullDSBuf = GetDiskSpaceRequired(DSR_DOWNLOAD_SIZE);
|
|
_ui64toa(ullDSBuf, tchBuffer, 10);
|
|
wsprintf(szBuf, sgInstallGui.szDownloadSize, tchBuffer);
|
|
|
|
// XXXben We don't support net stub installs yet.
|
|
// SetDlgItemText(hDlg, IDC_STATIC_DOWNLOAD_SIZE, szBuf);
|
|
#endif
|
|
}
|
|
|
|
break;
|
|
}
|
|
break;
|
|
|
|
case WM_NOTIFY:
|
|
notifyMessage = (LPNMHDR)lParam;
|
|
|
|
switch (notifyMessage->code) {
|
|
case PSN_SETACTIVE:
|
|
// Wizard dialog title
|
|
PropSheet_SetTitle(GetParent(hDlg), 0, (LPTSTR)diSelectComponents.szTitle);
|
|
|
|
PropSheet_SetWizButtons(GetParent(hDlg), PSWIZB_NEXT|PSWIZB_BACK);
|
|
|
|
break;
|
|
|
|
case PSN_WIZBACK:
|
|
// If we showed the "Upgrade" panel, be sure to show it again in the sequence
|
|
// on the way back, to not do so "feels" wrong/confusing.
|
|
if (gDidShowUpgradePanel)
|
|
SetWindowLong(hDlg, DWL_MSGRESULT, DLG_UPGRADE);
|
|
else
|
|
SetWindowLong(hDlg, DWL_MSGRESULT, DLG_SELECT_INSTALL_PATH);
|
|
|
|
return TRUE;
|
|
break;
|
|
|
|
case PSN_QUERYCANCEL:
|
|
return !ShouldExitSetup(hDlg);
|
|
}
|
|
|
|
break;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
// DIALOG: SUMMARY
|
|
//
|
|
|
|
BOOL IsSelectableComponent(siC* aComponent)
|
|
{
|
|
return !(aComponent->dwAttributes & SIC_INVISIBLE) &&
|
|
!(aComponent->dwAttributes & SIC_ADDITIONAL);
|
|
}
|
|
|
|
BOOL IsComponentSelected(siC* aComponent)
|
|
{
|
|
return aComponent->dwAttributes & SIC_SELECTED;
|
|
}
|
|
|
|
void GetRelativeRect(HWND aWindow, int aResourceID, RECT* aRect)
|
|
{
|
|
HWND ctrl;
|
|
POINT pt;
|
|
|
|
ctrl = GetDlgItem(aWindow, aResourceID);
|
|
|
|
GetWindowRect(ctrl, aRect);
|
|
|
|
pt.x = aRect->left;
|
|
pt.y = aRect->top;
|
|
ScreenToClient(aWindow, &pt);
|
|
aRect->left = pt.x;
|
|
aRect->top = pt.y;
|
|
|
|
pt.x = aRect->right;
|
|
pt.y = aRect->bottom;
|
|
ScreenToClient(aWindow, &pt);
|
|
aRect->right = pt.x;
|
|
aRect->bottom = pt.y;
|
|
}
|
|
|
|
void PositionControl(HWND aWindow, int aResourceIDRelative, int aResourceIDControl, int aOffset)
|
|
{
|
|
HWND ctrl;
|
|
RECT r1, r2;
|
|
|
|
GetRelativeRect(aWindow, aResourceIDRelative, &r1);
|
|
GetRelativeRect(aWindow, aResourceIDControl, &r2);
|
|
|
|
ctrl = GetDlgItem(aWindow, aResourceIDControl);
|
|
SetWindowPos(ctrl, NULL, r2.left, r1.bottom + aOffset, -1, -1, SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE);
|
|
}
|
|
|
|
|
|
LRESULT CALLBACK DlgProcSummary(HWND hDlg, UINT msg, WPARAM wParam, LONG lParam)
|
|
{
|
|
LPSTR szMessage = NULL;
|
|
LPNMHDR notifyMessage;
|
|
char szAddtlComps[MAX_BUF];
|
|
char szTemp[MAX_BUF];
|
|
char szFormat[MAX_BUF_TINY];
|
|
BOOL hasAddtlComps = FALSE;
|
|
BOOL skipNext = FALSE;
|
|
siC *currComponent, *mainComponent;
|
|
HICON largeIcon, smallIcon;
|
|
DWORD result;
|
|
HKEY theKey;
|
|
|
|
switch(msg) {
|
|
case WM_INITDIALOG:
|
|
SetDlgItemText(hDlg, IDC_MESSAGE1, diStartInstall.szMessage0);
|
|
SetDlgItemText(hDlg, IDC_MESSAGE2, sgInstallGui.szProxyMessage);
|
|
SetDlgItemText(hDlg, IDC_CONNECTION_SETTINGS, sgInstallGui.szProxyButton);
|
|
SetDlgItemText(hDlg, IDC_INSTALL_FOLDER_LABEL, sgInstallGui.szInstallFolder);
|
|
|
|
SendDlgItemMessage(hDlg, IDC_MESSAGE0, WM_SETFONT, (WPARAM)sgInstallGui.definedFont, 0L);
|
|
SendDlgItemMessage(hDlg, IDC_MESSAGE1, WM_SETFONT, (WPARAM)sgInstallGui.definedFont, 0L);
|
|
SendDlgItemMessage(hDlg, IDC_MESSAGE2, WM_SETFONT, (WPARAM)sgInstallGui.definedFont, 0L);
|
|
SendDlgItemMessage(hDlg, IDC_CONNECTION_SETTINGS, WM_SETFONT, (WPARAM)sgInstallGui.definedFont, 0L);
|
|
SendDlgItemMessage(hDlg, IDC_INSTALL_FOLDER_LABEL, WM_SETFONT, (WPARAM)sgInstallGui.definedFont, 0L);
|
|
SendDlgItemMessage(hDlg, IDC_INSTALL_FOLDER, WM_SETFONT, (WPARAM)sgInstallGui.definedFont, 0L);
|
|
SendDlgItemMessage(hDlg, IDC_PRIMARY_COMPONENT, WM_SETFONT, (WPARAM)sgInstallGui.definedFont, 0L);
|
|
SendDlgItemMessage(hDlg, IDC_OPTIONAL_COMPONENTS, WM_SETFONT, (WPARAM)sgInstallGui.definedFont, 0L);
|
|
|
|
ExtractIconEx("setuprsc.dll", 1, &largeIcon, &smallIcon, 1);
|
|
SendMessage(GetDlgItem(hDlg, IDC_APP_ICON), STM_SETICON, (LPARAM)smallIcon, 0);
|
|
|
|
break;
|
|
|
|
case WM_NOTIFY:
|
|
notifyMessage = (LPNMHDR)lParam;
|
|
|
|
switch (notifyMessage->code) {
|
|
case PSN_SETACTIVE:
|
|
// Wizard dialog title
|
|
PropSheet_SetTitle(GetParent(hDlg), 0, (LPTSTR)diSelectComponents.szTitle);
|
|
|
|
// Set the user-determined fields here in case they go back and change
|
|
// options - WM_INITDIALOG only gets called once, not every time the
|
|
// panel is displayed.
|
|
|
|
#ifdef STUB_INSTALLER
|
|
// Update strings that relate to whether or not files will be downloaded.
|
|
// The user may have selected additional components that require a download.
|
|
if ((diAdvancedSettings.bShowDialog == FALSE) || (GetTotalArchivesToDownload() == 0)) {
|
|
#endif
|
|
SetDlgItemText(hDlg, IDC_MESSAGE0, diStartInstall.szMessageInstall);
|
|
|
|
// Hide Download-related UI:
|
|
ShowWindow(GetDlgItem(hDlg, IDC_MESSAGE2), SW_HIDE);
|
|
ShowWindow(GetDlgItem(hDlg, IDC_CONNECTION_SETTINGS), SW_HIDE);
|
|
#ifdef STUB_INSTALLER
|
|
}
|
|
else
|
|
SetDlgItemText(hDlg, IDC_MESSAGE0, diStartInstall.szMessageDownload);
|
|
#endif
|
|
|
|
// Update the registry keys that the installer scripts use to determine
|
|
// what shortcuts to create
|
|
result = RegCreateKeyEx(HKEY_CURRENT_USER, diWindowsIntegration.szRegistryKey, 0, NULL,
|
|
0, KEY_READ | KEY_WRITE, NULL, &theKey, NULL);
|
|
if (result == ERROR_SUCCESS) {
|
|
RegSetValueEx(theKey, "Create Desktop Shortcut", 0, REG_DWORD,
|
|
(LPBYTE)&(diWindowsIntegration.wiCB0.bCheckBoxState),
|
|
sizeof(DWORD));
|
|
RegSetValueEx(theKey, "Create Start Menu Shortcut", 0, REG_DWORD,
|
|
(LPBYTE)&(diWindowsIntegration.wiCB1.bCheckBoxState),
|
|
sizeof(DWORD));
|
|
RegSetValueEx(theKey, "Create Quick Launch Shortcut", 0, REG_DWORD,
|
|
(LPBYTE)&(diWindowsIntegration.wiCB2.bCheckBoxState),
|
|
sizeof(DWORD));
|
|
RegCloseKey(theKey);
|
|
}
|
|
|
|
// Show the components we're going to install
|
|
szAddtlComps[0] = '\0';
|
|
currComponent = siComponents;
|
|
do {
|
|
if (!currComponent)
|
|
break;
|
|
|
|
if (currComponent->dwAttributes & SIC_MAIN_COMPONENT)
|
|
mainComponent = currComponent;
|
|
else if (IsSelectableComponent(currComponent) &&
|
|
IsComponentSelected(currComponent)) {
|
|
wsprintf(szFormat, "%s\r\n", sgInstallGui.szAddtlCompWrapper);
|
|
wsprintf(szTemp, szFormat, currComponent->szDescriptionShort);
|
|
lstrcat(szAddtlComps, szTemp);
|
|
|
|
hasAddtlComps = TRUE;
|
|
}
|
|
|
|
currComponent = currComponent->Next;
|
|
}
|
|
while (currComponent && currComponent != siComponents);
|
|
|
|
// Update the display to reflect whether or not additional components are going to
|
|
// be installed. If none are, we shift the install folder detail up so that it's
|
|
// neatly under the Primary Component name.
|
|
if (hasAddtlComps) {
|
|
wsprintf(szTemp, sgInstallGui.szPrimCompOthers, mainComponent->szDescriptionShort);
|
|
|
|
ShowWindow(GetDlgItem(hDlg, IDC_OPTIONAL_COMPONENTS), SW_SHOW);
|
|
|
|
SetDlgItemText(hDlg, IDC_OPTIONAL_COMPONENTS, szAddtlComps);
|
|
|
|
PositionControl(hDlg, IDC_OPTIONAL_COMPONENTS, IDC_INSTALL_FOLDER_LABEL, 10);
|
|
}
|
|
else {
|
|
wsprintf(szTemp, sgInstallGui.szPrimCompNoOthers, mainComponent->szDescriptionShort);
|
|
|
|
ShowWindow(GetDlgItem(hDlg, IDC_OPTIONAL_COMPONENTS), SW_HIDE);
|
|
|
|
// Shift the "Install Folder" text up in the "No Components" case
|
|
PositionControl(hDlg, IDC_PRIMARY_COMPONENT, IDC_INSTALL_FOLDER_LABEL, 10);
|
|
}
|
|
PositionControl(hDlg, IDC_INSTALL_FOLDER_LABEL, IDC_INSTALL_FOLDER, 10);
|
|
PositionControl(hDlg, IDC_INSTALL_FOLDER_LABEL, IDC_FOLDER_ICON, 7);
|
|
|
|
SetDlgItemText(hDlg, IDC_PRIMARY_COMPONENT, szTemp);
|
|
|
|
// Update the install folder.
|
|
InitPathDisplay(hDlg, sgProduct.szPath, IDC_FOLDER_ICON, IDC_INSTALL_FOLDER);
|
|
|
|
PropSheet_SetWizButtons(GetParent(hDlg), PSWIZB_NEXT|PSWIZB_BACK);
|
|
|
|
break;
|
|
|
|
case PSN_WIZNEXT:
|
|
SaveUserChanges();
|
|
|
|
if (!IsDownloadRequired()) {
|
|
// No download required, bypass the download step and go directly to
|
|
// the installing stage.
|
|
SetWindowLong(hDlg, DWL_MSGRESULT, DLG_EXTRACTING);
|
|
skipNext = TRUE;
|
|
}
|
|
break;
|
|
|
|
case PSN_WIZBACK:
|
|
// If the user selected Easy Install, go right back to the setup type
|
|
// selection page, bypassing the advanced configuration steps.
|
|
if (dwSetupType == ST_RADIO0) {
|
|
// If we showed the "Upgrade" panel, be sure to show it again in the sequence
|
|
// on the way back, to not do so "feels" wrong/confusing.
|
|
if (gDidShowUpgradePanel)
|
|
SetWindowLong(hDlg, DWL_MSGRESULT, DLG_UPGRADE);
|
|
else
|
|
SetWindowLong(hDlg, DWL_MSGRESULT, DLG_SETUP_TYPE);
|
|
skipNext = TRUE;
|
|
}
|
|
break;
|
|
|
|
case PSN_QUERYCANCEL:
|
|
return !ShouldExitSetup(hDlg);
|
|
}
|
|
break;
|
|
case WM_COMMAND:
|
|
switch(LOWORD(wParam)) {
|
|
case IDC_CONNECTION_SETTINGS:
|
|
break;
|
|
}
|
|
break;
|
|
}
|
|
|
|
return skipNext;
|
|
}
|
|
|
|
void SaveUserChanges()
|
|
{
|
|
char szDestPath[MAX_BUF];
|
|
char szInstallLogFile[MAX_BUF];
|
|
|
|
LogISShared();
|
|
LogISDestinationPath();
|
|
LogISSetupType();
|
|
LogISComponentsSelected();
|
|
LogISComponentsToDownload();
|
|
LogISDiskSpace(gdsnComponentDSRequirement);
|
|
|
|
lstrcpy(szDestPath, sgProduct.szPath);
|
|
if(*sgProduct.szSubPath != '\0')
|
|
{
|
|
AppendBackSlash(szDestPath, sizeof(szDestPath));
|
|
lstrcat(szDestPath, sgProduct.szSubPath);
|
|
}
|
|
AppendBackSlash(szDestPath, sizeof(szDestPath));
|
|
|
|
// Create the destination path here in case it had not been created,
|
|
// as in the case of silent or auto mode installs
|
|
if(CreateDirectoriesAll(szDestPath, ADD_TO_UNINSTALL_LOG) != WIZ_OK)
|
|
{
|
|
char buf[MAX_BUF];
|
|
char errorCreateDir[MAX_BUF];
|
|
char pathToShow[MAX_PATH];
|
|
|
|
// reformat the path to display so that it'll be readable in the
|
|
// error dialog shown
|
|
_snprintf(pathToShow, sizeof(pathToShow), "\"%s\" ", szDestPath);
|
|
pathToShow[sizeof(pathToShow) - 1] = '\0';
|
|
if(GetPrivateProfileString("Messages", "ERROR_CREATE_DIRECTORY", "", errorCreateDir, sizeof(errorCreateDir), szFileIniInstall))
|
|
wsprintf(buf, errorCreateDir, pathToShow);
|
|
assert(*buf != '\0');
|
|
PrintError(buf, ERROR_CODE_HIDE);
|
|
PostQuitMessage(1);
|
|
return;
|
|
}
|
|
|
|
// Set global var, that determines where the log file is to update, to
|
|
// not use the TEMP dir *before* the FileCopy() calls because we want
|
|
// to log the FileCopy() calls to where the log files were copied to.
|
|
// This is possible because the logging, that is done within the
|
|
// FileCopy() function, is done after the actual copy
|
|
//
|
|
gbILUseTemp = FALSE;
|
|
|
|
// copy the install_wizard.log file from the temp\ns_temp dir to
|
|
// the destination dir and use the new destination file to continue
|
|
// logging.
|
|
//
|
|
lstrcpy(szInstallLogFile, szTempDir);
|
|
AppendBackSlash(szInstallLogFile, sizeof(szInstallLogFile));
|
|
lstrcat(szInstallLogFile, FILE_INSTALL_LOG);
|
|
FileCopy(szInstallLogFile, szDestPath, FALSE, FALSE);
|
|
DeleteFile(szInstallLogFile);
|
|
|
|
// copy the install_status.log file from the temp\ns_temp dir to
|
|
// the destination dir and use the new destination file to continue
|
|
// logging.
|
|
//
|
|
lstrcpy(szInstallLogFile, szTempDir);
|
|
AppendBackSlash(szInstallLogFile, sizeof(szInstallLogFile));
|
|
lstrcat(szInstallLogFile, FILE_INSTALL_STATUS_LOG);
|
|
FileCopy(szInstallLogFile, szDestPath, FALSE, FALSE);
|
|
DeleteFile(szInstallLogFile);
|
|
}
|
|
|
|
BOOL IsDownloadRequired()
|
|
{
|
|
DWORD dwIndex0;
|
|
DWORD dwFileCounter;
|
|
siC *siCObject = NULL;
|
|
long result;
|
|
char szFileIdiGetArchives[MAX_BUF];
|
|
char szSection[MAX_BUF];
|
|
char szCorruptedArchiveList[MAX_BUF];
|
|
char szPartiallyDownloadedFilename[MAX_BUF];
|
|
|
|
ZeroMemory(szCorruptedArchiveList, sizeof(szCorruptedArchiveList));
|
|
lstrcpy(szFileIdiGetArchives, szTempDir);
|
|
AppendBackSlash(szFileIdiGetArchives, sizeof(szFileIdiGetArchives));
|
|
lstrcat(szFileIdiGetArchives, FILE_IDI_GETARCHIVES);
|
|
GetSetupCurrentDownloadFile(szPartiallyDownloadedFilename,
|
|
sizeof(szPartiallyDownloadedFilename));
|
|
|
|
gbDownloadTriggered= FALSE;
|
|
result = WIZ_OK;
|
|
dwIndex0 = 0;
|
|
dwFileCounter = 0;
|
|
siCObject = SiCNodeGetObject(dwIndex0, TRUE, AC_ALL);
|
|
|
|
while (siCObject) {
|
|
if (siCObject->dwAttributes & SIC_SELECTED) {
|
|
// If a previous unfinished setup was detected, then
|
|
// include the TEMP dir when searching for archives.
|
|
// Only download jars if not already in the local machine.
|
|
// Also if the last file being downloaded should be resumed.
|
|
// The resume detection is done automatically.
|
|
if ((LocateJar(siCObject, NULL, 0,
|
|
gbPreviousUnfinishedDownload) == AP_NOT_FOUND) ||
|
|
(lstrcmpi(szPartiallyDownloadedFilename,
|
|
siCObject->szArchiveName) == 0)) {
|
|
wsprintf(szSection, "File%d", dwFileCounter);
|
|
|
|
result = AddArchiveToIdiFile(siCObject,
|
|
szSection,
|
|
szFileIdiGetArchives);
|
|
if (result)
|
|
return result;
|
|
|
|
++dwFileCounter;
|
|
}
|
|
}
|
|
|
|
++dwIndex0;
|
|
siCObject = SiCNodeGetObject(dwIndex0, TRUE, AC_ALL);
|
|
}
|
|
|
|
// The existence of the getarchives.idi file determines if there are
|
|
// any archives needed to be downloaded.
|
|
return FileExists(szFileIdiGetArchives);
|
|
}
|
|
|
|
#ifdef STUB_INSTALLER
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
// DIALOG: CONNECTION SETTINGS
|
|
//
|
|
|
|
void SaveDownloadProtocolOption(HWND hDlg)
|
|
{
|
|
if(IsDlgButtonChecked(hDlg, IDC_USE_FTP) == BST_CHECKED)
|
|
diAdditionalOptions.dwUseProtocol = UP_FTP;
|
|
else if(IsDlgButtonChecked(hDlg, IDC_USE_HTTP) == BST_CHECKED)
|
|
diAdditionalOptions.dwUseProtocol = UP_HTTP;
|
|
}
|
|
|
|
LRESULT CALLBACK DlgProcAdvancedSettings(HWND hDlg, UINT msg, WPARAM wParam, LONG lParam)
|
|
{
|
|
char szBuf[MAX_BUF];
|
|
|
|
switch(msg)
|
|
{
|
|
case WM_INITDIALOG:
|
|
SetWindowText(hDlg, diAdvancedSettings.szTitle);
|
|
SetDlgItemText(hDlg, IDC_MESSAGE0, diAdvancedSettings.szMessage0);
|
|
SetDlgItemText(hDlg, IDC_EDIT_PROXY_SERVER, diAdvancedSettings.szProxyServer);
|
|
SetDlgItemText(hDlg, IDC_EDIT_PROXY_PORT, diAdvancedSettings.szProxyPort);
|
|
SetDlgItemText(hDlg, IDC_EDIT_PROXY_USER, diAdvancedSettings.szProxyUser);
|
|
SetDlgItemText(hDlg, IDC_EDIT_PROXY_PASSWD, diAdvancedSettings.szProxyPasswd);
|
|
|
|
GetIniConfigProfileString("Strings", "IDC Use Ftp", "", szBuf, sizeof(szBuf));
|
|
SetDlgItemText(hDlg, IDC_USE_FTP, szBuf);
|
|
GetIniConfigProfileString("Strings", "IDC Use Http", "", szBuf, sizeof(szBuf));
|
|
SetDlgItemText(hDlg, IDC_USE_HTTP, szBuf);
|
|
|
|
SetDlgItemText(hDlg, IDC_STATIC, sgInstallGui.szProxySettings);
|
|
SetDlgItemText(hDlg, IDC_STATIC1, sgInstallGui.szServer);
|
|
SetDlgItemText(hDlg, IDC_STATIC2, sgInstallGui.szPort);
|
|
SetDlgItemText(hDlg, IDC_STATIC3, sgInstallGui.szUserId);
|
|
SetDlgItemText(hDlg, IDC_STATIC4, sgInstallGui.szPassword);
|
|
SetDlgItemText(hDlg, IDWIZNEXT, sgInstallGui.szOk_);
|
|
SetDlgItemText(hDlg, IDCANCEL, sgInstallGui.szCancel_);
|
|
SendDlgItemMessage (hDlg, IDC_STATIC, WM_SETFONT, (WPARAM)sgInstallGui.definedFont, 0L);
|
|
SendDlgItemMessage (hDlg, IDC_STATIC1, WM_SETFONT, (WPARAM)sgInstallGui.definedFont, 0L);
|
|
SendDlgItemMessage (hDlg, IDC_STATIC2, WM_SETFONT, (WPARAM)sgInstallGui.definedFont, 0L);
|
|
SendDlgItemMessage (hDlg, IDC_STATIC3, WM_SETFONT, (WPARAM)sgInstallGui.definedFont, 0L);
|
|
SendDlgItemMessage (hDlg, IDC_STATIC4, WM_SETFONT, (WPARAM)sgInstallGui.definedFont, 0L);
|
|
SendDlgItemMessage (hDlg, IDWIZNEXT, WM_SETFONT, (WPARAM)sgInstallGui.definedFont, 0L);
|
|
SendDlgItemMessage (hDlg, IDCANCEL, WM_SETFONT, (WPARAM)sgInstallGui.definedFont, 0L);
|
|
SendDlgItemMessage (hDlg, IDC_MESSAGE0, WM_SETFONT, (WPARAM)sgInstallGui.definedFont, 0L);
|
|
SendDlgItemMessage (hDlg, IDC_EDIT_PROXY_SERVER, WM_SETFONT, (WPARAM)sgInstallGui.systemFont, 0L);
|
|
SendDlgItemMessage (hDlg, IDC_EDIT_PROXY_PORT, WM_SETFONT, (WPARAM)sgInstallGui.systemFont, 0L);
|
|
SendDlgItemMessage (hDlg, IDC_EDIT_PROXY_USER, WM_SETFONT, (WPARAM)sgInstallGui.systemFont, 0L);
|
|
SendDlgItemMessage (hDlg, IDC_EDIT_PROXY_PASSWD, WM_SETFONT, (WPARAM)sgInstallGui.systemFont, 0L);
|
|
SendDlgItemMessage (hDlg, IDC_USE_FTP, WM_SETFONT, (WPARAM)sgInstallGui.definedFont, 0L);
|
|
SendDlgItemMessage (hDlg, IDC_USE_HTTP, WM_SETFONT, (WPARAM)sgInstallGui.definedFont, 0L);
|
|
|
|
switch(diAdditionalOptions.dwUseProtocol)
|
|
{
|
|
case UP_HTTP:
|
|
CheckDlgButton(hDlg, IDC_USE_FTP, BST_UNCHECKED);
|
|
CheckDlgButton(hDlg, IDC_USE_HTTP, BST_CHECKED);
|
|
break;
|
|
|
|
case UP_FTP:
|
|
default:
|
|
CheckDlgButton(hDlg, IDC_USE_FTP, BST_CHECKED);
|
|
CheckDlgButton(hDlg, IDC_USE_HTTP, BST_UNCHECKED);
|
|
break;
|
|
|
|
}
|
|
|
|
if((diAdditionalOptions.bShowProtocols) && (diAdditionalOptions.bUseProtocolSettings))
|
|
{
|
|
ShowWindow(GetDlgItem(hDlg, IDC_USE_FTP), SW_SHOW);
|
|
ShowWindow(GetDlgItem(hDlg, IDC_USE_HTTP), SW_SHOW);
|
|
}
|
|
else
|
|
{
|
|
ShowWindow(GetDlgItem(hDlg, IDC_USE_FTP), SW_HIDE);
|
|
ShowWindow(GetDlgItem(hDlg, IDC_USE_HTTP), SW_HIDE);
|
|
}
|
|
|
|
break;
|
|
|
|
case WM_COMMAND:
|
|
switch(LOWORD(wParam))
|
|
{
|
|
case IDWIZNEXT:
|
|
/* get the proxy server and port information */
|
|
GetDlgItemText(hDlg, IDC_EDIT_PROXY_SERVER, diAdvancedSettings.szProxyServer, MAX_BUF);
|
|
GetDlgItemText(hDlg, IDC_EDIT_PROXY_PORT, diAdvancedSettings.szProxyPort, MAX_BUF);
|
|
GetDlgItemText(hDlg, IDC_EDIT_PROXY_USER, diAdvancedSettings.szProxyUser, MAX_BUF);
|
|
GetDlgItemText(hDlg, IDC_EDIT_PROXY_PASSWD, diAdvancedSettings.szProxyPasswd, MAX_BUF);
|
|
|
|
SaveDownloadProtocolOption(hDlg);
|
|
DestroyWindow(hDlg);
|
|
break;
|
|
|
|
case IDWIZBACK:
|
|
case IDCANCEL:
|
|
DestroyWindow(hDlg);
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
break;
|
|
}
|
|
return(0);
|
|
}
|
|
#endif
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
// DIALOG: DOWNLOADING FILES
|
|
//
|
|
|
|
LRESULT CALLBACK DlgProcDownloading(HWND hDlg, UINT msg, WPARAM wParam, LONG lParam)
|
|
{
|
|
#ifdef STUB_INSTALLER
|
|
switch(msg)
|
|
{
|
|
case WM_INITDIALOG:
|
|
SetWindowText(hDlg, diDownloading.szTitle);
|
|
|
|
SetDlgItemText(hDlg, IDC_MESSAGE0, diDownloading.szBlurb);
|
|
SetDlgItemText(hDlg, IDC_STATIC0, diDownloading.szFileNameKey);
|
|
SetDlgItemText(hDlg, IDC_STATIC1, diDownloading.szTimeRemainingKey);
|
|
|
|
SendDlgItemMessage(hDlg, IDC_MESSAGE0, WM_SETFONT, (WPARAM)sgInstallGui.definedFont, 0L);
|
|
SendDlgItemMessage(hDlg, IDC_STATIC0, WM_SETFONT, (WPARAM)sgInstallGui.definedFont, 0L);
|
|
SendDlgItemMessage(hDlg, IDC_STATIC1, WM_SETFONT, (WPARAM)sgInstallGui.definedFont, 0L);
|
|
|
|
break;
|
|
|
|
case WM_COMMAND:
|
|
switch(LOWORD(wParam))
|
|
{
|
|
default:
|
|
break;
|
|
}
|
|
break;
|
|
}
|
|
#endif
|
|
|
|
return 0;
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
// DIALOG: INSTALLING FILES
|
|
//
|
|
|
|
#define BTN_CLSNAME_LEN 7
|
|
#define BTN_CANCEL_OFFSET 4
|
|
BOOL CALLBACK DisableCancelButton(HWND aWindow, LPARAM aData)
|
|
{
|
|
static int offset = 0;
|
|
char className[BTN_CLSNAME_LEN];
|
|
char text[MAX_BUF];
|
|
|
|
GetClassName(aWindow, className, BTN_CLSNAME_LEN);
|
|
if (!strcmp(className, "Button") &&
|
|
GetParent(aWindow) == (HWND)aData) {
|
|
GetWindowText(aWindow, text, MAX_BUF-1);
|
|
if (++offset == BTN_CANCEL_OFFSET) {
|
|
offset = 0;
|
|
EnableWindow(aWindow, FALSE);
|
|
return FALSE;
|
|
}
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
LRESULT CALLBACK DlgProcInstalling(HWND hDlg, UINT msg, WPARAM wParam, LONG lParam)
|
|
{
|
|
LPNMHDR notifyMessage;
|
|
static BOOL initialized = FALSE;
|
|
HWND parent = GetParent(hDlg);
|
|
char installStart[MAX_BUF];
|
|
|
|
switch(msg) {
|
|
case WM_INITDIALOG:
|
|
SetWindowText(hDlg, diInstalling.szTitle);
|
|
|
|
SetDlgItemText(hDlg, IDC_STATUS0, diInstalling.szStatusFile);
|
|
SetDlgItemText(hDlg, IDC_STATUS3, diInstalling.szStatusComponent);
|
|
|
|
SendDlgItemMessage(hDlg, IDC_STATUS0, WM_SETFONT, (WPARAM)sgInstallGui.definedFont, 0L);
|
|
SendDlgItemMessage(hDlg, IDC_STATUS3, WM_SETFONT, (WPARAM)sgInstallGui.definedFont, 0L);
|
|
|
|
break;
|
|
|
|
case WM_PAINT:
|
|
if (initialized)
|
|
break;
|
|
|
|
initialized = TRUE;
|
|
|
|
if (InstallFiles(hDlg)) {
|
|
if (sgProduct.mode != AUTO) {
|
|
PropSheet_SetCurSelByID(parent, DLG_INSTALL_SUCCESSFUL);
|
|
}
|
|
break;
|
|
}
|
|
else {
|
|
// XXXben TODO: handle error.
|
|
printf("Files NOT Installed...\n");
|
|
}
|
|
break;
|
|
|
|
case WM_NOTIFY:
|
|
notifyMessage = (LPNMHDR)lParam;
|
|
|
|
switch (notifyMessage->code) {
|
|
case PSN_SETACTIVE:
|
|
// Wizard dialog title
|
|
PropSheet_SetTitle(parent, 0, (LPTSTR)diInstalling.szTitle);
|
|
|
|
GetPrivateProfileString("Messages", "MSG_SMARTUPDATE_START",
|
|
"", installStart,
|
|
sizeof(installStart),
|
|
szFileIniInstall);
|
|
|
|
SetDlgItemText(hDlg, IDC_STATUS0, installStart);
|
|
|
|
if (sgProduct.mode != AUTO) {
|
|
// Disable the Cancel button. This leaves the button disabled for
|
|
// this page (Installing) and the final page (Finish) because it
|
|
// is meaningless and potentially damaging in both places.
|
|
EnumChildWindows(parent, DisableCancelButton, (LPARAM)parent);
|
|
|
|
PropSheet_SetWizButtons(parent, 0);
|
|
}
|
|
|
|
break;
|
|
|
|
case PSN_QUERYCANCEL:
|
|
// Do NOT let the user cancel at this point.
|
|
SetWindowLong(hDlg, DWL_MSGRESULT, (LONG)FALSE);
|
|
return TRUE;
|
|
}
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
BOOL InstallFiles(HWND hDlg)
|
|
{
|
|
HRESULT err;
|
|
|
|
// Clean up old versions of GRE previously installed.
|
|
// These GREs should only be fully uninstalled if they were only
|
|
// being used by the mozilla that we're installing over/ontop of
|
|
// (upgrade scenario).
|
|
// We should only do this type of cleanup if we're about to install'
|
|
// GRE in shared mode.
|
|
//
|
|
// This should only be called when the installer is installing GRE!
|
|
if (IsInstallerProductGRE())
|
|
CleanupOrphanedGREs();
|
|
|
|
if (sgProduct.bInstallFiles) {
|
|
// POST_DOWNLOAD process file manipulation functions
|
|
ProcessFileOpsForAll(T_POST_DOWNLOAD);
|
|
// PRE_XPCOM process file manipulation functions
|
|
ProcessFileOpsForAll(T_PRE_XPCOM);
|
|
|
|
// save the installer files in the local machine
|
|
if (diAdditionalOptions.bSaveInstaller)
|
|
SaveInstallerFiles();
|
|
|
|
if (CheckInstances()) {
|
|
bSDUserCanceled = TRUE;
|
|
CleanupXpcomFile();
|
|
return FALSE;
|
|
}
|
|
|
|
// Remove the previous installation of the product here.
|
|
// This should be done before processing the Xpinstall engine.
|
|
if(sgProduct.doCleanupOnUpgrade) {
|
|
SetSetupState(SETUP_STATE_REMOVING_PREV_INST);
|
|
CleanupOnUpgrade();
|
|
}
|
|
|
|
if(gbDownloadTriggered || gbPreviousUnfinishedDownload)
|
|
SetSetupState(SETUP_STATE_UNPACK_XPCOM);
|
|
|
|
if(ProcessXpinstallEngine() != WIZ_OK) {
|
|
bSDUserCanceled = TRUE;
|
|
CleanupXpcomFile();
|
|
return FALSE;
|
|
}
|
|
|
|
if (gbDownloadTriggered || gbPreviousUnfinishedDownload)
|
|
SetSetupState(SETUP_STATE_INSTALL_XPI); // clears and sets new setup state
|
|
|
|
// POST_XPCOM process file manipulation functions
|
|
ProcessFileOpsForAll(T_POST_XPCOM);
|
|
// PRE_SMARTUPDATE process file manipulation functions
|
|
ProcessFileOpsForAll(T_PRE_SMARTUPDATE);
|
|
|
|
//XXXben TODO - process this return result!
|
|
err = SmartUpdateJars(hDlg);
|
|
}
|
|
else
|
|
err = WIZ_OK;
|
|
|
|
CleanupXpcomFile();
|
|
|
|
return err == WIZ_OK || err == 999;
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
// DIALOG: WINTEGRATION
|
|
// Not actually used yet!
|
|
|
|
LRESULT CALLBACK DlgProcWindowsIntegration(HWND hDlg, UINT msg, WPARAM wParam, LONG lParam)
|
|
{
|
|
LPNMHDR notifyMessage;
|
|
|
|
switch (msg) {
|
|
case WM_INITDIALOG:
|
|
SetDlgItemText(hDlg, IDC_MESSAGE0, diWindowsIntegration.szMessage0);
|
|
SendDlgItemMessage(hDlg, IDC_MESSAGE0, WM_SETFONT, (WPARAM)sgInstallGui.definedFont, 0L);
|
|
|
|
if (diWindowsIntegration.wiCB0.bEnabled) {
|
|
ShowWindow(GetDlgItem(hDlg, IDC_CHECK0), SW_SHOW);
|
|
SetDlgItemText(hDlg, IDC_CHECK0, diWindowsIntegration.wiCB0.szDescription);
|
|
SendDlgItemMessage(hDlg, IDC_CHECK0, WM_SETFONT, (WPARAM)sgInstallGui.definedFont, 0L);
|
|
}
|
|
else
|
|
ShowWindow(GetDlgItem(hDlg, IDC_CHECK0), SW_HIDE);
|
|
|
|
if (diWindowsIntegration.wiCB1.bEnabled) {
|
|
ShowWindow(GetDlgItem(hDlg, IDC_CHECK1), SW_SHOW);
|
|
SetDlgItemText(hDlg, IDC_CHECK1, diWindowsIntegration.wiCB1.szDescription);
|
|
SendDlgItemMessage(hDlg, IDC_CHECK1, WM_SETFONT, (WPARAM)sgInstallGui.definedFont, 0L);
|
|
}
|
|
else
|
|
ShowWindow(GetDlgItem(hDlg, IDC_CHECK1), SW_HIDE);
|
|
|
|
if (diWindowsIntegration.wiCB2.bEnabled) {
|
|
ShowWindow(GetDlgItem(hDlg, IDC_CHECK2), SW_SHOW);
|
|
SetDlgItemText(hDlg, IDC_CHECK2, diWindowsIntegration.wiCB2.szDescription);
|
|
SendDlgItemMessage(hDlg, IDC_CHECK2, WM_SETFONT, (WPARAM)sgInstallGui.definedFont, 0L);
|
|
}
|
|
else
|
|
ShowWindow(GetDlgItem(hDlg, IDC_CHECK2), SW_HIDE);
|
|
|
|
break;
|
|
|
|
case WM_NOTIFY:
|
|
notifyMessage = (LPNMHDR)lParam;
|
|
switch (notifyMessage->code) {
|
|
case PSN_SETACTIVE:
|
|
// Wizard dialog title
|
|
PropSheet_SetTitle(GetParent(hDlg), 0, (LPTSTR)diWindowsIntegration.szTitle);
|
|
|
|
// Restore state from default or cached value.
|
|
CheckDlgButton(hDlg, IDC_CHECK0,
|
|
diWindowsIntegration.wiCB0.bCheckBoxState);
|
|
CheckDlgButton(hDlg, IDC_CHECK1,
|
|
diWindowsIntegration.wiCB1.bCheckBoxState);
|
|
CheckDlgButton(hDlg, IDC_CHECK2,
|
|
diWindowsIntegration.wiCB2.bCheckBoxState);
|
|
|
|
PropSheet_SetWizButtons(GetParent(hDlg), PSWIZB_NEXT|PSWIZB_BACK);
|
|
break;
|
|
|
|
case PSN_WIZNEXT:
|
|
diWindowsIntegration.wiCB0.bCheckBoxState =
|
|
IsDlgButtonChecked(hDlg, IDC_CHECK0) == BST_CHECKED;
|
|
diWindowsIntegration.wiCB1.bCheckBoxState =
|
|
IsDlgButtonChecked(hDlg, IDC_CHECK1) == BST_CHECKED;
|
|
diWindowsIntegration.wiCB2.bCheckBoxState =
|
|
IsDlgButtonChecked(hDlg, IDC_CHECK2) == BST_CHECKED;
|
|
|
|
break;
|
|
|
|
case PSN_QUERYCANCEL:
|
|
return !ShouldExitSetup(hDlg);
|
|
}
|
|
|
|
break;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
// DIALOG: SUCCESSFUL INSTALL
|
|
//
|
|
|
|
LRESULT CALLBACK DlgProcInstallSuccessful(HWND hDlg, UINT msg, WPARAM wParam, LONG lParam)
|
|
{
|
|
char szBuf[MAX_BUF];
|
|
LPNMHDR notifyMessage;
|
|
static BOOL launchAppChecked = TRUE;
|
|
DWORD result;
|
|
|
|
switch(msg) {
|
|
case WM_INITDIALOG:
|
|
// UI Text, from localized config files
|
|
SetDlgItemText(hDlg, IDC_STATIC_TITLE, diInstallSuccessful.szMessageHeader);
|
|
wsprintf(szBuf, diInstallSuccessful.szMessage0, sgProduct.szProductName);
|
|
SetDlgItemText(hDlg, IDC_STATIC0, szBuf);
|
|
SetDlgItemText(hDlg, IDC_STATIC1, diInstallSuccessful.szMessage1);
|
|
wsprintf(szBuf, diInstallSuccessful.szLaunchApp, sgProduct.szProductName);
|
|
SetDlgItemText(hDlg, IDC_START_APP, szBuf);
|
|
|
|
// The header on the welcome page uses another font.
|
|
SendDlgItemMessage(hDlg, IDC_STATIC_TITLE, WM_SETFONT, (WPARAM)sgInstallGui.welcomeTitleFont, 0L);
|
|
|
|
SendDlgItemMessage(hDlg, IDC_STATIC0, WM_SETFONT, (WPARAM)sgInstallGui.definedFont, 0L);
|
|
SendDlgItemMessage(hDlg, IDC_STATIC1, WM_SETFONT, (WPARAM)sgInstallGui.definedFont, 0L);
|
|
SendDlgItemMessage(hDlg, IDC_START_APP, WM_SETFONT, (WPARAM)sgInstallGui.definedFont, 0L);
|
|
|
|
launchAppChecked = diInstallSuccessful.bLaunchAppChecked;
|
|
|
|
// Subclass dialog to paint all static controls white.
|
|
OldDialogWndProc = SubclassWindow(hDlg, (WNDPROC)NewDialogWndProc);
|
|
break;
|
|
|
|
case WM_NOTIFY:
|
|
notifyMessage = (LPNMHDR)lParam;
|
|
switch (notifyMessage->code) {
|
|
case PSN_SETACTIVE:
|
|
// Wizard dialog title
|
|
PropSheet_SetTitle(GetParent(hDlg), 0, (LPTSTR)diInstallSuccessful.szTitle);
|
|
|
|
// Restore state from default or cached value.
|
|
CheckDlgButton(hDlg, IDC_START_APP,
|
|
launchAppChecked ? BST_CHECKED : BST_UNCHECKED);
|
|
|
|
// Don't show the back button here UNLESS the previous
|
|
// page was Windows Integration - and that only happens on a custom
|
|
// install.
|
|
PropSheet_SetWizButtons(GetParent(hDlg), PSWIZB_FINISH);
|
|
break;
|
|
|
|
case PSN_WIZBACK:
|
|
// Store the checkbox state in case the user goes back to any post-install
|
|
// pages that we might add.
|
|
launchAppChecked = IsDlgButtonChecked(hDlg, IDC_START_APP) == BST_CHECKED;
|
|
break;
|
|
|
|
case PSN_WIZFINISH:
|
|
// Store state from the "Run App Now" checkbox. ProcessFileOpsForAll
|
|
// uses this variable to decide whether or not to launch the browser.
|
|
gbIgnoreRunAppX = IsDlgButtonChecked(hDlg, IDC_START_APP) != BST_CHECKED;
|
|
|
|
// Apply settings and close.
|
|
if (sgProduct.bInstallFiles)
|
|
UpdateJSProxyInfo();
|
|
|
|
/* POST_SMARTUPDATE process file manipulation functions */
|
|
ProcessFileOpsForAll(T_POST_SMARTUPDATE);
|
|
|
|
if (sgProduct.bInstallFiles) {
|
|
/* PRE_LAUNCHAPP process file manipulation functions */
|
|
ProcessFileOpsForAll(T_PRE_LAUNCHAPP);
|
|
|
|
LaunchApps();
|
|
|
|
// Refresh system icons if necessary
|
|
if (gSystemInfo.bRefreshIcons)
|
|
RefreshIcons();
|
|
|
|
UnsetSetupState(); // clear setup state
|
|
if (!gbIgnoreProgramFolderX)
|
|
ProcessProgramFolderShowCmd();
|
|
|
|
CleanupArgsRegistry();
|
|
CleanupPreviousVersionRegKeys();
|
|
|
|
/* POST_LAUNCHAPP process file manipulation functions */
|
|
ProcessFileOpsForAll(T_POST_LAUNCHAPP);
|
|
/* DEPEND_REBOOT process file manipulation functions */
|
|
ProcessFileOpsForAll(T_DEPEND_REBOOT);
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
case PSN_QUERYCANCEL:
|
|
// Cancel is meaningless and potentially harmful here (the install work
|
|
// is not yet complete). If the user finds a way of cancelling, e.g. by
|
|
// clicking the X button on the window, send the FINISH message.
|
|
|
|
// Assume at least that they didn't want the app to run right away.
|
|
gbIgnoreRunAppX = FALSE;
|
|
|
|
// Send the PSN_WIZFINISH so we can clean up properly.
|
|
notifyMessage->code = PSN_WIZFINISH;
|
|
SendMessage(hDlg, WM_NOTIFY, wParam, (LPARAM)notifyMessage);
|
|
|
|
// Tell the Wizard97 framework that we don't want to hard-quit. Processing
|
|
// of the PSN_WIZFINISH will cause the app to shut down.
|
|
SetWindowLong(hDlg, DWL_MSGRESULT, FALSE);
|
|
return TRUE;
|
|
}
|
|
|
|
break;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
// DIALOG: MESSAGE (A small utility message window)
|
|
//
|
|
|
|
LRESULT CALLBACK DlgProcMessage(HWND hDlg, UINT msg, WPARAM wParam, LONG lParam)
|
|
{
|
|
RECT rDlg;
|
|
HWND hSTMessage = GetDlgItem(hDlg, IDC_MESSAGE); /* handle to the Static Text message window */
|
|
HDC hdcSTMessage;
|
|
SIZE sizeString;
|
|
LOGFONT logFont;
|
|
HFONT hfontTmp;
|
|
HFONT hfontOld;
|
|
char szBuf[MAX_BUF];
|
|
char szBuf2[MAX_BUF];
|
|
|
|
ZeroMemory(szBuf, sizeof(szBuf));
|
|
ZeroMemory(szBuf2, sizeof(szBuf2));
|
|
|
|
switch(msg)
|
|
{
|
|
case WM_INITDIALOG:
|
|
if(GetPrivateProfileString("Messages", "STR_MESSAGEBOX_TITLE", "", szBuf2, sizeof(szBuf2), szFileIniInstall))
|
|
{
|
|
if((sgProduct.szProductName != NULL) && (*sgProduct.szProductName != '\0'))
|
|
wsprintf(szBuf, szBuf2, sgProduct.szProductName);
|
|
else
|
|
wsprintf(szBuf, szBuf2, "");
|
|
}
|
|
else if((sgProduct.szProductName != NULL) && (*sgProduct.szProductName != '\0'))
|
|
lstrcpy(szBuf, sgProduct.szProductName);
|
|
|
|
SetWindowText(hDlg, szBuf);
|
|
|
|
SendDlgItemMessage(hDlg, IDC_MESSAGE, WM_SETFONT, (WPARAM)sgInstallGui.definedFont, 0L);
|
|
|
|
break;
|
|
|
|
case WM_COMMAND:
|
|
switch(LOWORD(wParam))
|
|
{
|
|
case IDC_MESSAGE:
|
|
hdcSTMessage = GetWindowDC(hSTMessage);
|
|
|
|
SystemParametersInfo(SPI_GETICONTITLELOGFONT,
|
|
sizeof(logFont),
|
|
(PVOID)&logFont,
|
|
0);
|
|
hfontTmp = CreateFontIndirect(&logFont);
|
|
|
|
if(hfontTmp)
|
|
hfontOld = SelectObject(hdcSTMessage, hfontTmp);
|
|
|
|
GetTextExtentPoint32(hdcSTMessage, (LPSTR)lParam, lstrlen((LPSTR)lParam), &sizeString);
|
|
SelectObject(hdcSTMessage, hfontOld);
|
|
DeleteObject(hfontTmp);
|
|
ReleaseDC(hSTMessage, hdcSTMessage);
|
|
|
|
SetWindowPos(hDlg, NULL,
|
|
(gSystemInfo.lastWindowPosCenterX)-((sizeString.cx + 55)/2),
|
|
(gSystemInfo.lastWindowPosCenterY)-((sizeString.cy + 50)/2),
|
|
sizeString.cx + 55,
|
|
sizeString.cy + 50,
|
|
SWP_SHOWWINDOW|SWP_NOZORDER);
|
|
|
|
if(GetClientRect(hDlg, &rDlg))
|
|
SetWindowPos(hSTMessage,
|
|
HWND_TOP,
|
|
rDlg.left,
|
|
rDlg.top,
|
|
rDlg.right,
|
|
rDlg.bottom,
|
|
SWP_SHOWWINDOW|SWP_NOZORDER);
|
|
|
|
SetDlgItemText(hDlg, IDC_MESSAGE, (LPSTR)lParam);
|
|
break;
|
|
}
|
|
break;
|
|
}
|
|
return(0);
|
|
}
|
|
|
|
void ShowMessage(LPSTR szMessage, BOOL bShow)
|
|
{
|
|
if(sgProduct.mode != SILENT)
|
|
{
|
|
if(bShow && szMessage)
|
|
{
|
|
char szBuf[MAX_BUF];
|
|
|
|
ZeroMemory(szBuf, sizeof(szBuf));
|
|
GetPrivateProfileString("Messages", "MB_MESSAGE_STR", "", szBuf, sizeof(szBuf), szFileIniInstall);
|
|
hDlgMessage = InstantiateDialog(hWndMain, DLG_MESSAGE, szBuf, DlgProcMessage);
|
|
SendMessage(hDlgMessage, WM_COMMAND, IDC_MESSAGE, (LPARAM)szMessage);
|
|
}
|
|
else
|
|
{
|
|
DestroyWindow(hDlgMessage);
|
|
hDlgMessage = NULL;
|
|
}
|
|
}
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
// UTILITY FUNCTIONS
|
|
|
|
void ProcessWindowsMessages()
|
|
{
|
|
MSG msg;
|
|
|
|
while(PeekMessage(&msg, 0, 0, 0, PM_REMOVE))
|
|
{
|
|
TranslateMessage(&msg);
|
|
DispatchMessage(&msg);
|
|
}
|
|
}
|
|
|
|
HWND InstantiateDialog(HWND hParent, DWORD dwDlgID, LPSTR szTitle, WNDPROC wpDlgProc)
|
|
{
|
|
char szBuf[MAX_BUF];
|
|
HWND hDlg = NULL;
|
|
|
|
|
|
if((hDlg = CreateDialog(hSetupRscInst, MAKEINTRESOURCE(dwDlgID), hParent, wpDlgProc)) == NULL)
|
|
{
|
|
char szEDialogCreate[MAX_BUF];
|
|
|
|
if(GetPrivateProfileString("Messages", "ERROR_DIALOG_CREATE", "", szEDialogCreate, sizeof(szEDialogCreate), szFileIniInstall))
|
|
{
|
|
wsprintf(szBuf, szEDialogCreate, szTitle);
|
|
PrintError(szBuf, ERROR_CODE_SHOW);
|
|
}
|
|
PostQuitMessage(1);
|
|
}
|
|
|
|
return(hDlg);
|
|
}
|
|
|
|
void TruncateString(HWND hWnd, LPSTR szInURL, LPSTR szOutString, DWORD dwOutStringBufSize)
|
|
{
|
|
HDC hdcWnd;
|
|
LOGFONT logFont;
|
|
HFONT hfontNew;
|
|
HFONT hfontOld;
|
|
RECT rWndRect;
|
|
SIZE sizeString;
|
|
char *ptr = NULL;
|
|
int iHalfLen;
|
|
int iOutStringLen;
|
|
|
|
if((DWORD)lstrlen(szInURL) > dwOutStringBufSize)
|
|
return;
|
|
|
|
ZeroMemory(szOutString, dwOutStringBufSize);
|
|
lstrcpy(szOutString, szInURL);
|
|
iOutStringLen = lstrlen(szOutString);
|
|
hdcWnd = GetWindowDC(hWnd);
|
|
GetClientRect(hWnd, &rWndRect);
|
|
SystemParametersInfo(SPI_GETICONTITLELOGFONT,
|
|
sizeof(logFont),
|
|
(PVOID)&logFont,
|
|
0);
|
|
|
|
hfontNew = CreateFontIndirect(&logFont);
|
|
if(hfontNew)
|
|
{
|
|
hfontOld = (HFONT)SelectObject(hdcWnd, hfontNew);
|
|
|
|
GetTextExtentPoint32(hdcWnd, szOutString, iOutStringLen, &sizeString);
|
|
while(sizeString.cx > rWndRect.right)
|
|
{
|
|
iHalfLen = iOutStringLen / 2;
|
|
if(iHalfLen == 2)
|
|
break;
|
|
|
|
ptr = szOutString + iHalfLen;
|
|
memmove(ptr - 1, ptr, lstrlen(ptr) + 1);
|
|
szOutString[iHalfLen - 2] = '.';
|
|
szOutString[iHalfLen - 1] = '.';
|
|
szOutString[iHalfLen] = '.';
|
|
iOutStringLen = lstrlen(szOutString);
|
|
GetTextExtentPoint32(hdcWnd, szOutString, iOutStringLen, &sizeString);
|
|
}
|
|
}
|
|
|
|
SelectObject(hdcWnd, hfontOld);
|
|
DeleteObject(hfontNew);
|
|
ReleaseDC(hWnd, hdcWnd);
|
|
}
|
|
|
|
void InitPathDisplay (HWND aWindow, char* aPath, int aFolderIcon, int aFolderField)
|
|
{
|
|
HICON largeIcon, smallIcon;
|
|
char buf[MAX_BUF];
|
|
|
|
// Folder Icon
|
|
ExtractIconEx("shell32.dll", 3, &largeIcon, &smallIcon, 1);
|
|
SendMessage(GetDlgItem(aWindow, aFolderIcon), STM_SETICON, (LPARAM)smallIcon, 0);
|
|
|
|
TruncateString(GetDlgItem(aWindow, aFolderField),
|
|
aPath, buf, sizeof(buf));
|
|
SetDlgItemText(aWindow, aFolderField, buf);
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|