Exemplo n.º 1
0
int MSHelp2(const char *Keyword, const char *FileName, char *Error)
{
  char CommandLine[2048];
  if (Keyword)
    MakeCommandLine(CommandLine,PathToViewer,KeywordSearch,FileName,Keyword);
  else
    MakeCommandLine(CommandLine,PathToViewer,OpenContents,FileName,Keyword);
  STARTUPINFO si={0};
  si.cb=sizeof(si);
  PROCESS_INFORMATION pi;
  int ret = CreateProcess(NULL,CommandLine,NULL,NULL,TRUE,0,NULL,NULL,&si,&pi);
  if (!ret)
  {
    LPSTR MessageBuffer;
    DWORD dwFormatFlags = FORMAT_MESSAGE_ALLOCATE_BUFFER|FORMAT_MESSAGE_IGNORE_INSERTS|FORMAT_MESSAGE_FROM_SYSTEM;
    DWORD dwBufferLength = FormatMessageA(dwFormatFlags,NULL,GetLastError(),MAKELANGID(LANG_NEUTRAL,SUBLANG_DEFAULT),(LPSTR)&MessageBuffer,0,NULL);
    lstrcpyn(Error,MessageBuffer,dwBufferLength>128?128:dwBufferLength);
    CharToOem(Error,Error);
  }
  else
  {
    CloseHandle(pi.hProcess);
    CloseHandle(pi.hThread);
  }
  return ret;
}
BOOL
WinLaunchChild(const PRUnichar *exePath, int argc, PRUnichar **argv, int needElevation)
{
  PRUnichar *cl;
  BOOL ok;
  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;
  }

  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};

    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);
    }
  }

  free(cl);

  return ok;
}
Exemplo n.º 3
0
int ExternalFilter(const char *Command, const char *Keyword, const char *Output, char *Error)
{
  char CommandLine[2048];
  lstrcpy(CommandLine,"%COMSPEC% /C ");
  FSF.ExpandEnvironmentStr(CommandLine,CommandLine,sizeof(CommandLine));
  MakeCommandLine(CommandLine+lstrlen(CommandLine),Command,Keyword,Output);
  STARTUPINFO si={0};
  si.cb=sizeof(si);
  PROCESS_INFORMATION pi;
  int ret = CreateProcess(NULL,CommandLine,NULL,NULL,TRUE,0,NULL,NULL,&si,&pi);
  if (!ret)
  {
    LPSTR MessageBuffer;
    DWORD dwFormatFlags = FORMAT_MESSAGE_ALLOCATE_BUFFER|FORMAT_MESSAGE_IGNORE_INSERTS|FORMAT_MESSAGE_FROM_SYSTEM;
    DWORD dwBufferLength = FormatMessageA(dwFormatFlags,NULL,GetLastError(),MAKELANGID(LANG_NEUTRAL,SUBLANG_DEFAULT),(LPSTR)&MessageBuffer,0,NULL);
    lstrcpyn(Error,MessageBuffer,dwBufferLength>128?128:dwBufferLength);
    CharToOem(Error,Error);
  }
  else
  {
    WaitForSingleObject(pi.hProcess,INFINITE);
    CloseHandle(pi.hProcess);
    CloseHandle(pi.hThread);
  }
  return ret;
}
CXTranslationUnit ClangWorkerThread::DoCreateTU(CXIndex index, ClangThreadRequest* task, bool reparse)
{
    wxFileName fn(task->GetFileName());
    DoSetStatusMsg(wxString::Format(wxT("clang: parsing file %s..."), fn.GetFullName().c_str()));

    FileExtManager::FileType type = FileExtManager::GetType(task->GetFileName());
    int argc(0);
    char** argv = MakeCommandLine(task, argc, type);

    for(int i = 0; i < argc; i++) {
        CL_DEBUG(wxT("Command Line Argument: %s"), wxString(argv[i], wxConvUTF8).c_str());
    }

    std::string c_filename = task->GetFileName().mb_str(wxConvUTF8).data();
    CL_DEBUG(wxT("Calling clang_parseTranslationUnit..."));

    // First time, need to create it
    unsigned flags;
    if(reparse) {
        flags = CXTranslationUnit_CacheCompletionResults | CXTranslationUnit_PrecompiledPreamble |
                CXTranslationUnit_Incomplete | CXTranslationUnit_DetailedPreprocessingRecord |
                CXTranslationUnit_CXXChainedPCH;
    } else {
        flags = CXTranslationUnit_Incomplete | 
#if HAS_LIBCLANG_BRIEFCOMMENTS
		CXTranslationUnit_SkipFunctionBodies |
#endif
                CXTranslationUnit_DetailedPreprocessingRecord;
    }

    CXTranslationUnit TU = clang_parseTranslationUnit(index, c_filename.c_str(), argv, argc, NULL, 0, flags);

    CL_DEBUG(wxT("Calling clang_parseTranslationUnit... done"));
    ClangUtils::FreeArgv(argv, argc);
    DoSetStatusMsg(wxString::Format(wxT("clang: parsing file %s...done"), fn.GetFullName().c_str()));
    if(TU && reparse) {
        CL_DEBUG(wxT("Calling clang_reparseTranslationUnit..."));
        if(clang_reparseTranslationUnit(TU, 0, NULL, clang_defaultReparseOptions(TU)) == 0) {
            CL_DEBUG(wxT("Calling clang_reparseTranslationUnit... done"));
            return TU;

        } else {
            CL_DEBUG(wxT("An error occured during reparsing of the TU for file %s. TU: %p"),
                     task->GetFileName().c_str(),
                     (void*)TU);

            // The only thing that left to be done here, is to dispose the TU
            clang_disposeTranslationUnit(TU);
            PostEvent(wxEVT_CLANG_TU_CREATE_ERROR, task->GetFileName());
            return NULL;
        }
    }
    return TU;
}
Exemplo n.º 5
0
static int ProgramMode(int adx, int argc, FChS * argv[])
{
    FAssert(adx < argc);

    FObject nam = MakeStringS(argv[adx]);

    adx += 1;
    R.CommandLine = MakePair(MakeInvocation(adx, argv), MakeCommandLine(argc - adx, argv + adx));

    FObject port;
    {
        FDontWait dw;

        port = OpenInputFile(nam);
        if (TextualPortP(port) == 0)
        {
#ifdef FOMENT_WINDOWS
            printf("error: unable to open program: %S\n", argv[adx - 1]);
#endif // FOMENT_WINDOWS

#ifdef FOMENT_UNIX
            printf("error: unable to open program: %s\n", argv[adx - 1]);
#endif // FOMENT_UNIX
            return(Usage());
        }
    }

    FCh ch;

    // Skip #!/usr/local/bin/foment

    if (PeekCh(port, &ch) && ch == '#')
        ReadLine(port);

    FObject proc = CompileProgram(nam, port);

    ExecuteThunk(proc);
    ExitFoment();
    return(0);
}
Exemplo n.º 6
0
/**
 * Runs an update process as the service using the SYSTEM account.
 *
 * @param  argc           The number of arguments in argv
 * @param  argv           The arguments normally passed to updater.exe
 *                        argv[0] must be the path to updater.exe
 * @param  processStarted Set to TRUE if the process was started.
 * @return TRUE if the update process was run had a return code of 0.
 */
