1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: pipeimpl.cxx,v $
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"
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 //============================================================================
56 //============================================================================
65 //============================================================================
67 //============================================================================
71 #define ClientPipe ClientPipeW
72 #define ServerPipe ServerPipeW
75 #define ClientPipe ClientPipeA
76 #define ServerPipe ServerPipeA
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
);
94 const Pipe
& operator = ( const Pipe
& );
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
);
107 void * operator new( size_t nBytes
)
109 return HeapAlloc( GetProcessHeap(), 0, nBytes
);
112 void operator delete( void *ptr
)
114 HeapFree( GetProcessHeap(), 0, ptr
);
119 return (FALSE
!= HeapValidate( GetProcessHeap(), 0, this ));
124 //============================================================================
126 //============================================================================
128 class ClientPipe
: public Pipe
131 ClientPipe( HANDLE hReadPipe
, HANDLE hWritePipe
);
133 static ClientPipe
* Create( LPCTSTR lpName
);
136 //============================================================================
138 //============================================================================
140 class ServerPipe
: public Pipe
144 HANDLE m_hSynchronize
;
147 ServerPipe( LPCTSTR lpName
, HANDLE hMapping
, HANDLE hSynchronize
, HANDLE hReadPipe
, HANDLE hWritePipe
);
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
) );
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
);
184 SetLastError( ERROR_NOT_ENOUGH_MEMORY
);
190 _tcscat( lpMappingFileName
, lpMappingName
);
192 HANDLE hFile
= CreateFile(
194 GENERIC_READ
| GENERIC_WRITE
,
195 FILE_SHARE_READ
| FILE_SHARE_WRITE
,
198 FILE_ATTRIBUTE_TEMPORARY
| FILE_FLAG_DELETE_ON_CLOSE
,
201 if ( IsValidHandle(hFile
) )
203 hMapping
= CreateFileMapping(
205 (LPSECURITY_ATTRIBUTES
)NULL
,
211 CloseHandle( hFile
);
216 SetLastError( ERROR_NOT_ENOUGH_MEMORY
);
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
) );
233 _tcscpy( lpMappingName
, PIPE_NAME_PREFIX_MAPPING
);
234 _tcscat( lpMappingName
, lpName
);
236 hMapping
= OpenFileMapping( FILE_MAP_ALL_ACCESS
, FALSE
, lpMappingName
);
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
) );
253 _tcscpy( lpMutexName
, PIPE_NAME_PREFIX_SYNCHRONIZE
);
254 _tcscat( lpMutexName
, lpName
);
256 hMutex
= CreateMutex( NULL
, bInitialOwner
, lpMutexName
);
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
);
283 //----------------------------------------------------------------------------
285 //----------------------------------------------------------------------------
287 Pipe::Pipe( const Pipe
& rPipe
) :
288 m_hReadPipe( INVALID_HANDLE_VALUE
),
289 m_hWritePipe( INVALID_HANDLE_VALUE
)
298 DUPLICATE_SAME_ACCESS
);
307 DUPLICATE_SAME_ACCESS
);
310 //----------------------------------------------------------------------------
311 // Pipe assignment operator
312 //----------------------------------------------------------------------------
314 const Pipe
& Pipe::operator = ( const Pipe
& rPipe
)
325 DUPLICATE_SAME_ACCESS
);
334 DUPLICATE_SAME_ACCESS
);
339 //----------------------------------------------------------------------------
341 //----------------------------------------------------------------------------
343 Pipe::Pipe( HANDLE hReadPipe
, HANDLE hWritePipe
) :
344 m_hReadPipe( INVALID_HANDLE_VALUE
),
345 m_hWritePipe( INVALID_HANDLE_VALUE
)
354 DUPLICATE_SAME_ACCESS
);
363 DUPLICATE_SAME_ACCESS
);
366 //----------------------------------------------------------------------------
368 //----------------------------------------------------------------------------
375 //----------------------------------------------------------------------------
377 //----------------------------------------------------------------------------
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
;
398 //----------------------------------------------------------------------------
400 //----------------------------------------------------------------------------
402 bool Pipe::Write( LPCVOID lpBuffer
, DWORD dwBytesToWrite
, LPDWORD lpBytesWritten
, bool bWait
)
404 DWORD dwBytesAvailable
= 0;
405 BOOL fSuccess
= TRUE
;
408 fSuccess
= PeekNamedPipe( m_hReadPipe
, NULL
, 0, NULL
, &dwBytesAvailable
, NULL
);
412 if ( !bWait
&& dwBytesToWrite
> PIPE_BUFFER_SIZE
- dwBytesAvailable
)
413 dwBytesToWrite
= PIPE_BUFFER_SIZE
- dwBytesAvailable
;
415 return !!WriteFile( m_hWritePipe
, lpBuffer
, dwBytesToWrite
, lpBytesWritten
, NULL
);
421 //----------------------------------------------------------------------------
423 //----------------------------------------------------------------------------
425 bool Pipe::Read( LPVOID lpBuffer
, DWORD dwBytesToRead
, LPDWORD lpBytesRead
, bool bWait
)
427 DWORD dwBytesAvailable
= 0;
428 BOOL fSuccess
= TRUE
;
431 fSuccess
= PeekNamedPipe( m_hReadPipe
, NULL
, 0, NULL
, &dwBytesAvailable
, NULL
);
435 if ( bWait
|| dwBytesAvailable
)
436 return !!ReadFile( m_hReadPipe
, lpBuffer
, dwBytesToRead
, lpBytesRead
, NULL
);
449 //----------------------------------------------------------------------------
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 );
473 HANDLE hSourceProcess
= OpenProcess( PROCESS_DUP_HANDLE
, FALSE
, pData
->dwProcessId
);
475 if ( IsValidHandle(hSourceProcess
) )
478 HANDLE hReadPipe
= INVALID_HANDLE_VALUE
, hWritePipe
= INVALID_HANDLE_VALUE
;
480 fSuccess
= DuplicateHandle(
487 DUPLICATE_SAME_ACCESS
);
489 fSuccess
= fSuccess
&& DuplicateHandle(
496 DUPLICATE_SAME_ACCESS
);
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
);
527 //----------------------------------------------------------------------------
529 //----------------------------------------------------------------------------
531 ServerPipe::ServerPipe( LPCTSTR lpName
, HANDLE hMapping
, HANDLE hSynchronize
, HANDLE hReadPipe
, HANDLE hWritePipe
) : Pipe( hReadPipe
, hWritePipe
),
533 m_hSynchronize( NULL
),
543 DUPLICATE_SAME_ACCESS
);
552 DUPLICATE_SAME_ACCESS
554 m_lpName
= new TCHAR
[_tcslen(lpName
) + 1];
556 _tcscpy( m_lpName
, lpName
);
559 //----------------------------------------------------------------------------
561 //----------------------------------------------------------------------------
563 ServerPipe::~ServerPipe()
565 if ( IsValidHandle(m_hMapping
) )
566 CloseHandle( m_hMapping
);
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 );
586 // Create new inbound Pipe
588 HANDLE hClientWritePipe
= NULL
, hServerReadPipe
= NULL
;
590 BOOL fSuccess
= CreatePipe( &hServerReadPipe
, &hClientWritePipe
, NULL
, PIPE_BUFFER_SIZE
);
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
);
621 CloseHandle( hClientWritePipe
);
622 CloseHandle( hServerWritePipe
);
626 ReleaseMutex( hConnectionRequest
);
629 CloseHandle( hConnectionRequest
);
634 //----------------------------------------------------------------------------
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 );
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
);
671 // Create outbound pipe
673 HANDLE hServerWritePipe
= NULL
, hClientReadPipe
= NULL
;
675 fSuccess
= CreatePipe( &hClientReadPipe
, &hServerWritePipe
, NULL
, PIPE_BUFFER_SIZE
);
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
);
689 CloseHandle( hServerReadPipe
);
690 CloseHandle( hClientWritePipe
);
694 UnmapViewOfFile( pData
);
697 ReleaseMutex( hSynchronize
);
698 CloseHandle( hSynchronize
);
701 CloseHandle( hMapping
);
708 //----------------------------------------------------------------------------
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
;
735 return (HANDLE
)pPipe
->AcceptConnection();
738 SetLastError( ERROR_INVALID_HANDLE
);
743 extern "C" BOOL WINAPI
WaitForSimplePipe( LPCTSTR
/*lpName*/, DWORD
/*dwTimeOut*/ )
748 extern "C" BOOL WINAPI
WriteSimplePipe( HANDLE hPipe
, LPCVOID lpBuffer
, DWORD dwBytesToWrite
, LPDWORD lpBytesWritten
, BOOL bWait
)
750 Pipe
*pPipe
= (Pipe
*)hPipe
;
753 return pPipe
->Write( lpBuffer
, dwBytesToWrite
, lpBytesWritten
, bWait
);
756 SetLastError( ERROR_INVALID_HANDLE
);
761 extern "C" BOOL WINAPI
ReadSimplePipe( HANDLE hPipe
, LPVOID lpBuffer
, DWORD dwBytesToRead
, LPDWORD lpBytesRead
, BOOL bWait
)
763 Pipe
*pPipe
= (Pipe
*)hPipe
;
766 return pPipe
->Read( lpBuffer
, dwBytesToRead
, lpBytesRead
, bWait
);
769 SetLastError( ERROR_INVALID_HANDLE
);
774 extern "C" BOOL WINAPI
CloseSimplePipe( HANDLE hPipe
)
776 Pipe
*pPipe
= (Pipe
*)hPipe
;
785 SetLastError( ERROR_INVALID_HANDLE
);