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 //#define INCL_DOSERRORS 29 #include "system.h" 30 31 #include <osl/pipe.h> 32 #include <osl/diagnose.h> 33 #include <osl/thread.h> 34 #include <osl/mutex.h> 35 #include <osl/semaphor.h> 36 #include <osl/conditn.h> 37 #include <osl/interlck.h> 38 #include <osl/process.h> 39 #include <rtl/ustring.hxx> 40 41 #define PIPENAMEMASK "OSL_PIPE_%s" 42 #define SECPIPENAMEMASK "OSL_PIPE_%s_%s" 43 44 typedef enum { 45 MSG_SYN, 46 MSG_FIN, 47 MSG_DATA, 48 MSG_UNKNOWN 49 } MessageType; 50 51 struct oslPipeImpl { 52 oslInterlockedCount m_Reference; 53 HPIPE hPipe; 54 HMTX m_NamedObject; 55 APIRET nLastError; 56 //oslSecurity m_Security; 57 sal_Bool m_bClosed; 58 }; 59 60 /* default size for input/output buffer */ 61 static const ULONG ulBufSize = 4096; 62 63 /* OS/2 path for pipes */ 64 static const CHAR pszPipePath[] = "\\PIPE\\"; 65 static const UCHAR nPipePathLen = sizeof (pszPipePath) - 1; 66 67 /* global last error value to be returned from oslGetLastPipeError */ 68 static APIRET ngLastError; 69 70 using rtl::OString; 71 using rtl::OUString; 72 using rtl::OUStringToOString; 73 74 /*****************************************************************************/ 75 /* osl_create/destroy-PipeImpl */ 76 /*****************************************************************************/ 77 78 static oslInterlockedCount nPipes = 0; 79 80 oslPipe __osl_createPipeImpl(void) 81 { 82 oslPipe pPipe; 83 84 pPipe = (oslPipe) calloc(1,sizeof(struct oslPipeImpl)); 85 86 pPipe->m_bClosed = sal_False; 87 pPipe->m_Reference = 1; 88 pPipe->hPipe = NULL; 89 pPipe->m_NamedObject = NULL; 90 91 return pPipe; 92 } 93 94 void __osl_destroyPipeImpl(oslPipe pPipe) 95 { 96 if (pPipe != NULL) 97 { 98 DosCloseMutexSem( pPipe->m_NamedObject); 99 free(pPipe); 100 } 101 } 102 103 104 /*****************************************************************************/ 105 /* osl_createPipe */ 106 /*****************************************************************************/ 107 oslPipe SAL_CALL osl_createPipe(rtl_uString *ustrPipeName, oslPipeOptions Options, 108 oslSecurity Security) 109 { 110 oslPipe pPipe; 111 112 ULONG ulAction; 113 CHAR strPipeNameBuffer [CCHMAXPATHCOMP]; 114 rtl_String* strPipeName=0; 115 sal_Char* pszPipeName=0; 116 117 /* check parameters */ 118 OSL_ASSERT( ustrPipeName ); 119 //YD 17/04/06 OSL_ASSERT( Security == 0 ); 120 121 /* allocate impl-structure */ 122 pPipe = __osl_createPipeImpl(); 123 if (!pPipe) 124 { 125 OSL_TRACE( "osl_createPipe failed allocating memory.\n" ); 126 return NULL; 127 } 128 129 /* create pipe name */ 130 OString sPipe = OUStringToOString(ustrPipeName, RTL_TEXTENCODING_ASCII_US); 131 #if OSL_DEBUG_LEVEL>0 132 debug_printf("osl_createPipe options 0x%x\n", Options); 133 #endif 134 135 switch( Options ) 136 { 137 case osl_Pipe_OPEN: 138 { 139 APIRET fPipeAvailable; 140 141 sprintf (strPipeNameBuffer, "\\PIPE\\OSL_PIPE_%s", sPipe.getStr()); 142 #if OSL_DEBUG_LEVEL>0 143 debug_printf("osl_createPipe %s\n", strPipeNameBuffer); 144 #endif 145 ngLastError = DosOpen( (PCSZ)strPipeNameBuffer, 146 &(pPipe->hPipe), &ulAction, 147 0, FILE_NORMAL, FILE_OPEN, 148 OPEN_ACCESS_READWRITE | OPEN_SHARE_DENYREADWRITE, 149 (PEAOP2) NULL); 150 // if pipe is busy, wait for it 151 if (ngLastError == ERROR_PIPE_BUSY) 152 do 153 { 154 /* free instance should be available first */ 155 fPipeAvailable = DosWaitNPipe( (PCSZ)strPipeNameBuffer, -1); 156 /* first try to open system pipe */ 157 if ( fPipeAvailable == NO_ERROR ) 158 { 159 // We got it ! 160 ngLastError = NO_ERROR; 161 break; 162 } 163 // Pipe instance maybe catched by another client -> try again 164 printf("osl_createPipe wait for Pipe available\n"); 165 } while ( fPipeAvailable ); 166 } 167 break; 168 case osl_Pipe_CREATE: 169 { 170 sprintf (strPipeNameBuffer, "\\SEM32\\OSL_SEM_%s", sPipe.getStr()); 171 // check if semaphore exists (pipe create must fail for existig pipes) 172 ngLastError = DosCreateMutexSem( (PCSZ)strPipeNameBuffer, &(pPipe->m_NamedObject), 0, TRUE ); 173 if (ngLastError) 174 break; 175 176 sprintf (strPipeNameBuffer, "\\PIPE\\OSL_PIPE_%s", sPipe.getStr()); 177 #if OSL_DEBUG_LEVEL>0 178 debug_printf("osl_createPipe %s\n", strPipeNameBuffer); 179 #endif 180 ngLastError = DosCreateNPipe( (PCSZ)strPipeNameBuffer, 181 &(pPipe->hPipe), 182 NP_ACCESS_DUPLEX, /* open pipe for read and write access */ 183 0xFF, /* allow unlimited number of instances */ 184 ulBufSize, /* output buffer size */ 185 ulBufSize, /* input buffer size */ 186 0L /* use default time-out time */ 187 ); 188 } 189 break; 190 default: 191 ngLastError = ERROR_INVALID_PARAMETER; 192 } 193 194 /* if failed, release allocated memory */ 195 if (ngLastError) 196 { 197 OSL_TRACE( "osl_createPipe failed %s the pipe %s, Error Code %d.\n", 198 Options == osl_Pipe_OPEN ? "opening" : "creating", 199 strPipeNameBuffer, 200 ngLastError ); 201 __osl_destroyPipeImpl(pPipe); 202 return NULL; 203 } 204 205 pPipe->m_Reference= 1; 206 pPipe->m_bClosed = sal_False; 207 //pPipe->m_Security = Security; 208 pPipe->nLastError = NO_ERROR; 209 return (oslPipe)pPipe; 210 } 211 212 /*****************************************************************************/ 213 /* osl_copyPipe */ 214 /*****************************************************************************/ 215 oslPipe SAL_CALL osl_copyPipe(oslPipe pPipe) 216 { 217 //oslPipe* pPipe = (oslPipe*) Pipe; 218 oslPipe pNewPipe; 219 220 221 /* check parameter */ 222 OSL_ASSERT (pPipe); 223 224 /* allocate impl-structure */ 225 pNewPipe = __osl_createPipeImpl(); 226 if (!pNewPipe) return NULL; 227 228 /* create new handle */ 229 pNewPipe->hPipe = (HPIPE) -1; 230 ngLastError = DosDupHandle( pPipe->hPipe, &(pNewPipe->hPipe) ); 231 232 /* if failed, release allocated memory */ 233 if (ngLastError) 234 { 235 OSL_TRACE( "osl_copyPipe failed duplicating pipe handle, Error-Code: %d.\n", 236 ngLastError ); 237 free (pNewPipe); 238 return NULL; 239 } 240 241 pNewPipe->nLastError = NO_ERROR; 242 return (oslPipe)pNewPipe; 243 } 244 245 void SAL_CALL osl_acquirePipe( oslPipe pPipe ) 246 { 247 osl_incrementInterlockedCount( &(pPipe->m_Reference) ); 248 } 249 250 void SAL_CALL osl_releasePipe( oslPipe pPipe ) 251 { 252 // OSL_ASSERT( pPipe ); 253 254 if( 0 == pPipe ) 255 return; 256 257 if( 0 == osl_decrementInterlockedCount( &(pPipe->m_Reference) ) ) 258 { 259 if( ! pPipe->m_bClosed ) 260 osl_closePipe( pPipe ); 261 262 __osl_destroyPipeImpl( pPipe ); 263 } 264 } 265 266 /*****************************************************************************/ 267 /* osl_destroyPipe */ 268 /*************close****************************************************************/ 269 void SAL_CALL osl_closePipe(oslPipe pPipe) 270 { 271 //oslPipe* pPipe = (oslPipe*) Pipe; 272 /* check parameter */ 273 OSL_ASSERT (pPipe); 274 275 if( pPipe && ! pPipe->m_bClosed ) 276 { 277 pPipe->m_bClosed = sal_True; 278 /* if we have a system pipe close it */ 279 if (pPipe->hPipe != 0) 280 { 281 /* disconnect client */ 282 DosDisConnectNPipe (pPipe->hPipe); 283 284 /* close the pipe */ 285 DosClose (pPipe->hPipe); 286 } 287 } 288 } 289 290 /*****************************************************************************/ 291 /* osl_acceptPipe */ 292 /*****************************************************************************/ 293 oslPipe SAL_CALL osl_acceptPipe(oslPipe pPipe) 294 { 295 296 #define PINFO ((PIPEINFO *) &PipeInfoBuffer) 297 298 ///oslPipe* pPipe = (oslPipe*) Pipe; 299 oslPipe pNewPipe; 300 BYTE PipeInfoBuffer[sizeof(PIPEINFO) + CCHMAXPATHCOMP]; 301 302 /* check parameter */ 303 OSL_ASSERT (pPipe); 304 305 /* get pipe information */ 306 pPipe->nLastError = DosQueryNPipeInfo(pPipe->hPipe, 307 1, 308 (PVOID) &PipeInfoBuffer, 309 sizeof(PipeInfoBuffer)); 310 311 if (pPipe->nLastError) 312 { 313 OSL_TRACE( "osl_acceptPipe failed for requesting pipe information.\n", 314 pPipe->nLastError ); 315 return NULL; 316 } 317 318 /* create a new instance of the pipe if possible */ 319 if (PINFO->cbMaxInst == -1 || /* unlimited instances */ 320 PINFO->cbMaxInst > PINFO->cbCurInst) 321 { 322 HPIPE hPipe; 323 324 pNewPipe = __osl_createPipeImpl(); 325 326 if (!pNewPipe) 327 { 328 OSL_TRACE( "osl_acceptPipe failed creating new instance.\n", ngLastError ); 329 free(pNewPipe); 330 return NULL; 331 } 332 333 //pNewPipe->m_Security = pPipe->m_Security; 334 335 pNewPipe->nLastError = 336 DosCreateNPipe( (PCSZ)PINFO->szName, 337 &(pNewPipe->hPipe), 338 NP_ACCESS_DUPLEX, /* open pipe for read and write access */ 339 0xFF, /* allow unlimited number of instances */ 340 ulBufSize, /* output buffer size */ 341 ulBufSize, /* input buffer size */ 342 0L /* use default time-out time */ 343 ); 344 345 if (pNewPipe->nLastError) 346 { 347 OSL_TRACE( "osl_acceptPipe failed creating new named pipe, Error-Code: %d.\n", 348 pNewPipe->nLastError ); 349 free(pNewPipe); 350 return NULL; 351 } 352 353 /* switch pipe handles */ 354 hPipe = pPipe->hPipe; 355 pPipe->hPipe = pNewPipe->hPipe; 356 pNewPipe->hPipe = hPipe; 357 358 /* connect new handle to client */ 359 pNewPipe->nLastError = DosConnectNPipe( pNewPipe->hPipe ); 360 361 /* if failed, release allocated memory */ 362 if (pNewPipe->nLastError) 363 { 364 OSL_TRACE( "osl_acceptPipe failed connecting pipe to client, Error-Code: %d.\n", 365 pNewPipe->nLastError ); 366 367 osl_closePipe((oslPipe)pNewPipe); 368 return NULL; 369 } 370 return (oslPipe)pNewPipe; 371 } 372 else 373 { 374 /* connect original handle to client */ 375 pPipe->nLastError = DosConnectNPipe( pPipe->hPipe ); 376 377 if (pPipe->nLastError) 378 { 379 OSL_TRACE( "osl_acceptPipe failed connecting pipe to client, Error-Code: %d.\n", 380 pPipe->nLastError ); 381 return NULL; 382 } 383 384 return (oslPipe)pPipe; 385 } 386 } 387 388 /*****************************************************************************/ 389 /* osl_receivePipe */ 390 /*****************************************************************************/ 391 sal_Int32 SAL_CALL osl_receivePipe(oslPipe pPipe, 392 void* pBuffer, 393 sal_Int32 BytesToRead) 394 { 395 //oslPipe* pPipe = (oslPipe*) Pipe; 396 ULONG ulActual; 397 398 /* check parameter */ 399 OSL_ASSERT (pPipe); 400 401 /* read data from pipe */ 402 pPipe->nLastError = DosRead( pPipe->hPipe, pBuffer, BytesToRead, &ulActual ); 403 404 /* return -1 if failed */ 405 if( pPipe->nLastError ) 406 { 407 OSL_TRACE( "osl_receivePipe failed receiving from Pipe, Error-Code: %d.\n", 408 pPipe->nLastError ); 409 return -1; 410 } 411 412 return ulActual; 413 } 414 415 416 /*****************************************************************************/ 417 /* osl_sendPipe */ 418 /*****************************************************************************/ 419 sal_Int32 SAL_CALL osl_sendPipe(oslPipe pPipe, 420 const void* pBuffer, 421 sal_Int32 BytesToSend) 422 { 423 //oslPipe* pPipe = (oslPipe*) Pipe; 424 ULONG ulActual; 425 426 /* check parameter */ 427 OSL_ASSERT (pPipe); 428 429 /* read data from pipe */ 430 pPipe->nLastError = DosWrite( pPipe->hPipe, (PVOID) pBuffer, BytesToSend, &ulActual ); 431 432 /* return -1 if failed */ 433 if( pPipe->nLastError ) 434 { 435 OSL_TRACE( "osl_receivePipe failed writing to Pipe, Error-Code: %d.\n", 436 pPipe->nLastError ); 437 return -1; 438 } 439 440 return ulActual; 441 } 442 443 444 /*****************************************************************************/ 445 /* osl_getLastPipeError */ 446 /*****************************************************************************/ 447 448 oslPipeError SAL_CALL osl_getLastPipeError(oslPipe pPipe) 449 { 450 //oslPipe* pPipe = (oslPipe*) Pipe; 451 APIRET rc; 452 453 /* return local error value if possible */ 454 if (pPipe) 455 { 456 rc = pPipe->nLastError; 457 pPipe->nLastError = NO_ERROR; 458 } else 459 rc = ngLastError; 460 461 /* map OS/2 error values */ 462 switch (rc) 463 { 464 case NO_ERROR: return osl_Pipe_E_None; 465 case ERROR_PATH_NOT_FOUND: return osl_Pipe_E_NotFound; 466 case ERROR_NOT_ENOUGH_MEMORY: return osl_Pipe_E_NoBufferSpace; 467 default: return osl_Pipe_E_invalidError; 468 } 469 } 470 471 /*****************************************************************************/ 472 473 sal_Int32 SAL_CALL osl_writePipe( oslPipe pPipe, const void *pBuffer , sal_Int32 n ) 474 { 475 /* loop until all desired bytes were send or an error occured */ 476 sal_Int32 BytesSend= 0; 477 sal_Int32 BytesToSend= n; 478 479 OSL_ASSERT(pPipe); 480 while (BytesToSend > 0) 481 { 482 sal_Int32 RetVal; 483 484 RetVal= osl_sendPipe(pPipe, pBuffer, BytesToSend); 485 486 /* error occured? */ 487 if(RetVal <= 0) 488 { 489 break; 490 } 491 492 BytesToSend -= RetVal; 493 BytesSend += RetVal; 494 pBuffer= (sal_Char*)pBuffer + RetVal; 495 } 496 497 return BytesSend; 498 } 499 500 sal_Int32 SAL_CALL osl_readPipe( oslPipe pPipe, void *pBuffer , sal_Int32 n ) 501 { 502 /* loop until all desired bytes were read or an error occured */ 503 sal_Int32 BytesRead= 0; 504 sal_Int32 BytesToRead= n; 505 506 OSL_ASSERT( pPipe ); 507 while (BytesToRead > 0) 508 { 509 sal_Int32 RetVal; 510 RetVal= osl_receivePipe(pPipe, pBuffer, BytesToRead); 511 512 /* error occured? */ 513 if(RetVal <= 0) 514 { 515 break; 516 } 517 518 BytesToRead -= RetVal; 519 BytesRead += RetVal; 520 pBuffer= (sal_Char*)pBuffer + RetVal; 521 } 522 return BytesRead; 523 } 524 525 526 /****************************************************************************** 527 * 528 * New io resource transfer functions 529 * 530 *****************************************************************************/ 531 532 533 /********************************************** 534 osl_sendResourcePipe 535 *********************************************/ 536 537 sal_Bool osl_sendResourcePipe(oslPipe pPipe, oslSocket pSocket) 538 { 539 sal_Bool bRet = sal_False; 540 541 return bRet; 542 } 543 544 /********************************************** 545 osl_receiveResourcePipe 546 *********************************************/ 547 548 oslSocket osl_receiveResourcePipe(oslPipe pPipe) 549 { 550 oslSocket pSocket=0; 551 552 return (oslSocket) pSocket; 553 } 554 555 556