Ejemplo n.º 1
0
void StartupRunner::_SpawnProcess(LPTSTR ptzCommandLine, DWORD dwFlags)
{
    ASSERT(!(dwFlags & ERK_WAITFOR_QUIT && dwFlags & ERK_WAITFOR_IDLE));
    
    //
    // The following cases need to be supported:
    //
    // 1. "C:\Program Files\App\App.exe" -params
    // 2. C:\Program Files\App\App.exe -params
    // 3. App.exe -params  (App.exe is in %path% or HKLM->REGSTR_PATH_APPPATHS)
    // and all the above cases without arguments.
    //
    // Note that 'App.exe' may contain spaces too
    //
    // CreateProcess handles 1 and 2, ShellExecuteEx handles 1 and 3.
    // So if the first token doesn't contain path characters (':' or '\')
    // ShellExecuteEx is used. That's really ugly but it *should* work.
    //
    TCHAR tzToken[MAX_LINE_LENGTH] = { 0 };
    LPCTSTR ptzArgs = NULL;
    
    GetToken(ptzCommandLine, tzToken, &ptzArgs, FALSE);
    
    HANDLE hProcess = NULL;
    
    if (strchr(tzToken, _T('\\')) || strchr(tzToken, _T(':')))
    {
        hProcess = _CreateProcess(ptzCommandLine);
    }
    else
    {
        hProcess = _ShellExecuteEx(tzToken, ptzArgs);
    }
    
    if (hProcess != NULL)
    {
        if (dwFlags & ERK_WAITFOR_QUIT)
        {
            WaitForSingleObject(hProcess, INFINITE);
        }
        else if (dwFlags & ERK_WAITFOR_IDLE)
        {
            WaitForInputIdle(hProcess, INFINITE);
        }
        
        CloseHandle(hProcess);
    }
    else
    {
        TRACE("StartupRunner failed to launch '%s'", ptzCommandLine);
    }
}
Ejemplo n.º 2
0
void StartupRunner::_SpawnProcess(LPTSTR ptzCommandLine, DWORD dwFlags)
{
    ASSERT(!(dwFlags & ERK_WAITFOR_QUIT && dwFlags & ERK_WAITFOR_IDLE));

    //
    // The following cases need to be supported:
    //
    // 1. "C:\Program Files\App\App.exe" -params
    // 2. C:\Program Files\App\App.exe -params
    // 3. App.exe -params  (App.exe is in %path% or HKLM->REGSTR_PATH_APPPATHS)
    // and all the above cases without arguments.
    //
    // Note that 'App.exe' may contain spaces too
    //
    // CreateProcess handles 1 and 2, ShellExecuteEx handles 1 and 3.
    //
    // ShellExecuteEx works with UAC. CreateProcess does not.
    // Therefore, we have to attempt to emulate CreateProcess's path parsing
    // when we detect case 2.
    //
    TCHAR tzToken[MAX_LINE_LENGTH] = { 0 };
    LPTSTR ptzArgs = nullptr;

    GetTokenW(ptzCommandLine, tzToken, const_cast<LPCTSTR*>(&ptzArgs), FALSE);

    HANDLE hProcess = nullptr;

    // If the first character is a quote, assume that the first token is the complete path.
    // If the first token does not contain a \ or the first token does not contain a :, assume it's a relative path.
    if (*_tcsspnp(ptzCommandLine, _T(" \t")) == _T('"') || !_tcschr(tzToken, _T('\\')) || !_tcschr(tzToken, _T(':')))
    {
        hProcess = _ShellExecuteEx(tzToken, ptzArgs);
    }
    else
    {
        // This is an approximation of how CreateProcess determines which file to launch.
        ptzArgs = ptzCommandLine;
        do
        {
            ptzArgs = _tcschr(ptzArgs, _T(' '));
            if (ptzArgs != nullptr)
            {
                *ptzArgs++ = _T('\0');
            }
            if (PathFileExists(ptzCommandLine) && PathIsDirectory(ptzCommandLine) == FALSE)
            {
                hProcess = _ShellExecuteEx(ptzCommandLine, ptzArgs);
                break;
            }
            if (ptzArgs != nullptr)
            {
                *(ptzArgs-1) = _T(' ');
            }

        } while (ptzArgs != nullptr);
    }

    if (hProcess != nullptr)
    {
        if (dwFlags & ERK_WAITFOR_QUIT)
        {
            WaitForSingleObject(hProcess, INFINITE);
        }
        else if (dwFlags & ERK_WAITFOR_IDLE)
        {
            WaitForInputIdle(hProcess, INFINITE);
        }

        CloseHandle(hProcess);
    }
#ifdef _DEBUG
    else
    {
        TCHAR tzError[4096];
        DescriptionFromHR(HrGetLastError(), tzError, _countof(tzError));
        TRACE("StartupRunner failed to launch '%ls', %ls", ptzCommandLine, tzError);
    }
#endif
}