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