summaryrefslogtreecommitdiff
path: root/sal/osl/os2/pipeimpl.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'sal/osl/os2/pipeimpl.cxx')
-rw-r--r--sal/osl/os2/pipeimpl.cxx755
1 files changed, 755 insertions, 0 deletions
diff --git a/sal/osl/os2/pipeimpl.cxx b/sal/osl/os2/pipeimpl.cxx
new file mode 100644
index 000000000000..d08a370c428c
--- /dev/null
+++ b/sal/osl/os2/pipeimpl.cxx
@@ -0,0 +1,755 @@
+# include "pipeimpl.h"
+
+#ifndef _INC_MALLOC
+# include <malloc.h>
+#endif
+
+#ifndef _INC_TCHAR
+# ifdef UNICODE
+# define _UNICODE
+# endif
+# include <tchar.h>
+#endif
+
+const TCHAR PIPE_NAME_PREFIX_MAPPING[] = TEXT("PIPE_FILE_MAPPING_");
+const TCHAR PIPE_NAME_PREFIX_SYNCHRONIZE[] = TEXT("PIPE_SYNCHRONIZE_MUTEX_");
+const TCHAR PIPE_NAME_PREFIX_CONNECTION[] = TEXT("PIPE_CONNECTION_SEMAPHORE_");
+
+const DWORD PIPE_BUFFER_SIZE = 4096;
+
+
+//============================================================================
+// PipeData
+//============================================================================
+
+struct PipeData
+{
+ DWORD dwProcessId;
+ HANDLE hReadPipe;
+ HANDLE hWritePipe;
+};
+
+//============================================================================
+// Pipe
+//============================================================================
+
+#ifdef UNICODE
+#define Pipe PipeW
+#define ClientPipe ClientPipeW
+#define ServerPipe ServerPipeW
+#else
+#define Pipe PipeA
+#define ClientPipe ClientPipeA
+#define ServerPipe ServerPipeA
+#endif
+
+class Pipe
+{
+protected:
+ HANDLE m_hReadPipe; // Handle to use for reading
+ HANDLE m_hWritePipe; // Handle to use for writing
+
+ Pipe( HANDLE hReadPipe, HANDLE hWritePipe );
+
+ static HANDLE CreatePipeDataMutex( LPCTSTR lpName, BOOL bInitialOwner );
+ static HANDLE CreatePipeDataMapping( LPCTSTR lpName );
+ static HANDLE OpenPipeDataMapping( LPCTSTR lpName );
+ static HANDLE CreatePipeConnectionSemaphore( LPCTSTR lpName, LONG lInitialCount, LONG lMaximumcount );
+
+public:
+ Pipe( const Pipe& );
+ const Pipe& operator = ( const Pipe& );
+ virtual ~Pipe();
+
+ virtual bool Close();
+ virtual bool Write( LPCVOID lpBuffer, DWORD dwBytesToWrite, LPDWORD lpBytesWritten, bool bWait = true );
+ virtual bool Read( LPVOID lpBuffer, DWORD dwBytesToRead, LPDWORD lpBytesRead, bool bWait = true );
+
+ virtual Pipe *AcceptConnection()
+ {
+ SetLastError( ERROR_INVALID_HANDLE );
+ return NULL;
+ }
+
+ void * operator new( size_t nBytes )
+ {
+ return HeapAlloc( GetProcessHeap(), 0, nBytes );
+ }
+
+ void operator delete( void *ptr )
+ {
+ HeapFree( GetProcessHeap(), 0, ptr );
+ }
+
+ bool is() const
+ {
+ return (FALSE != HeapValidate( GetProcessHeap(), 0, this ));
+ }
+
+};
+
+//============================================================================
+// ClientPipe
+//============================================================================
+
+class ClientPipe : public Pipe
+{
+protected:
+ ClientPipe( HANDLE hReadPipe, HANDLE hWritePipe );
+public:
+ static ClientPipe* Create( LPCTSTR lpName );
+};
+
+//============================================================================
+// ServerPipe
+//============================================================================
+
+class ServerPipe : public Pipe
+{
+protected:
+ HANDLE m_hMapping;
+ HANDLE m_hSynchronize;
+ LPTSTR m_lpName;
+
+ ServerPipe( LPCTSTR lpName, HANDLE hMapping, HANDLE hSynchronize, HANDLE hReadPipe, HANDLE hWritePipe );
+public:
+ virtual ~ServerPipe();
+
+ static ServerPipe *Create( LPCTSTR lpName );
+
+ virtual Pipe *AcceptConnection();
+};
+
+//----------------------------------------------------------------------------
+//
+//----------------------------------------------------------------------------
+
+HANDLE Pipe::CreatePipeDataMapping( LPCTSTR lpName )
+{
+ HANDLE hMapping = NULL;
+ LPTSTR lpMappingName = (LPTSTR)alloca( _tcslen(lpName) * sizeof(TCHAR) + sizeof(PIPE_NAME_PREFIX_MAPPING) );
+
+ if ( lpMappingName )
+ {
+ _tcscpy( lpMappingName, PIPE_NAME_PREFIX_MAPPING );
+ _tcscat( lpMappingName, lpName );
+
+ LPTSTR lpMappingFileName = (LPTSTR)alloca( MAX_PATH * sizeof(TCHAR) );
+
+ if ( lpMappingFileName )
+ {
+ DWORD nChars = GetTempPath( MAX_PATH, lpMappingFileName );
+
+ if ( MAX_PATH + _tcslen(lpName) < nChars + 1 )
+ {
+ lpMappingFileName = (LPTSTR)alloca( (nChars + 1 + _tcslen(lpName)) * sizeof(TCHAR) );
+ if ( lpMappingFileName )
+ nChars = GetTempPath( nChars, lpMappingFileName );
+ else
+ {
+ nChars = 0;
+ SetLastError( ERROR_NOT_ENOUGH_MEMORY );
+ }
+ }
+
+ if ( nChars )
+ {
+ _tcscat( lpMappingFileName, lpMappingName );
+
+ HANDLE hFile = CreateFile(
+ lpMappingFileName,
+ GENERIC_READ | GENERIC_WRITE,
+ FILE_SHARE_READ | FILE_SHARE_WRITE,
+ NULL,
+ OPEN_ALWAYS,
+ FILE_ATTRIBUTE_TEMPORARY | FILE_FLAG_DELETE_ON_CLOSE,
+ NULL );
+
+ if ( IsValidHandle(hFile) )
+ {
+ hMapping = CreateFileMapping(
+ (HANDLE)hFile,
+ (LPSECURITY_ATTRIBUTES)NULL,
+ PAGE_READWRITE,
+ 0,
+ sizeof(PipeData),
+ lpMappingName );
+
+ CloseHandle( hFile );
+ }
+ }
+ }
+ else
+ SetLastError( ERROR_NOT_ENOUGH_MEMORY );
+ }
+
+ return hMapping;
+}
+
+//----------------------------------------------------------------------------
+//
+//----------------------------------------------------------------------------
+
+HANDLE Pipe::OpenPipeDataMapping( LPCTSTR lpName )
+{
+ HANDLE hMapping = NULL;
+ LPTSTR lpMappingName = (LPTSTR)alloca( _tcslen(lpName) * sizeof(TCHAR) + sizeof(PIPE_NAME_PREFIX_MAPPING) );
+
+ if ( lpMappingName )
+ {
+ _tcscpy( lpMappingName, PIPE_NAME_PREFIX_MAPPING );
+ _tcscat( lpMappingName, lpName );
+
+ hMapping = OpenFileMapping( FILE_MAP_ALL_ACCESS, FALSE, lpMappingName );
+ }
+
+ return hMapping;
+}
+
+//----------------------------------------------------------------------------
+//
+//----------------------------------------------------------------------------
+
+HANDLE Pipe::CreatePipeDataMutex( LPCTSTR lpName, BOOL bInitialOwner )
+{
+ HANDLE hMutex = NULL;
+ LPTSTR lpMutexName = (LPTSTR)alloca( _tcslen(lpName) * sizeof(TCHAR) + sizeof(PIPE_NAME_PREFIX_SYNCHRONIZE) );
+
+ if ( lpMutexName )
+ {
+ _tcscpy( lpMutexName, PIPE_NAME_PREFIX_SYNCHRONIZE );
+ _tcscat( lpMutexName, lpName );
+
+ hMutex = CreateMutex( NULL, bInitialOwner, lpMutexName );
+ }
+
+ return hMutex;
+}
+
+//----------------------------------------------------------------------------
+//
+//----------------------------------------------------------------------------
+
+HANDLE Pipe::CreatePipeConnectionSemaphore( LPCTSTR lpName, LONG lInitialCount, LONG lMaximumCount )
+{
+ HANDLE hSemaphore = NULL;
+ LPTSTR lpSemaphoreName = (LPTSTR)alloca( _tcslen(lpName) * sizeof(TCHAR) + sizeof(PIPE_NAME_PREFIX_CONNECTION) );
+
+ if ( lpSemaphoreName )
+ {
+ _tcscpy( lpSemaphoreName, PIPE_NAME_PREFIX_CONNECTION );
+ _tcscat( lpSemaphoreName, lpName );
+
+ hSemaphore = CreateSemaphore( NULL, lInitialCount, lMaximumCount, lpSemaphoreName );
+ }
+
+ return hSemaphore;
+}
+
+
+//----------------------------------------------------------------------------
+// Pipe copy ctor
+//----------------------------------------------------------------------------
+
+Pipe::Pipe( const Pipe& rPipe ) :
+m_hReadPipe( INVALID_HANDLE_VALUE ),
+m_hWritePipe( INVALID_HANDLE_VALUE )
+{
+ DuplicateHandle(
+ GetCurrentProcess(),
+ rPipe.m_hReadPipe,
+ GetCurrentProcess(),
+ &m_hReadPipe,
+ 0,
+ FALSE,
+ DUPLICATE_SAME_ACCESS );
+
+ DuplicateHandle(
+ GetCurrentProcess(),
+ rPipe.m_hWritePipe,
+ GetCurrentProcess(),
+ &m_hWritePipe,
+ 0,
+ FALSE,
+ DUPLICATE_SAME_ACCESS );
+}
+
+//----------------------------------------------------------------------------
+// Pipe assignment operator
+//----------------------------------------------------------------------------
+
+const Pipe& Pipe::operator = ( const Pipe& rPipe )
+{
+ Close();
+
+ DuplicateHandle(
+ GetCurrentProcess(),
+ rPipe.m_hReadPipe,
+ GetCurrentProcess(),
+ &m_hReadPipe,
+ 0,
+ FALSE,
+ DUPLICATE_SAME_ACCESS );
+
+ DuplicateHandle(
+ GetCurrentProcess(),
+ rPipe.m_hWritePipe,
+ GetCurrentProcess(),
+ &m_hWritePipe,
+ 0,
+ FALSE,
+ DUPLICATE_SAME_ACCESS );
+
+ return *this;
+}
+
+//----------------------------------------------------------------------------
+// Pipe ctor
+//----------------------------------------------------------------------------
+
+Pipe::Pipe( HANDLE hReadPipe, HANDLE hWritePipe ) :
+m_hReadPipe( INVALID_HANDLE_VALUE ),
+m_hWritePipe( INVALID_HANDLE_VALUE )
+{
+ DuplicateHandle(
+ GetCurrentProcess(),
+ hReadPipe,
+ GetCurrentProcess(),
+ &m_hReadPipe,
+ 0,
+ FALSE,
+ DUPLICATE_SAME_ACCESS );
+
+ DuplicateHandle(
+ GetCurrentProcess(),
+ hWritePipe,
+ GetCurrentProcess(),
+ &m_hWritePipe,
+ 0,
+ FALSE,
+ DUPLICATE_SAME_ACCESS );
+}
+
+//----------------------------------------------------------------------------
+// Pipe dtor
+//----------------------------------------------------------------------------
+
+Pipe::~Pipe()
+{
+ Close();
+}
+
+//----------------------------------------------------------------------------
+// Pipe Close
+//----------------------------------------------------------------------------
+
+bool Pipe::Close()
+{
+ bool fSuccess = false; // Assume failure
+
+ if ( IsValidHandle(m_hReadPipe) )
+ {
+ CloseHandle( m_hReadPipe );
+ m_hReadPipe = INVALID_HANDLE_VALUE;
+ }
+
+ if ( IsValidHandle(m_hWritePipe) )
+ {
+ CloseHandle( m_hWritePipe );
+ m_hWritePipe = INVALID_HANDLE_VALUE;
+ }
+
+ return fSuccess;
+}
+
+//----------------------------------------------------------------------------
+// Pipe Write
+//----------------------------------------------------------------------------
+
+bool Pipe::Write( LPCVOID lpBuffer, DWORD dwBytesToWrite, LPDWORD lpBytesWritten, bool bWait )
+{
+ DWORD dwBytesAvailable = 0;
+ BOOL fSuccess = TRUE;
+
+ if ( !bWait )
+ fSuccess = PeekNamedPipe( m_hReadPipe, NULL, 0, NULL, &dwBytesAvailable, NULL );
+
+ if ( fSuccess )
+ {
+ if ( !bWait && dwBytesToWrite > PIPE_BUFFER_SIZE - dwBytesAvailable )
+ dwBytesToWrite = PIPE_BUFFER_SIZE - dwBytesAvailable ;
+
+ return !!WriteFile( m_hWritePipe, lpBuffer, dwBytesToWrite, lpBytesWritten, NULL );
+ }
+
+ return false;
+}
+
+//----------------------------------------------------------------------------
+// Pipe Read
+//----------------------------------------------------------------------------
+
+bool Pipe::Read( LPVOID lpBuffer, DWORD dwBytesToRead, LPDWORD lpBytesRead, bool bWait )
+{
+ DWORD dwBytesAvailable = 0;
+ BOOL fSuccess = TRUE;
+
+ if ( !bWait )
+ fSuccess = PeekNamedPipe( m_hReadPipe, NULL, 0, NULL, &dwBytesAvailable, NULL );
+
+ if ( fSuccess )
+ {
+ if ( bWait || dwBytesAvailable )
+ return !!ReadFile( m_hReadPipe, lpBuffer, dwBytesToRead, lpBytesRead, NULL );
+ else
+ {
+ *lpBytesRead = 0;
+ return true;
+ }
+ }
+
+ return false;
+}
+
+
+
+//----------------------------------------------------------------------------
+// Client pipe dtor
+//----------------------------------------------------------------------------
+
+ClientPipe::ClientPipe( HANDLE hReadPipe, HANDLE hWritePipe ) : Pipe( hReadPipe, hWritePipe )
+{
+}
+
+//----------------------------------------------------------------------------
+// Client pipe creation
+//----------------------------------------------------------------------------
+
+ClientPipe *ClientPipe::Create( LPCTSTR lpName )
+{
+ ClientPipe *pPipe = NULL; // Assume failure
+
+ HANDLE hMapping = OpenPipeDataMapping( lpName );
+
+ if ( IsValidHandle(hMapping) )
+ {
+ PipeData *pData = (PipeData*)MapViewOfFile( hMapping, FILE_MAP_ALL_ACCESS, 0, 0, 0 );
+
+ if ( pData )
+ {
+ HANDLE hSourceProcess = OpenProcess( PROCESS_DUP_HANDLE, FALSE, pData->dwProcessId );
+
+ if ( IsValidHandle(hSourceProcess) )
+ {
+ BOOL fSuccess;
+ HANDLE hReadPipe = INVALID_HANDLE_VALUE, hWritePipe = INVALID_HANDLE_VALUE;
+
+ fSuccess = DuplicateHandle(
+ hSourceProcess,
+ pData->hReadPipe,
+ GetCurrentProcess(),
+ &hReadPipe,
+ 0,
+ FALSE,
+ DUPLICATE_SAME_ACCESS );
+
+ fSuccess = fSuccess && DuplicateHandle(
+ hSourceProcess,
+ pData->hWritePipe,
+ GetCurrentProcess(),
+ &hWritePipe,
+ 0,
+ FALSE,
+ DUPLICATE_SAME_ACCESS );
+
+ if ( fSuccess )
+ pPipe = new ClientPipe( hReadPipe, hWritePipe );
+
+ if ( IsValidHandle(hWritePipe) )
+ CloseHandle( hWritePipe );
+
+ if ( IsValidHandle(hReadPipe) )
+ CloseHandle( hReadPipe );
+
+ HANDLE hConnectionRequest = CreatePipeConnectionSemaphore( lpName, 0, 1 );
+
+ ReleaseSemaphore( hConnectionRequest, 1, NULL );
+
+ CloseHandle( hConnectionRequest );
+
+ CloseHandle( hSourceProcess );
+ }
+
+ UnmapViewOfFile( pData );
+ }
+
+ CloseHandle( hMapping );
+ }
+
+ return pPipe;
+}
+
+
+
+//----------------------------------------------------------------------------
+// ServerPipe ctor
+//----------------------------------------------------------------------------
+
+ServerPipe::ServerPipe( LPCTSTR lpName, HANDLE hMapping, HANDLE hSynchronize, HANDLE hReadPipe, HANDLE hWritePipe ) : Pipe( hReadPipe, hWritePipe ),
+m_hMapping( NULL ),
+m_hSynchronize( NULL ),
+m_lpName( NULL )
+{
+ DuplicateHandle(
+ GetCurrentProcess(),
+ hMapping,
+ GetCurrentProcess(),
+ &m_hMapping,
+ 0,
+ FALSE,
+ DUPLICATE_SAME_ACCESS );
+
+ DuplicateHandle(
+ GetCurrentProcess(),
+ hSynchronize,
+ GetCurrentProcess(),
+ &m_hSynchronize,
+ 0,
+ FALSE,
+ DUPLICATE_SAME_ACCESS
+ );
+ m_lpName = new TCHAR[_tcslen(lpName) + 1];
+ if ( m_lpName )
+ _tcscpy( m_lpName, lpName );
+}
+
+//----------------------------------------------------------------------------
+// ServerPipe dtor
+//----------------------------------------------------------------------------
+
+ServerPipe::~ServerPipe()
+{
+ if ( IsValidHandle(m_hMapping) )
+ CloseHandle( m_hMapping );
+ if ( m_lpName )
+ delete[]m_lpName;
+}
+
+//----------------------------------------------------------------------------
+// ServerPipe AcceptConnection
+//----------------------------------------------------------------------------
+
+Pipe *ServerPipe::AcceptConnection()
+{
+ Pipe *pPipe = NULL; // Assume failure;
+
+ HANDLE hConnectionRequest = CreatePipeConnectionSemaphore( m_lpName, 0, 1 );
+
+ if ( WAIT_OBJECT_0 == WaitForSingleObject( hConnectionRequest, INFINITE ) )
+ {
+ pPipe = new Pipe( *this );
+ Close();
+
+ // Create new inbound Pipe
+
+ HANDLE hClientWritePipe = NULL, hServerReadPipe = NULL;
+
+ BOOL fSuccess = CreatePipe( &hServerReadPipe, &hClientWritePipe, NULL, PIPE_BUFFER_SIZE );
+
+
+ if ( fSuccess )
+ {
+ // Create outbound pipe
+
+ HANDLE hClientReadPipe = NULL, hServerWritePipe = NULL;
+
+ if ( CreatePipe( &hClientReadPipe, &hServerWritePipe, NULL, PIPE_BUFFER_SIZE ) )
+ {
+ m_hReadPipe = hServerReadPipe;
+ m_hWritePipe = hServerWritePipe;
+
+ PipeData *pData = (PipeData *)MapViewOfFile( m_hMapping, FILE_MAP_ALL_ACCESS, 0, 0, sizeof(PipeData) );
+
+ HANDLE hSynchronize = CreatePipeDataMutex( m_lpName, TRUE );
+
+ CloseHandle( pData->hReadPipe );
+ CloseHandle( pData->hWritePipe );
+
+ pData->hReadPipe = hClientReadPipe;
+ pData->hWritePipe = hClientWritePipe;
+
+ ReleaseMutex( hSynchronize );
+
+ CloseHandle( hSynchronize );
+
+ }
+ else
+ {
+ CloseHandle( hClientWritePipe );
+ CloseHandle( hServerWritePipe );
+ }
+ }
+
+ ReleaseMutex( hConnectionRequest );
+ }
+
+ CloseHandle( hConnectionRequest );
+
+ return pPipe;
+}
+
+//----------------------------------------------------------------------------
+// Pipe creation
+//----------------------------------------------------------------------------
+
+ServerPipe *ServerPipe::Create( LPCTSTR lpName )
+{
+ ServerPipe *pPipe = NULL;
+
+ HANDLE hMapping = CreatePipeDataMapping( lpName );
+
+ if ( IsValidHandle(hMapping) )
+ {
+ if ( ERROR_FILE_EXISTS != GetLastError() )
+ {
+ HANDLE hSynchronize = CreatePipeDataMutex( lpName, FALSE);
+
+ WaitForSingleObject( hSynchronize, INFINITE );
+
+ PipeData *pData = (PipeData*)MapViewOfFile( hMapping, FILE_MAP_ALL_ACCESS, 0, 0, 0 );
+
+ if ( pData )
+ {
+
+ // Initialize pipe data
+
+ pData->dwProcessId = 0;
+ pData->hReadPipe = NULL;
+ pData->hWritePipe = NULL;
+
+ // Create inbound pipe
+
+ HANDLE hServerReadPipe = NULL, hClientWritePipe = NULL;
+
+ BOOL fSuccess = CreatePipe( &hServerReadPipe, &hClientWritePipe, NULL, PIPE_BUFFER_SIZE );
+
+ if ( fSuccess )
+ {
+ // Create outbound pipe
+
+ HANDLE hServerWritePipe = NULL, hClientReadPipe = NULL;
+
+ fSuccess = CreatePipe( &hClientReadPipe, &hServerWritePipe, NULL, PIPE_BUFFER_SIZE );
+
+ if ( fSuccess )
+ {
+ pData->dwProcessId = GetCurrentProcessId();
+ pData->hReadPipe = hClientReadPipe;
+ pData->hWritePipe = hClientWritePipe;
+ pPipe = new ServerPipe( lpName, hMapping, hSynchronize, hServerReadPipe, hServerWritePipe );
+
+ CloseHandle( hServerWritePipe );
+ CloseHandle( hServerReadPipe );
+ }
+ else
+ {
+ CloseHandle( hServerReadPipe );
+ CloseHandle( hClientWritePipe );
+ }
+ }
+
+ UnmapViewOfFile( pData );
+ }
+
+ ReleaseMutex( hSynchronize );
+ CloseHandle( hSynchronize );
+ }
+
+ CloseHandle( hMapping );
+ }
+
+ return pPipe;
+}
+
+
+//----------------------------------------------------------------------------
+// C style API
+//----------------------------------------------------------------------------
+
+const TCHAR LOCAL_PIPE_PREFIX[] = TEXT("\\\\.\\PIPE\\" );
+
+extern "C" HANDLE WINAPI CreateSimplePipe( LPCTSTR lpName )
+{
+ int nPrefixLen = _tcslen( LOCAL_PIPE_PREFIX );
+ if ( 0 == _tcsnicmp( lpName, LOCAL_PIPE_PREFIX, nPrefixLen ) )
+ lpName += nPrefixLen;
+ return (HANDLE)ServerPipe::Create( lpName );
+}
+
+extern "C" HANDLE WINAPI OpenSimplePipe( LPCTSTR lpName )
+{
+ int nPrefixLen = _tcslen( LOCAL_PIPE_PREFIX );
+ if ( 0 == _tcsnicmp( lpName, LOCAL_PIPE_PREFIX, nPrefixLen ) )
+ lpName += nPrefixLen;
+ return (HANDLE)ClientPipe::Create( lpName );
+}
+
+extern "C" HANDLE WINAPI AcceptSimplePipeConnection( HANDLE hPipe )
+{
+ Pipe *pPipe = (Pipe *)hPipe;
+
+ if ( pPipe->is() )
+ return (HANDLE)pPipe->AcceptConnection();
+ else
+ {
+ SetLastError( ERROR_INVALID_HANDLE );
+ return NULL;
+ }
+}
+
+extern "C" BOOL WINAPI WaitForSimplePipe( LPCTSTR /*lpName*/, DWORD /*dwTimeOut*/ )
+{
+ return FALSE;
+}
+
+extern "C" BOOL WINAPI WriteSimplePipe( HANDLE hPipe, LPCVOID lpBuffer, DWORD dwBytesToWrite, LPDWORD lpBytesWritten, BOOL bWait )
+{
+ Pipe *pPipe = (Pipe *)hPipe;
+
+ if ( pPipe->is() )
+ return pPipe->Write( lpBuffer, dwBytesToWrite, lpBytesWritten, bWait );
+ else
+ {
+ SetLastError( ERROR_INVALID_HANDLE );
+ return FALSE;
+ }
+}
+
+extern "C" BOOL WINAPI ReadSimplePipe( HANDLE hPipe, LPVOID lpBuffer, DWORD dwBytesToRead, LPDWORD lpBytesRead, BOOL bWait )
+{
+ Pipe *pPipe = (Pipe *)hPipe;
+
+ if ( pPipe->is() )
+ return pPipe->Read( lpBuffer, dwBytesToRead, lpBytesRead, bWait );
+ else
+ {
+ SetLastError( ERROR_INVALID_HANDLE );
+ return FALSE;
+ }
+}
+
+extern "C" BOOL WINAPI CloseSimplePipe( HANDLE hPipe )
+{
+ Pipe *pPipe = (Pipe *)hPipe;
+
+ if ( pPipe->is() )
+ {
+ delete pPipe;
+ return TRUE;
+ }
+ else
+ {
+ SetLastError( ERROR_INVALID_HANDLE );
+ return FALSE;
+ }
+}