1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
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 .
24 #pragma warning(push,1) /* disable warnings within system headers */
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>
40 #include "path_helper.hxx"
41 #include <rtl/ustrbuf.h>
42 #include <rtl/alloc.h>
44 /***************************************************************************
46 ***************************************************************************/
48 oslProcessError SAL_CALL
osl_terminateProcess(oslProcess Process
)
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
);
70 pProcImpl
= reinterpret_cast< oslProcessImpl
*>( rtl_allocateMemory(sizeof(oslProcessImpl
)) );
71 pProcImpl
->m_hProcess
= hProcess
;
72 pProcImpl
->m_IdProcess
= Ident
;
80 /***************************************************************************/
82 void SAL_CALL
osl_freeProcessHandle(oslProcess Process
)
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
)
102 hProcess
= GetCurrentProcess();
103 IdProcess
= GetCurrentProcessId();
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
;
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
)
131 MEMORY_BASIC_INFORMATION Info
;
133 pInfo
->HeapUsage
= 0;
137 if (VirtualQueryEx(hProcess
, lpAddress
, &Info
, sizeof(Info
)) == 0)
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
))
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
;
190 return osl_Process_E_Unknown
;
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
;
205 /***************************************************************************
206 * osl_bootstrap_getExecutableFile_Impl().
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
);
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
);
229 /* Convert from path to url. */
230 if (osl_getFileURLFromSystemPath (pAbsPath
, ppFileURL
) == osl_File_E_None
)
233 result
= osl_Process_E_None
;
235 rtl_uString_release (pAbsPath
);
242 /***************************************************************************
243 * Command Line Arguments.
244 ***************************************************************************/
246 struct CommandArgs_Impl
249 rtl_uString
** m_ppArgs
;
252 static struct CommandArgs_Impl g_command_args
=
259 #pragma warning( push )
260 #pragma warning( disable: 4100 )
262 static rtl_uString
** osl_createCommandArgs_Impl (int & argc
, char **)
265 LPWSTR
*wargv
= CommandLineToArgvW( GetCommandLineW(), &nArgs
);
268 assert(argc
== 0 /* special case - faked */);
271 rtl_uString
** ppArgs
=
272 (rtl_uString
**)rtl_allocateZeroMemory(nArgs
* sizeof(rtl_uString
*));
276 for (i
= 0; i
< nArgs
; i
++)
278 /* Convert to unicode */
279 rtl_uString_newFromStr( &(ppArgs
[i
]), reinterpret_cast<const sal_Unicode
*>(wargv
[i
]) );
283 /* Ensure absolute path */
284 ::osl::LongPathBuffer
< sal_Unicode
> aBuffer( MAX_LONG_PATH
);
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
);
298 /* Convert to FileURL, see @ osl_getExecutableFile() */
299 rtl_uString
* pResult
= 0;
300 osl_getFileURLFromSystemPath (ppArgs
[0], &pResult
);
303 rtl_uString_assign (&(ppArgs
[0]), pResult
);
304 rtl_uString_release (pResult
);
312 #pragma warning( pop )
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());
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) {
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());
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());
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
);
385 g_command_args
.m_nCount
= argc
;
386 g_command_args
.m_ppArgs
= ppArgs
;
389 osl_releaseMutex (*osl_getGlobalMutex());
392 /***************************************************************************
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
);
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
"=");
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
);
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() )
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
;
473 return osl_Process_E_None
;
476 return osl_Process_E_Unknown
;
479 /***************************************************************************
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
,
527 sal_Int32 BytesToRead
,
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
,
538 sal_Int32 BytesToSend
,
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
;
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
,
567 if (hRemoteProc
!= (HANDLE
)NULL
)
571 if (DuplicateHandle(GetCurrentProcess(),
575 0, FALSE
, DUPLICATE_SAME_ACCESS
))
578 WritePipe(hPipe
, &code
, sizeof(code
), &bytes
) &&
579 WritePipe(hPipe
, &newFd
, sizeof(fd
), &bytes
)
584 CloseHandle(hRemoteProc
);
590 sal_Int32 commitCode
;
591 OSL_TRACE("osl_sendResourcePipe: handle sent successfully, verify...");
594 !ReadPipe(hPipe
, &commitCode
, sizeof(commitCode
), &bytes
) ||
600 OSL_TRACE("osl_sendResourcePipe: exit... %d", bRet
);
605 oslSocket SAL_CALL
osl_receiveResourcePipe(oslPipe hPipe
)
607 sal_Bool bRet
= sal_False
;
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...");
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
);
633 OSL_TRACE("osl_receiveResourcePipe: UNKNOWN");
643 WritePipe(hPipe
, &commitCode
, sizeof(commitCode
), &bytes
);
645 OSL_TRACE("osl_receiveResourcePipe: exit... %d, %p", bRet
, pSocket
);
650 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */