Update ooo320-m1
[ooovba.git] / sal / osl / os2 / pipeimpl.cxx
blob1d613b871efd9ff4005d35ca647f48790773db03
1 # include "pipeimpl.h"
3 #ifndef _INC_MALLOC
4 # include <malloc.h>
5 #endif
7 #ifndef _INC_TCHAR
8 # ifdef UNICODE
9 # define _UNICODE
10 # endif
11 # include <tchar.h>
12 #endif
14 const TCHAR PIPE_NAME_PREFIX_MAPPING[] = TEXT("PIPE_FILE_MAPPING_");
15 const TCHAR PIPE_NAME_PREFIX_SYNCHRONIZE[] = TEXT("PIPE_SYNCHRONIZE_MUTEX_");
16 const TCHAR PIPE_NAME_PREFIX_CONNECTION[] = TEXT("PIPE_CONNECTION_SEMAPHORE_");
18 const DWORD PIPE_BUFFER_SIZE = 4096;
21 //============================================================================
22 // PipeData
23 //============================================================================
25 struct PipeData
27 DWORD dwProcessId;
28 HANDLE hReadPipe;
29 HANDLE hWritePipe;
32 //============================================================================
33 // Pipe
34 //============================================================================
36 #ifdef UNICODE
37 #define Pipe PipeW
38 #define ClientPipe ClientPipeW
39 #define ServerPipe ServerPipeW
40 #else
41 #define Pipe PipeA
42 #define ClientPipe ClientPipeA
43 #define ServerPipe ServerPipeA
44 #endif
46 class Pipe
48 protected:
49 HANDLE m_hReadPipe; // Handle to use for reading
50 HANDLE m_hWritePipe; // Handle to use for writing
52 Pipe( HANDLE hReadPipe, HANDLE hWritePipe );
54 static HANDLE CreatePipeDataMutex( LPCTSTR lpName, BOOL bInitialOwner );
55 static HANDLE CreatePipeDataMapping( LPCTSTR lpName );
56 static HANDLE OpenPipeDataMapping( LPCTSTR lpName );
57 static HANDLE CreatePipeConnectionSemaphore( LPCTSTR lpName, LONG lInitialCount, LONG lMaximumcount );
59 public:
60 Pipe( const Pipe& );
61 const Pipe& operator = ( const Pipe& );
62 virtual ~Pipe();
64 virtual bool Close();
65 virtual bool Write( LPCVOID lpBuffer, DWORD dwBytesToWrite, LPDWORD lpBytesWritten, bool bWait = true );
66 virtual bool Read( LPVOID lpBuffer, DWORD dwBytesToRead, LPDWORD lpBytesRead, bool bWait = true );
68 virtual Pipe *AcceptConnection()
70 SetLastError( ERROR_INVALID_HANDLE );
71 return NULL;
74 void * operator new( size_t nBytes )
76 return HeapAlloc( GetProcessHeap(), 0, nBytes );
79 void operator delete( void *ptr )
81 HeapFree( GetProcessHeap(), 0, ptr );
84 bool is() const
86 return (FALSE != HeapValidate( GetProcessHeap(), 0, this ));
91 //============================================================================
92 // ClientPipe
93 //============================================================================
95 class ClientPipe : public Pipe
97 protected:
98 ClientPipe( HANDLE hReadPipe, HANDLE hWritePipe );
99 public:
100 static ClientPipe* Create( LPCTSTR lpName );
103 //============================================================================
104 // ServerPipe
105 //============================================================================
107 class ServerPipe : public Pipe
109 protected:
110 HANDLE m_hMapping;
111 HANDLE m_hSynchronize;
112 LPTSTR m_lpName;
114 ServerPipe( LPCTSTR lpName, HANDLE hMapping, HANDLE hSynchronize, HANDLE hReadPipe, HANDLE hWritePipe );
115 public:
116 virtual ~ServerPipe();
118 static ServerPipe *Create( LPCTSTR lpName );
120 virtual Pipe *AcceptConnection();
123 //----------------------------------------------------------------------------
125 //----------------------------------------------------------------------------
127 HANDLE Pipe::CreatePipeDataMapping( LPCTSTR lpName )
129 HANDLE hMapping = NULL;
130 LPTSTR lpMappingName = (LPTSTR)alloca( _tcslen(lpName) * sizeof(TCHAR) + sizeof(PIPE_NAME_PREFIX_MAPPING) );
132 if ( lpMappingName )
134 _tcscpy( lpMappingName, PIPE_NAME_PREFIX_MAPPING );
135 _tcscat( lpMappingName, lpName );
137 LPTSTR lpMappingFileName = (LPTSTR)alloca( MAX_PATH * sizeof(TCHAR) );
139 if ( lpMappingFileName )
141 DWORD nChars = GetTempPath( MAX_PATH, lpMappingFileName );
143 if ( MAX_PATH + _tcslen(lpName) < nChars + 1 )
145 lpMappingFileName = (LPTSTR)alloca( (nChars + 1 + _tcslen(lpName)) * sizeof(TCHAR) );
146 if ( lpMappingFileName )
147 nChars = GetTempPath( nChars, lpMappingFileName );
148 else
150 nChars = 0;
151 SetLastError( ERROR_NOT_ENOUGH_MEMORY );
155 if ( nChars )
157 _tcscat( lpMappingFileName, lpMappingName );
159 HANDLE hFile = CreateFile(
160 lpMappingFileName,
161 GENERIC_READ | GENERIC_WRITE,
162 FILE_SHARE_READ | FILE_SHARE_WRITE,
163 NULL,
164 OPEN_ALWAYS,
165 FILE_ATTRIBUTE_TEMPORARY | FILE_FLAG_DELETE_ON_CLOSE,
166 NULL );
168 if ( IsValidHandle(hFile) )
170 hMapping = CreateFileMapping(
171 (HANDLE)hFile,
172 (LPSECURITY_ATTRIBUTES)NULL,
173 PAGE_READWRITE,
175 sizeof(PipeData),
176 lpMappingName );
178 CloseHandle( hFile );
182 else
183 SetLastError( ERROR_NOT_ENOUGH_MEMORY );
186 return hMapping;
189 //----------------------------------------------------------------------------
191 //----------------------------------------------------------------------------
193 HANDLE Pipe::OpenPipeDataMapping( LPCTSTR lpName )
195 HANDLE hMapping = NULL;
196 LPTSTR lpMappingName = (LPTSTR)alloca( _tcslen(lpName) * sizeof(TCHAR) + sizeof(PIPE_NAME_PREFIX_MAPPING) );
198 if ( lpMappingName )
200 _tcscpy( lpMappingName, PIPE_NAME_PREFIX_MAPPING );
201 _tcscat( lpMappingName, lpName );
203 hMapping = OpenFileMapping( FILE_MAP_ALL_ACCESS, FALSE, lpMappingName );
206 return hMapping;
209 //----------------------------------------------------------------------------
211 //----------------------------------------------------------------------------
213 HANDLE Pipe::CreatePipeDataMutex( LPCTSTR lpName, BOOL bInitialOwner )
215 HANDLE hMutex = NULL;
216 LPTSTR lpMutexName = (LPTSTR)alloca( _tcslen(lpName) * sizeof(TCHAR) + sizeof(PIPE_NAME_PREFIX_SYNCHRONIZE) );
218 if ( lpMutexName )
220 _tcscpy( lpMutexName, PIPE_NAME_PREFIX_SYNCHRONIZE );
221 _tcscat( lpMutexName, lpName );
223 hMutex = CreateMutex( NULL, bInitialOwner, lpMutexName );
226 return hMutex;
229 //----------------------------------------------------------------------------
231 //----------------------------------------------------------------------------
233 HANDLE Pipe::CreatePipeConnectionSemaphore( LPCTSTR lpName, LONG lInitialCount, LONG lMaximumCount )
235 HANDLE hSemaphore = NULL;
236 LPTSTR lpSemaphoreName = (LPTSTR)alloca( _tcslen(lpName) * sizeof(TCHAR) + sizeof(PIPE_NAME_PREFIX_CONNECTION) );
238 if ( lpSemaphoreName )
240 _tcscpy( lpSemaphoreName, PIPE_NAME_PREFIX_CONNECTION );
241 _tcscat( lpSemaphoreName, lpName );
243 hSemaphore = CreateSemaphore( NULL, lInitialCount, lMaximumCount, lpSemaphoreName );
246 return hSemaphore;
250 //----------------------------------------------------------------------------
251 // Pipe copy ctor
252 //----------------------------------------------------------------------------
254 Pipe::Pipe( const Pipe& rPipe ) :
255 m_hReadPipe( INVALID_HANDLE_VALUE ),
256 m_hWritePipe( INVALID_HANDLE_VALUE )
258 DuplicateHandle(
259 GetCurrentProcess(),
260 rPipe.m_hReadPipe,
261 GetCurrentProcess(),
262 &m_hReadPipe,
264 FALSE,
265 DUPLICATE_SAME_ACCESS );
267 DuplicateHandle(
268 GetCurrentProcess(),
269 rPipe.m_hWritePipe,
270 GetCurrentProcess(),
271 &m_hWritePipe,
273 FALSE,
274 DUPLICATE_SAME_ACCESS );
277 //----------------------------------------------------------------------------
278 // Pipe assignment operator
279 //----------------------------------------------------------------------------
281 const Pipe& Pipe::operator = ( const Pipe& rPipe )
283 Close();
285 DuplicateHandle(
286 GetCurrentProcess(),
287 rPipe.m_hReadPipe,
288 GetCurrentProcess(),
289 &m_hReadPipe,
291 FALSE,
292 DUPLICATE_SAME_ACCESS );
294 DuplicateHandle(
295 GetCurrentProcess(),
296 rPipe.m_hWritePipe,
297 GetCurrentProcess(),
298 &m_hWritePipe,
300 FALSE,
301 DUPLICATE_SAME_ACCESS );
303 return *this;
306 //----------------------------------------------------------------------------
307 // Pipe ctor
308 //----------------------------------------------------------------------------
310 Pipe::Pipe( HANDLE hReadPipe, HANDLE hWritePipe ) :
311 m_hReadPipe( INVALID_HANDLE_VALUE ),
312 m_hWritePipe( INVALID_HANDLE_VALUE )
314 DuplicateHandle(
315 GetCurrentProcess(),
316 hReadPipe,
317 GetCurrentProcess(),
318 &m_hReadPipe,
320 FALSE,
321 DUPLICATE_SAME_ACCESS );
323 DuplicateHandle(
324 GetCurrentProcess(),
325 hWritePipe,
326 GetCurrentProcess(),
327 &m_hWritePipe,
329 FALSE,
330 DUPLICATE_SAME_ACCESS );
333 //----------------------------------------------------------------------------
334 // Pipe dtor
335 //----------------------------------------------------------------------------
337 Pipe::~Pipe()
339 Close();
342 //----------------------------------------------------------------------------
343 // Pipe Close
344 //----------------------------------------------------------------------------
346 bool Pipe::Close()
348 bool fSuccess = false; // Assume failure
350 if ( IsValidHandle(m_hReadPipe) )
352 CloseHandle( m_hReadPipe );
353 m_hReadPipe = INVALID_HANDLE_VALUE;
356 if ( IsValidHandle(m_hWritePipe) )
358 CloseHandle( m_hWritePipe );
359 m_hWritePipe = INVALID_HANDLE_VALUE;
362 return fSuccess;
365 //----------------------------------------------------------------------------
366 // Pipe Write
367 //----------------------------------------------------------------------------
369 bool Pipe::Write( LPCVOID lpBuffer, DWORD dwBytesToWrite, LPDWORD lpBytesWritten, bool bWait )
371 DWORD dwBytesAvailable = 0;
372 BOOL fSuccess = TRUE;
374 if ( !bWait )
375 fSuccess = PeekNamedPipe( m_hReadPipe, NULL, 0, NULL, &dwBytesAvailable, NULL );
377 if ( fSuccess )
379 if ( !bWait && dwBytesToWrite > PIPE_BUFFER_SIZE - dwBytesAvailable )
380 dwBytesToWrite = PIPE_BUFFER_SIZE - dwBytesAvailable ;
382 return !!WriteFile( m_hWritePipe, lpBuffer, dwBytesToWrite, lpBytesWritten, NULL );
385 return false;
388 //----------------------------------------------------------------------------
389 // Pipe Read
390 //----------------------------------------------------------------------------
392 bool Pipe::Read( LPVOID lpBuffer, DWORD dwBytesToRead, LPDWORD lpBytesRead, bool bWait )
394 DWORD dwBytesAvailable = 0;
395 BOOL fSuccess = TRUE;
397 if ( !bWait )
398 fSuccess = PeekNamedPipe( m_hReadPipe, NULL, 0, NULL, &dwBytesAvailable, NULL );
400 if ( fSuccess )
402 if ( bWait || dwBytesAvailable )
403 return !!ReadFile( m_hReadPipe, lpBuffer, dwBytesToRead, lpBytesRead, NULL );
404 else
406 *lpBytesRead = 0;
407 return true;
411 return false;
416 //----------------------------------------------------------------------------
417 // Client pipe dtor
418 //----------------------------------------------------------------------------
420 ClientPipe::ClientPipe( HANDLE hReadPipe, HANDLE hWritePipe ) : Pipe( hReadPipe, hWritePipe )
424 //----------------------------------------------------------------------------
425 // Client pipe creation
426 //----------------------------------------------------------------------------
428 ClientPipe *ClientPipe::Create( LPCTSTR lpName )
430 ClientPipe *pPipe = NULL; // Assume failure
432 HANDLE hMapping = OpenPipeDataMapping( lpName );
434 if ( IsValidHandle(hMapping) )
436 PipeData *pData = (PipeData*)MapViewOfFile( hMapping, FILE_MAP_ALL_ACCESS, 0, 0, 0 );
438 if ( pData )
440 HANDLE hSourceProcess = OpenProcess( PROCESS_DUP_HANDLE, FALSE, pData->dwProcessId );
442 if ( IsValidHandle(hSourceProcess) )
444 BOOL fSuccess;
445 HANDLE hReadPipe = INVALID_HANDLE_VALUE, hWritePipe = INVALID_HANDLE_VALUE;
447 fSuccess = DuplicateHandle(
448 hSourceProcess,
449 pData->hReadPipe,
450 GetCurrentProcess(),
451 &hReadPipe,
453 FALSE,
454 DUPLICATE_SAME_ACCESS );
456 fSuccess = fSuccess && DuplicateHandle(
457 hSourceProcess,
458 pData->hWritePipe,
459 GetCurrentProcess(),
460 &hWritePipe,
462 FALSE,
463 DUPLICATE_SAME_ACCESS );
465 if ( fSuccess )
466 pPipe = new ClientPipe( hReadPipe, hWritePipe );
468 if ( IsValidHandle(hWritePipe) )
469 CloseHandle( hWritePipe );
471 if ( IsValidHandle(hReadPipe) )
472 CloseHandle( hReadPipe );
474 HANDLE hConnectionRequest = CreatePipeConnectionSemaphore( lpName, 0, 1 );
476 ReleaseSemaphore( hConnectionRequest, 1, NULL );
478 CloseHandle( hConnectionRequest );
480 CloseHandle( hSourceProcess );
483 UnmapViewOfFile( pData );
486 CloseHandle( hMapping );
489 return pPipe;
494 //----------------------------------------------------------------------------
495 // ServerPipe ctor
496 //----------------------------------------------------------------------------
498 ServerPipe::ServerPipe( LPCTSTR lpName, HANDLE hMapping, HANDLE hSynchronize, HANDLE hReadPipe, HANDLE hWritePipe ) : Pipe( hReadPipe, hWritePipe ),
499 m_hMapping( NULL ),
500 m_hSynchronize( NULL ),
501 m_lpName( NULL )
503 DuplicateHandle(
504 GetCurrentProcess(),
505 hMapping,
506 GetCurrentProcess(),
507 &m_hMapping,
509 FALSE,
510 DUPLICATE_SAME_ACCESS );
512 DuplicateHandle(
513 GetCurrentProcess(),
514 hSynchronize,
515 GetCurrentProcess(),
516 &m_hSynchronize,
518 FALSE,
519 DUPLICATE_SAME_ACCESS
521 m_lpName = new TCHAR[_tcslen(lpName) + 1];
522 if ( m_lpName )
523 _tcscpy( m_lpName, lpName );
526 //----------------------------------------------------------------------------
527 // ServerPipe dtor
528 //----------------------------------------------------------------------------
530 ServerPipe::~ServerPipe()
532 if ( IsValidHandle(m_hMapping) )
533 CloseHandle( m_hMapping );
534 if ( m_lpName )
535 delete[]m_lpName;
538 //----------------------------------------------------------------------------
539 // ServerPipe AcceptConnection
540 //----------------------------------------------------------------------------
542 Pipe *ServerPipe::AcceptConnection()
544 Pipe *pPipe = NULL; // Assume failure;
546 HANDLE hConnectionRequest = CreatePipeConnectionSemaphore( m_lpName, 0, 1 );
548 if ( WAIT_OBJECT_0 == WaitForSingleObject( hConnectionRequest, INFINITE ) )
550 pPipe = new Pipe( *this );
551 Close();
553 // Create new inbound Pipe
555 HANDLE hClientWritePipe = NULL, hServerReadPipe = NULL;
557 BOOL fSuccess = CreatePipe( &hServerReadPipe, &hClientWritePipe, NULL, PIPE_BUFFER_SIZE );
560 if ( fSuccess )
562 // Create outbound pipe
564 HANDLE hClientReadPipe = NULL, hServerWritePipe = NULL;
566 if ( CreatePipe( &hClientReadPipe, &hServerWritePipe, NULL, PIPE_BUFFER_SIZE ) )
568 m_hReadPipe = hServerReadPipe;
569 m_hWritePipe = hServerWritePipe;
571 PipeData *pData = (PipeData *)MapViewOfFile( m_hMapping, FILE_MAP_ALL_ACCESS, 0, 0, sizeof(PipeData) );
573 HANDLE hSynchronize = CreatePipeDataMutex( m_lpName, TRUE );
575 CloseHandle( pData->hReadPipe );
576 CloseHandle( pData->hWritePipe );
578 pData->hReadPipe = hClientReadPipe;
579 pData->hWritePipe = hClientWritePipe;
581 ReleaseMutex( hSynchronize );
583 CloseHandle( hSynchronize );
586 else
588 CloseHandle( hClientWritePipe );
589 CloseHandle( hServerWritePipe );
593 ReleaseMutex( hConnectionRequest );
596 CloseHandle( hConnectionRequest );
598 return pPipe;
601 //----------------------------------------------------------------------------
602 // Pipe creation
603 //----------------------------------------------------------------------------
605 ServerPipe *ServerPipe::Create( LPCTSTR lpName )
607 ServerPipe *pPipe = NULL;
609 HANDLE hMapping = CreatePipeDataMapping( lpName );
611 if ( IsValidHandle(hMapping) )
613 if ( ERROR_FILE_EXISTS != GetLastError() )
615 HANDLE hSynchronize = CreatePipeDataMutex( lpName, FALSE);
617 WaitForSingleObject( hSynchronize, INFINITE );
619 PipeData *pData = (PipeData*)MapViewOfFile( hMapping, FILE_MAP_ALL_ACCESS, 0, 0, 0 );
621 if ( pData )
624 // Initialize pipe data
626 pData->dwProcessId = 0;
627 pData->hReadPipe = NULL;
628 pData->hWritePipe = NULL;
630 // Create inbound pipe
632 HANDLE hServerReadPipe = NULL, hClientWritePipe = NULL;
634 BOOL fSuccess = CreatePipe( &hServerReadPipe, &hClientWritePipe, NULL, PIPE_BUFFER_SIZE );
636 if ( fSuccess )
638 // Create outbound pipe
640 HANDLE hServerWritePipe = NULL, hClientReadPipe = NULL;
642 fSuccess = CreatePipe( &hClientReadPipe, &hServerWritePipe, NULL, PIPE_BUFFER_SIZE );
644 if ( fSuccess )
646 pData->dwProcessId = GetCurrentProcessId();
647 pData->hReadPipe = hClientReadPipe;
648 pData->hWritePipe = hClientWritePipe;
649 pPipe = new ServerPipe( lpName, hMapping, hSynchronize, hServerReadPipe, hServerWritePipe );
651 CloseHandle( hServerWritePipe );
652 CloseHandle( hServerReadPipe );
654 else
656 CloseHandle( hServerReadPipe );
657 CloseHandle( hClientWritePipe );
661 UnmapViewOfFile( pData );
664 ReleaseMutex( hSynchronize );
665 CloseHandle( hSynchronize );
668 CloseHandle( hMapping );
671 return pPipe;
675 //----------------------------------------------------------------------------
676 // C style API
677 //----------------------------------------------------------------------------
679 const TCHAR LOCAL_PIPE_PREFIX[] = TEXT("\\\\.\\PIPE\\" );
681 extern "C" HANDLE WINAPI CreateSimplePipe( LPCTSTR lpName )
683 int nPrefixLen = _tcslen( LOCAL_PIPE_PREFIX );
684 if ( 0 == _tcsnicmp( lpName, LOCAL_PIPE_PREFIX, nPrefixLen ) )
685 lpName += nPrefixLen;
686 return (HANDLE)ServerPipe::Create( lpName );
689 extern "C" HANDLE WINAPI OpenSimplePipe( LPCTSTR lpName )
691 int nPrefixLen = _tcslen( LOCAL_PIPE_PREFIX );
692 if ( 0 == _tcsnicmp( lpName, LOCAL_PIPE_PREFIX, nPrefixLen ) )
693 lpName += nPrefixLen;
694 return (HANDLE)ClientPipe::Create( lpName );
697 extern "C" HANDLE WINAPI AcceptSimplePipeConnection( HANDLE hPipe )
699 Pipe *pPipe = (Pipe *)hPipe;
701 if ( pPipe->is() )
702 return (HANDLE)pPipe->AcceptConnection();
703 else
705 SetLastError( ERROR_INVALID_HANDLE );
706 return NULL;
710 extern "C" BOOL WINAPI WaitForSimplePipe( LPCTSTR /*lpName*/, DWORD /*dwTimeOut*/ )
712 return FALSE;
715 extern "C" BOOL WINAPI WriteSimplePipe( HANDLE hPipe, LPCVOID lpBuffer, DWORD dwBytesToWrite, LPDWORD lpBytesWritten, BOOL bWait )
717 Pipe *pPipe = (Pipe *)hPipe;
719 if ( pPipe->is() )
720 return pPipe->Write( lpBuffer, dwBytesToWrite, lpBytesWritten, bWait );
721 else
723 SetLastError( ERROR_INVALID_HANDLE );
724 return FALSE;
728 extern "C" BOOL WINAPI ReadSimplePipe( HANDLE hPipe, LPVOID lpBuffer, DWORD dwBytesToRead, LPDWORD lpBytesRead, BOOL bWait )
730 Pipe *pPipe = (Pipe *)hPipe;
732 if ( pPipe->is() )
733 return pPipe->Read( lpBuffer, dwBytesToRead, lpBytesRead, bWait );
734 else
736 SetLastError( ERROR_INVALID_HANDLE );
737 return FALSE;
741 extern "C" BOOL WINAPI CloseSimplePipe( HANDLE hPipe )
743 Pipe *pPipe = (Pipe *)hPipe;
745 if ( pPipe->is() )
747 delete pPipe;
748 return TRUE;
750 else
752 SetLastError( ERROR_INVALID_HANDLE );
753 return FALSE;