Updated core
[LibreOffice.git] / sal / osl / w32 / process.cxx
blobb775c6204e6ad2c9ef806826a0c0e66378c58047
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #define UNICODE
21 #include "system.h"
22 #include <string.h>
23 #ifdef _MSC_VER
24 #pragma warning(push,1) /* disable warnings within system headers */
25 #endif
26 #include <shellapi.h>
27 #ifdef _MSC_VER
28 #pragma warning(pop)
29 #endif
31 #include <osl/diagnose.h>
32 #include <osl/security.h>
33 #include <osl/nlsupport.h>
34 #include <osl/mutex.h>
35 #include <osl/thread.h>
37 #include "procimpl.h"
38 #include "sockimpl.h"
39 #include "file_url.h"
40 #include "path_helper.hxx"
41 #include <rtl/ustrbuf.h>
42 #include <rtl/alloc.h>
44 /***************************************************************************
45 * Process.
46 ***************************************************************************/
48 oslProcessError SAL_CALL osl_terminateProcess(oslProcess Process)
50 if (Process == NULL)
51 return osl_Process_E_Unknown;
53 if (TerminateProcess(((oslProcessImpl*)Process)->m_hProcess, 0))
54 return osl_Process_E_None;
57 return osl_Process_E_Unknown;
60 /***************************************************************************/
62 oslProcess SAL_CALL osl_getProcess(oslProcessIdentifier Ident)
64 oslProcessImpl* pProcImpl;
65 HANDLE hProcess = OpenProcess(
66 STANDARD_RIGHTS_REQUIRED | PROCESS_QUERY_INFORMATION | SYNCHRONIZE, FALSE, (DWORD)Ident);
68 if (hProcess)
70 pProcImpl = reinterpret_cast< oslProcessImpl*>( rtl_allocateMemory(sizeof(oslProcessImpl)) );
71 pProcImpl->m_hProcess = hProcess;
72 pProcImpl->m_IdProcess = Ident;
74 else
75 pProcImpl = NULL;
77 return (pProcImpl);
80 /***************************************************************************/
82 void SAL_CALL osl_freeProcessHandle(oslProcess Process)
84 if (Process != NULL)
86 CloseHandle(((oslProcessImpl*)Process)->m_hProcess);
88 rtl_freeMemory((oslProcessImpl*)Process);
92 /***************************************************************************/
94 oslProcessError SAL_CALL osl_getProcessInfo(oslProcess Process, oslProcessData Fields,
95 oslProcessInfo* pInfo)
97 HANDLE hProcess;
98 DWORD IdProcess;
100 if (Process == NULL)
102 hProcess = GetCurrentProcess();
103 IdProcess = GetCurrentProcessId();
105 else
107 hProcess = ((oslProcessImpl*)Process)->m_hProcess;
108 IdProcess = ((oslProcessImpl*)Process)->m_IdProcess;
111 if (! pInfo || (pInfo->Size != sizeof(oslProcessInfo)))
112 return osl_Process_E_Unknown;
114 pInfo->Fields = 0;
116 if (Fields & osl_Process_IDENTIFIER)
118 pInfo->Ident = IdProcess;
119 pInfo->Fields |= osl_Process_IDENTIFIER;
122 if (Fields & osl_Process_EXITCODE)
124 if (GetExitCodeProcess(hProcess, &(pInfo->Code)) && (pInfo->Code != STILL_ACTIVE))
125 pInfo->Fields |= osl_Process_EXITCODE;
128 if (Fields & osl_Process_HEAPUSAGE)
130 void* lpAddress=0;
131 MEMORY_BASIC_INFORMATION Info;
133 pInfo->HeapUsage = 0;
137 if (VirtualQueryEx(hProcess, lpAddress, &Info, sizeof(Info)) == 0)
138 break;
140 if ((Info.State == MEM_COMMIT) && (Info.Type == MEM_PRIVATE))
141 pInfo->HeapUsage += Info.RegionSize;
143 lpAddress = (LPBYTE)lpAddress + Info.RegionSize;
145 while (lpAddress < (void *)0x80000000); // 2GB address space
147 pInfo->Fields |= osl_Process_HEAPUSAGE;
150 if (Fields & osl_Process_CPUTIMES)
152 FILETIME CreationTime, ExitTime, KernelTime, UserTime;
154 if (GetProcessTimes(hProcess, &CreationTime, &ExitTime,
155 &KernelTime, &UserTime))
157 __int64 Value;
159 Value = *((__int64 *)&UserTime);
160 pInfo->UserTime.Seconds = (unsigned long) (Value / 10000000L);
161 pInfo->UserTime.Nanosec = (unsigned long)((Value % 10000000L) * 100);
163 Value = *((__int64 *)&KernelTime);
164 pInfo->SystemTime.Seconds = (unsigned long) (Value / 10000000L);
165 pInfo->SystemTime.Nanosec = (unsigned long)((Value % 10000000L) * 100);
167 pInfo->Fields |= osl_Process_CPUTIMES;
171 return (pInfo->Fields == Fields) ? osl_Process_E_None : osl_Process_E_Unknown;
174 /***************************************************************************/
176 oslProcessError SAL_CALL osl_joinProcess(oslProcess Process)
178 return osl_joinProcessWithTimeout(Process, NULL);
181 /***************************************************************************/
183 oslProcessError SAL_CALL osl_joinProcessWithTimeout(oslProcess Process, const TimeValue* pTimeout)
185 DWORD timeout = INFINITE;
186 oslProcessError osl_error = osl_Process_E_None;
187 DWORD ret;
189 if (NULL == Process)
190 return osl_Process_E_Unknown;
192 if (pTimeout)
193 timeout = pTimeout->Seconds * 1000 + pTimeout->Nanosec / 1000000L;
195 ret = WaitForSingleObject(((oslProcessImpl*)Process)->m_hProcess, timeout);
197 if (WAIT_FAILED == ret)
198 osl_error = osl_Process_E_Unknown;
199 else if (WAIT_TIMEOUT == ret)
200 osl_error = osl_Process_E_TimedOut;
202 return osl_error;
205 /***************************************************************************
206 * osl_bootstrap_getExecutableFile_Impl().
208 * @internal
209 * @see rtl_bootstrap
210 * @see #i37371#
212 ***************************************************************************/
214 extern "C" oslProcessError SAL_CALL osl_bootstrap_getExecutableFile_Impl (
215 rtl_uString ** ppFileURL
216 ) SAL_THROW_EXTERN_C()
218 oslProcessError result = osl_Process_E_NotFound;
220 ::osl::LongPathBuffer< sal_Unicode > aBuffer( MAX_LONG_PATH );
221 DWORD buflen = 0;
223 if ((buflen = GetModuleFileNameW (0, ::osl::mingw_reinterpret_cast<LPWSTR>(aBuffer), aBuffer.getBufSizeInSymbols())) > 0)
225 rtl_uString * pAbsPath = 0;
226 rtl_uString_newFromStr_WithLength (&(pAbsPath), aBuffer, buflen);
227 if (pAbsPath)
229 /* Convert from path to url. */
230 if (osl_getFileURLFromSystemPath (pAbsPath, ppFileURL) == osl_File_E_None)
232 /* Success. */
233 result = osl_Process_E_None;
235 rtl_uString_release (pAbsPath);
239 return (result);
242 /***************************************************************************
243 * Command Line Arguments.
244 ***************************************************************************/
246 struct CommandArgs_Impl
248 sal_uInt32 m_nCount;
249 rtl_uString ** m_ppArgs;
252 static struct CommandArgs_Impl g_command_args =
258 #ifdef _MSC_VER
259 #pragma warning( push )
260 #pragma warning( disable: 4100 )
261 #endif
262 static rtl_uString ** osl_createCommandArgs_Impl (int argc, char **)
264 rtl_uString ** ppArgs =
265 (rtl_uString**)rtl_allocateZeroMemory (argc * sizeof(rtl_uString*));
266 if (ppArgs != 0)
268 int i;
269 int nArgs;
270 LPWSTR *wargv = CommandLineToArgvW( GetCommandLineW(), &nArgs );
271 OSL_ASSERT( nArgs == argc );
272 for (i = 0; i < nArgs; i++)
274 /* Convert to unicode */
275 rtl_uString_newFromStr( &(ppArgs[i]), reinterpret_cast<const sal_Unicode*>(wargv[i]) );
277 if (ppArgs[0] != 0)
279 /* Ensure absolute path */
280 ::osl::LongPathBuffer< sal_Unicode > aBuffer( MAX_LONG_PATH );
281 DWORD dwResult = 0;
283 dwResult = SearchPath (
284 0, reinterpret_cast<LPCWSTR>(ppArgs[0]->buffer), L".exe", aBuffer.getBufSizeInSymbols(), ::osl::mingw_reinterpret_cast<LPWSTR>(aBuffer), 0);
285 if ((0 < dwResult) && (dwResult < aBuffer.getBufSizeInSymbols()))
287 /* Replace argv[0] with it's absolute path */
288 rtl_uString_newFromStr_WithLength(
289 &(ppArgs[0]), aBuffer, dwResult);
292 if (ppArgs[0] != 0)
294 /* Convert to FileURL, see @ osl_getExecutableFile() */
295 rtl_uString * pResult = 0;
296 osl_getFileURLFromSystemPath (ppArgs[0], &pResult);
297 if (pResult != 0)
299 rtl_uString_assign (&(ppArgs[0]), pResult);
300 rtl_uString_release (pResult);
304 return (ppArgs);
307 #ifdef _MSC_VER
308 #pragma warning( pop )
309 #endif
311 /***************************************************************************/
313 oslProcessError SAL_CALL osl_getExecutableFile( rtl_uString **ppustrFile )
315 oslProcessError result = osl_Process_E_NotFound;
317 osl_acquireMutex (*osl_getGlobalMutex());
318 OSL_ASSERT(g_command_args.m_nCount > 0);
319 if (g_command_args.m_nCount > 0)
321 /* CommandArgs set. Obtain arv[0]. */
322 rtl_uString_assign (ppustrFile, g_command_args.m_ppArgs[0]);
323 result = osl_Process_E_None;
325 osl_releaseMutex (*osl_getGlobalMutex());
327 return (result);
330 /***************************************************************************/
332 sal_uInt32 SAL_CALL osl_getCommandArgCount(void)
334 sal_uInt32 result = 0;
336 osl_acquireMutex (*osl_getGlobalMutex());
337 if (g_command_args.m_nCount == 0) {
338 OSL_TRACE(
339 OSL_LOG_PREFIX
340 "osl_getCommandArgCount w/o prior call to osl_setCommandArgs");
342 if (g_command_args.m_nCount > 0)
344 /* We're not counting argv[0] here. */
345 result = g_command_args.m_nCount - 1;
347 osl_releaseMutex (*osl_getGlobalMutex());
349 return (result);
352 /***************************************************************************/
354 oslProcessError SAL_CALL osl_getCommandArg( sal_uInt32 nArg, rtl_uString **strCommandArg)
356 oslProcessError result = osl_Process_E_NotFound;
358 osl_acquireMutex (*osl_getGlobalMutex());
359 OSL_ASSERT(g_command_args.m_nCount > 0);
360 if (g_command_args.m_nCount > (nArg + 1))
362 /* We're not counting argv[0] here. */
363 rtl_uString_assign (strCommandArg, g_command_args.m_ppArgs[nArg + 1]);
364 result = osl_Process_E_None;
366 osl_releaseMutex (*osl_getGlobalMutex());
368 return (result);
371 /***************************************************************************/
373 void SAL_CALL osl_setCommandArgs (int argc, char ** argv)
375 OSL_ASSERT(argc > 0);
376 osl_acquireMutex (*osl_getGlobalMutex());
377 if (g_command_args.m_nCount == 0)
379 rtl_uString** ppArgs = osl_createCommandArgs_Impl (argc, argv);
380 if (ppArgs != 0)
382 g_command_args.m_nCount = argc;
383 g_command_args.m_ppArgs = ppArgs;
386 osl_releaseMutex (*osl_getGlobalMutex());
389 /***************************************************************************
390 * Environment
391 ***************************************************************************/
392 #define ENV_BUFFER_SIZE (32*1024-1)
394 oslProcessError SAL_CALL osl_getEnvironment(rtl_uString *ustrVar, rtl_uString **ustrValue)
396 WCHAR buff[ENV_BUFFER_SIZE];
398 if (GetEnvironmentVariableW(reinterpret_cast<LPCWSTR>(ustrVar->buffer), buff, ENV_BUFFER_SIZE) > 0)
400 rtl_uString_newFromStr(ustrValue, reinterpret_cast<const sal_Unicode*>(buff));
401 return osl_Process_E_None;
403 return osl_Process_E_Unknown;
406 oslProcessError SAL_CALL osl_setEnvironment(rtl_uString *ustrVar, rtl_uString *ustrValue)
408 // set Windows environment variable
409 LPCWSTR lpName = reinterpret_cast<LPCWSTR>(ustrVar->buffer);
410 LPCWSTR lpValue = reinterpret_cast<LPCWSTR>(ustrValue->buffer);
411 if (SetEnvironmentVariableW(lpName, lpValue))
413 wchar_t *buffer = new wchar_t[wcslen(lpName) + 1 + wcslen(lpValue) + 1];
414 wcscpy(buffer, lpName);
415 wcscat(buffer, L"=");
416 wcscat(buffer, lpValue);
417 _wputenv(buffer);
418 delete[] buffer;
419 return osl_Process_E_None;
421 return osl_Process_E_Unknown;
424 oslProcessError SAL_CALL osl_clearEnvironment(rtl_uString *ustrVar)
426 // delete the variable from the current process environment
427 // by setting SetEnvironmentVariable's second parameter to NULL
428 LPCWSTR lpName = reinterpret_cast<LPCWSTR>(ustrVar->buffer);
429 if (SetEnvironmentVariableW(lpName, NULL))
431 wchar_t *buffer = new wchar_t[wcslen(lpName) + 1 + 1];
432 wcscpy(buffer, lpName);
433 wcscat(buffer, L"=");
434 _wputenv(buffer);
435 delete[] buffer;
436 return osl_Process_E_None;
438 return osl_Process_E_Unknown;
441 /***************************************************************************
442 * Current Working Directory.
443 ***************************************************************************/
445 extern "C" oslMutex g_CurrentDirectoryMutex;
447 oslProcessError SAL_CALL osl_getProcessWorkingDir( rtl_uString **pustrWorkingDir )
449 ::osl::LongPathBuffer< sal_Unicode > aBuffer( MAX_LONG_PATH );
450 DWORD dwLen = 0;
453 osl_acquireMutex( g_CurrentDirectoryMutex );
454 dwLen = GetCurrentDirectory( aBuffer.getBufSizeInSymbols(), ::osl::mingw_reinterpret_cast<LPWSTR>(aBuffer) );
455 osl_releaseMutex( g_CurrentDirectoryMutex );
457 if ( dwLen && dwLen < aBuffer.getBufSizeInSymbols() )
459 oslFileError eError;
460 rtl_uString *ustrTemp = NULL;;
462 rtl_uString_newFromStr_WithLength( &ustrTemp, aBuffer, dwLen );
463 eError = osl_getFileURLFromSystemPath( ustrTemp, pustrWorkingDir );
465 rtl_uString_release( ustrTemp );
467 if ( osl_File_E_None != eError )
468 return osl_Process_E_Unknown;
469 else
470 return osl_Process_E_None;
472 else
473 return osl_Process_E_Unknown;
476 /***************************************************************************
477 * Process Locale.
478 ***************************************************************************/
480 extern "C" void _imp_getProcessLocale( rtl_Locale ** ppLocale );
482 static rtl_Locale * g_theProcessLocale = NULL;
484 /***************************************************************************/
486 oslProcessError SAL_CALL osl_getProcessLocale( rtl_Locale ** ppLocale )
488 osl_acquireMutex( *osl_getGlobalMutex() );
490 /* determine the users default locale */
491 if( NULL == g_theProcessLocale )
492 _imp_getProcessLocale( &g_theProcessLocale );
494 /* or return the cached value */
495 *ppLocale = g_theProcessLocale;
497 osl_releaseMutex( *osl_getGlobalMutex() );
498 return osl_Process_E_None;
501 /***************************************************************************/
503 oslProcessError SAL_CALL osl_setProcessLocale( rtl_Locale * pLocale )
505 osl_acquireMutex( *osl_getGlobalMutex() );
507 /* check if locale is supported */
508 if( RTL_TEXTENCODING_DONTKNOW == osl_getTextEncodingFromLocale( pLocale ) )
509 return osl_Process_E_Unknown;
511 /* just remember the locale here */
512 g_theProcessLocale = pLocale;
514 osl_releaseMutex( *osl_getGlobalMutex() );
515 return osl_Process_E_None;
518 /************************************************
519 * Portal send/receive interface implementation
520 ************************************************/
522 static sal_Bool ReadPipe(oslPipe hPipe,
523 void* pBuffer,
524 sal_Int32 BytesToRead,
525 sal_Int32* nBytes)
527 *nBytes = osl_receivePipe(hPipe, pBuffer, BytesToRead);
528 OSL_TRACE("tried to receive %d, received %d.\n",
529 BytesToRead, *nBytes);
530 return (sal_Bool)((*nBytes >= 0) && (osl_getLastPipeError(hPipe) == osl_Pipe_E_None));
533 static sal_Bool WritePipe(oslPipe hPipe,
534 void* pBuffer,
535 sal_Int32 BytesToSend,
536 sal_Int32* nBytes)
538 *nBytes = osl_sendPipe(hPipe, pBuffer, BytesToSend);
539 OSL_TRACE("tried to send %d, sent %d\n",
540 BytesToSend, *nBytes);
541 return (sal_Bool)((*nBytes == BytesToSend) && (osl_getLastPipeError(hPipe) == osl_Pipe_E_None));
544 sal_Bool SAL_CALL osl_sendResourcePipe(oslPipe hPipe, oslSocket pSocket)
546 sal_Bool bRet = sal_False;
547 sal_Int32 bytes = 0;
549 /* duplicate handle on this other side ->
550 receive remote process
551 duplicate handle and send it */
552 DWORD remoteProcessID = 0;
553 HANDLE fd = (HANDLE)pSocket->m_Socket;
554 oslDescriptorType code = osl_Process_TypeSocket;
556 OSL_TRACE("osl_sendResourcePipe: enter...");
558 if (ReadPipe(hPipe, &remoteProcessID, sizeof(remoteProcessID), &bytes))
560 HANDLE hRemoteProc = OpenProcess(PROCESS_DUP_HANDLE,
561 FALSE,
562 remoteProcessID);
564 if (hRemoteProc != (HANDLE)NULL)
566 HANDLE newFd;
568 if (DuplicateHandle(GetCurrentProcess(),
570 hRemoteProc,
571 &newFd,
572 0, FALSE, DUPLICATE_SAME_ACCESS))
574 if (
575 WritePipe(hPipe, &code, sizeof(code), &bytes) &&
576 WritePipe(hPipe, &newFd, sizeof(fd), &bytes)
578 bRet = sal_True;
581 CloseHandle(hRemoteProc);
585 if (bRet)
587 sal_Int32 commitCode;
588 OSL_TRACE("osl_sendResourcePipe: handle sent successfully, verify...");
590 if (
591 !ReadPipe(hPipe, &commitCode, sizeof(commitCode), &bytes) ||
592 (commitCode <= 0)
594 bRet = sal_False;
597 OSL_TRACE("osl_sendResourcePipe: exit... %d", bRet);
598 return(bRet);
602 oslSocket SAL_CALL osl_receiveResourcePipe(oslPipe hPipe)
604 sal_Bool bRet = sal_False;
605 sal_Int32 bytes = 0;
606 sal_Int32 commitCode;
607 oslSocket pSocket = NULL;
609 /* duplicate handle on the other side ->
610 send my process id receive duplicated handle */
611 HANDLE fd = INVALID_HANDLE_VALUE;
612 DWORD myProcessID = GetCurrentProcessId();
613 oslDescriptorType code = osl_Process_TypeNone;
615 OSL_TRACE("osl_receiveResourcePipe: enter...");
617 if (
618 WritePipe(hPipe, &myProcessID, sizeof(myProcessID), &bytes) &&
619 ReadPipe(hPipe, &code, sizeof(code), &bytes) &&
620 ReadPipe(hPipe, &fd, sizeof(fd), &bytes)
623 if (code == osl_Process_TypeSocket)
625 pSocket = __osl_createSocketImpl((SOCKET)fd);
626 bRet = sal_True;
628 else
630 OSL_TRACE("osl_receiveResourcePipe: UKNOWN");
631 bRet = sal_False;
635 if (bRet)
636 commitCode = 1;
637 else
638 commitCode = 0;
640 WritePipe(hPipe, &commitCode, sizeof(commitCode), &bytes);
642 OSL_TRACE("osl_receiveResourcePipe: exit... %d, %p", bRet, pSocket);
644 return pSocket;
647 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */