Example #1
0
void LaunchWithSumatra(InstanceData *data, const char *url_utf8)
{
    if (!file::Exists(data->filepath))
        plogf("sp: NPP_StreamAsFile() error: file doesn't exist");

    ScopedMem<WCHAR> url(str::conv::FromUtf8(url_utf8));
    // escape quotation marks and backslashes for CmdLineParser.cpp's ParseQuoted
    if (str::FindChar(url, '"')) {
        WStrVec parts;
        parts.Split(url, L"\"");
        url.Set(parts.Join(L"%22"));
    }
    if (str::EndsWith(url, L"\\")) {
        url[str::Len(url) - 1] = '\0';
        url.Set(str::Join(url, L"%5c"));
    }
    // prevent overlong URLs from making LaunchProcess fail
    if (str::Len(url) > 4096)
        url.Set(NULL);

    ScopedMem<WCHAR> cmdLine(str::Format(L"\"%s\" -plugin \"%s\" %d \"%s\"",
        data->exepath, url ? url : L"", (HWND)data->npwin->window, data->filepath));
    data->hProcess = LaunchProcess(cmdLine);
    if (!data->hProcess)
    {
        plogf("sp: NPP_StreamAsFile() error: couldn't run SumatraPDF!");
        data->message = _TR("Error: Couldn't run SumatraPDF!");
    }
}
Example #2
0
 bool LaunchProcess(const CommandLine& cmdline,
     const LaunchOptions& options,
     ProcessHandle* process_handle)
 {
     return LaunchProcess(cmdline.GetCommandLineString(),
         options, process_handle);
 }
