| 601 | } |
| 602 | |
| 603 | static HRESULT launchProgram(const String& sCmd, WORD wShowWindow, DWORD &dwExitCode) |
| 604 | { |
| 605 | TempFile stderrFile; |
| 606 | String sOutputFile = stderrFile.Create(); |
| 607 | size_t size = 0; |
| 608 | _wgetenv_s(&size, nullptr, 0, L"WINMERGE_HOME"); |
| 609 | if (size == 0) |
| 610 | _wputenv_s(L"WINMERGE_HOME", env::GetProgPath().c_str()); |
| 611 | String command = sCmd; |
| 612 | STARTUPINFO stInfo = { sizeof(STARTUPINFO) }; |
| 613 | stInfo.dwFlags = STARTF_USESHOWWINDOW; |
| 614 | stInfo.wShowWindow = wShowWindow; |
| 615 | SECURITY_ATTRIBUTES sa{ sizeof(sa) }; |
| 616 | sa.bInheritHandle = true; |
| 617 | stInfo.hStdError = CreateFile(sOutputFile.c_str(), GENERIC_READ | GENERIC_WRITE, |
| 618 | FILE_SHARE_READ | FILE_SHARE_WRITE, &sa, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, nullptr); |
| 619 | stInfo.hStdOutput = stInfo.hStdError; |
| 620 | stInfo.dwFlags |= STARTF_USESTDHANDLES; |
| 621 | PROCESS_INFORMATION processInfo; |
| 622 | bool retVal = !!CreateProcess(nullptr, (tchar_t*)command.c_str(), |
| 623 | nullptr, nullptr, TRUE, CREATE_DEFAULT_ERROR_MODE, nullptr, nullptr, |
| 624 | &stInfo, &processInfo); |
| 625 | if (!retVal) |
| 626 | return HRESULT_FROM_WIN32(GetLastError()); |
| 627 | WaitForSingleObject(processInfo.hProcess, INFINITE); |
| 628 | GetExitCodeProcess(processInfo.hProcess, &dwExitCode); |
| 629 | CloseHandle(processInfo.hThread); |
| 630 | CloseHandle(processInfo.hProcess); |
| 631 | DWORD dwStdErrorSize = 0; |
| 632 | if (stInfo.hStdError != nullptr && stInfo.hStdError != INVALID_HANDLE_VALUE) |
| 633 | { |
| 634 | DWORD dwStdErrorSizeHigh = 0; |
| 635 | dwStdErrorSize = GetFileSize(stInfo.hStdError, &dwStdErrorSizeHigh); |
| 636 | CloseHandle(stInfo.hStdError); |
| 637 | } |
| 638 | if (dwExitCode != 0 && dwStdErrorSize > 0) |
| 639 | { |
| 640 | String error; |
| 641 | ReadFile(sOutputFile, error); |
| 642 | ICreateErrorInfo* pCreateErrorInfo = nullptr; |
| 643 | if (SUCCEEDED(CreateErrorInfo(&pCreateErrorInfo))) |
| 644 | { |
| 645 | pCreateErrorInfo->SetSource(const_cast<OLECHAR*>(command.c_str())); |
| 646 | pCreateErrorInfo->SetDescription(const_cast<OLECHAR*>(ucr::toUTF16(error).c_str())); |
| 647 | IErrorInfo* pErrorInfo = nullptr; |
| 648 | pCreateErrorInfo->QueryInterface(&pErrorInfo); |
| 649 | SetErrorInfo(0, pErrorInfo); |
| 650 | pErrorInfo->Release(); |
| 651 | pCreateErrorInfo->Release(); |
| 652 | return DISP_E_EXCEPTION; |
| 653 | } |
| 654 | } |
| 655 | return S_OK; |
| 656 | } |
| 657 | |
| 658 | Info m_info; |
| 659 | }; |
nothing calls this directly
no test coverage detected