merge the formfield patch from ooo-build
[ooovba.git] / sal / osl / w32 / process.c
blobcd61d936944aad8589ae2afefbb8ac63b7ab2e3e
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: process.c,v $
10 * $Revision: 1.35 $
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 ************************************************************************/
31 #define UNICODE
32 #include "system.h"
33 #ifdef _MSC_VER
34 #pragma warning(push,1) /* disable warnings within system headers */
35 #endif
36 #include <shellapi.h>
37 #ifdef _MSC_VER
38 #pragma warning(pop)
39 #endif
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>
47 #include "procimpl.h"
48 #include "sockimpl.h"
49 #include <rtl/ustrbuf.h>
50 #include <rtl/alloc.h>
52 /***************************************************************************
53 * Process.
54 ***************************************************************************/
56 oslProcessError SAL_CALL osl_terminateProcess(oslProcess Process)
58 if (Process == NULL)
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);
76 if (hProcess)
78 pProcImpl = rtl_allocateMemory(sizeof(oslProcessImpl));
79 pProcImpl->m_hProcess = hProcess;
80 pProcImpl->m_IdProcess = Ident;
82 else
83 pProcImpl = NULL;
85 return (pProcImpl);
88 /***************************************************************************/
90 void SAL_CALL osl_freeProcessHandle(oslProcess Process)
92 if (Process != NULL)
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)
105 HANDLE hProcess;
106 DWORD IdProcess;
108 if (Process == NULL)
110 hProcess = GetCurrentProcess();
111 IdProcess = GetCurrentProcessId();
113 else
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;
122 pInfo->Fields = 0;
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)
138 void* lpAddress=0;
139 MEMORY_BASIC_INFORMATION Info;
141 pInfo->HeapUsage = 0;
145 if (VirtualQueryEx(hProcess, lpAddress, &Info, sizeof(Info)) == 0)
146 break;
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))
165 __int64 Value;
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;
195 DWORD ret;
197 if (NULL == Process)
198 return osl_Process_E_Unknown;
200 if (pTimeout)
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;
210 return osl_error;
213 /***************************************************************************
214 * osl_bootstrap_getExecutableFile_Impl().
216 * @internal
217 * @see rtl_bootstrap
218 * @see #i37371#
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];
229 DWORD buflen;
231 if ((buflen = GetModuleFileNameW (0, buffer, MAX_PATH)) > 0)
233 rtl_uString * pAbsPath = 0;
234 rtl_uString_newFromStr_WithLength (&(pAbsPath), buffer, buflen);
235 if (pAbsPath)
237 /* Convert from path to url. */
238 if (osl_getFileURLFromSystemPath (pAbsPath, ppFileURL) == osl_File_E_None)
240 /* Success. */
241 result = osl_Process_E_None;
243 rtl_uString_release (pAbsPath);
247 return (result);
250 /***************************************************************************
251 * Command Line Arguments.
252 ***************************************************************************/
254 struct CommandArgs_Impl
256 sal_uInt32 m_nCount;
257 rtl_uString ** m_ppArgs;
260 static struct CommandArgs_Impl g_command_args =
266 #ifdef _MSC_VER
267 #pragma warning( push )
268 #pragma warning( disable: 4100 )
269 #endif
270 static rtl_uString ** osl_createCommandArgs_Impl (int argc, char ** argv)
272 rtl_uString ** ppArgs =
273 (rtl_uString**)rtl_allocateZeroMemory (argc * sizeof(rtl_uString*));
274 if (ppArgs != 0)
276 int i;
277 int nArgs;
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] );
285 if (ppArgs[0] != 0)
287 /* Ensure absolute path */
288 DWORD dwResult;
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);
300 if (ppArgs[0] != 0)
302 /* Convert to FileURL, see @ osl_getExecutableFile() */
303 rtl_uString * pResult = 0;
304 osl_getFileURLFromSystemPath (ppArgs[0], &pResult);
305 if (pResult != 0)
307 rtl_uString_assign (&(ppArgs[0]), pResult);
308 rtl_uString_release (pResult);
312 return (ppArgs);
315 #ifdef _MSC_VER
316 #pragma warning( pop )
317 #endif
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());
334 return (result);
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());
351 return (result);
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());
369 return (result);
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);
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 ***************************************************************************/
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];
422 DWORD dwLen;
425 osl_acquireMutex( g_CurrentDirectoryMutex );
426 dwLen = GetCurrentDirectory( sizeof(szBuffer) / sizeof(TCHAR), szBuffer );
427 osl_releaseMutex( g_CurrentDirectoryMutex );
429 if ( dwLen )
431 oslFileError eError;
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;
441 else
442 return osl_Process_E_None;
444 else
445 return osl_Process_E_Unknown;
448 /***************************************************************************
449 * Process Locale.
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,
495 void* pBuffer,
496 sal_Int32 BytesToRead,
497 sal_Int32* nBytes)
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,
506 void* pBuffer,
507 sal_Int32 BytesToSend,
508 sal_Int32* nBytes)
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;
519 sal_Int32 bytes = 0;
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,
533 FALSE,
534 remoteProcessID);
536 if (hRemoteProc != (HANDLE)NULL)
538 HANDLE newFd;
540 if (DuplicateHandle(GetCurrentProcess(),
541 fd,
542 hRemoteProc,
543 &newFd,
544 0, FALSE, DUPLICATE_SAME_ACCESS))
546 if (
547 WritePipe(hPipe, &code, sizeof(code), &bytes) &&
548 WritePipe(hPipe, &newFd, sizeof(fd), &bytes)
550 bRet = sal_True;
553 CloseHandle(hRemoteProc);
557 if (bRet)
559 sal_Int32 commitCode;
560 OSL_TRACE("osl_sendResourcePipe: handle sent successfully, verify...\n");
562 if (
563 !ReadPipe(hPipe, &commitCode, sizeof(commitCode), &bytes) ||
564 (commitCode <= 0)
566 bRet = sal_False;
569 OSL_TRACE("osl_sendResourcePipe: exit... %d\n", bRet);
570 return(bRet);
574 oslSocket SAL_CALL osl_receiveResourcePipe(oslPipe hPipe)
576 sal_Bool bRet = sal_False;
577 sal_Int32 bytes = 0;
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");
589 if (
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);
598 bRet = sal_True;
600 else
602 OSL_TRACE("osl_receiveResourcePipe: UKNOWN\n");
603 bRet = sal_False;
607 if (bRet)
608 commitCode = 1;
609 else
610 commitCode = 0;
612 WritePipe(hPipe, &commitCode, sizeof(commitCode), &bytes);
614 OSL_TRACE("osl_receiveResourcePipe: exit... %d, %p\n", bRet, pSocket);
616 return pSocket;