Version 4.2.0.1, tag libreoffice-4.2.0.1
[LibreOffice.git] / sal / osl / w32 / process.cxx
blob0328a4fbc9db64e836de2e48e96e1be9b3698f05
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 int nArgs(0);
265 LPWSTR *wargv = CommandLineToArgvW( GetCommandLineW(), &nArgs );
266 if (argc != nArgs)
268 assert(argc == 0 /* special case - faked */);
269 argc = nArgs;
271 rtl_uString ** ppArgs =
272 (rtl_uString**)rtl_allocateZeroMemory(nArgs * sizeof(rtl_uString*));
273 if (ppArgs != 0)
275 int i;
276 for (i = 0; i < nArgs; i++)
278 /* Convert to unicode */
279 rtl_uString_newFromStr( &(ppArgs[i]), reinterpret_cast<const sal_Unicode*>(wargv[i]) );
281 if (ppArgs[0] != 0)
283 /* Ensure absolute path */
284 ::osl::LongPathBuffer< sal_Unicode > aBuffer( MAX_LONG_PATH );
285 DWORD dwResult = 0;
287 dwResult = SearchPath (
288 0, reinterpret_cast<LPCWSTR>(ppArgs[0]->buffer), L".exe", aBuffer.getBufSizeInSymbols(), ::osl::mingw_reinterpret_cast<LPWSTR>(aBuffer), 0);
289 if ((0 < dwResult) && (dwResult < aBuffer.getBufSizeInSymbols()))
291 /* Replace argv[0] with it's absolute path */
292 rtl_uString_newFromStr_WithLength(
293 &(ppArgs[0]), aBuffer, dwResult);
296 if (ppArgs[0] != 0)
298 /* Convert to FileURL, see @ osl_getExecutableFile() */
299 rtl_uString * pResult = 0;
300 osl_getFileURLFromSystemPath (ppArgs[0], &pResult);
301 if (pResult != 0)
303 rtl_uString_assign (&(ppArgs[0]), pResult);
304 rtl_uString_release (pResult);
308 return (ppArgs);
311 #ifdef _MSC_VER
312 #pragma warning( pop )
313 #endif
315 /***************************************************************************/
317 oslProcessError SAL_CALL osl_getExecutableFile( rtl_uString **ppustrFile )
319 oslProcessError result = osl_Process_E_NotFound;
321 osl_acquireMutex (*osl_getGlobalMutex());
322 OSL_ASSERT(g_command_args.m_nCount > 0);
323 if (g_command_args.m_nCount > 0)
325 /* CommandArgs set. Obtain arv[0]. */
326 rtl_uString_assign (ppustrFile, g_command_args.m_ppArgs[0]);
327 result = osl_Process_E_None;
329 osl_releaseMutex (*osl_getGlobalMutex());
331 return (result);
334 /***************************************************************************/
336 sal_uInt32 SAL_CALL osl_getCommandArgCount(void)
338 sal_uInt32 result = 0;
340 osl_acquireMutex (*osl_getGlobalMutex());
341 if (g_command_args.m_nCount == 0) {
342 OSL_TRACE(
343 OSL_LOG_PREFIX
344 "osl_getCommandArgCount w/o prior call to osl_setCommandArgs");
346 if (g_command_args.m_nCount > 0)
348 /* We're not counting argv[0] here. */
349 result = g_command_args.m_nCount - 1;
351 osl_releaseMutex (*osl_getGlobalMutex());
353 return (result);
356 /***************************************************************************/
358 oslProcessError SAL_CALL osl_getCommandArg( sal_uInt32 nArg, rtl_uString **strCommandArg)
360 oslProcessError result = osl_Process_E_NotFound;
362 osl_acquireMutex (*osl_getGlobalMutex());
363 OSL_ASSERT(g_command_args.m_nCount > 0);
364 if (g_command_args.m_nCount > (nArg + 1))
366 /* We're not counting argv[0] here. */
367 rtl_uString_assign (strCommandArg, g_command_args.m_ppArgs[nArg + 1]);
368 result = osl_Process_E_None;
370 osl_releaseMutex (*osl_getGlobalMutex());
372 return (result);
375 /***************************************************************************/
377 void SAL_CALL osl_setCommandArgs (int argc, char ** argv)
379 osl_acquireMutex (*osl_getGlobalMutex());
380 if (g_command_args.m_nCount == 0)
382 rtl_uString** ppArgs = osl_createCommandArgs_Impl (argc, argv);
383 if (ppArgs != 0)
385 g_command_args.m_nCount = argc;
386 g_command_args.m_ppArgs = ppArgs;
389 osl_releaseMutex (*osl_getGlobalMutex());
392 /***************************************************************************
393 * Environment
394 ***************************************************************************/
395 #define ENV_BUFFER_SIZE (32*1024-1)
397 oslProcessError SAL_CALL osl_getEnvironment(rtl_uString *ustrVar, rtl_uString **ustrValue)
399 WCHAR buff[ENV_BUFFER_SIZE];
401 if (GetEnvironmentVariableW(reinterpret_cast<LPCWSTR>(ustrVar->buffer), buff, ENV_BUFFER_SIZE) > 0)
403 rtl_uString_newFromStr(ustrValue, reinterpret_cast<const sal_Unicode*>(buff));
404 return osl_Process_E_None;
406 return osl_Process_E_Unknown;
409 oslProcessError SAL_CALL osl_setEnvironment(rtl_uString *ustrVar, rtl_uString *ustrValue)
411 // set Windows environment variable
412 LPCWSTR lpName = reinterpret_cast<LPCWSTR>(ustrVar->buffer);
413 LPCWSTR lpValue = reinterpret_cast<LPCWSTR>(ustrValue->buffer);
414 if (SetEnvironmentVariableW(lpName, lpValue))
416 wchar_t *buffer = new wchar_t[wcslen(lpName) + 1 + wcslen(lpValue) + 1];
417 wcscpy(buffer, lpName);
418 wcscat(buffer, L"=");
419 wcscat(buffer, lpValue);
420 _wputenv(buffer);
421 delete[] buffer;
422 return osl_Process_E_None;
424 return osl_Process_E_Unknown;
427 oslProcessError SAL_CALL osl_clearEnvironment(rtl_uString *ustrVar)
429 // delete the variable from the current process environment
430 // by setting SetEnvironmentVariable's second parameter to NULL
431 LPCWSTR lpName = reinterpret_cast<LPCWSTR>(ustrVar->buffer);
432 if (SetEnvironmentVariableW(lpName, NULL))
434 wchar_t *buffer = new wchar_t[wcslen(lpName) + 1 + 1];
435 wcscpy(buffer, lpName);
436 wcscat(buffer, L"=");
437 _wputenv(buffer);
438 delete[] buffer;
439 return osl_Process_E_None;
441 return osl_Process_E_Unknown;
444 /***************************************************************************
445 * Current Working Directory.
446 ***************************************************************************/
448 extern "C" oslMutex g_CurrentDirectoryMutex;
450 oslProcessError SAL_CALL osl_getProcessWorkingDir( rtl_uString **pustrWorkingDir )
452 ::osl::LongPathBuffer< sal_Unicode > aBuffer( MAX_LONG_PATH );
453 DWORD dwLen = 0;
456 osl_acquireMutex( g_CurrentDirectoryMutex );
457 dwLen = GetCurrentDirectory( aBuffer.getBufSizeInSymbols(), ::osl::mingw_reinterpret_cast<LPWSTR>(aBuffer) );
458 osl_releaseMutex( g_CurrentDirectoryMutex );
460 if ( dwLen && dwLen < aBuffer.getBufSizeInSymbols() )
462 oslFileError eError;
463 rtl_uString *ustrTemp = NULL;;
465 rtl_uString_newFromStr_WithLength( &ustrTemp, aBuffer, dwLen );
466 eError = osl_getFileURLFromSystemPath( ustrTemp, pustrWorkingDir );
468 rtl_uString_release( ustrTemp );
470 if ( osl_File_E_None != eError )
471 return osl_Process_E_Unknown;
472 else
473 return osl_Process_E_None;
475 else
476 return osl_Process_E_Unknown;
479 /***************************************************************************
480 * Process Locale.
481 ***************************************************************************/
483 extern "C" void _imp_getProcessLocale( rtl_Locale ** ppLocale );
485 static rtl_Locale * g_theProcessLocale = NULL;
487 /***************************************************************************/
489 oslProcessError SAL_CALL osl_getProcessLocale( rtl_Locale ** ppLocale )
491 osl_acquireMutex( *osl_getGlobalMutex() );
493 /* determine the users default locale */
494 if( NULL == g_theProcessLocale )
495 _imp_getProcessLocale( &g_theProcessLocale );
497 /* or return the cached value */
498 *ppLocale = g_theProcessLocale;
500 osl_releaseMutex( *osl_getGlobalMutex() );
501 return osl_Process_E_None;
504 /***************************************************************************/
506 oslProcessError SAL_CALL osl_setProcessLocale( rtl_Locale * pLocale )
508 osl_acquireMutex( *osl_getGlobalMutex() );
510 /* check if locale is supported */
511 if( RTL_TEXTENCODING_DONTKNOW == osl_getTextEncodingFromLocale( pLocale ) )
512 return osl_Process_E_Unknown;
514 /* just remember the locale here */
515 g_theProcessLocale = pLocale;
517 osl_releaseMutex( *osl_getGlobalMutex() );
518 return osl_Process_E_None;
521 /************************************************
522 * Portal send/receive interface implementation
523 ************************************************/
525 static sal_Bool ReadPipe(oslPipe hPipe,
526 void* pBuffer,
527 sal_Int32 BytesToRead,
528 sal_Int32* nBytes)
530 *nBytes = osl_receivePipe(hPipe, pBuffer, BytesToRead);
531 OSL_TRACE("tried to receive %d, received %d.\n",
532 BytesToRead, *nBytes);
533 return (sal_Bool)((*nBytes >= 0) && (osl_getLastPipeError(hPipe) == osl_Pipe_E_None));
536 static sal_Bool WritePipe(oslPipe hPipe,
537 void* pBuffer,
538 sal_Int32 BytesToSend,
539 sal_Int32* nBytes)
541 *nBytes = osl_sendPipe(hPipe, pBuffer, BytesToSend);
542 OSL_TRACE("tried to send %d, sent %d\n",
543 BytesToSend, *nBytes);
544 return (sal_Bool)((*nBytes == BytesToSend) && (osl_getLastPipeError(hPipe) == osl_Pipe_E_None));
547 sal_Bool SAL_CALL osl_sendResourcePipe(oslPipe hPipe, oslSocket pSocket)
549 sal_Bool bRet = sal_False;
550 sal_Int32 bytes = 0;
552 /* duplicate handle on this other side ->
553 receive remote process
554 duplicate handle and send it */
555 DWORD remoteProcessID = 0;
556 HANDLE fd = (HANDLE)pSocket->m_Socket;
557 oslDescriptorType code = osl_Process_TypeSocket;
559 OSL_TRACE("osl_sendResourcePipe: enter...");
561 if (ReadPipe(hPipe, &remoteProcessID, sizeof(remoteProcessID), &bytes))
563 HANDLE hRemoteProc = OpenProcess(PROCESS_DUP_HANDLE,
564 FALSE,
565 remoteProcessID);
567 if (hRemoteProc != (HANDLE)NULL)
569 HANDLE newFd;
571 if (DuplicateHandle(GetCurrentProcess(),
573 hRemoteProc,
574 &newFd,
575 0, FALSE, DUPLICATE_SAME_ACCESS))
577 if (
578 WritePipe(hPipe, &code, sizeof(code), &bytes) &&
579 WritePipe(hPipe, &newFd, sizeof(fd), &bytes)
581 bRet = sal_True;
584 CloseHandle(hRemoteProc);
588 if (bRet)
590 sal_Int32 commitCode;
591 OSL_TRACE("osl_sendResourcePipe: handle sent successfully, verify...");
593 if (
594 !ReadPipe(hPipe, &commitCode, sizeof(commitCode), &bytes) ||
595 (commitCode <= 0)
597 bRet = sal_False;
600 OSL_TRACE("osl_sendResourcePipe: exit... %d", bRet);
601 return(bRet);
605 oslSocket SAL_CALL osl_receiveResourcePipe(oslPipe hPipe)
607 sal_Bool bRet = sal_False;
608 sal_Int32 bytes = 0;
609 sal_Int32 commitCode;
610 oslSocket pSocket = NULL;
612 /* duplicate handle on the other side ->
613 send my process id receive duplicated handle */
614 HANDLE fd = INVALID_HANDLE_VALUE;
615 DWORD myProcessID = GetCurrentProcessId();
616 oslDescriptorType code = osl_Process_TypeNone;
618 OSL_TRACE("osl_receiveResourcePipe: enter...");
620 if (
621 WritePipe(hPipe, &myProcessID, sizeof(myProcessID), &bytes) &&
622 ReadPipe(hPipe, &code, sizeof(code), &bytes) &&
623 ReadPipe(hPipe, &fd, sizeof(fd), &bytes)
626 if (code == osl_Process_TypeSocket)
628 pSocket = __osl_createSocketImpl((SOCKET)fd);
629 bRet = sal_True;
631 else
633 OSL_TRACE("osl_receiveResourcePipe: UNKNOWN");
634 bRet = sal_False;
638 if (bRet)
639 commitCode = 1;
640 else
641 commitCode = 0;
643 WritePipe(hPipe, &commitCode, sizeof(commitCode), &bytes);
645 OSL_TRACE("osl_receiveResourcePipe: exit... %d, %p", bRet, pSocket);
647 return pSocket;
650 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */