From 726d67443886410791bef5f2cb580893767a3fec Mon Sep 17 00:00:00 2001 From: Birunthan Mohanathas Date: Sat, 1 Feb 2014 14:11:08 +0200 Subject: [PATCH] New installer: Handle installation types properly --- Installer/DialogInstall.cpp | 126 ++++++++++++++++++++++++++++++++---- Installer/DialogInstall.h | 9 +++ Installer/StdAfx.h | 1 - Installer/Util.cpp | 3 +- 4 files changed, 126 insertions(+), 13 deletions(-) diff --git a/Installer/DialogInstall.cpp b/Installer/DialogInstall.cpp index f79bcc27..b86fb0c1 100644 --- a/Installer/DialogInstall.cpp +++ b/Installer/DialogInstall.cpp @@ -24,6 +24,10 @@ #include "../Common/ControlTemplate.h" #include "../Common/Platform.h" +#define APPNAME L"Rainmeter" + +const WCHAR* kRegistryInstallKey = L"SOFTWARE\\" APPNAME; + CDialogInstall* CDialogInstall::c_Dialog = nullptr; HICON GetIcon(UINT id, bool large) @@ -316,7 +320,7 @@ void CDialogInstall::TabContents::Create(HWND owner) 0, 43, 107, 9, WS_VISIBLE, 0), - CT_EDIT(Id_DestinationEdit, 14, + CT_EDIT(Id_DestinationEdit, 0, 107, 40, 192, 14, WS_VISIBLE | WS_TABSTOP | ES_AUTOHSCROLL | ES_READONLY, WS_EX_CLIENTEDGE), @@ -335,16 +339,8 @@ void CDialogInstall::TabContents::Create(HWND owner) ComboBox_AddString(item, L"English - English (United States)"); ComboBox_SetCurSel(item, 0); - item = GetControl(Id_InstallationTypeComboBox); - ComboBox_AddString(item, L"Standard 64-bit installation (reccomended)"); - ComboBox_SetItemData(item, 0, MAKELPARAM(InstallType::Standard, InstallArch::X64)); - ComboBox_AddString(item, L"Standard 32-bit installation"); - ComboBox_SetItemData(item, 1, MAKELPARAM(InstallType::Standard, InstallArch::X32)); - ComboBox_AddString(item, L"Portable 64-bit installation"); - ComboBox_SetItemData(item, 2, MAKELPARAM(InstallType::Portable, InstallArch::X64)); - ComboBox_AddString(item, L"Portable 32-bit installation"); - ComboBox_SetItemData(item, 3, MAKELPARAM(InstallType::Portable, InstallArch::X32)); - ComboBox_SetCurSel(item, 0); + PopulateInstallationTypes(); + UpdateDestinationDirectory(); } void CDialogInstall::TabContents::Initialize() @@ -383,9 +379,117 @@ INT_PTR CDialogInstall::TabContents::OnCommand(WPARAM wParam, LPARAM lParam) } break; + case Id_InstallationTypeComboBox: + { + if (HIWORD(wParam) == CBN_SELCHANGE) + { + UpdateDestinationDirectory(); + } + break; + } + default: return FALSE; } return TRUE; } + +InstallType CDialogInstall::TabContents::GetInstallType() +{ + HWND item = GetControl(TabContents::Id_InstallationTypeComboBox); + const LPARAM typeData = ComboBox_GetItemData(item, ComboBox_GetCurSel(item)); + return (InstallType)LOWORD(typeData); +} + +InstallArch CDialogInstall::TabContents::GetInstallArch() +{ + HWND item = GetControl(TabContents::Id_InstallationTypeComboBox); + const LPARAM typeData = ComboBox_GetItemData(item, ComboBox_GetCurSel(item)); + return (InstallArch)HIWORD(typeData); +} + +void CDialogInstall::TabContents::PopulateInstallationTypes() +{ + HWND item = GetControl(Id_InstallationTypeComboBox); + int index = 0; + if (Util::IsSystem64Bit()) + { + InstallArch existingArch; + const bool alreadyInstalled = IsAlreadyInstalled(existingArch); + if (!alreadyInstalled || existingArch == InstallArch::X64) + { + index = ComboBox_AddString(item, L"Standard 64-bit installation (recommended)"); + ComboBox_SetItemData(item, index, MAKELPARAM(InstallType::Standard, InstallArch::X64)); + } + if (!alreadyInstalled || existingArch == InstallArch::X32) + { + index = ComboBox_AddString(item, L"Standard 32-bit installation"); + ComboBox_SetItemData(item, index, MAKELPARAM(InstallType::Standard, InstallArch::X32)); + } + index = ComboBox_AddString(item, L"Portable 64-bit installation"); + ComboBox_SetItemData(item, index, MAKELPARAM(InstallType::Portable, InstallArch::X64)); + } + else + { + index = ComboBox_AddString(item, L"Standard 32-bit installation (recommended)"); + ComboBox_SetItemData(item, index, MAKELPARAM(InstallType::Standard, InstallArch::X32)); + } + index = ComboBox_AddString(item, L"Portable 32-bit installation"); + ComboBox_SetItemData(item, index, MAKELPARAM(InstallType::Portable, InstallArch::X32)); + + ComboBox_SetCurSel(item, 0); +} + +void CDialogInstall::TabContents::UpdateDestinationDirectory() +{ + WCHAR buffer[MAX_PATH]; + buffer[0] = L'\0'; + + if (GetInstallType() == InstallType::Standard) + { + const bool hasRegistryKey = Util::GetRegistryString( + HKEY_LOCAL_MACHINE, kRegistryInstallKey, nullptr, buffer, _countof(buffer)); + if (!hasRegistryKey) + { + const WCHAR* installPath = + GetInstallArch() == InstallArch::X32 ? L"%ProgramFiles%\\" APPNAME : L"%ProgramW6432%\\" APPNAME; + ExpandEnvironmentStrings(installPath, buffer, _countof(buffer)); + } + } + else + { + ExpandEnvironmentStrings(L"%SystemDrive%\\" APPNAME, buffer, _countof(buffer)); + } + + HWND item = GetControl(Id_DestinationEdit); + Edit_SetText(item, buffer); +} + +bool CDialogInstall::TabContents::IsAlreadyInstalled(InstallArch& arch) +{ + WCHAR buffer[MAX_PATH]; + const bool hasRegistryKey = Util::GetRegistryString( + HKEY_LOCAL_MACHINE, kRegistryInstallKey, nullptr, buffer, _countof(buffer)); + if (hasRegistryKey) + { + PathAppend(buffer, L"Rainmeter.exe"); + if (PathFileExists(buffer)) + { + // FIXME: This is an ugly way to check if Rainmeter.exe is 32-bit. + HMODULE rainmeterExe = LoadLibrary(buffer); + if (rainmeterExe) + { + arch = InstallArch::X32; + CloseHandle(rainmeterExe); + } + else + { + arch = InstallArch::X64; + } + return true; + } + } + + return false; +} diff --git a/Installer/DialogInstall.h b/Installer/DialogInstall.h index 88584030..a0ce13eb 100644 --- a/Installer/DialogInstall.h +++ b/Installer/DialogInstall.h @@ -19,6 +19,7 @@ #ifndef RM_INSTALLER_DIALOGINSTALL_H_ #define RM_INSTALLER_DIALOGINSTALL_H_ +#include "Install.h" #include "../Common/Dialog.h" class CDialogInstall : public Dialog @@ -52,6 +53,14 @@ protected: void Create(HWND owner); virtual void Initialize(); + InstallType GetInstallType(); + InstallArch GetInstallArch(); + + void PopulateInstallationTypes(); + void UpdateDestinationDirectory(); + + bool IsAlreadyInstalled(InstallArch& arch); + protected: virtual INT_PTR HandleMessage(UINT uMsg, WPARAM wParam, LPARAM lParam); INT_PTR OnCommand(WPARAM wParam, LPARAM lParam); diff --git a/Installer/StdAfx.h b/Installer/StdAfx.h index 0dbf5234..0b582c4d 100644 --- a/Installer/StdAfx.h +++ b/Installer/StdAfx.h @@ -19,7 +19,6 @@ #ifndef RM_INSTALLER_STDAFX_H_ #define RM_INSTALLER_STDAFX_H_ -#define WIN32_LEAN_AND_MEAN #include #include #include diff --git a/Installer/Util.cpp b/Installer/Util.cpp index d6beb441..b2728c3d 100644 --- a/Installer/Util.cpp +++ b/Installer/Util.cpp @@ -184,9 +184,10 @@ bool GetRegistryDword(HKEY rootKey, const WCHAR* subKey, const WCHAR* value, DWO type == REG_DWORD); } -bool GetRegistryString(HKEY rootKey, const WCHAR* subKey, const WCHAR* value, WCHAR* data, DWORD dataSize) +bool GetRegistryString(HKEY rootKey, const WCHAR* subKey, const WCHAR* value, WCHAR* data, DWORD bufferLength) { DWORD type; + DWORD dataSize = bufferLength * sizeof(data[0]); return (SHGetValue(rootKey, subKey, value, &type, data, &dataSize) == ERROR_SUCCESS && type == REG_SZ); }