diff --git a/src/win/pipe.c b/src/win/pipe.c index 15a29592..74a8c45f 100644 --- a/src/win/pipe.c +++ b/src/win/pipe.c @@ -356,15 +356,22 @@ static int uv_set_pipe_handle(uv_loop_t* loop, uv_pipe_t* handle, NTSTATUS nt_status; IO_STATUS_BLOCK io_status; FILE_MODE_INFORMATION mode_info; - DWORD mode = PIPE_TYPE_BYTE | PIPE_READMODE_BYTE | PIPE_WAIT; + DWORD oldmode, mode = PIPE_READMODE_BYTE | PIPE_WAIT; - if (!SetNamedPipeHandleState(pipeHandle, &mode, NULL, NULL)) { + if (!GetNamedPipeHandleState(pipeHandle, &oldmode, NULL, NULL, NULL, NULL, 0)) { + oldmode = PIPE_READMODE_MESSAGE | PIPE_NOWAIT; // assume the worst + } + + if (oldmode != mode && !SetNamedPipeHandleState(pipeHandle, &mode, NULL, NULL)) { /* If this returns ERROR_INVALID_PARAMETER we probably opened something */ /* that is not a pipe. */ if (GetLastError() == ERROR_INVALID_PARAMETER) { SetLastError(WSAENOTSOCK); + return -1; + } + if (oldmode & PIPE_NOWAIT) { + return -1; } - return -1; } /* Check if the pipe was created with FILE_FLAG_OVERLAPPED. */ @@ -1844,16 +1851,57 @@ static void eof_timer_close_cb(uv_handle_t* handle) { int uv_pipe_open(uv_pipe_t* pipe, uv_file file) { - HANDLE os_handle = (HANDLE)_get_osfhandle(file); + HANDLE os_handle = (HANDLE)_get_osfhandle(file), os_handle2; + NTSTATUS nt_status; + IO_STATUS_BLOCK io_status; + FILE_ACCESS_INFORMATION access; + + /* Try to duplicate the file handle, with FILE_WRITE_ATTRIBUTES access */ + nt_status = pNtQueryInformationFile(os_handle, + &io_status, + &access, + sizeof(access), + FileAccessInformation); + if (nt_status != STATUS_SUCCESS) { + return UV_EINVAL; + } + + if (pipe->flags&UV_HANDLE_PIPE_IPC) { + if (!(access.AccessFlags&FILE_WRITE_DATA) || + !(access.AccessFlags&FILE_READ_DATA)){ + return UV_EINVAL; + } + } + + if (!DuplicateHandle(GetCurrentProcess(), + os_handle, + GetCurrentProcess(), + &os_handle2, + access.AccessFlags|FILE_WRITE_ATTRIBUTES, + TRUE, + 0)) { + if (!DuplicateHandle(GetCurrentProcess(), + os_handle, + GetCurrentProcess(), + &os_handle2, + access.AccessFlags, + TRUE, + 0)) { + return UV_EINVAL; + } + } if (os_handle == INVALID_HANDLE_VALUE || - uv_set_pipe_handle(pipe->loop, pipe, os_handle, 0) == -1) { + uv_set_pipe_handle(pipe->loop, pipe, os_handle2, 0) == -1) { return UV_EINVAL; } uv_pipe_connection_init(pipe); pipe->handle = os_handle; - pipe->flags |= UV_HANDLE_READABLE | UV_HANDLE_WRITABLE; + if (access.AccessFlags&FILE_WRITE_DATA) + pipe->flags |= UV_HANDLE_READABLE; + if (access.AccessFlags&FILE_READ_DATA) + pipe->flags |= UV_HANDLE_WRITABLE; if (pipe->flags&UV_HANDLE_PIPE_IPC) { assert(!(pipe->flags & UV_HANDLE_NON_OVERLAPPED_PIPE)); diff --git a/src/win/tty.c b/src/win/tty.c index c2c8d01e..a4258e6e 100644 --- a/src/win/tty.c +++ b/src/win/tty.c @@ -96,11 +96,20 @@ void uv_console_init() { int uv_tty_init(uv_loop_t* loop, uv_tty_t* tty, uv_file fd, int readable) { - HANDLE handle; + HANDLE handle, os_handle; CONSOLE_SCREEN_BUFFER_INFO screen_buffer_info; - handle = (HANDLE) _get_osfhandle(fd); - if (handle == INVALID_HANDLE_VALUE) { + os_handle = (HANDLE) _get_osfhandle(fd); + if (os_handle == INVALID_HANDLE_VALUE) { + return UV_EBADF; + } + if (!DuplicateHandle(GetCurrentProcess(), + os_handle, + GetCurrentProcess(), + &handle, + 0, + TRUE, + DUPLICATE_SAME_ACCESS)) { return UV_EBADF; } diff --git a/src/win/winapi.h b/src/win/winapi.h index e023beed..fcd6f629 100644 --- a/src/win/winapi.h +++ b/src/win/winapi.h @@ -4124,6 +4124,10 @@ typedef struct _FILE_PIPE_LOCAL_INFORMATION { ULONG NamedPipeEnd; } FILE_PIPE_LOCAL_INFORMATION, *PFILE_PIPE_LOCAL_INFORMATION; +typedef struct _FILE_ACCESS_INFORMATION { + ULONG AccessFlags; +} FILE_ACCESS_INFORMATION, *PFILE_ACCESS_INFORMATION; + typedef struct _FILE_BASIC_INFORMATION { LARGE_INTEGER CreationTime; LARGE_INTEGER LastAccessTime;