update dev300-m58
[ooovba.git] / sal / osl / w32 / pipeimpl.cxx
blob9ea65f52242b91da7a07ea9d7406790a3a5f9454
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: pipeimpl.cxx,v $
10 * $Revision: 1.4 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
32 // MARKER(update_precomp.py): autogen include statement, do not remove
33 #include "precompiled_sal.hxx"
34 # include "pipeimpl.h"
36 #ifndef _INC_MALLOC
37 # include <malloc.h>
38 #endif
40 #ifndef _INC_TCHAR
41 # ifdef UNICODE
42 # define _UNICODE
43 # endif
44 # include <tchar.h>
45 #endif
47 const TCHAR PIPE_NAME_PREFIX_MAPPING[] = TEXT("PIPE_FILE_MAPPING_");
48 const TCHAR PIPE_NAME_PREFIX_SYNCHRONIZE[] = TEXT("PIPE_SYNCHRONIZE_MUTEX_");
49 const TCHAR PIPE_NAME_PREFIX_CONNECTION[] = TEXT("PIPE_CONNECTION_SEMAPHORE_");
51 const DWORD PIPE_BUFFER_SIZE = 4096;
54 //============================================================================
55 // PipeData
56 //============================================================================
58 struct PipeData
60 DWORD dwProcessId;
61 HANDLE hReadPipe;
62 HANDLE hWritePipe;
65 //============================================================================
66 // Pipe
67 //============================================================================
69 #ifdef UNICODE
70 #define Pipe PipeW
71 #define ClientPipe ClientPipeW
72 #define ServerPipe ServerPipeW
73 #else
74 #define Pipe PipeA
75 #define ClientPipe ClientPipeA
76 #define ServerPipe ServerPipeA
77 #endif
79 class Pipe
81 protected:
82 HANDLE m_hReadPipe; // Handle to use for reading
83 HANDLE m_hWritePipe; // Handle to use for writing
85 Pipe( HANDLE hReadPipe, HANDLE hWritePipe );
87 static HANDLE CreatePipeDataMutex( LPCTSTR lpName, BOOL bInitialOwner );
88 static HANDLE CreatePipeDataMapping( LPCTSTR lpName );
89 static HANDLE OpenPipeDataMapping( LPCTSTR lpName );
90 static HANDLE CreatePipeConnectionSemaphore( LPCTSTR lpName, LONG lInitialCount, LONG lMaximumcount );
92 public:
93 Pipe( const Pipe& );
94 const Pipe& operator = ( const Pipe& );
95 virtual ~Pipe();
97 virtual bool Close();
98 virtual bool Write( LPCVOID lpBuffer, DWORD dwBytesToWrite, LPDWORD lpBytesWritten, bool bWait = true );
99 virtual bool Read( LPVOID lpBuffer, DWORD dwBytesToRead, LPDWORD lpBytesRead, bool bWait = true );
101 virtual Pipe *AcceptConnection()
103 SetLastError( ERROR_INVALID_HANDLE );
104 return NULL;
107 void * operator new( size_t nBytes )
109 return HeapAlloc( GetProcessHeap(), 0, nBytes );
112 void operator delete( void *ptr )
114 HeapFree( GetProcessHeap(), 0, ptr );
117 bool is() const
119 return (FALSE != HeapValidate( GetProcessHeap(), 0, this ));
124 //============================================================================
125 // ClientPipe
126 //============================================================================
128 class ClientPipe : public Pipe
130 protected:
131 ClientPipe( HANDLE hReadPipe, HANDLE hWritePipe );
132 public:
133 static ClientPipe* Create( LPCTSTR lpName );
136 //============================================================================
137 // ServerPipe
138 //============================================================================
140 class ServerPipe : public Pipe
142 protected:
143 HANDLE m_hMapping;
144 HANDLE m_hSynchronize;
145 LPTSTR m_lpName;
147 ServerPipe( LPCTSTR lpName, HANDLE hMapping, HANDLE hSynchronize, HANDLE hReadPipe, HANDLE hWritePipe );
148 public:
149 virtual ~ServerPipe();
151 static ServerPipe *Create( LPCTSTR lpName );
153 virtual Pipe *AcceptConnection();
156 //----------------------------------------------------------------------------
158 //----------------------------------------------------------------------------
160 HANDLE Pipe::CreatePipeDataMapping( LPCTSTR lpName )
162 HANDLE hMapping = NULL;
163 LPTSTR lpMappingName = (LPTSTR)alloca( _tcslen(lpName) * sizeof(TCHAR) + sizeof(PIPE_NAME_PREFIX_MAPPING) );
165 if ( lpMappingName )
167 _tcscpy( lpMappingName, PIPE_NAME_PREFIX_MAPPING );
168 _tcscat( lpMappingName, lpName );
170 LPTSTR lpMappingFileName = (LPTSTR)alloca( MAX_PATH * sizeof(TCHAR) );
172 if ( lpMappingFileName )
174 DWORD nChars = GetTempPath( MAX_PATH, lpMappingFileName );
176 if ( MAX_PATH + _tcslen(lpName) < nChars + 1 )
178 lpMappingFileName = (LPTSTR)alloca( (nChars + 1 + _tcslen(lpName)) * sizeof(TCHAR) );
179 if ( lpMappingFileName )
180 nChars = GetTempPath( nChars, lpMappingFileName );
181 else
183 nChars = 0;
184 SetLastError( ERROR_NOT_ENOUGH_MEMORY );
188 if ( nChars )
190 _tcscat( lpMappingFileName, lpMappingName );
192 HANDLE hFile = CreateFile(
193 lpMappingFileName,
194 GENERIC_READ | GENERIC_WRITE,
195 FILE_SHARE_READ | FILE_SHARE_WRITE,
196 NULL,
197 OPEN_ALWAYS,
198 FILE_ATTRIBUTE_TEMPORARY | FILE_FLAG_DELETE_ON_CLOSE,
199 NULL );
201 if ( IsValidHandle(hFile) )
203 hMapping = CreateFileMapping(
204 (HANDLE)hFile,
205 (LPSECURITY_ATTRIBUTES)NULL,
206 PAGE_READWRITE,
208 sizeof(PipeData),
209 lpMappingName );
211 CloseHandle( hFile );
215 else
216 SetLastError( ERROR_NOT_ENOUGH_MEMORY );
219 return hMapping;
222 //----------------------------------------------------------------------------
224 //----------------------------------------------------------------------------
226 HANDLE Pipe::OpenPipeDataMapping( LPCTSTR lpName )
228 HANDLE hMapping = NULL;
229 LPTSTR lpMappingName = (LPTSTR)alloca( _tcslen(lpName) * sizeof(TCHAR) + sizeof(PIPE_NAME_PREFIX_MAPPING) );
231 if ( lpMappingName )
233 _tcscpy( lpMappingName, PIPE_NAME_PREFIX_MAPPING );
234 _tcscat( lpMappingName, lpName );
236 hMapping = OpenFileMapping( FILE_MAP_ALL_ACCESS, FALSE, lpMappingName );
239 return hMapping;
242 //----------------------------------------------------------------------------
244 //----------------------------------------------------------------------------
246 HANDLE Pipe::CreatePipeDataMutex( LPCTSTR lpName, BOOL bInitialOwner )
248 HANDLE hMutex = NULL;
249 LPTSTR lpMutexName = (LPTSTR)alloca( _tcslen(lpName) * sizeof(TCHAR) + sizeof(PIPE_NAME_PREFIX_SYNCHRONIZE) );
251 if ( lpMutexName )
253 _tcscpy( lpMutexName, PIPE_NAME_PREFIX_SYNCHRONIZE );
254 _tcscat( lpMutexName, lpName );
256 hMutex = CreateMutex( NULL, bInitialOwner, lpMutexName );
259 return hMutex;
262 //----------------------------------------------------------------------------
264 //----------------------------------------------------------------------------
266 HANDLE Pipe::CreatePipeConnectionSemaphore( LPCTSTR lpName, LONG lInitialCount, LONG lMaximumCount )
268 HANDLE hSemaphore = NULL;
269 LPTSTR lpSemaphoreName = (LPTSTR)alloca( _tcslen(lpName) * sizeof(TCHAR) + sizeof(PIPE_NAME_PREFIX_CONNECTION) );
271 if ( lpSemaphoreName )
273 _tcscpy( lpSemaphoreName, PIPE_NAME_PREFIX_CONNECTION );
274 _tcscat( lpSemaphoreName, lpName );
276 hSemaphore = CreateSemaphore( NULL, lInitialCount, lMaximumCount, lpSemaphoreName );
279 return hSemaphore;
283 //----------------------------------------------------------------------------
284 // Pipe copy ctor
285 //----------------------------------------------------------------------------
287 Pipe::Pipe( const Pipe& rPipe ) :
288 m_hReadPipe( INVALID_HANDLE_VALUE ),
289 m_hWritePipe( INVALID_HANDLE_VALUE )
291 DuplicateHandle(
292 GetCurrentProcess(),
293 rPipe.m_hReadPipe,
294 GetCurrentProcess(),
295 &m_hReadPipe,
297 FALSE,
298 DUPLICATE_SAME_ACCESS );
300 DuplicateHandle(
301 GetCurrentProcess(),
302 rPipe.m_hWritePipe,
303 GetCurrentProcess(),
304 &m_hWritePipe,
306 FALSE,
307 DUPLICATE_SAME_ACCESS );
310 //----------------------------------------------------------------------------
311 // Pipe assignment operator
312 //----------------------------------------------------------------------------
314 const Pipe& Pipe::operator = ( const Pipe& rPipe )
316 Close();
318 DuplicateHandle(
319 GetCurrentProcess(),
320 rPipe.m_hReadPipe,
321 GetCurrentProcess(),
322 &m_hReadPipe,
324 FALSE,
325 DUPLICATE_SAME_ACCESS );
327 DuplicateHandle(
328 GetCurrentProcess(),
329 rPipe.m_hWritePipe,
330 GetCurrentProcess(),
331 &m_hWritePipe,
333 FALSE,
334 DUPLICATE_SAME_ACCESS );
336 return *this;
339 //----------------------------------------------------------------------------
340 // Pipe ctor
341 //----------------------------------------------------------------------------
343 Pipe::Pipe( HANDLE hReadPipe, HANDLE hWritePipe ) :
344 m_hReadPipe( INVALID_HANDLE_VALUE ),
345 m_hWritePipe( INVALID_HANDLE_VALUE )
347 DuplicateHandle(
348 GetCurrentProcess(),
349 hReadPipe,
350 GetCurrentProcess(),
351 &m_hReadPipe,
353 FALSE,
354 DUPLICATE_SAME_ACCESS );
356 DuplicateHandle(
357 GetCurrentProcess(),
358 hWritePipe,
359 GetCurrentProcess(),
360 &m_hWritePipe,
362 FALSE,
363 DUPLICATE_SAME_ACCESS );
366 //----------------------------------------------------------------------------
367 // Pipe dtor
368 //----------------------------------------------------------------------------
370 Pipe::~Pipe()
372 Close();
375 //----------------------------------------------------------------------------
376 // Pipe Close
377 //----------------------------------------------------------------------------
379 bool Pipe::Close()
381 bool fSuccess = false; // Assume failure
383 if ( IsValidHandle(m_hReadPipe) )
385 CloseHandle( m_hReadPipe );
386 m_hReadPipe = INVALID_HANDLE_VALUE;
389 if ( IsValidHandle(m_hWritePipe) )
391 CloseHandle( m_hWritePipe );
392 m_hWritePipe = INVALID_HANDLE_VALUE;
395 return fSuccess;
398 //----------------------------------------------------------------------------
399 // Pipe Write
400 //----------------------------------------------------------------------------
402 bool Pipe::Write( LPCVOID lpBuffer, DWORD dwBytesToWrite, LPDWORD lpBytesWritten, bool bWait )
404 DWORD dwBytesAvailable = 0;
405 BOOL fSuccess = TRUE;
407 if ( !bWait )
408 fSuccess = PeekNamedPipe( m_hReadPipe, NULL, 0, NULL, &dwBytesAvailable, NULL );
410 if ( fSuccess )
412 if ( !bWait && dwBytesToWrite > PIPE_BUFFER_SIZE - dwBytesAvailable )
413 dwBytesToWrite = PIPE_BUFFER_SIZE - dwBytesAvailable ;
415 return !!WriteFile( m_hWritePipe, lpBuffer, dwBytesToWrite, lpBytesWritten, NULL );
418 return false;
421 //----------------------------------------------------------------------------
422 // Pipe Read
423 //----------------------------------------------------------------------------
425 bool Pipe::Read( LPVOID lpBuffer, DWORD dwBytesToRead, LPDWORD lpBytesRead, bool bWait )
427 DWORD dwBytesAvailable = 0;
428 BOOL fSuccess = TRUE;
430 if ( !bWait )
431 fSuccess = PeekNamedPipe( m_hReadPipe, NULL, 0, NULL, &dwBytesAvailable, NULL );
433 if ( fSuccess )
435 if ( bWait || dwBytesAvailable )
436 return !!ReadFile( m_hReadPipe, lpBuffer, dwBytesToRead, lpBytesRead, NULL );
437 else
439 *lpBytesRead = 0;
440 return true;
444 return false;
449 //----------------------------------------------------------------------------
450 // Client pipe dtor
451 //----------------------------------------------------------------------------
453 ClientPipe::ClientPipe( HANDLE hReadPipe, HANDLE hWritePipe ) : Pipe( hReadPipe, hWritePipe )
457 //----------------------------------------------------------------------------
458 // Client pipe creation
459 //----------------------------------------------------------------------------
461 ClientPipe *ClientPipe::Create( LPCTSTR lpName )
463 ClientPipe *pPipe = NULL; // Assume failure
465 HANDLE hMapping = OpenPipeDataMapping( lpName );
467 if ( IsValidHandle(hMapping) )
469 PipeData *pData = (PipeData*)MapViewOfFile( hMapping, FILE_MAP_ALL_ACCESS, 0, 0, 0 );
471 if ( pData )
473 HANDLE hSourceProcess = OpenProcess( PROCESS_DUP_HANDLE, FALSE, pData->dwProcessId );
475 if ( IsValidHandle(hSourceProcess) )
477 BOOL fSuccess;
478 HANDLE hReadPipe = INVALID_HANDLE_VALUE, hWritePipe = INVALID_HANDLE_VALUE;
480 fSuccess = DuplicateHandle(
481 hSourceProcess,
482 pData->hReadPipe,
483 GetCurrentProcess(),
484 &hReadPipe,
486 FALSE,
487 DUPLICATE_SAME_ACCESS );
489 fSuccess = fSuccess && DuplicateHandle(
490 hSourceProcess,
491 pData->hWritePipe,
492 GetCurrentProcess(),
493 &hWritePipe,
495 FALSE,
496 DUPLICATE_SAME_ACCESS );
498 if ( fSuccess )
499 pPipe = new ClientPipe( hReadPipe, hWritePipe );
501 if ( IsValidHandle(hWritePipe) )
502 CloseHandle( hWritePipe );
504 if ( IsValidHandle(hReadPipe) )
505 CloseHandle( hReadPipe );
507 HANDLE hConnectionRequest = CreatePipeConnectionSemaphore( lpName, 0, 1 );
509 ReleaseSemaphore( hConnectionRequest, 1, NULL );
511 CloseHandle( hConnectionRequest );
513 CloseHandle( hSourceProcess );
516 UnmapViewOfFile( pData );
519 CloseHandle( hMapping );
522 return pPipe;
527 //----------------------------------------------------------------------------
528 // ServerPipe ctor
529 //----------------------------------------------------------------------------
531 ServerPipe::ServerPipe( LPCTSTR lpName, HANDLE hMapping, HANDLE hSynchronize, HANDLE hReadPipe, HANDLE hWritePipe ) : Pipe( hReadPipe, hWritePipe ),
532 m_hMapping( NULL ),
533 m_hSynchronize( NULL ),
534 m_lpName( NULL )
536 DuplicateHandle(
537 GetCurrentProcess(),
538 hMapping,
539 GetCurrentProcess(),
540 &m_hMapping,
542 FALSE,
543 DUPLICATE_SAME_ACCESS );
545 DuplicateHandle(
546 GetCurrentProcess(),
547 hSynchronize,
548 GetCurrentProcess(),
549 &m_hSynchronize,
551 FALSE,
552 DUPLICATE_SAME_ACCESS
554 m_lpName = new TCHAR[_tcslen(lpName) + 1];
555 if ( m_lpName )
556 _tcscpy( m_lpName, lpName );
559 //----------------------------------------------------------------------------
560 // ServerPipe dtor
561 //----------------------------------------------------------------------------
563 ServerPipe::~ServerPipe()
565 if ( IsValidHandle(m_hMapping) )
566 CloseHandle( m_hMapping );
567 if ( m_lpName )
568 delete[]m_lpName;
571 //----------------------------------------------------------------------------
572 // ServerPipe AcceptConnection
573 //----------------------------------------------------------------------------
575 Pipe *ServerPipe::AcceptConnection()
577 Pipe *pPipe = NULL; // Assume failure;
579 HANDLE hConnectionRequest = CreatePipeConnectionSemaphore( m_lpName, 0, 1 );
581 if ( WAIT_OBJECT_0 == WaitForSingleObject( hConnectionRequest, INFINITE ) )
583 pPipe = new Pipe( *this );
584 Close();
586 // Create new inbound Pipe
588 HANDLE hClientWritePipe = NULL, hServerReadPipe = NULL;
590 BOOL fSuccess = CreatePipe( &hServerReadPipe, &hClientWritePipe, NULL, PIPE_BUFFER_SIZE );
593 if ( fSuccess )
595 // Create outbound pipe
597 HANDLE hClientReadPipe = NULL, hServerWritePipe = NULL;
599 if ( CreatePipe( &hClientReadPipe, &hServerWritePipe, NULL, PIPE_BUFFER_SIZE ) )
601 m_hReadPipe = hServerReadPipe;
602 m_hWritePipe = hServerWritePipe;
604 PipeData *pData = (PipeData *)MapViewOfFile( m_hMapping, FILE_MAP_ALL_ACCESS, 0, 0, sizeof(PipeData) );
606 HANDLE hSynchronize = CreatePipeDataMutex( m_lpName, TRUE );
608 CloseHandle( pData->hReadPipe );
609 CloseHandle( pData->hWritePipe );
611 pData->hReadPipe = hClientReadPipe;
612 pData->hWritePipe = hClientWritePipe;
614 ReleaseMutex( hSynchronize );
616 CloseHandle( hSynchronize );
619 else
621 CloseHandle( hClientWritePipe );
622 CloseHandle( hServerWritePipe );
626 ReleaseMutex( hConnectionRequest );
629 CloseHandle( hConnectionRequest );
631 return pPipe;
634 //----------------------------------------------------------------------------
635 // Pipe creation
636 //----------------------------------------------------------------------------
638 ServerPipe *ServerPipe::Create( LPCTSTR lpName )
640 ServerPipe *pPipe = NULL;
642 HANDLE hMapping = CreatePipeDataMapping( lpName );
644 if ( IsValidHandle(hMapping) )
646 if ( ERROR_FILE_EXISTS != GetLastError() )
648 HANDLE hSynchronize = CreatePipeDataMutex( lpName, FALSE);
650 WaitForSingleObject( hSynchronize, INFINITE );
652 PipeData *pData = (PipeData*)MapViewOfFile( hMapping, FILE_MAP_ALL_ACCESS, 0, 0, 0 );
654 if ( pData )
657 // Initialize pipe data
659 pData->dwProcessId = 0;
660 pData->hReadPipe = NULL;
661 pData->hWritePipe = NULL;
663 // Create inbound pipe
665 HANDLE hServerReadPipe = NULL, hClientWritePipe = NULL;
667 BOOL fSuccess = CreatePipe( &hServerReadPipe, &hClientWritePipe, NULL, PIPE_BUFFER_SIZE );
669 if ( fSuccess )
671 // Create outbound pipe
673 HANDLE hServerWritePipe = NULL, hClientReadPipe = NULL;
675 fSuccess = CreatePipe( &hClientReadPipe, &hServerWritePipe, NULL, PIPE_BUFFER_SIZE );
677 if ( fSuccess )
679 pData->dwProcessId = GetCurrentProcessId();
680 pData->hReadPipe = hClientReadPipe;
681 pData->hWritePipe = hClientWritePipe;
682 pPipe = new ServerPipe( lpName, hMapping, hSynchronize, hServerReadPipe, hServerWritePipe );
684 CloseHandle( hServerWritePipe );
685 CloseHandle( hServerReadPipe );
687 else
689 CloseHandle( hServerReadPipe );
690 CloseHandle( hClientWritePipe );
694 UnmapViewOfFile( pData );
697 ReleaseMutex( hSynchronize );
698 CloseHandle( hSynchronize );
701 CloseHandle( hMapping );
704 return pPipe;
708 //----------------------------------------------------------------------------
709 // C style API
710 //----------------------------------------------------------------------------
712 const TCHAR LOCAL_PIPE_PREFIX[] = TEXT("\\\\.\\PIPE\\" );
714 extern "C" HANDLE WINAPI CreateSimplePipe( LPCTSTR lpName )
716 int nPrefixLen = _tcslen( LOCAL_PIPE_PREFIX );
717 if ( 0 == _tcsnicmp( lpName, LOCAL_PIPE_PREFIX, nPrefixLen ) )
718 lpName += nPrefixLen;
719 return (HANDLE)ServerPipe::Create( lpName );
722 extern "C" HANDLE WINAPI OpenSimplePipe( LPCTSTR lpName )
724 int nPrefixLen = _tcslen( LOCAL_PIPE_PREFIX );
725 if ( 0 == _tcsnicmp( lpName, LOCAL_PIPE_PREFIX, nPrefixLen ) )
726 lpName += nPrefixLen;
727 return (HANDLE)ClientPipe::Create( lpName );
730 extern "C" HANDLE WINAPI AcceptSimplePipeConnection( HANDLE hPipe )
732 Pipe *pPipe = (Pipe *)hPipe;
734 if ( pPipe->is() )
735 return (HANDLE)pPipe->AcceptConnection();
736 else
738 SetLastError( ERROR_INVALID_HANDLE );
739 return NULL;
743 extern "C" BOOL WINAPI WaitForSimplePipe( LPCTSTR /*lpName*/, DWORD /*dwTimeOut*/ )
745 return FALSE;
748 extern "C" BOOL WINAPI WriteSimplePipe( HANDLE hPipe, LPCVOID lpBuffer, DWORD dwBytesToWrite, LPDWORD lpBytesWritten, BOOL bWait )
750 Pipe *pPipe = (Pipe *)hPipe;
752 if ( pPipe->is() )
753 return pPipe->Write( lpBuffer, dwBytesToWrite, lpBytesWritten, bWait );
754 else
756 SetLastError( ERROR_INVALID_HANDLE );
757 return FALSE;
761 extern "C" BOOL WINAPI ReadSimplePipe( HANDLE hPipe, LPVOID lpBuffer, DWORD dwBytesToRead, LPDWORD lpBytesRead, BOOL bWait )
763 Pipe *pPipe = (Pipe *)hPipe;
765 if ( pPipe->is() )
766 return pPipe->Read( lpBuffer, dwBytesToRead, lpBytesRead, bWait );
767 else
769 SetLastError( ERROR_INVALID_HANDLE );
770 return FALSE;
774 extern "C" BOOL WINAPI CloseSimplePipe( HANDLE hPipe )
776 Pipe *pPipe = (Pipe *)hPipe;
778 if ( pPipe->is() )
780 delete pPipe;
781 return TRUE;
783 else
785 SetLastError( ERROR_INVALID_HANDLE );
786 return FALSE;