bug 529897 - Make it possible to install Fennec over the existing version r=vlad a=blocking-fennec

This commit is contained in:
Alex Pakhotin 2009-11-25 12:20:32 -08:00
parent fced4ec129
commit a7d30c1691
3 changed files with 136 additions and 10 deletions

View File

@ -55,6 +55,7 @@
const WCHAR c_sInstallPathTemplate[] = L"%s\\%s";
const WCHAR c_sExtractCardPathTemplate[] = L"\\%s%s\\%s";
const WCHAR c_sAppRegKeyTemplate[] = L"Software\\%s";
// Message handler for the dialog
INT_PTR CALLBACK DlgMain(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
@ -169,6 +170,8 @@ BOOL nsInstallerDlg::OnInitDialog(HWND hDlg, WPARAM wParam, LPARAM lParam)
SendMessageToControl(IDC_CMB_PATH, CB_SETCURSEL, 0, 0 );
RunUninstall();
return (INT_PTR)TRUE;
}
@ -293,7 +296,7 @@ BOOL nsInstallerDlg::StoreInstallPath()
{
HKEY hKey;
WCHAR sRegFennecKey[MAX_PATH];
_snwprintf(sRegFennecKey, MAX_PATH, L"Software\\%s", Strings.GetString(StrID_AppShortName));
_snwprintf(sRegFennecKey, MAX_PATH, c_sAppRegKeyTemplate, Strings.GetString(StrID_AppShortName));
// Store the installation path - to be used by the uninstaller
LONG result = RegCreateKeyEx(HKEY_LOCAL_MACHINE, sRegFennecKey, 0, REG_NONE,
@ -360,3 +363,52 @@ void nsInstallerDlg::AddErrorMsg(WCHAR* sErr)
_snwprintf(sMsg, c_nMaxErrorLen, L"%s. LastError = %d\n", sErr, GetLastError());
wcsncat(m_sErrorMsg, sMsg, c_nMaxErrorLen - wcslen(m_sErrorMsg));
}
//////////////////////////////////////////////////////////////////////////
//
// Uninstall previous installation
//
//////////////////////////////////////////////////////////////////////////
BOOL nsInstallerDlg::GetInstallPath(WCHAR *sPath)
{
HKEY hKey;
WCHAR sRegFennecKey[MAX_PATH];
_snwprintf(sRegFennecKey, MAX_PATH, c_sAppRegKeyTemplate, Strings.GetString(StrID_AppShortName));
LONG result = RegOpenKeyEx(HKEY_LOCAL_MACHINE, sRegFennecKey, 0, KEY_ALL_ACCESS, &hKey);
if (result == ERROR_SUCCESS)
{
DWORD dwType = NULL;
DWORD dwCount = MAX_PATH * sizeof(WCHAR);
result = RegQueryValueEx(hKey, L"Path", NULL, &dwType, (LPBYTE)sPath, &dwCount);
RegCloseKey(hKey);
}
return (result == ERROR_SUCCESS);
}
void nsInstallerDlg::RunUninstall()
{
WCHAR sUninstallPath[MAX_PATH];
if (GetInstallPath(sUninstallPath))
{
if (wcslen(sUninstallPath) > 0 && sUninstallPath[wcslen(sUninstallPath)-1] != '\\')
wcscat(sUninstallPath, L"\\");
WCHAR sParam[MAX_PATH+10];
_snwprintf(sParam, MAX_PATH+9, L"remove %s", sUninstallPath);
wcscat(sUninstallPath, L"uninstall.exe");
PROCESS_INFORMATION pi;
BOOL bResult = CreateProcess(sUninstallPath, sParam,
NULL, NULL, FALSE, 0, NULL, NULL, NULL, &pi);
if (bResult)
{
// Wait for it to finish
WaitForSingleObject(pi.hProcess, INFINITE);
}
}
}

View File

@ -65,6 +65,9 @@ private:
BOOL MoveSetupStrings();
BOOL SilentFirstRun();
BOOL GetInstallPath(WCHAR *sPath);
void RunUninstall();
void AddErrorMsg(WCHAR* sErr);
static const int c_nMaxErrorLen = 2048;

View File

@ -50,8 +50,18 @@ nsSetupStrings Strings;
WCHAR g_sUninstallPath[MAX_PATH];
const DWORD c_nTempBufSize = MAX_PATH * 2;
const WCHAR c_sRemoveParam[] = L"remove";
enum {
ErrOK = 0,
ErrCancel = 1,
ErrNoStrings = -1,
ErrInstallationNotFound = -2,
ErrShutdownFailed = -3,
};
// Forward declarations
BOOL GetModulePath(WCHAR *sPath);
BOOL LoadStrings();
@ -60,6 +70,7 @@ BOOL DeleteShortcut(HWND hwndParent);
BOOL DeleteDirectory(const WCHAR* sPathToDelete);
BOOL DeleteRegistryKey();
BOOL CopyAndLaunch();
BOOL ShutdownFastStartService(const WCHAR *sInstallPath);
// Main
int WINAPI WinMain(HINSTANCE hInstance,
@ -82,7 +93,7 @@ int WINAPI WinMain(HINSTANCE hInstance,
// Just copy this EXE and launch it from a temp location with a special parameter
// to delete itself in the installation directory
if (CopyAndLaunch())
return 0;
return ErrOK;
}
// Perform uninstallation when executed with a special parameter
// (or in case when CopyAndLaunch failed - just execute in place)
@ -90,19 +101,28 @@ int WINAPI WinMain(HINSTANCE hInstance,
if (!LoadStrings())
{
MessageBoxW(hWnd, L"Cannot find the strings file.", L"Uninstall", MB_OK|MB_ICONWARNING);
return -1;
return ErrNoStrings;
}
WCHAR sInstallPath[MAX_PATH];
if (GetInstallPath(sInstallPath))
{
WCHAR sMsg[MAX_PATH+256];
_snwprintf(sMsg, MAX_PATH+256, L"%s %s\n%s", Strings.GetString(StrID_FilesWillBeRemoved),
if (!ShutdownFastStartService(sInstallPath))
{
//TODO: May need to handle this situation
//MessageBoxW(hWnd, L"Unable to shut down Fennec. Try to reset your device.",
// Strings.GetString(StrID_UninstallCaption), MB_OK|MB_ICONWARNING);
//return ErrShutdownFailed;
}
WCHAR sMsg[c_nTempBufSize];
_snwprintf(sMsg, c_nTempBufSize, L"%s %s\n%s", Strings.GetString(StrID_FilesWillBeRemoved),
sInstallPath, Strings.GetString(StrID_AreYouSure));
if (MessageBoxW(hWnd, sMsg, Strings.GetString(StrID_UninstallCaption),
MB_YESNO|MB_ICONWARNING) == IDNO)
{
return -2;
return ErrCancel;
}
// Remove all installed files
@ -119,10 +139,10 @@ int WINAPI WinMain(HINSTANCE hInstance,
{
MessageBoxW(hWnd, Strings.GetString(StrID_InstallationNotFound),
Strings.GetString(StrID_UninstallCaption), MB_OK|MB_ICONINFORMATION);
return -1;
return ErrInstallationNotFound;
}
return 0;
return ErrOK;
}
BOOL LoadStrings()
@ -266,8 +286,8 @@ BOOL CopyAndLaunch()
if (CopyFile(sModule, sNewName, FALSE))
{
PROCESS_INFORMATION pi;
WCHAR sParam[MAX_PATH+20];
_snwprintf(sParam, MAX_PATH+20, L"%s %s", c_sRemoveParam, g_sUninstallPath);
WCHAR sParam[c_nTempBufSize];
_snwprintf(sParam, c_nTempBufSize, L"%s %s", c_sRemoveParam, g_sUninstallPath);
// Launch "\Temp\uninstall.exe remove \Program Files\Fennec\"
return CreateProcess(sNewName, sParam, NULL, NULL, FALSE, 0, NULL, NULL, NULL, &pi);
@ -275,3 +295,54 @@ BOOL CopyAndLaunch()
else
return FALSE;
}
BOOL ConvertToChar(const WCHAR *wstr, char *str, DWORD bufSize)
{
return 0 != WideCharToMultiByte(CP_ACP, 0, wstr, -1, str, bufSize, NULL, NULL);
}
BOOL ShutdownFastStartService(const WCHAR *wsInstallPath)
{
BOOL result = TRUE;
// Class name: appName + "MessageWindow"
WCHAR sClassName[c_nTempBufSize];
_snwprintf(sClassName, c_nTempBufSize, L"%s%s", Strings.GetString(StrID_AppShortName), L"MessageWindow");
HWND handle = ::FindWindowW(sClassName, NULL);
if (handle)
{
char sPath[MAX_PATH];
ConvertToChar(wsInstallPath, sPath, MAX_PATH);
size_t pathLen = strlen(sPath);
if (pathLen > 0 && sPath[pathLen-1] != '\\')
{
strcat(sPath, "\\");
pathLen++;
}
char sCopyData[MAX_PATH * 3];
_snprintf(sCopyData, MAX_PATH * 2, "\"%s%S.exe\" -shutdown-faststart", sPath, Strings.GetString(StrID_AppShortName));
size_t cmdLineLen = strlen(sCopyData);
char *sRest = sCopyData + cmdLineLen + 1;
strcpy(sRest, sPath);
COPYDATASTRUCT cds = {
1,
pathLen + 1 + cmdLineLen,
(void*) sCopyData
};
::SendMessage(handle, WM_COPYDATA, 0, (LPARAM)&cds);
// Wait 10 seconds or until it's shut down
for (int i = 0; i < 20 && handle; i++)
{
Sleep(500);
handle = ::FindWindowW(sClassName, NULL);
}
// The window must not exist if the service shut down properly
result = (handle == NULL);
}
return result;
}