BOOL
StartUpdateProcess(int argc,
                   LPWSTR *argv,
                   BOOL &processStarted)
{
  LOG(("Starting update process as the service in session 0.\n"));
  STARTUPINFO si = {0};
  si.cb = sizeof(STARTUPINFO);
  si.lpDesktop = L"winsta0\\Default";
  PROCESS_INFORMATION pi = {0};

  // The updater command line is of the form:
  // updater.exe update-dir apply [wait-pid [callback-dir callback-path args]]
  LPWSTR cmdLine = MakeCommandLine(argc, argv);

  // If we're about to start the update process from session 0,
  // then we should not show a GUI.  This only really needs to be done
  // on Vista and higher, but it's better to keep everything consistent
  // across all OS if it's of no harm.
  if (argc >= 2 ) {
    // Setting the desktop to blank will ensure no GUI is displayed
    si.lpDesktop = L"";
    si.dwFlags |= STARTF_USESHOWWINDOW;
    si.wShowWindow = SW_HIDE;
  }

  // We move the updater.ini file out of the way because we will handle 
  // executing PostUpdate through the service.  We handle PostUpdate from
  // the service because there are some per user things that happen that
  // can't run in session 0 which we run updater.exe in.
  // Once we are done running updater.exe we rename updater.ini back so
  // that if there were any errors the next updater.exe will run correctly.
  WCHAR updaterINI[MAX_PATH + 1];
  WCHAR updaterINITemp[MAX_PATH + 1];
  BOOL selfHandlePostUpdate = FALSE;
  // We use the updater.ini from the same directory as the updater.exe
  // because of background updates.
  if (PathGetSiblingFilePath(updaterINI, argv[0], L"updater.ini") &&
      PathGetSiblingFilePath(updaterINITemp, argv[0], L"updater.tmp")) {
    selfHandlePostUpdate = MoveFileExW(updaterINI, updaterINITemp, 
                                       MOVEFILE_REPLACE_EXISTING);
  }

  // Add an env var for MOZ_USING_SERVICE so the updater.exe can
  // do anything special that it needs to do for service updates.
  // Search in updater.cpp for more info on MOZ_USING_SERVICE.
  putenv(const_cast<char*>("MOZ_USING_SERVICE=1"));
  LOG(("Starting service with cmdline: %ls\n", cmdLine));
  processStarted = CreateProcessW(argv[0], cmdLine, 
                                  NULL, NULL, FALSE, 
                                  CREATE_DEFAULT_ERROR_MODE, 
                                  NULL, 
                                  NULL, &si, &pi);
  // Empty value on putenv is how you remove an env variable in Windows
  putenv(const_cast<char*>("MOZ_USING_SERVICE="));
  
  BOOL updateWasSuccessful = FALSE;
  if (processStarted) {
    // Wait for the updater process to finish
    LOG(("Process was started... waiting on result.\n")); 
    DWORD waitRes = WaitForSingleObject(pi.hProcess, TIME_TO_WAIT_ON_UPDATER);
    if (WAIT_TIMEOUT == waitRes) {
      // We waited a long period of time for updater.exe and it never finished
      // so kill it.
      TerminateProcess(pi.hProcess, 1);
    } else {
      // Check the return code of updater.exe to make sure we get 0
      DWORD returnCode;
      if (GetExitCodeProcess(pi.hProcess, &returnCode)) {
        LOG(("Process finished with return code %d.\n", returnCode)); 
        // updater returns 0 if successful.
        updateWasSuccessful = (returnCode == 0);
      } else {
        LOG(("Process finished but could not obtain return code.\n")); 
      }
    }
    CloseHandle(pi.hProcess);
    CloseHandle(pi.hThread);

    // Check just in case updater.exe didn't change the status from
    // applying.  If this is the case we report an error.
    BOOL isApplying = FALSE;
    if (IsStatusApplying(argv[1], isApplying) && isApplying) {
      if (updateWasSuccessful) {
        LOG(("update.status is still applying even know update "
             " was successful.\n"));
        if (!WriteStatusFailure(argv[1], 
                                SERVICE_STILL_APPLYING_ON_SUCCESS)) {
          LOG(("Could not write update.status still applying on"
               " success error.\n"));
        }
        // Since we still had applying we know updater.exe didn't do its
        // job correctly.
        updateWasSuccessful = FALSE;
      } else {
        LOG(("update.status is still applying and update was not successful.\n"));
        if (!WriteStatusFailure(argv[1], 
                                SERVICE_STILL_APPLYING_ON_FAILURE)) {
          LOG(("Could not write update.status still applying on"
               " success error.\n"));
        }
      }
    }
  } else {
    DWORD lastError = GetLastError();
    LOG(("Could not create process as current user, "
         "updaterPath: %ls; cmdLine: %l.  (%d)\n", 
         argv[0], cmdLine, lastError));
  }

  // Now that we're done with the update, restore back the updater.ini file
  // We use it ourselves, and also we want it back in case we had any type 
  // of error so that the normal update process can use it.
  if (selfHandlePostUpdate) {
    MoveFileExW(updaterINITemp, updaterINI, MOVEFILE_REPLACE_EXISTING);

    // Only run the PostUpdate if the update was successful
    if (updateWasSuccessful && argc > 2) {
      LPCWSTR installationDir = argv[2];
      LPCWSTR updateInfoDir = argv[1];

      // Launch the PostProcess with admin access in session 0.  This is
      // actually launching the post update process but it takes in the 
      // callback app path to figure out where to apply to.
      // The PostUpdate process with user only access will be done inside
      // the unelevated updater.exe after the update process is complete
      // from the service.  We don't know here which session to start
      // the user PostUpdate process from.
      LOG(("Launching post update process as the service in session 0.\n"));
      if (!LaunchWinPostProcess(installationDir, updateInfoDir, true, NULL)) {
        LOG(("The post update process could not be launched.\n"));
      }
    }
  }

  free(cmdLine);
  return updateWasSuccessful;
}
Exemplo n.º 7
0
BOOL
WinLaunchChild(const wchar_t *exePath,
               int argc,
               wchar_t **argv,
               HANDLE userToken,
               HANDLE *hProcess)
{
  wchar_t *cl;
  BOOL ok;

  cl = MakeCommandLine(argc, argv);
  if (!cl) {
    return FALSE;
  }

  STARTUPINFOW si = {0};
  si.cb = sizeof(STARTUPINFOW);
  si.lpDesktop = L"winsta0\\Default";
  PROCESS_INFORMATION pi = {0};

  if (userToken == nullptr) {
    ok = CreateProcessW(exePath,
                        cl,
                        nullptr,  // no special security attributes
                        nullptr,  // no special thread attributes
                        FALSE, // don't inherit filehandles
                        0,     // creation flags
                        nullptr,  // inherit my environment
                        nullptr,  // use my current directory
                        &si,
                        &pi);
  } else {
    // Create an environment block for the process we're about to start using
    // the user's token.
    LPVOID environmentBlock = nullptr;
    if (!CreateEnvironmentBlock(&environmentBlock, userToken, TRUE)) {
      environmentBlock = nullptr;
    }

    ok = CreateProcessAsUserW(userToken,
                              exePath,
                              cl,
                              nullptr,  // no special security attributes
                              nullptr,  // no special thread attributes
                              FALSE,    // don't inherit filehandles
                              0,        // creation flags
                              environmentBlock,
                              nullptr,  // use my current directory
                              &si,
                              &pi);

    if (environmentBlock) {
      DestroyEnvironmentBlock(environmentBlock);
    }
  }

  if (ok) {
    if (hProcess) {
      *hProcess = pi.hProcess; // the caller now owns the HANDLE
    } else {
      CloseHandle(pi.hProcess);
    }
    CloseHandle(pi.hThread);
  } else {
    LPVOID lpMsgBuf = nullptr;
    FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER |
                  FORMAT_MESSAGE_FROM_SYSTEM |
                  FORMAT_MESSAGE_IGNORE_INSERTS,
                  nullptr,
                  GetLastError(),
                  MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
                  (LPTSTR) &lpMsgBuf,
                  0,
                  nullptr);
    wprintf(L"Error restarting: %s\n", lpMsgBuf ? static_cast<const wchar_t*>(lpMsgBuf) : L"(null)");
    if (lpMsgBuf)
      LocalFree(lpMsgBuf);
  }

  free(cl);

  return ok;
}
Exemplo n.º 8
0
int main(int argc, char * argv[])
#endif // FOMENT_UNIX
{
    int_t pdx = 0;
    int adx = 1;
    while (adx < argc)
    {
        if (StringCompareS(argv[adx], "-A") == 0)
            adx += 2;
        else if (StringCompareS(argv[adx], "-I") == 0)
            adx += 2;
        else if (StringCompareS(argv[adx], "-X") == 0)
            adx += 2;
        else if (argv[adx][0] != '-')
        {
            pdx = adx;
            break;
        }
        else if (StringCompareS(argv[adx], "-no-inline-procedures") == 0)
        {
            InlineProcedures = 0;
            adx += 1;
        }
        else if (StringCompareS(argv[adx], "-no-inline-imports") == 0)
        {
            InlineImports = 0;
            adx += 1;
        }
        else if (StringCompareS(argv[adx], "--validate-heap") == 0)
        {
            ValidateHeap = 1;
            adx += 1;
        }
#ifdef FOMENT_WINDOWS
        else if (StringCompareS(argv[adx], "--section-table") == 0)
        {
            adx += 1;

            if (adx < argc)
            {
#ifdef FOMENT_32BIT
                SectionTableBase = (void *) wcstol(argv[adx], 0, 16);
#endif // FOMENT_32BIT
#ifdef FOMENT_64BIT
                SectionTableBase = (void *) _wcstoui64(argv[adx], 0, 16);
#endif // FOMENT_64BIT

                adx += 1;
            }
        }
#endif // FOMENT_WINDOWS
        else if (StringCompareS(argv[adx], "--random-seed") == 0)
        {
            adx += 1;

            if (adx < argc)
            {
                RandomSeed = StringToInt(argv[adx]);
                adx += 1;
            }
        }
        else
            break;
    }

    FThreadState ts;

    try
    {
        SetupFoment(&ts);

        if (pdx > 0)
        {
            AddToLibraryPath(argv[pdx]);
        }
    }
    catch (FObject obj)
    {
        printf("Unexpected exception: SetupFoment: %p\n", obj);
        WriteSimple(R.StandardOutput, obj, 0);

        if (ValidateHeap)
        {
            FailedGC();
            FailedExecute();
        }
        return(1);
    }

    FAssert(argc >= 1);

    try
    {
        int adx = 1;
        while (adx < argc)
        {
            if (StringCompareS(argv[adx], "-A") == 0)
            {
                adx += 1;

                if (adx == argc)
                    return(MissingArgument(argv[adx - 1]));

                FObject lp = R.LibraryPath;

                for (;;)
                {
                    FAssert(PairP(lp));

                    if (Rest(lp) == EmptyListObject)
                        break;
                    lp = Rest(lp);
                }

//                AsPair(lp)->Rest = MakePair(MakeStringS(argv[adx]), EmptyListObject);
                SetRest(lp, MakePair(MakeStringS(argv[adx]), EmptyListObject));

                adx += 1;
            }
            else if (StringCompareS(argv[adx], "-I") == 0)
            {
                adx += 1;

                if (adx == argc)
                    return(MissingArgument(argv[adx - 1]));

                R.LibraryPath = MakePair(MakeStringS(argv[adx]), R.LibraryPath);

                adx += 1;
            }
            else if (StringCompareS(argv[adx], "-X") == 0)
            {
                adx += 1;

                if (adx == argc)
                    return(MissingArgument(argv[adx - 1]));

                R.LibraryExtensions = MakePair(MakeStringS(argv[adx]), R.LibraryExtensions);

                adx += 1;
            }
            else if (StringCompareS(argv[adx], "-no-inline-procedures") == 0
                     || StringCompareS(argv[adx], "-no-inline-imports") == 0
                     || StringCompareS(argv[adx], "--validate-heap") == 0)
                adx += 1;
#ifdef FOMENT_WINDOWS
            else if (StringCompareS(argv[adx], "--section-table") == 0)
                adx += 2;
#endif // FOMENT_WINDOWS
            else if (StringCompareS(argv[adx], "--random-seed") == 0)
                adx += 2;
            else if (argv[adx][0] != '-')
                return(ProgramMode(adx, argc, argv));
            else
                break;
        }

        R.LibraryPath = ReverseListModify(MakePair(MakeStringC("."), R.LibraryPath));
        R.CommandLine = MakePair(MakeInvocation(adx, argv),
                                 MakeCommandLine(argc - adx, argv + adx));

        ExecuteThunk(R.InteractiveThunk);
        ExitFoment();
        return(0);
//        return(RunRepl(GetInteractionEnv()));
    }
    catch (FObject obj)
    {
        if (ExceptionP(obj) == 0)
            WriteStringC(R.StandardOutput, "exception: ");
        WriteSimple(R.StandardOutput, obj, 0);
        WriteCh(R.StandardOutput, '\n');

        if (ValidateHeap)
        {
            FailedGC();
            FailedExecute();
        }
        return(-1);
    }
}
Exemplo n.º 9
0
bool
LaunchUnelevated(int aArgc, wchar_t* aArgv[])
{
  // We require a single-threaded apartment to talk to Explorer.
  mscom::STARegion sta;
  if (!sta.IsValid()) {
    return false;
  }

  // NB: Explorer is a local server, not an inproc server
  RefPtr<IShellWindows> shellWindows;
  HRESULT hr = ::CoCreateInstance(CLSID_ShellWindows, nullptr,
                                  CLSCTX_LOCAL_SERVER, IID_IShellWindows,
                                  getter_AddRefs(shellWindows));
  if (FAILED(hr)) {
    return false;
  }

  // 1. Find the shell view for the desktop.
  _variant_t loc(CSIDL_DESKTOP);
  _variant_t empty;
  long hwnd;
  RefPtr<IDispatch> dispDesktop;
  hr = shellWindows->FindWindowSW(&loc, &empty, SWC_DESKTOP, &hwnd,
                                  SWFO_NEEDDISPATCH, getter_AddRefs(dispDesktop));
  if (FAILED(hr)) {
    return false;
  }

  RefPtr<IServiceProvider> servProv;
  hr = dispDesktop->QueryInterface(IID_IServiceProvider, getter_AddRefs(servProv));
  if (FAILED(hr)) {
    return false;
  }

  RefPtr<IShellBrowser> browser;
  hr = servProv->QueryService(SID_STopLevelBrowser, IID_IShellBrowser,
                              getter_AddRefs(browser));
  if (FAILED(hr)) {
    return false;
  }

  RefPtr<IShellView> activeShellView;
  hr = browser->QueryActiveShellView(getter_AddRefs(activeShellView));
  if (FAILED(hr)) {
    return false;
  }

  // 2. Get the automation object for the desktop.
  RefPtr<IDispatch> dispView;
  hr = activeShellView->GetItemObject(SVGIO_BACKGROUND, IID_IDispatch,
                                      getter_AddRefs(dispView));
  if (FAILED(hr)) {
    return false;
  }

  RefPtr<IShellFolderViewDual> folderView;
  hr = dispView->QueryInterface(IID_IShellFolderViewDual,
                                getter_AddRefs(folderView));
  if (FAILED(hr)) {
    return false;
  }

  // 3. Get the interface to IShellDispatch2
  RefPtr<IDispatch> dispShell;
  hr = folderView->get_Application(getter_AddRefs(dispShell));
  if (FAILED(hr)) {
    return false;
  }

  RefPtr<IShellDispatch2> shellDisp;
  hr = dispShell->QueryInterface(IID_IShellDispatch2, getter_AddRefs(shellDisp));
  if (FAILED(hr)) {
    return false;
  }

  // 4. Now call IShellDispatch2::ShellExecute to ask Explorer to re-launch us.

  // Omit argv[0] because ShellExecute doesn't need it in params
  UniquePtr<wchar_t[]> cmdLine(MakeCommandLine(aArgc - 1, aArgv + 1));
  if (!cmdLine) {
    return false;
  }

  _bstr_t exe(aArgv[0]);
  _variant_t args(cmdLine.get());
  _variant_t operation(L"open");
  _variant_t directory;
  _variant_t showCmd(SW_SHOWNORMAL);
  hr = shellDisp->ShellExecute(exe, args, operation, directory, showCmd);
  return SUCCEEDED(hr);
}
Exemplo n.º 10
0
int
LauncherMain(int argc, wchar_t* argv[])
{
  // Make sure that the launcher process itself has image load policies set
  if (IsWin10AnniversaryUpdateOrLater()) {
    const DynamicallyLinkedFunctionPtr<decltype(&SetProcessMitigationPolicy)>
      pSetProcessMitigationPolicy(L"kernel32.dll", "SetProcessMitigationPolicy");
    if (pSetProcessMitigationPolicy) {
      PROCESS_MITIGATION_IMAGE_LOAD_POLICY imgLoadPol = {};
      imgLoadPol.PreferSystem32Images = 1;

      DebugOnly<BOOL> setOk = pSetProcessMitigationPolicy(ProcessImageLoadPolicy,
                                                          &imgLoadPol,
                                                          sizeof(imgLoadPol));
      MOZ_ASSERT(setOk);
    }
  }

  if (!SetArgv0ToFullBinaryPath(argv)) {
    ShowError();
    return 1;
  }

  LauncherFlags flags = ProcessCmdLine(argc, argv);

  nsAutoHandle mediumIlToken;
  Maybe<ElevationState> elevationState = GetElevationState(flags, mediumIlToken);
  if (!elevationState) {
    return 1;
  }

  // If we're elevated, we should relaunch ourselves as a normal user.
  // Note that we only call LaunchUnelevated when we don't need to wait for the
  // browser process.
  if (elevationState.value() == ElevationState::eElevated &&
      !(flags & (LauncherFlags::eWaitForBrowser | LauncherFlags::eNoDeelevate)) &&
      !mediumIlToken.get()) {
    return !LaunchUnelevated(argc, argv);
  }

  // Now proceed with setting up the parameters for process creation
  UniquePtr<wchar_t[]> cmdLine(MakeCommandLine(argc, argv));
  if (!cmdLine) {
    return 1;
  }

  const Maybe<bool> isSafeMode = IsSafeModeRequested(argc, argv,
                                                     SafeModeFlag::NoKeyPressCheck);
  if (!isSafeMode) {
    ShowError(ERROR_INVALID_PARAMETER);
    return 1;
  }

  ProcThreadAttributes attrs;
  SetMitigationPolicies(attrs, isSafeMode.value());

  HANDLE stdHandles[] = {
    ::GetStdHandle(STD_INPUT_HANDLE),
    ::GetStdHandle(STD_OUTPUT_HANDLE),
    ::GetStdHandle(STD_ERROR_HANDLE)
  };

  attrs.AddInheritableHandles(stdHandles);

  DWORD creationFlags = CREATE_SUSPENDED | CREATE_UNICODE_ENVIRONMENT;

  STARTUPINFOEXW siex;
  Maybe<bool> attrsOk = attrs.AssignTo(siex);
  if (!attrsOk) {
    ShowError();
    return 1;
  }

  BOOL inheritHandles = FALSE;

  if (attrsOk.value()) {
    creationFlags |= EXTENDED_STARTUPINFO_PRESENT;

    if (attrs.HasInheritableHandles()) {
      siex.StartupInfo.dwFlags |= STARTF_USESTDHANDLES;
      siex.StartupInfo.hStdInput = stdHandles[0];
      siex.StartupInfo.hStdOutput = stdHandles[1];
      siex.StartupInfo.hStdError = stdHandles[2];

      // Since attrsOk == true, we have successfully set the handle inheritance
      // whitelist policy, so only the handles added to attrs will be inherited.
      inheritHandles = TRUE;
    }
  }

  PROCESS_INFORMATION pi = {};
  BOOL createOk;

  if (mediumIlToken.get()) {
    createOk = ::CreateProcessAsUserW(mediumIlToken.get(), argv[0], cmdLine.get(),
                                      nullptr, nullptr, inheritHandles,
                                      creationFlags, nullptr, nullptr,
                                      &siex.StartupInfo, &pi);
  } else {
    createOk = ::CreateProcessW(argv[0], cmdLine.get(), nullptr, nullptr,
                                inheritHandles, creationFlags, nullptr, nullptr,
                                &siex.StartupInfo, &pi);
  }

  if (!createOk) {
    ShowError();
    return 1;
  }

  nsAutoHandle process(pi.hProcess);
  nsAutoHandle mainThread(pi.hThread);

  if (!PostCreationSetup(process.get(), mainThread.get(), isSafeMode.value()) ||
      ::ResumeThread(mainThread.get()) == static_cast<DWORD>(-1)) {
    ShowError();
    ::TerminateProcess(process.get(), 1);
    return 1;
  }

  if (flags & LauncherFlags::eWaitForBrowser) {
    DWORD exitCode;
    if (::WaitForSingleObject(process.get(), INFINITE) == WAIT_OBJECT_0 &&
        ::GetExitCodeProcess(process.get(), &exitCode)) {
      // Propagate the browser process's exit code as our exit code.
      return static_cast<int>(exitCode);
    }
  } else {
    const DWORD timeout = ::IsDebuggerPresent() ? INFINITE :
                          kWaitForInputIdleTimeoutMS;

    // Keep the current process around until the callback process has created
    // its message queue, to avoid the launched process's windows being forced
    // into the background.
    mozilla::WaitForInputIdle(process.get(), timeout);
  }

  return 0;
}
Exemplo n.º 11
0
/**
 * Runs an update process as the service using the SYSTEM account.
 *
 * @param  argc           The number of arguments in argv
 * @param  argv           The arguments normally passed to updater.exe
 *                        argv[0] must be the path to updater.exe
 * @param  processStarted Set to TRUE if the process was started.
 * @return TRUE if the update process was run had a return code of 0.
 */
