// // pszCmd should be less than 1024 bytes. // U32 CProcessUtil_i::RunSilentProcess(LPCTSTR pszCmd, LPCTSTR pAppCmd, DWORD dwTimeOut) { HANDLE hProcess = 0; HANDLE hThread = 0; STARTUPINFO si; PROCESS_INFORMATION pi; TCHAR szCmd[1024] = {0,}; if(pszCmd) { lstrcpyn(szCmd, pszCmd, sizeof(szCmd)-1); } ZeroMemory( &si, sizeof(si) ); si.cb = sizeof(si); //si.cb = sizeof(STARTUPINFO); //si.dwFlags = STARTF_USESTDHANDLES|STARTF_USESHOWWINDOW; si.hStdOutput = NULL; si.hStdInput = NULL; si.hStdError = NULL; // Use this if you want to show the child. si.wShowWindow = SW_HIDE; ZeroMemory( &pi, sizeof(pi) ); //SetCurrentDirectory(pszCurPath); //WinExec(pszCmd, SW_SHOW); //return FALSE; // Start the child process. if( !CreateProcess(pAppCmd , // the app line szCmd, // "C:\\pclint\\tst.bat" Command line. , bat or cmd.exe /k .... NULL, // Process handle not inheritable. NULL, // Thread handle not inheritable. FALSE, // Set handle inheritance to FALSE. CREATE_NO_WINDOW, // creation flags.CREATE_NEW_CONSOLE CREATE_NO_WINDOW NULL, // Use parent's environment block. NULL, // Use parent's starting directory. &si, // Pointer to STARTUPINFO structure. &pi ) // Pointer to PROCESS_INFORMATION structure. ) { return ERR_WIN32_ERROR_I; } hProcess = pi.hProcess; hThread = pi.hThread; if (hProcess == NULL) { OutputDbgStr(_T("Error: Internal error. \n")); return ERR_WIN32_ERROR_I; } else { switch (::WaitForSingleObject(hProcess, dwTimeOut)) // WaitForSingleObject( pi.hProcess, ); { case WAIT_OBJECT_0: break; case WAIT_TIMEOUT: break; default: break; } } DWORD dwExitCode = 0; GetExitCodeProcess(hProcess, &dwExitCode); // Close process and thread handles. CloseHandle( hProcess ); CloseHandle( hThread ); return dwExitCode; }
int APIENTRY _tWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCmdLine, int nCmdShow) #endif { hInst = hInstance; isWin64 = IsWindows64(); GetVersionEx(&gOSVer); int nInstallVer = 0; wsprintf(gsTitle, L"ConEmu %s installer", CONEMUVERL); lstrcpyn(gsRunAsAdm, L"Run installer as administrator", countof(gsRunAsAdm)); wchar_t szArg[MAX_PATH+1]; LPCWSTR pszCmdToken = GetCommandLine(); LPCWSTR pszCmdLineW = pszCmdToken; gsTempFolder[0] = 0; while (0 == NextArg(&pszCmdToken, szArg)) { if (lstrcmp(szArg, L"/?") == 0 || lstrcmp(szArg, L"-?") == 0 || lstrcmp(szArg, L"-h") == 0 || lstrcmp(szArg, L"-help") == 0 || lstrcmp(szArg, L"--help") == 0) { MessageBox(NULL, L"Usage:\n" L" ConEmuSetup [/p:x86[,adm] | /p:x64[,adm]] [<msi args>]\n" L" ConEmuSetup [/e[:<extract path>]] [/p:x86 | /p:x64]\n" L"Example (run x64 auto update as administrator):\n" L" ConEmuSetup /p:x64,adm /qr", gsTitle, MB_ICONINFORMATION); return 1; } if (*szArg == L'/') { if (szArg[1] == L'e' || szArg[1] == L'E') { gbExtractOnly = true; if (szArg[2] == L':' && szArg[3]) { lstrcpyn(gsTempFolder, (szArg[3]==L'"') ? (szArg+4) : (szArg+3), countof(gsTempFolder)); } continue; } if (memcmp(szArg, L"/p:x", 4*sizeof(*szArg)) == 0) { gbAlreadyAdmin = IsUserAdmin(); if (lstrcmpi(szArg+4, L"86") == 0) { nInstallVer = Ver86; } else if (lstrcmpi(szArg+4, L"86,adm") == 0) { nInstallVer = Ver86; gbUseElevation = !gbAlreadyAdmin; } else if (lstrcmpi(szArg+4, L"64") == 0) { nInstallVer = Ver64; } else if (lstrcmpi(szArg+4, L"64,adm") == 0) { nInstallVer = Ver64; gbUseElevation = !gbAlreadyAdmin; } } else pszCmdToken = pszCmdLineW; break; } else if (*szArg == L'-') { pszCmdToken = pszCmdLineW; break; } pszCmdLineW = pszCmdToken; } if (!gbExtractOnly) { wchar_t szInstallPath[MAX_PATH+32]; bool bInstalled; HKEY hk; lstrcpyn(gsMessage, L"Choose version to install", countof(gsMessage)); szInstallPath[0] = 0; bInstalled = false; struct {HKEY hk; LPCWSTR path; LPCWSTR name; bool our;} Keys[] = { {HKEY_LOCAL_MACHINE,L"SOFTWARE\\ConEmu",L"InstallDir",true}, {HKEY_LOCAL_MACHINE,L"SOFTWARE\\Far Manager",L"InstallDir"}, {HKEY_LOCAL_MACHINE,L"SOFTWARE\\Far2",L"InstallDir"}, {HKEY_LOCAL_MACHINE,L"SOFTWARE\\Far",L"InstallDir"}, }; for (size_t s = 0; s < countof(Keys); s++) { if (!RegOpenKeyEx(Keys[s].hk, Keys[s].path, 0, KEY_READ, &hk) || !RegOpenKeyEx(Keys[s].hk, Keys[s].path, 0, KEY_READ|KEY_WOW64_32KEY, &hk)) { wchar_t szPath[MAX_PATH+1] = {}; DWORD cbSize = sizeof(szPath)-2; LONG lRc = RegQueryValueEx(hk, Keys[s].name, NULL, NULL, (LPBYTE)szPath, &cbSize); RegCloseKey(hk); if (!lRc && *szPath) { bInstalled = Keys[s].our; lstrcpy(szInstallPath, szPath); cbSize = lstrlen(szInstallPath); if (szInstallPath[cbSize-1] == L'\\') szInstallPath[cbSize-1] = 0; break; } } } if (szInstallPath[0] == 0) { GetEnvironmentVariable(L"ProgramFiles", szInstallPath, MAX_PATH); int nLen = lstrlen(szInstallPath); lstrcat(szInstallPath, (nLen > 0 && szInstallPath[nLen-1] != L'\\') ? L"\\ConEmu" : L"ConEmu"); } wsprintf(gsVer86, L"%s x86\n%s installation folder is\n%s", CONEMUVERL, bInstalled ? L"Current" : L"Default", szInstallPath); if (isWin64) { szInstallPath[0] = 0; bInstalled = false; struct {HKEY hk; LPCWSTR path; LPCWSTR name; bool our;} Keys[] = { {HKEY_LOCAL_MACHINE,L"SOFTWARE\\ConEmu",L"InstallDir_x64",true}, {HKEY_LOCAL_MACHINE,L"SOFTWARE\\Far Manager",L"InstallDir_x64"}, {HKEY_LOCAL_MACHINE,L"SOFTWARE\\Far2",L"InstallDir_x64"}, {HKEY_LOCAL_MACHINE,L"SOFTWARE\\Far",L"InstallDir_x64"}, }; for (size_t s = 0; s < countof(Keys); s++) { if (!RegOpenKeyEx(Keys[s].hk, Keys[s].path, 0, KEY_READ|KEY_WOW64_64KEY, &hk)) { wchar_t szPath[MAX_PATH+1] = {}; DWORD cbSize = sizeof(szPath)-2; LONG lRc = RegQueryValueEx(hk, Keys[s].name, NULL, NULL, (LPBYTE)szPath, &cbSize); RegCloseKey(hk); if (!lRc && *szPath) { bInstalled = Keys[s].our; lstrcpy(szInstallPath, szPath); cbSize = lstrlen(szInstallPath); if (szInstallPath[cbSize-1] == L'\\') szInstallPath[cbSize-1] = 0; break; } } } if (szInstallPath[0] == 0) { GetEnvironmentVariable(L"ProgramW6432", szInstallPath, MAX_PATH); int nLen = lstrlen(szInstallPath); lstrcat(szInstallPath, (nLen > 0 && szInstallPath[nLen-1] != L'\\') ? L"\\ConEmu" : L"ConEmu"); } wsprintf(gsVer64, L"%s x64\n%s installation folder is\n%s", CONEMUVERL, bInstalled ? L"Current" : L"Default", szInstallPath); wsprintf(gsFull, L"%s\n\nPress `Yes` to install x64 version\nPress `No` to install x86 version", gsMessage); } else { gsVer64[0] = 0; } } else { wchar_t szPath[MAX_PATH+1]; if (*gsTempFolder) { lstrcpy(szPath, gsTempFolder); } else { GetTempPath(countof(szPath) - 14, szPath); wchar_t* pszSubDir = szPath+lstrlen(szPath); lstrcpy(pszSubDir, L"ConEmu"); pszSubDir += 6; lstrcpy(pszSubDir, CONEMUVERL); } lstrcpyn(gsMessage, L"Choose version to extract", countof(gsMessage)); wsprintf(gsVer86, L"%s x86\nExtract installation files to\n%s", CONEMUVERL, szPath); wsprintf(gsVer64, L"%s x64\nExtract installation files to\n%s", CONEMUVERL, szPath); wsprintf(gsFull, L"%s\n\nPress `Yes` to extract x64 version\nPress `No` to extract x86 version\n\n%s", gsMessage, szPath); } if (nInstallVer == 0) nInstallVer = ChooseVersion(); // IDCANCEL/Ver86/Ver64 if (nInstallVer != Ver86 && nInstallVer != Ver64) return 1; if (gbExtractOnly && *gsTempFolder) { CreateDirectory(gsTempFolder, NULL); } else { GetTempPath(countof(gsTempFolder) - 14, gsTempFolder); wchar_t* pszSubDir = gsTempFolder+lstrlen(gsTempFolder); lstrcpy(pszSubDir, L"ConEmu"); pszSubDir += 6; lstrcpy(pszSubDir, CONEMUVERL); pszSubDir += lstrlen(pszSubDir); if (!CreateDirectory(gsTempFolder, NULL)) { bool lbCreated = false; SYSTEMTIME st = {}; GetLocalTime(&st); for (int i = 0; i < 100; i++) { wsprintf(pszSubDir, L"_%02i%02i%02i%i", st.wHour, st.wMinute, st.wSecond, i); if (CreateDirectory(gsTempFolder, NULL)) { lbCreated = true; break; } } if (!lbCreated) { return ReportError(10, L"Can't create temp folder\n%s", gsTempFolder); } } } wsprintf(gsMsiFile, L"%s\\ConEmu.%s.%s.msi", gsTempFolder, CONEMUVERL, (nInstallVer == Ver86) ? L"x86" : L"x64"); wsprintf(gsCabFile, L"%s\\ConEmu.cab", gsTempFolder); bool lbNeedExe = false; if (!gbExtractOnly && gOSVer.dwMajorVersion >= 6) lbNeedExe = true; if (!lbNeedExe) gsExeFile[0] = 0; else wsprintf(gsExeFile, L"%s\\ConEmuSetup.exe", gsTempFolder); int iExpMsi = ExportFile(nInstallVer, gsMsiFile); int iExpCab = (iExpMsi == 0) ? ExportFile(CABFILE, gsCabFile) : -1; int iExpExe = (!lbNeedExe) ? 0 : (iExpCab == 0) ? ExportFile(EXEFILE, gsExeFile) : -1; if (iExpMsi != 0 || iExpCab != 0 || iExpExe != 0) { DeleteFile(gsMsiFile); DeleteFile(gsCabFile); if (*gsExeFile) DeleteFile(gsExeFile); RemoveDirectory(gsTempFolder); return (iExpMsi != 0) ? iExpMsi : iExpCab; } if (gbExtractOnly) { wchar_t szMessage[MAX_PATH*2]; wsprintf(szMessage, L"Installation files was extracted successfully\n%s", gsTempFolder); MessageBox(NULL, szMessage, gsTitle, MB_ICONINFORMATION); return 0; } int iInstRc = 0; SHELLEXECUTEINFO sei = {sizeof(sei)}; wchar_t* pszParms = NULL; sei.fMask = SEE_MASK_NOCLOSEPROCESS|/*SEE_MASK_NOASYNC*/0x00000100; //|/*SEE_MASK_NOZONECHECKS*/0x00800000; sei.lpVerb = L"open"; if (gOSVer.dwMajorVersion<=5 || !gbUseElevation) { sei.lpFile = gsMsiFile; sei.lpParameters = pszCmdToken; } else { sei.lpFile = gsExeFile; int nMaxLen = lstrlen(gsMsiFile) + (pszCmdToken ? lstrlen(pszCmdToken) : 0) + 64; pszParms = (wchar_t*)malloc(nMaxLen*sizeof(wchar_t)); wsprintf(pszParms, L"/i \"%s\" %s", gsMsiFile, pszCmdToken ? pszCmdToken : L""); sei.lpParameters = pszParms; } sei.lpDirectory = gsTempFolder; sei.nShow = SW_SHOWNORMAL; BOOL lbExecute = ShellExecuteEx(&sei); #if 0 if (!lbExecute && lbNeedExe) { DWORD nErr = GetLastError(); if (nErr == 1223) { // Отмена пользователем UAC, или правов не хватило? sei.fMask = SEE_MASK_NOCLOSEPROCESS|/*SEE_MASK_NOASYNC*/0x00000100; //|/*SEE_MASK_NOZONECHECKS*/0x00800000; sei.lpVerb = L"open"; sei.lpFile = gsMsiFile; sei.lpParameters = pszCmdToken; sei.lpDirectory = gsTempFolder; sei.nShow = SW_SHOWNORMAL; lbExecute = ShellExecuteEx(&sei); } } #endif if (!lbExecute) { iInstRc = ReportError(20, L"Installer failed\n%s", gsMsiFile); } else { if (!sei.hProcess) { iInstRc = ReportError(21, L"Installer failed\n%s", gsMsiFile); } else { WaitForSingleObject(sei.hProcess, INFINITE); DWORD nCode = 0; SetLastError(0); //1602 - это похоже "Отмена" пользователем if (!GetExitCodeProcess(sei.hProcess, &nCode) || (nCode != 0 && nCode != 1602)) { wchar_t szFormat[128]; wsprintf(szFormat, L"Installer failed\n%%s\nExitCode=%u", nCode); iInstRc = ReportError(100+nCode, szFormat, gsMsiFile); } } } DeleteFile(gsMsiFile); DeleteFile(gsCabFile); if (*gsExeFile) DeleteFile(gsExeFile); RemoveDirectory(gsTempFolder); return iInstRc; }
BOOL GetExitCode( DWORD* pdwExitCode ) { return GetExitCodeProcess( ph, pdwExitCode ); }
/* * Wrapper for fclose() to use for popen* files, so we can retrieve the * exit code for the child process and return as a result of the close. * * This function uses the _PyPopenProcs dictionary in order to map the * input file pointer to information about the process that was * originally created by the popen* call that created the file pointer. * The dictionary uses the file pointer as a key (with one entry * inserted for each file returned by the original popen* call) and a * single list object as the value for all files from a single call. * The list object contains the Win32 process handle at [0], and a file * count at [1], which is initialized to the total number of file * handles using that list. * * This function closes whichever handle it is passed, and decrements * the file count in the dictionary for the process handle pointed to * by this file. On the last close (when the file count reaches zero), * this function will wait for the child process and then return its * exit code as the result of the close() operation. This permits the * files to be closed in any order - it is always the close() of the * final handle that will return the exit code. */ static int _PyPclose(FILE *file) { int result; DWORD exit_code; HANDLE hProcess; PyObject *procObj, *hProcessObj, *intObj, *fileObj; long file_count; /* Close the file handle first, to ensure it can't block the * child from exiting if it's the last handle. */ result = fclose(file); if (_PyPopenProcs) { CEnterLeavePython _celp; if ((fileObj = PyLong_FromVoidPtr(file)) != NULL && (procObj = PyDict_GetItem(_PyPopenProcs, fileObj)) != NULL && (hProcessObj = PyList_GetItem(procObj,0)) != NULL && (intObj = PyList_GetItem(procObj,1)) != NULL) { hProcess = PyLong_AsVoidPtr(hProcessObj); file_count = PyInt_AsLong(intObj); if (file_count > 1) { /* Still other files referencing process */ file_count--; PyList_SetItem(procObj,1, PyInt_FromLong(file_count)); } else { Py_BEGIN_ALLOW_THREADS /* Last file for this process */ if (result != EOF && WaitForSingleObject(hProcess, INFINITE) != WAIT_FAILED && GetExitCodeProcess(hProcess, &exit_code)) { /* Possible truncation here in 16-bit environments, but * real exit codes are just the lower byte in any event. */ result = exit_code; } else { /* Indicate failure - this will cause the file object * to raise an I/O error and translate the last Win32 * error code from errno. We do have a problem with * last errors that overlap the normal errno table, * but that's a consistent problem with the file object. */ if (result != EOF) { /* If the error wasn't from the fclose(), then * set errno for the file object error handling. */ errno = GetLastError(); } result = -1; } /* Free up the native handle at this point */ CloseHandle(hProcess); Py_END_ALLOW_THREADS } /* Remove this file pointer from dictionary */ PyDict_DelItem(_PyPopenProcs, fileObj); if (PyDict_Size(_PyPopenProcs) == 0) { Py_DECREF(_PyPopenProcs); _PyPopenProcs = NULL; } } /* if object retrieval ok */ Py_XDECREF(fileObj); } /* if _PyPopenProcs */
bool processIsStillRunning(HANDLE hndl) { DWORD exitCode = 0; GetExitCodeProcess(hndl, &exitCode); return (exitCode==STILL_ACTIVE); }
DWORD JobbedProcessManager::return_code() { DWORD out; if (!GetExitCodeProcess(hProcess, &out)) throw WindowsException("GetExitCodeProcess"); return out; }
int nt_execve(const char *prog, const char *const *args, const char *const *envir) { STARTUPINFO si; PROCESS_INFORMATION pi; enum {none, directex, shellex} execmode; DWORD exitcode; DWORD dwCreationflags; int priority; char *argv0; char *cmdstr, *cmdend; unsigned int cmdsize; size_t prognamelen, cmdlen; int hasext; char extension[_MAX_FNAME]; const char *begin, *end, *extptr; static char exts[MAX_PATH]; UNREFERENCED_PARAMETER(envir); /* get default PATHEXT or use empty exts */ if (!*exts) { DWORD rc; /* not initialized */ rc = GetEnvironmentVariable("PATHEXT", exts, sizeof(exts)); if ((rc == 0) || (rc >= sizeof(exts))) /* if error or PATHEXT too big will retry at the next call */ *exts = 0; } /* if prog has an extension initialize begin end to skip PATHEXT search */ prognamelen = strlen(prog); extptr = prog + prognamelen - 1; hasext = 0; while (extptr > prog && !ISPATHSEP(*extptr)) { if (*extptr == '.' && *(extptr - 1) != ':' && !ISPATHSEP(*(extptr - 1))) { hasext++; break; } extptr--; } if (hasext) { begin = "."; end = ""; strcpy(extension, extptr); } else { begin = exts; end = exts; *extension = '\0'; } argv0 = (char *)heap_alloc(MAX_PATH); /* (prognamelen + 1) does not really matter, argv0 is '\0' filled */ memcpy(argv0, prog, prognamelen + 1); errno = 0; execmode = none; /* NOTE: loops over PATHEXT if no extension found */ while (*begin) { size_t extlen; if (GetBinaryType(argv0, &exitcode)) { /* exists and is executable NOTE: an "xxx.exe" without a correct PE header (i.e. a text file) has type "DOS binary", but execution will generate a WOW error */ execmode = directex; break; } if (GetLastError() == ERROR_BAD_EXE_FORMAT) { /* exists but is not "executable" */ execmode = shellex; break; } if (hasext) break; /* get next PATHEXT extension */ while (*begin && (*begin != '.')) begin++; while (*end && (*end != ';')) end++; if (!*begin) break; extlen = end - begin; if (extlen < sizeof(extension)) { memcpy(extension, begin, extlen); extension[extlen] = '\0'; /* prognamelen ignores the last '\r' if present */ memcpy(argv0, prog, prognamelen); /* update argv0 adding the extension to prog */ memcpy(argv0 + prognamelen, extension, extlen + 1); } begin = end; /* skip sequences of ';' */ while (*end && *end == ';') end++; }; cmdstr = (char *)heap_alloc(MAX_PATH << 2); cmdsize = MAX_PATH << 2; cmdlen = 0; cmdend = cmdstr; dbgprintf(PR_VERBOSE, "%s(): execute [%s] extension=[%s] mode=%d hasext=%d\n", __FUNCTION__, argv0, extension, execmode, hasext); /* skip over program name */ args++; /* the file (after PATHEXT search) exists, but it's not "executable" */ if (execmode == shellex) { /* if prog had no extension or has the extension associated to shell scripts */ if ((hasext == 0 && *extension == '\0') || is_shell_script(extension)) { int res = process_shebang(argv0, (const char *const *)&cmdstr, &cmdlen, &cmdend, &cmdsize); if (res < 0) { execmode = none; } else if (res == 0) { char *newargv[2]; cmdlen = copy_quote_and_fix_slashes(gModuleName, cmdstr); cmdend = cmdstr + cmdlen; newargv[0] = path_to_slash(argv0); newargv[1] = NULL; concat_args_and_quote((const char *const *)newargv, &cmdstr, &cmdlen, &cmdend, &cmdsize); *cmdend = 0; argv0 = gModuleName; execmode = directex; } else { cmdend = cmdstr + cmdlen; execmode = directex; } } else { unsigned long shflags = 0L; /* if the file extension is in pathext, use the same console and wait for child. StrStrI() is from shlwapi */ if (StrStrI(exts, extension)) shflags = SEE_MASK_NO_CONSOLE | SEE_MASK_NOCLOSEPROCESS; if (try_shell_ex(argv0, args, shflags, &cmdstr, &cmdsize)) return (0); /* ShellExecute failed, the file has an unknown extension, but it may be a shell script with a shebang */ if (process_shebang(argv0, (const char *const *)&cmdstr, &cmdlen, &cmdend, &cmdsize) > 0) { cmdend = cmdstr + cmdlen; execmode = directex; } else { /* the file extension is NOT known and the file has NO shebang: returns EPERM, see NOTES */ errno = EPERM; return (-1); } } } else if (execmode == directex) { cmdlen = copy_quote_and_fix_slashes(prog, cmdstr); cmdend = cmdstr + cmdlen; } if (execmode == none) { /* error: prog not found even after trying PATHEXT extensions */ errno = ENOENT; return (-1); } concat_args_and_quote(args, &cmdstr, &cmdlen, &cmdend, &cmdsize); if (*cmdstr == ' ') { /* if we left a ' ' for the quote and there is no quote */ cmdstr++; cmdlen--; } *cmdend = 0; init_startupinfo(&si); dwCreationflags = GetPriorityClass(GetCurrentProcess()); priority = GetThreadPriority(GetCurrentThread()); #if defined(W32DEBUG) /* DebugView output is very difficult to read with overlong lines */ if (cmdlen < 128) dbgprintf(PR_EXEC, "%s(): CreateProcess(%s, ..) cmdstr=[%s]\n", __FUNCTION__, argv0, cmdstr); else { char shortbuf[128+4]; memcpy(shortbuf, cmdstr, 128); memcpy(shortbuf + 128, "...", 4); dbgprintf(PR_EXEC, "nt_execve(): CreateProcess(%s, ..) cmdstr=[%s]\n", argv0, shortbuf); } #endif if (!CreateProcess(argv0, cmdstr, NULL, NULL, TRUE, // need this for redirecting std handles dwCreationflags | CREATE_SUSPENDED, NULL, NULL, &si, &pi)) { exitcode = GetLastError(); if (exitcode == ERROR_BAD_EXE_FORMAT) { dbgprintf(PR_ERROR, "!!! CreateProcess(%s, ..) error BAD_EXE_FORMAT in %s\n", argv0, __FUNCTION__); errno = ENOEXEC; } else if (exitcode == ERROR_INVALID_PARAMETER) { dbgprintf(PR_ERROR, "!!! CreateProcess(%s, ..) error INVALID_PARAMETER in %s, cmdstr len=%u\n", argv0, __FUNCTION__, strlen(cmdstr)); /* exceeded command line */ /* return NOT found, ENAMETOOLONG is correct but not understood by the shell that will retry with another path ... */ errno = ENOENT; } else { dbgprintf(PR_ERROR, "!!! CreateProcess(%s, ..) error %ld in %s\n", argv0, exitcode, __FUNCTION__); errno = ENOENT; } goto fail_return; } else { exitcode = 0; if (!SetThreadPriority(pi.hThread, priority)) dbgprintf(PR_ERROR, "!!! SetThreadPriority(0x%p) failed, error %ld\n", pi.hThread, GetLastError()); ResumeThread(pi.hThread); if (!is_gui(argv0)) { if (WaitForSingleObject(pi.hProcess, INFINITE) != WAIT_OBJECT_0) dbgprintf(PR_ERROR, "!!! error %ld waiting for process %ld\n", GetLastError(), pi.dwProcessId); if (!GetExitCodeProcess(pi.hProcess, &exitcode)) dbgprintf(PR_ERROR, "!!! GetExitCodeProcess(0x%p, ..) error %ld in %s\n", pi.hProcess, GetLastError(), __FUNCTION__); } CloseHandle(pi.hProcess); CloseHandle(pi.hThread); close_si_handles(); /* @@@@ should wait for the clipboard ? if (is_dev_clipboard_active) { CloseHandle((HANDLE)_get_osfhandle(0)); CloseHandle((HANDLE)_get_osfhandle(1)); CloseHandle((HANDLE)_get_osfhandle(2)); ... WaitForSingleObject(ghdevclipthread,60*1000); } */ dbgprintf(PR_ALL, "--- %s(): Exec'd process %ld terminated with exitcode %ld\n", __FUNCTION__, pi.dwProcessId, exitcode); exec_exit((int)exitcode); } fail_return: heap_free(cmdstr); close_si_handles(); exec_exit(-1); return (-1); }
// Launches tests as another process int fork() { DWORD dwExitCode = 1; CString sWorkingFolder; CString sCmdLine; CString sExeFolder; sWorkingFolder = Utility::GetModulePath(NULL); sExeFolder = Utility::GetModulePath(NULL); if(g_bRunningFromUNICODEFolder) { CString sAppDataFolder; Utility::GetSpecialFolder(CSIDL_LOCAL_APPDATA, sAppDataFolder); sWorkingFolder = sAppDataFolder+_T("\\CrashRpt UNICODE 应用程序名称"); BOOL bCreate = Utility::CreateFolder(sWorkingFolder); if(!bCreate) return 1; /* Copy all required files to temporary directory. */ #ifdef _DEBUG BOOL bCopy = CopyFile(sExeFolder+_T("\\CrashRptd.dll"), sWorkingFolder+_T("\\CrashRptd.dll"), TRUE); if(!bCopy) goto cleanup; BOOL bCopy5 = CopyFile(sExeFolder+_T("\\CrashRptProbed.dll"), sWorkingFolder+_T("\\CrashRptProbed.dll"), TRUE); if(!bCopy5) goto cleanup; BOOL bCopy2 = CopyFile(sExeFolder+_T("\\CrashSenderd.exe"), sWorkingFolder+_T("\\CrashSenderd.exe"), TRUE); if(!bCopy2) goto cleanup; BOOL bCopy4 = CopyFile(sExeFolder+_T("\\Testsd.exe"), sWorkingFolder+_T("\\Testsd.exe"), TRUE); if(!bCopy4) goto cleanup; #else #ifndef CRASHRPT_LIB BOOL bCopy = CopyFile(sExeFolder+_T("\\CrashRpt.dll"), sWorkingFolder+_T("\\CrashRpt.dll"), TRUE); if(!bCopy) goto cleanup; BOOL bCopy5 = CopyFile(sExeFolder+_T("\\CrashRptProbe.dll"), sWorkingFolder+_T("\\CrashRptProbe.dll"), TRUE); if(!bCopy5) goto cleanup; #endif //!CRASHRPT_LIB BOOL bCopy2 = CopyFile(sExeFolder+_T("\\CrashSender.exe"), sWorkingFolder+_T("\\CrashSender.exe"), TRUE); if(!bCopy2) goto cleanup; BOOL bCopy4 = CopyFile(sExeFolder+_T("\\Tests.exe"), sWorkingFolder+_T("\\Tests.exe"), TRUE); if(!bCopy4) goto cleanup; #endif BOOL bCopy3 = CopyFile(sExeFolder+_T("\\crashrpt_lang.ini"), sWorkingFolder+_T("\\crashrpt_lang.ini"), TRUE); if(!bCopy3) goto cleanup; BOOL bCopy6 = CopyFile(sExeFolder+_T("\\dummy.ini"), sWorkingFolder+_T("\\dummy.ini"), TRUE); if(!bCopy6) goto cleanup; BOOL bCopy7 = CopyFile(sExeFolder+_T("\\dummy.log"), sWorkingFolder+_T("\\dummy.log"), TRUE); if(!bCopy7) goto cleanup; BOOL bCopy8 = CopyFile(sExeFolder+_T("\\dbghelp.dll"), sWorkingFolder+_T("\\dbghelp.dll"), TRUE); if(!bCopy8) goto cleanup; } /* Create new process */ #ifdef _DEBUG sCmdLine = _T("\"") + sWorkingFolder+_T("\\Testsd.exe") + _T("\""); #else sCmdLine = _T("\"") + sWorkingFolder+_T("\\Tests.exe") + _T("\""); #endif if(g_bRunningFromUNICODEFolder) sCmdLine += _T(" /unicode"); HANDLE hProcess = NULL; STARTUPINFO si; memset(&si, 0, sizeof(STARTUPINFO)); si.cb = sizeof(STARTUPINFO); PROCESS_INFORMATION pi; memset(&pi, 0, sizeof(PROCESS_INFORMATION)); BOOL bCreateProcess = CreateProcess(NULL, sCmdLine.GetBuffer(0), NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi); if(!bCreateProcess) { _tprintf(_T("Error creating process! Press any key to exit.\n.")); _getch(); goto cleanup; } hProcess = pi.hProcess; // Wait until process exits. WaitForSingleObject(hProcess, INFINITE); GetExitCodeProcess(hProcess, &dwExitCode); cleanup: // Clean up if(g_bRunningFromUNICODEFolder) Utility::RecycleFile(sWorkingFolder, TRUE); return dwExitCode; }
// This routine creates a binding with the server. HRESULT JITManager::CreateBinding( __in HANDLE serverProcessHandle, __in_opt void * serverSecurityDescriptor, __in UUID * connectionUuid, __out RPC_BINDING_HANDLE * bindingHandle) { Assert(IsOOPJITEnabled()); RPC_STATUS status; DWORD attemptCount = 0; DWORD sleepInterval = 100; // in milliseconds RPC_BINDING_HANDLE localBindingHandle; RPC_BINDING_HANDLE_TEMPLATE_V1 bindingTemplate; RPC_BINDING_HANDLE_SECURITY_V1_W bindingSecurity; #ifndef NTBUILD RPC_SECURITY_QOS_V4 securityQOS; ZeroMemory(&securityQOS, sizeof(RPC_SECURITY_QOS_V4)); securityQOS.Capabilities = RPC_C_QOS_CAPABILITIES_DEFAULT; securityQOS.IdentityTracking = RPC_C_QOS_IDENTITY_DYNAMIC; securityQOS.ImpersonationType = RPC_C_IMP_LEVEL_IDENTIFY; securityQOS.Version = 4; #else RPC_SECURITY_QOS_V5 securityQOS; ZeroMemory(&securityQOS, sizeof(RPC_SECURITY_QOS_V5)); securityQOS.Capabilities = RPC_C_QOS_CAPABILITIES_DEFAULT; securityQOS.IdentityTracking = RPC_C_QOS_IDENTITY_DYNAMIC; securityQOS.ImpersonationType = RPC_C_IMP_LEVEL_IDENTIFY; securityQOS.Version = 5; securityQOS.ServerSecurityDescriptor = serverSecurityDescriptor; #endif // NTBUILD ZeroMemory(&bindingTemplate, sizeof(bindingTemplate)); bindingTemplate.Version = 1; bindingTemplate.ProtocolSequence = RPC_PROTSEQ_LRPC; bindingTemplate.StringEndpoint = NULL; memcpy_s(&bindingTemplate.ObjectUuid, sizeof(UUID), connectionUuid, sizeof(UUID)); bindingTemplate.Flags |= RPC_BHT_OBJECT_UUID_VALID; ZeroMemory(&bindingSecurity, sizeof(bindingSecurity)); bindingSecurity.Version = 1; bindingSecurity.AuthnLevel = RPC_C_AUTHN_LEVEL_PKT_PRIVACY; bindingSecurity.AuthnSvc = RPC_C_AUTHN_KERNEL; bindingSecurity.SecurityQos = (RPC_SECURITY_QOS*)&securityQOS; status = RpcBindingCreate(&bindingTemplate, &bindingSecurity, NULL, &localBindingHandle); if (status != RPC_S_OK) { return HRESULT_FROM_WIN32(status); } // We keep attempting to connect to the server with increasing wait intervals in between. // This will wait close to 5 minutes before it finally gives up. do { DWORD waitStatus; status = RpcBindingBind(NULL, localBindingHandle, ClientIChakraJIT_v0_0_c_ifspec); if (status == RPC_S_OK) { break; } else if (status == EPT_S_NOT_REGISTERED) { // The Server side has not finished registering the RPC Server yet. // We should only breakout if we have reached the max attempt count. if (attemptCount > 600) { break; } } else { // Some unknown error occurred. We are not going to retry for arbitrary errors. break; } // When we come to this point, it means the server has not finished registration yet. // We should wait for a while and then reattempt to bind. waitStatus = WaitForSingleObject(serverProcessHandle, sleepInterval); if (waitStatus == WAIT_OBJECT_0) { DWORD exitCode = (DWORD)-1; // The server process died for some reason. No need to reattempt. // We use -1 as the exit code if GetExitCodeProcess fails. Assert(GetExitCodeProcess(serverProcessHandle, &exitCode)); status = RPC_S_SERVER_UNAVAILABLE; break; } else if (waitStatus == WAIT_TIMEOUT) { // Not an error. the server is still alive and we should reattempt. } else { // wait operation failed for an unknown reason. Assert(false); status = HRESULT_FROM_WIN32(waitStatus); break; } attemptCount++; if (sleepInterval < 500) { sleepInterval += 100; } } while (status != RPC_S_OK); // redundant check, but compiler would not allow true here. if (status != RPC_S_OK) { RpcBindingFree(&localBindingHandle); return HRESULT_FROM_WIN32(status); } *bindingHandle = localBindingHandle; return S_OK; }
static int try_shell_ex(char *argv0, const char *const *argv, unsigned long shellexflags, char **cmdstr, unsigned int *cmdsize) { char *cmdend; size_t cmdlen; SHELLEXECUTEINFO shinfo; BOOL nocmd = 0; path_to_backslash(argv0); /* @@@@ is this code really needed ? when ? */ if ((!*argv) && (argv0[0] == '\\') && (argv0[1] == '\\')) { shellexflags |= SEE_MASK_CONNECTNETDRV; nocmd = 1; goto noargs; } cmdend = *cmdstr; cmdlen = 0; concat_args_and_quote(argv, cmdstr, &cmdlen, &cmdend, cmdsize); *cmdend = '\0'; noargs: dbgprintf(PR_EXEC, "ShellExecute(%s, ..) with cmdstr [%s]\n", argv0, *cmdstr); memset(&shinfo, 0, sizeof(shinfo)); shinfo.cbSize = sizeof(shinfo); shinfo.fMask = SEE_MASK_FLAG_NO_UI | SEE_MASK_FLAG_DDEWAIT | shellexflags; shinfo.hwnd = NULL; shinfo.lpVerb = NULL; shinfo.lpFile = argv0; shinfo.lpParameters = nocmd ? NULL : *cmdstr; shinfo.lpDirectory = 0; shinfo.nShow = SW_SHOWDEFAULT; if (ShellExecuteEx(&shinfo)) { DWORD retval = 255; dbgprintf(PR_EXEC, "ShellExecute() created process handle 0x%p\n", shinfo.hProcess); /* may happen if "executing" a file associated to a running program, i.e. "execute" a .html file with an already opened browser window */ if (shinfo.hProcess != (HANDLE)0) { if (shellexflags & SEE_MASK_NOCLOSEPROCESS) { if ((intptr_t)(shinfo.hInstApp) > 32) { if (WaitForSingleObject(shinfo.hProcess, INFINITE) == WAIT_OBJECT_0) { /* try to get the return value */ GetExitCodeProcess(shinfo.hProcess, &retval); } else { dbgprintf(PR_ERROR, "!!! ShellExecute() [%s] WaitForSingleObject() error %ld\n", argv0, GetLastError()); } } else { dbgprintf(PR_ERROR, "!!! ShellExecute() [%s] error %p\n", argv0, shinfo.hInstApp); } } /* try to close, it may fail but .. what else could we do */ CloseHandle(shinfo.hProcess); } dbgprintf(PR_ALL, "--- %s(): ShellExecute() OK, exiting with code %ld\n", __FUNCTION__, retval); exec_exit((int)retval); } else { dbgprintf(PR_EXEC, "ShellExecute() failed\n"); } return (0); }
int main() { DWORD dwRead, dwWrite; char *cmdLine; HANDLE hStdInput, hStdOutput, hStdError; HANDLE hFileInput, hFileOutput, hFileError; STARTUPINFO si; PROCESS_INFORMATION pi; char buf[8192]; DWORD result; hFileInput = INVALID_HANDLE_VALUE; hFileOutput = INVALID_HANDLE_VALUE; hFileError = INVALID_HANDLE_VALUE; result = 1; /* * Don't get command line from argc, argv, because the command line * tokenizer will have stripped off all the escape sequences needed * for quotes and backslashes, and then we'd have to put them all * back in again. Get the raw command line and parse off what we * want ourselves. The command line should be of the form: * * stub16.exe program arg1 arg2 ... */ cmdLine = strchr(GetCommandLine(), ' '); if (cmdLine == NULL) { return 1; } cmdLine++; hStdInput = GetStdHandle(STD_INPUT_HANDLE); hStdOutput = GetStdHandle(STD_OUTPUT_HANDLE); hStdError = GetStdHandle(STD_ERROR_HANDLE); if (GetFileType(hStdInput) == FILE_TYPE_PIPE) { hFileInput = CreateTempFile(); if (hFileInput == INVALID_HANDLE_VALUE) { goto cleanup; } while (ReadFile(hStdInput, buf, sizeof(buf), &dwRead, NULL) != FALSE) { if (dwRead == 0) { break; } if (WriteFile(hFileInput, buf, dwRead, &dwWrite, NULL) == FALSE) { goto cleanup; } } SetFilePointer(hFileInput, 0, 0, FILE_BEGIN); SetStdHandle(STD_INPUT_HANDLE, hFileInput); } if (GetFileType(hStdOutput) == FILE_TYPE_PIPE) { hFileOutput = CreateTempFile(); if (hFileOutput == INVALID_HANDLE_VALUE) { goto cleanup; } SetStdHandle(STD_OUTPUT_HANDLE, hFileOutput); } if (GetFileType(hStdError) == FILE_TYPE_PIPE) { hFileError = CreateTempFile(); if (hFileError == INVALID_HANDLE_VALUE) { goto cleanup; } SetStdHandle(STD_ERROR_HANDLE, hFileError); } ZeroMemory(&si, sizeof(si)); si.cb = sizeof(si); if (CreateProcess(NULL, cmdLine, NULL, NULL, TRUE, 0, NULL, NULL, &si, &pi) == FALSE) { goto cleanup; } WaitForInputIdle(pi.hProcess, 5000); WaitForSingleObject(pi.hProcess, INFINITE); GetExitCodeProcess(pi.hProcess, &result); CloseHandle(pi.hProcess); CloseHandle(pi.hThread); if (hFileOutput != INVALID_HANDLE_VALUE) { SetFilePointer(hFileOutput, 0, 0, FILE_BEGIN); while (ReadFile(hFileOutput, buf, sizeof(buf), &dwRead, NULL) != FALSE) { if (dwRead == 0) { break; } if (WriteFile(hStdOutput, buf, dwRead, &dwWrite, NULL) == FALSE) { break; } } } if (hFileError != INVALID_HANDLE_VALUE) { SetFilePointer(hFileError, 0, 0, FILE_BEGIN); while (ReadFile(hFileError, buf, sizeof(buf), &dwRead, NULL) != FALSE) { if (dwRead == 0) { break; } if (WriteFile(hStdError, buf, dwRead, &dwWrite, NULL) == FALSE) { break; } } } cleanup: if (hFileInput != INVALID_HANDLE_VALUE) { CloseHandle(hFileInput); } if (hFileOutput != INVALID_HANDLE_VALUE) { CloseHandle(hFileOutput); } if (hFileError != INVALID_HANDLE_VALUE) { CloseHandle(hFileError); } CloseHandle(hStdInput); CloseHandle(hStdOutput); CloseHandle(hStdError); ExitProcess(result); return 1; }
DWORD ExecCreateProcess(const char* command_str, char** result) { PROCESS_INFORMATION pi; STARTUPINFO si; //HANDLE hStdout; SECURITY_ATTRIBUTES sa; HANDLE hRead,hWrite; char buffer[4096] = {0}; DWORD bytesRead; DWORD ExitCode = ERROR; char* runcmd; sa.nLength = sizeof(SECURITY_ATTRIBUTES); sa.lpSecurityDescriptor = NULL; sa.bInheritHandle = TRUE; if (!CreatePipe(&hRead,&hWrite,&sa,0)) { printf("Error On CreatePipe()"); return ERROR; } runcmd=StringInit(); runcmd=StringSet(runcmd, command_str); //runcmd=StringInsert (runcmd,"c://windows//system32//cmd.exe /c ",0); //hStdout = GetStdHandle(STD_OUTPUT_HANDLE); ZeroMemory(&si, sizeof(si)); si.cb = sizeof(si); si.wShowWindow = SW_SHOW; si.dwFlags = STARTF_USESHOWWINDOW | STARTF_USESTDHANDLES; si.hStdOutput = hWrite; si.hStdError = hWrite; if (CreateProcess(NULL, runcmd, NULL, NULL, TRUE, CREATE_NO_WINDOW, NULL, NULL, &si, &pi)) { printf("Excuting \"%s\"\n", runcmd); WaitForSingleObject(pi.hProcess, INFINITE); GetExitCodeProcess(pi.hProcess, &ExitCode); CloseHandle(pi.hThread); CloseHandle(pi.hProcess); } else { //MessageBox(NULL, "The process could not be started...", NULL, MB_OK); printf("The process could not be started.\n"); CloseHandle(hWrite); free(runcmd); return 0; } CloseHandle(hWrite); *result = StringInit(); while (TRUE) { if (ReadFile(hRead, buffer, 4095, &bytesRead, NULL) == FALSE) { break; } *result = StringAppent(*result, buffer); memset(buffer,0,4096); //printf(buffer); } return ExitCode; }
DWORD CHooks::RunScript(CString cmd, LPCTSTR currentDir, CString& error, bool bWait, bool bShow) { DWORD exitcode = 0; SECURITY_ATTRIBUTES sa; SecureZeroMemory(&sa, sizeof(sa)); sa.nLength = sizeof(sa); sa.bInheritHandle = TRUE; CAutoFile hOut ; CAutoFile hRedir; CAutoFile hErr; // clear the error string error.Empty(); // Create Temp File for redirection TCHAR szTempPath[MAX_PATH]; TCHAR szOutput[MAX_PATH]; TCHAR szErr[MAX_PATH]; GetTortoiseGitTempPath(_countof(szTempPath), szTempPath); GetTempFileName(szTempPath, _T("git"), 0, szErr); // setup redirection handles // output handle must be WRITE mode, share READ // redirect handle must be READ mode, share WRITE hErr = CreateFile(szErr, GENERIC_WRITE, FILE_SHARE_READ, &sa, CREATE_ALWAYS, FILE_ATTRIBUTE_TEMPORARY, 0); if (!hErr) return (DWORD)-1; hRedir = CreateFile(szErr, GENERIC_READ, FILE_SHARE_WRITE, 0, OPEN_EXISTING, 0, 0); if (!hRedir) return (DWORD)-1; GetTempFileName(szTempPath, _T("git"), 0, szOutput); hOut = CreateFile(szOutput, GENERIC_WRITE, FILE_SHARE_READ, &sa, CREATE_ALWAYS, FILE_ATTRIBUTE_TEMPORARY, 0); if (!hOut) return (DWORD)-1; // setup startup info, set std out/err handles // hide window STARTUPINFO si; SecureZeroMemory(&si, sizeof(si)); si.cb = sizeof(si); if (hOut != INVALID_HANDLE_VALUE) { si.dwFlags = STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW; si.hStdOutput = hOut; si.hStdError = hErr; si.wShowWindow = bShow ? SW_SHOW : SW_HIDE; } PROCESS_INFORMATION pi; SecureZeroMemory(&pi, sizeof(pi)); DWORD dwFlags = 0; if (!CreateProcess(NULL, cmd.GetBuffer(), NULL, NULL, TRUE, dwFlags, NULL, currentDir, &si, &pi)) { int err = GetLastError(); // preserve the CreateProcess error error = CFormatMessageWrapper(err); SetLastError(err); cmd.ReleaseBuffer(); return (DWORD)-1; } cmd.ReleaseBuffer(); CloseHandle(pi.hThread); // wait for process to finish, capture redirection and // send it to the parent window/console if (bWait) { DWORD dw; char buf[256]; do { SecureZeroMemory(&buf,sizeof(buf)); while (ReadFile(hRedir, &buf, sizeof(buf)-1, &dw, NULL)) { if (dw == 0) break; error += CString(CStringA(buf,dw)); SecureZeroMemory(&buf,sizeof(buf)); } } while (WaitForSingleObject(pi.hProcess, 0) != WAIT_OBJECT_0); // perform any final flushing while (ReadFile(hRedir, &buf, sizeof(buf)-1, &dw, NULL)) { if (dw == 0) break; error += CString(CStringA(buf, dw)); SecureZeroMemory(&buf,sizeof(buf)); } WaitForSingleObject(pi.hProcess, INFINITE); GetExitCodeProcess(pi.hProcess, &exitcode); } CloseHandle(pi.hProcess); DeleteFile(szOutput); DeleteFile(szErr); return exitcode; }
// // Tries to call where.exe to find the location of dotnet.exe. // Will check that the bitness of dotnet matches the current // worker process bitness. // Returns true if a valid dotnet was found, else false.R // std::optional<fs::path> HOSTFXR_UTILITY::InvokeWhereToFindDotnet() { HRESULT hr = S_OK; // Arguments to call where.exe STARTUPINFOW startupInfo = { 0 }; PROCESS_INFORMATION processInformation = { 0 }; SECURITY_ATTRIBUTES securityAttributes; CHAR pzFileContents[READ_BUFFER_SIZE]; HandleWrapper<InvalidHandleTraits> hStdOutReadPipe; HandleWrapper<InvalidHandleTraits> hStdOutWritePipe; HandleWrapper<InvalidHandleTraits> hProcess; HandleWrapper<InvalidHandleTraits> hThread; CComBSTR pwzDotnetName = NULL; DWORD dwFilePointer; BOOL fIsWow64Process; BOOL fIsCurrentProcess64Bit; DWORD dwExitCode; STRU struDotnetSubstring; STRU struDotnetLocationsString; DWORD dwNumBytesRead; DWORD dwBinaryType; INT index = 0; INT prevIndex = 0; std::optional<fs::path> result; // Set the security attributes for the read/write pipe securityAttributes.nLength = sizeof(securityAttributes); securityAttributes.lpSecurityDescriptor = NULL; securityAttributes.bInheritHandle = TRUE; LOG_INFO(L"Invoking where.exe to find dotnet.exe"); // Create a read/write pipe that will be used for reading the result of where.exe FINISHED_LAST_ERROR_IF(!CreatePipe(&hStdOutReadPipe, &hStdOutWritePipe, &securityAttributes, 0)); FINISHED_LAST_ERROR_IF(!SetHandleInformation(hStdOutReadPipe, HANDLE_FLAG_INHERIT, 0)); // Set the stdout and err pipe to the write pipes. startupInfo.cb = sizeof(startupInfo); startupInfo.dwFlags |= STARTF_USESTDHANDLES; startupInfo.hStdOutput = hStdOutWritePipe; startupInfo.hStdError = hStdOutWritePipe; // CreateProcess requires a mutable string to be passed to commandline // See https://blogs.msdn.microsoft.com/oldnewthing/20090601-00/?p=18083/ pwzDotnetName = L"\"where.exe\" dotnet.exe"; // Create a process to invoke where.exe FINISHED_LAST_ERROR_IF(!CreateProcessW(NULL, pwzDotnetName, NULL, NULL, TRUE, CREATE_NO_WINDOW, NULL, NULL, &startupInfo, &processInformation )); // Store handles into wrapper so they get closed automatically hProcess = processInformation.hProcess; hThread = processInformation.hThread; // Wait for where.exe to return WaitForSingleObject(processInformation.hProcess, INFINITE); // // where.exe will return 0 on success, 1 if the file is not found // and 2 if there was an error. Check if the exit code is 1 and set // a new hr result saying it couldn't find dotnet.exe // FINISHED_LAST_ERROR_IF (!GetExitCodeProcess(processInformation.hProcess, &dwExitCode)); // // In this block, if anything fails, we will goto our fallback of // looking in C:/Program Files/ // if (dwExitCode != 0) { FINISHED_IF_FAILED(E_FAIL); } // Where succeeded. // Reset file pointer to the beginning of the file. dwFilePointer = SetFilePointer(hStdOutReadPipe, 0, NULL, FILE_BEGIN); if (dwFilePointer == INVALID_SET_FILE_POINTER) { FINISHED_IF_FAILED(E_FAIL); } // // As the call to where.exe succeeded (dotnet.exe was found), ReadFile should not hang. // TODO consider putting ReadFile in a separate thread with a timeout to guarantee it doesn't block. // FINISHED_LAST_ERROR_IF (!ReadFile(hStdOutReadPipe, pzFileContents, READ_BUFFER_SIZE, &dwNumBytesRead, NULL)); if (dwNumBytesRead >= READ_BUFFER_SIZE) { // This shouldn't ever be this large. We could continue to call ReadFile in a loop, // however if someone had this many dotnet.exes on their machine. FINISHED_IF_FAILED(E_FAIL); } FINISHED_IF_FAILED(struDotnetLocationsString.CopyA(pzFileContents, dwNumBytesRead)); LOG_INFOF(L"where.exe invocation returned: '%ls'", struDotnetLocationsString.QueryStr()); // Check the bitness of the currently running process // matches the dotnet.exe found. FINISHED_LAST_ERROR_IF (!IsWow64Process(GetCurrentProcess(), &fIsWow64Process)); if (fIsWow64Process) { // 32 bit mode fIsCurrentProcess64Bit = FALSE; } else { // Check the SystemInfo to see if we are currently 32 or 64 bit. SYSTEM_INFO systemInfo; GetNativeSystemInfo(&systemInfo); fIsCurrentProcess64Bit = systemInfo.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_AMD64; } LOG_INFOF(L"Current process bitness type detected as isX64=%d", fIsCurrentProcess64Bit); while (TRUE) { index = struDotnetLocationsString.IndexOf(L"\r\n", prevIndex); if (index == -1) { break; } FINISHED_IF_FAILED(struDotnetSubstring.Copy(&struDotnetLocationsString.QueryStr()[prevIndex], index - prevIndex)); // \r\n is two wchars, so add 2 here. prevIndex = index + 2; LOG_INFOF(L"Processing entry '%ls'", struDotnetSubstring.QueryStr()); if (LOG_LAST_ERROR_IF(!GetBinaryTypeW(struDotnetSubstring.QueryStr(), &dwBinaryType))) { continue; } LOG_INFOF(L"Binary type %d", dwBinaryType); if (fIsCurrentProcess64Bit == (dwBinaryType == SCS_64BIT_BINARY)) { // The bitness of dotnet matched with the current worker process bitness. return std::make_optional(struDotnetSubstring.QueryStr()); } } Finished: return result; }
int main( int argc, char *argv[] ) { extern HANDLE CDECL __wine_make_process_system(void); static const WCHAR RunW[] = {'R','u','n',0}; static const WCHAR RunOnceW[] = {'R','u','n','O','n','c','e',0}; static const WCHAR RunServicesW[] = {'R','u','n','S','e','r','v','i','c','e','s',0}; static const WCHAR RunServicesOnceW[] = {'R','u','n','S','e','r','v','i','c','e','s','O','n','c','e',0}; static const WCHAR wineboot_eventW[] = {'_','_','w','i','n','e','b','o','o','t','_','e','v','e','n','t',0}; /* First, set the current directory to SystemRoot */ int optc; BOOL end_session, force, init, kill, restart, shutdown, update; HANDLE event; SECURITY_ATTRIBUTES sa; BOOL is_wow64; end_session = force = init = kill = restart = shutdown = update = FALSE; GetWindowsDirectoryW( windowsdir, MAX_PATH ); if( !SetCurrentDirectoryW( windowsdir ) ) WINE_ERR("Cannot set the dir to %s (%d)\n", wine_dbgstr_w(windowsdir), GetLastError() ); if (IsWow64Process( GetCurrentProcess(), &is_wow64 ) && is_wow64) { STARTUPINFOW si; PROCESS_INFORMATION pi; WCHAR filename[MAX_PATH]; void *redir; DWORD exit_code; memset( &si, 0, sizeof(si) ); si.cb = sizeof(si); GetModuleFileNameW( 0, filename, MAX_PATH ); Wow64DisableWow64FsRedirection( &redir ); if (CreateProcessW( filename, GetCommandLineW(), NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi )) { WINE_TRACE( "restarting %s\n", wine_dbgstr_w(filename) ); WaitForSingleObject( pi.hProcess, INFINITE ); GetExitCodeProcess( pi.hProcess, &exit_code ); ExitProcess( exit_code ); } else WINE_ERR( "failed to restart 64-bit %s, err %d\n", wine_dbgstr_w(filename), GetLastError() ); Wow64RevertWow64FsRedirection( redir ); } while ((optc = getopt_long(argc, argv, short_options, long_options, NULL )) != -1) { switch(optc) { case 'e': end_session = TRUE; break; case 'f': force = TRUE; break; case 'i': init = TRUE; break; case 'k': kill = TRUE; break; case 'r': restart = TRUE; break; case 's': shutdown = TRUE; break; case 'u': update = TRUE; break; case 'h': usage(); return 0; case '?': usage(); return 1; } } if (end_session) { if (kill) { if (!shutdown_all_desktops( force )) return 1; } else if (!shutdown_close_windows( force )) return 1; } if (kill) kill_processes( shutdown ); if (shutdown) return 0; sa.nLength = sizeof(sa); sa.lpSecurityDescriptor = NULL; sa.bInheritHandle = TRUE; /* so that services.exe inherits it */ event = CreateEventW( &sa, TRUE, FALSE, wineboot_eventW ); ResetEvent( event ); /* in case this is a restart */ create_hardware_registry_keys(); create_dynamic_registry_keys(); create_environment_registry_keys(); wininit(); pendingRename(); ProcessWindowsFileProtection(); ProcessRunKeys( HKEY_LOCAL_MACHINE, RunServicesOnceW, TRUE, FALSE ); if (init || (kill && !restart)) { ProcessRunKeys( HKEY_LOCAL_MACHINE, RunServicesW, FALSE, FALSE ); start_services_process(); } if (init || update) update_wineprefix( update ); create_volatile_environment_registry_key(); ProcessRunKeys( HKEY_LOCAL_MACHINE, RunOnceW, TRUE, TRUE ); if (!init && !restart) { ProcessRunKeys( HKEY_LOCAL_MACHINE, RunW, FALSE, FALSE ); ProcessRunKeys( HKEY_CURRENT_USER, RunW, FALSE, FALSE ); ProcessStartupItems(); } WINE_TRACE("Operation done\n"); SetEvent( event ); return 0; }
bool execute(const char* command, std::string currentDir, DWORD& retCode, std::string& output) { HANDLE outWR; SECURITY_ATTRIBUTES sa; sa.nLength = sizeof(SECURITY_ATTRIBUTES); sa.lpSecurityDescriptor = NULL; sa.bInheritHandle = TRUE; TCHAR lpTempPathBuffer[BUFSIZE]; TCHAR szTempFileName[MAX_PATH]; DWORD ret = GetTempPath(BUFSIZE, lpTempPathBuffer); if (ret > BUFSIZE || ret == 0) { MessageBox( NULL, "Error GetTempPath", "Error", MB_OK ); return false; } ret = GetTempFileName(lpTempPathBuffer, "svn", 0, szTempFileName); if (ret == 0) { MessageBox( NULL, "Error GetTempFileName", "Error", MB_OK ); return false; } outWR = CreateFile(szTempFileName, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ, &sa, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); if (outWR == INVALID_HANDLE_VALUE) { MessageBox( NULL, "Error create file", "Error", MB_OK ); return false; } PROCESS_INFORMATION processInfomation; STARTUPINFO startupInfo; memset(&processInfomation, 0, sizeof(processInfomation)); memset(&startupInfo, 0, sizeof(startupInfo)); startupInfo.cb = sizeof(startupInfo); startupInfo.hStdError = outWR; startupInfo.hStdOutput = outWR; startupInfo.dwFlags |= STARTF_USESTDHANDLES; startupInfo.wShowWindow = SW_HIDE; BOOL result = CreateProcess( NULL, (char*) command, NULL, NULL, TRUE, 0, NULL, currentDir.c_str(), &startupInfo, &processInfomation); if (!result) { MessageBox( NULL, "Can't CreateProcess", "Error", MB_OK ); CloseHandle(outWR); return false; } else { WaitForSingleObject(processInfomation.hProcess, INFINITE); GetExitCodeProcess(processInfomation.hProcess, &retCode); CloseHandle(processInfomation.hProcess); CloseHandle(processInfomation.hThread); // read from stdout if (!CloseHandle(outWR)) { MessageBox( NULL, "Can't CloseHandle", "Error", MB_OK ); return false; } outWR = CreateFile(szTempFileName, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); if (outWR == INVALID_HANDLE_VALUE) { MessageBox( NULL, "Error open file", "Error", MB_OK ); return false; } CHAR buf[BUFSIZE]; DWORD dwRead; DWORD totalSize = 0; std::vector<char*> allBufs; std::vector<DWORD> lens; while (true) { result = ReadFile(outWR, buf, BUFSIZE, &dwRead, NULL); if (!result || dwRead == 0) break; totalSize += dwRead; char* content = new char[dwRead]; memcpy(content, buf, dwRead); allBufs.push_back(content); lens.push_back(dwRead); } char* content = new char[totalSize + 1]; char* currentPtr = content; for (std::size_t i = 0; i < allBufs.size(); i++) { memcpy(currentPtr, allBufs[i], lens[i]); currentPtr += lens[i]; } content[totalSize] = 0; for (std::size_t i = 0; i < allBufs.size(); i++) { delete[] allBufs[i]; } output.swap(std::string(content)); delete[] content; CloseHandle(outWR); return true; } }