bool CServerSession::OnRunImage( CNcpMessage* pMsg, int nSize ) { char path[MAXPATH]; //parse the parameters bool bSync = (bool)pMsg->GetRet(); string strImageName = (char*)(pMsg->GetData()); if( !IsAbsDir( strImageName.c_str() ) ) { strcpy( path, m_strCurDir.c_str() ); CatDir( path, strImageName.c_str(), path, ELEMENTS(path) ); } else { strcpy( path, strImageName.c_str() ); } BOOL bOk; int nPriority = m_pServApp->GetPriority(); DWORD dwExitCode = 0; if( bSync ) { //synchronize running, register the handle and wait the process HANDLE hProcess; //bOk = CreateProcess( path, m_strCurDir.c_str(), nPriority, &hProcess ); bOk = CreateProcess( path, m_strCurDir.c_str(), &hProcess ); SetProcessPriority( hProcess, nPriority ); m_pServApp->RegistProc( hProcess ); WaitForProcess( hProcess, &dwExitCode ); m_pServApp->UnregistProc( hProcess ); //CloseProcessHandle( hProcess ); CloseHandle( hProcess ); } else { //just run the process and return. bOk = CreateProcess( path, m_strCurDir.c_str(), NULL ); //bOk = CreateProcess( path, m_strCurDir.c_str(), nPriority, NULL ); //SetProcessPriority( hProcess, nPriority ); } #ifdef _WIN32 printf( "windows process exit code:%d\n", dwExitCode ); #else int status = dwExitCode; if( WIFEXITED(status) )printf( "normal termination, exit status=%d\n", WEXITSTATUS(status) ); else if( WIFSIGNALED(status) )printf( "abnormal termination, signal number=%d\n", WTERMSIG(status) ); else if( WIFSTOPPED(status) )printf( "child stopped, signal number=%d\n", WSTOPSIG(status) ); #endif //send back the return code. pMsg->Init( CM_ACK ); if( !bOk ) { pMsg->SetRet( E_NOEXEC ); } else { pMsg->SetRet( dwExitCode ); } pMsg->Send( m_sock ); return bOk; }
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) { /* * Gather the parameters of the real installer program. */ SetLastError(NO_ERROR); WCHAR wszCurDir[_MAX_PATH] = { 0 }; DWORD cchCurDir = GetCurrentDirectoryW(sizeof(wszCurDir), wszCurDir); if (cchCurDir == 0 || cchCurDir >= sizeof(wszCurDir)) { fwprintf(stderr, L"ERROR: GetCurrentDirectoryW failed: %u (ret %u)\n", GetLastError(), cchCurDir); return 12; } SetLastError(NO_ERROR); WCHAR wszModule[_MAX_PATH] = { 0 }; DWORD cchModule = GetModuleFileNameW(NULL, wszModule, sizeof(wszModule)); if (cchModule == 0 || cchModule >= sizeof(wszModule)) { fwprintf(stderr, L"ERROR: GetModuleFileNameW failed: %u (ret %u)\n", GetLastError(), cchModule); return 13; } /* Strip the extension off the module name and construct the arch specific one of the real installer program. */ DWORD off = cchModule - 1; while ( off > 0 && ( wszModule[off] != '/' && wszModule[off] != '\\' && wszModule[off] != ':')) { if (wszModule[off] == '.') { wszModule[off] = '\0'; cchModule = off; break; } off--; } WCHAR const *pwszSuff = IsWow64() ? L"-amd64.exe" : L"-x86.exe"; size_t cchSuff = wcslen(pwszSuff); if (cchSuff + cchModule >= sizeof(wszModule)) { fwprintf(stderr, L"ERROR: Real installer name is too long (%u chars)\n", cchSuff + cchModule); return 14; } wcscpy(&wszModule[cchModule], pwszSuff); cchModule += cchSuff; /* Replace the first argument of the argument list. */ PWCHAR pwszNewCmdLine = NULL; LPCWSTR pwszOrgCmdLine = GetCommandLineW(); if (pwszOrgCmdLine) /* Dunno if this can be NULL, but whatever. */ { /* Skip the first argument in the original. */ /** @todo Is there some ISBLANK or ISSPACE macro/function in Win32 that we could * use here, if it's correct wrt. command line conventions? */ WCHAR wch; while ((wch = *pwszOrgCmdLine) == L' ' || wch == L'\t') pwszOrgCmdLine++; if (wch == L'"') { pwszOrgCmdLine++; while ((wch = *pwszOrgCmdLine) != L'\0') { pwszOrgCmdLine++; if (wch == L'"') break; } } else { while ((wch = *pwszOrgCmdLine) != L'\0') { pwszOrgCmdLine++; if (wch == L' ' || wch == L'\t') break; } } while ((wch = *pwszOrgCmdLine) == L' ' || wch == L'\t') pwszOrgCmdLine++; /* Join up "szModule" with the remainder of the original command line. */ size_t cchOrgCmdLine = wcslen(pwszOrgCmdLine); size_t cchNewCmdLine = 1 + cchModule + 1 + 1 + cchOrgCmdLine + 1; PWCHAR pwsz = pwszNewCmdLine = (PWCHAR)LocalAlloc(LPTR, cchNewCmdLine * sizeof(WCHAR)); if (!pwsz) { fwprintf(stderr, L"ERROR: Out of memory (%u bytes)\n", cchNewCmdLine); return 15; } *pwsz++ = L'"'; wcscpy(pwsz, wszModule); pwsz += cchModule; *pwsz++ = L'"'; if (cchOrgCmdLine) { *pwsz++ = L' '; wcscpy(pwsz, pwszOrgCmdLine); } else { *pwsz = L'\0'; pwszOrgCmdLine = NULL; } } /* * Start the process. */ int iRet = 0; STARTUPINFOW StartupInfo = { sizeof(StartupInfo), 0 }; PROCESS_INFORMATION ProcInfo = { 0 }; SetLastError(740); BOOL fOk = CreateProcessW(wszModule, pwszNewCmdLine, NULL /*pProcessAttributes*/, NULL /*pThreadAttributes*/, TRUE /*fInheritHandles*/, 0 /*dwCreationFlags*/, NULL /*pEnvironment*/, NULL /*pCurrentDirectory*/, &StartupInfo, &ProcInfo); if (fOk) { /* Wait for the process to finish. */ CloseHandle(ProcInfo.hThread); WaitForProcess(ProcInfo.hProcess, &iRet); CloseHandle(ProcInfo.hProcess); } else if (GetLastError() == ERROR_ELEVATION_REQUIRED) { /* * Elevation is required. That can be accomplished via ShellExecuteEx * and the runas atom. */ MSG Msg; PeekMessage(&Msg, NULL, 0, 0, PM_NOREMOVE); CoInitializeEx(NULL, COINIT_APARTMENTTHREADED | COINIT_DISABLE_OLE1DDE); SHELLEXECUTEINFOW ShExecInfo = { 0 }; ShExecInfo.cbSize = sizeof(SHELLEXECUTEINFOW); ShExecInfo.fMask = SEE_MASK_NOCLOSEPROCESS; ShExecInfo.hwnd = NULL; ShExecInfo.lpVerb = L"runas" ; ShExecInfo.lpFile = wszModule; ShExecInfo.lpParameters = pwszOrgCmdLine; /* pass only args here!!! */ ShExecInfo.lpDirectory = wszCurDir; ShExecInfo.nShow = SW_NORMAL; ShExecInfo.hProcess = INVALID_HANDLE_VALUE; if (ShellExecuteExW(&ShExecInfo)) { if (ShExecInfo.hProcess != INVALID_HANDLE_VALUE) { WaitForProcess2(ShExecInfo.hProcess, &iRet); CloseHandle(ShExecInfo.hProcess); } else { fwprintf(stderr, L"ERROR: ShellExecuteExW did not return a valid process handle!\n"); iRet = 1; } } else { fwprintf(stderr, L"ERROR: Failed to execute '%ws' via ShellExecuteExW: %u\n", wszModule, GetLastError()); iRet = 9; } } else { fwprintf(stderr, L"ERROR: Failed to execute '%ws' via CreateProcessW: %u\n", wszModule, GetLastError()); iRet = 8; } if (pwszNewCmdLine) LocalFree(pwszNewCmdLine); #if 0 fwprintf(stderr, L"DEBUG: iRet=%d\n", iRet); fflush(stderr); #endif return iRet; }
int main(int argc, char ** argv) { --argc; ++argv; if (argc == 0) { printHelp(); return 0; } int waitpid = -1; PresentMonArgs args; std::string title_string = "PresentMon"; args.mTargetProcessName = "*"; for (int i = 0; i < argc; ++i) { // 2-component arguments if (i + 1 < argc) { if (!strcmp(argv[i], "-waitpid")) { waitpid = atoi(argv[++i]); continue; } else if (!strcmp(argv[i], "-process_name")) { args.mTargetProcessName = argv[++i]; } else if (!strcmp(argv[i], "-process_id")) { args.mTargetPid = atoi(argv[++i]); } else if (!strcmp(argv[i], "-output_file")) { args.mOutputFileName = argv[++i]; } else if (!strcmp(argv[i], "-etl_file")) { args.mEtlFileName = argv[++i]; } else if (!strcmp(argv[i], "-delay")) { args.mDelay = atoi(argv[++i]); } else if (!strcmp(argv[i], "-timed")) { args.mTimer = atoi(argv[++i]); } } // 1-component args { if (!strcmp(argv[i], "-no_csv")) { args.mOutputFileName = "*"; } else if (!strcmp(argv[i], "-exclude_dropped")) { args.mExcludeDropped = true; } else if (!strcmp(argv[i], "-scroll_toggle")) { args.mScrollLockToggle = true; } else if (!strcmp(argv[i], "-?") || !strcmp(argv[i], "-help")) { printHelp(); return 0; } } title_string += ' '; title_string += argv[i]; } if (waitpid >= 0) { WaitForProcess(waitpid); if (!HaveAdministratorPrivileges()) { printf("Elevation process failed. Aborting.\n"); return 0; } } if (!args.mEtlFileName && !HaveAdministratorPrivileges()) { printf("Process is not running as admin. Attempting to elevate.\n"); RestartAsAdministrator(argc, argv); return 0; } SetConsoleCtrlHandler(HandlerRoutine, TRUE); SetConsoleTitleA(title_string.c_str()); std::mutex exit_mutex; g_ExitMutex = &exit_mutex; // Run PM in a separate thread so we can join it in the CtrlHandler (can't join the main thread) std::thread pm(PresentMonEtw, args); g_PresentMonThread = ± while (!g_Quit) { Sleep(100); } // Wait for tracing to finish, to ensure the PM thread closes the session correctly // Prevent races on joining the PM thread between the control handler and the main thread std::lock_guard<std::mutex> lock(exit_mutex); if (g_PresentMonThread->joinable()) { g_PresentMonThread->join(); } return 0; }
///////////////////////////////////////////////////////////////////////////// // ExecuteVerifyUpdate // DWORD ExecuteVerifyUpdate(LPCSTR szModuleFile, LPCSTR szUpdateCachePath) { DWORD dwResult = 0; // build up CreateProcess structures STARTUPINFO sui; PROCESS_INFORMATION pi; memset((void*)&pi, 0x00, sizeof(PROCESS_INFORMATION)); memset((void*)&sui, 0x00, sizeof(STARTUPINFO)); sui.cb = sizeof(STARTUPINFO); sui.dwFlags = STARTF_USESHOWWINDOW; sui.wShowWindow = SW_SHOW; // // Build command line and specify delayreboot option to Update // The nine extra characters are required for the following: // 2 for the quotes enclosing the module path // 2 for /v // 2 for the spaces before and after /v // 2 for the quotes enclosing the Update path // 1 for the terminating null. // DWORD cchCommandLine = lstrlen(szModuleFile) + lstrlen(szUpdateCachePath) + 9; char *szCommandLine = new char[cchCommandLine]; if (!szCommandLine) { dwResult = ERROR_OUTOFMEMORY; goto Return_ExecuteVerifyUpdate; } if (FAILED(StringCchCopy(szCommandLine, cchCommandLine, "\"")) || FAILED(StringCchCat(szCommandLine, cchCommandLine, szModuleFile)) || FAILED(StringCchCat(szCommandLine, cchCommandLine, "\"")) || FAILED(StringCchCat(szCommandLine, cchCommandLine, " /v \"")) || FAILED(StringCchCat(szCommandLine, cchCommandLine, szUpdateCachePath)) || FAILED(StringCchCat(szCommandLine, cchCommandLine, "\""))) { dwResult = ERROR_INSTALL_FAILURE; goto Return_ExecuteVerifyUpdate; } // // Run the verification process. We use a copy of ourselves to do this. // if(!WIN::CreateProcess(NULL, szCommandLine, NULL, NULL, FALSE, CREATE_DEFAULT_ERROR_MODE, NULL, NULL, &sui, &pi)) { // failed to launch. dwResult = GetLastError(); goto Return_ExecuteVerifyUpdate; } dwResult = WaitForProcess(pi.hProcess); if(ERROR_SUCCESS != dwResult) goto Return_ExecuteVerifyUpdate; WIN::GetExitCodeProcess(pi.hProcess, &dwResult); Return_ExecuteVerifyUpdate: if (szCommandLine) delete [] szCommandLine; if (pi.hProcess) WIN::CloseHandle(pi.hProcess); if (pi.hThread) WIN::CloseHandle(pi.hThread); DebugMsg("[Info] Verification of Update returned %d\n", dwResult); return dwResult; }
DWORD ExecuteUpgradeMsi(__in LPSTR szUpgradeMsi) { DebugMsg("[Info] Running update package from --> %s\n", szUpgradeMsi); DWORD dwResult = 0; // build up CreateProcess structures STARTUPINFO sui; PROCESS_INFORMATION pi; memset((void*)&pi, 0x00, sizeof(PROCESS_INFORMATION)); memset((void*)&sui, 0x00, sizeof(STARTUPINFO)); sui.cb = sizeof(STARTUPINFO); sui.dwFlags = STARTF_USESHOWWINDOW; sui.wShowWindow = SW_SHOW; // // build command line and specify delayreboot option to Update // three acounts for terminating null plus quotes for module DWORD cchCommandLine = lstrlen(szUpgradeMsi) + lstrlen(szDelayReboot) + 3; char *szCommandLine = new char[cchCommandLine]; if (!szCommandLine) { dwResult = ERROR_OUTOFMEMORY; goto Return_ExecuteUpgradeMsi; } if (FAILED(StringCchCopy(szCommandLine, cchCommandLine, "\"")) || FAILED(StringCchCat(szCommandLine, cchCommandLine, szUpgradeMsi)) || FAILED(StringCchCat(szCommandLine, cchCommandLine, "\"")) || FAILED(StringCchCat(szCommandLine, cchCommandLine, szDelayReboot))) { dwResult = ERROR_INSTALL_FAILURE; goto Return_ExecuteUpgradeMsi; } // // run update process if(!WIN::CreateProcess(NULL, szCommandLine, NULL, NULL, FALSE, CREATE_DEFAULT_ERROR_MODE, NULL, NULL, &sui, &pi)) { // failed to launch. dwResult = GetLastError(); goto Return_ExecuteUpgradeMsi; } dwResult = WaitForProcess(pi.hProcess); if(ERROR_SUCCESS != dwResult) goto Return_ExecuteUpgradeMsi; WIN::GetExitCodeProcess(pi.hProcess, &dwResult); Return_ExecuteUpgradeMsi: if (szCommandLine) delete [] szCommandLine; if (pi.hProcess) WIN::CloseHandle(pi.hProcess); if (pi.hThread) WIN::CloseHandle(pi.hThread); return dwResult; }
int main(int argc, char ** argv) { --argc; ++argv; if (argc == 0) { printf( "command line options:\n" " -captureall: record ALL processes (default).\n" " -process_name [exe name]: record specific process.\n" " -process_id [integer]: record specific process ID.\n" " -output_file [path]: override the default output path.\n" " -no_csv: do not create any output file.\n" ); return 0; } int waitpid = -1; PresentMonArgs args; args.mTargetProcessName = "*"; for (int i = 0; i < argc; ++i) { // 2-component arguments if (i + 1 < argc) { if (!strcmp(argv[i], "-waitpid")) { waitpid = atoi(argv[++i]); } else if (!strcmp(argv[i], "-process_name")) { args.mTargetProcessName = argv[++i]; } else if (!strcmp(argv[i], "-process_id")) { args.mTargetPid = atoi(argv[++i]); } else if (!strcmp(argv[i], "-output_file")) { args.mOutputFileName = argv[++i]; } } // 1-component args else { if (!strcmp(argv[i], "-no_csv")) { args.mOutputFileName = "*"; } } } if (waitpid >= 0) { WaitForProcess(waitpid); if (!HaveAdministratorPrivilidges()) { printf("Elevation process failed. Aborting.\n"); return 0; } } if (!HaveAdministratorPrivilidges()) { printf("Process is not running as admin. Attempting to elevate.\n"); RestartAsAdministrator(argc, argv); return 0; } SetConsoleCtrlHandler(HandlerRoutine, TRUE); // Run PM in a separate thread so we can join it in the CtrlHandler (can't join the main thread) std::thread pm(PresentMonEtw, args); g_PresentMonThread = ± Sleep(INFINITE); }