diff --git a/mozilla/toolkit/mozapps/update/src/updater/Makefile.in b/mozilla/toolkit/mozapps/update/src/updater/Makefile.in index aac2e404dce..47828e6909b 100644 --- a/mozilla/toolkit/mozapps/update/src/updater/Makefile.in +++ b/mozilla/toolkit/mozapps/update/src/updater/Makefile.in @@ -108,8 +108,13 @@ libs:: mkdir -p $(DIST)/bin/updater.app rsync -a --exclude CVS $(srcdir)/macbuild/Contents $(DIST)/bin/updater.app mkdir -p $(DIST)/bin/updater.app/Contents/MacOS - # copy and remove to un-symlink (FSCopyObject seems to not copy symlinks) +# copy and remove to un-symlink (FSCopyObject seems to not copy symlinks) rm -f $(DIST)/bin/updater.app/Contents/MacOS/updater cp -f $(DIST)/bin/updater $(DIST)/bin/updater.app/Contents/MacOS rm -f $(DIST)/bin/updater endif + +ifeq ($(OS_ARCH),WINNT) +# Pick up nsWindowsRestart.cpp +LOCAL_INCLUDES += -I$(topsrcdir)/toolkit/xre +endif diff --git a/mozilla/toolkit/mozapps/update/src/updater/updater.cpp b/mozilla/toolkit/mozapps/update/src/updater/updater.cpp index 45e75966a95..3fac91fb957 100644 --- a/mozilla/toolkit/mozapps/update/src/updater/updater.cpp +++ b/mozilla/toolkit/mozapps/update/src/updater/updater.cpp @@ -948,6 +948,10 @@ PatchIfFile::Finish(int status) //----------------------------------------------------------------------------- +#ifdef XP_WIN +#include "nsWindowsRestart.cpp" +#endif + static void LaunchCallbackApp(int argc, char **argv) { @@ -956,13 +960,7 @@ LaunchCallbackApp(int argc, char **argv) #elif defined(XP_MACOSX) LaunchChild(argc, argv); #elif defined(XP_WIN) - // _spawnv gets angry if the executable path has spaces in it. - char shortPath[_MAX_PATH]; - ::GetShortPathName(argv[0], shortPath, sizeof(shortPath)); - - argv[0] = shortPath; - - _spawnv(_P_NOWAIT, shortPath, argv); + WinLaunchChild(argv[0], argc, argv); #else # warning "Need implementaton of LaunchCallbackApp" #endif diff --git a/mozilla/toolkit/xre/Makefile.in b/mozilla/toolkit/xre/Makefile.in index 53268a8ad61..b4bbe8cae49 100644 --- a/mozilla/toolkit/xre/Makefile.in +++ b/mozilla/toolkit/xre/Makefile.in @@ -184,6 +184,7 @@ export:: endif LOCAL_INCLUDES += \ + -I$(srcdir) \ -I$(topsrcdir)/xpfe/bootstrap \ -I$(srcdir)/../profile/src \ -I$(topsrcdir)/config \ diff --git a/mozilla/toolkit/xre/nsAppRunner.cpp b/mozilla/toolkit/xre/nsAppRunner.cpp index f42a0303d95..52d17aa955a 100644 --- a/mozilla/toolkit/xre/nsAppRunner.cpp +++ b/mozilla/toolkit/xre/nsAppRunner.cpp @@ -132,7 +132,6 @@ #endif //XP_BEOS #ifdef XP_WIN -#include #include #endif @@ -240,22 +239,6 @@ extern "C" { extern void InstallUnixSignalHandlers(const char *ProgramName); #endif -#if defined(XP_WIN) -/** - * Return a malloc'd copy of the given string surrounded with double quotes. - */ -static char *NewQuotedString(const char *input) -{ - int len = strlen(input); - char *p = (char *) malloc(len + 3); - p[0] = '\"'; - memcpy(&p[1], input, len); - p[len + 1] = '\"'; - p[len + 2] = '\0'; - return p; -} -#endif - int gArgc; char **gArgv; @@ -1159,6 +1142,10 @@ XRE_GetBinaryPath(const char* argv0, nsILocalFile* *aResult) #define NS_ERROR_LAUNCHED_CHILD_PROCESS NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_PROFILE, 200) +#ifdef XP_WIN +#include "nsWindowsRestart.cpp" +#endif + // If aBlankCommandLine is true, then the application will be launched with a // blank command line instead of being launched with the same command line that // it was initially started with. @@ -1189,15 +1176,7 @@ static nsresult LaunchChild(nsINativeAppSupport* aNative, return rv; #if defined(XP_WIN) - // We must shorten the path to a 8.3 path, since that's all _execv can - // handle (otherwise segments after any spaces that might exist in the path - // will be converted into parameters, and really weird things will happen) - char shortPath[MAXPATHLEN]; - ::GetShortPathName(exePath.get(), shortPath, MAXPATHLEN); - - gRestartArgv[0] = shortPath; - - if (_execv(shortPath, gRestartArgv) == -1) + if (!WinLaunchChild(exePath.get(), gRestartArgc, gRestartArgv)) return NS_ERROR_FAILURE; #elif defined(XP_OS2) if (_execv(exePath.get(), gRestartArgv) == -1) @@ -1459,7 +1438,7 @@ SelectProfile(nsIProfileLock* *aResult, nsINativeAppSupport* aNative, const char *dummy; CheckArg("p", &dummy); CheckArg("profile", &dummy); - CheckArg("profilemanager", &dummy); + CheckArg("profilemanager"); return NS_LockProfilePath(lf, localDir, nsnull, aResult); } @@ -1906,13 +1885,6 @@ XRE_main(int argc, char* argv[], const nsXREAppData* aAppData) int i; for (i = 0; i < argc; ++i) { -#if defined(XP_WIN) - if (strchr(argv[i], ' ')) { - gRestartArgv[i] = NewQuotedString(argv[i]); - if (!gRestartArgv[i]) return 1; - } - else -#endif gRestartArgv[i] = argv[i]; } gRestartArgv[argc] = nsnull; diff --git a/mozilla/toolkit/xre/nsAppRunner.h b/mozilla/toolkit/xre/nsAppRunner.h index 416a6dda51c..d514230b30a 100644 --- a/mozilla/toolkit/xre/nsAppRunner.h +++ b/mozilla/toolkit/xre/nsAppRunner.h @@ -37,7 +37,11 @@ #ifndef nsAppRunner_h__ #define nsAppRunner_h__ - + +#ifdef XP_WIN +#include +#endif + #ifndef MAXPATHLEN #ifdef _MAX_PATH #define MAXPATHLEN _MAX_PATH @@ -110,6 +114,11 @@ NS_LockProfilePath(nsILocalFile* aPath, nsILocalFile* aTempPath, NS_HIDDEN_(void) WriteConsoleLog(); +#ifdef XP_WIN +BOOL +WinLaunchChild(const char *exePath, int argc, char **argv); +#endif + #define NS_NATIVEAPPSUPPORT_CONTRACTID "@mozilla.org/toolkit/native-app-support;1" #endif // nsAppRunner_h__ diff --git a/mozilla/toolkit/xre/nsUpdateDriver.cpp b/mozilla/toolkit/xre/nsUpdateDriver.cpp index cdcd2eb1764..0d35416e961 100644 --- a/mozilla/toolkit/xre/nsUpdateDriver.cpp +++ b/mozilla/toolkit/xre/nsUpdateDriver.cpp @@ -40,6 +40,7 @@ #include #include "nsUpdateDriver.h" #include "nsXULAppAPI.h" +#include "nsAppRunner.h" #include "nsILocalFile.h" #include "nsISimpleEnumerator.h" #include "nsIDirectoryEnumerator.h" @@ -314,20 +315,6 @@ ApplyUpdate(nsIFile *appDir, nsIFile *updateDir, nsILocalFile *statusFile, return; } -#if defined(XP_WIN) - // Avoid paths that contain spaces... - char tempBuf[_MAX_PATH]; - - ::GetShortPathName(updaterPath.get(), tempBuf, sizeof(tempBuf)); - updaterPath = tempBuf; - - ::GetShortPathName(updateDirPath.get(), tempBuf, sizeof(tempBuf)); - updateDirPath = tempBuf; - - ::GetShortPathName(appFilePath.get(), tempBuf, sizeof(tempBuf)); - appFilePath = tempBuf; -#endif - // Construct the PID argument for this process. If we are using execv, then // we pass "0" which is then ignored by the updater. #if defined(USE_EXECV) @@ -363,7 +350,9 @@ ApplyUpdate(nsIFile *appDir, nsIFile *updateDir, nsILocalFile *statusFile, execv(updaterPath.get(), argv); #elif defined(XP_WIN) _chdir(appDirPath.get()); - _spawnv(_P_NOWAIT, updaterPath.get(), argv); + + if (!WinLaunchChild(updaterPath.get(), appArgc + 3, argv)) + return; _exit(0); #else PRStatus status; diff --git a/mozilla/toolkit/xre/nsWindowsRestart.cpp b/mozilla/toolkit/xre/nsWindowsRestart.cpp new file mode 100755 index 00000000000..dd3bd29ba5f --- /dev/null +++ b/mozilla/toolkit/xre/nsWindowsRestart.cpp @@ -0,0 +1,153 @@ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is Mozilla XULRunner bootstrap. + * + * The Initial Developer of the Original Code is + * Benjamin Smedberg . + * + * Portions created by the Initial Developer are Copyright (C) 2005 + * the Mozilla Foundation. 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 ***** */ + +// This file is not build directly. Instead, it is included in multiple +// shared objects. + +#ifdef nsWindowsRestart_cpp +#error "nsWindowsRestart.cpp is not a header file, and must only be included once." +#else +#define nsWindowsRestart_cpp +#endif + +/** + * Get the length that the string will take when it is quoted. + */ +static int QuotedStrLen(const char *s) +{ + int i = 2; // initial and final quote + while (*s) { + if (*s == '"') { + ++i; + } + + ++i; ++s; + } + return i; +} + +/** + * Copy string "s" to string "d", quoting and escaping all double quotes. + * The CRT parses this to retrieve the original argc/argv that we meant, + * see STDARGV.C in the MSVC6 CRT sources. + * + * @return the end of the string + */ +static char* QuoteString(char *d, const char *s) +{ + *d = '"'; + ++d; + + while (*s) { + *d = *s; + if (*s == '"') { + ++d; + *d = '"'; + } + + ++d; ++s; + } + + *d = '"'; + ++d; + + return d; +} + +/** + * Create a quoted command from a list of arguments. The returned string + * is allocated with "malloc" and should be "free"d. + */ +static char* +MakeCommandLine(int argc, char **argv) +{ + int i; + int len = 1; // null-termination + + for (i = 0; i < argc; ++i) + len += QuotedStrLen(argv[i]) + 1; + + char *s = (char*) malloc(len); + if (!s) + return NULL; + + char *c = s; + for (i = 0; i < argc; ++i) { + c = QuoteString(c, argv[i]); + *c = ' '; + ++c; + } + + *c = '\0'; + + return s; +} + +/** + * Launch a child process with the specified arguments. + * @note argv[0] is ignored + */ +BOOL +WinLaunchChild(const char *exePath, int argc, char **argv) +{ + char *cl = MakeCommandLine(argc, argv); + if (!cl) + return FALSE; + + 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); + + free(cl); + + if (ok) { + CloseHandle(pi.hProcess); + CloseHandle(pi.hThread); + } + + return ok; +}