Example #3
0
static BaseEngine *ps2pdf(const WCHAR *fileName)
{
    // TODO: read from gswin32c's stdout instead of using a TEMP file
    ScopedMem<WCHAR> shortPath(path::ShortPath(fileName));
    ScopedMem<WCHAR> tmpFile(path::GetTempPath(L"PsE"));
    ScopedFile tmpFileScope(tmpFile);
    ScopedMem<WCHAR> gswin32c(GetGhostscriptPath());
    if (!shortPath || !tmpFile || !gswin32c)
        return NULL;

    // try to help Ghostscript determine the intended page size
    ScopedMem<WCHAR> psSetup;
    RectI page = ExtractDSCPageSize(fileName);
    if (!page.IsEmpty())
        psSetup.Set(str::Format(L" << /PageSize [%i %i] >> setpagedevice", page.dx, page.dy));

    ScopedMem<WCHAR> cmdLine(str::Format(
        L"\"%s\" -q -dSAFER -dNOPAUSE -dBATCH -dEPSCrop -sOutputFile=\"%s\" -sDEVICE=pdfwrite -c \".setpdfwrite%s\" -f \"%s\"",
        gswin32c, tmpFile, psSetup ? psSetup : L"", shortPath));
    fprintf(stderr, "- %s:%d: using '%ls' for creating '%%TEMP%%\\%ls'\n", path::GetBaseName(__FILE__), __LINE__, gswin32c.Get(), path::GetBaseName(tmpFile));

    // TODO: the PS-to-PDF conversion can hang the UI for several seconds
    HANDLE process = LaunchProcess(cmdLine, NULL, CREATE_NO_WINDOW);
    if (!process)
        return NULL;

    DWORD timeout = 10000;
#ifdef DEBUG
    // allow to disable the timeout for debugging purposes
    if (GetEnvironmentVariable(L"SUMATRAPDF_NO_GHOSTSCRIPT_TIMEOUT", NULL, 0))
        timeout = INFINITE;
#endif
    DWORD exitCode = EXIT_FAILURE;
    WaitForSingleObject(process, timeout);
    GetExitCodeProcess(process, &exitCode);
    TerminateProcess(process, 1);
    CloseHandle(process);
    if (exitCode != EXIT_SUCCESS)
        return NULL;

    size_t len;
    ScopedMem<char> pdfData(file::ReadAll(tmpFile, &len));
    if (!pdfData)
        return NULL;

    ScopedComPtr<IStream> stream(CreateStreamFromData(pdfData, len));
    if (!stream)
        return NULL;

    return PdfEngine::CreateFromStream(stream);
}
Example #4
0
// based on http://mdb-blog.blogspot.com/2013/01/nsis-lunch-program-as-user-from-uac.html
// uses $WINDIR\explorer.exe to launch cmd
// Other promising approaches:
// - http://blogs.msdn.com/b/oldnewthing/archive/2013/11/18/10468726.aspx
// - http://brandonlive.com/2008/04/27/getting-the-shell-to-run-an-application-for-you-part-2-how/
// - http://www.codeproject.com/Articles/23090/Creating-a-process-with-Medium-Integration-Level-f
// Approaches tried but didn't work:
// - http://stackoverflow.com/questions/3298611/run-my-program-asuser
// - using CreateProcessAsUser() with hand-crafted token
// It'll always run the process, might fail to run non-elevated if fails to find explorer.exe
// Also, if explorer.exe is running elevated, it'll probably run elevated as well.
void RunNonElevated(const WCHAR *exePath)
{
    ScopedMem<WCHAR> cmd, explorerPath;
    WCHAR buf[MAX_PATH] = { 0 };
    UINT res = GetWindowsDirectory(buf, dimof(buf));
    if (0 == res || res >= dimof(buf))
        goto Run;
    explorerPath.Set(path::Join(buf, L"explorer.exe"));
    if (!file::Exists(explorerPath))
        goto Run;
    cmd.Set(str::Format(L"\"%s\" \"%s\"", explorerPath.Get(), exePath));
Run:
    HANDLE h = LaunchProcess(cmd ? cmd : exePath);
    SafeCloseHandle(&h);
}
Example #5
0
// === PUBLIC ===
bool TTYProcess::startTTY(QString prog, QStringList args, QString workdir){
  if(workdir=="~"){ workdir = QDir::homePath(); }
  QDir::setCurrent(workdir);
  QProcessEnvironment env = QProcessEnvironment::systemEnvironment();
  setenv("TERM","vt100",1); //vt100: VT100 emulation support
  unsetenv("TERMCAP");
  /*setenv("TERMCAP","mvterm|vv100|mvterm emulator with ANSI colors:\
	:pa#64:Co#8:AF=\E[3%dm:AB=\E[4%dm:op=\E[100m:tc=vt102:",1); //see /etc/termcap as well*/
  QStringList filter = env.keys().filter("XTERM");
  for(int i=0; i<filter.length(); i++){ unsetenv(filter[i].toLocal8Bit().data()); }
  //if(env.contains("TERM")){ unsetenv("TERM"); }
  //else if(env.contains
  //Turn the program/arguments into C-compatible arrays
  char cprog[prog.length()]; strcpy(cprog, prog.toLocal8Bit().data());
  char *cargs[args.length()+2];
  QByteArray nullarray;
  for(int i=0; i<args.length()+2; i++){
    // First arg needs to be the program
    if ( i == 0 ) {
      cargs[i] = new char[ prog.toLocal8Bit().size()+1];
      strcpy( cargs[i], prog.toLocal8Bit().data() );
    } else if(i<args.length()){
      cargs[i] = new char[ args[i].toLocal8Bit().size()+1];
      strcpy( cargs[i], args[i].toLocal8Bit().data() );
    }else{
      cargs[i] = NULL;
    }
  }
  qDebug() << "PTY Start:" << prog;
  //Launch the process attached to a new PTY
  int FD = 0;
  pid_t tmp = LaunchProcess(FD, cprog, cargs);
  qDebug() << " - PID:" << tmp;
  qDebug() << " - FD:" << FD;
  if(tmp<0){ return false; } //error
  else{
    childProc = tmp;
    //Load the file for close notifications
      //TO-DO
    //Watch the socket for activity
    sn= new QSocketNotifier(FD, QSocketNotifier::Read);
	sn->setEnabled(true);
	connect(sn, SIGNAL(activated(int)), this, SLOT(checkStatus(int)) );
    ttyfd = FD;
    qDebug() << " - PTY:" << ptsname(FD);
    return true;
  }
}
Example #6
0
static PdfEngine *ps2pdf(const WCHAR *fileName)
{
    // TODO: read from gswin32c's stdout instead of using a TEMP file
    ScopedMem<WCHAR> shortPath(path::ShortPath(fileName));
    ScopedMem<WCHAR> tmpFile(path::GetTempPath(L"PsE"));
    ScopedFile tmpFileScope(tmpFile);
    ScopedMem<WCHAR> gswin32c(GetGhostscriptPath());
    if (!shortPath || !tmpFile || !gswin32c)
        return NULL;
    ScopedMem<WCHAR> cmdLine(str::Format(L"\"%s\" -q -dSAFER -dNOPAUSE -dBATCH -dEPSCrop -sOutputFile=\"%s\" -sDEVICE=pdfwrite -c .setpdfwrite -f \"%s\"", gswin32c, tmpFile, shortPath));

    if (GetEnvironmentVariable(L"MULOG", NULL, 0)) {
        wprintf(L"ps2pdf: using Ghostscript from '%s'\n", gswin32c.Get());
        wprintf(L"ps2pdf: for creating '%s'\n", tmpFile.Get());
    }

    // TODO: the PS-to-PDF conversion can hang the UI for several seconds
    HANDLE process = LaunchProcess(cmdLine, NULL, CREATE_NO_WINDOW);
    if (!process)
        return NULL;

    DWORD exitCode = EXIT_FAILURE;
    WaitForSingleObject(process, 10000);
    GetExitCodeProcess(process, &exitCode);
    TerminateProcess(process, 1);
    CloseHandle(process);
    if (exitCode != EXIT_SUCCESS)
        return NULL;

    size_t len;
    ScopedMem<char> pdfData(file::ReadAll(tmpFile, &len));
    if (!pdfData)
        return NULL;

    ScopedComPtr<IStream> stream(CreateStreamFromData(pdfData, len));
    if (!stream)
        return NULL;

    if (GetEnvironmentVariable(L"MULOG", NULL, 0))
        printf("ps2pdf: PDF conversion successful\n");

    return PdfEngine::CreateFromStream(stream);
}
Example #7
0
// returns true if the double-click was handled and false if it wasn't
bool OnInverseSearch(WindowInfo *win, int x, int y)
{
    if (!HasPermission(Perm_DiskAccess) || gPluginMode) return false;
    if (!win->IsDocLoaded() || win->dm->engineType != Engine_PDF) return false;

    // Clear the last forward-search result
    win->fwdSearchMark.rects.Reset();
    InvalidateRect(win->hwndCanvas, NULL, FALSE);

    // On double-clicking error message will be shown to the user
    // if the PDF does not have a synchronization file
    if (!win->pdfsync) {
        int err = Synchronizer::Create(win->loadedFilePath,
            static_cast<PdfEngine *>(win->dm->engine), &win->pdfsync);
        if (err == PDFSYNCERR_SYNCFILE_NOTFOUND) {
            // We used to warn that "No synchronization file found" at this
            // point if gGlobalPrefs->enableTeXEnhancements is set; we no longer
            // so do because a double-click has several other meanings
            // (selecting a word or an image, navigating quickly using links)
            // and showing an unrelated warning in all those cases seems wrong
            return false;
        }
        if (err != PDFSYNCERR_SUCCESS) {
            ShowNotification(win, _TR("Synchronization file cannot be opened"));
            return true;
        }
        gGlobalPrefs->enableTeXEnhancements = true;
    }

    int pageNo = win->dm->GetPageNoByPoint(PointI(x, y));
    if (!win->dm->ValidPageNo(pageNo))
        return false;

    PointI pt = win->dm->CvtFromScreen(PointI(x, y), pageNo).Convert<int>();
    ScopedMem<WCHAR> srcfilepath;
    UINT line, col;
    int err = win->pdfsync->DocToSource(pageNo, pt, srcfilepath, &line, &col);
    if (err != PDFSYNCERR_SUCCESS) {
        ShowNotification(win, _TR("No synchronization info at this position"));
        return true;
    }

    WCHAR *inverseSearch = gGlobalPrefs->inverseSearchCmdLine;
    if (!inverseSearch)
        // Detect a text editor and use it as the default inverse search handler for now
        inverseSearch = AutoDetectInverseSearchCommands();

    ScopedMem<WCHAR> cmdline;
    if (inverseSearch)
        cmdline.Set(win->pdfsync->PrepareCommandline(inverseSearch, srcfilepath, line, col));
    if (!str::IsEmpty(cmdline.Get())) {
        // resolve relative paths with relation to SumatraPDF.exe's directory
        ScopedMem<WCHAR> appDir(GetExePath());
        if (appDir)
            appDir.Set(path::GetDir(appDir));
        ScopedHandle process(LaunchProcess(cmdline, appDir));
        if (!process)
            ShowNotification(win, _TR("Cannot start inverse search command. Please check the command line in the settings."));
    }
    else if (gGlobalPrefs->enableTeXEnhancements)
        ShowNotification(win, _TR("Cannot start inverse search command. Please check the command line in the settings."));

    if (inverseSearch != gGlobalPrefs->inverseSearchCmdLine)
        free(inverseSearch);

    return true;
}
Example #8
0
/*-----------------------------------------------------------------------------
  Background thread for managing the state of the agent
-----------------------------------------------------------------------------*/
void CurlBlastDlg::ThreadProc(void)
{
    LoadSettings();

    // configure the desktop resolution
    WaitForSingleObject(testingMutex, INFINITE);
    SetupScreen();
    ReleaseMutex(testingMutex);

    // wait for the statup delay
    SetStatus(_T("Starting up..."));
    DWORD ms = startupDelay;
    while( ms > 0 && WaitForSingleObject(hMustExit,0) == WAIT_TIMEOUT) {
        Sleep(500);
        ms -= 500;
    }

    // launch the watchdog
    TCHAR path[MAX_PATH];
    GetModuleFileName(NULL, path, MAX_PATH);
    lstrcpy(PathFindFileName(path), _T("wptwatchdog.exe"));
    CString watchdog;
    watchdog.Format(_T("\"%s\" %d"), path, GetCurrentProcessId());
    HANDLE process = NULL;
    LaunchProcess(watchdog, &process);
    if (process)
        CloseHandle(process);

    if (WaitForSingleObject(hMustExit,0) == WAIT_TIMEOUT) {
        DoStartup();
    }

    // handle the periodic cleanup until it is time to exit
    Alive();
    DWORD msCleanup = 500;
    DWORD msTemp = 20000;
    while(WaitForSingleObject(hMustExit,0) == WAIT_TIMEOUT) {
        if (!msCleanup) {
            CloseDialogs();
            KillProcs();
            msCleanup = 500;
        } else
            msCleanup -= 500;

        if (!msTemp) {
            if (WaitForSingleObject(testingMutex, 0) != WAIT_TIMEOUT) {
                ClearTemp();
                msTemp = 20000;
                ReleaseMutex(testingMutex);
            }
        } else
            msTemp -= 500;

        CheckAlive();
        Sleep(500);
    }

    // signal and wait for all of the workers to finish
    KillWorker();

    // shut down the url manager
    urlManager.Stop();
}
/**
 * Read command line parameters and control the launching of the agents. 
 */
