1 /**************************************************************
2 *
3 * Licensed to the Apache Software Foundation (ASF) under one
4 * or more contributor license agreements. See the NOTICE file
5 * distributed with this work for additional information
6 * regarding copyright ownership. The ASF licenses this file
7 * to you under the Apache License, Version 2.0 (the
8 * "License"); you may not use this file except in compliance
9 * with the License. You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing,
14 * software distributed under the License is distributed on an
15 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16 * KIND, either express or implied. See the License for the
17 * specific language governing permissions and limitations
18 * under the License.
19 *
20 *************************************************************/
21
22
23
24 #define UNICODE
25 #include "system.h"
26 #ifdef _MSC_VER
27 #pragma warning(push,1) /* disable warnings within system headers */
28 #endif
29 #include <shellapi.h>
30 #ifdef _MSC_VER
31 #pragma warning(pop)
32 #endif
33
34 #include <osl/diagnose.h>
35 #include <osl/security.h>
36 #include <osl/nlsupport.h>
37 #include <osl/mutex.h>
38 #include <osl/thread.h>
39
40 #include "procimpl.h"
41 #include "sockimpl.h"
42 #include "file_url.h"
43 #include "path_helper.hxx"
44 #include <rtl/ustrbuf.h>
45 #include <rtl/alloc.h>
46
47 /***************************************************************************
48 * Process.
49 ***************************************************************************/
50
osl_terminateProcess(oslProcess Process)51 oslProcessError SAL_CALL osl_terminateProcess(oslProcess Process)
52 {
53 if (Process == NULL)
54 return osl_Process_E_Unknown;
55
56 if (TerminateProcess(((oslProcessImpl*)Process)->m_hProcess, 0))
57 return osl_Process_E_None;
58
59
60 return osl_Process_E_Unknown;
61 }
62
63 /***************************************************************************/
64
osl_getProcess(oslProcessIdentifier Ident)65 oslProcess SAL_CALL osl_getProcess(oslProcessIdentifier Ident)
66 {
67 oslProcessImpl* pProcImpl;
68 HANDLE hProcess = OpenProcess(
69 STANDARD_RIGHTS_REQUIRED | PROCESS_QUERY_INFORMATION | SYNCHRONIZE, FALSE, (DWORD)Ident);
70
71 if (hProcess)
72 {
73 pProcImpl = reinterpret_cast< oslProcessImpl*>( rtl_allocateMemory(sizeof(oslProcessImpl)) );
74 pProcImpl->m_hProcess = hProcess;
75 pProcImpl->m_IdProcess = Ident;
76 }
77 else
78 pProcImpl = NULL;
79
80 return (pProcImpl);
81 }
82
83 /***************************************************************************/
84
osl_freeProcessHandle(oslProcess Process)85 void SAL_CALL osl_freeProcessHandle(oslProcess Process)
86 {
87 if (Process != NULL)
88 {
89 CloseHandle(((oslProcessImpl*)Process)->m_hProcess);
90
91 rtl_freeMemory((oslProcessImpl*)Process);
92 }
93 }
94
95 /***************************************************************************/
96
osl_getProcessInfo(oslProcess Process,oslProcessData Fields,oslProcessInfo * pInfo)97 oslProcessError SAL_CALL osl_getProcessInfo(oslProcess Process, oslProcessData Fields,
98 oslProcessInfo* pInfo)
99 {
100 HANDLE hProcess;
101 DWORD IdProcess;
102
103 if (Process == NULL)
104 {
105 hProcess = GetCurrentProcess();
106 IdProcess = GetCurrentProcessId();
107 }
108 else
109 {
110 hProcess = ((oslProcessImpl*)Process)->m_hProcess;
111 IdProcess = ((oslProcessImpl*)Process)->m_IdProcess;
112 }
113
114 if (! pInfo || (pInfo->Size != sizeof(oslProcessInfo)))
115 return osl_Process_E_Unknown;
116
117 pInfo->Fields = 0;
118
119 if (Fields & osl_Process_IDENTIFIER)
120 {
121 pInfo->Ident = IdProcess;
122 pInfo->Fields |= osl_Process_IDENTIFIER;
123 }
124
125 if (Fields & osl_Process_EXITCODE)
126 {
127 if (GetExitCodeProcess(hProcess, &(pInfo->Code)) && (pInfo->Code != STILL_ACTIVE))
128 pInfo->Fields |= osl_Process_EXITCODE;
129 }
130
131 if (Fields & osl_Process_HEAPUSAGE)
132 {
133 void* lpAddress=0;
134 MEMORY_BASIC_INFORMATION Info;
135
136 pInfo->HeapUsage = 0;
137
138 do
139 {
140 if (VirtualQueryEx(hProcess, lpAddress, &Info, sizeof(Info)) == 0)
141 break;
142
143 if ((Info.State == MEM_COMMIT) && (Info.Type == MEM_PRIVATE))
144 pInfo->HeapUsage += Info.RegionSize;
145
146 lpAddress = (LPBYTE)lpAddress + Info.RegionSize;
147 }
148 while (lpAddress < (void *)0x80000000); // 2GB address space
149
150 pInfo->Fields |= osl_Process_HEAPUSAGE;
151 }
152
153 if (Fields & osl_Process_CPUTIMES)
154 {
155 FILETIME CreationTime, ExitTime, KernelTime, UserTime;
156
157 if (GetProcessTimes(hProcess, &CreationTime, &ExitTime,
158 &KernelTime, &UserTime))
159 {
160 __int64 Value;
161
162 Value = *((__int64 *)&UserTime);
163 pInfo->UserTime.Seconds = (unsigned long) (Value / 10000000L);
164 pInfo->UserTime.Nanosec = (unsigned long)((Value % 10000000L) * 100);
165
166 Value = *((__int64 *)&KernelTime);
167 pInfo->SystemTime.Seconds = (unsigned long) (Value / 10000000L);
168 pInfo->SystemTime.Nanosec = (unsigned long)((Value % 10000000L) * 100);
169
170 pInfo->Fields |= osl_Process_CPUTIMES;
171 }
172 }
173
174 return (pInfo->Fields == Fields) ? osl_Process_E_None : osl_Process_E_Unknown;
175 }
176
177 /***************************************************************************/
178
osl_joinProcess(oslProcess Process)179 oslProcessError SAL_CALL osl_joinProcess(oslProcess Process)
180 {
181 return osl_joinProcessWithTimeout(Process, NULL);
182 }
183
184 /***************************************************************************/
185
osl_joinProcessWithTimeout(oslProcess Process,const TimeValue * pTimeout)186 oslProcessError SAL_CALL osl_joinProcessWithTimeout(oslProcess Process, const TimeValue* pTimeout)
187 {
188 DWORD timeout = INFINITE;
189 oslProcessError osl_error = osl_Process_E_None;
190 DWORD ret;
191
192 if (NULL == Process)
193 return osl_Process_E_Unknown;
194
195 if (pTimeout)
196 timeout = pTimeout->Seconds * 1000 + pTimeout->Nanosec / 1000000L;
197
198 ret = WaitForSingleObject(((oslProcessImpl*)Process)->m_hProcess, timeout);
199
200 if (WAIT_FAILED == ret)
201 osl_error = osl_Process_E_Unknown;
202 else if (WAIT_TIMEOUT == ret)
203 osl_error = osl_Process_E_TimedOut;
204
205 return osl_error;
206 }
207
208 /***************************************************************************
209 * osl_bootstrap_getExecutableFile_Impl().
210 *
211 * @internal
212 * @see rtl_bootstrap
213 * @see #i37371#
214 *
215 ***************************************************************************/
216
osl_bootstrap_getExecutableFile_Impl(rtl_uString ** ppFileURL)217 extern "C" oslProcessError SAL_CALL osl_bootstrap_getExecutableFile_Impl (
218 rtl_uString ** ppFileURL
219 ) SAL_THROW_EXTERN_C()
220 {
221 oslProcessError result = osl_Process_E_NotFound;
222
223 ::osl::LongPathBuffer< sal_Unicode > aBuffer( MAX_LONG_PATH );
224 DWORD buflen = 0;
225
226 if ((buflen = GetModuleFileNameW (0, ::osl::mingw_reinterpret_cast<LPWSTR>(aBuffer), aBuffer.getBufSizeInSymbols())) > 0)
227 {
228 rtl_uString * pAbsPath = 0;
229 rtl_uString_newFromStr_WithLength (&(pAbsPath), aBuffer, buflen);
230 if (pAbsPath)
231 {
232 /* Convert from path to url. */
233 if (osl_getFileURLFromSystemPath (pAbsPath, ppFileURL) == osl_File_E_None)
234 {
235 /* Success. */
236 result = osl_Process_E_None;
237 }
238 rtl_uString_release (pAbsPath);
239 }
240 }
241
242 return (result);
243 }
244
245 /***************************************************************************
246 * Command Line Arguments.
247 ***************************************************************************/
248
249 struct CommandArgs_Impl
250 {
251 sal_uInt32 m_nCount;
252 rtl_uString ** m_ppArgs;
253 };
254
255 static struct CommandArgs_Impl g_command_args =
256 {
257 0,
258 0
259 };
260
261 #ifdef _MSC_VER
262 #pragma warning( push )
263 #pragma warning( disable: 4100 )
264 #endif
osl_createCommandArgs_Impl(int argc,char ** argv)265 static rtl_uString ** osl_createCommandArgs_Impl (int argc, char ** argv)
266 {
267 rtl_uString ** ppArgs =
268 (rtl_uString**)rtl_allocateZeroMemory (argc * sizeof(rtl_uString*));
269 if (ppArgs != 0)
270 {
271 int i;
272 int nArgs;
273 LPWSTR *wargv = CommandLineToArgvW( GetCommandLineW(), &nArgs );
274 OSL_ASSERT( nArgs == argc );
275 for (i = 0; i < nArgs; i++)
276 {
277 /* Convert to unicode */
278 rtl_uString_newFromStr( &(ppArgs[i]), reinterpret_cast<const sal_Unicode*>(wargv[i]) );
279 }
280 if (ppArgs[0] != 0)
281 {
282 /* Ensure absolute path */
283 ::osl::LongPathBuffer< sal_Unicode > aBuffer( MAX_LONG_PATH );
284 DWORD dwResult = 0;
285
286 dwResult = SearchPath (
287 0, reinterpret_cast<LPCWSTR>(ppArgs[0]->buffer), L".exe", aBuffer.getBufSizeInSymbols(), ::osl::mingw_reinterpret_cast<LPWSTR>(aBuffer), 0);
288 if ((0 < dwResult) && (dwResult < aBuffer.getBufSizeInSymbols()))
289 {
290 /* Replace argv[0] with it's absolute path */
291 rtl_uString_newFromStr_WithLength(
292 &(ppArgs[0]), aBuffer, dwResult);
293 }
294 }
295 if (ppArgs[0] != 0)
296 {
297 /* Convert to FileURL, see @ osl_getExecutableFile() */
298 rtl_uString * pResult = 0;
299 osl_getFileURLFromSystemPath (ppArgs[0], &pResult);
300 if (pResult != 0)
301 {
302 rtl_uString_assign (&(ppArgs[0]), pResult);
303 rtl_uString_release (pResult);
304 }
305 }
306 }
307 return (ppArgs);
308
309 }
310 #ifdef _MSC_VER
311 #pragma warning( pop )
312 #endif
313
314 /***************************************************************************/
315
osl_getExecutableFile(rtl_uString ** ppustrFile)316 oslProcessError SAL_CALL osl_getExecutableFile( rtl_uString **ppustrFile )
317 {
318 oslProcessError result = osl_Process_E_NotFound;
319
320 osl_acquireMutex (*osl_getGlobalMutex());
321 OSL_ASSERT(g_command_args.m_nCount > 0);
322 if (g_command_args.m_nCount > 0)
323 {
324 /* CommandArgs set. Obtain arv[0]. */
325 rtl_uString_assign (ppustrFile, g_command_args.m_ppArgs[0]);
326 result = osl_Process_E_None;
327 }
328 osl_releaseMutex (*osl_getGlobalMutex());
329
330 return (result);
331 }
332
333 /***************************************************************************/
334
osl_getCommandArgCount(void)335 sal_uInt32 SAL_CALL osl_getCommandArgCount(void)
336 {
337 sal_uInt32 result = 0;
338
339 osl_acquireMutex (*osl_getGlobalMutex());
340 OSL_ASSERT(g_command_args.m_nCount > 0);
341 if (g_command_args.m_nCount > 0)
342 {
343 /* We're not counting argv[0] here. */
344 result = g_command_args.m_nCount - 1;
345 }
346 osl_releaseMutex (*osl_getGlobalMutex());
347
348 return (result);
349 }
350
351 /***************************************************************************/
352
osl_getCommandArg(sal_uInt32 nArg,rtl_uString ** strCommandArg)353 oslProcessError SAL_CALL osl_getCommandArg( sal_uInt32 nArg, rtl_uString **strCommandArg)
354 {
355 oslProcessError result = osl_Process_E_NotFound;
356
357 osl_acquireMutex (*osl_getGlobalMutex());
358 OSL_ASSERT(g_command_args.m_nCount > 0);
359 if (g_command_args.m_nCount > (nArg + 1))
360 {
361 /* We're not counting argv[0] here. */
362 rtl_uString_assign (strCommandArg, g_command_args.m_ppArgs[nArg + 1]);
363 result = osl_Process_E_None;
364 }
365 osl_releaseMutex (*osl_getGlobalMutex());
366
367 return (result);
368 }
369
370 /***************************************************************************/
371
osl_setCommandArgs(int argc,char ** argv)372 void SAL_CALL osl_setCommandArgs (int argc, char ** argv)
373 {
374 OSL_ASSERT(argc > 0);
375 osl_acquireMutex (*osl_getGlobalMutex());
376 if (g_command_args.m_nCount == 0)
377 {
378 rtl_uString** ppArgs = osl_createCommandArgs_Impl (argc, argv);
379 if (ppArgs != 0)
380 {
381 g_command_args.m_nCount = argc;
382 g_command_args.m_ppArgs = ppArgs;
383 }
384 }
385 osl_releaseMutex (*osl_getGlobalMutex());
386 }
387
388 /***************************************************************************
389 * Environment
390 ***************************************************************************/
391 #define ENV_BUFFER_SIZE (32*1024-1)
392
osl_getEnvironment(rtl_uString * ustrVar,rtl_uString ** ustrValue)393 oslProcessError SAL_CALL osl_getEnvironment(rtl_uString *ustrVar, rtl_uString **ustrValue)
394 {
395 WCHAR buff[ENV_BUFFER_SIZE];
396
397 if (GetEnvironmentVariableW(reinterpret_cast<LPCWSTR>(ustrVar->buffer), buff, ENV_BUFFER_SIZE) > 0)
398 {
399 rtl_uString_newFromStr(ustrValue, reinterpret_cast<const sal_Unicode*>(buff));
400 return osl_Process_E_None;
401 }
402 return osl_Process_E_Unknown;
403 }
404
osl_setEnvironment(rtl_uString * ustrVar,rtl_uString * ustrValue)405 oslProcessError SAL_CALL osl_setEnvironment(rtl_uString *ustrVar, rtl_uString *ustrValue)
406 {
407 // set Windows environment variable
408 LPCWSTR lpName = reinterpret_cast<LPCWSTR>(ustrVar->buffer);
409 LPCWSTR lpValue = reinterpret_cast<LPCWSTR>(ustrValue->buffer);
410 if( !SetEnvironmentVariableW( lpName, lpValue))
411 return osl_Process_E_Unknown;
412
413 // also set the variable in the crt environment
414 _wputenv_s( lpName, lpValue);
415 return osl_Process_E_None;
416 }
417
osl_clearEnvironment(rtl_uString * ustrVar)418 oslProcessError SAL_CALL osl_clearEnvironment(rtl_uString *ustrVar)
419 {
420 // delete the variable from the current process environment
421 // by setting SetEnvironmentVariable's second parameter to NULL
422 LPCWSTR lpName = reinterpret_cast<LPCWSTR>(ustrVar->buffer);
423 if( !SetEnvironmentVariableW( lpName, NULL))
424 return osl_Process_E_Unknown;
425
426 // also remove the variable from the crt environment
427 wchar_t aEmptyName = 0;
428 _wputenv_s( lpName, &aEmptyName);
429 return osl_Process_E_None;
430 }
431
432 /***************************************************************************
433 * Current Working Directory.
434 ***************************************************************************/
435
436 extern "C" oslMutex g_CurrentDirectoryMutex;
437
osl_getProcessWorkingDir(rtl_uString ** pustrWorkingDir)438 oslProcessError SAL_CALL osl_getProcessWorkingDir( rtl_uString **pustrWorkingDir )
439 {
440 ::osl::LongPathBuffer< sal_Unicode > aBuffer( MAX_LONG_PATH );
441 DWORD dwLen = 0;
442
443
444 osl_acquireMutex( g_CurrentDirectoryMutex );
445 dwLen = GetCurrentDirectory( aBuffer.getBufSizeInSymbols(), ::osl::mingw_reinterpret_cast<LPWSTR>(aBuffer) );
446 osl_releaseMutex( g_CurrentDirectoryMutex );
447
448 if ( dwLen && dwLen < aBuffer.getBufSizeInSymbols() )
449 {
450 oslFileError eError;
451 rtl_uString *ustrTemp = NULL;;
452
453 rtl_uString_newFromStr_WithLength( &ustrTemp, aBuffer, dwLen );
454 eError = osl_getFileURLFromSystemPath( ustrTemp, pustrWorkingDir );
455
456 rtl_uString_release( ustrTemp );
457
458 if ( osl_File_E_None != eError )
459 return osl_Process_E_Unknown;
460 else
461 return osl_Process_E_None;
462 }
463 else
464 return osl_Process_E_Unknown;
465 }
466
467 /***************************************************************************
468 * Process Locale.
469 ***************************************************************************/
470
471 extern "C" void _imp_getProcessLocale( rtl_Locale ** ppLocale );
472
473 static rtl_Locale * g_theProcessLocale = NULL;
474
475 /***************************************************************************/
476
osl_getProcessLocale(rtl_Locale ** ppLocale)477 oslProcessError SAL_CALL osl_getProcessLocale( rtl_Locale ** ppLocale )
478 {
479 osl_acquireMutex( *osl_getGlobalMutex() );
480
481 /* determine the users default locale */
482 if( NULL == g_theProcessLocale )
483 _imp_getProcessLocale( &g_theProcessLocale );
484
485 /* or return the cached value */
486 *ppLocale = g_theProcessLocale;
487
488 osl_releaseMutex( *osl_getGlobalMutex() );
489 return osl_Process_E_None;
490 }
491
492 /***************************************************************************/
493
osl_setProcessLocale(rtl_Locale * pLocale)494 oslProcessError SAL_CALL osl_setProcessLocale( rtl_Locale * pLocale )
495 {
496 osl_acquireMutex( *osl_getGlobalMutex() );
497
498 /* check if locale is supported */
499 if( RTL_TEXTENCODING_DONTKNOW == osl_getTextEncodingFromLocale( pLocale ) )
500 return osl_Process_E_Unknown;
501
502 /* just remember the locale here */
503 g_theProcessLocale = pLocale;
504
505 osl_releaseMutex( *osl_getGlobalMutex() );
506 return osl_Process_E_None;
507 }
508
509 /************************************************
510 * Portal send/receive interface implementation
511 ************************************************/
512
ReadPipe(oslPipe hPipe,void * pBuffer,sal_Int32 BytesToRead,sal_Int32 * nBytes)513 static sal_Bool ReadPipe(oslPipe hPipe,
514 void* pBuffer,
515 sal_Int32 BytesToRead,
516 sal_Int32* nBytes)
517 {
518 *nBytes = osl_receivePipe(hPipe, pBuffer, BytesToRead);
519 OSL_TRACE("tried to receive %d, received %d.\n",
520 BytesToRead, *nBytes);
521 return (sal_Bool)((*nBytes >= 0) && (osl_getLastPipeError(hPipe) == osl_Pipe_E_None));
522 }
523
WritePipe(oslPipe hPipe,void * pBuffer,sal_Int32 BytesToSend,sal_Int32 * nBytes)524 static sal_Bool WritePipe(oslPipe hPipe,
525 void* pBuffer,
526 sal_Int32 BytesToSend,
527 sal_Int32* nBytes)
528 {
529 *nBytes = osl_sendPipe(hPipe, pBuffer, BytesToSend);
530 OSL_TRACE("tried to send %d, sent %d\n",
531 BytesToSend, *nBytes);
532 return (sal_Bool)((*nBytes == BytesToSend) && (osl_getLastPipeError(hPipe) == osl_Pipe_E_None));
533 }
534
osl_sendResourcePipe(oslPipe hPipe,oslSocket pSocket)535 sal_Bool SAL_CALL osl_sendResourcePipe(oslPipe hPipe, oslSocket pSocket)
536 {
537 sal_Bool bRet = sal_False;
538 sal_Int32 bytes = 0;
539
540 /* duplicate handle on this other side ->
541 receive remote process
542 duplicate handle and send it */
543 DWORD remoteProcessID = 0;
544 HANDLE fd = (HANDLE)pSocket->m_Socket;
545 oslDescriptorType code = osl_Process_TypeSocket;
546
547 OSL_TRACE("osl_sendResourcePipe: enter...");
548
549 if (ReadPipe(hPipe, &remoteProcessID, sizeof(remoteProcessID), &bytes))
550 {
551 HANDLE hRemoteProc = OpenProcess(PROCESS_DUP_HANDLE,
552 FALSE,
553 remoteProcessID);
554
555 if (hRemoteProc != (HANDLE)NULL)
556 {
557 HANDLE newFd;
558
559 if (DuplicateHandle(GetCurrentProcess(),
560 fd,
561 hRemoteProc,
562 &newFd,
563 0, FALSE, DUPLICATE_SAME_ACCESS))
564 {
565 if (
566 WritePipe(hPipe, &code, sizeof(code), &bytes) &&
567 WritePipe(hPipe, &newFd, sizeof(fd), &bytes)
568 )
569 bRet = sal_True;
570 }
571
572 CloseHandle(hRemoteProc);
573 }
574 }
575
576 if (bRet)
577 {
578 sal_Int32 commitCode;
579 OSL_TRACE("osl_sendResourcePipe: handle sent successfully, verify...\n");
580
581 if (
582 !ReadPipe(hPipe, &commitCode, sizeof(commitCode), &bytes) ||
583 (commitCode <= 0)
584 )
585 bRet = sal_False;
586 }
587
588 OSL_TRACE("osl_sendResourcePipe: exit... %d\n", bRet);
589 return(bRet);
590 }
591
592
osl_receiveResourcePipe(oslPipe hPipe)593 oslSocket SAL_CALL osl_receiveResourcePipe(oslPipe hPipe)
594 {
595 sal_Bool bRet = sal_False;
596 sal_Int32 bytes = 0;
597 sal_Int32 commitCode;
598 oslSocket pSocket = NULL;
599
600 /* duplicate handle on the other side ->
601 send my process id receive duplicated handle */
602 HANDLE fd = INVALID_HANDLE_VALUE;
603 DWORD myProcessID = GetCurrentProcessId();
604 oslDescriptorType code = osl_Process_TypeNone;
605
606 OSL_TRACE("osl_receiveResourcePipe: enter...\n");
607
608 if (
609 WritePipe(hPipe, &myProcessID, sizeof(myProcessID), &bytes) &&
610 ReadPipe(hPipe, &code, sizeof(code), &bytes) &&
611 ReadPipe(hPipe, &fd, sizeof(fd), &bytes)
612 )
613 {
614 if (code == osl_Process_TypeSocket)
615 {
616 pSocket = __osl_createSocketImpl((SOCKET)fd);
617 bRet = sal_True;
618 }
619 else
620 {
621 OSL_TRACE("osl_receiveResourcePipe: UKNOWN\n");
622 bRet = sal_False;
623 }
624 }
625
626 if (bRet)
627 commitCode = 1;
628 else
629 commitCode = 0;
630
631 WritePipe(hPipe, &commitCode, sizeof(commitCode), &bytes);
632
633 OSL_TRACE("osl_receiveResourcePipe: exit... %d, %p\n", bRet, pSocket);
634
635 return pSocket;
636 }
637