Line data Source code
1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /*
3 : * This file is part of the LibreOffice project.
4 : *
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/.
8 : *
9 : * This file incorporates work covered by the following license notice:
10 : *
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 .
18 : */
19 :
20 : #include "rtl/logfile.hxx"
21 :
22 : #include <osl/file.hxx>
23 : #include <osl/signal.h>
24 :
25 : #include "tools/debug.hxx"
26 : #include "tools/resmgr.hxx"
27 :
28 : #include "comphelper/processfactory.hxx"
29 :
30 : #include "unotools/syslocaleoptions.hxx"
31 : #include "vcl/svapp.hxx"
32 : #include "vcl/wrkwin.hxx"
33 : #include "vcl/cvtgrf.hxx"
34 : #include "vcl/image.hxx"
35 : #include "vcl/settings.hxx"
36 : #include "vcl/unowrap.hxx"
37 : #include "vcl/configsettings.hxx"
38 : #include "vcl/lazydelete.hxx"
39 : #include "vcl/embeddedfontshelper.hxx"
40 :
41 : #ifdef WNT
42 : #include <svsys.h>
43 : #include <process.h>
44 : #include <ole2.h>
45 : #endif
46 :
47 : #ifdef ANDROID
48 : #include <cppuhelper/bootstrap.hxx>
49 : #include <jni.h>
50 : #endif
51 :
52 : #include "salinst.hxx"
53 : #include "salwtype.hxx"
54 : #include "svdata.hxx"
55 : #include "svmain.hxx"
56 : #include "dbggui.hxx"
57 : #include "accmgr.hxx"
58 : #include "idlemgr.hxx"
59 : #include "outdev.h"
60 : #include "outfont.hxx"
61 : #include "PhysicalFontCollection.hxx"
62 : #include "print.h"
63 : #include "salsys.hxx"
64 : #include "saltimer.hxx"
65 : #include "salimestatus.hxx"
66 : #include "impimagetree.hxx"
67 : #include "xconnection.hxx"
68 :
69 : #include "osl/process.h"
70 : #include "com/sun/star/lang/XMultiServiceFactory.hpp"
71 : #include "com/sun/star/lang/XComponent.hpp"
72 : #include "com/sun/star/frame/Desktop.hpp"
73 :
74 : #include "cppuhelper/implbase1.hxx"
75 : #include "uno/current_context.hxx"
76 :
77 : #if OSL_DEBUG_LEVEL > 0
78 : #include <typeinfo>
79 : #include "rtl/strbuf.hxx"
80 : #endif
81 :
82 : using namespace ::com::sun::star;
83 :
84 0 : oslSignalAction SAL_CALL VCLExceptionSignal_impl( void* /*pData*/, oslSignalInfo* pInfo)
85 : {
86 : static bool bIn = false;
87 :
88 : // if we crash again, bail out immediately
89 0 : if ( !bIn )
90 : {
91 0 : sal_uInt16 nVCLException = 0;
92 :
93 : // UAE
94 0 : if ( (pInfo->Signal == osl_Signal_AccessViolation) ||
95 0 : (pInfo->Signal == osl_Signal_IntegerDivideByZero) ||
96 0 : (pInfo->Signal == osl_Signal_FloatDivideByZero) ||
97 0 : (pInfo->Signal == osl_Signal_DebugBreak) )
98 0 : nVCLException = EXC_SYSTEM;
99 :
100 : // RC
101 0 : if ((pInfo->Signal == osl_Signal_User) &&
102 0 : (pInfo->UserSignal == OSL_SIGNAL_USER_RESOURCEFAILURE) )
103 0 : nVCLException = EXC_RSCNOTLOADED;
104 :
105 : // DISPLAY-Unix
106 0 : if ((pInfo->Signal == osl_Signal_User) &&
107 0 : (pInfo->UserSignal == OSL_SIGNAL_USER_X11SUBSYSTEMERROR) )
108 0 : nVCLException = EXC_DISPLAY;
109 :
110 : // Remote-Client
111 0 : if ((pInfo->Signal == osl_Signal_User) &&
112 0 : (pInfo->UserSignal == OSL_SIGNAL_USER_RVPCONNECTIONERROR) )
113 0 : nVCLException = EXC_REMOTE;
114 :
115 0 : if ( nVCLException )
116 : {
117 0 : bIn = true;
118 :
119 0 : SolarMutexGuard aLock;
120 :
121 : // do not stop timer because otherwise the UAE-Box will not be painted as well
122 0 : ImplSVData* pSVData = ImplGetSVData();
123 0 : if ( pSVData->mpApp )
124 : {
125 0 : sal_uInt16 nOldMode = Application::GetSystemWindowMode();
126 0 : Application::SetSystemWindowMode( nOldMode & ~SYSTEMWINDOW_MODE_NOAUTOMODE );
127 0 : pSVData->mpApp->Exception( nVCLException );
128 0 : Application::SetSystemWindowMode( nOldMode );
129 : }
130 0 : bIn = false;
131 :
132 0 : return osl_Signal_ActCallNextHdl;
133 : }
134 : }
135 :
136 0 : return osl_Signal_ActCallNextHdl;
137 :
138 : }
139 :
140 1 : int ImplSVMain()
141 : {
142 : // The 'real' SVMain()
143 1 : ImplSVData* pSVData = ImplGetSVData();
144 :
145 : DBG_ASSERT( pSVData->mpApp, "no instance of class Application" );
146 :
147 1 : int nReturn = EXIT_FAILURE;
148 :
149 1 : bool bInit = InitVCL();
150 :
151 1 : if( bInit )
152 : {
153 : // call application main
154 1 : pSVData->maAppData.mbInAppMain = true;
155 1 : nReturn = pSVData->mpApp->Main();
156 1 : pSVData->maAppData.mbInAppMain = false;
157 : }
158 :
159 1 : if( pSVData->mxDisplayConnection.is() )
160 : {
161 0 : pSVData->mxDisplayConnection->terminate();
162 0 : pSVData->mxDisplayConnection.clear();
163 : }
164 :
165 : // This is a hack to work around the problem of the asynchronous nature
166 : // of bridging accessibility through Java: on shutdown there might still
167 : // be some events in the AWT EventQueue, which need the SolarMutex which
168 : // - on the other hand - is destroyed in DeInitVCL(). So empty the queue
169 : // here ..
170 1 : if( pSVData->mxAccessBridge.is() )
171 : {
172 0 : sal_uLong nCount = Application::ReleaseSolarMutex();
173 0 : pSVData->mxAccessBridge->dispose();
174 0 : Application::AcquireSolarMutex(nCount);
175 0 : pSVData->mxAccessBridge.clear();
176 : }
177 :
178 1 : DeInitVCL();
179 1 : return nReturn;
180 : }
181 :
182 1 : int SVMain()
183 : {
184 : int nRet;
185 1 : if( !Application::IsConsoleOnly() && ImplSVMainHook( &nRet ) )
186 0 : return nRet;
187 : else
188 1 : return ImplSVMain();
189 : }
190 :
191 : // This variable is set when no Application object has been instantiated
192 : // before InitVCL is called
193 : static Application * pOwnSvApp = NULL;
194 :
195 : // Exception handler. pExceptionHandler != NULL => VCL already inited
196 : oslSignalHandler pExceptionHandler = NULL;
197 :
198 0 : class DummyApplication : public Application
199 : {
200 : public:
201 0 : int Main() SAL_OVERRIDE { return EXIT_SUCCESS; };
202 : };
203 :
204 0 : class DesktopEnvironmentContext: public cppu::WeakImplHelper1< com::sun::star::uno::XCurrentContext >
205 : {
206 : public:
207 1 : DesktopEnvironmentContext( const com::sun::star::uno::Reference< com::sun::star::uno::XCurrentContext > & ctx)
208 1 : : m_xNextContext( ctx ) {}
209 :
210 : // XCurrentContext
211 : virtual com::sun::star::uno::Any SAL_CALL getValueByName( const OUString& Name )
212 : throw (com::sun::star::uno::RuntimeException, std::exception) SAL_OVERRIDE;
213 :
214 : private:
215 : com::sun::star::uno::Reference< com::sun::star::uno::XCurrentContext > m_xNextContext;
216 : };
217 :
218 0 : uno::Any SAL_CALL DesktopEnvironmentContext::getValueByName( const OUString& Name) throw (uno::RuntimeException, std::exception)
219 : {
220 0 : uno::Any retVal;
221 :
222 0 : if ( Name == "system.desktop-environment" )
223 : {
224 0 : retVal = uno::makeAny( Application::GetDesktopEnvironment() );
225 : }
226 0 : else if( m_xNextContext.is() )
227 : {
228 : // Call next context in chain if found
229 0 : retVal = m_xNextContext->getValueByName( Name );
230 : }
231 0 : return retVal;
232 : }
233 :
234 1 : bool InitVCL()
235 : {
236 1 : if( pExceptionHandler != NULL )
237 0 : return false;
238 :
239 1 : EmbeddedFontsHelper::clearTemporaryFontFiles();
240 :
241 1 : if( ! ImplGetSVData() )
242 0 : ImplInitSVData();
243 :
244 1 : if( !ImplGetSVData()->mpApp )
245 : {
246 0 : pOwnSvApp = new DummyApplication();
247 : }
248 1 : InitSalMain();
249 :
250 1 : ImplSVData* pSVData = ImplGetSVData();
251 :
252 : // remember Main-Thread-Id
253 1 : pSVData->mnMainThreadId = ::osl::Thread::getCurrentIdentifier();
254 :
255 : // Initialize Sal
256 1 : pSVData->mpDefInst = CreateSalInstance();
257 1 : if ( !pSVData->mpDefInst )
258 0 : return false;
259 :
260 : // Desktop Environment context (to be able to get value of "system.desktop-environment" as soon as possible)
261 : com::sun::star::uno::setCurrentContext(
262 1 : new DesktopEnvironmentContext( com::sun::star::uno::getCurrentContext() ) );
263 :
264 : // Initialize application instance (should be done after initialization of VCL SAL part)
265 1 : if( pSVData->mpApp )
266 : // call init to initialize application class
267 : // soffice/sfx implementation creates the global service manager
268 1 : pSVData->mpApp->Init();
269 :
270 1 : pSVData->mpDefInst->AfterAppInit();
271 :
272 : // Fetch AppFileName and make it absolute before the workdir changes...
273 1 : OUString aExeFileName;
274 1 : osl_getExecutableFile( &aExeFileName.pData );
275 :
276 : // convert path to native file format
277 2 : OUString aNativeFileName;
278 1 : osl::FileBase::getSystemPathFromFileURL( aExeFileName, aNativeFileName );
279 1 : pSVData->maAppData.mpAppFileName = new OUString( aNativeFileName );
280 :
281 : // Initialize global data
282 1 : pSVData->maGDIData.mpScreenFontList = new PhysicalFontCollection;
283 1 : pSVData->maGDIData.mpScreenFontCache = new ImplFontCache;
284 1 : pSVData->maGDIData.mpGrfConverter = new GraphicConverter;
285 :
286 : // Set exception handler
287 1 : pExceptionHandler = osl_addSignalHandler(VCLExceptionSignal_impl, NULL);
288 :
289 : DBGGUI_INIT_SOLARMUTEXCHECK();
290 :
291 2 : return true;
292 : }
293 :
294 : #ifdef ANDROID
295 :
296 : extern "C" __attribute__ ((visibility("default"))) void
297 : InitVCLWrapper()
298 : {
299 : uno::Reference<uno::XComponentContext> xContext( cppu::defaultBootstrap_InitialComponentContext() );
300 : uno::Reference<lang::XMultiComponentFactory> xFactory( xContext->getServiceManager() );
301 :
302 : uno::Reference<lang::XMultiServiceFactory> xSM( xFactory, uno::UNO_QUERY_THROW );
303 :
304 : comphelper::setProcessServiceFactory( xSM );
305 :
306 : InitVCL();
307 : }
308 :
309 : #endif
310 :
311 : namespace
312 : {
313 :
314 : /** Serves for destroying the VCL UNO wrapper as late as possible. This avoids
315 : crash at exit in some special cases when a11y is enabled (e.g., when
316 : a bundled extension is registered/deregistered during startup, forcing exit
317 : while the app is still in splash screen.)
318 : */
319 0 : class VCLUnoWrapperDeleter : public cppu::WeakImplHelper1<com::sun::star::lang::XEventListener>
320 : {
321 : virtual void SAL_CALL disposing(lang::EventObject const& rSource) throw(uno::RuntimeException, std::exception) SAL_OVERRIDE;
322 : };
323 :
324 : void
325 0 : VCLUnoWrapperDeleter::disposing(lang::EventObject const& /* rSource */)
326 : throw(uno::RuntimeException, std::exception)
327 : {
328 0 : ImplSVData* const pSVData = ImplGetSVData();
329 0 : if (pSVData && pSVData->mpUnoWrapper)
330 : {
331 0 : pSVData->mpUnoWrapper->Destroy();
332 0 : pSVData->mpUnoWrapper = NULL;
333 : }
334 0 : }
335 :
336 : }
337 :
338 1 : void DeInitVCL()
339 : {
340 1 : ImplSVData* pSVData = ImplGetSVData();
341 1 : pSVData->mbDeInit = true;
342 :
343 1 : vcl::DeleteOnDeinitBase::ImplDeleteOnDeInit();
344 :
345 : // give ime status a chance to destroy its own windows
346 1 : delete pSVData->mpImeStatus;
347 1 : pSVData->mpImeStatus = NULL;
348 :
349 : #if OSL_DEBUG_LEVEL > 0
350 : OStringBuffer aBuf( 256 );
351 : aBuf.append( "DeInitVCL: some top Windows are still alive\n" );
352 : long nTopWindowCount = Application::GetTopWindowCount();
353 : long nBadTopWindows = nTopWindowCount;
354 : for( long i = 0; i < nTopWindowCount; i++ )
355 : {
356 : Window* pWin = Application::GetTopWindow( i );
357 : // default window will be destroyed further down
358 : // but may still be useful during deinit up to that point
359 : if( pWin == pSVData->mpDefaultWin )
360 : nBadTopWindows--;
361 : else
362 : {
363 : aBuf.append( "text = \"" );
364 : aBuf.append( OUStringToOString( pWin->GetText(), osl_getThreadTextEncoding() ) );
365 : aBuf.append( "\" type = \"" );
366 : aBuf.append( typeid(*pWin).name() );
367 : aBuf.append( "\", ptr = 0x" );
368 : aBuf.append( sal_Int64( pWin ), 16 );
369 : aBuf.append( "\n" );
370 : }
371 : }
372 : DBG_ASSERT( nBadTopWindows==0, aBuf.getStr() );
373 : #endif
374 :
375 1 : ImplImageTreeSingletonRef()->shutDown();
376 :
377 1 : osl_removeSignalHandler( pExceptionHandler);
378 1 : pExceptionHandler = NULL;
379 :
380 : // free global data
381 1 : delete pSVData->maGDIData.mpGrfConverter;
382 :
383 1 : if( pSVData->mpSettingsConfigItem )
384 0 : delete pSVData->mpSettingsConfigItem, pSVData->mpSettingsConfigItem = NULL;
385 :
386 1 : if ( pSVData->maAppData.mpIdleMgr )
387 0 : delete pSVData->maAppData.mpIdleMgr;
388 1 : Timer::ImplDeInitTimer();
389 :
390 1 : if ( pSVData->maWinData.mpMsgBoxImgList )
391 : {
392 0 : delete pSVData->maWinData.mpMsgBoxImgList;
393 0 : pSVData->maWinData.mpMsgBoxImgList = NULL;
394 : }
395 1 : if ( pSVData->maCtrlData.mpCheckImgList )
396 : {
397 0 : delete pSVData->maCtrlData.mpCheckImgList;
398 0 : pSVData->maCtrlData.mpCheckImgList = NULL;
399 : }
400 1 : if ( pSVData->maCtrlData.mpRadioImgList )
401 : {
402 0 : delete pSVData->maCtrlData.mpRadioImgList;
403 0 : pSVData->maCtrlData.mpRadioImgList = NULL;
404 : }
405 1 : if ( pSVData->maCtrlData.mpPinImgList )
406 : {
407 0 : delete pSVData->maCtrlData.mpPinImgList;
408 0 : pSVData->maCtrlData.mpPinImgList = NULL;
409 : }
410 1 : if ( pSVData->maCtrlData.mpSplitHPinImgList )
411 : {
412 0 : delete pSVData->maCtrlData.mpSplitHPinImgList;
413 0 : pSVData->maCtrlData.mpSplitHPinImgList = NULL;
414 : }
415 1 : if ( pSVData->maCtrlData.mpSplitVPinImgList )
416 : {
417 0 : delete pSVData->maCtrlData.mpSplitVPinImgList;
418 0 : pSVData->maCtrlData.mpSplitVPinImgList = NULL;
419 : }
420 1 : if ( pSVData->maCtrlData.mpSplitHArwImgList )
421 : {
422 0 : delete pSVData->maCtrlData.mpSplitHArwImgList;
423 0 : pSVData->maCtrlData.mpSplitHArwImgList = NULL;
424 : }
425 1 : if ( pSVData->maCtrlData.mpSplitVArwImgList )
426 : {
427 0 : delete pSVData->maCtrlData.mpSplitVArwImgList;
428 0 : pSVData->maCtrlData.mpSplitVArwImgList = NULL;
429 : }
430 1 : if ( pSVData->maCtrlData.mpDisclosurePlus )
431 : {
432 0 : delete pSVData->maCtrlData.mpDisclosurePlus;
433 0 : pSVData->maCtrlData.mpDisclosurePlus = NULL;
434 : }
435 1 : if ( pSVData->maCtrlData.mpDisclosureMinus )
436 : {
437 0 : delete pSVData->maCtrlData.mpDisclosureMinus;
438 0 : pSVData->maCtrlData.mpDisclosureMinus = NULL;
439 : }
440 1 : if ( pSVData->mpDefaultWin )
441 : {
442 0 : delete pSVData->mpDefaultWin;
443 0 : pSVData->mpDefaultWin = NULL;
444 : }
445 :
446 : DBGGUI_DEINIT_SOLARMUTEXCHECK();
447 :
448 1 : if ( pSVData->mpUnoWrapper )
449 : {
450 : try
451 : {
452 : uno::Reference<frame::XDesktop2> const xDesktop = frame::Desktop::create(
453 0 : comphelper::getProcessComponentContext() );
454 0 : xDesktop->addEventListener(new VCLUnoWrapperDeleter());
455 : }
456 0 : catch (uno::Exception const&)
457 : {
458 : // ignore
459 : }
460 : }
461 :
462 1 : if( pSVData->mpApp )
463 : {
464 1 : sal_uLong nCount = Application::ReleaseSolarMutex();
465 : // call deinit to deinitialize application class
466 : // soffice/sfx implementation disposes the global service manager
467 : // Warning: After this call you can't call uno services
468 1 : pSVData->mpApp->DeInit();
469 1 : Application::AcquireSolarMutex(nCount);
470 : }
471 :
472 1 : if ( pSVData->maAppData.mpSettings )
473 : {
474 0 : if ( pSVData->maAppData.mpCfgListener )
475 : {
476 0 : pSVData->maAppData.mpSettings->GetSysLocale().GetOptions().RemoveListener( pSVData->maAppData.mpCfgListener );
477 0 : delete pSVData->maAppData.mpCfgListener;
478 : }
479 :
480 0 : delete pSVData->maAppData.mpSettings;
481 0 : pSVData->maAppData.mpSettings = NULL;
482 : }
483 1 : if ( pSVData->maAppData.mpAccelMgr )
484 : {
485 0 : delete pSVData->maAppData.mpAccelMgr;
486 0 : pSVData->maAppData.mpAccelMgr = NULL;
487 : }
488 1 : if ( pSVData->maAppData.mpAppFileName )
489 : {
490 1 : delete pSVData->maAppData.mpAppFileName;
491 1 : pSVData->maAppData.mpAppFileName = NULL;
492 : }
493 1 : if ( pSVData->maAppData.mpAppName )
494 : {
495 1 : delete pSVData->maAppData.mpAppName;
496 1 : pSVData->maAppData.mpAppName = NULL;
497 : }
498 1 : if ( pSVData->maAppData.mpDisplayName )
499 : {
500 0 : delete pSVData->maAppData.mpDisplayName;
501 0 : pSVData->maAppData.mpDisplayName = NULL;
502 : }
503 1 : if ( pSVData->maAppData.mpEventListeners )
504 : {
505 0 : delete pSVData->maAppData.mpEventListeners;
506 0 : pSVData->maAppData.mpEventListeners = NULL;
507 : }
508 1 : if ( pSVData->maAppData.mpKeyListeners )
509 : {
510 0 : delete pSVData->maAppData.mpKeyListeners;
511 0 : pSVData->maAppData.mpKeyListeners = NULL;
512 : }
513 1 : if ( pSVData->maAppData.mpPostYieldListeners )
514 : {
515 0 : delete pSVData->maAppData.mpPostYieldListeners;
516 0 : pSVData->maAppData.mpPostYieldListeners = NULL;
517 : }
518 :
519 1 : if ( pSVData->maAppData.mpFirstHotKey )
520 0 : ImplFreeHotKeyData();
521 1 : if ( pSVData->maAppData.mpFirstEventHook )
522 0 : ImplFreeEventHookData();
523 :
524 1 : if (pSVData->mpBlendFrameCache)
525 0 : delete pSVData->mpBlendFrameCache, pSVData->mpBlendFrameCache = NULL;
526 :
527 1 : ImplDeletePrnQueueList();
528 1 : delete pSVData->maGDIData.mpScreenFontList;
529 1 : pSVData->maGDIData.mpScreenFontList = NULL;
530 1 : delete pSVData->maGDIData.mpScreenFontCache;
531 1 : pSVData->maGDIData.mpScreenFontCache = NULL;
532 :
533 1 : if ( pSVData->mpResMgr )
534 : {
535 0 : delete pSVData->mpResMgr;
536 0 : pSVData->mpResMgr = NULL;
537 : }
538 :
539 1 : ResMgr::DestroyAllResMgr();
540 :
541 : // destroy all Sal interfaces before destorying the instance
542 : // and thereby unloading the plugin
543 1 : delete pSVData->mpSalSystem;
544 1 : pSVData->mpSalSystem = NULL;
545 1 : delete pSVData->mpSalTimer;
546 1 : pSVData->mpSalTimer = NULL;
547 :
548 : // Deinit Sal
549 1 : DestroySalInstance( pSVData->mpDefInst );
550 :
551 1 : if( pOwnSvApp )
552 : {
553 0 : delete pOwnSvApp;
554 0 : pOwnSvApp = NULL;
555 : }
556 :
557 1 : EmbeddedFontsHelper::clearTemporaryFontFiles();
558 1 : }
559 :
560 : // only one call is allowed
561 : struct WorkerThreadData
562 : {
563 : oslWorkerFunction pWorker;
564 : void * pThreadData;
565 0 : WorkerThreadData( oslWorkerFunction pWorker_, void * pThreadData_ )
566 : : pWorker( pWorker_ )
567 0 : , pThreadData( pThreadData_ )
568 : {
569 0 : }
570 : };
571 :
572 : #ifdef WNT
573 : static HANDLE hThreadID = 0;
574 : static unsigned __stdcall _threadmain( void *pArgs )
575 : {
576 : OleInitialize( NULL );
577 : ((WorkerThreadData*)pArgs)->pWorker( ((WorkerThreadData*)pArgs)->pThreadData );
578 : delete (WorkerThreadData*)pArgs;
579 : OleUninitialize();
580 : hThreadID = 0;
581 : return 0;
582 : }
583 : #else
584 : static oslThread hThreadID = 0;
585 : extern "C"
586 : {
587 0 : static void SAL_CALL MainWorkerFunction( void* pArgs )
588 : {
589 0 : ((WorkerThreadData*)pArgs)->pWorker( ((WorkerThreadData*)pArgs)->pThreadData );
590 0 : delete (WorkerThreadData*)pArgs;
591 0 : hThreadID = 0;
592 0 : }
593 : } // extern "C"
594 : #endif
595 :
596 0 : void CreateMainLoopThread( oslWorkerFunction pWorker, void * pThreadData )
597 : {
598 : #ifdef WNT
599 : // sal thread always call CoInitializeEx, so a sysdepen implementation is necessary
600 :
601 : unsigned uThreadID;
602 : hThreadID = (HANDLE)_beginthreadex(
603 : NULL, // no security handle
604 : 0, // stacksize 0 means default
605 : _threadmain, // thread worker function
606 : new WorkerThreadData( pWorker, pThreadData ), // arguments for worker function
607 : 0, // 0 means: create immediately otherwise use CREATE_SUSPENDED
608 : &uThreadID ); // thread id to fill
609 : #else
610 0 : hThreadID = osl_createThread( MainWorkerFunction, new WorkerThreadData( pWorker, pThreadData ) );
611 : #endif
612 0 : }
613 :
614 0 : void JoinMainLoopThread()
615 : {
616 0 : if( hThreadID )
617 : {
618 : #ifdef WNT
619 : WaitForSingleObject(hThreadID, INFINITE);
620 : #else
621 0 : osl_joinWithThread(hThreadID);
622 0 : osl_destroyThread( hThreadID );
623 : #endif
624 : }
625 0 : }
626 :
627 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|