xref: /trunk/main/sal/osl/w32/pipeimpl.cxx (revision 1ecadb572e7010ff3b3382ad9bf179dbc6efadbb)
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