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 #define UNICODE 25 #include "system.h" 26 #ifdef _MSC_VER 27 #pragma warning(push,1) /* disable warnings within system headers */ 28 #endif 29 #include <shellapi.h> 30 #ifdef _MSC_VER 31 #pragma warning(pop) 32 #endif 33 34 #include <osl/diagnose.h> 35 #include <osl/security.h> 36 #include <osl/nlsupport.h> 37 #include <osl/mutex.h> 38 #include <osl/thread.h> 39 40 #include "procimpl.h" 41 #include "sockimpl.h" 42 #include "file_url.h" 43 #include "path_helper.hxx" 44 #include <rtl/ustrbuf.h> 45 #include <rtl/alloc.h> 46 47 /*************************************************************************** 48 * Process. 49 ***************************************************************************/ 50 51 oslProcessError SAL_CALL osl_terminateProcess(oslProcess Process) 52 { 53 if (Process == NULL) 54 return osl_Process_E_Unknown; 55 56 if (TerminateProcess(((oslProcessImpl*)Process)->m_hProcess, 0)) 57 return osl_Process_E_None; 58 59 60 return osl_Process_E_Unknown; 61 } 62 63 /***************************************************************************/ 64 65 oslProcess SAL_CALL osl_getProcess(oslProcessIdentifier Ident) 66 { 67 oslProcessImpl* pProcImpl; 68 HANDLE hProcess = OpenProcess( 69 STANDARD_RIGHTS_REQUIRED | PROCESS_QUERY_INFORMATION | SYNCHRONIZE, FALSE, (DWORD)Ident); 70 71 if (hProcess) 72 { 73 pProcImpl = reinterpret_cast< oslProcessImpl*>( rtl_allocateMemory(sizeof(oslProcessImpl)) ); 74 pProcImpl->m_hProcess = hProcess; 75 pProcImpl->m_IdProcess = Ident; 76 } 77 else 78 pProcImpl = NULL; 79 80 return (pProcImpl); 81 } 82 83 /***************************************************************************/ 84 85 void SAL_CALL osl_freeProcessHandle(oslProcess Process) 86 { 87 if (Process != NULL) 88 { 89 CloseHandle(((oslProcessImpl*)Process)->m_hProcess); 90 91 rtl_freeMemory((oslProcessImpl*)Process); 92 } 93 } 94 95 /***************************************************************************/ 96 97 oslProcessError SAL_CALL osl_getProcessInfo(oslProcess Process, oslProcessData Fields, 98 oslProcessInfo* pInfo) 99 { 100 HANDLE hProcess; 101 DWORD IdProcess; 102 103 if (Process == NULL) 104 { 105 hProcess = GetCurrentProcess(); 106 IdProcess = GetCurrentProcessId(); 107 } 108 else 109 { 110 hProcess = ((oslProcessImpl*)Process)->m_hProcess; 111 IdProcess = ((oslProcessImpl*)Process)->m_IdProcess; 112 } 113 114 if (! pInfo || (pInfo->Size != sizeof(oslProcessInfo))) 115 return osl_Process_E_Unknown; 116 117 pInfo->Fields = 0; 118 119 if (Fields & osl_Process_IDENTIFIER) 120 { 121 pInfo->Ident = IdProcess; 122 pInfo->Fields |= osl_Process_IDENTIFIER; 123 } 124 125 if (Fields & osl_Process_EXITCODE) 126 { 127 if (GetExitCodeProcess(hProcess, &(pInfo->Code)) && (pInfo->Code != STILL_ACTIVE)) 128 pInfo->Fields |= osl_Process_EXITCODE; 129 } 130 131 if (Fields & osl_Process_HEAPUSAGE) 132 { 133 void* lpAddress=0; 134 MEMORY_BASIC_INFORMATION Info; 135 136 pInfo->HeapUsage = 0; 137 138 do 139 { 140 if (VirtualQueryEx(hProcess, lpAddress, &Info, sizeof(Info)) == 0) 141 break; 142 143 if ((Info.State == MEM_COMMIT) && (Info.Type == MEM_PRIVATE)) 144 pInfo->HeapUsage += Info.RegionSize; 145 146 lpAddress = (LPBYTE)lpAddress + Info.RegionSize; 147 } 148 while (lpAddress < (void *)0x80000000); // 2GB address space 149 150 pInfo->Fields |= osl_Process_HEAPUSAGE; 151 } 152 153 if (Fields & osl_Process_CPUTIMES) 154 { 155 FILETIME CreationTime, ExitTime, KernelTime, UserTime; 156 157 if (GetProcessTimes(hProcess, &CreationTime, &ExitTime, 158 &KernelTime, &UserTime)) 159 { 160 __int64 Value; 161 162 Value = *((__int64 *)&UserTime); 163 pInfo->UserTime.Seconds = (unsigned long) (Value / 10000000L); 164 pInfo->UserTime.Nanosec = (unsigned long)((Value % 10000000L) * 100); 165 166 Value = *((__int64 *)&KernelTime); 167 pInfo->SystemTime.Seconds = (unsigned long) (Value / 10000000L); 168 pInfo->SystemTime.Nanosec = (unsigned long)((Value % 10000000L) * 100); 169 170 pInfo->Fields |= osl_Process_CPUTIMES; 171 } 172 } 173 174 return (pInfo->Fields == Fields) ? osl_Process_E_None : osl_Process_E_Unknown; 175 } 176 177 /***************************************************************************/ 178 179 oslProcessError SAL_CALL osl_joinProcess(oslProcess Process) 180 { 181 return osl_joinProcessWithTimeout(Process, NULL); 182 } 183 184 /***************************************************************************/ 185 186 oslProcessError SAL_CALL osl_joinProcessWithTimeout(oslProcess Process, const TimeValue* pTimeout) 187 { 188 DWORD timeout = INFINITE; 189 oslProcessError osl_error = osl_Process_E_None; 190 DWORD ret; 191 192 if (NULL == Process) 193 return osl_Process_E_Unknown; 194 195 if (pTimeout) 196 timeout = pTimeout->Seconds * 1000 + pTimeout->Nanosec / 1000000L; 197 198 ret = WaitForSingleObject(((oslProcessImpl*)Process)->m_hProcess, timeout); 199 200 if (WAIT_FAILED == ret) 201 osl_error = osl_Process_E_Unknown; 202 else if (WAIT_TIMEOUT == ret) 203 osl_error = osl_Process_E_TimedOut; 204 205 return osl_error; 206 } 207 208 /*************************************************************************** 209 * osl_bootstrap_getExecutableFile_Impl(). 210 * 211 * @internal 212 * @see rtl_bootstrap 213 * @see #i37371# 214 * 215 ***************************************************************************/ 216 217 extern "C" oslProcessError SAL_CALL osl_bootstrap_getExecutableFile_Impl ( 218 rtl_uString ** ppFileURL 219 ) SAL_THROW_EXTERN_C() 220 { 221 oslProcessError result = osl_Process_E_NotFound; 222 223 ::osl::LongPathBuffer< sal_Unicode > aBuffer( MAX_LONG_PATH ); 224 DWORD buflen = 0; 225 226 if ((buflen = GetModuleFileNameW (0, ::osl::mingw_reinterpret_cast<LPWSTR>(aBuffer), aBuffer.getBufSizeInSymbols())) > 0) 227 { 228 rtl_uString * pAbsPath = 0; 229 rtl_uString_newFromStr_WithLength (&(pAbsPath), aBuffer, buflen); 230 if (pAbsPath) 231 { 232 /* Convert from path to url. */ 233 if (osl_getFileURLFromSystemPath (pAbsPath, ppFileURL) == osl_File_E_None) 234 { 235 /* Success. */ 236 result = osl_Process_E_None; 237 } 238 rtl_uString_release (pAbsPath); 239 } 240 } 241 242 return (result); 243 } 244 245 /*************************************************************************** 246 * Command Line Arguments. 247 ***************************************************************************/ 248 249 struct CommandArgs_Impl 250 { 251 sal_uInt32 m_nCount; 252 rtl_uString ** m_ppArgs; 253 }; 254 255 static struct CommandArgs_Impl g_command_args = 256 { 257 0, 258 0 259 }; 260 261 #ifdef _MSC_VER 262 #pragma warning( push ) 263 #pragma warning( disable: 4100 ) 264 #endif 265 static rtl_uString ** osl_createCommandArgs_Impl (int argc, char ** argv) 266 { 267 rtl_uString ** ppArgs = 268 (rtl_uString**)rtl_allocateZeroMemory (argc * sizeof(rtl_uString*)); 269 if (ppArgs != 0) 270 { 271 int i; 272 int nArgs; 273 LPWSTR *wargv = CommandLineToArgvW( GetCommandLineW(), &nArgs ); 274 OSL_ASSERT( nArgs == argc ); 275 for (i = 0; i < nArgs; i++) 276 { 277 /* Convert to unicode */ 278 rtl_uString_newFromStr( &(ppArgs[i]), reinterpret_cast<const sal_Unicode*>(wargv[i]) ); 279 } 280 if (ppArgs[0] != 0) 281 { 282 /* Ensure absolute path */ 283 ::osl::LongPathBuffer< sal_Unicode > aBuffer( MAX_LONG_PATH ); 284 DWORD dwResult = 0; 285 286 dwResult = SearchPath ( 287 0, reinterpret_cast<LPCWSTR>(ppArgs[0]->buffer), L".exe", aBuffer.getBufSizeInSymbols(), ::osl::mingw_reinterpret_cast<LPWSTR>(aBuffer), 0); 288 if ((0 < dwResult) && (dwResult < aBuffer.getBufSizeInSymbols())) 289 { 290 /* Replace argv[0] with it's absolute path */ 291 rtl_uString_newFromStr_WithLength( 292 &(ppArgs[0]), aBuffer, dwResult); 293 } 294 } 295 if (ppArgs[0] != 0) 296 { 297 /* Convert to FileURL, see @ osl_getExecutableFile() */ 298 rtl_uString * pResult = 0; 299 osl_getFileURLFromSystemPath (ppArgs[0], &pResult); 300 if (pResult != 0) 301 { 302 rtl_uString_assign (&(ppArgs[0]), pResult); 303 rtl_uString_release (pResult); 304 } 305 } 306 } 307 return (ppArgs); 308 309 } 310 #ifdef _MSC_VER 311 #pragma warning( pop ) 312 #endif 313 314 /***************************************************************************/ 315 316 oslProcessError SAL_CALL osl_getExecutableFile( rtl_uString **ppustrFile ) 317 { 318 oslProcessError result = osl_Process_E_NotFound; 319 320 osl_acquireMutex (*osl_getGlobalMutex()); 321 OSL_ASSERT(g_command_args.m_nCount > 0); 322 if (g_command_args.m_nCount > 0) 323 { 324 /* CommandArgs set. Obtain arv[0]. */ 325 rtl_uString_assign (ppustrFile, g_command_args.m_ppArgs[0]); 326 result = osl_Process_E_None; 327 } 328 osl_releaseMutex (*osl_getGlobalMutex()); 329 330 return (result); 331 } 332 333 /***************************************************************************/ 334 335 sal_uInt32 SAL_CALL osl_getCommandArgCount(void) 336 { 337 sal_uInt32 result = 0; 338 339 osl_acquireMutex (*osl_getGlobalMutex()); 340 OSL_ASSERT(g_command_args.m_nCount > 0); 341 if (g_command_args.m_nCount > 0) 342 { 343 /* We're not counting argv[0] here. */ 344 result = g_command_args.m_nCount - 1; 345 } 346 osl_releaseMutex (*osl_getGlobalMutex()); 347 348 return (result); 349 } 350 351 /***************************************************************************/ 352 353 oslProcessError SAL_CALL osl_getCommandArg( sal_uInt32 nArg, rtl_uString **strCommandArg) 354 { 355 oslProcessError result = osl_Process_E_NotFound; 356 357 osl_acquireMutex (*osl_getGlobalMutex()); 358 OSL_ASSERT(g_command_args.m_nCount > 0); 359 if (g_command_args.m_nCount > (nArg + 1)) 360 { 361 /* We're not counting argv[0] here. */ 362 rtl_uString_assign (strCommandArg, g_command_args.m_ppArgs[nArg + 1]); 363 result = osl_Process_E_None; 364 } 365 osl_releaseMutex (*osl_getGlobalMutex()); 366 367 return (result); 368 } 369 370 /***************************************************************************/ 371 372 void SAL_CALL osl_setCommandArgs (int argc, char ** argv) 373 { 374 OSL_ASSERT(argc > 0); 375 osl_acquireMutex (*osl_getGlobalMutex()); 376 if (g_command_args.m_nCount == 0) 377 { 378 rtl_uString** ppArgs = osl_createCommandArgs_Impl (argc, argv); 379 if (ppArgs != 0) 380 { 381 g_command_args.m_nCount = argc; 382 g_command_args.m_ppArgs = ppArgs; 383 } 384 } 385 osl_releaseMutex (*osl_getGlobalMutex()); 386 } 387 388 /*************************************************************************** 389 * Environment 390 ***************************************************************************/ 391 #define ENV_BUFFER_SIZE (32*1024-1) 392 393 oslProcessError SAL_CALL osl_getEnvironment(rtl_uString *ustrVar, rtl_uString **ustrValue) 394 { 395 WCHAR buff[ENV_BUFFER_SIZE]; 396 397 if (GetEnvironmentVariableW(reinterpret_cast<LPCWSTR>(ustrVar->buffer), buff, ENV_BUFFER_SIZE) > 0) 398 { 399 rtl_uString_newFromStr(ustrValue, reinterpret_cast<const sal_Unicode*>(buff)); 400 return osl_Process_E_None; 401 } 402 return osl_Process_E_Unknown; 403 } 404 405 oslProcessError SAL_CALL osl_setEnvironment(rtl_uString *ustrVar, rtl_uString *ustrValue) 406 { 407 LPCWSTR lpName = reinterpret_cast<LPCWSTR>(ustrVar->buffer); 408 LPCWSTR lpValue = reinterpret_cast<LPCWSTR>(ustrValue->buffer); 409 if (SetEnvironmentVariableW(lpName, lpValue)) 410 return osl_Process_E_None; 411 return osl_Process_E_Unknown; 412 } 413 414 oslProcessError SAL_CALL osl_clearEnvironment(rtl_uString *ustrVar) 415 { 416 //If the second parameter is NULL, the variable is deleted from the current 417 //process's environment. 418 LPCWSTR lpName = reinterpret_cast<LPCWSTR>(ustrVar->buffer); 419 if (SetEnvironmentVariableW(lpName, NULL)) 420 return osl_Process_E_None; 421 return osl_Process_E_Unknown; 422 } 423 424 /*************************************************************************** 425 * Current Working Directory. 426 ***************************************************************************/ 427 428 extern "C" oslMutex g_CurrentDirectoryMutex; 429 430 oslProcessError SAL_CALL osl_getProcessWorkingDir( rtl_uString **pustrWorkingDir ) 431 { 432 ::osl::LongPathBuffer< sal_Unicode > aBuffer( MAX_LONG_PATH ); 433 DWORD dwLen = 0; 434 435 436 osl_acquireMutex( g_CurrentDirectoryMutex ); 437 dwLen = GetCurrentDirectory( aBuffer.getBufSizeInSymbols(), ::osl::mingw_reinterpret_cast<LPWSTR>(aBuffer) ); 438 osl_releaseMutex( g_CurrentDirectoryMutex ); 439 440 if ( dwLen && dwLen < aBuffer.getBufSizeInSymbols() ) 441 { 442 oslFileError eError; 443 rtl_uString *ustrTemp = NULL;; 444 445 rtl_uString_newFromStr_WithLength( &ustrTemp, aBuffer, dwLen ); 446 eError = osl_getFileURLFromSystemPath( ustrTemp, pustrWorkingDir ); 447 448 rtl_uString_release( ustrTemp ); 449 450 if ( osl_File_E_None != eError ) 451 return osl_Process_E_Unknown; 452 else 453 return osl_Process_E_None; 454 } 455 else 456 return osl_Process_E_Unknown; 457 } 458 459 /*************************************************************************** 460 * Process Locale. 461 ***************************************************************************/ 462 463 extern "C" void _imp_getProcessLocale( rtl_Locale ** ppLocale ); 464 465 static rtl_Locale * g_theProcessLocale = NULL; 466 467 /***************************************************************************/ 468 469 oslProcessError SAL_CALL osl_getProcessLocale( rtl_Locale ** ppLocale ) 470 { 471 osl_acquireMutex( *osl_getGlobalMutex() ); 472 473 /* determine the users default locale */ 474 if( NULL == g_theProcessLocale ) 475 _imp_getProcessLocale( &g_theProcessLocale ); 476 477 /* or return the cached value */ 478 *ppLocale = g_theProcessLocale; 479 480 osl_releaseMutex( *osl_getGlobalMutex() ); 481 return osl_Process_E_None; 482 } 483 484 /***************************************************************************/ 485 486 oslProcessError SAL_CALL osl_setProcessLocale( rtl_Locale * pLocale ) 487 { 488 osl_acquireMutex( *osl_getGlobalMutex() ); 489 490 /* check if locale is supported */ 491 if( RTL_TEXTENCODING_DONTKNOW == osl_getTextEncodingFromLocale( pLocale ) ) 492 return osl_Process_E_Unknown; 493 494 /* just remember the locale here */ 495 g_theProcessLocale = pLocale; 496 497 osl_releaseMutex( *osl_getGlobalMutex() ); 498 return osl_Process_E_None; 499 } 500 501 /************************************************ 502 * Portal send/receive interface implementation 503 ************************************************/ 504 505 static sal_Bool ReadPipe(oslPipe hPipe, 506 void* pBuffer, 507 sal_Int32 BytesToRead, 508 sal_Int32* nBytes) 509 { 510 *nBytes = osl_receivePipe(hPipe, pBuffer, BytesToRead); 511 OSL_TRACE("tried to recieve %d, recieved %d.\n", 512 BytesToRead, *nBytes); 513 return (sal_Bool)((*nBytes >= 0) && (osl_getLastPipeError(hPipe) == osl_Pipe_E_None)); 514 } 515 516 static sal_Bool WritePipe(oslPipe hPipe, 517 void* pBuffer, 518 sal_Int32 BytesToSend, 519 sal_Int32* nBytes) 520 { 521 *nBytes = osl_sendPipe(hPipe, pBuffer, BytesToSend); 522 OSL_TRACE("tried to send %d, sent %d\n", 523 BytesToSend, *nBytes); 524 return (sal_Bool)((*nBytes == BytesToSend) && (osl_getLastPipeError(hPipe) == osl_Pipe_E_None)); 525 } 526 527 sal_Bool SAL_CALL osl_sendResourcePipe(oslPipe hPipe, oslSocket pSocket) 528 { 529 sal_Bool bRet = sal_False; 530 sal_Int32 bytes = 0; 531 532 /* duplicate handle on this other side -> 533 receive remote process 534 duplicate handle and send it */ 535 DWORD remoteProcessID = 0; 536 HANDLE fd = (HANDLE)pSocket->m_Socket; 537 oslDescriptorType code = osl_Process_TypeSocket; 538 539 OSL_TRACE("osl_sendResourcePipe: enter..."); 540 541 if (ReadPipe(hPipe, &remoteProcessID, sizeof(remoteProcessID), &bytes)) 542 { 543 HANDLE hRemoteProc = OpenProcess(PROCESS_DUP_HANDLE, 544 FALSE, 545 remoteProcessID); 546 547 if (hRemoteProc != (HANDLE)NULL) 548 { 549 HANDLE newFd; 550 551 if (DuplicateHandle(GetCurrentProcess(), 552 fd, 553 hRemoteProc, 554 &newFd, 555 0, FALSE, DUPLICATE_SAME_ACCESS)) 556 { 557 if ( 558 WritePipe(hPipe, &code, sizeof(code), &bytes) && 559 WritePipe(hPipe, &newFd, sizeof(fd), &bytes) 560 ) 561 bRet = sal_True; 562 } 563 564 CloseHandle(hRemoteProc); 565 } 566 } 567 568 if (bRet) 569 { 570 sal_Int32 commitCode; 571 OSL_TRACE("osl_sendResourcePipe: handle sent successfully, verify...\n"); 572 573 if ( 574 !ReadPipe(hPipe, &commitCode, sizeof(commitCode), &bytes) || 575 (commitCode <= 0) 576 ) 577 bRet = sal_False; 578 } 579 580 OSL_TRACE("osl_sendResourcePipe: exit... %d\n", bRet); 581 return(bRet); 582 } 583 584 585 oslSocket SAL_CALL osl_receiveResourcePipe(oslPipe hPipe) 586 { 587 sal_Bool bRet = sal_False; 588 sal_Int32 bytes = 0; 589 sal_Int32 commitCode; 590 oslSocket pSocket = NULL; 591 592 /* duplicate handle on the other side -> 593 send my process id receive duplicated handle */ 594 HANDLE fd = INVALID_HANDLE_VALUE; 595 DWORD myProcessID = GetCurrentProcessId(); 596 oslDescriptorType code = osl_Process_TypeNone; 597 598 OSL_TRACE("osl_receiveResourcePipe: enter...\n"); 599 600 if ( 601 WritePipe(hPipe, &myProcessID, sizeof(myProcessID), &bytes) && 602 ReadPipe(hPipe, &code, sizeof(code), &bytes) && 603 ReadPipe(hPipe, &fd, sizeof(fd), &bytes) 604 ) 605 { 606 if (code == osl_Process_TypeSocket) 607 { 608 pSocket = __osl_createSocketImpl((SOCKET)fd); 609 bRet = sal_True; 610 } 611 else 612 { 613 OSL_TRACE("osl_receiveResourcePipe: UKNOWN\n"); 614 bRet = sal_False; 615 } 616 } 617 618 if (bRet) 619 commitCode = 1; 620 else 621 commitCode = 0; 622 623 WritePipe(hPipe, &commitCode, sizeof(commitCode), &bytes); 624 625 OSL_TRACE("osl_receiveResourcePipe: exit... %d, %p\n", bRet, pSocket); 626 627 return pSocket; 628 } 629