void QAdvancedSettingWidget::TPDP_OnRSP(T3K_DEVICE_INFO /*devInfo*/, ResponsePart Part, unsigned short /*ticktime*/, const char */*partid*/, int /*id*/, bool /*bFinal*/, const char *cmd) { if( !winId() ) return; if( strstr( cmd, cstrCamPosTrc ) == cmd ) { QString strCmd( cmd ); strCmd = strCmd.mid( strCmd.indexOf('=')+1 ); switch( Part ) { case CM1: m_strCam1PosTrc = strCmd; break; case CM2: m_strCam2PosTrc = strCmd; break; case CM1_1: m_strCamS1PosTrc = strCmd; break; case CM2_1: m_strCamS2PosTrc = strCmd; break; case MM: default: break; } } else if( strstr( cmd, cstrFactoryCalibration ) == cmd ) { QString strCmd( cmd ); m_strFactoryCalibration = strCmd.mid( strCmd.indexOf('=')+1 ); } }
int WINAPI _tWinMain(HINSTANCE hInstance, HINSTANCE /*hPrevInstance*/, LPTSTR lpstrCmdLine, int nCmdShow) { HRESULT hRes = ::CoInitialize(NULL); // If you are running on NT 4.0 or higher you can use the following call instead to // make the EXE free threaded. This means that calls come in on a random RPC thread. // HRESULT hRes = ::CoInitializeEx(NULL, COINIT_MULTITHREADED); ATLASSERT(SUCCEEDED(hRes)); // this resolves ATL window thunking problem when Microsoft Layer for Unicode (MSLU) is used ::DefWindowProc(NULL, 0, 0, 0L); AtlInitCommonControls( ICC_BAR_CLASSES | ICC_WIN95_CLASSES | ICC_DATE_CLASSES | ICC_USEREX_CLASSES | ICC_COOL_CLASSES | ICC_PAGESCROLLER_CLASS | ICC_NATIVEFNTCTL_CLASS); // add flags to support other controls hRes = _Module.Init(NULL, hInstance); ATLASSERT(SUCCEEDED(hRes)); CString strCmd(lpstrCmdLine); if (-1 != strCmd.Find(_T("/FloatBar"))) Config::StartupShowFloatBar = true; int nRet = _Module.Main(); //Run(lpstrCmdLine, nCmdShow); _Module.Term(); ::CoUninitialize(); return nRet; }
BOOL RunProcess(LPCTSTR szFileName, LPCTSTR cmdline/* = nullptr*/, BOOL bHide /* = TRUE */, LPCTSTR dir /* = nullptr*/, BOOL bWait /* = TRUE */, DWORD dwWaitTime /* = INFINITE */) { LPCTSTR process_dir; if (dir == nullptr || _tcslen(dir) == 0) process_dir = nullptr; else process_dir = dir; LPCTSTR process_name; if (szFileName == nullptr || _tcslen(szFileName) == 0) process_name = nullptr; else process_name = szFileName; STARTUPINFO si; ZeroMemory(&si, sizeof(si)); si.cb = sizeof(si); DWORD dwCreationFlags = 0; if (bHide) { si.wShowWindow = SW_HIDE; #ifndef _WIN32_WCE dwCreationFlags = CREATE_NO_WINDOW; #endif } PROCESS_INFORMATION pi; ZeroMemory(&pi, sizeof(pi)); // Start the child process CString strCmd(cmdline); LPTSTR pszcmd = (LPTSTR)(LPCTSTR)strCmd; BOOL bRet = CreateProcess( process_name, pszcmd, // Command line. nullptr, // Process handle not inheritable. nullptr, // Thread handle not inheritable. FALSE, // Set handle inheritance to FALSE. dwCreationFlags, // No creation flags. nullptr, // Use parent's environment block. (LPTSTR)process_dir, // Use parent's starting directory. &si, // Pointer to STARTUPINFO structure. &pi ); if(bRet) { if(bWait) bRet = (::WaitForSingleObject(pi.hProcess, dwWaitTime) != WAIT_FAILED) ? TRUE : FALSE; ::CloseHandle(pi.hProcess); ::CloseHandle(pi.hThread); } return bRet; }
int GetCmdOpt(LPCTSTR szCmdLine, CStringArray &arOpt) { int iPos = 0; CString strCmd(szCmdLine), strTok; arOpt.RemoveAll(); strTok = strCmd.Tokenize(" ", iPos); while (strTok != "") { arOpt.Add(strTok); strTok = strCmd.Tokenize(" ", iPos); } return arOpt.GetSize(); }
// 設定ボタンのEnable調節 void CKeyBoardPropertyPage::EnableSetBtn() { // New アクセスキーテキスト TCHAR cBuff[MAX_PATH]; cBuff[0] = 0; //+++ ::GetWindowText(m_editNew.m_hWnd, cBuff, MAX_PATH); CString strAccelNew(cBuff); // Now アクセスキーテキスト ::GetWindowText(m_editNow.m_hWnd, cBuff, MAX_PATH); CString strAccelNow(cBuff); // 既存コマンドテキスト ::GetWindowText(GetDlgItem(IDC_STC01), cBuff, MAX_PATH); CString strCmd(cBuff); BOOL bEnableSetBtn = TRUE; if (strAccelNew.IsEmpty() == FALSE) { // Now アクセスキーがない時 if ( strAccelNow.IsEmpty() ) { if ( strCmd.IsEmpty() ) bEnableSetBtn = TRUE; else if (m_nCmdMove == 1) bEnableSetBtn = TRUE; else bEnableSetBtn = FALSE; } else { if ( strCmd.IsEmpty() ) { if (m_nCmdUpdate == 1) bEnableSetBtn = TRUE; else bEnableSetBtn = FALSE; } else { if (m_nCmdMove == 1 && m_nCmdUpdate == 1) bEnableSetBtn = TRUE; else bEnableSetBtn = FALSE; } } } else { bEnableSetBtn = FALSE; } ::EnableWindow(GetDlgItem(IDC_BTN_SET), bEnableSetBtn); }
//++ ------------------------------------------------------------------------------------ // Details: The invoker requires this function. The command does work in this function. // The command is likely to communicate with the LLDB SBDebugger in here. // Type: Overridden. // Args: None. // Return: MIstatus::success - Functional succeeded. // MIstatus::failure - Functional failed. // Throws: None. //-- bool CMICmdCmdExecInterrupt::Execute() { CMICmnLLDBDebugSessionInfo &rSessionInfo(CMICmnLLDBDebugSessionInfo::Instance()); lldb::SBDebugger &rDebugger = rSessionInfo.GetDebugger(); CMIUtilString strCmd("process interrupt"); const lldb::ReturnStatus status = rDebugger.GetCommandInterpreter().HandleCommand(strCmd.c_str(), m_lldbResult, false); MIunused(status); // CODETAG_DEBUG_SESSION_RUNNING_PROG_RECEIVED_SIGINT_PAUSE_PROGRAM if (!CMIDriver::Instance().SetDriverStateRunningNotDebugging()) { const CMIUtilString &rErrMsg(CMIDriver::Instance().GetErrorDescription()); SetErrorDescription(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_SET_NEW_DRIVER_STATE), strCmd.c_str(), rErrMsg.c_str())); return MIstatus::failure; } return MIstatus::success; }
//++ ------------------------------------------------------------------------------------ // Details: The invoker requires this function. The command does work in this function. // The command is likely to communicate with the LLDB SBDebugger in here. // Type: Overridden. // Args: None. // Return: MIstatus::success - Functional succeeded. // MIstatus::failure - Functional failed. // Throws: None. //-- bool CMICmdCmdExecFinish::Execute() { CMICMDBASE_GETOPTION(pArgThread, OptionLong, m_constStrArgThread); // Retrieve the --thread option's thread ID (only 1) MIuint64 nThreadId = UINT64_MAX; if (pArgThread->GetFound() && !pArgThread->GetExpectedOption<CMICmdArgValNumber, MIuint64>(nThreadId)) { SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_OPTION_NOT_FOUND), m_cmdData.strMiCmd.c_str(), m_constStrArgThread.c_str())); return MIstatus::failure; } CMICmnLLDBDebugSessionInfo &rSessionInfo(CMICmnLLDBDebugSessionInfo::Instance()); lldb::SBDebugger &rDebugger = rSessionInfo.GetDebugger(); CMIUtilString strCmd("thread step-out"); if (nThreadId != UINT64_MAX) strCmd += CMIUtilString::Format(" %llu", nThreadId); rDebugger.GetCommandInterpreter().HandleCommand(strCmd.c_str(), m_lldbResult, false); return MIstatus::success; }
void QNMouseProfileWidget::onCBPredefinedProfileActivated(int index) { if( index < 0 ) return; if( index == 0 && m_cbPredefinedProfile.itemText(0) == QLangManager::instance()->getResource(). getResString( QString::fromUtf8("EDIT PROFILE ITEM"), QString::fromUtf8("TEXT_PROFILE_ITEM_USER_DEFINED") ) ) { return; } m_RequestCmdManager.Stop(); QString strV = m_cbPredefinedProfile.itemData( index ).toString(); int nProfileIdx = ui->TabMouseSettingTable->getActiveTab(); if( !m_strPrevZommValue.isEmpty() ) { int nP = strV.indexOf(" 80"); m_strPrevZommValue = strV.mid( nP+3, 10 ); QSettings settings( "Habilience", "T3kCfg" ); settings.beginGroup( "Options" ); settings.setValue( "MacOSX_Gesture_Value", m_strPrevZommValue ); settings.endGroup(); strV = strV.replace( nP, 11, " 8000000000" ); } QString strCmd(cstrMouseProfile1); strCmd.replace( '1', QString::number(nProfileIdx+1) ); m_RequestCmdManager.AddItem( strCmd.toUtf8().data(), strV ); m_RequestCmdManager.Start( m_pT3kHandle ); if( index != 0 && m_cbPredefinedProfile.itemText(0) == QLangManager::instance()->getResource(). getResString( QString::fromUtf8("EDIT PROFILE ITEM"), QString::fromUtf8("TEXT_PROFILE_ITEM_USER_DEFINED") ) ) { m_cbPredefinedProfile.removeItem( 0 ); return; } }
QAdvancedSettingWidget::QAdvancedSettingWidget(QWidget *parent) : QDialog(parent), ui(new Ui::QAdvancedSettingWidget) { ui->setupUi(this); setWindowFlags( Qt::Dialog | Qt::WindowTitleHint | Qt::WindowCloseButtonHint ); setWindowModality( Qt::WindowModal ); setModal( true ); connect( ui->BtnCancel, &QPushButton::clicked, this, &QDialog::close ); QT3kDevice* pHandle = QT3kUserData::GetInstance()->getT3kHandle(); int nRetry = 3; bool bOK = false; m_bRSE = false; QString strCmd(sCam1 + cstrCamPosTrc + "?"); do { if (pHandle->sendCommand(strCmd, false)) { bOK = true; break; } } while (--nRetry > 0); ui->BtnDefault->setVisible( bOK && !m_bRSE && !m_strCam1PosTrc.isEmpty() ); if( QConfigData::instance()->getData("ADVANCED", "ID", "").toString().isEmpty() ) { ui->LbPassword->setVisible( false ); ui->EditPassword->setVisible( false ); } onChangeLanguage(); }
//-------------------------------------------------------------- /// Injects the application specified by the Inject command and /// sends the results of the injection to the requester /// \param requestID the ID of the incoming request /// \param sCmd pointer to the string containing the request /// \param pClientSocket the socket used to send the response //-------------------------------------------------------------- void ProcessTracker::DoInjectCommand(CommunicationID requestID, char** sCmd, NetSocket* pClientSocket) { // clear the previous data since it is about to get reset g_allowedWrappersMap.clear(); m_injectedAppName = ""; m_injectedAppArgs = ""; // parse the command gtASCIIString strCmd(*sCmd); std::list< gtASCIIString > paramList; strCmd.Split("&", true, paramList); for (std::list< gtASCIIString >::const_iterator iter = paramList.begin(); iter != paramList.end(); ++iter) { char* pParam = (char*) iter->asCharArray(); char** ppParam = &pParam; if (IsToken(ppParam, "plugins=")) { // plugins= is followed by a list of comma separated short descriptions of wrappers gtASCIIString strPlugins(*ppParam); std::list< gtASCIIString > pluginList; strPlugins.Split(",", true, pluginList); for (std::list< gtASCIIString >::const_iterator iter1 = pluginList.begin(); iter1 != pluginList.end(); ++iter1) { if (*iter1 == "") { Log(logERROR, "Failed to parse plugin name\n"); SendTextResponse(requestID, "Error: Failed to parse plugin name.", pClientSocket); return; } WrapperMap::iterator iWrapper = GetWrapperMap().find(iter1->asCharArray()); if (iWrapper == GetWrapperMap().end()) { Log(logERROR, "Invalid plugin requested, you requested plugin %s\n", (*iter1).asCharArray()); SendFormattedTextResponse(requestID, pClientSocket, "Error: Invalid plugin requested, you requested plugin %s\n", (*iter1).asCharArray()); return; } // we have a valid index g_allowedWrappersMap.insert(*iWrapper); } } else if (IsToken(ppParam, "app=")) { m_injectedAppName = *ppParam; } else if (IsToken(ppParam, "args=")) { m_injectedAppArgs = *ppParam; } } // make sure an app name was specified if (m_injectedAppName.empty() == true) { Log(logERROR, "Application name not specified\n"); SendTextResponse(requestID, "Error: Application name not specified", pClientSocket); return; } // if no wrappers were specified, then use them all if (g_allowedWrappersMap.empty() == true) { g_allowedWrappersMap = GetWrapperMap(); } // fix the path gtASCIIString appName = m_injectedAppName.c_str(); appName.replace("%20", " "); appName.replace("%22", "\""); appName.replace("%5C", "\\"); appName.replace("%E2%80%93", "-"); appName.replace("%26", "&"); appName.replace("%27", "'"); appName.replace("%60", "`"); appName.replace("%E2%80%98", "`"); m_injectedAppName = appName.asCharArray(); gtASCIIString appArgs = m_injectedAppArgs.c_str(); appArgs.replace("%22", "\""); appArgs.replace("%20", " "); appArgs.replace("%5C", "\\"); appArgs.replace("%E2%80%93", "-"); appArgs.replace("%26", "&"); appArgs.replace("%27", "'"); appArgs.replace("%60", "`"); appArgs.replace("%E2%80%98", "`"); m_injectedAppArgs = appArgs.asCharArray(); if (WritePluginsToSharedMemoryAndLaunchApp() == true) { // loop up to 500 times while checking to see if a // wrapper name has been written into the shared memory from MicroDLL unsigned int uTimeout = 500; while (smGet("ActivePlugins", NULL, 0) == 0 && uTimeout > 0) { uTimeout--; osSleep(10); } if (uTimeout > 0) { SendHTMLResponse(requestID, "<html>OK</html>", pClientSocket); } else { Log(logWARNING, "The server has timed out while trying to receive the current active plugins\n"); gtASCIIString strErrorResponse; strErrorResponse = "<html>The server is taking a while to respond. <p/>Either the application does not use one of the selected APIs or it takes a while to load.<p/><br/>"; strErrorResponse.appendFormattedString("Please <a href='/page/index.html'>try to reconnect</a> if you expect it to continue or<br/> <a href='/%d/Kill'>click here to kill the process</a></html>", m_injectedAppID); SendHTMLResponse(requestID, strErrorResponse.asCharArray(), pClientSocket); } } else { Log(logERROR, "The plugins could not be written to shared memory or the application could not be launched\n"); SendTextResponse(requestID, "Error, see log file for more details", pClientSocket); } return; }
// execute a command with a DOS command processor; see CPEXEC_xxx for return values int CConsolePipe::Execute(LPCTSTR pszCommand) { assert(pszCommand && *pszCommand); // for (running) reusable command processors, send this as another input if(m_hListenerThread) { if(CPF_REUSECMDPROC & m_dwFlags) { TString strCmd(pszCommand); assert(strCmd.find(_T('\n')) == TString::npos); strCmd += _T("\r\n"); /* WINDOWS APPLICATIONS * If one tries to launch a windows proggy (e.g. notepad) most of the time nowt * happens first time round. If a second newline is keyed then the window appears. * I have checked with the task manager and sure enough the process exist from the * first time, only it is invisible! I haven't got a clue why this happens; perhaps * it's the SW_HIDE passed in the original CreateProcess, but that is required @@@ */ SendChildInput(strCmd.c_str()); return CPEXEC_OK; // can't tell if it is busy... // moreover, if cmd is busy with a proggy that accepts input, our command will be lost } } assert(NULL == m_hChildProcess); assert(INVALID_HANDLE_VALUE == m_hInputWrite); assert(INVALID_HANDLE_VALUE == m_hOutputRead); if(m_hListenerThread) return CPEXEC_MISC_ERROR; if(pszCommand==0 || *pszCommand == 0) return CPEXEC_COMMAND_ERROR; // for 9x we need a console for THIS process to be inherited by the child // this circumvents the ugly stub processes recommended by Q150956 // ADDENDUM: ok for NT too in the end, since I want to be able to send Ctrl-C events if(!IsConsoleAttached()) { if(!SetupConsole()) { #ifdef _DEBUG ATLTRACE(_T("MINI-assert: can't create console window\n")); #endif return CPEXEC_MISC_ERROR; } } // execution with redirection follows guidelines from: // Q190351 - HOWTO: Spawn Console Processes with Redirected Standard Handles HANDLE loadzaHandles[5]; // for EZ cleanup int i; for(i = 0; i < sizeof(loadzaHandles)/sizeof(loadzaHandles[0]); i++) loadzaHandles[i] = INVALID_HANDLE_VALUE; #if 0 // that's the array correspondence, in order HANDLE hOutputReadTmp, hOutputWrite; HANDLE hInputWriteTmp, hInputRead; HANDLE hErrorWrite; #endif SECURITY_ATTRIBUTES sa; // Set up the security attributes struct. sa.nLength = sizeof(SECURITY_ATTRIBUTES); sa.lpSecurityDescriptor = NULL; sa.bInheritHandle = TRUE; int status; HANDLE hProc = GetCurrentProcess(); // Create the child output pipe, default buffer size if(CreatePipe(&loadzaHandles[0], &loadzaHandles[1], &sa, 0) && // Create a duplicate of the output write handle for the std error // write handle. This is necessary in case the child application // closes one of its std output handles. (you don't say! :) DuplicateHandle(hProc, loadzaHandles[1], hProc, &loadzaHandles[4], 0, TRUE, DUPLICATE_SAME_ACCESS) && // Create the child input pipe. CreatePipe(&loadzaHandles[3], &loadzaHandles[2], &sa, 0) && // Create new output read handle and the input write handles. Set // the Properties to FALSE. Otherwise, the child inherits the // properties and, as a result, non-closeable handles to the pipes // are created. DuplicateHandle(hProc, loadzaHandles[0], hProc, &m_hOutputRead, // Address of new handle. 0, FALSE, // Make it uninheritable. DUPLICATE_SAME_ACCESS) && DuplicateHandle(hProc, loadzaHandles[2], hProc, &m_hInputWrite, // Address of new handle. 0, FALSE, // Make it uninheritable. DUPLICATE_SAME_ACCESS)) { // Close inheritable copies of the handles you do not want to be inherited. CloseHandle(loadzaHandles[0]); loadzaHandles[0] = INVALID_HANDLE_VALUE; CloseHandle(loadzaHandles[2]); loadzaHandles[2] = INVALID_HANDLE_VALUE; if(LaunchRedirected(pszCommand, loadzaHandles[1], loadzaHandles[3], loadzaHandles[4])) { // Close pipe handles (do not continue to modify the parent). // You need to make sure that no handles to the write end of the // output pipe are maintained in this process or else the pipe will // not close when the child process exits and the ReadFile will hang. for(i = 0; i < sizeof(loadzaHandles)/sizeof(loadzaHandles[0]); i++) { if(loadzaHandles[i] != INVALID_HANDLE_VALUE) { CloseHandle(loadzaHandles[i]); loadzaHandles[i] = INVALID_HANDLE_VALUE; } } // now all's left are the handles to the pipe ends we use for communication // i.e. m_hOutputRead (receive stdout) & m_hInputWrite (specify stdin) // create thread that monitors for printfs // since it don't uses CRT, a plain creation is sufficient DWORD ThreadId; m_hListenerThread = ::CreateThread(NULL, 0, ListenerThreadProc, (LPVOID)this, 0, &ThreadId); if(m_hListenerThread) status = CPEXEC_OK; else status = CPEXEC_MISC_ERROR; // rare } else status = CPEXEC_COMMAND_ERROR; } else status = CPEXEC_MISC_ERROR; // cleanup in case of errors for(i = 0; i < sizeof(loadzaHandles)/sizeof(loadzaHandles[0]); i++) { if(loadzaHandles[i] != INVALID_HANDLE_VALUE) CloseHandle(loadzaHandles[i]); } if(CPEXEC_OK != status) { #ifdef _DEBUG ATLTRACE(_T("MINI-assert: can't launch redirected child (%d)\n"), status); #endif assert(!m_hListenerThread); Cleanup(); // now this object is ready for another Execute() attempt or destruction } // if this didn't succeed, clients should delete this object // for CPEXEC_MISC_ERROR try a non-posh alternative like CreateProcess/ShellExecute return status; }
int main(int /*argc*/, char** /*argv*/) { char cmd[256]; std::vector<std::string> availableModules = GetExampleModules(); /* module path -> lib handle */ std::map<std::string, SharedLibrary> libraryHandles; SharedLibrary sharedLib(LIB_PATH, ""); std::cout << "> "; while(std::cin.getline(cmd, sizeof(cmd))) { std::string strCmd(cmd); if (strCmd == "q") { break; } else if (strCmd == "h") { std::cout << std::left << std::setw(15) << "h" << " This help text\n" << std::setw(15) << "l <id | name>" << " Load the module with id <id> or name <name>\n" << std::setw(15) << "u <id>" << " Unload the module with id <id>\n" << std::setw(15) << "s" << " Print status information\n" << std::setw(15) << "q" << " Quit\n" << std::flush; } else if (strCmd.find("l ") != std::string::npos) { std::string idOrName; idOrName.assign(strCmd.begin()+2, strCmd.end()); std::stringstream ss(idOrName); long int id = -1; ss >> id; if (id > 0) { Module* module = ModuleRegistry::GetModule(id); if (!module) { std::cout << "Error: unknown id" << std::endl; } else if (module->IsLoaded()) { std::cout << "Info: module already loaded" << std::endl; } else { try { std::map<std::string, SharedLibrary>::iterator libIter = libraryHandles.find(module->GetLocation()); if (libIter != libraryHandles.end()) { libIter->second.Load(); } else { // The module has been loaded previously due to a // linker dependency SharedLibrary libHandle(module->GetLocation()); libHandle.Load(); libraryHandles.insert(std::make_pair(libHandle.GetFilePath(), libHandle)); } } catch (const std::exception& e) { std::cout << e.what() << std::endl; } } } else { Module* module = ModuleRegistry::GetModule(idOrName); if (!module) { try { std::map<std::string, SharedLibrary>::iterator libIter = libraryHandles.find(sharedLib.GetFilePath(idOrName)); if (libIter != libraryHandles.end()) { libIter->second.Load(); } else { bool libFound = false; for (std::vector<std::string>::const_iterator availableModuleIter = availableModules.begin(); availableModuleIter != availableModules.end(); ++availableModuleIter) { if (*availableModuleIter == idOrName) { libFound = true; } } if (!libFound) { std::cout << "Error: unknown example module" << std::endl; } else { SharedLibrary libHandle(LIB_PATH, idOrName); libHandle.Load(); libraryHandles.insert(std::make_pair(libHandle.GetFilePath(), libHandle)); } } std::vector<Module*> modules = ModuleRegistry::GetModules(); for (std::vector<Module*>::const_iterator moduleIter = modules.begin(); moduleIter != modules.end(); ++moduleIter) { availableModules.erase(std::remove(availableModules.begin(), availableModules.end(), (*moduleIter)->GetName()), availableModules.end()); } } catch (const std::exception& e) { std::cout << e.what() << std::endl; } } else if (!module->IsLoaded()) { try { const std::string modulePath = module->GetLocation(); std::map<std::string, SharedLibrary>::iterator libIter = libraryHandles.find(modulePath); if (libIter != libraryHandles.end()) { libIter->second.Load(); } else { SharedLibrary libHandle(LIB_PATH, idOrName); libHandle.Load(); libraryHandles.insert(std::make_pair(libHandle.GetFilePath(), libHandle)); } } catch (const std::exception& e) { std::cout << e.what() << std::endl; } } else if (module) { std::cout << "Info: module already loaded" << std::endl; } } } else if (strCmd.find("u ") != std::string::npos)
bool CSubprocess::CreateProcess(LPCTSTR pszCmdline) { STARTUPINFO si; // For CreateProcess call HANDLE hrPipe,hwPipe,hwPipe2,m_hrPipeTemp,m_hwPipeTemp; // Create the anonymous pipe SECURITY_ATTRIBUTES saPipe; // Security for anonymous pipe saPipe.nLength = sizeof(SECURITY_ATTRIBUTES); saPipe.lpSecurityDescriptor = NULL; saPipe.bInheritHandle = true; ::CreatePipe(&m_hrPipeTemp,&hwPipe,&saPipe,10240); // In most cases you can get away with using the same anonymous // pipe write handle for both the child's standard output and // standard error, but this may cause problems if the child app // explicitly closes one of its standard output or error handles. If // that happens, the anonymous pipe will close, since the child's // standard output and error handles are really the same handle. The // child won't be able to write to the other write handle since the // pipe is now gone, and parent reads from the pipe will return // ERROR_BROKEN_PIPE and child output will be lost. To solve this // problem, simply duplicate the write end of the pipe to create // another distinct, separate handle to the write end of the pipe. // One pipe write handle will serve as standard out, the other as // standard error. Now *both* write handles must be closed before the // write end of the pipe actually closes. ::DuplicateHandle(::GetCurrentProcess(), // Source process hwPipe, // Handle to duplicate ::GetCurrentProcess(), // Destination process &hwPipe2, // New handle, used as stderr by child 0, // New access flags - ignored since DUPLICATE_SAME_ACCESS true, // It's inheritable DUPLICATE_SAME_ACCESS); ::CreatePipe(&hrPipe,&m_hwPipeTemp,&saPipe,10240); // Create new output read handle and the input write handles, setting // the Properties to FALSE. Otherwise, the child inherits the // properties and, as a result, non-closeable handles to the pipes // are created. DuplicateHandle(GetCurrentProcess(),m_hrPipeTemp, GetCurrentProcess(), &m_hrPipe, // Address of new handle. 0,FALSE, // Make it uninheritable. DUPLICATE_SAME_ACCESS); DuplicateHandle(GetCurrentProcess(),m_hwPipeTemp, GetCurrentProcess(), &m_hwPipe, // Address of new handle. 0,FALSE, // Make it uninheritable. DUPLICATE_SAME_ACCESS); // Close inheritable copies of the handles we do not want to be inherited: CloseHandle(m_hrPipeTemp); CloseHandle(m_hwPipeTemp); memset(&si, 0, sizeof(si)); si.cb = sizeof(si); si.hStdOutput = hwPipe; si.hStdError = hwPipe2; si.hStdInput = hrPipe; si.dwFlags = STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW; si.wShowWindow = SW_SHOW; LPCTSTR pszDir; if(m_strDir.empty()){ pszDir=NULL; // current directory } else { pszDir=m_strDir; } PROCESS_INFORMATION pi; String strCmd(pszCmdline); String strOrigpath; if(!m_strPath.empty()){ int nSize=GetEnvironmentVariable(_T("PATH"), NULL, 0); if(nSize>0){ GetEnvironmentVariable(_T("PATH"),strOrigpath.GetBuffer(nSize),nSize); strOrigpath.ReleaseBuffer(); SetEnvironmentVariable(_T("PATH"),m_strPath); } } bool rc=(TRUE==::CreateProcess(NULL,strCmd.GetBuffer(),NULL,NULL,true,DETACHED_PROCESS|CREATE_NEW_PROCESS_GROUP,NULL,pszDir,&si,&pi)); if(!m_strPath.empty()){ SetEnvironmentVariable(_T("PATH"),strOrigpath); } m_nErr=GetLastError(); strCmd.ReleaseBuffer(); if(rc){ m_idProcess=pi.dwProcessId; m_hProcess=pi.hProcess; if(m_bVerbose){ Output(String::SFormat(_T("*** Process %d created \"%s\"\n"),m_idProcess,pszCmdline)); } TRACE(String::SFormat(_T("Process %d created \"%s\"\n"),m_idProcess,pszCmdline)); m_nExitCode=STILL_ACTIVE; CloseHandle(pi.hThread); } else { m_idProcess=0; if(m_bVerbose){ Output(String::SFormat(_T("*** Failed to create process \"%s\" %s\n"),pszCmdline,(LPCTSTR)ErrorString())); } TRACE(String::SFormat(_T("Failed to create process \"%s\" %s\n"),pszCmdline,(LPCTSTR)ErrorString())); m_nExitCode=GetLastError(); CloseHandle(m_hrPipe);m_hrPipe=INVALID_HANDLE_VALUE; CloseHandle(m_hwPipe);m_hwPipe=INVALID_HANDLE_VALUE; } CloseHandle(hrPipe); CloseHandle(hwPipe); CloseHandle(hwPipe2); return rc; }