31inline std::string
call(
const std::string &cmd)
36 const size_t spcidx = cmd.find_first_of(
" ");
37 if (spcidx != std::string::npos)
39 name = cmd.substr(0, spcidx);
40 if (spcidx + 1 < cmd.length())
41 args = cmd.substr(spcidx + 1);
47 wchar_t *syspath_ptr =
nullptr;
48 if (::SHGetKnownFolderPath(FOLDERID_System, 0,
nullptr, &syspath_ptr) != S_OK)
49 throw win_call(
"cannot get system path using SHGetKnownFolderPath");
52 { ::CoTaskMemFree(p); });
54 const size_t wcmdlen = ::wcslen(syspath.get()) + name.length() + args.length() + 64;
55 std::unique_ptr<wchar_t[]> wcmd(
new wchar_t[wcmdlen]);
59 ::_snwprintf(wcmd.get(), wcmdlen, L
"\"%s\\%S.exe\"%S%S", syspath.get(), name.c_str(), spc, args.c_str());
60 wcmd.get()[wcmdlen - 1] = 0;
64 SECURITY_ATTRIBUTES saAttr;
65 saAttr.nLength =
sizeof(SECURITY_ATTRIBUTES);
66 saAttr.bInheritHandle = TRUE;
67 saAttr.lpSecurityDescriptor =
nullptr;
72 if (!::CreatePipe(cstdout_r.
ref(), cstdout_w.
ref(), &saAttr, 0))
73 throw win_call(
"cannot create pipe for child stdout");
76 if (!::SetHandleInformation(cstdout_r(), HANDLE_FLAG_INHERIT, 0))
77 throw win_call(
"SetHandleInformation failed for child stdout pipe");
80 PROCESS_INFORMATION piProcInfo;
81 ::ZeroMemory(&piProcInfo,
sizeof(PROCESS_INFORMATION));
85 STARTUPINFOW siStartInfo;
86 ::ZeroMemory(&siStartInfo,
sizeof(STARTUPINFO));
87 siStartInfo.cb =
sizeof(STARTUPINFO);
88 siStartInfo.hStdError = cstdout_w();
89 siStartInfo.hStdOutput = cstdout_w();
90 siStartInfo.hStdInput =
nullptr;
91 siStartInfo.dwFlags |= STARTF_USESTDHANDLES;
94 if (!::CreateProcessW(
nullptr,
104 throw win_call(
"cannot create process");
114 const size_t outbuf_size = 512;
115 std::unique_ptr<char[]> outbuf(
new char[outbuf_size]);
120 if (!::ReadFile(cstdout_r(), outbuf.get(), outbuf_size, &dwRead,
nullptr))
124 out += std::string(outbuf.get(), 0, dwRead);
133 out.assign(utf8output.get());
136 if (::WaitForSingleObject(process_hand(), INFINITE) == WAIT_FAILED)
137 throw win_call(
"WaitForSingleObject failed on child process handle");