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