1e66f31c5Sopenharmony_ci/* Copyright Joyent, Inc. and other Node contributors. All rights reserved. 2e66f31c5Sopenharmony_ci * 3e66f31c5Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a copy 4e66f31c5Sopenharmony_ci * of this software and associated documentation files (the "Software"), to 5e66f31c5Sopenharmony_ci * deal in the Software without restriction, including without limitation the 6e66f31c5Sopenharmony_ci * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 7e66f31c5Sopenharmony_ci * sell copies of the Software, and to permit persons to whom the Software is 8e66f31c5Sopenharmony_ci * furnished to do so, subject to the following conditions: 9e66f31c5Sopenharmony_ci * 10e66f31c5Sopenharmony_ci * The above copyright notice and this permission notice shall be included in 11e66f31c5Sopenharmony_ci * all copies or substantial portions of the Software. 12e66f31c5Sopenharmony_ci * 13e66f31c5Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14e66f31c5Sopenharmony_ci * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15e66f31c5Sopenharmony_ci * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16e66f31c5Sopenharmony_ci * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17e66f31c5Sopenharmony_ci * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 18e66f31c5Sopenharmony_ci * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 19e66f31c5Sopenharmony_ci * IN THE SOFTWARE. 20e66f31c5Sopenharmony_ci */ 21e66f31c5Sopenharmony_ci 22e66f31c5Sopenharmony_ci#include <assert.h> 23e66f31c5Sopenharmony_ci#include <io.h> 24e66f31c5Sopenharmony_ci#include <stdio.h> 25e66f31c5Sopenharmony_ci#include <stdlib.h> 26e66f31c5Sopenharmony_ci 27e66f31c5Sopenharmony_ci#include "uv.h" 28e66f31c5Sopenharmony_ci#include "internal.h" 29e66f31c5Sopenharmony_ci#include "handle-inl.h" 30e66f31c5Sopenharmony_ci 31e66f31c5Sopenharmony_ci 32e66f31c5Sopenharmony_ci/* 33e66f31c5Sopenharmony_ci * The `child_stdio_buffer` buffer has the following layout: 34e66f31c5Sopenharmony_ci * int number_of_fds 35e66f31c5Sopenharmony_ci * unsigned char crt_flags[number_of_fds] 36e66f31c5Sopenharmony_ci * HANDLE os_handle[number_of_fds] 37e66f31c5Sopenharmony_ci */ 38e66f31c5Sopenharmony_ci#define CHILD_STDIO_SIZE(count) \ 39e66f31c5Sopenharmony_ci (sizeof(int) + \ 40e66f31c5Sopenharmony_ci sizeof(unsigned char) * (count) + \ 41e66f31c5Sopenharmony_ci sizeof(uintptr_t) * (count)) 42e66f31c5Sopenharmony_ci 43e66f31c5Sopenharmony_ci#define CHILD_STDIO_COUNT(buffer) \ 44e66f31c5Sopenharmony_ci *((unsigned int*) (buffer)) 45e66f31c5Sopenharmony_ci 46e66f31c5Sopenharmony_ci#define CHILD_STDIO_CRT_FLAGS(buffer, fd) \ 47e66f31c5Sopenharmony_ci *((unsigned char*) (buffer) + sizeof(int) + fd) 48e66f31c5Sopenharmony_ci 49e66f31c5Sopenharmony_ci#define CHILD_STDIO_HANDLE(buffer, fd) \ 50e66f31c5Sopenharmony_ci *((HANDLE*) ((unsigned char*) (buffer) + \ 51e66f31c5Sopenharmony_ci sizeof(int) + \ 52e66f31c5Sopenharmony_ci sizeof(unsigned char) * \ 53e66f31c5Sopenharmony_ci CHILD_STDIO_COUNT((buffer)) + \ 54e66f31c5Sopenharmony_ci sizeof(HANDLE) * (fd))) 55e66f31c5Sopenharmony_ci 56e66f31c5Sopenharmony_ci 57e66f31c5Sopenharmony_ci/* CRT file descriptor mode flags */ 58e66f31c5Sopenharmony_ci#define FOPEN 0x01 59e66f31c5Sopenharmony_ci#define FEOFLAG 0x02 60e66f31c5Sopenharmony_ci#define FCRLF 0x04 61e66f31c5Sopenharmony_ci#define FPIPE 0x08 62e66f31c5Sopenharmony_ci#define FNOINHERIT 0x10 63e66f31c5Sopenharmony_ci#define FAPPEND 0x20 64e66f31c5Sopenharmony_ci#define FDEV 0x40 65e66f31c5Sopenharmony_ci#define FTEXT 0x80 66e66f31c5Sopenharmony_ci 67e66f31c5Sopenharmony_ci 68e66f31c5Sopenharmony_ci/* 69e66f31c5Sopenharmony_ci * Clear the HANDLE_FLAG_INHERIT flag from all HANDLEs that were inherited 70e66f31c5Sopenharmony_ci * the parent process. Don't check for errors - the stdio handles may not be 71e66f31c5Sopenharmony_ci * valid, or may be closed already. There is no guarantee that this function 72e66f31c5Sopenharmony_ci * does a perfect job. 73e66f31c5Sopenharmony_ci */ 74e66f31c5Sopenharmony_civoid uv_disable_stdio_inheritance(void) { 75e66f31c5Sopenharmony_ci HANDLE handle; 76e66f31c5Sopenharmony_ci STARTUPINFOW si; 77e66f31c5Sopenharmony_ci 78e66f31c5Sopenharmony_ci /* Make the windows stdio handles non-inheritable. */ 79e66f31c5Sopenharmony_ci handle = GetStdHandle(STD_INPUT_HANDLE); 80e66f31c5Sopenharmony_ci if (handle != NULL && handle != INVALID_HANDLE_VALUE) 81e66f31c5Sopenharmony_ci SetHandleInformation(handle, HANDLE_FLAG_INHERIT, 0); 82e66f31c5Sopenharmony_ci 83e66f31c5Sopenharmony_ci handle = GetStdHandle(STD_OUTPUT_HANDLE); 84e66f31c5Sopenharmony_ci if (handle != NULL && handle != INVALID_HANDLE_VALUE) 85e66f31c5Sopenharmony_ci SetHandleInformation(handle, HANDLE_FLAG_INHERIT, 0); 86e66f31c5Sopenharmony_ci 87e66f31c5Sopenharmony_ci handle = GetStdHandle(STD_ERROR_HANDLE); 88e66f31c5Sopenharmony_ci if (handle != NULL && handle != INVALID_HANDLE_VALUE) 89e66f31c5Sopenharmony_ci SetHandleInformation(handle, HANDLE_FLAG_INHERIT, 0); 90e66f31c5Sopenharmony_ci 91e66f31c5Sopenharmony_ci /* Make inherited CRT FDs non-inheritable. */ 92e66f31c5Sopenharmony_ci GetStartupInfoW(&si); 93e66f31c5Sopenharmony_ci if (uv__stdio_verify(si.lpReserved2, si.cbReserved2)) 94e66f31c5Sopenharmony_ci uv__stdio_noinherit(si.lpReserved2); 95e66f31c5Sopenharmony_ci} 96e66f31c5Sopenharmony_ci 97e66f31c5Sopenharmony_ci 98e66f31c5Sopenharmony_cistatic int uv__duplicate_handle(uv_loop_t* loop, HANDLE handle, HANDLE* dup) { 99e66f31c5Sopenharmony_ci HANDLE current_process; 100e66f31c5Sopenharmony_ci 101e66f31c5Sopenharmony_ci 102e66f31c5Sopenharmony_ci /* _get_osfhandle will sometimes return -2 in case of an error. This seems to 103e66f31c5Sopenharmony_ci * happen when fd <= 2 and the process' corresponding stdio handle is set to 104e66f31c5Sopenharmony_ci * NULL. Unfortunately DuplicateHandle will happily duplicate (HANDLE) -2, so 105e66f31c5Sopenharmony_ci * this situation goes unnoticed until someone tries to use the duplicate. 106e66f31c5Sopenharmony_ci * Therefore we filter out known-invalid handles here. */ 107e66f31c5Sopenharmony_ci if (handle == INVALID_HANDLE_VALUE || 108e66f31c5Sopenharmony_ci handle == NULL || 109e66f31c5Sopenharmony_ci handle == (HANDLE) -2) { 110e66f31c5Sopenharmony_ci *dup = INVALID_HANDLE_VALUE; 111e66f31c5Sopenharmony_ci return ERROR_INVALID_HANDLE; 112e66f31c5Sopenharmony_ci } 113e66f31c5Sopenharmony_ci 114e66f31c5Sopenharmony_ci current_process = GetCurrentProcess(); 115e66f31c5Sopenharmony_ci 116e66f31c5Sopenharmony_ci if (!DuplicateHandle(current_process, 117e66f31c5Sopenharmony_ci handle, 118e66f31c5Sopenharmony_ci current_process, 119e66f31c5Sopenharmony_ci dup, 120e66f31c5Sopenharmony_ci 0, 121e66f31c5Sopenharmony_ci TRUE, 122e66f31c5Sopenharmony_ci DUPLICATE_SAME_ACCESS)) { 123e66f31c5Sopenharmony_ci *dup = INVALID_HANDLE_VALUE; 124e66f31c5Sopenharmony_ci return GetLastError(); 125e66f31c5Sopenharmony_ci } 126e66f31c5Sopenharmony_ci 127e66f31c5Sopenharmony_ci return 0; 128e66f31c5Sopenharmony_ci} 129e66f31c5Sopenharmony_ci 130e66f31c5Sopenharmony_ci 131e66f31c5Sopenharmony_cistatic int uv__duplicate_fd(uv_loop_t* loop, int fd, HANDLE* dup) { 132e66f31c5Sopenharmony_ci HANDLE handle; 133e66f31c5Sopenharmony_ci 134e66f31c5Sopenharmony_ci if (fd == -1) { 135e66f31c5Sopenharmony_ci *dup = INVALID_HANDLE_VALUE; 136e66f31c5Sopenharmony_ci return ERROR_INVALID_HANDLE; 137e66f31c5Sopenharmony_ci } 138e66f31c5Sopenharmony_ci 139e66f31c5Sopenharmony_ci handle = uv__get_osfhandle(fd); 140e66f31c5Sopenharmony_ci return uv__duplicate_handle(loop, handle, dup); 141e66f31c5Sopenharmony_ci} 142e66f31c5Sopenharmony_ci 143e66f31c5Sopenharmony_ci 144e66f31c5Sopenharmony_ciint uv__create_nul_handle(HANDLE* handle_ptr, 145e66f31c5Sopenharmony_ci DWORD access) { 146e66f31c5Sopenharmony_ci HANDLE handle; 147e66f31c5Sopenharmony_ci SECURITY_ATTRIBUTES sa; 148e66f31c5Sopenharmony_ci 149e66f31c5Sopenharmony_ci sa.nLength = sizeof sa; 150e66f31c5Sopenharmony_ci sa.lpSecurityDescriptor = NULL; 151e66f31c5Sopenharmony_ci sa.bInheritHandle = TRUE; 152e66f31c5Sopenharmony_ci 153e66f31c5Sopenharmony_ci handle = CreateFileW(L"NUL", 154e66f31c5Sopenharmony_ci access, 155e66f31c5Sopenharmony_ci FILE_SHARE_READ | FILE_SHARE_WRITE, 156e66f31c5Sopenharmony_ci &sa, 157e66f31c5Sopenharmony_ci OPEN_EXISTING, 158e66f31c5Sopenharmony_ci 0, 159e66f31c5Sopenharmony_ci NULL); 160e66f31c5Sopenharmony_ci if (handle == INVALID_HANDLE_VALUE) { 161e66f31c5Sopenharmony_ci return GetLastError(); 162e66f31c5Sopenharmony_ci } 163e66f31c5Sopenharmony_ci 164e66f31c5Sopenharmony_ci *handle_ptr = handle; 165e66f31c5Sopenharmony_ci return 0; 166e66f31c5Sopenharmony_ci} 167e66f31c5Sopenharmony_ci 168e66f31c5Sopenharmony_ci 169e66f31c5Sopenharmony_ciint uv__stdio_create(uv_loop_t* loop, 170e66f31c5Sopenharmony_ci const uv_process_options_t* options, 171e66f31c5Sopenharmony_ci BYTE** buffer_ptr) { 172e66f31c5Sopenharmony_ci BYTE* buffer; 173e66f31c5Sopenharmony_ci int count, i; 174e66f31c5Sopenharmony_ci int err; 175e66f31c5Sopenharmony_ci 176e66f31c5Sopenharmony_ci count = options->stdio_count; 177e66f31c5Sopenharmony_ci 178e66f31c5Sopenharmony_ci if (count < 0 || count > 255) { 179e66f31c5Sopenharmony_ci /* Only support FDs 0-255 */ 180e66f31c5Sopenharmony_ci return ERROR_NOT_SUPPORTED; 181e66f31c5Sopenharmony_ci } else if (count < 3) { 182e66f31c5Sopenharmony_ci /* There should always be at least 3 stdio handles. */ 183e66f31c5Sopenharmony_ci count = 3; 184e66f31c5Sopenharmony_ci } 185e66f31c5Sopenharmony_ci 186e66f31c5Sopenharmony_ci /* Allocate the child stdio buffer */ 187e66f31c5Sopenharmony_ci buffer = (BYTE*) uv__malloc(CHILD_STDIO_SIZE(count)); 188e66f31c5Sopenharmony_ci if (buffer == NULL) { 189e66f31c5Sopenharmony_ci return ERROR_OUTOFMEMORY; 190e66f31c5Sopenharmony_ci } 191e66f31c5Sopenharmony_ci 192e66f31c5Sopenharmony_ci /* Prepopulate the buffer with INVALID_HANDLE_VALUE handles so we can clean 193e66f31c5Sopenharmony_ci * up on failure. */ 194e66f31c5Sopenharmony_ci CHILD_STDIO_COUNT(buffer) = count; 195e66f31c5Sopenharmony_ci for (i = 0; i < count; i++) { 196e66f31c5Sopenharmony_ci CHILD_STDIO_CRT_FLAGS(buffer, i) = 0; 197e66f31c5Sopenharmony_ci CHILD_STDIO_HANDLE(buffer, i) = INVALID_HANDLE_VALUE; 198e66f31c5Sopenharmony_ci } 199e66f31c5Sopenharmony_ci 200e66f31c5Sopenharmony_ci for (i = 0; i < count; i++) { 201e66f31c5Sopenharmony_ci uv_stdio_container_t fdopt; 202e66f31c5Sopenharmony_ci if (i < options->stdio_count) { 203e66f31c5Sopenharmony_ci fdopt = options->stdio[i]; 204e66f31c5Sopenharmony_ci } else { 205e66f31c5Sopenharmony_ci fdopt.flags = UV_IGNORE; 206e66f31c5Sopenharmony_ci } 207e66f31c5Sopenharmony_ci 208e66f31c5Sopenharmony_ci switch (fdopt.flags & (UV_IGNORE | UV_CREATE_PIPE | UV_INHERIT_FD | 209e66f31c5Sopenharmony_ci UV_INHERIT_STREAM)) { 210e66f31c5Sopenharmony_ci case UV_IGNORE: 211e66f31c5Sopenharmony_ci /* Starting a process with no stdin/stout/stderr can confuse it. So no 212e66f31c5Sopenharmony_ci * matter what the user specified, we make sure the first three FDs are 213e66f31c5Sopenharmony_ci * always open in their typical modes, e. g. stdin be readable and 214e66f31c5Sopenharmony_ci * stdout/err should be writable. For FDs > 2, don't do anything - all 215e66f31c5Sopenharmony_ci * handles in the stdio buffer are initialized with. 216e66f31c5Sopenharmony_ci * INVALID_HANDLE_VALUE, which should be okay. */ 217e66f31c5Sopenharmony_ci if (i <= 2) { 218e66f31c5Sopenharmony_ci DWORD access = (i == 0) ? FILE_GENERIC_READ : 219e66f31c5Sopenharmony_ci FILE_GENERIC_WRITE | FILE_READ_ATTRIBUTES; 220e66f31c5Sopenharmony_ci 221e66f31c5Sopenharmony_ci err = uv__create_nul_handle(&CHILD_STDIO_HANDLE(buffer, i), 222e66f31c5Sopenharmony_ci access); 223e66f31c5Sopenharmony_ci if (err) 224e66f31c5Sopenharmony_ci goto error; 225e66f31c5Sopenharmony_ci 226e66f31c5Sopenharmony_ci CHILD_STDIO_CRT_FLAGS(buffer, i) = FOPEN | FDEV; 227e66f31c5Sopenharmony_ci } 228e66f31c5Sopenharmony_ci break; 229e66f31c5Sopenharmony_ci 230e66f31c5Sopenharmony_ci case UV_CREATE_PIPE: { 231e66f31c5Sopenharmony_ci /* Create a pair of two connected pipe ends; one end is turned into an 232e66f31c5Sopenharmony_ci * uv_pipe_t for use by the parent. The other one is given to the 233e66f31c5Sopenharmony_ci * child. */ 234e66f31c5Sopenharmony_ci uv_pipe_t* parent_pipe = (uv_pipe_t*) fdopt.data.stream; 235e66f31c5Sopenharmony_ci HANDLE child_pipe = INVALID_HANDLE_VALUE; 236e66f31c5Sopenharmony_ci 237e66f31c5Sopenharmony_ci /* Create a new, connected pipe pair. stdio[i]. stream should point to 238e66f31c5Sopenharmony_ci * an uninitialized, but not connected pipe handle. */ 239e66f31c5Sopenharmony_ci assert(fdopt.data.stream->type == UV_NAMED_PIPE); 240e66f31c5Sopenharmony_ci assert(!(fdopt.data.stream->flags & UV_HANDLE_CONNECTION)); 241e66f31c5Sopenharmony_ci assert(!(fdopt.data.stream->flags & UV_HANDLE_PIPESERVER)); 242e66f31c5Sopenharmony_ci 243e66f31c5Sopenharmony_ci err = uv__create_stdio_pipe_pair(loop, 244e66f31c5Sopenharmony_ci parent_pipe, 245e66f31c5Sopenharmony_ci &child_pipe, 246e66f31c5Sopenharmony_ci fdopt.flags); 247e66f31c5Sopenharmony_ci if (err) 248e66f31c5Sopenharmony_ci goto error; 249e66f31c5Sopenharmony_ci 250e66f31c5Sopenharmony_ci CHILD_STDIO_HANDLE(buffer, i) = child_pipe; 251e66f31c5Sopenharmony_ci CHILD_STDIO_CRT_FLAGS(buffer, i) = FOPEN | FPIPE; 252e66f31c5Sopenharmony_ci break; 253e66f31c5Sopenharmony_ci } 254e66f31c5Sopenharmony_ci 255e66f31c5Sopenharmony_ci case UV_INHERIT_FD: { 256e66f31c5Sopenharmony_ci /* Inherit a raw FD. */ 257e66f31c5Sopenharmony_ci HANDLE child_handle; 258e66f31c5Sopenharmony_ci 259e66f31c5Sopenharmony_ci /* Make an inheritable duplicate of the handle. */ 260e66f31c5Sopenharmony_ci err = uv__duplicate_fd(loop, fdopt.data.fd, &child_handle); 261e66f31c5Sopenharmony_ci if (err) { 262e66f31c5Sopenharmony_ci /* If fdopt. data. fd is not valid and fd <= 2, then ignore the 263e66f31c5Sopenharmony_ci * error. */ 264e66f31c5Sopenharmony_ci if (fdopt.data.fd <= 2 && err == ERROR_INVALID_HANDLE) { 265e66f31c5Sopenharmony_ci CHILD_STDIO_CRT_FLAGS(buffer, i) = 0; 266e66f31c5Sopenharmony_ci CHILD_STDIO_HANDLE(buffer, i) = INVALID_HANDLE_VALUE; 267e66f31c5Sopenharmony_ci break; 268e66f31c5Sopenharmony_ci } 269e66f31c5Sopenharmony_ci goto error; 270e66f31c5Sopenharmony_ci } 271e66f31c5Sopenharmony_ci 272e66f31c5Sopenharmony_ci /* Figure out what the type is. */ 273e66f31c5Sopenharmony_ci switch (GetFileType(child_handle)) { 274e66f31c5Sopenharmony_ci case FILE_TYPE_DISK: 275e66f31c5Sopenharmony_ci CHILD_STDIO_CRT_FLAGS(buffer, i) = FOPEN; 276e66f31c5Sopenharmony_ci break; 277e66f31c5Sopenharmony_ci 278e66f31c5Sopenharmony_ci case FILE_TYPE_PIPE: 279e66f31c5Sopenharmony_ci CHILD_STDIO_CRT_FLAGS(buffer, i) = FOPEN | FPIPE; 280e66f31c5Sopenharmony_ci break; 281e66f31c5Sopenharmony_ci 282e66f31c5Sopenharmony_ci case FILE_TYPE_CHAR: 283e66f31c5Sopenharmony_ci case FILE_TYPE_REMOTE: 284e66f31c5Sopenharmony_ci CHILD_STDIO_CRT_FLAGS(buffer, i) = FOPEN | FDEV; 285e66f31c5Sopenharmony_ci break; 286e66f31c5Sopenharmony_ci 287e66f31c5Sopenharmony_ci case FILE_TYPE_UNKNOWN: 288e66f31c5Sopenharmony_ci if (GetLastError() != 0) { 289e66f31c5Sopenharmony_ci err = GetLastError(); 290e66f31c5Sopenharmony_ci CloseHandle(child_handle); 291e66f31c5Sopenharmony_ci goto error; 292e66f31c5Sopenharmony_ci } 293e66f31c5Sopenharmony_ci CHILD_STDIO_CRT_FLAGS(buffer, i) = FOPEN | FDEV; 294e66f31c5Sopenharmony_ci break; 295e66f31c5Sopenharmony_ci 296e66f31c5Sopenharmony_ci default: 297e66f31c5Sopenharmony_ci assert(0); 298e66f31c5Sopenharmony_ci return -1; 299e66f31c5Sopenharmony_ci } 300e66f31c5Sopenharmony_ci 301e66f31c5Sopenharmony_ci CHILD_STDIO_HANDLE(buffer, i) = child_handle; 302e66f31c5Sopenharmony_ci break; 303e66f31c5Sopenharmony_ci } 304e66f31c5Sopenharmony_ci 305e66f31c5Sopenharmony_ci case UV_INHERIT_STREAM: { 306e66f31c5Sopenharmony_ci /* Use an existing stream as the stdio handle for the child. */ 307e66f31c5Sopenharmony_ci HANDLE stream_handle, child_handle; 308e66f31c5Sopenharmony_ci unsigned char crt_flags; 309e66f31c5Sopenharmony_ci uv_stream_t* stream = fdopt.data.stream; 310e66f31c5Sopenharmony_ci 311e66f31c5Sopenharmony_ci /* Leech the handle out of the stream. */ 312e66f31c5Sopenharmony_ci if (stream->type == UV_TTY) { 313e66f31c5Sopenharmony_ci stream_handle = ((uv_tty_t*) stream)->handle; 314e66f31c5Sopenharmony_ci crt_flags = FOPEN | FDEV; 315e66f31c5Sopenharmony_ci } else if (stream->type == UV_NAMED_PIPE && 316e66f31c5Sopenharmony_ci stream->flags & UV_HANDLE_CONNECTION) { 317e66f31c5Sopenharmony_ci stream_handle = ((uv_pipe_t*) stream)->handle; 318e66f31c5Sopenharmony_ci crt_flags = FOPEN | FPIPE; 319e66f31c5Sopenharmony_ci } else { 320e66f31c5Sopenharmony_ci stream_handle = INVALID_HANDLE_VALUE; 321e66f31c5Sopenharmony_ci crt_flags = 0; 322e66f31c5Sopenharmony_ci } 323e66f31c5Sopenharmony_ci 324e66f31c5Sopenharmony_ci if (stream_handle == NULL || 325e66f31c5Sopenharmony_ci stream_handle == INVALID_HANDLE_VALUE) { 326e66f31c5Sopenharmony_ci /* The handle is already closed, or not yet created, or the stream 327e66f31c5Sopenharmony_ci * type is not supported. */ 328e66f31c5Sopenharmony_ci err = ERROR_NOT_SUPPORTED; 329e66f31c5Sopenharmony_ci goto error; 330e66f31c5Sopenharmony_ci } 331e66f31c5Sopenharmony_ci 332e66f31c5Sopenharmony_ci /* Make an inheritable copy of the handle. */ 333e66f31c5Sopenharmony_ci err = uv__duplicate_handle(loop, stream_handle, &child_handle); 334e66f31c5Sopenharmony_ci if (err) 335e66f31c5Sopenharmony_ci goto error; 336e66f31c5Sopenharmony_ci 337e66f31c5Sopenharmony_ci CHILD_STDIO_HANDLE(buffer, i) = child_handle; 338e66f31c5Sopenharmony_ci CHILD_STDIO_CRT_FLAGS(buffer, i) = crt_flags; 339e66f31c5Sopenharmony_ci break; 340e66f31c5Sopenharmony_ci } 341e66f31c5Sopenharmony_ci 342e66f31c5Sopenharmony_ci default: 343e66f31c5Sopenharmony_ci assert(0); 344e66f31c5Sopenharmony_ci return -1; 345e66f31c5Sopenharmony_ci } 346e66f31c5Sopenharmony_ci } 347e66f31c5Sopenharmony_ci 348e66f31c5Sopenharmony_ci *buffer_ptr = buffer; 349e66f31c5Sopenharmony_ci return 0; 350e66f31c5Sopenharmony_ci 351e66f31c5Sopenharmony_ci error: 352e66f31c5Sopenharmony_ci uv__stdio_destroy(buffer); 353e66f31c5Sopenharmony_ci return err; 354e66f31c5Sopenharmony_ci} 355e66f31c5Sopenharmony_ci 356e66f31c5Sopenharmony_ci 357e66f31c5Sopenharmony_civoid uv__stdio_destroy(BYTE* buffer) { 358e66f31c5Sopenharmony_ci int i, count; 359e66f31c5Sopenharmony_ci 360e66f31c5Sopenharmony_ci count = CHILD_STDIO_COUNT(buffer); 361e66f31c5Sopenharmony_ci for (i = 0; i < count; i++) { 362e66f31c5Sopenharmony_ci HANDLE handle = CHILD_STDIO_HANDLE(buffer, i); 363e66f31c5Sopenharmony_ci if (handle != INVALID_HANDLE_VALUE) { 364e66f31c5Sopenharmony_ci CloseHandle(handle); 365e66f31c5Sopenharmony_ci } 366e66f31c5Sopenharmony_ci } 367e66f31c5Sopenharmony_ci 368e66f31c5Sopenharmony_ci uv__free(buffer); 369e66f31c5Sopenharmony_ci} 370e66f31c5Sopenharmony_ci 371e66f31c5Sopenharmony_ci 372e66f31c5Sopenharmony_civoid uv__stdio_noinherit(BYTE* buffer) { 373e66f31c5Sopenharmony_ci int i, count; 374e66f31c5Sopenharmony_ci 375e66f31c5Sopenharmony_ci count = CHILD_STDIO_COUNT(buffer); 376e66f31c5Sopenharmony_ci for (i = 0; i < count; i++) { 377e66f31c5Sopenharmony_ci HANDLE handle = CHILD_STDIO_HANDLE(buffer, i); 378e66f31c5Sopenharmony_ci if (handle != INVALID_HANDLE_VALUE) { 379e66f31c5Sopenharmony_ci SetHandleInformation(handle, HANDLE_FLAG_INHERIT, 0); 380e66f31c5Sopenharmony_ci } 381e66f31c5Sopenharmony_ci } 382e66f31c5Sopenharmony_ci} 383e66f31c5Sopenharmony_ci 384e66f31c5Sopenharmony_ci 385e66f31c5Sopenharmony_ciint uv__stdio_verify(BYTE* buffer, WORD size) { 386e66f31c5Sopenharmony_ci unsigned int count; 387e66f31c5Sopenharmony_ci 388e66f31c5Sopenharmony_ci /* Check the buffer pointer. */ 389e66f31c5Sopenharmony_ci if (buffer == NULL) 390e66f31c5Sopenharmony_ci return 0; 391e66f31c5Sopenharmony_ci 392e66f31c5Sopenharmony_ci /* Verify that the buffer is at least big enough to hold the count. */ 393e66f31c5Sopenharmony_ci if (size < CHILD_STDIO_SIZE(0)) 394e66f31c5Sopenharmony_ci return 0; 395e66f31c5Sopenharmony_ci 396e66f31c5Sopenharmony_ci /* Verify if the count is within range. */ 397e66f31c5Sopenharmony_ci count = CHILD_STDIO_COUNT(buffer); 398e66f31c5Sopenharmony_ci if (count > 256) 399e66f31c5Sopenharmony_ci return 0; 400e66f31c5Sopenharmony_ci 401e66f31c5Sopenharmony_ci /* Verify that the buffer size is big enough to hold info for N FDs. */ 402e66f31c5Sopenharmony_ci if (size < CHILD_STDIO_SIZE(count)) 403e66f31c5Sopenharmony_ci return 0; 404e66f31c5Sopenharmony_ci 405e66f31c5Sopenharmony_ci return 1; 406e66f31c5Sopenharmony_ci} 407e66f31c5Sopenharmony_ci 408e66f31c5Sopenharmony_ci 409e66f31c5Sopenharmony_ciWORD uv__stdio_size(BYTE* buffer) { 410e66f31c5Sopenharmony_ci return (WORD) CHILD_STDIO_SIZE(CHILD_STDIO_COUNT((buffer))); 411e66f31c5Sopenharmony_ci} 412e66f31c5Sopenharmony_ci 413e66f31c5Sopenharmony_ci 414e66f31c5Sopenharmony_ciHANDLE uv__stdio_handle(BYTE* buffer, int fd) { 415e66f31c5Sopenharmony_ci return CHILD_STDIO_HANDLE(buffer, fd); 416e66f31c5Sopenharmony_ci} 417