| 485 | |
| 486 | #if defined(_win_) |
| 487 | void TShellCommand::TImpl::StartProcess(TShellCommand::TImpl::TPipes& pipes) { |
| 488 | // Setup STARTUPINFO to redirect handles. |
| 489 | STARTUPINFOW startup_info; |
| 490 | ZeroMemory(&startup_info, sizeof(startup_info)); |
| 491 | startup_info.cb = sizeof(startup_info); |
| 492 | startup_info.dwFlags = STARTF_USESTDHANDLES; |
| 493 | |
| 494 | if (Options_.OutputMode != TShellCommandOptions::HANDLE_INHERIT) { |
| 495 | if (!SetHandleInformation(pipes.OutputPipeFd[1], HANDLE_FLAG_INHERIT, HANDLE_FLAG_INHERIT)) { |
| 496 | ythrow TSystemError() << "cannot set handle info"; |
| 497 | } |
| 498 | } |
| 499 | if (Options_.ErrorMode != TShellCommandOptions::HANDLE_INHERIT) { |
| 500 | if (!SetHandleInformation(pipes.ErrorPipeFd[1], HANDLE_FLAG_INHERIT, HANDLE_FLAG_INHERIT)) { |
| 501 | ythrow TSystemError() << "cannot set handle info"; |
| 502 | } |
| 503 | } |
| 504 | if (InputMode != TShellCommandOptions::HANDLE_INHERIT) { |
| 505 | if (!SetHandleInformation(pipes.InputPipeFd[0], HANDLE_FLAG_INHERIT, HANDLE_FLAG_INHERIT)) { |
| 506 | ythrow TSystemError() << "cannot set handle info"; |
| 507 | } |
| 508 | } |
| 509 | |
| 510 | // A sockets do not work as std streams for some reason |
| 511 | if (Options_.OutputMode != TShellCommandOptions::HANDLE_INHERIT) { |
| 512 | startup_info.hStdOutput = pipes.OutputPipeFd[1]; |
| 513 | } else { |
| 514 | startup_info.hStdOutput = GetStdHandle(STD_OUTPUT_HANDLE); |
| 515 | } |
| 516 | if (Options_.ErrorMode != TShellCommandOptions::HANDLE_INHERIT) { |
| 517 | startup_info.hStdError = pipes.ErrorPipeFd[1]; |
| 518 | } else { |
| 519 | startup_info.hStdError = GetStdHandle(STD_ERROR_HANDLE); |
| 520 | } |
| 521 | if (InputMode != TShellCommandOptions::HANDLE_INHERIT) { |
| 522 | startup_info.hStdInput = pipes.InputPipeFd[0]; |
| 523 | } else { |
| 524 | // Don't leave hStdInput unfilled, otherwise any attempt to retrieve the operating-system file handle |
| 525 | // that is associated with the specified file descriptor will led to errors. |
| 526 | startup_info.hStdInput = GetStdHandle(STD_INPUT_HANDLE); |
| 527 | } |
| 528 | |
| 529 | PROCESS_INFORMATION process_info; |
| 530 | // TString cmd = "cmd /U" + TUtf16String can be used to read unicode messages from cmd |
| 531 | // /A - ansi charset /Q - echo off, /C - command, /Q - special quotes |
| 532 | TString qcmd = GetQuotedCommand(); |
| 533 | TString cmd = Options_.UseShell ? "cmd /A /Q /S /C \"" + qcmd + "\"" : qcmd; |
| 534 | // winapi can modify command text, copy it |
| 535 | |
| 536 | Y_ENSURE_EX(cmd.size() < MAX_COMMAND_LINE, yexception() << "Command is too long (length=" << cmd.size() << ")"); |
| 537 | TTempArray<wchar_t> cmdcopy(MAX_COMMAND_LINE); |
| 538 | Copy(cmd.data(), cmd.data() + cmd.size(), cmdcopy.Data()); |
| 539 | *(cmdcopy.Data() + cmd.size()) = 0; |
| 540 | |
| 541 | const wchar_t* cwd = NULL; |
| 542 | std::wstring cwdBuff; |
| 543 | if (WorkDir.size()) { |
| 544 | cwdBuff = GetWString(WorkDir.data()); |
nothing calls this directly
no test coverage detected