156513f5ff4f3e851c5f0cb38dc8851d18616b3c0Jesse Hall/* 256513f5ff4f3e851c5f0cb38dc8851d18616b3c0Jesse Hall* Copyright (C) 2011 The Android Open Source Project 356513f5ff4f3e851c5f0cb38dc8851d18616b3c0Jesse Hall* 456513f5ff4f3e851c5f0cb38dc8851d18616b3c0Jesse Hall* Licensed under the Apache License, Version 2.0 (the "License"); 556513f5ff4f3e851c5f0cb38dc8851d18616b3c0Jesse Hall* you may not use this file except in compliance with the License. 656513f5ff4f3e851c5f0cb38dc8851d18616b3c0Jesse Hall* You may obtain a copy of the License at 756513f5ff4f3e851c5f0cb38dc8851d18616b3c0Jesse Hall* 856513f5ff4f3e851c5f0cb38dc8851d18616b3c0Jesse Hall* http://www.apache.org/licenses/LICENSE-2.0 956513f5ff4f3e851c5f0cb38dc8851d18616b3c0Jesse Hall* 1056513f5ff4f3e851c5f0cb38dc8851d18616b3c0Jesse Hall* Unless required by applicable law or agreed to in writing, software 1156513f5ff4f3e851c5f0cb38dc8851d18616b3c0Jesse Hall* distributed under the License is distributed on an "AS IS" BASIS, 1256513f5ff4f3e851c5f0cb38dc8851d18616b3c0Jesse Hall* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1356513f5ff4f3e851c5f0cb38dc8851d18616b3c0Jesse Hall* See the License for the specific language governing permissions and 1456513f5ff4f3e851c5f0cb38dc8851d18616b3c0Jesse Hall* limitations under the License. 1556513f5ff4f3e851c5f0cb38dc8851d18616b3c0Jesse Hall*/ 1656513f5ff4f3e851c5f0cb38dc8851d18616b3c0Jesse Hall#include "Win32PipeStream.h" 1756513f5ff4f3e851c5f0cb38dc8851d18616b3c0Jesse Hall 1856513f5ff4f3e851c5f0cb38dc8851d18616b3c0Jesse Hall#include <errno.h> 1956513f5ff4f3e851c5f0cb38dc8851d18616b3c0Jesse Hall#include <stdio.h> 2056513f5ff4f3e851c5f0cb38dc8851d18616b3c0Jesse Hall#include <stdlib.h> 2156513f5ff4f3e851c5f0cb38dc8851d18616b3c0Jesse Hall#include <unistd.h> 2256513f5ff4f3e851c5f0cb38dc8851d18616b3c0Jesse Hall#include <string.h> 2356513f5ff4f3e851c5f0cb38dc8851d18616b3c0Jesse Hall#include <windows.h> 2456513f5ff4f3e851c5f0cb38dc8851d18616b3c0Jesse Hall 2556513f5ff4f3e851c5f0cb38dc8851d18616b3c0Jesse Hall#ifndef _WIN32 2656513f5ff4f3e851c5f0cb38dc8851d18616b3c0Jesse Hall#error ONLY BUILD THIS SOURCE FILE FOR WINDOWS! 2756513f5ff4f3e851c5f0cb38dc8851d18616b3c0Jesse Hall#endif 2856513f5ff4f3e851c5f0cb38dc8851d18616b3c0Jesse Hall 2956513f5ff4f3e851c5f0cb38dc8851d18616b3c0Jesse Hall/* The official documentation states that the name of a given named 3056513f5ff4f3e851c5f0cb38dc8851d18616b3c0Jesse Hall * pipe cannot be more than 256 characters long. 3156513f5ff4f3e851c5f0cb38dc8851d18616b3c0Jesse Hall */ 3256513f5ff4f3e851c5f0cb38dc8851d18616b3c0Jesse Hall#define NAMED_PIPE_MAX 256 3356513f5ff4f3e851c5f0cb38dc8851d18616b3c0Jesse Hall 3456513f5ff4f3e851c5f0cb38dc8851d18616b3c0Jesse HallWin32PipeStream::Win32PipeStream(size_t bufSize) : 3556513f5ff4f3e851c5f0cb38dc8851d18616b3c0Jesse Hall SocketStream(bufSize), 3656513f5ff4f3e851c5f0cb38dc8851d18616b3c0Jesse Hall m_pipe(INVALID_HANDLE_VALUE) 3756513f5ff4f3e851c5f0cb38dc8851d18616b3c0Jesse Hall{ 3856513f5ff4f3e851c5f0cb38dc8851d18616b3c0Jesse Hall} 3956513f5ff4f3e851c5f0cb38dc8851d18616b3c0Jesse Hall 4056513f5ff4f3e851c5f0cb38dc8851d18616b3c0Jesse HallWin32PipeStream::Win32PipeStream(HANDLE pipe, size_t bufSize) : 4156513f5ff4f3e851c5f0cb38dc8851d18616b3c0Jesse Hall SocketStream(-1, bufSize), 4256513f5ff4f3e851c5f0cb38dc8851d18616b3c0Jesse Hall m_pipe(pipe) 4356513f5ff4f3e851c5f0cb38dc8851d18616b3c0Jesse Hall{ 4456513f5ff4f3e851c5f0cb38dc8851d18616b3c0Jesse Hall} 4556513f5ff4f3e851c5f0cb38dc8851d18616b3c0Jesse Hall 4656513f5ff4f3e851c5f0cb38dc8851d18616b3c0Jesse HallWin32PipeStream::~Win32PipeStream() 4756513f5ff4f3e851c5f0cb38dc8851d18616b3c0Jesse Hall{ 4856513f5ff4f3e851c5f0cb38dc8851d18616b3c0Jesse Hall if (m_pipe != INVALID_HANDLE_VALUE) { 4956513f5ff4f3e851c5f0cb38dc8851d18616b3c0Jesse Hall CloseHandle(m_pipe); 5056513f5ff4f3e851c5f0cb38dc8851d18616b3c0Jesse Hall m_pipe = INVALID_HANDLE_VALUE; 5156513f5ff4f3e851c5f0cb38dc8851d18616b3c0Jesse Hall } 5256513f5ff4f3e851c5f0cb38dc8851d18616b3c0Jesse Hall} 5356513f5ff4f3e851c5f0cb38dc8851d18616b3c0Jesse Hall 5456513f5ff4f3e851c5f0cb38dc8851d18616b3c0Jesse Hall/* Initialize the pipe name corresponding to a given port 5556513f5ff4f3e851c5f0cb38dc8851d18616b3c0Jesse Hall */ 5656513f5ff4f3e851c5f0cb38dc8851d18616b3c0Jesse Hallstatic void 5756513f5ff4f3e851c5f0cb38dc8851d18616b3c0Jesse Hallmake_pipe_name(char *path, size_t pathlen, int port_number) 5856513f5ff4f3e851c5f0cb38dc8851d18616b3c0Jesse Hall{ 5956513f5ff4f3e851c5f0cb38dc8851d18616b3c0Jesse Hall snprintf(path, pathlen, "\\\\.\\pipe\\qemu-gles-%d", port_number); 6056513f5ff4f3e851c5f0cb38dc8851d18616b3c0Jesse Hall} 6156513f5ff4f3e851c5f0cb38dc8851d18616b3c0Jesse Hall 6256513f5ff4f3e851c5f0cb38dc8851d18616b3c0Jesse Hall 6356513f5ff4f3e851c5f0cb38dc8851d18616b3c0Jesse Hall/* Technical note: Named pipes work differently from BSD Sockets. 6456513f5ff4f3e851c5f0cb38dc8851d18616b3c0Jesse Hall * One does not create/bind a pipe, and collect a new handle each 6556513f5ff4f3e851c5f0cb38dc8851d18616b3c0Jesse Hall * time a client connects with accept(). 6656513f5ff4f3e851c5f0cb38dc8851d18616b3c0Jesse Hall * 6756513f5ff4f3e851c5f0cb38dc8851d18616b3c0Jesse Hall * Instead, the server creates a new pipe instance each time it wants 6856513f5ff4f3e851c5f0cb38dc8851d18616b3c0Jesse Hall * to get a new client connection, then calls ConnectNamedPipe() to 6956513f5ff4f3e851c5f0cb38dc8851d18616b3c0Jesse Hall * wait for a connection. 7056513f5ff4f3e851c5f0cb38dc8851d18616b3c0Jesse Hall * 7156513f5ff4f3e851c5f0cb38dc8851d18616b3c0Jesse Hall * So listen() is a no-op, and accept() really creates the pipe handle. 7256513f5ff4f3e851c5f0cb38dc8851d18616b3c0Jesse Hall * 7356513f5ff4f3e851c5f0cb38dc8851d18616b3c0Jesse Hall * Also, connect() must create a pipe handle with CreateFile() and 7456513f5ff4f3e851c5f0cb38dc8851d18616b3c0Jesse Hall * wait for a server instance with WaitNamedPipe() 7556513f5ff4f3e851c5f0cb38dc8851d18616b3c0Jesse Hall */ 7656513f5ff4f3e851c5f0cb38dc8851d18616b3c0Jesse Hallint Win32PipeStream::listen(unsigned short port) 7756513f5ff4f3e851c5f0cb38dc8851d18616b3c0Jesse Hall{ 7856513f5ff4f3e851c5f0cb38dc8851d18616b3c0Jesse Hall // just save the port number for accept() 7956513f5ff4f3e851c5f0cb38dc8851d18616b3c0Jesse Hall m_port = port; 8056513f5ff4f3e851c5f0cb38dc8851d18616b3c0Jesse Hall return 0; 8156513f5ff4f3e851c5f0cb38dc8851d18616b3c0Jesse Hall} 8256513f5ff4f3e851c5f0cb38dc8851d18616b3c0Jesse Hall 8356513f5ff4f3e851c5f0cb38dc8851d18616b3c0Jesse HallSocketStream * Win32PipeStream::accept() 8456513f5ff4f3e851c5f0cb38dc8851d18616b3c0Jesse Hall{ 8556513f5ff4f3e851c5f0cb38dc8851d18616b3c0Jesse Hall char path[NAMED_PIPE_MAX+1]; 8656513f5ff4f3e851c5f0cb38dc8851d18616b3c0Jesse Hall SocketStream* clientStream; 8756513f5ff4f3e851c5f0cb38dc8851d18616b3c0Jesse Hall HANDLE pipe; 8856513f5ff4f3e851c5f0cb38dc8851d18616b3c0Jesse Hall 8956513f5ff4f3e851c5f0cb38dc8851d18616b3c0Jesse Hall make_pipe_name(path, sizeof(path), m_port); 9056513f5ff4f3e851c5f0cb38dc8851d18616b3c0Jesse Hall 9156513f5ff4f3e851c5f0cb38dc8851d18616b3c0Jesse Hall pipe = ::CreateNamedPipe( 9256513f5ff4f3e851c5f0cb38dc8851d18616b3c0Jesse Hall path, // pipe name 9356513f5ff4f3e851c5f0cb38dc8851d18616b3c0Jesse Hall PIPE_ACCESS_DUPLEX, // read-write access 9456513f5ff4f3e851c5f0cb38dc8851d18616b3c0Jesse Hall PIPE_TYPE_BYTE | // byte-oriented writes 9556513f5ff4f3e851c5f0cb38dc8851d18616b3c0Jesse Hall PIPE_READMODE_BYTE | // byte-oriented reads 9656513f5ff4f3e851c5f0cb38dc8851d18616b3c0Jesse Hall PIPE_WAIT, // blocking operations 9756513f5ff4f3e851c5f0cb38dc8851d18616b3c0Jesse Hall PIPE_UNLIMITED_INSTANCES, // no limit on clients 9856513f5ff4f3e851c5f0cb38dc8851d18616b3c0Jesse Hall 4096, // input buffer size 9956513f5ff4f3e851c5f0cb38dc8851d18616b3c0Jesse Hall 4096, // output buffer size 10056513f5ff4f3e851c5f0cb38dc8851d18616b3c0Jesse Hall 0, // client time-out 10156513f5ff4f3e851c5f0cb38dc8851d18616b3c0Jesse Hall NULL); // default security attributes 10256513f5ff4f3e851c5f0cb38dc8851d18616b3c0Jesse Hall 10356513f5ff4f3e851c5f0cb38dc8851d18616b3c0Jesse Hall if (pipe == INVALID_HANDLE_VALUE) { 10456513f5ff4f3e851c5f0cb38dc8851d18616b3c0Jesse Hall ERR("%s: CreateNamedPipe failed %d\n", __FUNCTION__, (int)GetLastError()); 10556513f5ff4f3e851c5f0cb38dc8851d18616b3c0Jesse Hall return NULL; 10656513f5ff4f3e851c5f0cb38dc8851d18616b3c0Jesse Hall } 10756513f5ff4f3e851c5f0cb38dc8851d18616b3c0Jesse Hall 10856513f5ff4f3e851c5f0cb38dc8851d18616b3c0Jesse Hall // Stupid Win32 API design: If a client is already connected, then 10956513f5ff4f3e851c5f0cb38dc8851d18616b3c0Jesse Hall // ConnectNamedPipe will return 0, and GetLastError() will return 11056513f5ff4f3e851c5f0cb38dc8851d18616b3c0Jesse Hall // ERROR_PIPE_CONNECTED. This is not an error! It just means that the 11156513f5ff4f3e851c5f0cb38dc8851d18616b3c0Jesse Hall // function didn't have to wait. 11256513f5ff4f3e851c5f0cb38dc8851d18616b3c0Jesse Hall // 11356513f5ff4f3e851c5f0cb38dc8851d18616b3c0Jesse Hall if (::ConnectNamedPipe(pipe, NULL) == 0 && GetLastError() != ERROR_PIPE_CONNECTED) { 11456513f5ff4f3e851c5f0cb38dc8851d18616b3c0Jesse Hall ERR("%s: ConnectNamedPipe failed: %d\n", __FUNCTION__, (int)GetLastError()); 11556513f5ff4f3e851c5f0cb38dc8851d18616b3c0Jesse Hall CloseHandle(pipe); 11656513f5ff4f3e851c5f0cb38dc8851d18616b3c0Jesse Hall return NULL; 11756513f5ff4f3e851c5f0cb38dc8851d18616b3c0Jesse Hall } 11856513f5ff4f3e851c5f0cb38dc8851d18616b3c0Jesse Hall 11956513f5ff4f3e851c5f0cb38dc8851d18616b3c0Jesse Hall clientStream = new Win32PipeStream(pipe, m_bufsize); 12056513f5ff4f3e851c5f0cb38dc8851d18616b3c0Jesse Hall return clientStream; 12156513f5ff4f3e851c5f0cb38dc8851d18616b3c0Jesse Hall} 12256513f5ff4f3e851c5f0cb38dc8851d18616b3c0Jesse Hall 12356513f5ff4f3e851c5f0cb38dc8851d18616b3c0Jesse Hallint Win32PipeStream::connect(unsigned short port) 12456513f5ff4f3e851c5f0cb38dc8851d18616b3c0Jesse Hall{ 12556513f5ff4f3e851c5f0cb38dc8851d18616b3c0Jesse Hall char path[NAMED_PIPE_MAX+1]; 12656513f5ff4f3e851c5f0cb38dc8851d18616b3c0Jesse Hall HANDLE pipe; 12756513f5ff4f3e851c5f0cb38dc8851d18616b3c0Jesse Hall int tries = 10; 12856513f5ff4f3e851c5f0cb38dc8851d18616b3c0Jesse Hall 12956513f5ff4f3e851c5f0cb38dc8851d18616b3c0Jesse Hall make_pipe_name(path, sizeof(path), port); 13056513f5ff4f3e851c5f0cb38dc8851d18616b3c0Jesse Hall 13156513f5ff4f3e851c5f0cb38dc8851d18616b3c0Jesse Hall /* We're going to loop in order to wait for the pipe server to 13256513f5ff4f3e851c5f0cb38dc8851d18616b3c0Jesse Hall * be setup properly. 13356513f5ff4f3e851c5f0cb38dc8851d18616b3c0Jesse Hall */ 13456513f5ff4f3e851c5f0cb38dc8851d18616b3c0Jesse Hall for (; tries > 0; tries--) { 13556513f5ff4f3e851c5f0cb38dc8851d18616b3c0Jesse Hall pipe = ::CreateFile( 13656513f5ff4f3e851c5f0cb38dc8851d18616b3c0Jesse Hall path, // pipe name 13756513f5ff4f3e851c5f0cb38dc8851d18616b3c0Jesse Hall GENERIC_READ | GENERIC_WRITE, // read & write 13856513f5ff4f3e851c5f0cb38dc8851d18616b3c0Jesse Hall 0, // no sharing 13956513f5ff4f3e851c5f0cb38dc8851d18616b3c0Jesse Hall NULL, // default security attrs 14056513f5ff4f3e851c5f0cb38dc8851d18616b3c0Jesse Hall OPEN_EXISTING, // open existing pipe 14156513f5ff4f3e851c5f0cb38dc8851d18616b3c0Jesse Hall 0, // default attributes 14256513f5ff4f3e851c5f0cb38dc8851d18616b3c0Jesse Hall NULL); // no template file 14356513f5ff4f3e851c5f0cb38dc8851d18616b3c0Jesse Hall 14456513f5ff4f3e851c5f0cb38dc8851d18616b3c0Jesse Hall /* If we have a valid pipe handle, break from the loop */ 14556513f5ff4f3e851c5f0cb38dc8851d18616b3c0Jesse Hall if (pipe != INVALID_HANDLE_VALUE) { 14656513f5ff4f3e851c5f0cb38dc8851d18616b3c0Jesse Hall break; 14756513f5ff4f3e851c5f0cb38dc8851d18616b3c0Jesse Hall } 14856513f5ff4f3e851c5f0cb38dc8851d18616b3c0Jesse Hall 14956513f5ff4f3e851c5f0cb38dc8851d18616b3c0Jesse Hall /* We can get here if the pipe is busy, i.e. if the server hasn't 15056513f5ff4f3e851c5f0cb38dc8851d18616b3c0Jesse Hall * create a new pipe instance to service our request. In which case 15156513f5ff4f3e851c5f0cb38dc8851d18616b3c0Jesse Hall * GetLastError() will return ERROR_PIPE_BUSY. 15256513f5ff4f3e851c5f0cb38dc8851d18616b3c0Jesse Hall * 15356513f5ff4f3e851c5f0cb38dc8851d18616b3c0Jesse Hall * If so, then use WaitNamedPipe() to wait for a decent time 15456513f5ff4f3e851c5f0cb38dc8851d18616b3c0Jesse Hall * to try again. 15556513f5ff4f3e851c5f0cb38dc8851d18616b3c0Jesse Hall */ 15656513f5ff4f3e851c5f0cb38dc8851d18616b3c0Jesse Hall if (GetLastError() != ERROR_PIPE_BUSY) { 15756513f5ff4f3e851c5f0cb38dc8851d18616b3c0Jesse Hall /* Not ERROR_PIPE_BUSY */ 15856513f5ff4f3e851c5f0cb38dc8851d18616b3c0Jesse Hall ERR("%s: CreateFile failed: %d\n", __FUNCTION__, (int)GetLastError()); 15956513f5ff4f3e851c5f0cb38dc8851d18616b3c0Jesse Hall errno = EINVAL; 16056513f5ff4f3e851c5f0cb38dc8851d18616b3c0Jesse Hall return -1; 16156513f5ff4f3e851c5f0cb38dc8851d18616b3c0Jesse Hall } 16256513f5ff4f3e851c5f0cb38dc8851d18616b3c0Jesse Hall 16356513f5ff4f3e851c5f0cb38dc8851d18616b3c0Jesse Hall /* Wait for 5 seconds */ 16456513f5ff4f3e851c5f0cb38dc8851d18616b3c0Jesse Hall if ( !WaitNamedPipe(path, 5000) ) { 16556513f5ff4f3e851c5f0cb38dc8851d18616b3c0Jesse Hall ERR("%s: WaitNamedPipe failed: %d\n", __FUNCTION__, (int)GetLastError()); 16656513f5ff4f3e851c5f0cb38dc8851d18616b3c0Jesse Hall errno = EINVAL; 16756513f5ff4f3e851c5f0cb38dc8851d18616b3c0Jesse Hall return -1; 16856513f5ff4f3e851c5f0cb38dc8851d18616b3c0Jesse Hall } 16956513f5ff4f3e851c5f0cb38dc8851d18616b3c0Jesse Hall } 17056513f5ff4f3e851c5f0cb38dc8851d18616b3c0Jesse Hall 17156513f5ff4f3e851c5f0cb38dc8851d18616b3c0Jesse Hall m_pipe = pipe; 17256513f5ff4f3e851c5f0cb38dc8851d18616b3c0Jesse Hall return 0; 17356513f5ff4f3e851c5f0cb38dc8851d18616b3c0Jesse Hall} 17456513f5ff4f3e851c5f0cb38dc8851d18616b3c0Jesse Hall 17556513f5ff4f3e851c5f0cb38dc8851d18616b3c0Jesse Hall/* Special buffer methods, since we can't use socket functions here */ 17656513f5ff4f3e851c5f0cb38dc8851d18616b3c0Jesse Hall 17756513f5ff4f3e851c5f0cb38dc8851d18616b3c0Jesse Hallint Win32PipeStream::commitBuffer(size_t size) 17856513f5ff4f3e851c5f0cb38dc8851d18616b3c0Jesse Hall{ 17956513f5ff4f3e851c5f0cb38dc8851d18616b3c0Jesse Hall if (m_pipe == INVALID_HANDLE_VALUE) 18056513f5ff4f3e851c5f0cb38dc8851d18616b3c0Jesse Hall return -1; 18156513f5ff4f3e851c5f0cb38dc8851d18616b3c0Jesse Hall 18256513f5ff4f3e851c5f0cb38dc8851d18616b3c0Jesse Hall size_t res = size; 18356513f5ff4f3e851c5f0cb38dc8851d18616b3c0Jesse Hall int retval = 0; 18456513f5ff4f3e851c5f0cb38dc8851d18616b3c0Jesse Hall 18556513f5ff4f3e851c5f0cb38dc8851d18616b3c0Jesse Hall while (res > 0) { 18656513f5ff4f3e851c5f0cb38dc8851d18616b3c0Jesse Hall DWORD written; 18756513f5ff4f3e851c5f0cb38dc8851d18616b3c0Jesse Hall if (! ::WriteFile(m_pipe, (const char *)m_buf + (size - res), res, &written, NULL)) { 18856513f5ff4f3e851c5f0cb38dc8851d18616b3c0Jesse Hall retval = -1; 18956513f5ff4f3e851c5f0cb38dc8851d18616b3c0Jesse Hall ERR("%s: failed: %d\n", __FUNCTION__, (int)GetLastError()); 19056513f5ff4f3e851c5f0cb38dc8851d18616b3c0Jesse Hall break; 19156513f5ff4f3e851c5f0cb38dc8851d18616b3c0Jesse Hall } 19256513f5ff4f3e851c5f0cb38dc8851d18616b3c0Jesse Hall res -= written; 19356513f5ff4f3e851c5f0cb38dc8851d18616b3c0Jesse Hall } 19456513f5ff4f3e851c5f0cb38dc8851d18616b3c0Jesse Hall return retval; 19556513f5ff4f3e851c5f0cb38dc8851d18616b3c0Jesse Hall} 19656513f5ff4f3e851c5f0cb38dc8851d18616b3c0Jesse Hall 19756513f5ff4f3e851c5f0cb38dc8851d18616b3c0Jesse Hallconst unsigned char *Win32PipeStream::readFully(void *buf, size_t len) 19856513f5ff4f3e851c5f0cb38dc8851d18616b3c0Jesse Hall{ 19956513f5ff4f3e851c5f0cb38dc8851d18616b3c0Jesse Hall const unsigned char* ret = NULL; 20056513f5ff4f3e851c5f0cb38dc8851d18616b3c0Jesse Hall 20156513f5ff4f3e851c5f0cb38dc8851d18616b3c0Jesse Hall if (m_pipe == INVALID_HANDLE_VALUE) 20256513f5ff4f3e851c5f0cb38dc8851d18616b3c0Jesse Hall return NULL; 20356513f5ff4f3e851c5f0cb38dc8851d18616b3c0Jesse Hall 20456513f5ff4f3e851c5f0cb38dc8851d18616b3c0Jesse Hall if (!buf) { 20556513f5ff4f3e851c5f0cb38dc8851d18616b3c0Jesse Hall return NULL; // do not allow NULL buf in that implementation 20656513f5ff4f3e851c5f0cb38dc8851d18616b3c0Jesse Hall } 20756513f5ff4f3e851c5f0cb38dc8851d18616b3c0Jesse Hall 20856513f5ff4f3e851c5f0cb38dc8851d18616b3c0Jesse Hall size_t res = len; 20956513f5ff4f3e851c5f0cb38dc8851d18616b3c0Jesse Hall while (res > 0) { 21056513f5ff4f3e851c5f0cb38dc8851d18616b3c0Jesse Hall DWORD readcount = 0; 21156513f5ff4f3e851c5f0cb38dc8851d18616b3c0Jesse Hall if (! ::ReadFile(m_pipe, (char *)buf + (len - res), res, &readcount, NULL) || readcount == 0) { 21256513f5ff4f3e851c5f0cb38dc8851d18616b3c0Jesse Hall errno = (int)GetLastError(); 21356513f5ff4f3e851c5f0cb38dc8851d18616b3c0Jesse Hall return NULL; 21456513f5ff4f3e851c5f0cb38dc8851d18616b3c0Jesse Hall } 21556513f5ff4f3e851c5f0cb38dc8851d18616b3c0Jesse Hall res -= readcount; 21656513f5ff4f3e851c5f0cb38dc8851d18616b3c0Jesse Hall } 21756513f5ff4f3e851c5f0cb38dc8851d18616b3c0Jesse Hall return (const unsigned char *)buf; 21856513f5ff4f3e851c5f0cb38dc8851d18616b3c0Jesse Hall} 21956513f5ff4f3e851c5f0cb38dc8851d18616b3c0Jesse Hall 22056513f5ff4f3e851c5f0cb38dc8851d18616b3c0Jesse Hallconst unsigned char *Win32PipeStream::read( void *buf, size_t *inout_len) 22156513f5ff4f3e851c5f0cb38dc8851d18616b3c0Jesse Hall{ 22256513f5ff4f3e851c5f0cb38dc8851d18616b3c0Jesse Hall size_t len = *inout_len; 22356513f5ff4f3e851c5f0cb38dc8851d18616b3c0Jesse Hall DWORD readcount; 22456513f5ff4f3e851c5f0cb38dc8851d18616b3c0Jesse Hall 22556513f5ff4f3e851c5f0cb38dc8851d18616b3c0Jesse Hall if (m_pipe == INVALID_HANDLE_VALUE) 22656513f5ff4f3e851c5f0cb38dc8851d18616b3c0Jesse Hall return NULL; 22756513f5ff4f3e851c5f0cb38dc8851d18616b3c0Jesse Hall 22856513f5ff4f3e851c5f0cb38dc8851d18616b3c0Jesse Hall if (!buf) { 22956513f5ff4f3e851c5f0cb38dc8851d18616b3c0Jesse Hall return NULL; // do not allow NULL buf in that implementation 23056513f5ff4f3e851c5f0cb38dc8851d18616b3c0Jesse Hall } 23156513f5ff4f3e851c5f0cb38dc8851d18616b3c0Jesse Hall 23256513f5ff4f3e851c5f0cb38dc8851d18616b3c0Jesse Hall if (!::ReadFile(m_pipe, (char *)buf, len, &readcount, NULL)) { 23356513f5ff4f3e851c5f0cb38dc8851d18616b3c0Jesse Hall errno = (int)GetLastError(); 23456513f5ff4f3e851c5f0cb38dc8851d18616b3c0Jesse Hall return NULL; 23556513f5ff4f3e851c5f0cb38dc8851d18616b3c0Jesse Hall } 23656513f5ff4f3e851c5f0cb38dc8851d18616b3c0Jesse Hall 23756513f5ff4f3e851c5f0cb38dc8851d18616b3c0Jesse Hall *inout_len = (size_t)readcount; 23856513f5ff4f3e851c5f0cb38dc8851d18616b3c0Jesse Hall return (const unsigned char *)buf; 23956513f5ff4f3e851c5f0cb38dc8851d18616b3c0Jesse Hall} 240