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 **)
264 rtl_uString
** ppArgs
=
265 (rtl_uString
**)rtl_allocateZeroMemory (argc
* sizeof(rtl_uString
*));
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
]) );
279 /* Ensure absolute path */
280 ::osl::LongPathBuffer
< sal_Unicode
> aBuffer( MAX_LONG_PATH
);
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
);
294 /* Convert to FileURL, see @ osl_getExecutableFile() */
295 rtl_uString
* pResult
= 0;
296 osl_getFileURLFromSystemPath (ppArgs
[0], &pResult
);
299 rtl_uString_assign (&(ppArgs
[0]), pResult
);
300 rtl_uString_release (pResult
);
308 #pragma warning( pop )
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());
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) {
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());
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());
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
);
382 g_command_args
.m_nCount
= argc
;
383 g_command_args
.m_ppArgs
= ppArgs
;
386 osl_releaseMutex (*osl_getGlobalMutex());
389 /***************************************************************************
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
);
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
"=");
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
);
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() )
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
;
470 return osl_Process_E_None
;
473 return osl_Process_E_Unknown
;
476 /***************************************************************************
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
,
524 sal_Int32 BytesToRead
,
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
,
535 sal_Int32 BytesToSend
,
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
;
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
,
564 if (hRemoteProc
!= (HANDLE
)NULL
)
568 if (DuplicateHandle(GetCurrentProcess(),
572 0, FALSE
, DUPLICATE_SAME_ACCESS
))
575 WritePipe(hPipe
, &code
, sizeof(code
), &bytes
) &&
576 WritePipe(hPipe
, &newFd
, sizeof(fd
), &bytes
)
581 CloseHandle(hRemoteProc
);
587 sal_Int32 commitCode
;
588 OSL_TRACE("osl_sendResourcePipe: handle sent successfully, verify...");
591 !ReadPipe(hPipe
, &commitCode
, sizeof(commitCode
), &bytes
) ||
597 OSL_TRACE("osl_sendResourcePipe: exit... %d", bRet
);
602 oslSocket SAL_CALL
osl_receiveResourcePipe(oslPipe hPipe
)
604 sal_Bool bRet
= sal_False
;
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...");
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
);
630 OSL_TRACE("osl_receiveResourcePipe: UKNOWN");
640 WritePipe(hPipe
, &commitCode
, sizeof(commitCode
), &bytes
);
642 OSL_TRACE("osl_receiveResourcePipe: exit... %d, %p", bRet
, pSocket
);
647 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */