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