xref: /trunk/main/sal/osl/w32/pipeimpl.cxx (revision cdf0e10c)
1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
11  * OpenOffice.org is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License version 3
13  * only, as published by the Free Software Foundation.
14  *
15  * OpenOffice.org is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Lesser General Public License version 3 for more details
19  * (a copy is included in the LICENSE file that accompanied this code).
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * version 3 along with OpenOffice.org.  If not, see
23  * <http://www.openoffice.org/license.html>
24  * for a copy of the LGPLv3 License.
25  *
26  ************************************************************************/
27 
28 
29 // MARKER(update_precomp.py): autogen include statement, do not remove
30 #include "precompiled_sal.hxx"
31 #	include "pipeimpl.h"
32 
33 #ifndef _INC_MALLOC
34 #	include <malloc.h>
35 #endif
36 
37 #ifndef _INC_TCHAR
38 #	ifdef UNICODE
39 #		define _UNICODE
40 #	endif
41 #	include <tchar.h>
42 #endif
43 
44 const TCHAR PIPE_NAME_PREFIX_MAPPING[] = TEXT("PIPE_FILE_MAPPING_");
45 const TCHAR PIPE_NAME_PREFIX_SYNCHRONIZE[] = TEXT("PIPE_SYNCHRONIZE_MUTEX_");
46 const TCHAR PIPE_NAME_PREFIX_CONNECTION[] = TEXT("PIPE_CONNECTION_SEMAPHORE_");
47 
48 const DWORD PIPE_BUFFER_SIZE = 4096;
49 
50 
51 //============================================================================
52 //	PipeData
53 //============================================================================
54 
55 struct PipeData
56 {
57 	DWORD	dwProcessId;
58 	HANDLE	hReadPipe;
59 	HANDLE	hWritePipe;
60 };
61 
62 //============================================================================
63 //	Pipe
64 //============================================================================
65 
66 #ifdef UNICODE
67 #define Pipe		PipeW
68 #define ClientPipe	ClientPipeW
69 #define ServerPipe	ServerPipeW
70 #else
71 #define Pipe		PipeA
72 #define ClientPipe	ClientPipeA
73 #define ServerPipe	ServerPipeA
74 #endif
75 
76 class Pipe
77 {
78 protected:
79 	HANDLE	m_hReadPipe;	// Handle to use for reading
80 	HANDLE	m_hWritePipe;	// Handle to use for writing
81 
82 	Pipe( HANDLE hReadPipe, HANDLE hWritePipe );
83 
84 	static HANDLE CreatePipeDataMutex( LPCTSTR lpName, BOOL bInitialOwner );
85 	static HANDLE CreatePipeDataMapping( LPCTSTR lpName );
86 	static HANDLE OpenPipeDataMapping( LPCTSTR lpName );
87 	static HANDLE CreatePipeConnectionSemaphore( LPCTSTR lpName, LONG lInitialCount, LONG lMaximumcount );
88 
89 public:
90 	Pipe( const Pipe& );
91 	const Pipe& operator = ( const Pipe& );
92 	virtual ~Pipe();
93 
94 	virtual bool Close();
95 	virtual bool Write( LPCVOID lpBuffer, DWORD dwBytesToWrite, LPDWORD lpBytesWritten, bool bWait = true );
96 	virtual bool Read( LPVOID lpBuffer, DWORD dwBytesToRead, LPDWORD lpBytesRead, bool bWait = true );
97 
98 	virtual Pipe *AcceptConnection()
99 	{
100 		SetLastError( ERROR_INVALID_HANDLE );
101 		return NULL;
102 	}
103 
104 	void * operator new( size_t nBytes )
105 	{
106 		return HeapAlloc( GetProcessHeap(), 0, nBytes );
107 	}
108 
109 	void operator delete( void *ptr )
110 	{
111 		HeapFree( GetProcessHeap(), 0, ptr );
112 	}
113 
114 	bool is() const
115 	{
116 		return (FALSE != HeapValidate( GetProcessHeap(), 0, this ));
117 	}
118 
119 };
120 
121 //============================================================================
122 //	ClientPipe
123 //============================================================================
124 
125 class ClientPipe : public Pipe
126 {
127 protected:
128 	ClientPipe( HANDLE hReadPipe, HANDLE hWritePipe );
129 public:
130 	static ClientPipe* Create( LPCTSTR lpName );
131 };
132 
133 //============================================================================
134 //	ServerPipe
135 //============================================================================
136 
137 class ServerPipe : public Pipe
138 {
139 protected:
140 	HANDLE	m_hMapping;
141 	HANDLE	m_hSynchronize;
142 	LPTSTR	m_lpName;
143 
144 	ServerPipe( LPCTSTR lpName, HANDLE hMapping, HANDLE hSynchronize, HANDLE hReadPipe, HANDLE hWritePipe );
145 public:
146 	virtual ~ServerPipe();
147 
148 	static ServerPipe *Create( LPCTSTR lpName );
149 
150 	virtual Pipe *AcceptConnection();
151 };
152 
153 //----------------------------------------------------------------------------
154 //
155 //----------------------------------------------------------------------------
156 
157 HANDLE	Pipe::CreatePipeDataMapping( LPCTSTR lpName )
158 {
159 	HANDLE	hMapping = NULL;
160 	LPTSTR	lpMappingName = (LPTSTR)alloca( _tcslen(lpName) * sizeof(TCHAR) + sizeof(PIPE_NAME_PREFIX_MAPPING) );
161 
162 	if ( lpMappingName )
163 	{
164 		_tcscpy( lpMappingName, PIPE_NAME_PREFIX_MAPPING );
165 		_tcscat( lpMappingName, lpName );
166 
167 		LPTSTR	lpMappingFileName = (LPTSTR)alloca( MAX_PATH * sizeof(TCHAR) );
168 
169 		if ( lpMappingFileName )
170 		{
171 			DWORD	nChars = GetTempPath( MAX_PATH, lpMappingFileName );
172 
173 			if ( MAX_PATH + _tcslen(lpName) < nChars + 1 )
174 			{
175 				lpMappingFileName = (LPTSTR)alloca( (nChars + 1 + _tcslen(lpName)) * sizeof(TCHAR) );
176 				if ( lpMappingFileName )
177 					nChars = GetTempPath( nChars, lpMappingFileName );
178 				else
179 				{
180 					nChars = 0;
181 					SetLastError( ERROR_NOT_ENOUGH_MEMORY );
182 				}
183 			}
184 
185 			if ( nChars )
186 			{
187 				_tcscat( lpMappingFileName, lpMappingName );
188 
189 				HANDLE hFile = CreateFile(
190 					lpMappingFileName,
191 					GENERIC_READ | GENERIC_WRITE,
192 					FILE_SHARE_READ | FILE_SHARE_WRITE,
193 					NULL,
194 					OPEN_ALWAYS,
195 					FILE_ATTRIBUTE_TEMPORARY | FILE_FLAG_DELETE_ON_CLOSE,
196 					NULL );
197 
198 				if ( IsValidHandle(hFile) )
199 				{
200 					hMapping = CreateFileMapping(
201 						(HANDLE)hFile,
202 						(LPSECURITY_ATTRIBUTES)NULL,
203 						PAGE_READWRITE,
204 						0,
205 						sizeof(PipeData),
206 						lpMappingName );
207 
208 					CloseHandle( hFile );
209 				}
210 			}
211 		}
212 		else
213 			SetLastError( ERROR_NOT_ENOUGH_MEMORY );
214 	}
215 
216 	return hMapping;
217 }
218 
219 //----------------------------------------------------------------------------
220 //
221 //----------------------------------------------------------------------------
222 
223 HANDLE	Pipe::OpenPipeDataMapping( LPCTSTR lpName )
224 {
225 	HANDLE	hMapping = NULL;
226 	LPTSTR	lpMappingName = (LPTSTR)alloca( _tcslen(lpName) * sizeof(TCHAR) + sizeof(PIPE_NAME_PREFIX_MAPPING) );
227 
228 	if ( lpMappingName )
229 	{
230 		_tcscpy( lpMappingName, PIPE_NAME_PREFIX_MAPPING );
231 		_tcscat( lpMappingName, lpName );
232 
233 		hMapping = OpenFileMapping( FILE_MAP_ALL_ACCESS, FALSE, lpMappingName );
234 	}
235 
236 	return hMapping;
237 }
238 
239 //----------------------------------------------------------------------------
240 //
241 //----------------------------------------------------------------------------
242 
243 HANDLE	Pipe::CreatePipeDataMutex( LPCTSTR lpName, BOOL bInitialOwner )
244 {
245 	HANDLE	hMutex = NULL;
246 	LPTSTR	lpMutexName = (LPTSTR)alloca( _tcslen(lpName) * sizeof(TCHAR) + sizeof(PIPE_NAME_PREFIX_SYNCHRONIZE) );
247 
248 	if ( lpMutexName )
249 	{
250 		_tcscpy( lpMutexName, PIPE_NAME_PREFIX_SYNCHRONIZE );
251 		_tcscat( lpMutexName, lpName );
252 
253 		hMutex = CreateMutex( NULL, bInitialOwner, lpMutexName );
254 	}
255 
256 	return hMutex;
257 }
258 
259 //----------------------------------------------------------------------------
260 //
261 //----------------------------------------------------------------------------
262 
263 HANDLE Pipe::CreatePipeConnectionSemaphore( LPCTSTR lpName, LONG lInitialCount, LONG lMaximumCount )
264 {
265 	HANDLE	hSemaphore = NULL;
266 	LPTSTR	lpSemaphoreName = (LPTSTR)alloca( _tcslen(lpName) * sizeof(TCHAR) + sizeof(PIPE_NAME_PREFIX_CONNECTION) );
267 
268 	if ( lpSemaphoreName )
269 	{
270 		_tcscpy( lpSemaphoreName, PIPE_NAME_PREFIX_CONNECTION );
271 		_tcscat( lpSemaphoreName, lpName );
272 
273 		hSemaphore = CreateSemaphore( NULL, lInitialCount, lMaximumCount, lpSemaphoreName );
274 	}
275 
276 	return hSemaphore;
277 }
278 
279 
280 //----------------------------------------------------------------------------
281 //	Pipe copy ctor
282 //----------------------------------------------------------------------------
283 
284 Pipe::Pipe( const Pipe& rPipe ) :
285 m_hReadPipe( INVALID_HANDLE_VALUE ),
286 m_hWritePipe( INVALID_HANDLE_VALUE )
287 {
288 	DuplicateHandle(
289 		GetCurrentProcess(),
290 		rPipe.m_hReadPipe,
291 		GetCurrentProcess(),
292 		&m_hReadPipe,
293 		0,
294 		FALSE,
295 		DUPLICATE_SAME_ACCESS );
296 
297 	DuplicateHandle(
298 		GetCurrentProcess(),
299 		rPipe.m_hWritePipe,
300 		GetCurrentProcess(),
301 		&m_hWritePipe,
302 		0,
303 		FALSE,
304 		DUPLICATE_SAME_ACCESS );
305 }
306 
307 //----------------------------------------------------------------------------
308 //	Pipe assignment operator
309 //----------------------------------------------------------------------------
310 
311 const Pipe& Pipe::operator = ( const Pipe& rPipe )
312 {
313 	Close();
314 
315 	DuplicateHandle(
316 		GetCurrentProcess(),
317 		rPipe.m_hReadPipe,
318 		GetCurrentProcess(),
319 		&m_hReadPipe,
320 		0,
321 		FALSE,
322 		DUPLICATE_SAME_ACCESS );
323 
324 	DuplicateHandle(
325 		GetCurrentProcess(),
326 		rPipe.m_hWritePipe,
327 		GetCurrentProcess(),
328 		&m_hWritePipe,
329 		0,
330 		FALSE,
331 		DUPLICATE_SAME_ACCESS );
332 
333 	return *this;
334 }
335 
336 //----------------------------------------------------------------------------
337 //	Pipe ctor
338 //----------------------------------------------------------------------------
339 
340 Pipe::Pipe( HANDLE hReadPipe, HANDLE hWritePipe ) :
341 m_hReadPipe( INVALID_HANDLE_VALUE ),
342 m_hWritePipe( INVALID_HANDLE_VALUE )
343 {
344 	DuplicateHandle(
345 		GetCurrentProcess(),
346 		hReadPipe,
347 		GetCurrentProcess(),
348 		&m_hReadPipe,
349 		0,
350 		FALSE,
351 		DUPLICATE_SAME_ACCESS );
352 
353 	DuplicateHandle(
354 		GetCurrentProcess(),
355 		hWritePipe,
356 		GetCurrentProcess(),
357 		&m_hWritePipe,
358 		0,
359 		FALSE,
360 		DUPLICATE_SAME_ACCESS );
361 }
362 
363 //----------------------------------------------------------------------------
364 //	Pipe dtor
365 //----------------------------------------------------------------------------
366 
367 Pipe::~Pipe()
368 {
369 	Close();
370 }
371 
372 //----------------------------------------------------------------------------
373 //	Pipe Close
374 //----------------------------------------------------------------------------
375 
376 bool Pipe::Close()
377 {
378 	bool	fSuccess = false;	// Assume failure
379 
380 	if ( IsValidHandle(m_hReadPipe) )
381 	{
382 		CloseHandle( m_hReadPipe );
383 		m_hReadPipe = INVALID_HANDLE_VALUE;
384 	}
385 
386 	if ( IsValidHandle(m_hWritePipe) )
387 	{
388 		CloseHandle( m_hWritePipe );
389 		m_hWritePipe = INVALID_HANDLE_VALUE;
390 	}
391 
392 	return fSuccess;
393 }
394 
395 //----------------------------------------------------------------------------
396 //	Pipe Write
397 //----------------------------------------------------------------------------
398 
399 bool Pipe::Write( LPCVOID lpBuffer, DWORD dwBytesToWrite, LPDWORD lpBytesWritten, bool bWait )
400 {
401 	DWORD	dwBytesAvailable = 0;
402 	BOOL	fSuccess = TRUE;
403 
404 	if ( !bWait )
405 		fSuccess = PeekNamedPipe( m_hReadPipe, NULL, 0, NULL, &dwBytesAvailable, NULL );
406 
407 	if ( fSuccess )
408 	{
409 		if ( !bWait && dwBytesToWrite > PIPE_BUFFER_SIZE - dwBytesAvailable )
410 			dwBytesToWrite = PIPE_BUFFER_SIZE - dwBytesAvailable ;
411 
412 		return !!WriteFile( m_hWritePipe, lpBuffer, dwBytesToWrite, lpBytesWritten, NULL );
413 	}
414 
415 	return false;
416 }
417 
418 //----------------------------------------------------------------------------
419 //	Pipe Read
420 //----------------------------------------------------------------------------
421 
422 bool Pipe::Read( LPVOID lpBuffer, DWORD dwBytesToRead, LPDWORD lpBytesRead, bool bWait )
423 {
424 	DWORD	dwBytesAvailable = 0;
425 	BOOL	fSuccess = TRUE;
426 
427 	if ( !bWait )
428 		fSuccess = PeekNamedPipe( m_hReadPipe, NULL, 0, NULL, &dwBytesAvailable, NULL );
429 
430 	if ( fSuccess )
431 	{
432 		if ( bWait || dwBytesAvailable )
433 			return !!ReadFile( m_hReadPipe, lpBuffer, dwBytesToRead, lpBytesRead, NULL );
434 		else
435 		{
436 			*lpBytesRead = 0;
437 			return true;
438 		}
439 	}
440 
441 	return false;
442 }
443 
444 
445 
446 //----------------------------------------------------------------------------
447 //	Client pipe dtor
448 //----------------------------------------------------------------------------
449 
450 ClientPipe::ClientPipe( HANDLE hReadPipe, HANDLE hWritePipe ) : Pipe( hReadPipe, hWritePipe )
451 {
452 }
453 
454 //----------------------------------------------------------------------------
455 //	Client pipe creation
456 //----------------------------------------------------------------------------
457 
458 ClientPipe *ClientPipe::Create( LPCTSTR lpName )
459 {
460 	ClientPipe	*pPipe = NULL;	// Assume failure
461 
462 	HANDLE	hMapping = OpenPipeDataMapping( lpName );
463 
464 	if ( IsValidHandle(hMapping) )
465 	{
466 		PipeData	*pData = (PipeData*)MapViewOfFile( hMapping, FILE_MAP_ALL_ACCESS, 0, 0, 0 );
467 
468 		if ( pData )
469 		{
470 			HANDLE	hSourceProcess = OpenProcess( PROCESS_DUP_HANDLE, FALSE, pData->dwProcessId );
471 
472 			if ( IsValidHandle(hSourceProcess) )
473 			{
474 				BOOL fSuccess;
475 				HANDLE	hReadPipe = INVALID_HANDLE_VALUE, hWritePipe = INVALID_HANDLE_VALUE;
476 
477 				fSuccess = DuplicateHandle(
478 					hSourceProcess,
479 					pData->hReadPipe,
480 					GetCurrentProcess(),
481 					&hReadPipe,
482 					0,
483 					FALSE,
484 					DUPLICATE_SAME_ACCESS );
485 
486 				fSuccess = fSuccess && DuplicateHandle(
487 					hSourceProcess,
488 					pData->hWritePipe,
489 					GetCurrentProcess(),
490 					&hWritePipe,
491 					0,
492 					FALSE,
493 					DUPLICATE_SAME_ACCESS );
494 
495 				if ( fSuccess )
496 					pPipe = new ClientPipe( hReadPipe, hWritePipe );
497 
498 				if ( IsValidHandle(hWritePipe) )
499 					CloseHandle( hWritePipe );
500 
501 				if ( IsValidHandle(hReadPipe) )
502 					CloseHandle( hReadPipe );
503 
504 				HANDLE	hConnectionRequest = CreatePipeConnectionSemaphore( lpName, 0, 1 );
505 
506 				ReleaseSemaphore( hConnectionRequest, 1, NULL );
507 
508 				CloseHandle( hConnectionRequest );
509 
510 				CloseHandle( hSourceProcess );
511 			}
512 
513 			UnmapViewOfFile( pData );
514 		}
515 
516 		CloseHandle( hMapping );
517 	}
518 
519 	return pPipe;
520 }
521 
522 
523 
524 //----------------------------------------------------------------------------
525 //	ServerPipe ctor
526 //----------------------------------------------------------------------------
527 
528 ServerPipe::ServerPipe( LPCTSTR	lpName, HANDLE hMapping, HANDLE hSynchronize, HANDLE hReadPipe, HANDLE hWritePipe ) : Pipe( hReadPipe, hWritePipe ),
529 m_hMapping( NULL ),
530 m_hSynchronize( NULL ),
531 m_lpName( NULL )
532 {
533 	DuplicateHandle(
534 		GetCurrentProcess(),
535 		hMapping,
536 		GetCurrentProcess(),
537 		&m_hMapping,
538 		0,
539 		FALSE,
540 		DUPLICATE_SAME_ACCESS );
541 
542 	DuplicateHandle(
543 		GetCurrentProcess(),
544 		hSynchronize,
545 		GetCurrentProcess(),
546 		&m_hSynchronize,
547 		0,
548 		FALSE,
549 		DUPLICATE_SAME_ACCESS
550 		);
551 	m_lpName = new TCHAR[_tcslen(lpName) + 1];
552 	if ( m_lpName )
553 		_tcscpy( m_lpName, lpName );
554 }
555 
556 //----------------------------------------------------------------------------
557 //	ServerPipe dtor
558 //----------------------------------------------------------------------------
559 
560 ServerPipe::~ServerPipe()
561 {
562 	if ( IsValidHandle(m_hMapping) )
563 		CloseHandle( m_hMapping );
564 	if ( m_lpName )
565 		delete[]m_lpName;
566 }
567 
568 //----------------------------------------------------------------------------
569 //	ServerPipe AcceptConnection
570 //----------------------------------------------------------------------------
571 
572 Pipe *ServerPipe::AcceptConnection()
573 {
574 	Pipe	*pPipe = NULL;	// Assume failure;
575 
576 	HANDLE	hConnectionRequest = CreatePipeConnectionSemaphore( m_lpName, 0, 1 );
577 
578 	if ( WAIT_OBJECT_0 == WaitForSingleObject( hConnectionRequest, INFINITE ) )
579 	{
580 		pPipe = new Pipe( *this );
581 		Close();
582 
583 		// Create new inbound Pipe
584 
585 		HANDLE	hClientWritePipe = NULL, hServerReadPipe = NULL;
586 
587 		BOOL	fSuccess = CreatePipe( &hServerReadPipe, &hClientWritePipe, NULL, PIPE_BUFFER_SIZE );
588 
589 
590 		if ( fSuccess )
591 		{
592 			// Create outbound pipe
593 
594 			HANDLE	hClientReadPipe = NULL, hServerWritePipe = NULL;
595 
596 			if ( CreatePipe( &hClientReadPipe, &hServerWritePipe, NULL, PIPE_BUFFER_SIZE ) )
597 			{
598 				m_hReadPipe = hServerReadPipe;
599 				m_hWritePipe = hServerWritePipe;
600 
601 				PipeData	*pData = (PipeData *)MapViewOfFile( m_hMapping, FILE_MAP_ALL_ACCESS, 0, 0, sizeof(PipeData) );
602 
603 				HANDLE	hSynchronize = CreatePipeDataMutex( m_lpName, TRUE );
604 
605 				CloseHandle( pData->hReadPipe );
606 				CloseHandle( pData->hWritePipe );
607 
608 				pData->hReadPipe = hClientReadPipe;
609 				pData->hWritePipe = hClientWritePipe;
610 
611 				ReleaseMutex( hSynchronize );
612 
613 				CloseHandle( hSynchronize );
614 
615 			}
616 			else
617 			{
618 				CloseHandle( hClientWritePipe );
619 				CloseHandle( hServerWritePipe );
620 			}
621 		}
622 
623 		ReleaseMutex( hConnectionRequest );
624 	}
625 
626 	CloseHandle( hConnectionRequest );
627 
628 	return pPipe;
629 }
630 
631 //----------------------------------------------------------------------------
632 //	Pipe creation
633 //----------------------------------------------------------------------------
634 
635 ServerPipe *ServerPipe::Create( LPCTSTR lpName )
636 {
637 	ServerPipe	*pPipe = NULL;
638 
639 	HANDLE	hMapping = CreatePipeDataMapping( lpName );
640 
641 	if ( IsValidHandle(hMapping) )
642 	{
643 		if ( ERROR_FILE_EXISTS != GetLastError() )
644 		{
645 			HANDLE	hSynchronize = CreatePipeDataMutex( lpName, FALSE);
646 
647 			WaitForSingleObject( hSynchronize, INFINITE );
648 
649 			PipeData	*pData = (PipeData*)MapViewOfFile( hMapping, FILE_MAP_ALL_ACCESS, 0, 0, 0 );
650 
651 			if ( pData )
652 			{
653 
654 				// Initialize pipe data
655 
656 				pData->dwProcessId = 0;
657 				pData->hReadPipe = NULL;
658 				pData->hWritePipe = NULL;
659 
660 				// Create inbound pipe
661 
662 				HANDLE	hServerReadPipe = NULL, hClientWritePipe = NULL;
663 
664 				BOOL	fSuccess = CreatePipe( &hServerReadPipe, &hClientWritePipe, NULL, PIPE_BUFFER_SIZE );
665 
666 				if ( fSuccess )
667 				{
668 					// Create outbound pipe
669 
670 					HANDLE	hServerWritePipe = NULL, hClientReadPipe = NULL;
671 
672 					fSuccess = CreatePipe( &hClientReadPipe, &hServerWritePipe, NULL, PIPE_BUFFER_SIZE );
673 
674 					if ( fSuccess )
675 					{
676 						pData->dwProcessId = GetCurrentProcessId();
677 						pData->hReadPipe = hClientReadPipe;
678 						pData->hWritePipe = hClientWritePipe;
679 						pPipe = new ServerPipe( lpName, hMapping, hSynchronize, hServerReadPipe, hServerWritePipe );
680 
681 						CloseHandle( hServerWritePipe );
682 						CloseHandle( hServerReadPipe );
683 					}
684 					else
685 					{
686 						CloseHandle( hServerReadPipe );
687 						CloseHandle( hClientWritePipe );
688 					}
689 				}
690 
691 				UnmapViewOfFile( pData );
692 			}
693 
694 			ReleaseMutex( hSynchronize );
695 			CloseHandle( hSynchronize );
696 		}
697 
698 		CloseHandle( hMapping );
699 	}
700 
701 	return pPipe;
702 }
703 
704 
705 //----------------------------------------------------------------------------
706 //	C style API
707 //----------------------------------------------------------------------------
708 
709 const TCHAR	LOCAL_PIPE_PREFIX[] = TEXT("\\\\.\\PIPE\\" );
710 
711 extern "C" HANDLE WINAPI CreateSimplePipe( LPCTSTR lpName )
712 {
713 	int	nPrefixLen = _tcslen( LOCAL_PIPE_PREFIX );
714 	if ( 0 == _tcsnicmp( lpName, LOCAL_PIPE_PREFIX, nPrefixLen ) )
715 		lpName += nPrefixLen;
716 	return (HANDLE)ServerPipe::Create( lpName );
717 }
718 
719 extern "C" HANDLE WINAPI OpenSimplePipe( LPCTSTR lpName )
720 {
721 	int	nPrefixLen = _tcslen( LOCAL_PIPE_PREFIX );
722 	if ( 0 == _tcsnicmp( lpName, LOCAL_PIPE_PREFIX, nPrefixLen ) )
723 		lpName += nPrefixLen;
724 	return (HANDLE)ClientPipe::Create( lpName );
725 }
726 
727 extern "C" HANDLE WINAPI AcceptSimplePipeConnection( HANDLE hPipe )
728 {
729 	Pipe	*pPipe = (Pipe *)hPipe;
730 
731 	if ( pPipe->is() )
732 		return (HANDLE)pPipe->AcceptConnection();
733 	else
734 	{
735 		SetLastError( ERROR_INVALID_HANDLE );
736 		return NULL;
737 	}
738 }
739 
740 extern "C" BOOL WINAPI WaitForSimplePipe( LPCTSTR /*lpName*/, DWORD /*dwTimeOut*/ )
741 {
742 	return FALSE;
743 }
744 
745 extern "C" BOOL WINAPI WriteSimplePipe( HANDLE hPipe, LPCVOID lpBuffer, DWORD dwBytesToWrite, LPDWORD lpBytesWritten, BOOL bWait )
746 {
747 	Pipe	*pPipe = (Pipe *)hPipe;
748 
749 	if ( pPipe->is() )
750 		return pPipe->Write( lpBuffer, dwBytesToWrite, lpBytesWritten, bWait );
751 	else
752 	{
753 		SetLastError( ERROR_INVALID_HANDLE );
754 		return FALSE;
755 	}
756 }
757 
758 extern "C" BOOL WINAPI ReadSimplePipe( HANDLE hPipe, LPVOID lpBuffer, DWORD dwBytesToRead, LPDWORD lpBytesRead, BOOL bWait )
759 {
760 	Pipe	*pPipe = (Pipe *)hPipe;
761 
762 	if ( pPipe->is() )
763 		return pPipe->Read( lpBuffer, dwBytesToRead, lpBytesRead, bWait );
764 	else
765 	{
766 		SetLastError( ERROR_INVALID_HANDLE );
767 		return FALSE;
768 	}
769 }
770 
771 extern "C" BOOL WINAPI CloseSimplePipe( HANDLE hPipe )
772 {
773 	Pipe	*pPipe = (Pipe *)hPipe;
774 
775 	if ( pPipe->is() )
776 	{
777 		delete pPipe;
778 		return TRUE;
779 	}
780 	else
781 	{
782 		SetLastError( ERROR_INVALID_HANDLE );
783 		return FALSE;
784 	}
785 }
786