BOOL
WinLaunchChild(const PRUnichar *exePath, int argc, char **argv, int needElevation)
{
  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);
  FreeAllocStrings(argc, argvConverted);
  return ok;
}
Beispiel #2
0
static void
LaunchApp(const NS_tchar *workingDir, int argc, NS_tchar **argv)
{
  putenv("NO_EM_RESTART=");
  putenv("MOZ_LAUNCHED_CHILD=1");

  // 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);
#else
# warning "Need implementaton of LaunchCallbackApp"
#endif
}
BOOL
WinLaunchChild(const wchar_t *exePath,
               int argc, char **argv,
               HANDLE userToken,
               HANDLE *hProcess)
{
  wchar_t** argvConverted = new wchar_t*[argc];
  if (!argvConverted)
    return FALSE;

  for (int i = 0; i < argc; ++i) {
      argvConverted[i] = reinterpret_cast<wchar_t*>(AllocConvertUTF8toUTF16(argv[i]));
    if (!argvConverted[i]) {
      FreeAllocStrings(i, argvConverted);
      return FALSE;
    }
  }

  BOOL ok = WinLaunchChild(exePath, argc, argvConverted, userToken, hProcess);
  FreeAllocStrings(argc, argvConverted);
  return ok;
}
Beispiel #4
0
static void
ApplyUpdate(nsIFile *greDir, nsIFile *updateDir, nsILocalFile *statusFile,
            nsIFile *appDir, int appArgc, char **appArgv)
{
    nsresult rv;

    // Steps:
    //  - mark update as 'applying'
    //  - copy updater into update dir
    //  - run updater w/ appDir as the current working dir

    nsCOMPtr<nsIFile> updater;
    if (!CopyUpdaterIntoUpdateDir(greDir, appDir, updateDir, updater)) {
        LOG(("failed copying updater\n"));
        return;
    }

    // We need to use the value returned from XRE_GetBinaryPath when attempting
    // to restart the running application.
    nsCOMPtr<nsILocalFile> appFile;

#if defined(XP_MACOSX)
    // On OS X we need to pass the location of the xulrunner-stub executable
    // rather than xulrunner-bin. See bug 349737.
    GetXULRunnerStubPath(appArgv[0], getter_AddRefs(appFile));
#else
    XRE_GetBinaryPath(appArgv[0], getter_AddRefs(appFile));
#endif

    if (!appFile)
        return;

#ifdef XP_WIN
    nsAutoString appFilePathW;
    rv = appFile->GetPath(appFilePathW);
    if (NS_FAILED(rv))
        return;
    NS_ConvertUTF16toUTF8 appFilePath(appFilePathW);

    nsAutoString updaterPathW;
    rv = updater->GetPath(updaterPathW);
    if (NS_FAILED(rv))
        return;

    NS_ConvertUTF16toUTF8 updaterPath(updaterPathW);

#else
    nsCAutoString appFilePath;
    rv = appFile->GetNativePath(appFilePath);
    if (NS_FAILED(rv))
        return;

    nsCAutoString updaterPath;
    rv = updater->GetNativePath(updaterPath);
    if (NS_FAILED(rv))
        return;

#endif

    // Get the directory to which the update will be applied. On Mac OSX we need
    // to apply the update to the Foo.app directory which is the parent of the
    // parent of the appDir. On other platforms we will just apply to the appDir.
#if defined(XP_MACOSX)
    nsCAutoString applyToDir;
    {
        nsCOMPtr<nsIFile> parentDir1, parentDir2;
        rv = appDir->GetParent(getter_AddRefs(parentDir1));
        if (NS_FAILED(rv))
            return;
        rv = parentDir1->GetParent(getter_AddRefs(parentDir2));
        if (NS_FAILED(rv))
            return;
        rv = parentDir2->GetNativePath(applyToDir);
    }
#elif defined(XP_WIN)
    nsAutoString applyToDir;
    rv = appDir->GetPath(applyToDir);
#else
    nsCAutoString applyToDir;
    rv = appDir->GetNativePath(applyToDir);
#endif
    if (NS_FAILED(rv))
        return;

#if defined(XP_WIN)
    nsAutoString updateDirPathW;
    rv = updateDir->GetPath(updateDirPathW);

    NS_ConvertUTF16toUTF8 updateDirPath(updateDirPathW);
#else
    nsCAutoString updateDirPath;
    rv = updateDir->GetNativePath(updateDirPath);
#endif

    if (NS_FAILED(rv))
        return;

    // Get the current working directory.
    char workingDirPath[MAXPATHLEN];
    rv = GetCurrentWorkingDir(workingDirPath, sizeof(workingDirPath));
    if (NS_FAILED(rv))
        return;

    if (!SetStatus(statusFile, "applying")) {
        LOG(("failed setting status to 'applying'\n"));
        return;
    }

    // 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)
    NS_NAMED_LITERAL_CSTRING(pid, "0");
#else
    nsCAutoString pid;
    pid.AppendInt((PRInt32) getpid());
#endif

    int argc = appArgc + 4;
    char **argv = new char*[argc + 1];
    if (!argv)
        return;
    argv[0] = (char*) updaterPath.get();
    argv[1] = (char*) updateDirPath.get();
    argv[2] = (char*) pid.get();
    if (appArgc) {
        argv[3] = workingDirPath;
        argv[4] = (char*) appFilePath.get();
        for (int i = 1; i < appArgc; ++i)
            argv[4 + i] = appArgv[i];
        argv[4 + appArgc] = nsnull;
    } else {
        argv[3] = nsnull;
        argc = 3;
    }

    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))
        return;
    _exit(0);
#else
    PRStatus status;
    PRProcessAttr *attr;

    attr = PR_NewProcessAttr();
    if (!attr)
        goto end;

    status = PR_ProcessAttrSetCurrentDirectory(attr, applyToDir.get());
    if (status != PR_SUCCESS)
        goto end;

#ifdef XP_MACOSX
    CommandLineServiceMac::SetupMacCommandLine(argc, argv, PR_TRUE);
#endif

    PR_CreateProcessDetached(updaterPath.get(), argv, nsnull, attr);
    exit(0);

end:
    PR_DestroyProcessAttr(attr);
    delete[] argv;
#endif
}