1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: process.c,v $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
34 #pragma warning(push,1) /* disable warnings within system headers */
41 #include <osl/diagnose.h>
42 #include <osl/security.h>
43 #include <osl/nlsupport.h>
44 #include <osl/mutex.h>
45 #include <osl/thread.h>
49 #include <rtl/ustrbuf.h>
50 #include <rtl/alloc.h>
52 /***************************************************************************
54 ***************************************************************************/
56 oslProcessError SAL_CALL
osl_terminateProcess(oslProcess Process
)
59 return osl_Process_E_Unknown
;
61 if (TerminateProcess(((oslProcessImpl
*)Process
)->m_hProcess
, 0))
62 return osl_Process_E_None
;
65 return osl_Process_E_Unknown
;
68 /***************************************************************************/
70 oslProcess SAL_CALL
osl_getProcess(oslProcessIdentifier Ident
)
72 oslProcessImpl
* pProcImpl
;
73 HANDLE hProcess
= OpenProcess(
74 STANDARD_RIGHTS_REQUIRED
| PROCESS_QUERY_INFORMATION
| SYNCHRONIZE
, FALSE
, (DWORD
)Ident
);
78 pProcImpl
= rtl_allocateMemory(sizeof(oslProcessImpl
));
79 pProcImpl
->m_hProcess
= hProcess
;
80 pProcImpl
->m_IdProcess
= Ident
;
88 /***************************************************************************/
90 void SAL_CALL
osl_freeProcessHandle(oslProcess Process
)
94 CloseHandle(((oslProcessImpl
*)Process
)->m_hProcess
);
96 rtl_freeMemory((oslProcessImpl
*)Process
);
100 /***************************************************************************/
102 oslProcessError SAL_CALL
osl_getProcessInfo(oslProcess Process
, oslProcessData Fields
,
103 oslProcessInfo
* pInfo
)
110 hProcess
= GetCurrentProcess();
111 IdProcess
= GetCurrentProcessId();
115 hProcess
= ((oslProcessImpl
*)Process
)->m_hProcess
;
116 IdProcess
= ((oslProcessImpl
*)Process
)->m_IdProcess
;
119 if (! pInfo
|| (pInfo
->Size
!= sizeof(oslProcessInfo
)))
120 return osl_Process_E_Unknown
;
124 if (Fields
& osl_Process_IDENTIFIER
)
126 pInfo
->Ident
= IdProcess
;
127 pInfo
->Fields
|= osl_Process_IDENTIFIER
;
130 if (Fields
& osl_Process_EXITCODE
)
132 if (GetExitCodeProcess(hProcess
, &(pInfo
->Code
)) && (pInfo
->Code
!= STILL_ACTIVE
))
133 pInfo
->Fields
|= osl_Process_EXITCODE
;
136 if (Fields
& osl_Process_HEAPUSAGE
)
139 MEMORY_BASIC_INFORMATION Info
;
141 pInfo
->HeapUsage
= 0;
145 if (VirtualQueryEx(hProcess
, lpAddress
, &Info
, sizeof(Info
)) == 0)
148 if ((Info
.State
== MEM_COMMIT
) && (Info
.Type
== MEM_PRIVATE
))
149 pInfo
->HeapUsage
+= Info
.RegionSize
;
151 lpAddress
= (LPBYTE
)lpAddress
+ Info
.RegionSize
;
153 while (lpAddress
< (void *)0x80000000); // 2GB address space
155 pInfo
->Fields
|= osl_Process_HEAPUSAGE
;
158 if (Fields
& osl_Process_CPUTIMES
)
160 FILETIME CreationTime
, ExitTime
, KernelTime
, UserTime
;
162 if (GetProcessTimes(hProcess
, &CreationTime
, &ExitTime
,
163 &KernelTime
, &UserTime
))
167 Value
= *((__int64
*)&UserTime
);
168 pInfo
->UserTime
.Seconds
= (unsigned long) (Value
/ 10000000L);
169 pInfo
->UserTime
.Nanosec
= (unsigned long)((Value
% 10000000L) * 100);
171 Value
= *((__int64
*)&KernelTime
);
172 pInfo
->SystemTime
.Seconds
= (unsigned long) (Value
/ 10000000L);
173 pInfo
->SystemTime
.Nanosec
= (unsigned long)((Value
% 10000000L) * 100);
175 pInfo
->Fields
|= osl_Process_CPUTIMES
;
179 return (pInfo
->Fields
== Fields
) ? osl_Process_E_None
: osl_Process_E_Unknown
;
182 /***************************************************************************/
184 oslProcessError SAL_CALL
osl_joinProcess(oslProcess Process
)
186 return osl_joinProcessWithTimeout(Process
, NULL
);
189 /***************************************************************************/
191 oslProcessError SAL_CALL
osl_joinProcessWithTimeout(oslProcess Process
, const TimeValue
* pTimeout
)
193 DWORD timeout
= INFINITE
;
194 oslProcessError osl_error
= osl_Process_E_None
;
198 return osl_Process_E_Unknown
;
201 timeout
= pTimeout
->Seconds
* 1000 + pTimeout
->Nanosec
/ 1000000L;
203 ret
= WaitForSingleObject(((oslProcessImpl
*)Process
)->m_hProcess
, timeout
);
205 if (WAIT_FAILED
== ret
)
206 osl_error
= osl_Process_E_Unknown
;
207 else if (WAIT_TIMEOUT
== ret
)
208 osl_error
= osl_Process_E_TimedOut
;
213 /***************************************************************************
214 * osl_bootstrap_getExecutableFile_Impl().
220 ***************************************************************************/
222 oslProcessError SAL_CALL
osl_bootstrap_getExecutableFile_Impl (
223 rtl_uString
** ppFileURL
224 ) SAL_THROW_EXTERN_C()
226 oslProcessError result
= osl_Process_E_NotFound
;
228 TCHAR buffer
[MAX_PATH
];
231 if ((buflen
= GetModuleFileNameW (0, buffer
, MAX_PATH
)) > 0)
233 rtl_uString
* pAbsPath
= 0;
234 rtl_uString_newFromStr_WithLength (&(pAbsPath
), buffer
, buflen
);
237 /* Convert from path to url. */
238 if (osl_getFileURLFromSystemPath (pAbsPath
, ppFileURL
) == osl_File_E_None
)
241 result
= osl_Process_E_None
;
243 rtl_uString_release (pAbsPath
);
250 /***************************************************************************
251 * Command Line Arguments.
252 ***************************************************************************/
254 struct CommandArgs_Impl
257 rtl_uString
** m_ppArgs
;
260 static struct CommandArgs_Impl g_command_args
=
267 #pragma warning( push )
268 #pragma warning( disable: 4100 )
270 static rtl_uString
** osl_createCommandArgs_Impl (int argc
, char ** argv
)
272 rtl_uString
** ppArgs
=
273 (rtl_uString
**)rtl_allocateZeroMemory (argc
* sizeof(rtl_uString
*));
278 LPWSTR
*wargv
= CommandLineToArgvW( GetCommandLineW(), &nArgs
);
279 OSL_ASSERT( nArgs
== argc
);
280 for (i
= 0; i
< nArgs
; i
++)
282 /* Convert to unicode */
283 rtl_uString_newFromStr( &(ppArgs
[i
]), wargv
[i
] );
287 /* Ensure absolute path */
289 TCHAR szBuffer
[MAX_PATH
];
291 dwResult
= SearchPath (
292 0, ppArgs
[0]->buffer
, L
".exe", MAX_PATH
, szBuffer
, 0);
293 if ((0 < dwResult
) && (dwResult
< MAX_PATH
))
295 /* Replace argv[0] with it's absolute path */
296 rtl_uString_newFromStr_WithLength(
297 &(ppArgs
[0]), szBuffer
, dwResult
);
302 /* Convert to FileURL, see @ osl_getExecutableFile() */
303 rtl_uString
* pResult
= 0;
304 osl_getFileURLFromSystemPath (ppArgs
[0], &pResult
);
307 rtl_uString_assign (&(ppArgs
[0]), pResult
);
308 rtl_uString_release (pResult
);
316 #pragma warning( pop )
319 /***************************************************************************/
321 oslProcessError SAL_CALL
osl_getExecutableFile( rtl_uString
**ppustrFile
)
323 oslProcessError result
= osl_Process_E_NotFound
;
325 osl_acquireMutex (*osl_getGlobalMutex());
326 if (g_command_args
.m_nCount
> 0)
328 /* CommandArgs set. Obtain arv[0]. */
329 rtl_uString_assign (ppustrFile
, g_command_args
.m_ppArgs
[0]);
330 result
= osl_Process_E_None
;
332 osl_releaseMutex (*osl_getGlobalMutex());
337 /***************************************************************************/
339 sal_uInt32 SAL_CALL
osl_getCommandArgCount(void)
341 sal_uInt32 result
= 0;
343 osl_acquireMutex (*osl_getGlobalMutex());
344 if (g_command_args
.m_nCount
> 0)
346 /* We're not counting argv[0] here. */
347 result
= g_command_args
.m_nCount
- 1;
349 osl_releaseMutex (*osl_getGlobalMutex());
354 /***************************************************************************/
356 oslProcessError SAL_CALL
osl_getCommandArg( sal_uInt32 nArg
, rtl_uString
**strCommandArg
)
358 oslProcessError result
= osl_Process_E_NotFound
;
360 osl_acquireMutex (*osl_getGlobalMutex());
361 if (g_command_args
.m_nCount
> (nArg
+ 1))
363 /* We're not counting argv[0] here. */
364 rtl_uString_assign (strCommandArg
, g_command_args
.m_ppArgs
[nArg
+ 1]);
365 result
= osl_Process_E_None
;
367 osl_releaseMutex (*osl_getGlobalMutex());
372 /***************************************************************************/
374 void SAL_CALL
osl_setCommandArgs (int argc
, char ** argv
)
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 ***************************************************************************/
393 #109941# because of a bug in the M$ unicows library we have to
394 allocate a buffer large enough to hold the requested environment
395 variable instead of testing for the required size. This wastes
396 some stack space, maybe we should revoke this work around if
397 unicows library is fixed.
399 #define ENV_BUFFER_SIZE (32*1024-1)
401 oslProcessError SAL_CALL
osl_getEnvironment(rtl_uString
*ustrVar
, rtl_uString
**ustrValue
)
403 WCHAR buff
[ENV_BUFFER_SIZE
];
405 if (GetEnvironmentVariableW(ustrVar
->buffer
, buff
, ENV_BUFFER_SIZE
) > 0)
407 rtl_uString_newFromStr(ustrValue
, buff
);
408 return osl_Process_E_None
;
410 return osl_Process_E_Unknown
;
413 /***************************************************************************
414 * Current Working Directory.
415 ***************************************************************************/
417 extern oslMutex g_CurrentDirectoryMutex
;
419 oslProcessError SAL_CALL
osl_getProcessWorkingDir( rtl_uString
**pustrWorkingDir
)
421 TCHAR szBuffer
[MAX_PATH
];
425 osl_acquireMutex( g_CurrentDirectoryMutex
);
426 dwLen
= GetCurrentDirectory( sizeof(szBuffer
) / sizeof(TCHAR
), szBuffer
);
427 osl_releaseMutex( g_CurrentDirectoryMutex
);
432 rtl_uString
*ustrTemp
= NULL
;;
434 rtl_uString_newFromStr_WithLength( &ustrTemp
, szBuffer
, dwLen
);
435 eError
= osl_getFileURLFromSystemPath( ustrTemp
, pustrWorkingDir
);
437 rtl_uString_release( ustrTemp
);
439 if ( osl_File_E_None
!= eError
)
440 return osl_Process_E_Unknown
;
442 return osl_Process_E_None
;
445 return osl_Process_E_Unknown
;
448 /***************************************************************************
450 ***************************************************************************/
452 extern void _imp_getProcessLocale( rtl_Locale
** ppLocale
);
454 static rtl_Locale
* g_theProcessLocale
= NULL
;
456 /***************************************************************************/
458 oslProcessError SAL_CALL
osl_getProcessLocale( rtl_Locale
** ppLocale
)
460 osl_acquireMutex( *osl_getGlobalMutex() );
462 /* determine the users default locale */
463 if( NULL
== g_theProcessLocale
)
464 _imp_getProcessLocale( &g_theProcessLocale
);
466 /* or return the cached value */
467 *ppLocale
= g_theProcessLocale
;
469 osl_releaseMutex( *osl_getGlobalMutex() );
470 return osl_Process_E_None
;
473 /***************************************************************************/
475 oslProcessError SAL_CALL
osl_setProcessLocale( rtl_Locale
* pLocale
)
477 osl_acquireMutex( *osl_getGlobalMutex() );
479 /* check if locale is supported */
480 if( RTL_TEXTENCODING_DONTKNOW
== osl_getTextEncodingFromLocale( pLocale
) )
481 return osl_Process_E_Unknown
;
483 /* just remember the locale here */
484 g_theProcessLocale
= pLocale
;
486 osl_releaseMutex( *osl_getGlobalMutex() );
487 return osl_Process_E_None
;
490 /************************************************
491 * Portal send/receive interface implementation
492 ************************************************/
494 static sal_Bool
ReadPipe(oslPipe hPipe
,
496 sal_Int32 BytesToRead
,
499 *nBytes
= osl_receivePipe(hPipe
, pBuffer
, BytesToRead
);
500 OSL_TRACE("tried to recieve %d, recieved %d.\n",
501 BytesToRead
, *nBytes
);
502 return (sal_Bool
)((*nBytes
>= 0) && (osl_getLastPipeError(hPipe
) == osl_Pipe_E_None
));
505 static sal_Bool
WritePipe(oslPipe hPipe
,
507 sal_Int32 BytesToSend
,
510 *nBytes
= osl_sendPipe(hPipe
, pBuffer
, BytesToSend
);
511 OSL_TRACE("tried to send %d, sent %d\n",
512 BytesToSend
, *nBytes
);
513 return (sal_Bool
)((*nBytes
== BytesToSend
) && (osl_getLastPipeError(hPipe
) == osl_Pipe_E_None
));
516 sal_Bool SAL_CALL
osl_sendResourcePipe(oslPipe hPipe
, oslSocket pSocket
)
518 sal_Bool bRet
= sal_False
;
521 /* duplicate handle on this other side ->
522 receive remote process
523 duplicate handle and send it */
524 DWORD remoteProcessID
= 0;
525 HANDLE fd
= (HANDLE
)pSocket
->m_Socket
;
526 oslDescriptorType code
= osl_Process_TypeSocket
;
528 OSL_TRACE("osl_sendResourcePipe: enter...");
530 if (ReadPipe(hPipe
, &remoteProcessID
, sizeof(remoteProcessID
), &bytes
))
532 HANDLE hRemoteProc
= OpenProcess(PROCESS_DUP_HANDLE
,
536 if (hRemoteProc
!= (HANDLE
)NULL
)
540 if (DuplicateHandle(GetCurrentProcess(),
544 0, FALSE
, DUPLICATE_SAME_ACCESS
))
547 WritePipe(hPipe
, &code
, sizeof(code
), &bytes
) &&
548 WritePipe(hPipe
, &newFd
, sizeof(fd
), &bytes
)
553 CloseHandle(hRemoteProc
);
559 sal_Int32 commitCode
;
560 OSL_TRACE("osl_sendResourcePipe: handle sent successfully, verify...\n");
563 !ReadPipe(hPipe
, &commitCode
, sizeof(commitCode
), &bytes
) ||
569 OSL_TRACE("osl_sendResourcePipe: exit... %d\n", bRet
);
574 oslSocket SAL_CALL
osl_receiveResourcePipe(oslPipe hPipe
)
576 sal_Bool bRet
= sal_False
;
578 sal_Int32 commitCode
;
579 oslSocket pSocket
= NULL
;
581 /* duplicate handle on the other side ->
582 send my process id receive duplicated handle */
583 HANDLE fd
= INVALID_HANDLE_VALUE
;
584 DWORD myProcessID
= GetCurrentProcessId();
585 oslDescriptorType code
= osl_Process_TypeNone
;
587 OSL_TRACE("osl_receiveResourcePipe: enter...\n");
590 WritePipe(hPipe
, &myProcessID
, sizeof(myProcessID
), &bytes
) &&
591 ReadPipe(hPipe
, &code
, sizeof(code
), &bytes
) &&
592 ReadPipe(hPipe
, &fd
, sizeof(fd
), &bytes
)
595 if (code
== osl_Process_TypeSocket
)
597 pSocket
= __osl_createSocketImpl((SOCKET
)fd
);
602 OSL_TRACE("osl_receiveResourcePipe: UKNOWN\n");
612 WritePipe(hPipe
, &commitCode
, sizeof(commitCode
), &bytes
);
614 OSL_TRACE("osl_receiveResourcePipe: exit... %d, %p\n", bRet
, pSocket
);