BOOL
StartUpdateProcess(int argc,
                   LPWSTR *argv,
                   LPCWSTR installDir,
                   BOOL &processStarted)
{
  LOG(("Starting update process as the service in session 0."));
  STARTUPINFO si = {0};
  si.cb = sizeof(STARTUPINFO);
  si.lpDesktop = L"winsta0\\Default";
  PROCESS_INFORMATION pi = {0};

  // The updater command line is of the form:
  // updater.exe update-dir apply [wait-pid [callback-dir callback-path args]]
  LPWSTR cmdLine = MakeCommandLine(argc, argv);

  int index = 3;
  if (IsOldCommandline(argc, argv)) {
    index = 2;
  }

  // If we're about to start the update process from session 0,
  // then we should not show a GUI.  This only really needs to be done
  // on Vista and higher, but it's better to keep everything consistent
  // across all OS if it's of no harm.
  if (argc >= index) {
    // Setting the desktop to blank will ensure no GUI is displayed
    si.lpDesktop = L"";
    si.dwFlags |= STARTF_USESHOWWINDOW;
    si.wShowWindow = SW_HIDE;
  }

  // Add an env var for MOZ_USING_SERVICE so the updater.exe can
  // do anything special that it needs to do for service updates.
  // Search in updater.cpp for more info on MOZ_USING_SERVICE.
  putenv(const_cast<char*>("MOZ_USING_SERVICE=1"));
  LOG(("Starting service with cmdline: %ls", cmdLine));
  processStarted = CreateProcessW(argv[0], cmdLine,
                                  nullptr, nullptr, FALSE,
                                  CREATE_DEFAULT_ERROR_MODE,
                                  nullptr,
                                  nullptr, &si, &pi);

  BOOL updateWasSuccessful = FALSE;
  if (processStarted) {
    // Wait for the updater process to finish
    LOG(("Process was started... waiting on result."));
    DWORD waitRes = WaitForSingleObject(pi.hProcess, TIME_TO_WAIT_ON_UPDATER);
    if (WAIT_TIMEOUT == waitRes) {
      // We waited a long period of time for updater.exe and it never finished
      // so kill it.
      TerminateProcess(pi.hProcess, 1);
    } else {
      // Check the return code of updater.exe to make sure we get 0
      DWORD returnCode;
      if (GetExitCodeProcess(pi.hProcess, &returnCode)) {
        LOG(("Process finished with return code %d.", returnCode));
        // updater returns 0 if successful.
        updateWasSuccessful = (returnCode == 0);
      } else {
        LOG_WARN(("Process finished but could not obtain return code."));
      }
    }
    CloseHandle(pi.hProcess);
    CloseHandle(pi.hThread);

    // Check just in case updater.exe didn't change the status from
    // applying.  If this is the case we report an error.
    BOOL isApplying = FALSE;
    if (IsStatusApplying(argv[1], isApplying) && isApplying) {
      if (updateWasSuccessful) {
        LOG(("update.status is still applying even know update "
             " was successful."));
        if (!WriteStatusFailure(argv[1],
                                SERVICE_STILL_APPLYING_ON_SUCCESS)) {
          LOG_WARN(("Could not write update.status still applying on"
                    " success error."));
        }
        // Since we still had applying we know updater.exe didn't do its
        // job correctly.
        updateWasSuccessful = FALSE;
      } else {
        LOG_WARN(("update.status is still applying and update was not successful."));
        if (!WriteStatusFailure(argv[1],
                                SERVICE_STILL_APPLYING_ON_FAILURE)) {
          LOG_WARN(("Could not write update.status still applying on"
                    " success error."));
        }
      }
    }
  } else {
    DWORD lastError = GetLastError();
    LOG_WARN(("Could not create process as current user, "
              "updaterPath: %ls; cmdLine: %ls.  (%d)",
              argv[0], cmdLine, lastError));
  }
  // Empty value on putenv is how you remove an env variable in Windows
  putenv(const_cast<char*>("MOZ_USING_SERVICE="));

  free(cmdLine);
  return updateWasSuccessful;
}
Exemplo n.º 12
0
// Compares compareCmdLine with the output of MakeCommandLine. This is
// accomplished by converting inCmdLine to an argument list with
// CommandLineToArgvW and converting it back to a command line with
// MakeCommandLine.
static int
verifyCmdLineCreation(PRUnichar *inCmdLine,
                      PRUnichar *compareCmdLine,
                      bool passes, int testNum)
{
  int rv = 0;
  int i;
  int inArgc;
  int outArgc;
  bool isEqual;

  // When debugging with command lines containing Unicode characters greater
  // than 255 you can set the mode for stdout to Unicode so the console will
  // receive the correct characters though it won't display them properly unless
  // the console's font has been set to one that can display the characters. You
  // can also redirect the console output to a file that has been saved as Unicode
  // to view the characters.
//  _setmode(_fileno(stdout), _O_WTEXT);

  // Prepend an additional argument to the command line. CommandLineToArgvW
  // handles argv[0] differently than other arguments since argv[0] is the path
  // to the binary being executed and MakeCommandLine only handles argv[1] and
  // larger.
  PRUnichar *inCmdLineNew = (PRUnichar *) malloc((wcslen(DUMMY_ARG1) + wcslen(inCmdLine) + 1) * sizeof(PRUnichar));
  wcscpy(inCmdLineNew, DUMMY_ARG1);
  wcscat(inCmdLineNew, inCmdLine);
  LPWSTR *inArgv = CommandLineToArgvW(inCmdLineNew, &inArgc);

  PRUnichar *outCmdLine = MakeCommandLine(inArgc - 1, inArgv + 1);
  PRUnichar *outCmdLineNew = (PRUnichar *) malloc((wcslen(DUMMY_ARG1) + wcslen(outCmdLine) + 1) * sizeof(PRUnichar));
  wcscpy(outCmdLineNew, DUMMY_ARG1);
  wcscat(outCmdLineNew, outCmdLine);
  LPWSTR *outArgv = CommandLineToArgvW(outCmdLineNew, &outArgc);

  if (VERBOSE) {
    wprintf(L"\n");
    wprintf(L"Verbose Output\n");
    wprintf(L"--------------\n");
    wprintf(L"Input command line   : >%s<\n", inCmdLine);
    wprintf(L"MakeComandLine output: >%s<\n", outCmdLine);
    wprintf(L"Expected command line: >%s<\n", compareCmdLine);

    wprintf(L"input argc : %d\n", inArgc - 1);
    wprintf(L"output argc: %d\n", outArgc - 1);

    for (i = 1; i < inArgc; ++i) {
      wprintf(L"input argv[%d] : >%s<\n", i - 1, inArgv[i]);
    }

    for (i = 1; i < outArgc; ++i) {
      wprintf(L"output argv[%d]: >%s<\n", i - 1, outArgv[i]);
    }
    wprintf(L"\n");
  }

  isEqual = (inArgc == outArgc);
  if (!isEqual) {
    wprintf(L"TEST-%s-FAIL | %s | ARGC Comparison (check %2d)\n",
            passes ? L"UNEXPECTED" : L"KNOWN", TEST_NAME, testNum);
    if (passes) {
      rv = 1;
    }
    LocalFree(inArgv);
    LocalFree(outArgv);
    free(inCmdLineNew);
    free(outCmdLineNew);
    free(outCmdLine);
    return rv;
  }

  for (i = 1; i < inArgc; ++i) {
    isEqual = (wcscmp(inArgv[i], outArgv[i]) == 0);
    if (!isEqual) {
      wprintf(L"TEST-%s-FAIL | %s | ARGV Comparison (check %2d)\n",
              passes ? L"UNEXPECTED" : L"KNOWN", TEST_NAME, testNum);
      if (passes) {
        rv = 1;
      }
      LocalFree(inArgv);
      LocalFree(outArgv);
      free(inCmdLineNew);
      free(outCmdLineNew);
      free(outCmdLine);
      return rv;
    }
  }

  isEqual = (wcscmp(outCmdLine, compareCmdLine) == 0);
  if (!isEqual) {
    wprintf(L"TEST-%s-FAIL | %s | Command Line Comparison (check %2d)\n",
            passes ? L"UNEXPECTED" : L"KNOWN", TEST_NAME, testNum);
    if (passes) {
      rv = 1;
    }
    LocalFree(inArgv);
    LocalFree(outArgv);
    free(inCmdLineNew);
    free(outCmdLineNew);
    free(outCmdLine);
    return rv;
  }

  if (rv == 0) {
    if (passes) {
      wprintf(L"TEST-PASS | %s | check %2d\n", TEST_NAME, testNum);
    } else {
      wprintf(L"TEST-UNEXPECTED-PASS | %s | check %2d\n", TEST_NAME, testNum);
      rv = 1;
    }
  }

  LocalFree(inArgv);
  LocalFree(outArgv);
  free(inCmdLineNew);
  free(outCmdLineNew);
  free(outCmdLine);
  return rv;
}