void MainL()
	{	
	LOG_MSG( "ENTER: t_multi_agent_launcher MainL()");

	TInt ret = KErrNone;
	TInt numAgents = KNumAgents;
	TInt numTargets = KNumTargets;
	TInt numTestRuns = KNumTestRuns;

	TInt argc = User::CommandLineLength();
	HBufC* commandLine = NULL;
	LOG_MSG2("t_multi_agent_launcher: MainL(): argc=%d", argc);
    
	if(argc)
		{
		commandLine = HBufC::NewLC(argc);
		TPtr commandLineBuffer = commandLine->Des();
		User::CommandLine(commandLineBuffer);

		RBuf printCommandLine;
		CleanupClosePushL( printCommandLine );
		printCommandLine.CreateL( commandLine->Des().Length() );
		printCommandLine.Copy( commandLine->Des() );
		printCommandLine.Collapse();
		LOG_MSG2("t_multi_agent_launcher: command line = %S", &printCommandLine);
		CleanupStack::PopAndDestroy( &printCommandLine );
 
		// create a lexer and read through the command line
		TLex lex(*commandLine);
		while (!lex.Eos())
			{
			// only look for options with first character '-'
			if (lex.Get() == '-')
				{
					TChar arg = lex.Get();
					switch ( arg )
						{
						case 'n':
							lex.Val( numAgents );
							LOG_MSG2("t_multi_agent_launcher: parsed numAgents as %d", numAgents);
							break;
						case 'm':
							lex.Val( numTargets );
							LOG_MSG2("t_multi_agent_launcher: parsed numTargets as %d", numTargets);                        
							break;  
						case 't':
							lex.Val( numTestRuns );
							LOG_MSG2("t_multi_agent_launcher: parsed numTestRuns as %d", numTestRuns);                        
							break;                    
						default:
							LOG_MSG("t_multi_agent_launcher: unknown argument ignoring it");
							break;                 
						}
				}
			}
		}

	// Note: below is a workaround to overcome an issue with RTest server crashing 
	// when writing to the windows console from different agents (on different CPUs 
	// at the same time). To overcome this we get signaled by the agents when they have 
	// completed their tests so that we can do a RTest complete
	RSemaphore launchSemaphore;
	CleanupClosePushL(launchSemaphore);
	ret = launchSemaphore.CreateGlobal(KLaunchSemaphoreName, 0);
	LOG_MSG2( ">Target Launcher : RSemaphore.CreateGlobal ret %d", ret);
	User::LeaveIfError( ret );

	ret = launchSemaphore.OpenGlobal(KLaunchSemaphoreName);
	LOG_MSG2( ">Target Launcher : RSemaphore.OpenGlobal ret %d", ret);
	User::LeaveIfError( ret );

	//Now launch the requested number of apps for the requested number of test runs
	for( TInt j = 0; j < numTestRuns; j++ )
		{ 
			for( TInt i = 0; i < numAgents; i++ )  
				{
					RBuf targetName;
					targetName.CleanupClosePushL();
					targetName.CreateL(KAgentExe());

					RProcess aProc;
					CleanupClosePushL(aProc); 
					RBuf launcherOptions;
					CleanupClosePushL(launcherOptions);
				    const TInt additionalWords = 2;	
					launcherOptions.CreateL( KAgentOptions().Length() + additionalWords );
		
					// Apply offset: launcherOptions.Format( .., .., i * numTargets, ..)
					// workaround to ensure we have the same binary for multiple agents. 
					// e.g. So if offset = 0, agent attaches to app1, app2, app3, app4, app5
					// if offset = 5, agent attached to app6, app7, app8, app9, app10 etc.
					// Note: apps need to be in rom otherwise the agent will fail on an assert 
					// (with KErrNotFound)
					launcherOptions.Format( KAgentOptions(), (TUint)numTargets, i * numTargets, 0);
			
					ret = LaunchProcess( aProc, targetName, launcherOptions );	
					CleanupStack::PopAndDestroy(3,&targetName);
					User::LeaveIfError(ret);
				}
		}

	// Wait for all agents to do their testing before checking the semaphore
	User::After(12000000);

	LOG_MSG( ">Target Launcher:  Semaphore wait");

	for (TInt i = 0; i < numAgents; i ++)
		{
		//We need this delay just in case an agent crashes and never signals the sem
		ret = launchSemaphore.Wait(100000);
		if( ret != KErrNone )
			{
			LOG_MSG3("launchSemaphore.Wait ret %d for agent %d", ret, i);
			break;
			}
		}

	LOG_MSG2( "testing for Semaphore ret %d", ret);

	// We only want to have one RTest instance at any one time since otherwise RTest can panic
	RTest test(_L("T_MULTI_AGENT_LAUNCHER"));
	test.Start(_L("t_multi_agent_launcher Check for agents finishing correctly"));
	test(ret == KErrNone);
	test.End();
	test.Close();

	CleanupStack::PopAndDestroy(&launchSemaphore); // launchSemaphore

	if( commandLine )
	CleanupStack::PopAndDestroy(commandLine);
	
	LOG_MSG("EXIT: t_multi_agent_launcher MainL()");
	}
