235{
237
239
240
241
242 __crt_unique_handle new_pipe_handle;
244 process_handle,
246 process_handle,
247 new_pipe_handle.get_address_of(),
248 0,
251 {
252 return nullptr;
253 }
254
256 pipe_handles[0] = -1;
257
258
259 unique_stream pipe_stream(stdio_traits::tfdopen(pipe_handles[1], fdopen_mode));
260 if (!pipe_stream)
261 return nullptr;
262
263
265 if (!id_pair)
266 return nullptr;
267
268
269 static Character const default_cmd_exe[] = { 'c', 'm', 'd', '.', 'e', 'x', 'e', '\0' };
270
271 __crt_unique_heap_ptr<Character const> const comspec_variable(get_comspec<Character>());
272 Character const* const cmd_exe = comspec_variable.get() != nullptr
273 ? comspec_variable.get()
274 : default_cmd_exe;
275
277 startup_info.
cb =
sizeof(startup_info);
278
279
284
285 static Character const slash_c[] = { ' ', '/', 'c', ' ', '\0' };
286
287 size_t const command_line_count =
288 stdio_traits::tcslen(cmd_exe) +
289 stdio_traits::tcslen(slash_c) +
290 stdio_traits::tcslen(
command) +
291 1;
292
293 __crt_unique_heap_ptr<Character> const command_line(_calloc_crt_t(Character, command_line_count));
294 if (command_line.get() == nullptr)
295 return nullptr;
296
297 _ERRCHECK(stdio_traits::tcscpy_s(command_line.get(), command_line_count, cmd_exe));
298 _ERRCHECK(stdio_traits::tcscat_s(command_line.get(), command_line_count, slash_c));
299 _ERRCHECK(stdio_traits::tcscat_s(command_line.get(), command_line_count,
command));
300
301
303 if (selected_cmd_exe == nullptr)
304 return nullptr;
305
306
307
308 __crt_unique_heap_ptr<Character const> const owned_final_exe_path(selected_cmd_exe != cmd_exe
309 ? selected_cmd_exe
310 : nullptr);
311
313 BOOL const child_status = stdio_traits::create_process(
314 selected_cmd_exe,
315 command_line.get(),
316 nullptr,
317 nullptr,
319 0,
320 nullptr,
321 nullptr,
322 &startup_info,
323 &process_info);
324
325 if (!child_status)
326 return nullptr;
327
328 FILE*
const result_stream = pipe_stream.detach();
329
331 id_pair.get()->process_handle =
reinterpret_cast<intptr_t>(process_info.
hProcess);
332 id_pair.get()->stream = result_stream;
333 id_pair.detach();
334 return result_stream;
335}
#define GetCurrentProcess()
BOOL WINAPI DuplicateHandle(IN HANDLE hSourceProcessHandle, IN HANDLE hSourceHandle, IN HANDLE hTargetProcessHandle, OUT LPHANDLE lpTargetHandle, IN DWORD dwDesiredAccess, IN BOOL bInheritHandle, IN DWORD dwOptions)
__crt_unique_handle_t< stream_traits > unique_stream
__crt_unique_handle_t< process_handle_pair_traits > unique_process_handle_pair
static Character const *__cdecl get_executable_path(Character const *const executable)
struct _PROCESS_INFORMATION PROCESS_INFORMATION
#define STARTF_USESTDHANDLES
#define DUPLICATE_SAME_ACCESS