Landing of interdependent bugs for Vista support. Bug 354005 Setting the app as the OS default is broken on Vista. r=sspitzer, r=dougt, sr=bsmedberg. Bug 351949 – Automatic Update is not working for Vista users with limited account privilege and UAC (User Account Control) enabled. r=sspitzer, r=rstrong. Bug 354226 – nsPostUpdateWin.js fails to update registry keys / log files after an update has been applied. r=rstrong.

git-svn-id: svn://10.0.0.236/trunk@219158 18797224-902f-48f8-a5cc-f745e15eee43
This commit is contained in:
rob_strong%exchangecode.com
2007-01-30 05:14:50 +00:00
parent e72cf3994c
commit bfca43936b
32 changed files with 1716 additions and 1100 deletions

View File

@@ -61,6 +61,8 @@ const nsIWindowWatcher = Components.interfaces.nsIWindowWatcher;
const nsICategoryManager = Components.interfaces.nsICategoryManager;
const nsIWebNavigationInfo = Components.interfaces.nsIWebNavigationInfo;
const nsIBrowserSearchService = Components.interfaces.nsIBrowserSearchService;
const nsITimer = Components.interfaces.nsITimer;
const nsITimerCallback = Components.interfaces.nsITimerCallback;
const NS_BINDING_ABORTED = 0x804b0002;
const NS_ERROR_WONT_HANDLE_CONTENT = 0x805d0001;
@@ -595,16 +597,73 @@ var nsDefaultCommandLineHandler = {
QueryInterface : function dch_QI(iid) {
if (!iid.equals(nsISupports) &&
!iid.equals(nsICommandLineHandler) &&
!iid.equals(nsITimerCallback) &&
!iid.equals(nsIFactory))
throw Components.results.NS_ERROR_NO_INTERFACE;
return this;
},
// True when a DDE request will follow
_requestPending: false,
_URIs: [ ],
_timer: null,
/* nsITimerCallback - opens urls after the ui is sufficiently initialized */
notify: function (aTimer) {
try {
var navWin = getMostRecentBrowserWindow();
var navNav = navWin.QueryInterface(nsIInterfaceRequestor)
.getInterface(nsIWebNavigation);
var rootItem = navNav.QueryInterface(nsIDocShellTreeItem).rootTreeItem;
var rootWin = rootItem.QueryInterface(nsIInterfaceRequestor)
.getInterface(nsIDOMWindow);
var bwin = rootWin.QueryInterface(nsIDOMChromeWindow).browserDOMWindow;
if (bwin) {
var browser = navWin.getBrowser();
var tabPanels = browser.browsers;
var count = this._URIs.length;
for (var i = 0; i < count; ++i) {
var uri = this._URIs[0];
if (tabPanels.length == 1 &&
tabPanels[0].currentURI.spec == "about:blank" &&
!tabPanels[0].webProgress.isLoadingDocument) {
if (shouldLoadURI(uri))
handURIToExistingBrowser(uri, nsIBrowserDOMWindow.OPEN_CURRENTWINDOW);
}
else {
handURIToExistingBrowser(uri, nsIBrowserDOMWindow.OPEN_DEFAULTWINDOW);
}
this._URIs.splice(0, 1);
}
this._requestPending = false;
this._timer.cancel();
this._timer = null;
this._URIs = [ ];
return;
}
}
catch (e) {
}
},
/* nsICommandLineHandler */
handle : function dch_handle(cmdLine) {
var urilist = [];
#ifdef XP_WIN
if (cmdLine.handleFlag("requestpending", false) &&
cmdLine.state == nsICommandLine.STATE_INITIAL_LAUNCH) {
this._requestPending = true;
// When the requestpending flag is present a dde message will follow that
// contains the same url. By handling the url flag here as a noop
// duplicate requests to open the same url are prevented. When the
// application needs to restart during startup the requestpending flag
// is removed and the url flag will be handled normally after the restart.
cmdLine.handleFlagWithParam("url", false);
}
#endif
try {
var ar;
while ((ar = cmdLine.handleFlagWithParam("url", false))) {
@@ -615,6 +674,41 @@ var nsDefaultCommandLineHandler = {
Components.utils.reportError(e);
}
#ifdef XP_WIN
if (cmdLine.state == nsICommandLine.STATE_REMOTE_EXPLICIT && this._requestPending) {
// Handdle DDE request to open an url by first trying to open it via an
// existing window's openURI. If this fails a timer will be used to allow
// the window to finish opening so the url can be opened correctly and
// respect the OPEN_EXTERNAL pref.
try {
var navWin = getMostRecentBrowserWindow();
var navNav = navWin.QueryInterface(nsIInterfaceRequestor)
.getInterface(nsIWebNavigation);
var rootItem = navNav.QueryInterface(nsIDocShellTreeItem).rootTreeItem;
var rootWin = rootItem.QueryInterface(nsIInterfaceRequestor)
.getInterface(nsIDOMWindow);
var bwin = rootWin.QueryInterface(nsIDOMChromeWindow).browserDOMWindow;
bwin.openURI(urilist[0], null, nsIBrowserDOMWindow.OPEN_DEFAULTWINDOW,
nsIBrowserDOMWindow.OPEN_EXTERNAL);
this._requestPending = false;
}
catch (e) {
this._URIs.push(urilist[0]);
// If multiple urls (e.g. local files, etc.) are opened at the same
// time when the app is not running it is possible to have multiple
// requests before there is a window available to handle the request so
// a timer is used to allow the window to finish opening before
// attempting to open the url.
if (!this._timer) {
this._timer = Components.classes["@mozilla.org/timer;1"]
.createInstance(nsITimer);
this._timer.initWithCallback(this, 100, nsITimer.TYPE_REPEATING_SLACK);
}
}
return;
}
#endif
var count = cmdLine.length;
for (var i = 0; i < count; ++i) {

View File

@@ -62,6 +62,9 @@
#include "shlobj.h"
#include "nsIWindowsRegKey.h"
#include "windows.h"
#include "shellapi.h"
#include <mbstring.h>
#ifndef MAX_BUF
@@ -97,26 +100,40 @@ OpenUserKeyForReading(HKEY aStartKey, const char* aKeyName, HKEY* aKey)
return NS_OK;
}
// Sets the default browser registry keys for Windows versions prior to Vista.
// Try to open / create the key in HKLM and if that fails try to do the same
// in HKCU. Though this is not strictly the behavior I would expect it is the
// same behavior that IE has when setting the default browser previous to Vista.
static nsresult
OpenKeyForWriting(const char* aKeyName, HKEY* aKey, PRBool aForAllUsers, PRBool aCreate)
OpenKeyForWriting(HKEY aStartKey, const char* aKeyName, HKEY* aKey,
PRBool aHKLMOnly)
{
nsresult rv = NS_OK;
DWORD dwDisp = 0;
DWORD rv = ::RegCreateKeyEx(aStartKey, aKeyName, 0, NULL, 0,
KEY_READ | KEY_WRITE, NULL, aKey, &dwDisp);
HKEY rootKey = aForAllUsers ? HKEY_LOCAL_MACHINE : HKEY_CURRENT_USER;
DWORD result = ::RegOpenKeyEx(rootKey, aKeyName, 0, KEY_READ | KEY_WRITE, aKey);
switch (result) {
switch (rv) {
case ERROR_SUCCESS:
break;
case ERROR_ACCESS_DENIED:
return NS_ERROR_FILE_ACCESS_DENIED;
if (aHKLMOnly || aStartKey == HKEY_CURRENT_USER)
return NS_ERROR_FILE_ACCESS_DENIED;
// fallback to HKCU immediately on access denied since we won't be able
// to create the key.
return OpenKeyForWriting(HKEY_CURRENT_USER, aKeyName, aKey, aHKLMOnly);
case ERROR_FILE_NOT_FOUND:
if (aCreate)
result = ::RegCreateKey(HKEY_LOCAL_MACHINE, aKeyName, aKey);
rv = NS_ERROR_FILE_NOT_FOUND;
break;
rv = ::RegCreateKey(aStartKey, aKeyName, aKey);
if (rv != ERROR_SUCCESS) {
if (aHKLMOnly || aStartKey == HKEY_CURRENT_USER) {
// prevent infinite recursion on the second pass through here if
// ::RegCreateKey fails in the current user case.
return NS_ERROR_FILE_ACCESS_DENIED;
}
return OpenKeyForWriting(HKEY_CURRENT_USER, aKeyName, aKey, aHKLMOnly);
}
}
return rv;
return NS_OK;
}
///////////////////////////////////////////////////////////////////////////////
@@ -128,55 +145,69 @@ OpenKeyForWriting(const char* aKeyName, HKEY* aKey, PRBool aForAllUsers, PRBool
// .htm .html .shtml .xht .xhtml
// are mapped like so:
//
// HKCU\SOFTWARE\Classes\.<ext>\ (default) REG_SZ FirefoxHTML
// HKCU\SOFTWARE\Classes\.<ext>\ (default) REG_SZ FirefoxHTML
//
// as aliases to the class:
//
// HKCU\SOFTWARE\Classes\FirefoxHTML\
// DefaultIcon (default) REG_SZ <appname>,1
// shell\open\command (default) REG_SZ <appname> -url "%1"
// DefaultIcon (default) REG_SZ <apppath>,1
// shell\open\command (default) REG_SZ <apppath> -url "%1" -requestPending
// shell\open\ddeexec (default) REG_SZ "%1",,0,0,,,,
// shell\open\ddeexec NoActivateHandler REG_SZ
// \Application (default) REG_SZ Firefox
// \Topic (default) REG_SZ WWW_OpenURL
//
// - Windows Vista Protocol Handler
//
// HKCU\SOFTWARE\Classes\FirefoxURL\ (default) REG_SZ <appname> URL
// EditFlags REG_DWORD 2
// FriendlyTypeName REG_SZ <appname> URL
// DefaultIcon (default) REG_SZ <apppath>,0
// shell\open\command (default) REG_SZ <apppath> -url "%1" -requestPending
// shell\open\ddeexec (default) REG_SZ "%1",,0,0,,,,
// shell\open\ddeexec NoActivateHandler REG_SZ
// \Application (default) REG_SZ Firefox
// \Topic (default) REG_SZ WWW_OpenURL
//
// - Protocol Mappings
// -----------------
// The following protocols:
// HTTP, HTTPS, FTP, GOPHER, CHROME
// HTTP, HTTPS, FTP, GOPHER
// are mapped like so:
//
// HKCU\SOFTWARE\Classes\<protocol>\
// DefaultIcon (default) REG_SZ <appname>,0
// shell\open\command (default) REG_SZ <appname> -url "%1"
// shell\open\ddeexec (default) REG_SZ "%1",,0,0,,,,
// shell\open\ddeexec NoActivateHandler REG_SZ
// \application (default) REG_SZ Firefox
// \ifexec (default) REG_SZ ,,0,0,,,,
// \topic (default) REG_SZ WWW_OpenURL
//
// HKCU\SOFTWARE\Classes\<protocol>\
// DefaultIcon (default) REG_SZ <apppath>,0
// shell\open\command (default) REG_SZ <apppath> -url "%1" -requestPending
// shell\open\ddeexec (default) REG_SZ "%1",,0,0,,,,
// shell\open\ddeexec NoActivateHandler REG_SZ
// \Application (default) REG_SZ Firefox
// \Topic (default) REG_SZ WWW_OpenURL
//
// - Windows XP Start Menu Browser
// -----------------------------
// The following keys are set to make Firefox appear in the Windows XP
// Start Menu as the browser:
// - Windows Start Menu (Win2K SP2, XP SP1, and newer)
// -------------------------------------------------
// The following keys are set to make Firefox appear in the Start Menu as the
// browser:
//
// HKCU\SOFTWARE\Clients\StartMenuInternet
// firefox.exe\DefaultIcon (default) REG_SZ <appname>,0
// firefox.exe\shell\open\command (default) REG_SZ <appname>
// firefox.exe\shell\properties (default) REG_SZ Firefox &Options
// firefox.exe\shell\properties\command(default) REG_SZ <appname> -preferences
//
// - Uninstall Information
// ---------------------
// Every key that is set has the previous value stored in:
//
// HKCU\SOFTWARE\Mozilla\Desktop\ <keyname> REG_SZ oldval
//
// If there is no previous value, an empty value is set to indicate that the
// key should be removed completely.
// HKCU\SOFTWARE\Clients\StartMenuInternet\FIREFOX.EXE\
// (default) REG_SZ <appname>
// DefaultIcon (default) REG_SZ <apppath>,0
// InstallInfo HideIconsCommand REG_SZ <uninstpath> /HideShortcuts
// InstallInfo IconsVisible REG_DWORD 1
// InstallInfo ReinstallCommand REG_SZ <uninstpath> /SetAsDefaultAppGlobal
// InstallInfo ShowIconsCommand REG_SZ <uninstpath> /ShowShortcuts
// shell\open\command (default) REG_SZ <apppath>
// shell\properties (default) REG_SZ <appname> &Options
// shell\properties\command (default) REG_SZ <apppath> -preferences
// shell\safemode (default) REG_SZ <appname> &Safe Mode
// shell\safemode\command (default) REG_SZ <apppath> -safe-mode
//
typedef enum { NO_SUBSTITUTION = 0x00,
PATH_SUBSTITUTION = 0x01,
EXE_SUBSTITUTION = 0x02,
NON_ESSENTIAL = 0x04} SettingFlags;
typedef enum { NO_SUBSTITUTION = 0x00,
APP_PATH_SUBSTITUTION = 0x01,
EXE_NAME_SUBSTITUTION = 0x02,
UNINST_PATH_SUBSTITUTION = 0x04,
HKLM_ONLY = 0x08,
NON_ESSENTIAL = 0x10 } SettingFlags;
typedef struct {
char* keyName;
char* valueName;
@@ -185,20 +216,24 @@ typedef struct {
PRInt32 flags;
} SETTING;
#define APP_REG_NAME L"Firefox"
#define SMI "SOFTWARE\\Clients\\StartMenuInternet\\"
#define CLS "SOFTWARE\\Classes\\"
#define DI "\\DefaultIcon"
#define II "\\InstallInfo"
#define SOP "\\shell\\open\\command"
#define DDE "\\shell\\open\\ddeexec\\"
#define DDE_NAME "Firefox" // This must be kept in sync with ID_DDE_APPLICATION_NAME as defined in splash.rc
#define APP_REG_NAME L"Firefox"
#define DDE_COMMAND "\"%1\",,0,0,,,,"
#define DDE_IFEXEC ",,0,0,,,,"
// For the InstallInfo HideIconsCommand, ShowIconsCommand, and ReinstallCommand
// registry keys. This must be kept in sync with the uninstaller.
#define UNINSTALL_EXE "\\uninstall\\helper.exe"
#define CLS_HTML "FirefoxHTML"
#define CLS_URL "FirefoxURL"
#define VAL_URL_ICON "%APPPATH%,0"
#define VAL_FILE_ICON "%APPPATH%,1"
#define VAL_OPEN "\"%APPPATH%\" -url \"%1\""
#define VAL_OPEN "\"%APPPATH%\" -url \"%1\" -requestPending"
#define MAKE_KEY_NAME1(PREFIX, MID) \
PREFIX MID
@@ -210,12 +245,6 @@ typedef struct {
PREFIX MID MID2 SUFFIX
static SETTING gSettings[] = {
// Extension Manager Keys
{ MAKE_KEY_NAME1(CLS, "MIME\\Database\\Content Type\\application/x-xpinstall;app=firefox"),
"Extension",
".xpi",
NO_SUBSTITUTION | NON_ESSENTIAL },
// File Extension Aliases
{ MAKE_KEY_NAME1(CLS, ".htm"), "", CLS_HTML, NO_SUBSTITUTION | NON_ESSENTIAL },
{ MAKE_KEY_NAME1(CLS, ".html"), "", CLS_HTML, NO_SUBSTITUTION | NON_ESSENTIAL },
@@ -224,64 +253,72 @@ static SETTING gSettings[] = {
{ MAKE_KEY_NAME1(CLS, ".xhtml"), "", CLS_HTML, NO_SUBSTITUTION | NON_ESSENTIAL },
// File Extension Class
{ MAKE_KEY_NAME2(CLS, CLS_HTML, DI), "", VAL_FILE_ICON, PATH_SUBSTITUTION | NON_ESSENTIAL },
{ MAKE_KEY_NAME2(CLS, CLS_HTML, SOP), "", VAL_OPEN, PATH_SUBSTITUTION | NON_ESSENTIAL },
{ MAKE_KEY_NAME2(CLS, CLS_HTML, DI), "", VAL_FILE_ICON, APP_PATH_SUBSTITUTION },
{ MAKE_KEY_NAME2(CLS, CLS_HTML, SOP), "", VAL_OPEN, APP_PATH_SUBSTITUTION },
// Protocol Handler Class - for Vista and above
{ MAKE_KEY_NAME2(CLS, CLS_URL, DI), "", VAL_URL_ICON, APP_PATH_SUBSTITUTION },
{ MAKE_KEY_NAME2(CLS, CLS_URL, SOP), "", VAL_OPEN, APP_PATH_SUBSTITUTION },
// Protocol Handlers
{ MAKE_KEY_NAME2(CLS, "HTTP", DI), "", VAL_URL_ICON, PATH_SUBSTITUTION },
{ MAKE_KEY_NAME2(CLS, "HTTP", SOP), "", VAL_OPEN, PATH_SUBSTITUTION },
{ MAKE_KEY_NAME2(CLS, "HTTPS", DI), "", VAL_URL_ICON, PATH_SUBSTITUTION },
{ MAKE_KEY_NAME2(CLS, "HTTPS", SOP), "", VAL_OPEN, PATH_SUBSTITUTION },
{ MAKE_KEY_NAME2(CLS, "FTP", DI), "", VAL_URL_ICON, PATH_SUBSTITUTION | NON_ESSENTIAL },
{ MAKE_KEY_NAME2(CLS, "FTP", SOP), "", VAL_OPEN, PATH_SUBSTITUTION | NON_ESSENTIAL },
{ MAKE_KEY_NAME2(CLS, "GOPHER", DI), "", VAL_URL_ICON, PATH_SUBSTITUTION | NON_ESSENTIAL },
{ MAKE_KEY_NAME2(CLS, "GOPHER", SOP), "", VAL_OPEN, PATH_SUBSTITUTION | NON_ESSENTIAL },
{ MAKE_KEY_NAME2(CLS, "CHROME", DI), "", VAL_URL_ICON, PATH_SUBSTITUTION | NON_ESSENTIAL },
{ MAKE_KEY_NAME2(CLS, "CHROME", SOP), "", VAL_OPEN, PATH_SUBSTITUTION | NON_ESSENTIAL },
{ MAKE_KEY_NAME2(CLS, "HTTP", DI), "", VAL_URL_ICON, APP_PATH_SUBSTITUTION },
{ MAKE_KEY_NAME2(CLS, "HTTP", SOP), "", VAL_OPEN, APP_PATH_SUBSTITUTION },
{ MAKE_KEY_NAME2(CLS, "HTTPS", DI), "", VAL_URL_ICON, APP_PATH_SUBSTITUTION },
{ MAKE_KEY_NAME2(CLS, "HTTPS", SOP), "", VAL_OPEN, APP_PATH_SUBSTITUTION },
{ MAKE_KEY_NAME2(CLS, "FTP", DI), "", VAL_URL_ICON, APP_PATH_SUBSTITUTION | NON_ESSENTIAL },
{ MAKE_KEY_NAME2(CLS, "FTP", SOP), "", VAL_OPEN, APP_PATH_SUBSTITUTION | NON_ESSENTIAL },
{ MAKE_KEY_NAME2(CLS, "GOPHER", DI), "", VAL_URL_ICON, APP_PATH_SUBSTITUTION | NON_ESSENTIAL },
{ MAKE_KEY_NAME2(CLS, "GOPHER", SOP), "", VAL_OPEN, APP_PATH_SUBSTITUTION | NON_ESSENTIAL },
// DDE settings
{ MAKE_KEY_NAME2(CLS, CLS_HTML, DDE), "", DDE_COMMAND, NO_SUBSTITUTION },
{ MAKE_KEY_NAME3(CLS, CLS_HTML, DDE, "Application"), "", DDE_NAME, NO_SUBSTITUTION },
{ MAKE_KEY_NAME3(CLS, CLS_HTML, DDE, "Topic"), "", "WWW_OpenURL", NO_SUBSTITUTION },
{ MAKE_KEY_NAME3(CLS, CLS_HTML, DDE, "ifexec"), "", DDE_IFEXEC, NO_SUBSTITUTION },
{ MAKE_KEY_NAME2(CLS, "HTTP", DDE), "", DDE_COMMAND, NO_SUBSTITUTION },
{ MAKE_KEY_NAME3(CLS, "HTTP", DDE, "Application"), "", DDE_NAME, NO_SUBSTITUTION },
{ MAKE_KEY_NAME3(CLS, "HTTP", DDE, "Topic"), "", "WWW_OpenURL", NO_SUBSTITUTION },
{ MAKE_KEY_NAME3(CLS, "HTTP", DDE, "ifexec"), "", DDE_IFEXEC, NO_SUBSTITUTION },
{ MAKE_KEY_NAME2(CLS, "HTTPS", DDE), "", DDE_COMMAND, NO_SUBSTITUTION },
{ MAKE_KEY_NAME3(CLS, "HTTPS", DDE, "Application"), "", DDE_NAME, NO_SUBSTITUTION },
{ MAKE_KEY_NAME3(CLS, "HTTPS", DDE, "Topic"), "", "WWW_OpenURL", NO_SUBSTITUTION },
{ MAKE_KEY_NAME3(CLS, "HTTPS", DDE, "ifexec"), "", DDE_IFEXEC, NO_SUBSTITUTION },
{ MAKE_KEY_NAME2(CLS, "FTP", DDE), "", DDE_COMMAND, NO_SUBSTITUTION },
{ MAKE_KEY_NAME3(CLS, "FTP", DDE, "Application"), "", DDE_NAME, NO_SUBSTITUTION },
{ MAKE_KEY_NAME3(CLS, "FTP", DDE, "Topic"), "", "WWW_OpenURL", NO_SUBSTITUTION },
{ MAKE_KEY_NAME3(CLS, "FTP", DDE, "ifexec"), "", DDE_IFEXEC, NO_SUBSTITUTION },
{ MAKE_KEY_NAME2(CLS, CLS_HTML, DDE), "", DDE_COMMAND, NO_SUBSTITUTION | NON_ESSENTIAL },
{ MAKE_KEY_NAME3(CLS, CLS_HTML, DDE, "Application"), "", DDE_NAME, NO_SUBSTITUTION | NON_ESSENTIAL },
{ MAKE_KEY_NAME3(CLS, CLS_HTML, DDE, "Topic"), "", "WWW_OpenURL", NO_SUBSTITUTION | NON_ESSENTIAL },
{ MAKE_KEY_NAME2(CLS, CLS_URL, DDE), "", DDE_COMMAND, NO_SUBSTITUTION | NON_ESSENTIAL },
{ MAKE_KEY_NAME3(CLS, CLS_URL, DDE, "Application"), "", DDE_NAME, NO_SUBSTITUTION | NON_ESSENTIAL },
{ MAKE_KEY_NAME3(CLS, CLS_URL, DDE, "Topic"), "", "WWW_OpenURL", NO_SUBSTITUTION | NON_ESSENTIAL },
{ MAKE_KEY_NAME2(CLS, "HTTP", DDE), "", DDE_COMMAND, NO_SUBSTITUTION | NON_ESSENTIAL },
{ MAKE_KEY_NAME3(CLS, "HTTP", DDE, "Application"), "", DDE_NAME, NO_SUBSTITUTION | NON_ESSENTIAL },
{ MAKE_KEY_NAME3(CLS, "HTTP", DDE, "Topic"), "", "WWW_OpenURL", NO_SUBSTITUTION | NON_ESSENTIAL },
{ MAKE_KEY_NAME2(CLS, "HTTPS", DDE), "", DDE_COMMAND, NO_SUBSTITUTION | NON_ESSENTIAL },
{ MAKE_KEY_NAME3(CLS, "HTTPS", DDE, "Application"), "", DDE_NAME, NO_SUBSTITUTION | NON_ESSENTIAL },
{ MAKE_KEY_NAME3(CLS, "HTTPS", DDE, "Topic"), "", "WWW_OpenURL", NO_SUBSTITUTION | NON_ESSENTIAL },
{ MAKE_KEY_NAME2(CLS, "FTP", DDE), "", DDE_COMMAND, NO_SUBSTITUTION | NON_ESSENTIAL },
{ MAKE_KEY_NAME3(CLS, "FTP", DDE, "Application"), "", DDE_NAME, NO_SUBSTITUTION | NON_ESSENTIAL },
{ MAKE_KEY_NAME3(CLS, "FTP", DDE, "Topic"), "", "WWW_OpenURL", NO_SUBSTITUTION | NON_ESSENTIAL },
{ MAKE_KEY_NAME2(CLS, "GOPHER", DDE), "", DDE_COMMAND, NO_SUBSTITUTION | NON_ESSENTIAL },
{ MAKE_KEY_NAME3(CLS, "GOPHER", DDE, "Application"), "", DDE_NAME, NO_SUBSTITUTION | NON_ESSENTIAL },
{ MAKE_KEY_NAME3(CLS, "GOPHER", DDE, "Topic"), "", "WWW_OpenURL", NO_SUBSTITUTION | NON_ESSENTIAL },
{ MAKE_KEY_NAME3(CLS, "GOPHER", DDE, "ifexec"), "", DDE_IFEXEC, NO_SUBSTITUTION },
{ MAKE_KEY_NAME2(CLS, "CHROME", DDE), "", DDE_COMMAND, NO_SUBSTITUTION | NON_ESSENTIAL },
{ MAKE_KEY_NAME3(CLS, "CHROME", DDE, "Application"), "", DDE_NAME, NO_SUBSTITUTION | NON_ESSENTIAL },
{ MAKE_KEY_NAME3(CLS, "CHROME", DDE, "Topic"), "", "WWW_OpenURL", NO_SUBSTITUTION | NON_ESSENTIAL },
{ MAKE_KEY_NAME3(CLS, "CHROME", DDE, "ifexec"), "", DDE_IFEXEC, NO_SUBSTITUTION },
// Windows XP Start Menu
{ MAKE_KEY_NAME2(SMI, "%APPEXE%", DI),
"",
"%APPPATH%,0",
PATH_SUBSTITUTION | EXE_SUBSTITUTION | NON_ESSENTIAL },
APP_PATH_SUBSTITUTION | EXE_NAME_SUBSTITUTION | HKLM_ONLY | NON_ESSENTIAL },
{ MAKE_KEY_NAME2(SMI, "%APPEXE%", II),
"HideIconsCommand",
"\"%UNINSTPATH%\" /HideShortcuts",
UNINST_PATH_SUBSTITUTION | EXE_NAME_SUBSTITUTION | HKLM_ONLY | NON_ESSENTIAL },
{ MAKE_KEY_NAME2(SMI, "%APPEXE%", II),
"ReinstallCommand",
"\"%UNINSTPATH%\" /SetAsDefaultAppGlobal",
UNINST_PATH_SUBSTITUTION | EXE_NAME_SUBSTITUTION | HKLM_ONLY | NON_ESSENTIAL },
{ MAKE_KEY_NAME2(SMI, "%APPEXE%", II),
"ShowIconsCommand",
"\"%UNINSTPATH%\" /ShowShortcuts",
UNINST_PATH_SUBSTITUTION | EXE_NAME_SUBSTITUTION | HKLM_ONLY | NON_ESSENTIAL },
{ MAKE_KEY_NAME2(SMI, "%APPEXE%", SOP),
"",
"%APPPATH%",
PATH_SUBSTITUTION | EXE_SUBSTITUTION | NON_ESSENTIAL },
APP_PATH_SUBSTITUTION | EXE_NAME_SUBSTITUTION | HKLM_ONLY | NON_ESSENTIAL },
{ MAKE_KEY_NAME1(SMI, "%APPEXE%\\shell\\properties\\command"),
"",
"\"%APPPATH%\" -preferences",
PATH_SUBSTITUTION | EXE_SUBSTITUTION | NON_ESSENTIAL },
APP_PATH_SUBSTITUTION | EXE_NAME_SUBSTITUTION | HKLM_ONLY | NON_ESSENTIAL },
{ MAKE_KEY_NAME1(SMI, "%APPEXE%\\shell\\safemode\\command"),
"",
"\"%APPPATH%\" -safe-mode",
PATH_SUBSTITUTION | EXE_SUBSTITUTION | NON_ESSENTIAL }
APP_PATH_SUBSTITUTION | EXE_NAME_SUBSTITUTION | HKLM_ONLY | NON_ESSENTIAL }
// These values must be set by hand, since they contain localized strings.
// firefox.exe\shell\properties (default) REG_SZ Firefox &Options
@@ -390,6 +427,12 @@ nsWindowsShellService::SetDefaultBrowserVista()
NS_IMETHODIMP
nsWindowsShellService::IsDefaultBrowser(PRBool aStartupCheck, PRBool* aIsDefaultBrowser)
{
// To support side by side installs on Vista we also need to check if the
// FirefoxHTML and FirefoxURL registry keys in HKLM / HKCU point to our
// install location. If the HKLM keys point to this install location we have
// to verify that the keys don't exist in HKCU and remove them if the app is
// then set as default. If the HKLM keys don't point to this install location
// then we have to add these keys in HKCU to over-ride the HKLM keys.
if (IsDefaultBrowserVista(aStartupCheck, aIsDefaultBrowser))
return NS_OK;
@@ -433,7 +476,7 @@ nsWindowsShellService::IsDefaultBrowser(PRBool aStartupCheck, PRBool* aIsDefault
nsCAutoString dataLongPath(settings->valueData);
nsCAutoString dataShortPath(settings->valueData);
nsCAutoString key(settings->keyName);
if (settings->flags & PATH_SUBSTITUTION) {
if (settings->flags & APP_PATH_SUBSTITUTION) {
PRInt32 offset = dataLongPath.Find("%APPPATH%");
dataLongPath.Replace(offset, 9, appLongPath);
// Remove the quotes around %APPPATH% in VAL_OPEN for short paths
@@ -443,7 +486,7 @@ nsWindowsShellService::IsDefaultBrowser(PRBool aStartupCheck, PRBool* aIsDefault
else
dataShortPath.Replace(offset, 9, appShortPath);
}
if (settings->flags & EXE_SUBSTITUTION) {
if (settings->flags & EXE_NAME_SUBSTITUTION) {
PRInt32 offset = key.Find("%APPEXE%");
key.Replace(offset, 8, exeName);
}
@@ -502,26 +545,39 @@ nsWindowsShellService::SetDefaultBrowser(PRBool aClaimAllTypes, PRBool aForAllUs
return rv;
ToUpperCase(exeName);
nsCOMPtr<nsIFile> appDir;
rv = lf->GetParent(getter_AddRefs(appDir));
if (NS_FAILED(rv))
return rv;
nsCAutoString parentPath;
appDir->GetNativePath(parentPath);
nsCAutoString uninstLongPath(parentPath.get());
uninstLongPath.Append(UNINSTALL_EXE);
for (settings = gSettings; settings < end; ++settings) {
nsCAutoString dataLongPath(settings->valueData);
nsCAutoString key(settings->keyName);
if (settings->flags & PATH_SUBSTITUTION) {
if (settings->flags & APP_PATH_SUBSTITUTION) {
PRInt32 offset = dataLongPath.Find("%APPPATH%");
dataLongPath.Replace(offset, 9, appLongPath);
}
if (settings->flags & EXE_SUBSTITUTION) {
if (settings->flags & UNINST_PATH_SUBSTITUTION) {
PRInt32 offset = dataLongPath.Find("%UNINSTPATH%");
dataLongPath.Replace(offset, 12, uninstLongPath);
}
if (settings->flags & EXE_NAME_SUBSTITUTION) {
PRInt32 offset = key.Find("%APPEXE%");
key.Replace(offset, 8, exeName);
}
PRBool replaceExisting = aClaimAllTypes ? PR_TRUE : !(settings->flags & NON_ESSENTIAL);
SetRegKey(key.get(), settings->valueName, dataLongPath.get(),
replaceExisting, aForAllUsers);
(settings->flags & HKLM_ONLY));
}
// Select the Default Browser for the Windows XP Start Menu
SetRegKey(NS_LITERAL_CSTRING(SMI).get(), "", exeName.get(), aClaimAllTypes,
aForAllUsers);
SetRegKey(NS_LITERAL_CSTRING(SMI).get(), "", exeName.get(), PR_TRUE);
nsCOMPtr<nsIStringBundleService> bundleService(do_GetService("@mozilla.org/intl/stringbundle;1"));
if (!bundleService)
@@ -545,8 +601,7 @@ nsWindowsShellService::SetDefaultBrowser(PRBool aClaimAllTypes, PRBool aForAllUs
nsCAutoString key1(NS_LITERAL_CSTRING(SMI));
key1.Append(exeName);
key1.Append("\\");
SetRegKey(key1.get(), "", nativeFullName.get(), aClaimAllTypes,
aForAllUsers);
SetRegKey(key1.get(), "", nativeFullName.get(), PR_TRUE);
// Set the Options and Safe Mode start menu context menu item labels
nsCAutoString optionsKey(SMI);
@@ -577,13 +632,11 @@ nsWindowsShellService::SetDefaultBrowser(PRBool aClaimAllTypes, PRBool aForAllUs
// For the now, we use 'A' APIs (see bug 240272, 239279)
NS_UTF16ToCString(optionsTitle, NS_CSTRING_ENCODING_NATIVE_FILESYSTEM,
nativeTitle);
SetRegKey(optionsKey.get(), "", nativeTitle.get(), aClaimAllTypes,
aForAllUsers);
SetRegKey(optionsKey.get(), "", nativeTitle.get(), PR_TRUE);
// For the now, we use 'A' APIs (see bug 240272, 239279)
NS_UTF16ToCString(safeModeTitle, NS_CSTRING_ENCODING_NATIVE_FILESYSTEM,
nativeTitle);
SetRegKey(safeModeKey.get(), "", nativeTitle.get(), aClaimAllTypes,
aForAllUsers);
SetRegKey(safeModeKey.get(), "", nativeTitle.get(), PR_TRUE);
// Refresh the Shell
SHChangeNotify(SHCNE_ASSOCCHANGED, SHCNF_IDLIST, 0, 0);
@@ -592,19 +645,14 @@ nsWindowsShellService::SetDefaultBrowser(PRBool aClaimAllTypes, PRBool aForAllUs
void
nsWindowsShellService::SetRegKey(const char* aKeyName, const char* aValueName,
const char* aValue, PRBool aReplaceExisting,
PRBool aForAllUsers)
const char* aValue, PRBool aHKLMOnly)
{
char buf[MAX_BUF];
DWORD len = sizeof buf;
HKEY theKey;
nsresult rv = OpenKeyForWriting(aKeyName, &theKey, aForAllUsers, PR_TRUE);
if (NS_FAILED(rv) && rv != NS_ERROR_FILE_NOT_FOUND) return;
// If we're not allowed to replace an existing key, and one exists (i.e. the
// result isn't ERROR_FILE_NOT_FOUND, then just return now.
if (!aReplaceExisting && rv != NS_ERROR_FILE_NOT_FOUND)
nsresult rv = OpenKeyForWriting(HKEY_LOCAL_MACHINE, aKeyName, &theKey, aHKLMOnly);
if (NS_FAILED(rv))
return;
// Get the old value

View File

@@ -61,8 +61,7 @@ protected:
PRBool GetMailAccountKey(HKEY* aResult);
void SetRegKey(const char* aKeyName, const char* aValueName,
const char* aValue, PRBool aReplaceExisting,
PRBool aForAllUsers);
const char* aValue, PRBool aHKLMOnly);
private:
PRBool mCheckedThisSession;

View File

@@ -68,5 +68,7 @@ extensions/inspector@mozilla.org/components/inspector.xpt
extensions/inspector@mozilla.org/components/@DLL_PREFIX@inspector@DLL_SUFFIX@
uninstall/UninstallFirefox.exe
uninstall/UninstallDeerPark.exe
uninstall/uninst.exe
uninstall/uninstall.exe
components/myspell/en-US.dic
components/myspell/en-US.aff

View File

@@ -56,6 +56,7 @@ INSTALLER_FILES = \
app.tag \
nsis/installer.nsi \
nsis/uninstaller.nsi \
nsis/shared.nsh \
$(NULL)
BRANDING_FILES = \

View File

@@ -9,3 +9,4 @@
!define FileMainEXE "@MOZ_APP_NAME@.exe"
!define WindowClass "FirefoxMessageWindow"
!define DDEApplication "Firefox"
!define AppRegName "Firefox"

View File

@@ -83,7 +83,6 @@ Var fhUninstallLog
!insertmacro GetOptions
!insertmacro GetRoot
!insertmacro DriveSpace
!insertmacro GetParent
; NSIS provided macros that we have overridden
!include overrides.nsh
@@ -97,6 +96,8 @@ Var fhUninstallLog
!include locales.nsi
!include version.nsh
VIAddVersionKey "FileDescription" "${BrandShortName} Installer"
!insertmacro RegCleanMain
!insertmacro RegCleanUninstall
!insertmacro CloseApp
@@ -105,9 +106,10 @@ Var fhUninstallLog
!insertmacro CreateRegKey
!insertmacro CanWriteToInstallDir
!insertmacro CheckDiskSpace
!insertmacro AddHandlerValues
!insertmacro DisplayCopyErrMsg
!insertmacro GetExistingInstallPath
!insertmacro IsVista
!include shared.nsh
Name "${BrandFullName}"
OutFile "setup.exe"
@@ -432,240 +434,35 @@ Section "-Application" Section1
; MUST add children first so they will be removed first on uninstall so they
; will be empty when the key is deleted. This allows the uninstaller to
; specify that only empty keys will be deleted.
${SetAppKeys}
StrCpy $0 "Software\Mozilla\${BrandFullNameInternal}\${AppVersion} (${AB_CD})\Main"
${WriteRegStr2} $TmpVal "$0" "Install Directory" "$INSTDIR" 0
${WriteRegStr2} $TmpVal "$0" "PathToExe" "$INSTDIR\${FileMainEXE}" 0
${WriteRegStr2} $TmpVal "$0" "Program Folder Path" "$SMPROGRAMS\$StartMenuDir" 0
${WriteRegDWORD2} $TmpVal "$0" "Create Quick Launch Shortcut" $AddQuickLaunchSC 0
${WriteRegDWORD2} $TmpVal "$0" "Create Desktop Shortcut" $AddDesktopSC 0
; XXXrstrong - this should be set in shared.nsh along with "Create Quick
; Launch Shortcut" and Create Desktop Shortcut.
StrCpy $0 "Software\Mozilla\${BrandFullNameInternal}\${AppVersion} (${AB_CD})\Uninstall"
${WriteRegDWORD2} $TmpVal "$0" "Create Start Menu Shortcut" $AddStartMenuSC 0
StrCpy $0 "Software\Mozilla\${BrandFullNameInternal}\${AppVersion} (${AB_CD})\Uninstall"
${WriteRegStr2} $TmpVal "$0" "Uninstall Log Folder" "$INSTDIR\uninstall" 0
${WriteRegStr2} $TmpVal "$0" "Description" "${BrandFullNameInternal} (${AppVersion})" 0
${FixFileKeys}
StrCpy $0 "Software\Mozilla\${BrandFullNameInternal}\${AppVersion} (${AB_CD})"
${WriteRegStr2} $TmpVal "$0" "" "${AppVersion} (${AB_CD})" 0
${FixProtocolKeys}
StrCpy $0 "Software\Mozilla\${BrandFullNameInternal} ${AppVersion}\bin"
${WriteRegStr2} $TmpVal "$0" "PathToExe" "$INSTDIR\${FileMainEXE}" 0
; The following keys should only be set if we can write to HKLM
${If} $TmpVal == "HKLM"
; Uninstall keys can only exist under HKLM on some versions of windows.
${SetUninstallKeys}
StrCpy $0 "Software\Mozilla\${BrandFullNameInternal} ${AppVersion}\extensions"
${WriteRegStr2} $TmpVal "$0" "Components" "$INSTDIR\components" 0
${WriteRegStr2} $TmpVal "$0" "Plugins" "$INSTDIR\plugins" 0
; Set the Start Menu Internet and Vista Registered App HKLM registry keys.
${SetStartMenuInternet}
StrCpy $0 "Software\Mozilla\${BrandFullNameInternal} ${AppVersion}"
${WriteRegStr2} $TmpVal "$0" "GeckoVer" "${GREVersion}" 0
StrCpy $0 "Software\Mozilla\${BrandFullNameInternal}"
${WriteRegStr2} $TmpVal "$0" "" "${GREVersion}" 0
${WriteRegStr2} $TmpVal "$0" "CurrentVersion" "${AppVersion} (${AB_CD})" 0
; XXXrstrong - there are several values that will be overwritten by and
; overwrite other installs of the same application.
${StrFilter} "${FileMainEXE}" "+" "" "" $R9
StrCpy $0 "Software\Clients\StartMenuInternet\$R9"
${WriteRegStr2} $TmpVal "$0" "" "${BrandShortName}" 0
StrCpy $0 "Software\Clients\StartMenuInternet\$R9\DefaultIcon"
StrCpy $1 "$\"$INSTDIR\${FileMainEXE}$\",0"
${WriteRegStr2} $TmpVal "$0" "" "$1" 0
; The Reinstall Command is defined at
; http://msdn.microsoft.com/library/default.asp?url=/library/en-us/shellcc/platform/shell/programmersguide/shell_adv/registeringapps.asp
StrCpy $0 "Software\Clients\StartMenuInternet\$R9\InstallInfo"
StrCpy $1 "$\"$INSTDIR\uninstall\uninst.exe$\" /HideShortcuts"
${WriteRegStr2} $TmpVal "$0" "HideIconsCommand" "$1" 0
${WriteRegDWORD2} $TmpVal "$0" "IconsVisible" 1 0
StrCpy $0 "Software\Clients\StartMenuInternet\$R9\InstallInfo"
StrCpy $1 "$\"$INSTDIR\${FileMainEXE}$\" -silent -setDefaultBrowser"
${WriteRegStr2} $TmpVal "$0" "ReinstallCommand" "$1" 0
StrCpy $1 "$\"$INSTDIR\uninstall\uninst.exe$\" /ShowShortcuts"
${WriteRegStr2} $TmpVal "$0" "ShowIconsCommand" "$1" 0
StrCpy $0 "Software\Clients\StartMenuInternet\$R9\shell\open\command"
${WriteRegStr2} $TmpVal "$0" "" "$INSTDIR\${FileMainEXE}" 0
StrCpy $0 "Software\Clients\StartMenuInternet\$R9\shell\properties"
${WriteRegStr2} $TmpVal "$0" "" "$(OPTIONS)" 0
StrCpy $0 "Software\Clients\StartMenuInternet\$R9\shell\properties\command"
${WriteRegStr2} $TmpVal "$0" "" "$INSTDIR\${FileMainEXE} -preferences" 0
${IsVista} $R9
${If} $R9 == "true"
; For Vista these keys and name / value pairs may need to be created during
; install.
ReadRegStr $0 HKLM "Software\Classes\.shtml" "Content Type"
${If} $0 == ""
StrCpy $0 "Software\Classes\.shtml"
${WriteRegStr2} $TmpVal "$0" "" "FirefoxHTML" 0
${WriteRegStr2} $TmpVal "$0" "Content Type" "text/html" 0
${WriteRegStr2} $TmpVal "$0" "PerceivedType" "text" 0
; If we are writing to HKLM and create the quick launch and the desktop
; shortcuts set IconsVisible to 1 otherwise to 0.
${If} $AddQuickLaunchSC == 1
${OrIf} $AddDesktopSC == 1
${StrFilter} "${FileMainEXE}" "+" "" "" $R9
StrCpy $0 "Software\Clients\StartMenuInternet\$R9\InstallInfo"
WriteRegDWORD HKLM "$0" "IconsVisible" 1
${Else}
WriteRegDWORD HKLM "$0" "IconsVisible" 0
${EndIf}
ReadRegStr $0 HKLM "Software\Classes\.xht" "Content Type"
${If} $0 == ""
StrCpy $0 "Software\Classes\.xht"
${WriteRegStr2} $TmpVal "$0" "" "FirefoxHTML" 0
${WriteRegStr2} $TmpVal "$0" "Content Type" "application/xhtml+xml" 0
${EndIf}
ReadRegStr $0 HKLM "Software\Classes\.xhtml" "Content Type"
${If} $0 == ""
StrCpy $0 "Software\Classes\.xhtml"
${WriteRegStr2} $TmpVal "$0" "" "FirefoxHTML" 0
${WriteRegStr2} $TmpVal "$0" "Content Type" "application/xhtml+xml" 0
${EndIf}
ReadRegStr $0 HKLM "Software\Classes\gopher\shell\open\command" ""
${If} $0 == ""
StrCpy $0 "Software\Classes\gopher"
${WriteRegStr2} $TmpVal "$0" "" "URL:Gopher Protocol" 0
${WriteRegStr2} $TmpVal "$0" "URL Protocol" "" 0
${WriteRegDWORD2} $TmpVal "$0" "EditFlags" 2 0
StrCpy $0 "Software\Classes\gopher\DefaultIcon"
StrCpy $1 "$\"$INSTDIR\${FileMainEXE}$\",0"
${WriteRegStr2} $TmpVal "$0" "" "$1" 0
StrCpy $0 "Software\Classes\gopher\shell\open\command"
StrCpy $1 "$\"$INSTDIR\${FileMainEXE}$\" -url $\"%1$\""
${WriteRegStr2} $TmpVal "$0" "" "$1" 0
StrCpy $0 "Software\Classes\gopher\shell\open\ddeexec"
StrCpy $1 "$\"%1$\",,0,0,,,,"
${WriteRegStr2} $TmpVal "$0" "" "$1" 0
${WriteRegStr2} $TmpVal "$0" "NoActivateHandler" "" 0
StrCpy $0 "Software\Classes\gopher\shell\open\ddeexec\Application"
${WriteRegStr2} $TmpVal "$0" "" "${DDEApplication}" 0
StrCpy $0 "Software\Classes\gopher\shell\open\ddeexec\ifexec"
StrCpy $1 ",,0,0,,,,"
${WriteRegStr2} $TmpVal "$0" "" "$1" 0
StrCpy $0 "Software\Classes\gopher\shell\open\ddeexec\Topic"
${WriteRegStr2} $TmpVal "$0" "" "WWW_OpenURL" 0
${EndIf}
; Only create the key and its children if it doesn't exist
ReadRegStr $0 HKLM "Software\Classes\chrome\shell\open\command" ""
${If} $0 == ""
StrCpy $0 "Software\Classes\chrome"
${WriteRegStr2} $TmpVal "$0" "" "URL:Chrome Protocol" 0
${WriteRegStr2} $TmpVal "$0" "URL Protocol" "" 0
${WriteRegDWORD2} $TmpVal "$0" "EditFlags" 2 0
StrCpy $0 "Software\Classes\chrome\DefaultIcon"
StrCpy $1 "$\"$INSTDIR\${FileMainEXE}$\",0"
${WriteRegStr2} $TmpVal "$0" "" "$1" 0
StrCpy $0 "Software\Classes\chrome\shell\open\command"
StrCpy $1 "$\"$INSTDIR\${FileMainEXE}$\" -url $\"%1$\""
${WriteRegStr2} $TmpVal "$0" "" "$1" 0
StrCpy $0 "Software\Classes\chrome\shell\open\ddeexec"
StrCpy $1 "$\"%1$\",,0,0,,,,"
${WriteRegStr2} $TmpVal "$0" "" "$1" 0
${WriteRegStr2} $TmpVal "$0" "NoActivateHandler" "" 0
StrCpy $0 "Software\Classes\chrome\shell\open\ddeexec\Application"
${WriteRegStr2} $TmpVal "$0" "" "${DDEApplication}" 0
StrCpy $0 "Software\Classes\chrome\shell\open\ddeexec\ifexec"
StrCpy $1 ",,0,0,,,,"
${WriteRegStr2} $TmpVal "$0" "" "$1" 0
StrCpy $0 "Software\Classes\chrome\shell\open\ddeexec\Topic"
${WriteRegStr2} $TmpVal "$0" "" "WWW_OpenURL" 0
${EndIf}
; Always set the file and protocol handlers since they may specify a
; different path and the path is used by Vista when setting associations.
StrCpy $0 "Software\Classes\FirefoxURL"
${WriteRegStr2} $TmpVal "$0" "" "Firefox URL" 0
${WriteRegStr2} $TmpVal "$0" "FriendlyTypeName" "Firefox URL" 0
${WriteRegStr2} $TmpVal "$0" "URL Protocol" "" 0
${WriteRegDWORD2} $TmpVal "$0" "EditFlags" 2 0
StrCpy $0 "Software\Classes\FirefoxURL\DefaultIcon"
StrCpy $1 "$\"$INSTDIR\${FileMainEXE}$\",0"
${WriteRegStr2} $TmpVal "$0" "" "$1" 0
StrCpy $0 "Software\Classes\FirefoxURL\shell\open\command"
StrCpy $1 "$\"$INSTDIR\${FileMainEXE}$\" -url $\"%1$\""
${WriteRegStr2} $TmpVal "$0" "" "$1" 0
StrCpy $0 "Software\Classes\FirefoxURL\shell\open\ddeexec"
StrCpy $1 "$\"%1$\",,0,0,,,,"
${WriteRegStr2} $TmpVal "$0" "" "$1" 0
${WriteRegStr2} $TmpVal "$0" "NoActivateHandler" "" 0
StrCpy $0 "Software\Classes\FirefoxURL\shell\open\ddeexec\Application"
${WriteRegStr2} $TmpVal "$0" "" "${DDEApplication}" 0
StrCpy $0 "Software\Classes\FirefoxURL\shell\open\ddeexec\ifexec"
StrCpy $1 ",,0,0,,,,"
${WriteRegStr2} $TmpVal "$0" "" "$1" 0
StrCpy $0 "Software\Classes\FirefoxURL\shell\open\ddeexec\Topic"
${WriteRegStr2} $TmpVal "$0" "" "WWW_OpenURL" 0
StrCpy $0 "Software\Classes\FirefoxHTML\DefaultIcon"
StrCpy $1 "$\"$INSTDIR\${FileMainEXE}$\",1"
${WriteRegStr2} $TmpVal "$0" "" "$1" 0
StrCpy $0 "Software\Classes\FirefoxHTML\shell\open\command"
StrCpy $1 "$\"$INSTDIR\${FileMainEXE}$\" -url $\"%1$\""
${WriteRegStr2} $TmpVal "$0" "" "$1" 0
StrCpy $0 "Software\Classes\FirefoxHTML\shell\open\ddeexec"
StrCpy $1 "$\"%1$\",,0,0,,,,"
${WriteRegStr2} $TmpVal "$0" "" "$1" 0
${WriteRegStr2} $TmpVal "$0" "NoActivateHandler" "" 0
StrCpy $0 "Software\Classes\FirefoxHTML\shell\open\ddeexec\Application"
${WriteRegStr2} $TmpVal "$0" "" "${DDEApplication}" 0
StrCpy $0 "Software\Classes\FirefoxHTML\shell\open\ddeexec\ifexec"
StrCpy $1 ",,0,0,,,,"
${WriteRegStr2} $TmpVal "$0" "" "$1" 0
StrCpy $0 "Software\Classes\FirefoxHTML\shell\open\ddeexec\Topic"
${WriteRegStr2} $TmpVal "$0" "" "WWW_OpenURL" 0
; Vista Registered Application
${StrFilter} "${FileMainEXE}" "+" "" "" $R9
StrCpy $0 "Software\RegisteredApplications"
StrCpy $1 "Software\Clients\StartMenuInternet\$R9\Capabilities"
${WriteRegStr2} $TmpVal "$0" "${DDEApplication}" "$1" 0
; Vista Capabilities registry keys
StrCpy $0 "Software\Clients\StartMenuInternet\$R9\Capabilities"
StrCpy $1 "$\"$INSTDIR\${FileMainEXE}$\",0"
${WriteRegStr2} $TmpVal "$0" "ApplicationDescription" "$(REG_APP_DESC)" 0
${WriteRegStr2} $TmpVal "$0" "ApplicationIcon" "$1" 0
StrCpy $0 "Software\Clients\StartMenuInternet\$R9\Capabilities\FileAssociations"
${WriteRegStr2} $TmpVal "$0" ".htm" "FirefoxHTML" 0
${WriteRegStr2} $TmpVal "$0" ".html" "FirefoxHTML" 0
${WriteRegStr2} $TmpVal "$0" ".shtml" "FirefoxHTML" 0
${WriteRegStr2} $TmpVal "$0" ".xht" "FirefoxHTML" 0
${WriteRegStr2} $TmpVal "$0" ".xhtml" "FirefoxHTML" 0
StrCpy $0 "Software\Clients\StartMenuInternet\$R9\Capabilities\StartMenu"
${WriteRegStr2} $TmpVal "$0" "StartMenuInternet" "$R9" 0
StrCpy $0 "Software\Clients\StartMenuInternet\$R9\Capabilities\URLAssociations"
${WriteRegStr2} $TmpVal "$0" "chrome" "FirefoxURL" 0
${WriteRegStr2} $TmpVal "$0" "ftp" "FirefoxURL" 0
${WriteRegStr2} $TmpVal "$0" "gopher" "FirefoxURL" 0
${WriteRegStr2} $TmpVal "$0" "http" "FirefoxURL" 0
${WriteRegStr2} $TmpVal "$0" "https" "FirefoxURL" 0
${EndIf}
; These need special handling on uninstall since they may be overwritten by
@@ -674,27 +471,9 @@ Section "-Application" Section1
${WriteRegStr2} $TmpVal "$0" "" "$INSTDIR\${FileMainEXE}" 0
${WriteRegStr2} $TmpVal "$0" "Path" "$INSTDIR" 0
StrCpy $0 "Software\Classes\MIME\Database\Content Type\application/x-xpinstall;app=firefox"
${WriteRegStr2} $TmpVal "$0" "Extension" ".xpi" 0
StrCpy $0 "Software\Microsoft\MediaPlayer\ShimInclusionList\$R9"
${CreateRegKey} "$TmpVal" "$0" 0
; Write the uninstall registry keys
StrCpy $0 "Software\Microsoft\Windows\CurrentVersion\Uninstall\${BrandFullNameInternal} (${AppVersion})"
StrCpy $1 "$INSTDIR\uninstall\uninst.exe"
${WriteRegStr2} $TmpVal "$0" "Comments" "${BrandFullNameInternal}" 0
${WriteRegStr2} $TmpVal "$0" "DisplayIcon" "$INSTDIR\${FileMainEXE},0" 0
${WriteRegStr2} $TmpVal "$0" "DisplayName" "${BrandFullNameInternal} (${AppVersion})" 0
${WriteRegStr2} $TmpVal "$0" "DisplayVersion" "${AppVersion} (${AB_CD})" 0
${WriteRegStr2} $TmpVal "$0" "InstallLocation" "$INSTDIR" 0
${WriteRegStr2} $TmpVal "$0" "Publisher" "Mozilla" 0
${WriteRegStr2} $TmpVal "$0" "UninstallString" "$1" 0
${WriteRegStr2} $TmpVal "$0" "URLInfoAbout" "${URLInfoAbout}" 0
${WriteRegStr2} $TmpVal "$0" "URLUpdateInfo" "${URLUpdateInfo}" 0
${WriteRegDWORD2} $TmpVal "$0" "NoModify" 1 0
${WriteRegDWORD2} $TmpVal "$0" "NoRepair" 1 0
!insertmacro MUI_STARTMENU_WRITE_BEGIN Application
; Create Start Menu shortcuts
@@ -905,7 +684,7 @@ Function CopyFile
; If the file is installed into the installation directory remove the
; installation directory's path from the file path when writing to the
; uninstall.log so it will be a relative path. This allows the same
; uninst.exe to be used with zip builds if we supply an uninstall.log.
; helper.exe to be used with zip builds if we supply an uninstall.log.
${WordReplace} "$R1$R3\$R7" "$INSTDIR" "" "+" $R3
${LogUninstall} "File: $R3"
${EndIf}
@@ -1067,22 +846,6 @@ Function leaveComponents
FunctionEnd
Function preDirectory
${IsVista} $R9
${If} $R9 == "true"
SetShellVarContext all ; Set SHCTX to HKLM
${GetExistingInstallPath} "Software\Mozilla" $R9
${If} $R9 != "false"
StrCpy $INSTDIR "$R9"
${CheckDiskSpace} $R9
${If} $R9 == "true"
${CanWriteToInstallDir} $R9
${If} $R9 == "true"
Abort
${EndIf}
${EndIf}
${EndIf}
${EndIf}
${If} $InstallType != 4
${CheckDiskSpace} $R9
${If} $R9 != "false"

View File

@@ -0,0 +1,373 @@
# ***** 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 the Mozilla Installer code.
#
# The Initial Developer of the Original Code is Mozilla Foundation
# Portions created by the Initial Developer are Copyright (C) 2006
# the Initial Developer. All Rights Reserved.
#
# Contributor(s):
# Robert Strong <robert.bugzilla@gmail.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 *****
!macro PostUpdate
SetShellVarContext all
${SetStartMenuInternet}
; Remove registry entries for non-existent apps and for apps that point to our
; install location in the Software\Mozilla key.
SetShellVarContext current ; Set SHCTX to HKCU
${RegCleanMain} "Software\Mozilla"
SetShellVarContext all ; Set SHCTX to HKLM
${RegCleanMain} "Software\Mozilla"
; Remove uninstall entries that point to our install location
${RegCleanUninstall}
; Add Software\Mozilla\ registry entries
${SetAppKeys}
${SetUninstallKeys}
${FixFileKeys}
${FixProtocolKeys}
!macroend
!define PostUpdate "!insertmacro PostUpdate"
!macro SetAsDefaultAppUser
SetShellVarContext current
${SetHandlers}
!macroend
!define SetAsDefaultAppUser "!insertmacro SetAsDefaultAppUser"
!macro SetAsDefaultAppGlobal
SetShellVarContext all
${SetHandlers}
${SetStartMenuInternet}
WriteRegStr HKLM "Software\Clients\StartMenuInternet" "" "$R9"
${ShowShortcuts}
!macroend
!define SetAsDefaultAppGlobal "!insertmacro SetAsDefaultAppGlobal"
!macro HideShortcuts
${StrFilter} "${FileMainEXE}" "+" "" "" $0
StrCpy $R1 "Software\Clients\StartMenuInternet\$0\InstallInfo"
WriteRegDWORD HKLM $R1 "IconsVisible" 0
SetShellVarContext all ; Set $DESKTOP to All Users
${Unless} ${FileExists} "$DESKTOP\${BrandFullName}.lnk"
SetShellVarContext current ; Set $DESKTOP to the current user's desktop
${EndUnless}
${If} ${FileExists} "$DESKTOP\${BrandFullName}.lnk"
ShellLink::GetShortCutArgs "$DESKTOP\${BrandFullName}.lnk"
Pop $0
${If} $0 == ""
ShellLink::GetShortCutTarget "$DESKTOP\${BrandFullName}.lnk"
Pop $0
; Needs to handle short paths
${If} $0 == "$INSTDIR\${FileMainEXE}"
Delete "$DESKTOP\${BrandFullName}.lnk"
${EndIf}
${EndIf}
${EndIf}
${If} ${FileExists} "$QUICKLAUNCH\${BrandFullName}.lnk"
ShellLink::GetShortCutArgs "$QUICKLAUNCH\${BrandFullName}.lnk"
Pop $0
${If} $0 == ""
ShellLink::GetShortCutTarget "$QUICKLAUNCH\${BrandFullName}.lnk"
Pop $0
; Needs to handle short paths
${If} $0 == "$INSTDIR\${FileMainEXE}"
Delete "$QUICKLAUNCH\${BrandFullName}.lnk"
${EndIf}
${EndIf}
${EndIf}
!macroend
!define HideShortcuts "!insertmacro HideShortcuts"
!macro ShowShortcuts
${StrFilter} "${FileMainEXE}" "+" "" "" $0
StrCpy $R1 "Software\Clients\StartMenuInternet\$0\InstallInfo"
WriteRegDWORD HKLM $R1 "IconsVisible" 1
SetShellVarContext all ; Set $DESKTOP to All Users
${Unless} ${FileExists} "$DESKTOP\${BrandFullName}.lnk"
CreateShortCut "$DESKTOP\${BrandFullName}.lnk" "$INSTDIR\${FileMainEXE}" "" "$INSTDIR\${FileMainEXE}" 0
ShellLink::SetShortCutWorkingDirectory "$DESKTOP\${BrandFullName}.lnk" "$INSTDIR"
${Unless} ${FileExists} "$DESKTOP\${BrandFullName}.lnk"
SetShellVarContext current ; Set $DESKTOP to the current user's desktop
${Unless} ${FileExists} "$DESKTOP\${BrandFullName}.lnk"
CreateShortCut "$DESKTOP\${BrandFullName}.lnk" "$INSTDIR\${FileMainEXE}" "" "$INSTDIR\${FileMainEXE}" 0
ShellLink::SetShortCutWorkingDirectory "$DESKTOP\${BrandFullName}.lnk" "$INSTDIR"
${EndUnless}
${EndUnless}
${EndUnless}
${Unless} ${FileExists} "$QUICKLAUNCH\${BrandFullName}.lnk"
CreateShortCut "$QUICKLAUNCH\${BrandFullName}.lnk" "$INSTDIR\${FileMainEXE}" "" "$INSTDIR\${FileMainEXE}" 0
ShellLink::SetShortCutWorkingDirectory "$QUICKLAUNCH\${BrandFullName}.lnk" "$INSTDIR"
${EndUnless}
!macroend
!define ShowShortcuts "!insertmacro ShowShortcuts"
!macro SetHandlers
GetFullPathName $8 "$INSTDIR\${FileMainEXE}"
StrCpy $0 "SOFTWARE\Classes"
StrCpy $2 "$\"$8$\" -url $\"%1$\" -requestPending"
; Associate the file handlers with FirefoxHTML
WriteRegStr SHCTX "$0\.htm" "" "FirefoxHTML"
WriteRegStr SHCTX "$0\.html" "" "FirefoxHTML"
WriteRegStr SHCTX "$0\.shtml" "" "FirefoxHTML"
WriteRegStr SHCTX "$0\.xht" "" "FirefoxHTML"
WriteRegStr SHCTX "$0\.xhtml" "" "FirefoxHTML"
; An empty string is used for the 5th param because FirefoxHTML is not a
; protocol handler
${AddHandlerValues} "$0\FirefoxHTML" "$2" "$8,1" "${AppRegName} Document" "" "true"
${AddHandlerValues} "$0\FirefoxURL" "$2" "$8,0" "${AppRegName} URL" "true" "true"
${AddHandlerValues} "$0\gopher" "$2" "$8,0" "URL:Gopher Protocol" "true" "true"
; An empty string is used for the 4th & 5th params because the following
; protocol handlers already have a display name and additional keys required
; for a protocol handler.
${AddHandlerValues} "$0\ftp" "$2" "$8,0" "" "" "true"
${AddHandlerValues} "$0\http" "$2" "$8,0" "" "" "true"
${AddHandlerValues} "$0\https" "$2" "$8,0" "" "" "true"
!macroend
!define SetHandlers "!insertmacro SetHandlers"
; XXXrstrong - there are several values that will be overwritten by and
; overwrite other installs of the same application.
!macro SetStartMenuInternet
GetFullPathName $8 "$INSTDIR\${FileMainEXE}"
GetFullPathName $7 "$INSTDIR\uninstall\helper.exe"
${StrFilter} "${FileMainEXE}" "+" "" "" $R9
StrCpy $0 "Software\Clients\StartMenuInternet\$R9"
; Remove existing keys so we only have our settings
DeleteRegKey HKLM "$0"
WriteRegStr HKLM "$0" "" "${BrandFullName}"
WriteRegStr HKLM "$0\DefaultIcon" "" "$8,0"
; The Reinstall Command is defined at
; http://msdn.microsoft.com/library/default.asp?url=/library/en-us/shellcc/platform/shell/programmersguide/shell_adv/registeringapps.asp
WriteRegStr HKLM "$0\InstallInfo" "HideIconsCommand" "$\"$7$\" /HideShortcuts"
WriteRegStr HKLM "$0\InstallInfo" "ShowIconsCommand" "$\"$7$\" /ShowShortcuts"
WriteRegStr HKLM "$0\InstallInfo" "ReinstallCommand" "$\"$7$\" /SetAsDefaultAppGlobal"
WriteRegStr HKLM "$0\shell\open\command" "" "$8"
WriteRegStr HKLM "$0\shell\properties" "" "$(CONTEXT_OPTIONS)"
WriteRegStr HKLM "$0\shell\properties\command" "" "$\"$8$\" -preferences"
WriteRegStr HKLM "$0\shell\safemode" "" "$(CONTEXT_SAFE_MODE)"
WriteRegStr HKLM "$0\shell\safemode\command" "" "$\"$8$\" -safemode"
; Vista Capabilities registry keys
WriteRegStr HKLM "$0\Capabilities" "ApplicationDescription" "$(REG_APP_DESC)"
WriteRegStr HKLM "$0\Capabilities" "ApplicationIcon" "$8,0"
WriteRegStr HKLM "$0\Capabilities" "ApplicationName" "${BrandShortName}"
WriteRegStr HKLM "$0\Capabilities\FileAssociations" ".htm" "FirefoxHTML"
WriteRegStr HKLM "$0\Capabilities\FileAssociations" ".html" "FirefoxHTML"
WriteRegStr HKLM "$0\Capabilities\FileAssociations" ".shtml" "FirefoxHTML"
WriteRegStr HKLM "$0\Capabilities\FileAssociations" ".xht" "FirefoxHTML"
WriteRegStr HKLM "$0\Capabilities\FileAssociations" ".xhtml" "FirefoxHTML"
WriteRegStr HKLM "$0\Capabilities\StartMenu" "StartMenuInternet" "$R9"
WriteRegStr HKLM "$0\Capabilities\URLAssociations" "ftp" "FirefoxURL"
WriteRegStr HKLM "$0\Capabilities\URLAssociations" "gopher" "FirefoxURL"
WriteRegStr HKLM "$0\Capabilities\URLAssociations" "http" "FirefoxURL"
WriteRegStr HKLM "$0\Capabilities\URLAssociations" "https" "FirefoxURL"
; Vista Registered Application
WriteRegStr HKLM "Software\RegisteredApplications" "${AppRegName}" "$0\Capabilities"
!macroend
!define SetStartMenuInternet "!insertmacro SetStartMenuInternet"
!macro SetAppKeys
StrCpy $0 "Software\Mozilla\${BrandFullNameInternal}\${AppVersion} (${AB_CD})\Main"
${WriteRegStr2} $TmpVal "$0" "Install Directory" "$INSTDIR" 0
${WriteRegStr2} $TmpVal "$0" "PathToExe" "$INSTDIR\${FileMainEXE}" 0
${WriteRegStr2} $TmpVal "$0" "Program Folder Path" "$SMPROGRAMS\$StartMenuDir" 0
SetShellVarContext all ; Set $DESKTOP to All Users
${Unless} ${FileExists} "$DESKTOP\${BrandFullName}.lnk"
SetShellVarContext current ; Set $DESKTOP to the current user's desktop
${EndUnless}
${If} ${FileExists} "$DESKTOP\${BrandFullName}.lnk"
ShellLink::GetShortCutArgs "$DESKTOP\${BrandFullName}.lnk"
Pop $1
${If} $1 == ""
ShellLink::GetShortCutTarget "$DESKTOP\${BrandFullName}.lnk"
Pop $1
; Needs to handle short paths
${If} $1 == "$INSTDIR\${FileMainEXE}"
${WriteRegDWORD2} $TmpVal "$0" "Create Desktop Shortcut" 1 0
${Else}
${WriteRegDWORD2} $TmpVal "$0" "Create Desktop Shortcut" 0 0
${EndIf}
${EndIf}
${EndIf}
; XXXrstrong - need a cleaner way to prevent unsetting SHCTX from HKLM when
; trying to find the desktop shortcut.
${If} $TmpVal == "HKCU"
SetShellVarContext current
${Else}
SetShellVarContext all
${EndIf}
${If} ${FileExists} "$QUICKLAUNCH\${BrandFullName}.lnk"
ShellLink::GetShortCutArgs "$QUICKLAUNCH\${BrandFullName}.lnk"
Pop $1
${If} $1 == ""
ShellLink::GetShortCutTarget "$QUICKLAUNCH\${BrandFullName}.lnk"
Pop $1
; Needs to handle short paths
${If} $1 == "$INSTDIR\${FileMainEXE}"
${WriteRegDWORD2} $TmpVal "$0" "Create Quick Launch Shortcut" 1 0
${Else}
${WriteRegDWORD2} $TmpVal "$0" "Create Quick Launch Shortcut" 0 0
${EndIf}
${EndIf}
${EndIf}
; XXXrstrong - "Create Start Menu Shortcut" and "Start Menu Folder" are only
; set in the installer and should also be set here for software update.
StrCpy $0 "Software\Mozilla\${BrandFullNameInternal}\${AppVersion} (${AB_CD})\Uninstall"
${WriteRegStr2} $TmpVal "$0" "Uninstall Log Folder" "$INSTDIR\uninstall" 0
${WriteRegStr2} $TmpVal "$0" "Description" "${BrandFullNameInternal} (${AppVersion})" 0
StrCpy $0 "Software\Mozilla\${BrandFullNameInternal}\${AppVersion} (${AB_CD})"
${WriteRegStr2} $TmpVal "$0" "" "${AppVersion} (${AB_CD})" 0
StrCpy $0 "Software\Mozilla\${BrandFullNameInternal} ${AppVersion}\bin"
${WriteRegStr2} $TmpVal "$0" "PathToExe" "$INSTDIR\${FileMainEXE}" 0
StrCpy $0 "Software\Mozilla\${BrandFullNameInternal} ${AppVersion}\extensions"
${WriteRegStr2} $TmpVal "$0" "Components" "$INSTDIR\components" 0
${WriteRegStr2} $TmpVal "$0" "Plugins" "$INSTDIR\plugins" 0
StrCpy $0 "Software\Mozilla\${BrandFullNameInternal} ${AppVersion}"
${WriteRegStr2} $TmpVal "$0" "GeckoVer" "${GREVersion}" 0
StrCpy $0 "Software\Mozilla\${BrandFullNameInternal}"
${WriteRegStr2} $TmpVal "$0" "" "${GREVersion}" 0
${WriteRegStr2} $TmpVal "$0" "CurrentVersion" "${AppVersion} (${AB_CD})" 0
!macroend
!define SetAppKeys "!insertmacro SetAppKeys"
!macro SetUninstallKeys
; Write the uninstall registry keys
StrCpy $0 "Software\Microsoft\Windows\CurrentVersion\Uninstall\${BrandFullNameInternal} (${AppVersion})"
GetFullPathName $8 "$INSTDIR\${FileMainEXE}"
GetFullPathName $7 "$INSTDIR\uninstall\helper.exe"
${WriteRegStr2} $TmpVal "$0" "Comments" "${BrandFullNameInternal}" 0
${WriteRegStr2} $TmpVal "$0" "DisplayIcon" "$8,0" 0
${WriteRegStr2} $TmpVal "$0" "DisplayName" "${BrandFullNameInternal} (${AppVersion})" 0
${WriteRegStr2} $TmpVal "$0" "DisplayVersion" "${AppVersion} (${AB_CD})" 0
${WriteRegStr2} $TmpVal "$0" "InstallLocation" "$INSTDIR" 0
${WriteRegStr2} $TmpVal "$0" "Publisher" "Mozilla" 0
${WriteRegStr2} $TmpVal "$0" "UninstallString" "$7" 0
${WriteRegStr2} $TmpVal "$0" "URLInfoAbout" "${URLInfoAbout}" 0
${WriteRegStr2} $TmpVal "$0" "URLUpdateInfo" "${URLUpdateInfo}" 0
${WriteRegDWORD2} $TmpVal "$0" "NoModify" 1 0
${WriteRegDWORD2} $TmpVal "$0" "NoRepair" 1 0
!macroend
!define SetUninstallKeys "!insertmacro SetUninstallKeys"
; File handler keys and name value pairs that may need to be created during
; install or upgrade.
!macro FixFileKeys
ReadRegStr $0 HKLM "Software\Classes\.shtml" "Content Type"
${If} $0 == ""
StrCpy $0 "Software\Classes\.shtml"
${WriteRegStr2} $TmpVal "$0" "" "shtmlfile" 0
${WriteRegStr2} $TmpVal "$0" "Content Type" "text/html" 0
${WriteRegStr2} $TmpVal "$0" "PerceivedType" "text" 0
${EndIf}
ReadRegStr $0 HKLM "Software\Classes\.xht" "Content Type"
${If} $0 == ""
StrCpy $0 "Software\Classes\.xht"
${WriteRegStr2} $TmpVal "$0" "" "xhtfile" 0
${WriteRegStr2} $TmpVal "$0" "Content Type" "application/xhtml+xml" 0
${EndIf}
ReadRegStr $0 HKLM "Software\Classes\.xhtml" "Content Type"
${If} $0 == ""
StrCpy $0 "Software\Classes\.xhtml"
${WriteRegStr2} $TmpVal "$0" "" "xhtmlfile" 0
${WriteRegStr2} $TmpVal "$0" "Content Type" "application/xhtml+xml" 0
${EndIf}
!macroend
!define FixFileKeys "!insertmacro FixFileKeys"
; Protocol handler keys and name value pairs that may need to be updated during
; install or upgrade.
!macro FixProtocolKeys
; Bug 301073 Comment #9 makes it so Firefox no longer supports launching
; chrome urls from the shell so remove it during install or update if the
; DefaultIcon is from firefox.exe.
ReadRegStr $0 HKLM "Software\Classes\chrome\DefaultIcon" ""
${Unless} $0 == ""
StrCpy $0 "$0" "" -13
StrCpy $0 "$0" 11
${If} "$0" == "firefox.exe"
DeleteRegKey HKLM "Software\Classes\chrome"
${EndIf}
${EndUnless}
; Store the command to open the app with an url in a register for easy access.
GetFullPathName $8 "$INSTDIR\${FileMainEXE}"
StrCpy $1 "$\"$8$\" -url $\"%1$\" -requestPending"
; Only set the gopher key if it doesn't already exist with a default value
ReadRegStr $0 HKLM "Software\Classes\gopher" ""
${If} $0 == ""
${AddHandlerValues} "Software\Classes\gopher" "$1" "$8,0" "URL:Gopher Protocol" "true" "true"
${EndIf}
; Always set the file and protocol handlers since they may specify a
; different path and the path is used by Vista when setting associations.
${AddHandlerValues} "Software\Classes\FirefoxURL" "$1" "$8,0" "${AppRegName} URL" "true" "true"
; An empty string is used for the 5th param because FirefoxHTML is not a
; protocol handler
${AddHandlerValues} "Software\Classes\FirefoxHTML" "$1" "$8,1" "${AppRegName} Document" "" "true"
!macroend
!define FixProtocolKeys "!insertmacro FixProtocolKeys"

View File

@@ -48,6 +48,9 @@ CRCCheck on
!addplugindir ./
; prevents compiling of the reg write logging.
!define NO_LOG
Var TmpVal
; Other included files may depend upon these includes!
@@ -59,7 +62,11 @@ Var TmpVal
!include WordFunc.nsh
!include MUI.nsh
!insertmacro GetOptions
!insertmacro GetParameters
!insertmacro StrFilter
!insertmacro WordReplace
!insertmacro un.LineFind
!insertmacro un.TrimNewLines
@@ -70,14 +77,24 @@ Var TmpVal
!include locales.nsi
!include version.nsh
; This is named BrandShortName helper because we use this for software update
; post update cleanup.
VIAddVersionKey "FileDescription" "${BrandShortName} Helper"
!insertmacro AddHandlerValues
!insertmacro RegCleanMain
!insertmacro RegCleanUninstall
!insertmacro WriteRegStr2
!insertmacro WriteRegDWORD2
!insertmacro un.RegCleanMain
!insertmacro un.RegCleanUninstall
!insertmacro un.CloseApp
!insertmacro un.GetSecondInstallPath
!insertmacro un.IsVista
!include shared.nsh
Name "${BrandFullName}"
OutFile "uninst.exe"
OutFile "helper.exe"
InstallDirRegKey HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${BrandFullNameInternal} (${AppVersion})" "InstallLocation"
InstallDir "$PROGRAMFILES\${BrandFullName}"
ShowUnInstDetails nevershow
@@ -173,18 +190,19 @@ Section "Uninstall"
; installing even if there is another install of Firefox that is set as the
; default browser. Now the key is always updated on install but it is only
; removed if it refers to this install location.
${If} $INSTDIR == $R1
${If} "$INSTDIR" == "$R1"
; XXXrstrong - if there is another installation of the same app ideally we
; would just modify these values. The GetSecondInstallPath macro could be
; made to provide enough information to do this.
DeleteRegKey HKLM "Software\Clients\StartMenuInternet\${FileMainEXE}"
DeleteRegValue HKLM "Software\RegisteredApplications" "${AppRegName}"
${EndIf}
StrCpy $0 "Software\Microsoft\Windows\CurrentVersion\App Paths\${FileMainEXE}"
${If} $R9 == "false"
DeleteRegKey HKLM "$0"
DeleteRegKey HKCU "$0"
StrCpy $0 "Software\Microsoft\MediaPlayer\ShimInclusionList\$R9"
StrCpy $0 "Software\Microsoft\MediaPlayer\ShimInclusionList\${FileMainEXE}"
DeleteRegKey HKLM "$0"
DeleteRegKey HKCU "$0"
StrCpy $0 "MIME\Database\Content Type\application/x-xpinstall;app=firefox"
@@ -197,7 +215,7 @@ Section "Uninstall"
Push $R0
${GetParentDir}
Pop $R1
${If} $INSTDIR == $R1
${If} "$INSTDIR" == "$R1"
WriteRegStr HKLM "$0" "" "$R9"
Push $R9
${GetParentDir}
@@ -206,11 +224,6 @@ Section "Uninstall"
${EndIf}
${EndIf}
${un.IsVista} $R9
${If} $R9 == "true"
DeleteRegValue HKLM "Software\RegisteredApplications" "${DDEApplication}"
${EndIf}
; Remove files. If we don't have a log file skip
${If} ${FileExists} "$INSTDIR\uninstall\uninstall.log"
; Copy the uninstall log file to a temporary file
@@ -380,7 +393,6 @@ Function un.preInstFiles
ClearErrors
${un.CloseApp} "true" $(WARN_APP_RUNNING_UNINSTALL)
ClearErrors
; Try one more time and if that fails uninstall what ever we are able to.
${DeleteFile} "$INSTDIR\${FileMainEXE}"
${EndIf}
${EndIf}
@@ -426,61 +438,57 @@ Function .onInit
${EndUnless}
${GetParameters} $R0
StrCpy $R1 "Software\Clients\StartMenuInternet\${FileMainEXE}\InstallInfo"
SetShellVarContext all ; Set $DESKTOP to All Users
; Hide icons - initiated from Set Program Access and Defaults
${If} $R0 == "/HideShortcuts"
WriteRegDWORD HKLM $R1 "IconsVisible" 0
${Unless} ${FileExists} "$DESKTOP\${BrandFullName}.lnk"
SetShellVarContext current ; Set $DESKTOP to the current user's desktop
${EndUnless}
${If} ${FileExists} "$DESKTOP\${BrandFullName}.lnk"
ShellLink::GetShortCutArgs "$DESKTOP\${BrandFullName}.lnk"
Pop $0
${If} $0 == ""
ShellLink::GetShortCutTarget "$DESKTOP\${BrandFullName}.lnk"
Pop $0
${If} $0 == "$INSTDIR\${FileMainEXE}"
Delete "$DESKTOP\${BrandFullName}.lnk"
${EndIf}
${EndIf}
${EndIf}
${If} ${FileExists} "$QUICKLAUNCH\${BrandFullName}.lnk"
ShellLink::GetShortCutArgs "$QUICKLAUNCH\${BrandFullName}.lnk"
Pop $0
${If} $0 == ""
ShellLink::GetShortCutTarget "$QUICKLAUNCH\${BrandFullName}.lnk"
Pop $0
${If} $0 == "$INSTDIR\${FileMainEXE}"
Delete "$QUICKLAUNCH\${BrandFullName}.lnk"
${EndIf}
${EndIf}
${EndIf}
Abort
${EndIf}
; Show icons - initiated from Set Program Access and Defaults
${If} $R0 == "/ShowShortcuts"
WriteRegDWORD HKLM $R1 "IconsVisible" 1
${Unless} ${FileExists} "$DESKTOP\${BrandFullName}.lnk"
CreateShortCut "$DESKTOP\${BrandFullName}.lnk" "$INSTDIR\${FileMainEXE}" "" "$INSTDIR\${FileMainEXE}" 0
ShellLink::SetShortCutWorkingDirectory "$DESKTOP\${BrandFullName}.lnk" "$INSTDIR"
${Unless} ${FileExists} "$DESKTOP\${BrandFullName}.lnk"
SetShellVarContext current ; Set $DESKTOP to the current user's desktop
${Unless} ${FileExists} "$DESKTOP\${BrandFullName}.lnk"
CreateShortCut "$DESKTOP\${BrandFullName}.lnk" "$INSTDIR\${FileMainEXE}" "" "$INSTDIR\${FileMainEXE}" 0
ShellLink::SetShortCutWorkingDirectory "$DESKTOP\${BrandFullName}.lnk" "$INSTDIR"
${Switch} $R0
${Case} "/HideShortcuts"
${HideShortcuts}
StrCpy $R1 "true"
${Break}
${Case} "/ShowShortcuts"
${ShowShortcuts}
StrCpy $R1 "true"
${Break}
${Case} "/SetAsDefaultAppUser"
${SetAsDefaultAppUser}
StrCpy $R1 "true"
${Break}
${Case} "/SetAsDefaultAppGlobal"
${SetAsDefaultAppGlobal}
StrCpy $R1 "true"
${Break}
${Default}
ClearErrors
${Unless} "$R0" == ""
${WordReplace} "$R0" "$\"" "" "+" $R0
ClearErrors
${GetOptions} "$R0" "/PostUpdate" $R2
${Unless} ${Errors}
${PostUpdate}
ClearErrors
${GetOptions} "$R0" "/UninstallLog=" $R2
${Unless} ${Errors}
${Unless} "$R2" == ""
GetFullPathName $R3 "$R2"
${If} ${FileExists} "$R3"
Delete "$INSTDIR\uninstall\*wizard*"
Delete "$INSTDIR\uninstall\uninstall.log"
CopyFiles /SILENT "$R3" "$INSTDIR\uninstall\"
Push $R3
${GetParentDir}
Pop $R4
Delete "$R3"
RmDir "$R4"
${EndIf}
${EndUnless}
${EndUnless}
StrCpy $R1 "true"
${EndUnless}
${EndUnless}
${EndUnless}
${Unless} ${FileExists} "$QUICKLAUNCH\${BrandFullName}.lnk"
CreateShortCut "$QUICKLAUNCH\${BrandFullName}.lnk" "$INSTDIR\${FileMainEXE}" "" "$INSTDIR\${FileMainEXE}" 0
ShellLink::SetShortCutWorkingDirectory "$QUICKLAUNCH\${BrandFullName}.lnk" "$INSTDIR"
${EndUnless}
Abort
${Break}
${EndSwitch}
${If} $R1 == "true"
System::Call "shell32::SHChangeNotify(i, i, i, i) v (0x08000000, 0, 0, 0)"
Quit
${EndIf}
; If we made it this far then this installer is being used as an uninstaller.

View File

@@ -24,7 +24,7 @@ bin\defaults\profile\prefs.js
bin\defaults\profile\search.rdf
bin\defaults\profile\mimeTypes.rdf
bin\defaults\profile\chrome\*
bin\uninstall\uninst.exe
bin\uninstall\helper.exe
bin\updater.ini
bin\dictionaries\*

View File

@@ -193,7 +193,7 @@ endif
$(MAKE) -C ../installer/windows CONFIG_DIR=l10ngen l10ngen/setup.exe l10ngen/7zSD.sfx
cp ../installer/windows/l10ngen/setup.exe l10n-stage
$(NSINSTALL) -D l10n-stage/localized/uninstall
cp ../installer/windows/l10ngen/uninst.exe l10n-stage/localized/uninstall
cp ../installer/windows/l10ngen/helper.exe l10n-stage/localized/uninstall
rm -f app.7z
cd l10n-stage && \
$(CYGWIN_WRAPPER) 7z a -r -t7z ../app.7z -mx -m0=BCJ2 -m1=LZMA:d24 -m2=LZMA:d19 -m3=LZMA:d19 -mb0:1 -mb0s1:2 -mb0s2:3
@@ -232,7 +232,7 @@ repackage-zip: $(ZIP_IN)
ifeq (WINNT,$(OS_ARCH))
$(RM) -r $(STAGEDIST)/uninstall
$(NSINSTALL) -D $(STAGEDIST)/uninstall
cp ../installer/windows/l10ngen/uninst.exe $(STAGEDIST)/uninstall
cp ../installer/windows/l10ngen/helper.exe $(STAGEDIST)/uninstall
endif
$(RM) -r $(DIST)/xpi-stage/locale-$(AB_CD)/chrome/$(AB_CD)
cd $(DIST)/xpi-stage/locale-$(AB_CD) && \

View File

@@ -55,7 +55,8 @@ DOMI_TITLE=DOM Inspector
DOMI_TEXT=Inspects the structure and properties of a window and its contents.
QFA_TITLE=Quality Feedback Agent
QFA_TEXT=Sends information about program crashes to Mozilla.
OPTIONS=$(^NameDA) &Options
CONTEXT_OPTIONS=${BrandShortName} &Options
CONTEXT_SAFE_MODE=${BrandShortName} &Safe Mode
SAFE_MODE=Safe Mode
OPTIONS_PAGE_TITLE=Setup Type
OPTIONS_PAGE_SUBTITLE=Choose setup options

View File

@@ -91,6 +91,8 @@ Var fhUninstallLog
!include locales.nsi
!include version.nsh
VIAddVersionKey "FileDescription" "${BrandShortName} Installer"
!insertmacro RegCleanMain
!insertmacro RegCleanUninstall
!insertmacro CloseApp

View File

@@ -70,6 +70,10 @@ Var TmpVal
!include locales.nsi
!include version.nsh
; This is named BrandShortName helper because we use this for software update
; post update cleanup.
VIAddVersionKey "FileDescription" "${BrandShortName} Helper"
!insertmacro un.RegCleanMain
!insertmacro un.RegCleanUninstall
!insertmacro un.CloseApp

View File

@@ -92,6 +92,8 @@ Var ShortPathNameToExe
!include locales.nsi
!include version.nsh
VIAddVersionKey "FileDescription" "${BrandShortName} Installer"
!insertmacro RegCleanMain
!insertmacro RegCleanUninstall
!insertmacro CloseApp

View File

@@ -71,6 +71,10 @@ Var TmpVal
!include locales.nsi
!include version.nsh
; This is named BrandShortName helper because we use this for software update
; post update cleanup.
VIAddVersionKey "FileDescription" "${BrandShortName} Helper"
!insertmacro un.RegCleanMain
!insertmacro un.RegCleanUninstall
!insertmacro un.CloseApp

View File

@@ -530,87 +530,6 @@ Exch $R9 ; exchange the new $R9 value with the top of the stack
!verbose pop
!macroend
/**
* Checks whether the system is running Vista. If the system is running Vista
* this will return true... if not, this will return false.
*
* IMPORTANT! $R9 will be overwritten by this macro with the return value so
* protect yourself!
*
* @return _RESULT
* true if the system is running Vista otherwise false.
*
* $R7 = value of CurrentVersion from call to ReadRegStr
* $R8 = leftmost char from $R7 used for comparison. If this is 6 then the
* system is running Vista.
* $R9 = _RESULT
*/
!macro IsVista
!ifndef ${_MOZFUNC_UN}IsVista
!verbose push
!verbose ${_MOZFUNC_VERBOSE}
!define ${_MOZFUNC_UN}IsVista "!insertmacro ${_MOZFUNC_UN}IsVistaCall"
Function ${_MOZFUNC_UN}IsVista
Push $R7
Push $R8
StrCpy $R9 "false"
ClearErrors
ReadRegStr $R7 HKLM "SOFTWARE\Microsoft\Windows NT\CurrentVersion" CurrentVersion
IfErrors end 0
StrCpy $R8 $R7 1
StrCmp $R8 "6" 0 end
StrCpy $R9 "true"
end:
ClearErrors
Pop $R8
Pop $R7
Push $R9
FunctionEnd
!verbose pop
!endif
!macroend
!macro IsVistaCall _RESULT
!verbose push
!verbose ${_MOZFUNC_VERBOSE}
Call IsVista
Pop ${_RESULT}
!verbose pop
!macroend
!macro un.IsVistaCall _RESULT
!verbose push
!verbose ${_MOZFUNC_VERBOSE}
Call un.IsVista
Pop ${_RESULT}
!verbose pop
!macroend
!macro un.IsVista
!ifndef un.IsVista
!verbose push
!verbose ${_MOZFUNC_VERBOSE}
!undef _MOZFUNC_UN
!define _MOZFUNC_UN "un."
!insertmacro IsVista
!undef _MOZFUNC_UN
!define _MOZFUNC_UN
!verbose pop
!endif
!macroend
/**
* Checks whether we can write to the install directory. If the install
* directory already exists this will attempt to create a temporary file in the
@@ -1190,12 +1109,15 @@ Exch $R9 ; exchange the new $R9 value with the top of the stack
ClearErrors
WriteRegStr SHCTX "$R6" "$R7" "$R8"
!ifndef NO_LOG
IfErrors 0 +3
FileWrite $fhInstallLog " ** ERROR Adding Registry String: $R5 | $R6 | $R7 | $R8 **$\r$\n"
GoTo +4
IntCmp $R9 1 0 +2
FileWrite $fhUninstallLog "RegVal: $R5 | $R6 | $R7$\r$\n"
FileWrite $fhInstallLog " Added Registry String: $R5 | $R6 | $R7 | $R8$\r$\n"
!endif
Exch $R5
Exch 4
@@ -1292,12 +1214,14 @@ Exch $R9 ; exchange the new $R9 value with the top of the stack
ClearErrors
WriteRegDWORD SHCTX "$R6" "$R7" "$R8"
!ifndef NO_LOG
IfErrors 0 +3
FileWrite $fhInstallLog " ** ERROR Adding Registry DWord: $R5 | $R6 | $R7 | $R8 **$\r$\n"
GoTo +4
IntCmp $R5 1 0 +2
FileWrite $fhUninstallLog "RegVal: $R5 | $R6 | $R7$\r$\n"
FileWrite $fhInstallLog " Added Registry DWord: $R5 | $R6 | $R7 | $R8$\r$\n"
!endif
Exch $R5
Exch 4
@@ -1394,12 +1318,15 @@ Exch $R9 ; exchange the new $R9 value with the top of the stack
ClearErrors
WriteRegStr HKCR "$R6" "$R7" "$R8"
!ifndef NO_LOG
IfErrors 0 +3
FileWrite $fhInstallLog " ** ERROR Adding Registry String: $R5 | $R6 | $R7 | $R8 **$\r$\n"
GoTo +4
IntCmp $R5 1 0 +2
FileWrite $fhUninstallLog "RegVal: $R5 | $R6 | $R7$\r$\n"
FileWrite $fhInstallLog " Added Registry String: $R5 | $R6 | $R7 | $R8$\r$\n"
!endif
Exch $R5
Exch 4
@@ -1515,6 +1442,7 @@ Exch $R9 ; exchange the new $R9 value with the top of the stack
; see definition of RegCreateKey
System::Call "${RegCreateKey}($R6, '$R8', .r14) .r15"
!ifndef NO_LOG
; if $R5 is not 0 then there was an error creating the registry key.
IntCmp $R5 0 +3
FileWrite $fhInstallLog " ** ERROR Adding Registry Key: $R7 | $R8 **$\r$\n"
@@ -1522,6 +1450,7 @@ Exch $R9 ; exchange the new $R9 value with the top of the stack
IntCmp $R9 1 0 +2
FileWrite $fhUninstallLog "RegKey: $R7 | $R8$\r$\n"
FileWrite $fhInstallLog " Added Registry Key: $R7 | $R8$\r$\n"
!endif
Pop $R4
Pop $R5
@@ -1572,114 +1501,6 @@ Exch $R9 ; exchange the new $R9 value with the top of the stack
!endif
!macroend
/**
* Finds an installation of the application so we can force an install into an
* existing location for Vista. This uses SHCTX to determine the
* registry hive so you must call SetShellVarContext first.
*
* IMPORTANT! $R9 will be overwritten by this macro with the return value so
* protect yourself!
*
* @param _KEY
* The registry subkey (typically this will be Software\Mozilla).
* @return _RESULT
* false if an install isn't found, path to the main exe if an install
* is found.
*
* $R3 = _KEY
* $R4 = value returned from the outer loop's EnumRegKey
* $R5 = value returned from ReadRegStr
* $R6 = counter for the outer loop's EnumRegKey
* $R7 = value returned popped from the stack for GetPathFromRegStr macro
* $R8 = value returned popped from the stack for GetParentDir macro
* $R9 = _RESULT
*/
!macro GetExistingInstallPath
!ifndef ${_MOZFUNC_UN}GetExistingInstallPath
!verbose push
!verbose ${_MOZFUNC_VERBOSE}
!define ${_MOZFUNC_UN}GetExistingInstallPath "!insertmacro ${_MOZFUNC_UN}GetExistingInstallPathCall"
Function ${_MOZFUNC_UN}GetExistingInstallPath
Exch $R3
Push $R4
Push $R5
Push $R6
Push $R7
Push $R8
StrCpy $R9 "false"
StrCpy $R6 0 ; set the counter for the loop to 0
loop:
EnumRegKey $R4 SHCTX $R3 $R6
StrCmp $R4 "" end ; if empty there are no more keys to enumerate
IntOp $R6 $R6 + 1 ; increment the loop's counter
ClearErrors
ReadRegStr $R5 SHCTX "$R3\$R4\bin" "PathToExe"
IfErrors loop
Push $R5
${GetPathFromRegStr}
Pop $R7
IfFileExists "$R7" 0 +5
Push "$R7"
${GetParent} "$R7" $R8
StrCpy $R9 "$R8"
GoTo end
GoTo loop
end:
ClearErrors
Pop $R8
Pop $R7
Pop $R6
Pop $R5
Pop $R4
Exch $R3
Push $R9
FunctionEnd
!verbose pop
!endif
!macroend
!macro GetExistingInstallPathCall _KEY _RESULT
!verbose push
!verbose ${_MOZFUNC_VERBOSE}
Push "${_KEY}"
Call GetExistingInstallPath
Pop ${_RESULT}
!verbose pop
!macroend
!macro un.GetExistingInstallPathCall _KEY _RESULT
!verbose push
!verbose ${_MOZFUNC_VERBOSE}
Push "${_KEY}"
Call un.GetExistingInstallPath
Pop ${_RESULT}
!verbose pop
!macroend
!macro un.GetExistingInstallPath
!ifndef un.GetExistingInstallPath
!verbose push
!verbose ${_MOZFUNC_VERBOSE}
!undef _MOZFUNC_UN
!define _MOZFUNC_UN "un."
!insertmacro GetExistingInstallPath
!undef _MOZFUNC_UN
!define _MOZFUNC_UN
!verbose pop
!endif
!macroend
/**
* Finds a second installation of the application so we can make informed
* decisions about registry operations. This uses SHCTX to determine the
@@ -1791,6 +1612,137 @@ Exch $R9 ; exchange the new $R9 value with the top of the stack
!endif
!macroend
/**
* Writes common registry values for a handler using SHCTX.
* @param _KEY
* The subkey in relation to the key root.
* @param _VALOPEN
* The path and args to launch the application.
* @param _VALICON
* The path to an exe that contains an icon and the icon resource id.
* @param _DISPNAME
* The display name for the handler. If emtpy no value will be set.
* @param _ISPROTOCOL
* Sets protocol handler specific registry values when "true".
* @param _ISDDE
* Sets DDE specific registry values when "true".
*
* $R3 = string value of the current registry key path.
* $R4 = _KEY
* $R5 = _VALOPEN
* $R6 = _VALICON
* $R7 = _DISPNAME
* $R8 = _ISPROTOCOL
* $R9 = _ISDDE
*/
!macro AddHandlerValues
!ifndef ${_MOZFUNC_UN}AddHandlerValues
!verbose push
!verbose ${_MOZFUNC_VERBOSE}
!define ${_MOZFUNC_UN}AddHandlerValues "!insertmacro ${_MOZFUNC_UN}AddHandlerValuesCall"
Function ${_MOZFUNC_UN}AddHandlerValues
Exch $R9
Exch 1
Exch $R8
Exch 2
Exch $R7
Exch 3
Exch $R6
Exch 4
Exch $R5
Exch 5
Exch $R4
Push $R3
StrCmp "$R7" "" +6 0
ReadRegStr $R3 SHCTX "$R4" "FriendlyTypeName"
StrCmp "$R3" "" 0 +3
WriteRegStr SHCTX "$R4" "" "$R7"
WriteRegStr SHCTX "$R4" "FriendlyTypeName" "$R7"
StrCmp "$R8" "true" 0 +4
DeleteRegValue SHCTX "$R4" "EditFlags"
WriteRegBin SHCTX "$R4" "EditFlags" 2
WriteRegStr SHCTX "$R4" "URL Protocol" ""
StrCmp "$R9" "true" 0 +13
WriteRegStr SHCTX "$R4\DefaultIcon" "" "$R6"
WriteRegStr SHCTX "$R4\shell\open\command" "" "$R5"
WriteRegStr SHCTX "$R4\shell\open\ddeexec" "" "$\"%1$\",,0,0,,,,"
WriteRegStr SHCTX "$R4\shell\open\ddeexec" "NoActivateHandler" ""
WriteRegStr SHCTX "$R4\shell\open\ddeexec\Application" "" "${DDEApplication}"
WriteRegStr SHCTX "$R4\shell\open\ddeexec\Topic" "" "WWW_OpenURL"
; The ifexec key may have been added by another application so try to
; delete it to prevent it from breaking this app's shell integration.
; Also, IE 6 and below doesn't remove this key when it sets itself as the
; default handler and if this key exists IE's shell integration breaks.
DeleteRegKey HKLM "$R4\shell\open\ddeexec\ifexec"
DeleteRegKey HKCU "$R4\shell\open\ddeexec\ifexec"
ClearErrors
Pop $R3
Exch $R4
Exch 5
Exch $R5
Exch 4
Exch $R6
Exch 3
Exch $R7
Exch 2
Exch $R8
Exch 1
Exch $R9
FunctionEnd
!verbose pop
!endif
!macroend
!macro AddHandlerValuesCall _KEY _VALOPEN _VALICON _DISPNAME _ISPROTOCOL _ISDDE
!verbose push
!verbose ${_MOZFUNC_VERBOSE}
Push "${_KEY}"
Push "${_VALOPEN}"
Push "${_VALICON}"
Push "${_DISPNAME}"
Push "${_ISPROTOCOL}"
Push "${_ISDDE}"
Call AddHandlerValues
!verbose pop
!macroend
!macro un.AddHandlerValuesCall _KEY _VALOPEN _VALICON _DISPNAME _ISPROTOCOL _ISDDE
!verbose push
!verbose ${_MOZFUNC_VERBOSE}
Push "${_KEY}"
Push "${_VALOPEN}"
Push "${_VALICON}"
Push "${_DISPNAME}"
Push "${_ISPROTOCOL}"
Push "${_ISDDE}"
Call un.AddHandlerValues
!verbose pop
!macroend
!macro un.AddHandlerValues
!ifndef un.AddHandlerValues
!verbose push
!verbose ${_MOZFUNC_VERBOSE}
!undef _MOZFUNC_UN
!define _MOZFUNC_UN "un."
!insertmacro AddHandlerValues
!undef _MOZFUNC_UN
!define _MOZFUNC_UN
!verbose pop
!endif
!macroend
/**
* Displays a error message when a file can't be copied.
*

View File

@@ -80,4 +80,8 @@ uninstaller::
$(INSTALL) $(topsrcdir)/toolkit/mozapps/installer/windows/nsis/setup.ico $(CONFIG_DIR)
cd $(CONFIG_DIR) && makensis.exe uninstaller.nsi
$(NSINSTALL) -D $(DIST)/bin/uninstall
ifdef MOZ_PHOENIX
cp $(CONFIG_DIR)/helper.exe $(DIST)/bin/uninstall
else
cp $(CONFIG_DIR)/uninst.exe $(DIST)/bin/uninstall
endif

View File

@@ -12,6 +12,5 @@ VIAddVersionKey "ProductName" "${BrandShortName}"
VIAddVersionKey "CompanyName" "${CompanyName}"
VIAddVersionKey "LegalTrademarks" "${BrandShortName} is a Trademark of The Mozilla Foundation."
VIAddVersionKey "LegalCopyright" "${CompanyName}"
VIAddVersionKey "FileDescription" "${BrandShortName} Installer"
VIAddVersionKey "FileVersion" "${AppVersion}"
;VIAddVersionKey "Comments" "Comments"

View File

@@ -73,7 +73,7 @@ var gLogEnabled = { };
* The string to write to the error console..
*/
function LOG(module, string) {
if (module in gLogEnabled) {
if (module in gLogEnabled || "all" in gLogEnabled) {
dump("*** " + module + ":" + string + "\n");
gConsole.logStringMessage(string);
}

View File

@@ -43,12 +43,12 @@
*/
const URI_BRAND_PROPERTIES = "chrome://branding/locale/brand.properties";
const URI_UNINSTALL_PROPERTIES = "chrome://branding/content/uninstall.properties";
const KEY_APPDIR = "XCurProcD";
const KEY_COMPONENTS_DIR = "ComsD";
const KEY_PLUGINS_DIR = "APlugns";
const KEY_EXECUTABLE_FILE = "XREExeF";
const KEY_TMPDIR = "TmpD";
const KEY_LOCALDATA = "DefProfLRt";
const KEY_PROGRAMFILES = "ProgF";
const KEY_UAPPDATA = "UAppData";
// see prio.h
const PR_RDONLY = 0x01;
@@ -56,16 +56,23 @@ const PR_WRONLY = 0x02;
const PR_APPEND = 0x10;
const PERMS_FILE = 0644;
const PERMS_DIR = 0700;
const nsIWindowsRegKey = Components.interfaces.nsIWindowsRegKey;
var gConsole = null;
var gAppUpdateLogPostUpdate = false;
//-----------------------------------------------------------------------------
/**
* Console logging support
*/
function LOG(s) {
dump("*** PostUpdateWin: " + s + "\n");
if (gAppUpdateLogPostUpdate) {
dump("*** PostUpdateWin: " + s + "\n");
gConsole.logStringMessage(s);
}
}
/**
@@ -122,24 +129,6 @@ function openFileOutputStream(file, flags) {
return stream;
}
/**
* Gets the current value of the locale. It's possible for this preference to
* be localized, so we have to do a little extra work here. Similar code
* exists in nsHttpHandler.cpp when building the UA string.
*/
function getLocale() {
const prefName = "general.useragent.locale";
var prefs =
Components.classes["@mozilla.org/preferences-service;1"].
getService(Components.interfaces.nsIPrefBranch);
try {
return prefs.getComplexValue(prefName,
Components.interfaces.nsIPrefLocalizedString).data;
} catch (e) {}
return prefs.getCharPref(prefName);
}
//-----------------------------------------------------------------------------
const PREFIX_FILE = "File: ";
@@ -179,20 +168,49 @@ InstallLogWriter.prototype = {
* updates/0 directory has already been cleaned out (see bug 311302).
*/
_getUpdateLogFile: function() {
var file = getFile(KEY_APPDIR);
file.append("updates");
file.append("0");
file.append("update.log");
if (file.exists())
return file;
function appendUpdateLogPath(root) {
var file = root.clone();
file.append("updates");
file.append("0");
file.append("update.log");
if (file.exists())
return file;
file = getFile(KEY_APPDIR);
file.append("updates");
file.append("last-update.log");
if (file.exists())
return file;
file = root;
file.append("updates");
file.append("last-update.log");
if (file.exists())
return file;
return null;
return null;
}
// See the local appdata first if app dir is under Program Files.
var file = null;
var updRoot = getFile(KEY_APPDIR);
var fileLocator = Components.classes["@mozilla.org/file/directory_service;1"]
.getService(Components.interfaces.nsIProperties);
var programFilesDir = fileLocator.get(KEY_PROGRAMFILES,
Components.interfaces.nsILocalFile);
if (programFilesDir.contains(updRoot, true)) {
var relativePath = updRoot.QueryInterface(Components.interfaces.nsILocalFile).
getRelativeDescriptor(programFilesDir);
var userLocalDir = fileLocator.get(KEY_LOCALDATA,
Components.interfaces.nsILocalFile).parent;
updRoot.setRelativeDescriptor(userLocalDir, relativePath);
file = appendUpdateLogPath(updRoot);
// When updating from Fx 2.0.0.1 to 2.0.0.3 (or later) on Vista,
// we will have to see also user app data (see bug 351949).
if (!file)
file = appendUpdateLogPath(getFile(KEY_UAPPDATA));
}
// See the app dir if not found or app dir is out of Program Files.
if (!file)
file = appendUpdateLogPath(getFile(KEY_APPDIR));
return file;
},
/**
@@ -337,8 +355,27 @@ InstallLogWriter.prototype = {
if (newEntries.length == 0)
return;
// since we are not running with elevated privs, we can't write out
// the log file (at least, not on Vista). So, write the output to
// temp, and then later, we'll pass the file (gCopiedLog) to
// the post update clean up process, which can copy it to
// the desired location (because it will have elevated privs)
gCopiedLog = getFile(KEY_TMPDIR);
gCopiedLog.append("uninstall");
gCopiedLog.createUnique(gCopiedLog.DIRECTORY_TYPE, PERMS_DIR);
if (uninstallLog)
uninstallLog.copyTo(gCopiedLog, "uninstall.log");
gCopiedLog.append("uninstall.log");
LOG("uninstallLog = " + uninstallLog.path);
LOG("copiedLog = " + gCopiedLog.path);
if (!gCopiedLog.exists())
gCopiedLog.create(Components.interfaces.nsILocalFile.NORMAL_FILE_TYPE,
PERMS_FILE);
this._outputStream =
openFileOutputStream(uninstallLog, PR_WRONLY | PR_APPEND);
openFileOutputStream(gCopiedLog, PR_WRONLY | PR_APPEND);
// The NSIS uninstaller deletes all directories where the installer has
// added a file if the directory is empty after the files have been removed
@@ -356,12 +393,15 @@ InstallLogWriter.prototype = {
};
var installLogWriter;
var gCopiedLog;
//-----------------------------------------------------------------------------
/**
* A thin wrapper around nsIWindowsRegKey that keeps track of its path
* and notifies the installLogWriter when modifications are made.
* A thin wrapper around nsIWindowsRegKey
* note, only the "read" methods are exposed. If you want to write
* to the registry on Vista, you need to be a priveleged app.
* We've moved that code into the uninstaller.
*/
function RegKey() {
// Internally, we may pass parameters to this constructor.
@@ -381,12 +421,11 @@ RegKey.prototype = {
_path: null,
ACCESS_READ: nsIWindowsRegKey.ACCESS_READ,
ACCESS_WRITE: nsIWindowsRegKey.ACCESS_WRITE,
ACCESS_ALL: nsIWindowsRegKey.ACCESS_ALL,
ROOT_KEY_CURRENT_USER: nsIWindowsRegKey.ROOT_KEY_CURRENT_USER,
ROOT_KEY_LOCAL_MACHINE: nsIWindowsRegKey.ROOT_KEY_LOCAL_MACHINE,
ROOT_KEY_CLASSES_ROOT: nsIWindowsRegKey.ROOT_KEY_CLASSES_ROOT,
close: function() {
this._key.close();
this._root = null;
@@ -404,24 +443,10 @@ RegKey.prototype = {
return new RegKey(child, this._root, this._path + "\\" + path);
},
createChild: function(path, mode) {
var child = this._key.createChild(path, mode);
var key = new RegKey(child, this._root, this._path + "\\" + path);
return key;
},
readStringValue: function(name) {
return this._key.readStringValue(name);
},
writeStringValue: function(name, value) {
this._key.writeStringValue(name, value);
},
writeIntValue: function(name, value) {
this._key.writeIntValue(name, value);
},
hasValue: function(name) {
return this._key.hasValue(name);
},
@@ -438,13 +463,12 @@ RegKey.prototype = {
return this._key.getChildName(index);
},
removeChild: function(name) {
this._key.removeChild(name);
},
toString: function() {
var root;
switch (this._root) {
case this.ROOT_KEY_CLASSES_ROOT:
root = "HKEY_KEY_CLASSES_ROOT";
break;
case this.ROOT_KEY_LOCAL_MACHINE:
root = "HKEY_LOCAL_MACHINE";
break;
@@ -459,86 +483,14 @@ RegKey.prototype = {
}
};
//-----------------------------------------------------------------------------
/*
RegKey.prototype = {
// The name of the registry key
name: "";
// An array of strings, where each even-indexed string names a value,
// and the subsequent string provides data for the value.
values: [];
// An array of RegKey objects.
children: [];
}
*/
/**
* This function creates a heirarchy of registry keys. If any of the
* keys or values already exist, then they will be updated instead.
* @param rootKey
* The root registry key from which to create the new registry
* keys.
* @param data
* A JS object with properties: "name", "values", and "children"
* as defined above. All children of this key will be created.
*/
function createRegistryKeys(rootKey, data) {
var key;
try {
key = rootKey.createChild(data.name, rootKey.ACCESS_WRITE);
var i;
if ("values" in data) {
for (i = 0; i < data.values.length; i += 2)
key.writeStringValue(data.values[i], data.values[i + 1]);
}
if ("children" in data) {
for (i = 0; i < data.children.length; ++i)
createRegistryKeys(key, data.children[i]);
}
key.close();
} catch (e) {
LOG(e);
if (key)
key.close();
}
}
/**
* This function deletes the specified registry key and optionally all of its
* children.
* @param rootKey
* The parent nsIwindowRegKey of the key to delete.
* @param name
* The name of the key to delete.
* @param recurse
* Pass true to also delete all children of the named key. Take care!
*/
function deleteRegistryKey(rootKey, name, recurse) {
if (!rootKey.hasChild(name)) {
LOG("deleteRegistryKey: rootKey does not have child: \"" + name + "\"");
return;
}
if (recurse) {
var key = rootKey.openChild(name, rootKey.ACCESS_ALL);
try {
for (var i = key.childCount - 1; i >= 0; --i)
deleteRegistryKey(key, key.getChildName(i), true);
} finally {
key.close();
}
}
rootKey.removeChild(name);
}
/**
* This method walks the registry looking for the registry keys of
* the previous version of the application.
*/
function locateOldInstall(key, ourInstallDir) {
var result, childKey, productKey, mainKey;
function haveOldInstall(key, brandFullName, version) {
var ourInstallDir = getFile(KEY_APPDIR);
var result = false;
var childKey, productKey, mainKey;
try {
for (var i = 0; i < key.childCount; ++i) {
var childName = key.getChildName(i);
@@ -550,14 +502,14 @@ function locateOldInstall(key, ourInstallDir) {
if (productKey.hasChild("Main")) {
mainKey = productKey.openChild("Main", key.ACCESS_READ);
var installDir = mainKey.readStringValue("Install Directory");
var menuPath = mainKey.readStringValue("Program Folder Path");
mainKey.close();
if (newFile(installDir).equals(ourInstallDir)) {
result = new Object();
result.fullName = childName;
result.versionWithLocale = productVer;
result.version = productVer.split(" ")[0];
result.menuPath = menuPath;
LOG("old install? " + installDir + " vs " + ourInstallDir.path);
LOG("old install? " + childName + " vs " + brandFullName);
LOG("old install? " + productVer.split(" ")[0] + " vs " + version);
if (newFile(installDir).equals(ourInstallDir) &&
(childName != brandFullName ||
productVer.split(" ")[0] != version)) {
result = true;
}
}
productKey.close();
@@ -570,7 +522,7 @@ function locateOldInstall(key, ourInstallDir) {
break;
}
} catch (e) {
result = null;
result = false;
if (childKey)
childKey.close();
if (productKey)
@@ -581,239 +533,62 @@ function locateOldInstall(key, ourInstallDir) {
return result;
}
/**
* Delete registry keys left-over from the previous version of the app
* installed at our location.
*/
function deleteOldRegKeys(key, info) {
deleteRegistryKey(key, info.fullName + " " + info.version, true);
var productKey = key.openChild(info.fullName, key.ACCESS_ALL);
var productCount;
function checkRegistry()
{
// XXX todo
// this is firefox specific
// figure out what to do about tbird and sunbird, etc
LOG("checkRegistry");
var result = false;
try {
deleteRegistryKey(productKey, info.versionWithLocale, true);
productCount = productKey.childCount;
} finally {
productKey.close();
var key = new RegKey();
key.open(RegKey.prototype.ROOT_KEY_CLASSES_ROOT, "FirefoxHTML\\shell\\open\\command", key.ACCESS_READ);
var commandKey = key.readStringValue("");
LOG("commandKey = " + commandKey);
// if "-requestPending" is not found, we need to do the cleanup
result = (commandKey.indexOf("-requestPending") == -1);
} catch (e) {
LOG("failed to open command key for FirefoxHTML: " + e);
}
if (productCount == 0)
key.removeChild(info.fullName);
key.close();
return result;
}
/**
* The installer sets various registry keys and values that may need to be
* updated.
*
* This operation is a bit tricky since we do not know the previous value of
* brandFullName. As a result, we must walk the registry looking for an
* existing key that references the same install directory. We assume that
* the value of vendorShortName does not change across updates.
*/
function updateRegistry(rootKey) {
LOG("updateRegistry");
var ourInstallDir = getFile(KEY_APPDIR);
var app =
Components.classes["@mozilla.org/xre/app-info;1"].
getService(Components.interfaces.nsIXULAppInfo).
QueryInterface(Components.interfaces.nsIXULRuntime);
var sbs =
Components.classes["@mozilla.org/intl/stringbundle;1"].
getService(Components.interfaces.nsIStringBundleService);
var brandBundle = sbs.createBundle(URI_BRAND_PROPERTIES);
var brandFullName = brandBundle.GetStringFromName("brandFullName");
var vendorShortName;
try {
// The Thunderbird vendorShortName is "Mozilla Thunderbird", but we
// just want "Thunderbird", so allow it to be overridden in prefs.
var prefs =
Components.classes["@mozilla.org/preferences-service;1"].
getService(Components.interfaces.nsIPrefBranch);
vendorShortName = prefs.getCharPref("app.update.vendorName.override");
}
catch (e) {
vendorShortName = brandBundle.GetStringFromName("vendorShortName");
}
function checkOldInstall(rootKey, vendorShortName, brandFullName, version)
{
var key = new RegKey();
var result = false;
var oldInstall;
try {
key.open(rootKey, "SOFTWARE\\" + vendorShortName, key.ACCESS_READ);
oldInstall = locateOldInstall(key, ourInstallDir);
} catch (e) {}
key.close();
if (!oldInstall) {
LOG("no existing registry keys found");
return;
LOG("checkOldInstall: " + key + " " + brandFullName + " " + version);
result = haveOldInstall(key, brandFullName, version);
} catch (e) {
LOG("failed trying to find old install: " + e);
}
const uninstallRoot =
"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall";
// Maybe nothing needs to be changed...
if (oldInstall.fullName == brandFullName &&
oldInstall.version == app.version) {
var uninst = getFile(KEY_APPDIR);
uninst.append("uninstall");
uninst.append("uninst.exe");
var uninstString = uninst.path;
nameWithVersion = oldInstall.fullName + " (" + oldInstall.version + ")";
try {
key.open(rootKey, uninstallRoot + "\\" + nameWithVersion, key.ACCESS_READ);
var regUninstString = key.readStringValue("UninstallString");
if (regUninstString != uninstString) {
LOG("updating UninstallString registry value");
key.close();
key.open(rootKey, uninstallRoot, key.ACCESS_READ);
createRegistryKeys(key, { name: nameWithVersion,
values: ["UninstallString", uninstString] });
} else {
LOG("registry is up-to-date");
}
} catch (e) {}
key.close();
return;
}
// Delete the old keys:
try {
key.open(rootKey, "SOFTWARE\\" + vendorShortName, key.ACCESS_READ);
deleteOldRegKeys(key, oldInstall);
} catch (e) {}
key.close();
// Create the new keys:
var versionWithLocale = app.version + " (" + getLocale() + ")";
var installPath = ourInstallDir.path + "\\";
var pathToExe = getFile(KEY_EXECUTABLE_FILE).path;
var Key_bin = {
name: "bin",
values: [
"PathToExe", pathToExe
]
};
var Key_extensions = {
name: "Extensions",
values: [
"Components", getFile(KEY_COMPONENTS_DIR).path + "\\",
"Plugins", getFile(KEY_PLUGINS_DIR).path + "\\"
]
};
var Key_nameWithVersion = {
name: brandFullName + " " + app.version,
values: [
"GeckoVer", app.platformVersion
],
children: [
Key_bin,
Key_extensions
]
};
var Key_main = {
name: "Main",
values: [
"Install Directory", installPath,
"PathToExe", pathToExe,
"Program Folder Path", oldInstall.menuPath
]
};
var Key_uninstall = {
name: "Uninstall",
values: [
"Description", brandFullName + " (" + app.version + ")",
"Uninstall Log Folder", installPath + "uninstall"
]
};
var Key_versionWithLocale = {
name: versionWithLocale,
children: [
Key_main,
Key_uninstall
]
};
var Key_name = {
name: brandFullName,
values: [
"CurrentVersion", versionWithLocale
],
children: [
Key_versionWithLocale
]
};
var Key_brand = {
name: vendorShortName,
children: [
Key_name,
Key_nameWithVersion
]
};
try {
key.open(rootKey, "SOFTWARE", key.ACCESS_READ);
createRegistryKeys(key, Key_brand);
} catch (e) {}
key.close();
if (rootKey != RegKey.prototype.ROOT_KEY_LOCAL_MACHINE)
return;
// Now, do the same thing for the Add/Remove Programs control panel:
try {
key.open(rootKey, uninstallRoot, key.ACCESS_READ);
var oldName = oldInstall.fullName + " (" + oldInstall.version + ")";
deleteRegistryKey(key, oldName, false);
} catch (e) {}
key.close();
var uninstallBundle = sbs.createBundle(URI_UNINSTALL_PROPERTIES);
var nameWithVersion = brandFullName + " (" + app.version + ")";
var uninstaller = getFile(KEY_APPDIR);
uninstaller.append("uninstall");
uninstaller.append("uninst.exe");
var uninstallString = uninstaller.path;
Key_uninstall = {
name: nameWithVersion,
values: [
"Comment", brandFullName,
"DisplayIcon", pathToExe + ",0", // XXX don't hardcode me!
"DisplayName", nameWithVersion,
"DisplayVersion", versionWithLocale,
"InstallLocation", ourInstallDir.path, // no trailing slash
"Publisher", vendorShortName,
"UninstallString", uninstallString,
"URLInfoAbout", uninstallBundle.GetStringFromName("URLInfoAbout"),
"URLUpdateInfo", uninstallBundle.GetStringFromName("URLUpdateInfo")
]
};
var child;
try {
key.open(rootKey, uninstallRoot, key.ACCESS_READ);
createRegistryKeys(key, Key_uninstall);
// Create additional DWORD keys for NoModify and NoRepair:
child = key.openChild(nameWithVersion, key.ACCESS_WRITE);
child.writeIntValue("NoModify", 1);
child.writeIntValue("NoRepair", 1);
} catch (e) {}
if (child)
child.close();
key.close();
return result;
}
//-----------------------------------------------------------------------------
function nsPostUpdateWin() {
gConsole = Components.classes["@mozilla.org/consoleservice;1"]
.getService(Components.interfaces.nsIConsoleService);
var prefs = Components.classes["@mozilla.org/preferences-service;1"].
getService(Components.interfaces.nsIPrefBranch);
try {
gAppUpdateLogPostUpdate = prefs.getBoolPref("app.update.log.all");
}
catch (ex) {
}
try {
if (!gAppUpdateLogPostUpdate)
gAppUpdateLogPostUpdate = prefs.getBoolPref("app.update.log.PostUpdate");
}
catch (ex) {
}
}
nsPostUpdateWin.prototype = {
@@ -826,20 +601,66 @@ nsPostUpdateWin.prototype = {
run: function() {
try {
// We use a global object here for the install log writer, so that the
// registry updating code can easily inform it of registry keys that it
// may create.
installLogWriter = new InstallLogWriter();
try {
installLogWriter.begin();
updateRegistry(RegKey.prototype.ROOT_KEY_CURRENT_USER);
updateRegistry(RegKey.prototype.ROOT_KEY_LOCAL_MACHINE);
} finally {
installLogWriter.end();
installLogWriter = null;
}
} catch (e) {
LOG(e);
}
var app =
Components.classes["@mozilla.org/xre/app-info;1"].
getService(Components.interfaces.nsIXULAppInfo).
QueryInterface(Components.interfaces.nsIXULRuntime);
var sbs =
Components.classes["@mozilla.org/intl/stringbundle;1"].
getService(Components.interfaces.nsIStringBundleService);
var brandBundle = sbs.createBundle(URI_BRAND_PROPERTIES);
var vendorShortName;
try {
// The Thunderbird vendorShortName is "Mozilla Thunderbird", but we
// just want "Thunderbird", so allow it to be overridden in prefs.
var prefs =
Components.classes["@mozilla.org/preferences-service;1"].
getService(Components.interfaces.nsIPrefBranch);
vendorShortName = prefs.getCharPref("app.update.vendorName.override");
}
catch (e) {
vendorShortName = brandBundle.GetStringFromName("vendorShortName");
}
var brandFullName = brandBundle.GetStringFromName("brandFullName");
if (!gCopiedLog &&
!checkRegistry() &&
!checkOldInstall(RegKey.prototype.ROOT_KEY_LOCAL_MACHINE,
vendorShortName, brandFullName, app.version) &&
!checkOldInstall(RegKey.prototype.ROOT_KEY_CURRENT_USER,
vendorShortName, brandFullName, app.version)) {
LOG("nothing to do, so don't launch the helper");
return;
}
try {
var winAppHelper =
app.QueryInterface(Components.interfaces.nsIWinAppHelper);
// note, gCopiedLog could be null
if (gCopiedLog)
LOG("calling postUpdate with: " + gCopiedLog.path);
else
LOG("calling postUpdate without a log");
winAppHelper.postUpdate(gCopiedLog);
} catch (e) {
LOG("failed to launch the helper to do the post update cleanup: " + e);
}
}
};

View File

@@ -65,6 +65,11 @@ const URI_UPDATES_PROPERTIES = "chrome://mozapps/locale/update/updates.proper
const URI_UPDATE_NS = "http://www.mozilla.org/2005/app-update";
const KEY_APPDIR = "XCurProcD";
#ifdef XP_WIN
const KEY_LOCALDATA = "DefProfLRt";
const KEY_PROGRAMFILES = "ProgF";
const KEY_UAPPDATA = "UAppData";
#endif
const DIR_UPDATES = "updates";
const FILE_UPDATE_STATUS = "update.status";
@@ -180,7 +185,7 @@ function getURLSpecFromFile(file) {
* parent directories that need to be created.
*/
function getDir(key, pathArray) {
return getDirInternal(key, pathArray, true);
return getDirInternal(key, pathArray, true, false);
}
/**
@@ -195,7 +200,21 @@ function getDir(key, pathArray) {
* requested does not exist, it is NOT created.
*/
function getDirNoCreate(key, pathArray) {
return getDirInternal(key, pathArray, false);
return getDirInternal(key, pathArray, false, false);
}
/**
* Gets the specified directory at the specified hierarchy under the
* update root directory.
* @param pathArray
* An array of path components to locate beneath the directory
* specified by |key|
* @return nsIFile object for the location specified. If the directory
* requested does not exist, it is created, along with any
* parent directories that need to be created.
*/
function getUpdateDir(pathArray) {
return getDirInternal(KEY_APPDIR, pathArray, true, true);
}
/**
@@ -210,12 +229,27 @@ function getDirNoCreate(key, pathArray) {
* true if the directory hierarchy specified in |pathArray|
* should be created if it does not exist,
* false otherwise.
* @param update
* true if finding the update directory,
* false otherwise.
* @return nsIFile object for the location specified.
*/
function getDirInternal(key, pathArray, shouldCreate) {
function getDirInternal(key, pathArray, shouldCreate, update) {
var fileLocator = Components.classes["@mozilla.org/file/directory_service;1"]
.getService(Components.interfaces.nsIProperties);
var dir = fileLocator.get(key, Components.interfaces.nsIFile);
var dir = fileLocator.get(key, Components.interfaces.nsILocalFile);
#ifdef XP_WIN
if (update) {
var programFilesDir = fileLocator.get(KEY_PROGRAMFILES,
Components.interfaces.nsILocalFile);
if (programFilesDir.contains(dir, true)) {
var relativePath = dir.getRelativeDescriptor(programFilesDir);
var userLocalDir = fileLocator.get(KEY_LOCALDATA,
Components.interfaces.nsILocalFile).parent;
dir.setRelativeDescriptor(userLocalDir, relativePath);
}
}
#endif
for (var i = 0; i < pathArray.length; ++i) {
dir.append(pathArray[i]);
if (shouldCreate && !dir.exists())
@@ -242,6 +276,22 @@ function getFile(key, pathArray) {
return file;
}
/**
* Gets the file at the speciifed hierarchy under the update root directory.
* @param pathArray
* An array of path components to locate beneath the directory
* specified by |key|. The last item in this array must be the
* leaf name of a file.
* @return nsIFile object for the file specified. The file is NOT created
* if it does not exist, however all required directories along
* the way are.
*/
function getUpdateFile(pathArray) {
var file = getUpdateDir(pathArray.slice(0, -1));
file.append(pathArray[pathArray.length - 1]);
return file;
}
/**
* Closes a Safe Output Stream
* @param fos
@@ -289,18 +339,36 @@ function getStatusTextFromCode(code, defaultCode) {
/**
* Get the Active Updates directory
* @param key
* The Directory Service Key (optional).
* If used, don't search local appdata on Win32 and don't create dir.
* @returns The active updates directory, as a nsIFile object
*/
function getUpdatesDir() {
function getUpdatesDir(key) {
// Right now, we only support downloading one patch at a time, so we always
// use the same target directory.
var fileLocator =
Components.classes["@mozilla.org/file/directory_service;1"].
getService(Components.interfaces.nsIProperties);
var appDir = fileLocator.get(KEY_APPDIR, Components.interfaces.nsIFile);
var appDir;
if (key)
appDir = fileLocator.get(key, Components.interfaces.nsILocalFile);
else {
appDir = fileLocator.get(KEY_APPDIR, Components.interfaces.nsILocalFile);
#ifdef XP_WIN
var programFilesDir = fileLocator.get(KEY_PROGRAMFILES,
Components.interfaces.nsILocalFile);
if (programFilesDir.contains(appDir, true)) {
var relativePath = appDir.getRelativeDescriptor(programFilesDir);
var userLocalDir = fileLocator.get(KEY_LOCALDATA,
Components.interfaces.nsILocalFile).parent;
appDir.setRelativeDescriptor(userLocalDir, relativePath);
}
#endif
}
appDir.append(DIR_UPDATES);
appDir.append("0");
if (!appDir.exists())
if (!appDir.exists() && !key)
appDir.create(nsILocalFile.DIRECTORY_TYPE, PERMS_DIRECTORY);
return appDir;
}
@@ -337,17 +405,20 @@ function writeStatusFile(dir, state) {
/**
* Removes the Updates Directory
* @param key
* The Directory Service Key under which update directory resides
* (optional).
*/
function cleanUpUpdatesDir() {
function cleanUpUpdatesDir(key) {
// Bail out if we don't have appropriate permissions
var updateDir;
try {
updateDir = getUpdatesDir();
updateDir = getUpdatesDir(key);
}
catch (e) {
return;
}
var e = updateDir.directoryEntries;
while (e.hasMoreElements()) {
var f = e.getNext().QueryInterface(Components.interfaces.nsIFile);
@@ -386,8 +457,11 @@ function cleanUpUpdatesDir() {
/**
* Clean up updates list and the updates directory.
* @param key
* The Directory Service Key under which update directory resides
* (optional).
*/
function cleanupActiveUpdate() {
function cleanupActiveUpdate(key) {
// Move the update from the Active Update list into the Past Updates list.
var um =
Components.classes["@mozilla.org/updates/update-manager;1"].
@@ -396,7 +470,7 @@ function cleanupActiveUpdate() {
um.saveUpdates();
// Now trash the updates directory, since we're done with it
cleanUpUpdatesDir();
cleanUpUpdatesDir(key);
}
/**
@@ -1048,6 +1122,30 @@ UpdateService.prototype = {
if (status == "null")
status = null;
var updRootKey = null;
#ifdef XP_WIN
function findPreviousUpdate(key) {
var updateDir = getUpdatesDir(key);
if (updateDir.exists()) {
status = readStatusFile(updateDir);
// Previous download should succeed. Otherwise, we will not be here!
if (status == STATE_SUCCEEDED)
updRootKey = key;
else
status = null;
}
}
// required when updating from Fx 2.0.0.1 to 2.0.0.3 (or later)
// on Windows Vista.
if (status == null)
findPreviousUpdate(KEY_UAPPDATA);
// required to migrate from older versions.
if (status == null)
findPreviousUpdate(KEY_APPDIR);
#endif
if (status == STATE_DOWNLOADING) {
LOG("UpdateService", "_postUpdateProcessing: Downloading patch, resuming...");
}
@@ -1098,7 +1196,7 @@ UpdateService.prototype = {
}
// Done with this update. Clean it up.
cleanupActiveUpdate();
cleanupActiveUpdate(updRootKey);
}
else {
// If we hit an error, then the error code will be included in the
@@ -1407,7 +1505,7 @@ UpdateService.prototype = {
*/
get canUpdate() {
try {
var appDirFile = getFile(KEY_APPDIR, [FILE_PERMS_TEST]);
var appDirFile = getUpdateFile([FILE_PERMS_TEST]);
if (!appDirFile.exists()) {
appDirFile.create(nsILocalFile.NORMAL_FILE_TYPE, PERMS_FILE);
appDirFile.remove(false);
@@ -1516,8 +1614,7 @@ UpdateService.prototype = {
*/
function UpdateManager() {
// Ensure the Active Update file is loaded
var updates = this._loadXMLFileIntoArray(getFile(KEY_APPDIR,
[FILE_UPDATE_ACTIVE]));
var updates = this._loadXMLFileIntoArray(getUpdateFile([FILE_UPDATE_ACTIVE]));
if (updates.length > 0)
this._activeUpdate = updates[0];
}
@@ -1584,7 +1681,7 @@ UpdateManager.prototype = {
*/
_ensureUpdates: function() {
if (!this._updates) {
this._updates = this._loadXMLFileIntoArray(getFile(KEY_APPDIR,
this._updates = this._loadXMLFileIntoArray(getUpdateFile(
[FILE_UPDATES_DB]));
// Make sure that any active update is part of our updates list
@@ -1635,7 +1732,7 @@ UpdateManager.prototype = {
}
else
this._writeUpdatesToXMLFile([this._activeUpdate],
getFile(KEY_APPDIR, [FILE_UPDATE_ACTIVE]));
getUpdateFile([FILE_UPDATE_ACTIVE]));
return activeUpdate;
},
@@ -1707,10 +1804,10 @@ UpdateManager.prototype = {
*/
saveUpdates: function() {
this._writeUpdatesToXMLFile([this._activeUpdate],
getFile(KEY_APPDIR, [FILE_UPDATE_ACTIVE]));
getUpdateFile([FILE_UPDATE_ACTIVE]));
if (this._updates) {
this._writeUpdatesToXMLFile(this._updates.slice(0, 10),
getFile(KEY_APPDIR, [FILE_UPDATES_DB]));
getUpdateFile([FILE_UPDATES_DB]));
}
},

View File

@@ -64,7 +64,7 @@ USE_STATIC_LIBS = 1
HAVE_PROGRESSUI = 1
RCINCLUDE = updater.rc
CPPSRCS += progressui_win.cpp
OS_LIBS += $(call EXPAND_LIBNAME,comctl32 ws2_32)
OS_LIBS += $(call EXPAND_LIBNAME,comctl32 ws2_32 shell32)
ifndef GNU_CC
RCFLAGS += -I$(srcdir)
else

View File

@@ -1022,7 +1022,7 @@ LaunchCallbackApp(const char *workingDir, int argc, char **argv)
#elif defined(XP_MACOSX)
LaunchChild(argc, argv);
#elif defined(XP_WIN)
WinLaunchChild(argv[0], argc, argv);
WinLaunchChild(argv[0], argc, argv, -1);
#else
# warning "Need implementaton of LaunchCallbackApp"
#endif
@@ -1200,8 +1200,10 @@ ActionList::Prepare()
// If the action list is empty then we should fail in order to signal that
// something has gone wrong. Otherwise we report success when nothing is
// actually done. See bug 327140.
if (mCount == 0)
if (mCount == 0) {
LOG(("empty action list\n"));
return UNEXPECTED_ERROR;
}
Action *a = mFirst;
while (a) {

View File

@@ -96,6 +96,10 @@ XPIDLSRCS = \
nsIXULRuntime.idl \
$(NULL)
ifeq ($(OS_ARCH),WINNT)
XPIDLSRCS += nsIWinAppHelper.idl
endif
EXPORTS = \
xrecore.h \
nsXULAppAPI.h \

View File

@@ -98,6 +98,9 @@
#include "nsIWindowWatcher.h"
#include "nsIXULAppInfo.h"
#include "nsIXULRuntime.h"
#ifdef XP_WIN
#include "nsIWinAppHelper.h"
#endif
#include "nsCRT.h"
#include "nsCOMPtr.h"
@@ -138,6 +141,8 @@
#ifdef XP_WIN
#include <process.h>
#include <shlobj.h>
#include "nsThreadUtils.h"
#endif
#ifdef XP_OS2
@@ -407,6 +412,75 @@ CheckArg(const char* aArg, const char **aParam = nsnull)
return ARG_NONE;
}
#if defined(XP_WIN)
/**
* Check for a commandline flag from the windows shell and remove it from the
* argv used when restarting. Flags MUST be in the form -arg.
*
* @param aArg the parameter to check. Must be lowercase.
*/
static ArgResult
CheckArgShell(const char* aArg)
{
char **curarg = gRestartArgv + 1; // skip argv[0]
while (*curarg) {
char *arg = curarg[0];
if (arg[0] == '-') {
++arg;
if (strimatch(aArg, arg)) {
do {
*curarg = *(curarg + 1);
++curarg;
} while (*curarg);
--gRestartArgc;
return ARG_FOUND;
}
}
++curarg;
}
return ARG_NONE;
}
/**
* Spins up Windows DDE when the app needs to restart or the profile manager
* will be displayed during startup and the app has been launched by the Windows
* shell to open an url. This prevents Windows from displaying an error message
* due to the DDE message not being acknowledged.
*/
static void
ProcessDDE(nsINativeAppSupport* aNative)
{
// When the app is launched by the windows shell the windows shell
// expects the app to be available for DDE messages and if it isn't
// windows displays an error dialog. To prevent the error the DDE server
// is enabled and pending events are processed when the app needs to
// restart after it was launched by the shell with the requestpending
// argument. The requestpending pending argument is removed to
// differentiate it from being launched when an app restart is not
// required.
ArgResult ar;
ar = CheckArgShell("requestpending");
if (ar == ARG_FOUND) {
aNative->Enable(); // enable win32 DDE responses
nsIThread *thread = NS_GetCurrentThread();
// This is just a guesstimate based on testing different values.
// If count is 8 or less windows will display an error dialog.
PRInt32 count = 20;
while(--count >= 0) {
NS_ProcessNextEvent(thread);
PR_Sleep(PR_MillisecondsToInterval(1));
}
}
}
#endif
PRBool gSafeMode = PR_FALSE;
/**
@@ -414,17 +488,29 @@ PRBool gSafeMode = PR_FALSE;
* singleton.
*/
class nsXULAppInfo : public nsIXULAppInfo,
#ifdef XP_WIN
public nsIWinAppHelper,
#endif
public nsIXULRuntime
{
public:
NS_DECL_ISUPPORTS_INHERITED
NS_DECL_NSIXULAPPINFO
NS_DECL_NSIXULRUNTIME
#ifdef XP_WIN
NS_DECL_NSIWINAPPHELPER
private:
nsresult LaunchAppHelperWithArgs(int aArgc, char **aArgv);
#endif
};
NS_INTERFACE_MAP_BEGIN(nsXULAppInfo)
NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIXULRuntime)
NS_INTERFACE_MAP_ENTRY(nsIXULRuntime)
#ifdef XP_WIN
NS_INTERFACE_MAP_ENTRY(nsIWinAppHelper)
#endif
NS_INTERFACE_MAP_ENTRY_CONDITIONAL(nsIXULAppInfo, gAppData)
NS_INTERFACE_MAP_END
@@ -535,6 +621,92 @@ nsXULAppInfo::GetXPCOMABI(nsACString& aResult)
#endif
}
#ifdef XP_WIN
nsresult
nsXULAppInfo::LaunchAppHelperWithArgs(int aArgc, char **aArgv)
{
nsresult rv;
nsCOMPtr<nsIProperties> directoryService =
do_GetService(NS_DIRECTORY_SERVICE_CONTRACTID, &rv);
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<nsILocalFile> appHelper;
rv = directoryService->Get(NS_XPCOM_CURRENT_PROCESS_DIR, NS_GET_IID(nsILocalFile), getter_AddRefs(appHelper));
NS_ENSURE_SUCCESS(rv, rv);
rv = appHelper->AppendNative(NS_LITERAL_CSTRING("uninstall"));
NS_ENSURE_SUCCESS(rv, rv);
rv = appHelper->AppendNative(NS_LITERAL_CSTRING("helper.exe"));
NS_ENSURE_SUCCESS(rv, rv);
nsCAutoString appHelperPath;
rv = appHelper->GetNativePath(appHelperPath);
NS_ENSURE_SUCCESS(rv, rv);
if (!WinLaunchChild(appHelperPath.get(), aArgc, aArgv, 1))
return NS_ERROR_FAILURE;
else
return NS_OK;
}
NS_IMETHODIMP
nsXULAppInfo::FixReg()
{
int resetRegArgc = 2;
char **resetRegArgv = (char**) malloc(sizeof(char*) * (resetRegArgc + 1));
if (!resetRegArgv)
return NS_ERROR_OUT_OF_MEMORY;
resetRegArgv[0] = "argv0ignoredbywinlaunchchild";
resetRegArgv[1] = "/fixreg";
resetRegArgv[2] = nsnull;
nsresult rv = LaunchAppHelperWithArgs(resetRegArgc, resetRegArgv);
free(resetRegArgv);
return rv;
}
NS_IMETHODIMP
nsXULAppInfo::PostUpdate(nsILocalFile *aLogFile)
{
nsresult rv;
int upgradeArgc = aLogFile ? 3 : 2;
char **upgradeArgv = (char**) malloc(sizeof(char*) * (upgradeArgc + 1));
if (!upgradeArgv)
return NS_ERROR_OUT_OF_MEMORY;
upgradeArgv[0] = "argv0ignoredbywinlaunchchild";
upgradeArgv[1] = "/postupdate";
char *pathArg = nsnull;
if (aLogFile) {
nsCAutoString logFilePath;
rv = aLogFile->GetNativePath(logFilePath);
NS_ENSURE_SUCCESS(rv, rv);
pathArg = PR_smprintf("/uninstalllog=%s", logFilePath.get());
if (!pathArg)
return NS_ERROR_OUT_OF_MEMORY;
upgradeArgv[2] = pathArg;
upgradeArgv[3] = nsnull;
}
else {
upgradeArgv[2] = nsnull;
}
rv = LaunchAppHelperWithArgs(upgradeArgc, upgradeArgv);
if (pathArg)
PR_smprintf_free(pathArg);
free(upgradeArgv);
return rv;
}
#endif
static const nsXULAppInfo kAppInfo;
static NS_METHOD AppInfoConstructor(nsISupports* aOuter,
REFNSIID aIID, void **aResult)
@@ -1199,6 +1371,27 @@ XRE_GetBinaryPath(const char* argv0, nsILocalFile* *aResult)
return NS_OK;
}
// copied from nsXREDirProvider.cpp
#ifdef XP_WIN
static nsresult
GetShellFolderPath(int folder, char result[MAXPATHLEN])
{
LPITEMIDLIST pItemIDList = NULL;
nsresult rv;
if (SUCCEEDED(SHGetSpecialFolderLocation(NULL, folder, &pItemIDList)) &&
SUCCEEDED(SHGetPathFromIDList(pItemIDList, result))) {
rv = NS_OK;
} else {
rv = NS_ERROR_NOT_AVAILABLE;
}
CoTaskMemFree(pItemIDList);
return rv;
}
#endif
#define NS_ERROR_LAUNCHED_CHILD_PROCESS NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_PROFILE, 200)
#ifdef XP_WIN
@@ -1237,7 +1430,7 @@ static nsresult LaunchChild(nsINativeAppSupport* aNative,
return rv;
#if defined(XP_WIN)
if (!WinLaunchChild(exePath.get(), gRestartArgc, gRestartArgv))
if (!WinLaunchChild(exePath.get(), gRestartArgc, gRestartArgv, 0))
return NS_ERROR_FAILURE;
#elif defined(XP_OS2)
if (_execv(exePath.get(), gRestartArgv) == -1)
@@ -1369,6 +1562,10 @@ ShowProfileManager(nsIToolkitProfileService* aProfileSvc,
SetupMacCommandLine(gRestartArgc, gRestartArgv);
#endif
#ifdef XP_WIN
ProcessDDE(aNative);
#endif
{ //extra scoping is needed so we release these components before xpcom shutdown
nsCOMPtr<nsIWindowWatcher> windowWatcher
(do_GetService(NS_WINDOWWATCHER_CONTRACTID));
@@ -2251,8 +2448,45 @@ XRE_main(int argc, char* argv[], const nsXREAppData* aAppData)
#if defined(MOZ_UPDATER)
// Check for and process any available updates
nsCOMPtr<nsIFile> updRoot = dirProvider.GetAppDir();
nsCOMPtr<nsILocalFile> updRootl(do_QueryInterface(updRoot));
#ifdef XP_WIN
// Use <UserLocalDataDir>\updates\<relative path to app dir from
// Program Files> if app dir is under Program Files to avoid the
// folder virtualization mess on Windows Vista
char path[MAXPATHLEN];
rv = GetShellFolderPath(CSIDL_PROGRAM_FILES, path);
NS_ENSURE_SUCCESS(rv, 1);
nsCOMPtr<nsILocalFile> programFilesDir;
rv = NS_NewNativeLocalFile(nsDependentCString(path), PR_FALSE,
getter_AddRefs(programFilesDir));
NS_ENSURE_SUCCESS(rv, 1);
PRBool descendant;
rv = programFilesDir->Contains(updRootl, PR_TRUE, &descendant);
NS_ENSURE_SUCCESS(rv, 1);
if (descendant) {
nsCAutoString relativePath;
rv = updRootl->GetRelativeDescriptor(programFilesDir, relativePath);
NS_ENSURE_SUCCESS(rv, 1);
nsCOMPtr<nsILocalFile> userLocalDir;
rv = dirProvider.GetUserLocalDataDirectory(getter_AddRefs(userLocalDir));
NS_ENSURE_SUCCESS(rv, 1);
rv = NS_NewNativeLocalFile(EmptyCString(), PR_FALSE,
getter_AddRefs(updRootl));
NS_ENSURE_SUCCESS(rv, 1);
rv = updRootl->SetRelativeDescriptor(userLocalDir, relativePath);
NS_ENSURE_SUCCESS(rv, 1);
}
#endif
ProcessUpdates(dirProvider.GetGREDir(),
dirProvider.GetAppDir(),
updRootl,
gRestartArgc,
gRestartArgv);
#endif
@@ -2543,6 +2777,10 @@ XRE_main(int argc, char* argv[], const nsXREAppData* aAppData)
// registry - major milestone vs. build id.
needsRestart = PR_TRUE;
#ifdef XP_WIN
ProcessDDE(nativeApp);
#endif
#ifdef XP_MACOSX
SetupMacCommandLine(gRestartArgc, gRestartArgv);
#endif

View File

@@ -119,7 +119,7 @@ WriteConsoleLog();
#ifdef XP_WIN
BOOL
WinLaunchChild(const char *exePath, int argc, char **argv);
WinLaunchChild(const char *exePath, int argc, char **argv, int needElevation);
#endif
#define NS_NATIVEAPPSUPPORT_CONTRACTID "@mozilla.org/toolkit/native-app-support;1"

View File

@@ -0,0 +1,54 @@
/* ***** 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 post update cleanup
*
* The Initial Developer of the Original Code is
* Seth Spitzer <sspitzer@mozilla.org>
* Portions created by the Initial Developer are Copyright (C) 2007
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
*
* 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 ***** */
#include "nsISupports.idl"
/**
* A scriptable interface used on Windows only to do some work from
* a special process that gets created with elevated privileges.
*
* @status UNSTABLE - This interface is not frozen and will probably change in
* future releases.
*/
interface nsILocalFile;
[scriptable, uuid(575249a7-de7a-4602-a997-b7ad2b3b6dab)]
interface nsIWinAppHelper : nsISupports
{
void postUpdate(in nsILocalFile logFile);
void fixReg();
};

View File

@@ -21,6 +21,7 @@
*
* Contributor(s):
* Bill Law law@netscape.com
* Robert Strong robert.bugzilla@gmail.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
@@ -256,10 +257,10 @@ private:
* whether Mozilla is already running.
*/
/* Update 2006 September
/* Update 2007 January
*
* A change in behavior was implemented in July 2004 which made the
* application add on launch and remove on quit the ddexec registry key.
* application on launch to add and on quit to remove the ddexec registry key.
* See bug 246078.
* Windows Vista has changed the methods used to set an application as default
* and the new methods are incompatible with removing the ddeexec registry key.
@@ -280,21 +281,20 @@ private:
* for the verb (e.g. open).
*
* Application DDE Sequence:
* 1. If the application is running a DDE request is received DDE with the
* 1. If the application is running a DDE request is received with the
* WWW_OpenURL topic and the params as specified in the default value of the
* ddeexec registry key (e.g. "%1",,0,0,,,, where '%1' is the url to open)
* for the verb (e.g. open).
* 2. If the application is not running it is launched with the -url argument.
* 2. If the application is not running it is launched with the -requestPending
* and the -url argument.
* 2.1 If the application does not need to restart and the -requestPending
* argument is present the accompanying url will not be used. Instead the
* application will wait for the DDE message to open the url.
* 2.2 If the application needs to restart the -requestPending argument is
* removed from the arguments used to restart the application and the url
* will be handled normally.
*
* Note: Typically the application should use the DDE request to open the page
* instead of using a command line argument. The command line argument is
* used to work around when the DDE queue is hung by a different
* application. See bug 53952.
*
* 3. The application receives a DDE request with the WWW_OpenURL topic and the
* params from the ifexec key without the url (e.g. ,,0,0,,,,). The
* application treats this request as a noop internally and returns the
* correct values for the DDE request to the OS.
* Note: Due to a bug in IE the ifexec key should not be used (see bug 355650).
*/
class nsNativeAppSupportWin : public nsNativeAppSupportBase,
@@ -457,6 +457,7 @@ NS_CreateNativeAppSupport( nsINativeAppSupport **aResult ) {
// Constants
#define MOZ_DDE_APPLICATION "Mozilla"
#define MOZ_MUTEX_NAMESPACE "Local\\"
#define MOZ_STARTUP_MUTEX_NAME "StartupMutex"
#define MOZ_DDE_START_TIMEOUT 30000
#define MOZ_DDE_STOP_TIMEOUT 15000
@@ -677,7 +678,8 @@ nsNativeAppSupportWin::Start( PRBool *aResult ) {
// Grab mutex first.
// Build mutex name from app name.
::_snprintf( mMutexName, sizeof mMutexName, "%s%s", gAppData->name, MOZ_STARTUP_MUTEX_NAME );
::_snprintf( mMutexName, sizeof mMutexName, "%s%s%s", MOZ_MUTEX_NAMESPACE,
gAppData->name, MOZ_STARTUP_MUTEX_NAME );
Mutex startupLock = Mutex( mMutexName );
NS_ENSURE_TRUE( startupLock.Lock( MOZ_DDE_START_TIMEOUT ), NS_ERROR_FAILURE );
@@ -835,6 +837,9 @@ nsNativeAppSupportWin::Quit() {
}
DdeUninitialize( mInstance );
mInstance = 0;
#if MOZ_DEBUG_DDE
printf( "DDE server stopped\n" );
#endif
}
return NS_OK;
@@ -978,25 +983,23 @@ nsNativeAppSupportWin::HandleDDENotification( UINT uType, // transaction t
nsCAutoString url;
ParseDDEArg(hsz2, 0, url);
if ( !url.Equals( "" ) ) {
// Read the 3rd argument in the command to determine if a
// new window is to be used.
nsCAutoString windowID;
ParseDDEArg(hsz2, 2, windowID);
// "" means to open the URL in a new window.
if ( windowID.Equals( "" ) ) {
url.Insert("mozilla -new-window ", 0);
}
else {
url.Insert("mozilla -url ", 0);
}
// Read the 3rd argument in the command to determine if a
// new window is to be used.
nsCAutoString windowID;
ParseDDEArg(hsz2, 2, windowID);
// "" means to open the URL in a new window.
if ( windowID.Equals( "" ) ) {
url.Insert("mozilla -new-window ", 0);
}
else {
url.Insert("mozilla -url ", 0);
}
#if MOZ_DEBUG_DDE
printf( "Handling dde XTYP_REQUEST request: [%s]...\n", url.get() );
printf( "Handling dde XTYP_REQUEST request: [%s]...\n", url.get() );
#endif
// Now handle it.
HandleCommandLine(url.get(), nsnull, nsICommandLine::STATE_REMOTE_EXPLICIT);
}
// Now handle it.
HandleCommandLine(url.get(), nsnull, nsICommandLine::STATE_REMOTE_EXPLICIT);
// Return pseudo window ID.
result = CreateDDEData( 1 );
@@ -1151,25 +1154,23 @@ nsNativeAppSupportWin::HandleDDENotification( UINT uType, // transaction t
nsCAutoString url;
ParseDDEArg((const char*) request, 0, url);
if ( !url.Equals( "" ) ) {
// Read the 3rd argument in the command to determine if a
// new window is to be used.
nsCAutoString windowID;
ParseDDEArg((const char*) request, 2, windowID);
// Read the 3rd argument in the command to determine if a
// new window is to be used.
nsCAutoString windowID;
ParseDDEArg((const char*) request, 2, windowID);
// "" means to open the URL in a new window.
if ( windowID.Equals( "" ) ) {
url.Insert("mozilla -new-window ", 0);
}
else {
url.Insert("mozilla -url ", 0);
}
#if MOZ_DEBUG_DDE
printf( "Handling dde XTYP_REQUEST request: [%s]...\n", url.get() );
#endif
// Now handle it.
HandleCommandLine(url.get(), nsnull, nsICommandLine::STATE_REMOTE_EXPLICIT);
// "" means to open the URL in a new window.
if ( windowID.Equals( "" ) ) {
url.Insert("mozilla -new-window ", 0);
}
else {
url.Insert("mozilla -url ", 0);
}
#if MOZ_DEBUG_DDE
printf( "Handling dde XTYP_REQUEST request: [%s]...\n", url.get() );
#endif
// Now handle it.
HandleCommandLine(url.get(), nsnull, nsICommandLine::STATE_REMOTE_EXPLICIT);
// Release the data.
DdeUnaccessData( hdata );

View File

@@ -435,7 +435,7 @@ ApplyUpdate(nsIFile *greDir, nsIFile *updateDir, nsILocalFile *statusFile,
#elif defined(XP_WIN)
_chdir(applyToDir.get());
if (!WinLaunchChild(updaterPath.get(), appArgc + 4, argv))
if (!WinLaunchChild(updaterPath.get(), appArgc + 4, argv, 1))
return;
_exit(0);
#else
@@ -464,12 +464,13 @@ end:
}
nsresult
ProcessUpdates(nsIFile *greDir, nsIFile *appDir, int argc, char **argv)
ProcessUpdates(nsIFile *greDir, nsIFile *appDir, nsIFile *updRootDir,
int argc, char **argv)
{
nsresult rv;
nsCOMPtr<nsIFile> updatesDir;
rv = appDir->Clone(getter_AddRefs(updatesDir));
rv = updRootDir->Clone(getter_AddRefs(updatesDir));
if (NS_FAILED(rv))
return rv;
rv = updatesDir->AppendNative(NS_LITERAL_CSTRING("updates"));

View File

@@ -58,6 +58,7 @@ class nsIFile;
* This function does not modify appDir.
*/
NS_HIDDEN_(nsresult) ProcessUpdates(nsIFile *greDir, nsIFile *appDir,
nsIFile *updRootDir,
int argc, char **argv);
#endif // nsUpdateDriver_h__

View File

@@ -44,6 +44,24 @@
#define nsWindowsRestart_cpp
#endif
#include <shellapi.h>
#ifndef ERROR_ELEVATION_REQUIRED
#define ERROR_ELEVATION_REQUIRED 740L
#endif
BOOL (WINAPI *pCreateProcessWithTokenW)(HANDLE,
DWORD,
LPCWSTR,
LPWSTR,
DWORD,
LPVOID,
LPCWSTR,
LPSTARTUPINFOW,
LPPROCESS_INFORMATION);
BOOL (WINAPI *pIsUserAnAdmin)(VOID);
/**
* Get the length that the string will take when it is quoted.
*/
@@ -117,37 +135,159 @@ MakeCommandLine(int argc, char **argv)
return s;
}
/**
* alloc and convert multibyte char to unicode char
*/
static PRUnichar *
AllocConvertAToW(const char *buf)
{
PRUint32 inputLen = strlen(buf) + 1;
int n = MultiByteToWideChar(CP_ACP, 0, buf, inputLen, NULL, 0);
if (n <= 0)
return NULL;
PRUnichar *result = (PRUnichar *)malloc(n * sizeof(PRUnichar));
if (!result)
return NULL;
MultiByteToWideChar(CP_ACP, 0, buf, inputLen, result, n);
return result;
}
/**
* Launch a child process without elevated privilege.
*/
static BOOL
LaunchAsNormalUser(const char *exePath, char *cl)
{
if (!pCreateProcessWithTokenW) {
// IsUserAnAdmin is not present on Win9x and not exported by name on Win2k
*(FARPROC *)&pIsUserAnAdmin =
GetProcAddress(GetModuleHandle("shell32.dll"), "IsUserAnAdmin");
// CreateProcessWithTokenW is not present on WinXP or earlier
*(FARPROC *)&pCreateProcessWithTokenW =
GetProcAddress(GetModuleHandle("advapi32.dll"),
"CreateProcessWithTokenW");
if (!pCreateProcessWithTokenW)
return FALSE;
}
// do nothing here if we are not elevated or IsUserAnAdmin is not present.
if (!pIsUserAnAdmin || pIsUserAnAdmin && !pIsUserAnAdmin())
return FALSE;
// borrow the shell token to drop the privilege
HWND hwndShell = FindWindow("Progman", NULL);
DWORD dwProcessId;
GetWindowThreadProcessId(hwndShell, &dwProcessId);
HANDLE hProcessShell = OpenProcess(MAXIMUM_ALLOWED, FALSE, dwProcessId);
if (!hProcessShell)
return FALSE;
HANDLE hTokenShell;
BOOL ok = OpenProcessToken(hProcessShell, MAXIMUM_ALLOWED, &hTokenShell);
CloseHandle(hProcessShell);
if (!ok)
return FALSE;
HANDLE hNewToken;
ok = DuplicateTokenEx(hTokenShell,
MAXIMUM_ALLOWED,
NULL,
SecurityDelegation,
TokenPrimary,
&hNewToken);
CloseHandle(hTokenShell);
if (!ok)
return FALSE;
STARTUPINFOW si = {sizeof(si), 0};
PROCESS_INFORMATION pi = {0};
PRUnichar *exePathW = AllocConvertAToW(exePath);
PRUnichar *clW = AllocConvertAToW(cl);
ok = exePathW && clW;
if (ok) {
ok = pCreateProcessWithTokenW(hNewToken,
0, // profile is already loaded
exePathW,
clW,
0, // No special process creation flags
NULL, // inherit my environment
NULL, // use my current directory
&si,
&pi);
}
free(exePathW);
free(clW);
CloseHandle(hNewToken);
if (!ok)
return FALSE;
CloseHandle(pi.hProcess);
CloseHandle(pi.hThread);
return TRUE;
}
/**
* Launch a child process with the specified arguments.
* @param needElevation 1:need elevation, -1:want to drop priv, 0:don't care
* @note argv[0] is ignored
*/
BOOL
WinLaunchChild(const char *exePath, int argc, char **argv)
WinLaunchChild(const char *exePath, int argc, char **argv, int needElevation)
{
char *cl = MakeCommandLine(argc, argv);
char *cl;
BOOL ok;
if (needElevation > 0) {
cl = MakeCommandLine(argc - 1, argv + 1);
if (!cl)
return FALSE;
ok = ShellExecute(NULL, // no special UI window
NULL, // use default verb
exePath,
cl,
NULL, // use my current directory
SW_SHOWDEFAULT) > (HINSTANCE)32;
free(cl);
return ok;
}
cl = MakeCommandLine(argc, argv);
if (!cl)
return FALSE;
STARTUPINFO si = {sizeof(si), 0};
PROCESS_INFORMATION pi = {0};
if (needElevation < 0) {
// try to launch as a normal user first
ok = LaunchAsNormalUser(exePath, cl);
// if it fails, fallback to normal launching
if (!ok)
needElevation = 0;
}
if (needElevation == 0) {
STARTUPINFO si = {sizeof(si), 0};
PROCESS_INFORMATION pi = {0};
BOOL ok = CreateProcess(exePath,
cl,
NULL, // no special security attributes
NULL, // no special thread attributes
FALSE, // don't inherit filehandles
0, // No special process creation flags
NULL, // inherit my environment
NULL, // use my current directory
&si,
&pi);
ok = CreateProcess(exePath,
cl,
NULL, // no special security attributes
NULL, // no special thread attributes
FALSE, // don't inherit filehandles
0, // No special process creation flags
NULL, // inherit my environment
NULL, // use my current directory
&si,
&pi);
if (ok) {
CloseHandle(pi.hProcess);
CloseHandle(pi.hThread);
}
}
free(cl);
if (ok) {
CloseHandle(pi.hProcess);
CloseHandle(pi.hThread);
}
return ok;
}