/**
 * Read command line parameters and control the launching of targets. 
 * Create global launch semaphore KLaunchSemaphoreName
 */
void MainL()
    {

    TInt numApps = KNumApps;
    TInt numLaunches = KNumLaunches;
    TInt launchControl = 0;

    TInt argc = User::CommandLineLength();
    HBufC* commandLine = NULL;
    RDebug::Printf( ">Launcher Process() argc=%d", argc );

    if( argc )
        {
        commandLine = HBufC::NewLC(argc);
        TPtr commandLineBuffer = commandLine->Des();
        User::CommandLine(commandLineBuffer);

        RBuf printCommandLine;
        CleanupClosePushL( printCommandLine );
        printCommandLine.CreateL( commandLine->Des().Length() );
        printCommandLine.Copy( commandLine->Des() );
        printCommandLine.Collapse();
        RDebug::Printf( ">command line = %S", &printCommandLine );
        CleanupStack::PopAndDestroy( &printCommandLine );

        // create a lexer and read through the command line
        TLex lex(*commandLine);
        while (!lex.Eos())
            {
            // only look for options with first character '+', other switches are for the targets
            if (lex.Get() == '+')
                {
                TChar arg = lex.Get();
                switch (arg)
                    {
                    case 'n':
                        lex.Val( numApps );
                        RDebug::Printf("parsed numApps as %d", numApps);
                        break;
                    case 'm':
                        lex.Val( numLaunches );
                        RDebug::Printf("parsed numLaunches as %d", numLaunches );
                        break;
                    case 'o':
                        lex.Val( launchControl );
                        RDebug::Printf("parsed launchControl as %d", launchControl);
                        break;
                    default:
                        // unknown argument ignore it
                        break;             
                    }//switch
                }// if +
            }//while
        }//if argc

   RSemaphore launchSemaphore;
   TInt ret = KErrNone;
   CleanupClosePushL( launchSemaphore );
   ret = launchSemaphore.CreateGlobal( KLaunchSemaphoreName, 0 );
   RDebug::Printf( ">Target Launcher : RSemaphore.CreateGlobal ret %d", ret);
   User::LeaveIfError( ret );

   ret = launchSemaphore.OpenGlobal( KLaunchSemaphoreName );
   RDebug::Printf( ">Target Launcher : RSemaphore.OpenGlobal ret %d", ret);
   User::LeaveIfError( ret );
   
   //Only now indicate to the launcher that we have fully started, so they can find and open the semaphore
   RProcess::Rendezvous(KErrNone);

   //Now launch the requested number of apps for the requested number of launches
   for( ; numLaunches > 0; numLaunches-- )
       { 
       for( TInt launchIndex = numApps; launchIndex > 0; launchIndex-- )  
           {
           RDebug::Printf( ">Target Launcher:  Semaphore wait app %d, launch %d", launchIndex, numLaunches );
           launchSemaphore.Wait();

           RBuf targetName;
           CleanupClosePushL( targetName );
           RDebug::Printf( ">Target Launcher:  targetName.Create %d, launch %d", launchIndex, numLaunches );
           targetName.Create( KTargetExe().Length() + 2 );

           if( launchControl == 1 )
               {
               // Reverse the order of the apps launched by reversing the index in the name
               RDebug::Printf( ">Target Launcher:  targetName.Format %d, launch %d", numApps - launchIndex + 1, numLaunches );
               targetName.Format( KTargetExe(), numApps - launchIndex + 1 );
               }
           else
               {
               RDebug::Printf( ">Target Launcher:  targetName.Format %d, launch %d", launchIndex, numLaunches );
               targetName.Format( KTargetExe(), launchIndex );
               }

           RProcess aProc;
           CleanupClosePushL( aProc ); 
    
           RDebug::Printf( ">Target Launcher: LaunchProcess %d, launch %d", launchIndex, numLaunches );
           RDebug::Printf( ">LaunchProcess %lS", &targetName );
           TPtr cmdLinePtr( commandLine->Des() );
           ret = LaunchProcess( aProc, targetName, cmdLinePtr );
           CleanupStack::PopAndDestroy( &aProc );

           RDebug::Printf( "<Target Launcher: LaunchProcess returned %d", ret );
           CleanupStack::PopAndDestroy( &targetName );

           User::LeaveIfError( ret );

           //By now the add proc event should have been delivered to the
           //test app agent.
           }
       }

    launchSemaphore.Wait( 500000 );

    CleanupStack::PopAndDestroy( &launchSemaphore );

    if( commandLine )
       CleanupStack::PopAndDestroy( commandLine );
 
    }