Bug 459615 - Remove the needElevation param from WinLaunchChild. r=ted.mielczarek, r=jmathies
authorRobert Strong <robert.bugzilla@gmail.com>
Thu, 01 Jan 2009 16:18:33 -0800
changeset 23244 40f7e81126a2b03f29457c71f857be8adb0676cd
parent 23243 45f0ebf6eecc1744bc84cffc69d4ea30835994ac
child 23245 a980f7c6189d38e2a68bc59c7eef121c532ff936
push id4409
push userrstrong@mozilla.com
push dateFri, 02 Jan 2009 00:18:58 +0000
treeherdermozilla-central@40f7e81126a2 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersted.mielczarek, jmathies
bugs459615
milestone1.9.2a1pre
Bug 459615 - Remove the needElevation param from WinLaunchChild. r=ted.mielczarek, r=jmathies
toolkit/mozapps/update/src/updater/updater.cpp
toolkit/xre/nsAppRunner.cpp
toolkit/xre/nsAppRunner.h
toolkit/xre/nsUpdateDriver.cpp
toolkit/xre/nsWindowsRestart.cpp
--- a/toolkit/mozapps/update/src/updater/updater.cpp
+++ b/toolkit/mozapps/update/src/updater/updater.cpp
@@ -1088,30 +1088,52 @@ LaunchWinPostProcess(const WCHAR *appExe
   wcscpy(dlogFile, exefullpath);
 
   slash = wcsrchr(dlogFile, '\\');
   wcscpy(slash + 1, L"uninstall.update");
 
   WCHAR slogFile[MAXPATHLEN];
   _snwprintf(slogFile, MAXPATHLEN, L"%s/update.log", gSourcePath);
 
+  WCHAR dummyArg[13];
+  wcscpy(dummyArg, L"argv0ignored ");
+
+  int len = wcslen(exearg) + wcslen(dummyArg);
+  WCHAR *cmdline = (WCHAR *) malloc((len + 1) * sizeof(WCHAR));
+  if (!cmdline)
+    return;
+
+  wcscpy(cmdline, dummyArg);
+  wcscat(cmdline, exearg);
+
   // We want to launch the post update helper app to update the Windows
   // registry even if there is a failure with removing the uninstall.update
   // file or copying the update.log file.
   NS_tremove(dlogFile);
   CopyFile(slogFile, dlogFile, FALSE);
 
-  static int    argc = 2;
-  static WCHAR* argv[3] = {
-    L"argv0ignoredbywinlaunchchild",
-    exearg,
-    L"\0"
-  };
- 
-  WinLaunchChild(exefullpath, argc, argv, 0);
+  STARTUPINFOW si = {sizeof(si), 0};
+  PROCESS_INFORMATION pi = {0};
+
+  BOOL ok = CreateProcessW(exefullpath,
+                           cmdline,
+                           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(cmdline);
+
+  if (ok) {
+    CloseHandle(pi.hProcess);
+    CloseHandle(pi.hThread);
+  }
 }
 #endif
 
 static void
 LaunchCallbackApp(const NS_tchar *workingDir, int argc, NS_tchar **argv)
 {
   putenv("NO_EM_RESTART=");
   putenv("MOZ_LAUNCHED_CHILD=1");
@@ -1119,17 +1141,17 @@ LaunchCallbackApp(const NS_tchar *workin
   // Run from the specified working directory (see bug 312360).
   NS_tchdir(workingDir);
 
 #if defined(USE_EXECV)
   execv(argv[0], argv);
 #elif defined(XP_MACOSX)
   LaunchChild(argc, argv);
 #elif defined(XP_WIN)
-  WinLaunchChild(argv[0], argc, argv, 0);
+  WinLaunchChild(argv[0], argc, argv);
 #else
 # warning "Need implementaton of LaunchCallbackApp"
 #endif
 }
 
 static void
 WriteStatusFile(int status)
 {
--- a/toolkit/xre/nsAppRunner.cpp
+++ b/toolkit/xre/nsAppRunner.cpp
@@ -601,18 +601,16 @@ public:
   NS_DECL_ISUPPORTS_INHERITED
   NS_DECL_NSIXULAPPINFO
   NS_DECL_NSIXULRUNTIME
 #ifdef MOZ_CRASHREPORTER
   NS_DECL_NSICRASHREPORTER
 #endif
 #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)
@@ -726,19 +724,22 @@ nsXULAppInfo::GetXPCOMABI(nsACString& aR
   aResult.AssignLiteral(TARGET_XPCOM_ABI);
   return NS_OK;
 #else
   return NS_ERROR_NOT_AVAILABLE;
 #endif
 }
 
 #ifdef XP_WIN
-nsresult 
-nsXULAppInfo::LaunchAppHelperWithArgs(int aArgc, char **aArgv)
+#include <shellapi.h>
+
+NS_IMETHODIMP
+nsXULAppInfo::PostUpdate(nsILocalFile *aLogFile)
 {
+#ifndef WINCE
   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);
@@ -748,60 +749,53 @@ nsXULAppInfo::LaunchAppHelperWithArgs(in
 
   rv = appHelper->AppendNative(NS_LITERAL_CSTRING("helper.exe"));
   NS_ENSURE_SUCCESS(rv, rv);
 
   nsAutoString appHelperPath;
   rv = appHelper->GetPath(appHelperPath);
   NS_ENSURE_SUCCESS(rv, rv);
 
-  if (!WinLaunchChild(appHelperPath.get(), aArgc, aArgv, 1))
-    return NS_ERROR_FAILURE;
-  else
-    return NS_OK;
-}
-
-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;
+  nsAutoString logFilePath;
+  PRUnichar *dummyArg = L"argv0ignored ";
+  PRUnichar *firstArg = L"/postupdate";
+  PRUnichar *secondArg = L" /uninstalllog=";
+  int len = wcslen(dummyArg) + wcslen(firstArg);
 
   if (aLogFile) {
-    nsCAutoString logFilePath;
-    rv = aLogFile->GetNativePath(logFilePath);
+    rv = aLogFile->GetPath(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;
+    len += wcslen(secondArg);
+    len += wcslen(logFilePath.get());
   }
-  else {
-    upgradeArgv[2] = nsnull;
+
+  PRUnichar *cmdLine = (PRUnichar *) malloc((len + 1) * sizeof(PRUnichar));
+  if (!cmdLine)
+    return NS_ERROR_OUT_OF_MEMORY;
+
+  wcscpy(cmdLine, dummyArg);
+  wcscat(cmdLine, firstArg);
+
+  if (aLogFile) {
+    wcscat(cmdLine, secondArg);
+    wcscat(cmdLine, logFilePath.get());
   }
 
-  rv = LaunchAppHelperWithArgs(upgradeArgc, upgradeArgv);
-  
-  if (pathArg)
-    PR_smprintf_free(pathArg);
-
-  free(upgradeArgv);
-  return rv;
+  BOOL ok = ShellExecuteW(NULL, // no special UI window
+                          NULL, // use default verb
+                          appHelperPath.get(),
+                          cmdLine,
+                          NULL, // use my current directory
+                          SW_SHOWDEFAULT) > (HINSTANCE)32;
+  free(cmdLine);
+
+  return (!ok ? NS_ERROR_FAILURE : NS_OK);
+#else
+  return NS_ERROR_NOT_AVAILABLE;
+#endif
 }
 
 // Matches the enum in WinNT.h for the Vista SDK but renamed so that we can
 // safely build with the Vista SDK and without it.
 typedef enum 
 {
   VistaTokenElevationTypeDefault = 1,
   VistaTokenElevationTypeFull,
@@ -1484,16 +1478,17 @@ XRE_GetBinaryPath(const char* argv0, nsI
   NS_ADDREF(*aResult = lf);
   return NS_OK;
 }
 
 #define NS_ERROR_LAUNCHED_CHILD_PROCESS NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_PROFILE, 200)
 
 #ifdef XP_WIN
 #include "nsWindowsRestart.cpp"
+#include <shellapi.h>
 #endif
 
 #if defined(XP_OS2) && (__KLIBC__ == 0 && __KLIBC_MINOR__ >= 6) // broken kLibc
 // Copy the environment maintained by the C library into an ASCIIZ array
 // that can be used to pass it on to the OS/2 Dos* APIs (which otherwise
 // don't know anything about the stuff set by PR_SetEnv() or setenv()).
 char *createEnv()
 {
@@ -1605,17 +1600,17 @@ static nsresult LaunchChild(nsINativeApp
     return rv;
 
 #if defined(XP_WIN)
   nsAutoString exePath;
   rv = lf->GetPath(exePath);
   if (NS_FAILED(rv))
     return rv;
 
-  if (!WinLaunchChild(exePath.get(), gRestartArgc, gRestartArgv, 0))
+  if (!WinLaunchChild(exePath.get(), gRestartArgc, gRestartArgv))
     return NS_ERROR_FAILURE;
 
 #else
   nsCAutoString exePath;
   rv = lf->GetNativePath(exePath);
   if (NS_FAILED(rv))
     return rv;
 
--- a/toolkit/xre/nsAppRunner.h
+++ b/toolkit/xre/nsAppRunner.h
@@ -132,17 +132,17 @@ NS_HIDDEN_(nsresult)
 NS_LockProfilePath(nsILocalFile* aPath, nsILocalFile* aTempPath,
                    nsIProfileUnlocker* *aUnlocker, nsIProfileLock* *aResult);
 
 NS_HIDDEN_(void)
 WriteConsoleLog();
 
 #ifdef XP_WIN
 BOOL
-WinLaunchChild(const PRUnichar *exePath, int argc, char **argv, int needElevation);
+WinLaunchChild(const PRUnichar *exePath, int argc, char **argv);
 #endif
 
 #define NS_NATIVEAPPSUPPORT_CONTRACTID "@mozilla.org/toolkit/native-app-support;1"
 
 // Like nsXREAppData, but releases all strong refs/allocated memory
 // in the destructor.
 class ScopedAppData : public nsXREAppData
 {
--- a/toolkit/xre/nsUpdateDriver.cpp
+++ b/toolkit/xre/nsUpdateDriver.cpp
@@ -508,17 +508,17 @@ ApplyUpdate(nsIFile *greDir, nsIFile *up
   LOG(("spawning updater process [%s]\n", updaterPath.get()));
 
 #if defined(USE_EXECV)
   chdir(applyToDir.get());
   execv(updaterPath.get(), argv);
 #elif defined(XP_WIN)
   _wchdir(applyToDir.get());
 
-  if (!WinLaunchChild(updaterPathW.get(), appArgc + 4, argv, 0))
+  if (!WinLaunchChild(updaterPathW.get(), appArgc + 4, argv))
     return;
   _exit(0);
 #else
   PRStatus status;
   PRProcessAttr *attr;
   
   attr = PR_NewProcessAttr();
   if (!attr)
--- a/toolkit/xre/nsWindowsRestart.cpp
+++ b/toolkit/xre/nsWindowsRestart.cpp
@@ -190,100 +190,16 @@ MakeCommandLine(int argc, PRUnichar **ar
   }
 
   *c = '\0';
 
   return s;
 }
 
 /**
- * Launch a child process without elevated privilege.
- */
-static BOOL
-LaunchAsNormalUser(const PRUnichar *exePath, PRUnichar *cl)
-{
-#ifdef WINCE
-  return PR_FALSE;
-#else
-  if (!pCreateProcessWithTokenW) {
-    // IsUserAnAdmin is not present on Win9x and not exported by name on Win2k
-    *(FARPROC *)&pIsUserAnAdmin =
-        GetProcAddress(GetModuleHandleA("shell32.dll"), "IsUserAnAdmin");
-
-    // CreateProcessWithTokenW is not present on WinXP or earlier
-    *(FARPROC *)&pCreateProcessWithTokenW =
-        GetProcAddress(GetModuleHandleA("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 = FindWindowA("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};
-
-  // When launching with reduced privileges, environment inheritance
-  // (passing NULL as lpEnvironment) doesn't work correctly. Pass our
-  // current environment block explicitly
-  WCHAR* myenv = GetEnvironmentStringsW();
-
-  ok = pCreateProcessWithTokenW(hNewToken,
-                                0,    // profile is already loaded
-                                exePath,
-                                cl,
-                                CREATE_UNICODE_ENVIRONMENT,
-                                myenv, // inherit my environment
-                                NULL, // use my current directory
-                                &si,
-                                &pi);
-
-  if (myenv)
-    FreeEnvironmentStringsW(myenv);
-
-  CloseHandle(hNewToken);
-  if (!ok)
-    return FALSE;
-
-  CloseHandle(pi.hProcess);
-  CloseHandle(pi.hThread);
-
-  return TRUE;
-#endif
-}
-/**
  * Convert UTF8 to UTF16 without using the normal XPCOM goop, which we
  * can't link to updater.exe.
  */
 static PRUnichar*
 AllocConvertUTF8toUTF16(const char *arg)
 {
   // UTF16 can't be longer in units than UTF8
   int len = strlen(arg);
@@ -305,91 +221,66 @@ FreeAllocStrings(int argc, PRUnichar **a
     delete [] argv[argc];
   }
 
   delete [] argv;
 }
 
 /**
  * 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
  * @note The form of this function that takes char **argv expects UTF-8
  */
 
 BOOL
-WinLaunchChild(const PRUnichar *exePath, int argc, PRUnichar **argv, int needElevation);
+WinLaunchChild(const PRUnichar *exePath, int argc, PRUnichar **argv);
 
 BOOL
-WinLaunchChild(const PRUnichar *exePath, int argc, char **argv, int needElevation)
+WinLaunchChild(const PRUnichar *exePath, int argc, char **argv)
 {
   PRUnichar** argvConverted = new PRUnichar*[argc];
   if (!argvConverted)
     return FALSE;
 
   for (int i = 0; i < argc; ++i) {
     argvConverted[i] = AllocConvertUTF8toUTF16(argv[i]);
     if (!argvConverted[i]) {
       return FALSE;
     }
   }
 
-  BOOL ok = WinLaunchChild(exePath, argc, argvConverted, needElevation);
+  BOOL ok = WinLaunchChild(exePath, argc, argvConverted);
   FreeAllocStrings(argc, argvConverted);
   return ok;
 }
 
 BOOL
-WinLaunchChild(const PRUnichar *exePath, int argc, PRUnichar **argv, int needElevation)
+WinLaunchChild(const PRUnichar *exePath, int argc, PRUnichar **argv)
 {
   PRUnichar *cl;
   BOOL ok;
-#ifndef WINCE
-  if (needElevation > 0) {
-    cl = MakeCommandLine(argc - 1, argv + 1);
-    if (!cl)
-      return FALSE;
-    ok = ShellExecuteW(NULL, // no special UI window
-                       NULL, // use default verb
-                       exePath,
-                       cl,
-                       NULL, // use my current directory
-                       SW_SHOWDEFAULT) > (HINSTANCE)32;
-    free(cl);
-    return ok;
-  }
-#endif
   cl = MakeCommandLine(argc, argv);
   if (!cl)
     return FALSE;
 
-  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) {
-    STARTUPINFOW si = {sizeof(si), 0};
-    PROCESS_INFORMATION pi = {0};
+  STARTUPINFOW si = {sizeof(si), 0};
+  PROCESS_INFORMATION pi = {0};
 
-    ok = CreateProcessW(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 = CreateProcessW(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);
-    }
+  if (ok) {
+    CloseHandle(pi.hProcess);
+    CloseHandle(pi.hThread);
   }
 
   free(cl);
 
   return ok;
 }