xref: /AOO41X/main/vcl/win/source/app/salinst.cxx (revision 79aad27f7f29270c03e208e3d687e8e3850af11d)
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 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_vcl.hxx"
26 
27 #include <string.h>
28 #include <tools/svwin.h>
29 #ifdef WNT
30 #include <process.h>
31 #endif
32 #ifdef __MINGW32__
33 #include <excpt.h>
34 #endif
35 
36 #include <osl/file.hxx>
37 
38 #include <vos/mutex.hxx>
39 
40 #include <tools/solarmutex.hxx>
41 #include <tools/debug.hxx>
42 
43 #include <vcl/timer.hxx>
44 #include <vcl/apptypes.hxx>
45 
46 #include <win/wincomp.hxx>
47 #include <win/salids.hrc>
48 #include <win/saldata.hxx>
49 #include <win/salinst.h>
50 #include <win/salframe.h>
51 #include <win/salobj.h>
52 #include <win/saltimer.h>
53 #include <win/salbmp.h>
54 
55 #include <salimestatus.hxx>
56 #include <salsys.hxx>
57 
58 #ifndef min
59 #define min(a,b)    (((a) < (b)) ? (a) : (b))
60 #endif
61 #ifndef max
62 #define max(a,b)    (((a) > (b)) ? (a) : (b))
63 #endif
64 
65 #if defined _MSC_VER
66 #pragma warning(push, 1)
67 #pragma warning( disable: 4917 )
68 #endif
69 
70 #include <GdiPlus.h>
71 #include <GdiPlusEnums.h>
72 #include <GdiPlusColor.h>
73 #include <Shlobj.h>
74 
75 #if defined _MSC_VER
76 #pragma warning(pop)
77 #endif
78 
79 // =======================================================================
80 
SalAbort(const XubString & rErrorText)81 void SalAbort( const XubString& rErrorText )
82 {
83     ImplFreeSalGDI();
84 
85     if ( !rErrorText.Len() )
86     {
87         // #112255# make sure crash reporter is triggered
88         RaiseException( 0, EXCEPTION_NONCONTINUABLE, 0, NULL );
89         FatalAppExit( 0, "Application Error" );
90     }
91     else
92     {
93         // #112255# make sure crash reporter is triggered
94         RaiseException( 0, EXCEPTION_NONCONTINUABLE, 0, NULL );
95         ByteString aErrorText( ImplSalGetWinAnsiString( rErrorText ) );
96         FatalAppExit( 0, aErrorText.GetBuffer() );
97     }
98 }
99 
100 // =======================================================================
101 
102 LRESULT CALLBACK SalComWndProcA( HWND hWnd, UINT nMsg, WPARAM wParam, LPARAM lParam );
103 LRESULT CALLBACK SalComWndProcW( HWND hWnd, UINT nMsg, WPARAM wParam, LPARAM lParam );
104 
105 // =======================================================================
106 
107 class SalYieldMutex : public vos::OMutex
108 {
109 public: // for ImplSalYield()
110     WinSalInstance*             mpInstData;
111     sal_uLong                       mnCount;
112     DWORD                       mnThreadId;
113 
114 public:
115                                 SalYieldMutex( WinSalInstance* pInstData );
116 
117     virtual void SAL_CALL       acquire();
118     virtual void SAL_CALL       release();
119     virtual sal_Bool SAL_CALL   tryToAcquire();
120 
121     sal_uLong                       GetAcquireCount( sal_uLong nThreadId );
122 };
123 
124 // -----------------------------------------------------------------------
125 
SalYieldMutex(WinSalInstance * pInstData)126 SalYieldMutex::SalYieldMutex( WinSalInstance* pInstData )
127 {
128     mpInstData  = pInstData;
129     mnCount     = 0;
130     mnThreadId  = 0;
131 }
132 
133 // -----------------------------------------------------------------------
134 
acquire()135 void SAL_CALL SalYieldMutex::acquire()
136 {
137     OMutex::acquire();
138     mnCount++;
139     mnThreadId = GetCurrentThreadId();
140 }
141 
142 // -----------------------------------------------------------------------
143 
release()144 void SAL_CALL SalYieldMutex::release()
145 {
146     DWORD nThreadId = GetCurrentThreadId();
147     if ( mnThreadId != nThreadId )
148         OMutex::release();
149     else
150     {
151         SalData* pSalData = GetSalData();
152         if ( pSalData->mnAppThreadId != nThreadId )
153         {
154             if ( mnCount == 1 )
155             {
156                 // If we don't call these message, the Output from the
157                 // Java clients doesn't come in the right order
158                 GdiFlush();
159 
160                 mpInstData->mpSalWaitMutex->acquire();
161                 if ( mpInstData->mnYieldWaitCount )
162                     ImplPostMessage( mpInstData->mhComWnd, SAL_MSG_RELEASEWAITYIELD, 0, 0 );
163                 mnThreadId = 0;
164                 mnCount--;
165                 OMutex::release();
166                 mpInstData->mpSalWaitMutex->release();
167             }
168             else
169             {
170                 mnCount--;
171                 OMutex::release();
172             }
173         }
174         else
175         {
176             if ( mnCount == 1 )
177                 mnThreadId = 0;
178             mnCount--;
179             OMutex::release();
180         }
181     }
182 }
183 
184 // -----------------------------------------------------------------------
185 
tryToAcquire()186 sal_Bool SAL_CALL SalYieldMutex::tryToAcquire()
187 {
188     if( OMutex::tryToAcquire() )
189     {
190         mnCount++;
191         mnThreadId = GetCurrentThreadId();
192         return sal_True;
193     }
194     else
195         return sal_False;
196 }
197 
198 // -----------------------------------------------------------------------
199 
GetAcquireCount(sal_uLong nThreadId)200 sal_uLong SalYieldMutex::GetAcquireCount( sal_uLong nThreadId )
201 {
202     if ( nThreadId == mnThreadId )
203         return mnCount;
204     else
205         return 0;
206 }
207 
208 // -----------------------------------------------------------------------
209 
ImplSalYieldMutexAcquireWithWait()210 void ImplSalYieldMutexAcquireWithWait()
211 {
212     WinSalInstance* pInst = GetSalData()->mpFirstInstance;
213     if ( !pInst )
214         return;
215 
216     // If we are the main thread, then we must wait with wait, because
217     // in if we don't reschedule, then we create deadlocks if a Windows
218     // Function is called from another thread. If we arn't the main thread,
219     // than we call qcquire directly.
220     DWORD nThreadId = GetCurrentThreadId();
221     SalData* pSalData = GetSalData();
222     if ( pSalData->mnAppThreadId == nThreadId )
223     {
224         // Wenn wir den Mutex nicht bekommen, muessen wir solange
225         // warten, bis wir Ihn bekommen
226         sal_Bool bAcquire = FALSE;
227         do
228         {
229             if ( pInst->mpSalYieldMutex->tryToAcquire() )
230                 bAcquire = TRUE;
231             else
232             {
233                 pInst->mpSalWaitMutex->acquire();
234                 if ( pInst->mpSalYieldMutex->tryToAcquire() )
235                 {
236                     bAcquire = TRUE;
237                     pInst->mpSalWaitMutex->release();
238                 }
239                 else
240                 {
241                     pInst->mnYieldWaitCount++;
242                     pInst->mpSalWaitMutex->release();
243                     MSG aTmpMsg;
244                     ImplGetMessage( &aTmpMsg, pInst->mhComWnd, SAL_MSG_RELEASEWAITYIELD, SAL_MSG_RELEASEWAITYIELD );
245                     pInst->mnYieldWaitCount--;
246                     if ( pInst->mnYieldWaitCount )
247                         ImplPostMessage( pInst->mhComWnd, SAL_MSG_RELEASEWAITYIELD, 0, 0 );
248                 }
249             }
250         }
251         while ( !bAcquire );
252     }
253     else
254         pInst->mpSalYieldMutex->acquire();
255 }
256 
257 // -----------------------------------------------------------------------
258 
ImplSalYieldMutexTryToAcquire()259 sal_Bool ImplSalYieldMutexTryToAcquire()
260 {
261     WinSalInstance* pInst = GetSalData()->mpFirstInstance;
262     if ( pInst )
263         return pInst->mpSalYieldMutex->tryToAcquire();
264     else
265         return FALSE;
266 }
267 
268 // -----------------------------------------------------------------------
269 
ImplSalYieldMutexAcquire()270 void ImplSalYieldMutexAcquire()
271 {
272     WinSalInstance* pInst = GetSalData()->mpFirstInstance;
273     if ( pInst )
274         pInst->mpSalYieldMutex->acquire();
275 }
276 
277 // -----------------------------------------------------------------------
278 
ImplSalYieldMutexRelease()279 void ImplSalYieldMutexRelease()
280 {
281     WinSalInstance* pInst = GetSalData()->mpFirstInstance;
282     if ( pInst )
283     {
284         GdiFlush();
285         pInst->mpSalYieldMutex->release();
286     }
287 }
288 
289 // -----------------------------------------------------------------------
290 
ImplSalReleaseYieldMutex()291 sal_uLong ImplSalReleaseYieldMutex()
292 {
293     WinSalInstance* pInst = GetSalData()->mpFirstInstance;
294     if ( !pInst )
295         return 0;
296 
297     SalYieldMutex*  pYieldMutex = pInst->mpSalYieldMutex;
298     sal_uLong           nCount = pYieldMutex->GetAcquireCount( GetCurrentThreadId() );
299     sal_uLong           n = nCount;
300     while ( n )
301     {
302         pYieldMutex->release();
303         n--;
304     }
305 
306     return nCount;
307 }
308 
309 // -----------------------------------------------------------------------
310 
ImplSalAcquireYieldMutex(sal_uLong nCount)311 void ImplSalAcquireYieldMutex( sal_uLong nCount )
312 {
313     WinSalInstance* pInst = GetSalData()->mpFirstInstance;
314     if ( !pInst )
315         return;
316 
317     SalYieldMutex*  pYieldMutex = pInst->mpSalYieldMutex;
318     while ( nCount )
319     {
320         pYieldMutex->acquire();
321         nCount--;
322     }
323 }
324 
325 // -----------------------------------------------------------------------
326 
CheckYieldMutex()327 bool WinSalInstance::CheckYieldMutex()
328 {
329     bool bRet = true;
330     SalData*    pSalData = GetSalData();
331     DWORD       nCurThreadId = GetCurrentThreadId();
332     if ( pSalData->mnAppThreadId != nCurThreadId )
333     {
334         if ( pSalData->mpFirstInstance )
335         {
336             SalYieldMutex* pYieldMutex = pSalData->mpFirstInstance->mpSalYieldMutex;
337             if ( pYieldMutex->mnThreadId != nCurThreadId )
338             {
339                 bRet = false;
340             }
341         }
342     }
343     else
344     {
345         if ( pSalData->mpFirstInstance )
346         {
347             SalYieldMutex* pYieldMutex = pSalData->mpFirstInstance->mpSalYieldMutex;
348             if ( pYieldMutex->mnThreadId != nCurThreadId )
349             {
350                 bRet = false;
351             }
352         }
353     }
354     return bRet;
355 }
356 
357 // =======================================================================
358 
initKeyCodeMap()359 void SalData::initKeyCodeMap()
360 {
361     UINT nKey = 0xffffffff;
362     #define initKey( a, b )\
363         nKey = LOWORD( VkKeyScan( a ) );\
364         if( nKey < 0xffff )\
365             maVKMap[ nKey ] = b;
366 
367     initKey( '+', KEY_ADD );
368     initKey( '-', KEY_SUBTRACT );
369     initKey( '*', KEY_MULTIPLY );
370     initKey( '/', KEY_DIVIDE );
371     initKey( '.', KEY_POINT );
372     initKey( ',', KEY_COMMA );
373     initKey( '<', KEY_LESS );
374     initKey( '>', KEY_GREATER );
375     initKey( '=', KEY_EQUAL );
376     initKey( '~', KEY_TILDE );
377     initKey( '`', KEY_QUOTELEFT );
378 }
379 
380 // =======================================================================
381 // -------
382 // SalData
383 // -------
384 
SalData()385 SalData::SalData()
386 {
387     mhInst = 0;                 // default instance handle
388     mhPrevInst = 0;             // previous instance handle
389     mnCmdShow = 0;              // default frame show style
390     mhDitherPal = 0;            // dither palette
391     mhDitherDIB = 0;            // dither memory handle
392     mpDitherDIB = 0;            // dither memory
393     mpDitherDIBData = 0;        // beginning of DIB data
394     mpDitherDiff = 0;           // Dither mapping table
395     mpDitherLow = 0;            // Dither mapping table
396     mpDitherHigh = 0;           // Dither mapping table
397     mnTimerMS = 0;              // Current Time (in MS) of the Timer
398     mnTimerOrgMS = 0;           // Current Original Time (in MS)
399     mnNextTimerTime = 0;
400     mnLastEventTime = 0;
401     mnTimerId = 0;              // windows timer id
402     mbInTimerProc = FALSE;      // timer event is currently being dispatched
403     mhSalObjMsgHook = 0;        // hook to get interesting msg for SalObject
404     mhWantLeaveMsg = 0;         // window handle, that want a MOUSELEAVE message
405     mpMouseLeaveTimer = 0;      // Timer for MouseLeave Test
406     mpFirstInstance = 0;        // pointer of first instance
407     mpFirstFrame = 0;           // pointer of first frame
408     mpFirstObject = 0;          // pointer of first object window
409     mpFirstVD = 0;              // first VirDev
410     mpFirstPrinter = 0;         // first printing printer
411     mpHDCCache = 0;             // Cache for three DC's
412     mh50Bmp = 0;                // 50% Bitmap
413     mh50Brush = 0;              // 50% Brush
414     int i;
415     for(i=0; i<MAX_STOCKPEN; i++)
416     {
417         maStockPenColorAry[i] = 0;
418         mhStockPenAry[i] = 0;
419     }
420     for(i=0; i<MAX_STOCKBRUSH; i++)
421     {
422         maStockBrushColorAry[i] = 0;
423         mhStockBrushAry[i] = 0;
424     }
425     mnStockPenCount = 0;        // count of static pens
426     mnStockBrushCount = 0;      // count of static brushes
427     mnSalObjWantKeyEvt = 0;     // KeyEvent, welcher vom SalObj-Hook verarbeitet werden soll
428     mnCacheDCInUse = 0;         // count of CacheDC in use
429     mbObjClassInit = FALSE;     // is SALOBJECTCLASS initialised
430     mbInPalChange = FALSE;      // is in WM_QUERYNEWPALETTE
431     mnAppThreadId = 0;          // Id from Applikation-Thread
432     mbScrSvrEnabled = FALSE;    // ScreenSaver enabled
433     mnSageStatus = 0;           // status of Sage-DLL (DISABLE_AGENT == nicht vorhanden)
434     mpSageEnableProc = 0;       // funktion to deactivate the system agent
435     mpFirstIcon = 0;            // icon cache, points to first icon, NULL if none
436     mpTempFontItem = 0;
437     mbThemeChanged = FALSE;     // true if visual theme was changed: throw away theme handles
438     mbThemeMenuSupport = FALSE;
439 
440     // init with NULL
441     gdiplusToken = 0;
442     maDwmLib     = 0;
443     mpDwmIsCompositionEnabled = 0;
444 
445     initKeyCodeMap();
446 
447     SetSalData( this );
448     initNWF();
449 }
450 
~SalData()451 SalData::~SalData()
452 {
453     deInitNWF();
454     SetSalData( NULL );
455 }
456 
InitSalData()457 void InitSalData()
458 {
459     SalData* pSalData = new SalData;
460     CoInitialize(0);
461 
462     // init GDIPlus
463     static Gdiplus::GdiplusStartupInput gdiplusStartupInput;
464     Gdiplus::GdiplusStartup(&pSalData->gdiplusToken, &gdiplusStartupInput, NULL);
465 }
466 
467 
DeInitSalData()468 void DeInitSalData()
469 {
470     CoUninitialize();
471     SalData* pSalData = GetSalData();
472 
473     // deinit GDIPlus
474     if(pSalData)
475     {
476         Gdiplus::GdiplusShutdown(pSalData->gdiplusToken);
477     }
478 
479     delete pSalData;
480 }
481 
482 // -----------------------------------------------------------------------
483 
InitSalMain()484 void InitSalMain()
485 {
486     // remember data, copied from WinMain
487     SalData* pData = GetAppSalData();
488     if ( pData )    // Im AppServer NULL
489     {
490         STARTUPINFO aSI;
491         aSI.cb = sizeof( aSI );
492         GetStartupInfo( &aSI );
493         pData->mhInst                   = GetModuleHandle( NULL );
494         pData->mhPrevInst               = NULL;
495         pData->mnCmdShow                = aSI.wShowWindow;
496     }
497 }
498 
DeInitSalMain()499 void DeInitSalMain()
500 {
501 }
502 
503 // -----------------------------------------------------------------------
504 
CreateSalInstance()505 SalInstance* CreateSalInstance()
506 {
507     SalData* pSalData = GetSalData();
508 
509     // determine the windows version
510     aSalShlData.mbWXP        = 0;
511     aSalShlData.mbWPrinter   = 0;
512     WORD nVer = (WORD)GetVersion();
513     aSalShlData.mnVersion = (((WORD)LOBYTE(nVer)) * 100) + HIBYTE(nVer);
514     if ( aSalShlData.mnVersion >= 400 )
515         aSalShlData.mbW40 = 1;
516     rtl_zeroMemory( &aSalShlData.maVersionInfo, sizeof(aSalShlData.maVersionInfo) );
517     aSalShlData.maVersionInfo.dwOSVersionInfoSize = sizeof( aSalShlData.maVersionInfo );
518     if ( GetVersionEx( &aSalShlData.maVersionInfo ) )
519     {
520         if ( aSalShlData.maVersionInfo.dwPlatformId == VER_PLATFORM_WIN32_NT )
521         {
522             // Windows XP ?
523             if ( aSalShlData.maVersionInfo.dwMajorVersion > 5 ||
524                ( aSalShlData.maVersionInfo.dwMajorVersion == 5 && aSalShlData.maVersionInfo.dwMinorVersion >= 1 ) )
525                 aSalShlData.mbWXP = 1;
526             if( aSalShlData.maVersionInfo.dwMajorVersion >= 5 )
527                 aSalShlData.mbWPrinter = 1;
528         }
529     }
530 
531     pSalData->mnAppThreadId = GetCurrentThreadId();
532 
533     // register frame class
534     if ( !pSalData->mhPrevInst )
535     {
536             WNDCLASSEXW aWndClassEx;
537             aWndClassEx.cbSize          = sizeof( aWndClassEx );
538             aWndClassEx.style           = CS_OWNDC;
539             aWndClassEx.lpfnWndProc     = SalFrameWndProcW;
540             aWndClassEx.cbClsExtra      = 0;
541             aWndClassEx.cbWndExtra      = SAL_FRAME_WNDEXTRA;
542             aWndClassEx.hInstance       = pSalData->mhInst;
543             aWndClassEx.hCursor         = 0;
544             aWndClassEx.hbrBackground   = 0;
545             aWndClassEx.lpszMenuName    = 0;
546             aWndClassEx.lpszClassName   = SAL_FRAME_CLASSNAMEW;
547             ImplLoadSalIcon( SAL_RESID_ICON_DEFAULT, aWndClassEx.hIcon, aWndClassEx.hIconSm );
548             if ( !RegisterClassExW( &aWndClassEx ) )
549                 return NULL;
550 
551             aWndClassEx.hIcon           = 0;
552             aWndClassEx.hIconSm         = 0;
553             aWndClassEx.style          |= CS_SAVEBITS;
554             aWndClassEx.lpszClassName   = SAL_SUBFRAME_CLASSNAMEW;
555             if ( !RegisterClassExW( &aWndClassEx ) )
556                 return NULL;
557 
558             // shadow effect for popups on XP
559             if( aSalShlData.mbWXP )
560                 aWndClassEx.style       |= CS_DROPSHADOW;
561             aWndClassEx.lpszClassName   = SAL_TMPSUBFRAME_CLASSNAMEW;
562             if ( !RegisterClassExW( &aWndClassEx ) )
563                 return NULL;
564 
565             aWndClassEx.style           = 0;
566             aWndClassEx.lpfnWndProc     = SalComWndProcW;
567             aWndClassEx.cbWndExtra      = 0;
568             aWndClassEx.lpszClassName   = SAL_COM_CLASSNAMEW;
569             if ( !RegisterClassExW( &aWndClassEx ) )
570                 return NULL;
571     }
572 
573     HWND hComWnd = CreateWindowExW( WS_EX_TOOLWINDOW, SAL_COM_CLASSNAMEW,
574                                    L"", WS_POPUP, 0, 0, 0, 0, 0, 0,
575                                    pSalData->mhInst, NULL );
576     if ( !hComWnd )
577         return NULL;
578 
579     WinSalInstance* pInst = new WinSalInstance;
580 
581     // init instance (only one instance in this version !!!)
582     pSalData->mpFirstInstance   = pInst;
583     pInst->mhInst    = pSalData->mhInst;
584     pInst->mhComWnd  = hComWnd;
585 
586     // init static GDI Data
587     ImplInitSalGDI();
588 
589     return pInst;
590 }
591 
592 // -----------------------------------------------------------------------
593 
DestroySalInstance(SalInstance * pInst)594 void DestroySalInstance( SalInstance* pInst )
595 {
596     SalData* pSalData = GetSalData();
597 
598     //  (only one instance in this version !!!)
599 
600     ImplFreeSalGDI();
601 
602     // reset instance
603     if ( pSalData->mpFirstInstance == pInst )
604         pSalData->mpFirstInstance = NULL;
605 
606     delete pInst;
607 }
608 
609 // -----------------------------------------------------------------------
610 
WinSalInstance()611 WinSalInstance::WinSalInstance()
612 {
613     mhComWnd                 = 0;
614     mpSalYieldMutex          = new SalYieldMutex( this );
615     mpSalWaitMutex           = new vos::OMutex;
616     mnYieldWaitCount         = 0;
617     mpSalYieldMutex->acquire();
618     ::tools::SolarMutex::SetSolarMutex( mpSalYieldMutex );
619 }
620 
621 // -----------------------------------------------------------------------
622 
~WinSalInstance()623 WinSalInstance::~WinSalInstance()
624 {
625     ::tools::SolarMutex::SetSolarMutex( 0 );
626     mpSalYieldMutex->release();
627     delete mpSalYieldMutex;
628     delete mpSalWaitMutex;
629     DestroyWindow( mhComWnd );
630 }
631 
632 // -----------------------------------------------------------------------
633 
GetYieldMutex()634 vos::IMutex* WinSalInstance::GetYieldMutex()
635 {
636     return mpSalYieldMutex;
637 }
638 
639 // -----------------------------------------------------------------------
640 
ReleaseYieldMutex()641 sal_uLong WinSalInstance::ReleaseYieldMutex()
642 {
643     return ImplSalReleaseYieldMutex();
644 }
645 
646 // -----------------------------------------------------------------------
647 
AcquireYieldMutex(sal_uLong nCount)648 void WinSalInstance::AcquireYieldMutex( sal_uLong nCount )
649 {
650     ImplSalAcquireYieldMutex( nCount );
651 }
652 
653 // -----------------------------------------------------------------------
654 
ImplSalDispatchMessage(MSG * pMsg)655 static void ImplSalDispatchMessage( MSG* pMsg )
656 {
657     SalData* pSalData = GetSalData();
658     if ( pSalData->mpFirstObject )
659     {
660         if ( ImplSalPreDispatchMsg( pMsg ) )
661             return;
662     }
663     LRESULT lResult = ImplDispatchMessage( pMsg );
664     if ( pSalData->mpFirstObject )
665         ImplSalPostDispatchMsg( pMsg, lResult );
666 }
667 
668 // -----------------------------------------------------------------------
669 
ImplSalYield(sal_Bool bWait,sal_Bool bHandleAllCurrentEvents)670 void ImplSalYield( sal_Bool bWait, sal_Bool bHandleAllCurrentEvents )
671 {
672     MSG aMsg;
673     bool bWasMsg = false, bOneEvent = false;
674 
675     int nMaxEvents = bHandleAllCurrentEvents ? 100 : 1;
676     do
677     {
678         if ( ImplPeekMessage( &aMsg, 0, 0, 0, PM_REMOVE ) )
679         {
680             if ( !ImplInterceptChildWindowKeyDown( aMsg ) )
681             {
682                 TranslateMessage( &aMsg );
683                 ImplSalDispatchMessage( &aMsg );
684             }
685 
686             bOneEvent = bWasMsg = true;
687         }
688         else
689             bOneEvent = false;
690     } while( --nMaxEvents && bOneEvent );
691 
692     if ( bWait && ! bWasMsg )
693     {
694         if ( ImplGetMessage( &aMsg, 0, 0, 0 ) )
695         {
696             if ( !ImplInterceptChildWindowKeyDown( aMsg ) )
697             {
698                 TranslateMessage( &aMsg );
699                 ImplSalDispatchMessage( &aMsg );
700             }
701         }
702     }
703 }
704 
705 // -----------------------------------------------------------------------
706 
Yield(bool bWait,bool bHandleAllCurrentEvents)707 void WinSalInstance::Yield( bool bWait, bool bHandleAllCurrentEvents )
708 {
709     SalYieldMutex*  pYieldMutex = mpSalYieldMutex;
710     SalData*        pSalData = GetSalData();
711     DWORD           nCurThreadId = GetCurrentThreadId();
712     sal_uLong           nCount = pYieldMutex->GetAcquireCount( nCurThreadId );
713     sal_uLong           n = nCount;
714     while ( n )
715     {
716         pYieldMutex->release();
717         n--;
718     }
719     if ( pSalData->mnAppThreadId != nCurThreadId )
720     {
721         // #97739# A SendMessage call blocks until the called thread (here: the main thread)
722         // returns. During a yield however, messages are processed in the main thread that might
723         // result in a new message loop due to opening a dialog. Thus, SendMessage would not
724         // return which will block this thread!
725         // Solution: just give up the time slice and hope that messages are processed
726         // by the main thread anyway (where all windows are created)
727         // If the mainthread is not currently handling messages, then our SendMessage would
728         // also do nothing, so this seems to be reasonable.
729 
730         // #i18883# only sleep if potential deadlock scenario, ie, when a dialog is open
731         if( ImplGetSVData()->maAppData.mnModalMode )
732             Sleep(1);
733         else
734             ImplSendMessage( mhComWnd, SAL_MSG_THREADYIELD, (WPARAM)bWait, (LPARAM)bHandleAllCurrentEvents );
735 
736         n = nCount;
737         while ( n )
738         {
739             pYieldMutex->acquire();
740             n--;
741         }
742     }
743     else
744     {
745         ImplSalYield( bWait, bHandleAllCurrentEvents );
746 
747         n = nCount;
748         while ( n )
749         {
750             ImplSalYieldMutexAcquireWithWait();
751             n--;
752         }
753     }
754 }
755 
756 // -----------------------------------------------------------------------
757 
SalComWndProc(HWND hWnd,UINT nMsg,WPARAM wParam,LPARAM lParam,int & rDef)758 LRESULT CALLBACK SalComWndProc( HWND hWnd, UINT nMsg, WPARAM wParam, LPARAM lParam, int& rDef )
759 {
760     LRESULT nRet = 0;
761 
762 
763     switch ( nMsg )
764     {
765         case SAL_MSG_PRINTABORTJOB:
766             ImplSalPrinterAbortJobAsync( (HDC)wParam );
767             rDef = FALSE;
768             break;
769         case SAL_MSG_THREADYIELD:
770             ImplSalYield( (sal_Bool)wParam, (sal_Bool)lParam );
771             rDef = FALSE;
772             break;
773         // If we get this message, because another GetMessage() call
774         // has recieved this message, we must post this message to
775         // us again, because in the other case we wait forever.
776         case SAL_MSG_RELEASEWAITYIELD:
777             {
778             WinSalInstance* pInst = GetSalData()->mpFirstInstance;
779             if ( pInst && pInst->mnYieldWaitCount )
780                 ImplPostMessage( hWnd, SAL_MSG_RELEASEWAITYIELD, wParam, lParam );
781             }
782             rDef = FALSE;
783             break;
784         case SAL_MSG_STARTTIMER:
785             ImplSalStartTimer( (sal_uLong) lParam, FALSE );
786             rDef = FALSE;
787             break;
788         case SAL_MSG_CREATEFRAME:
789             nRet = (LRESULT)ImplSalCreateFrame( GetSalData()->mpFirstInstance, (HWND)lParam, (sal_uLong)wParam );
790             rDef = FALSE;
791             break;
792         case SAL_MSG_RECREATEHWND:
793             nRet = (LRESULT)ImplSalReCreateHWND( (HWND)wParam, (HWND)lParam, FALSE );
794             rDef = FALSE;
795             break;
796         case SAL_MSG_RECREATECHILDHWND:
797             nRet = (LRESULT)ImplSalReCreateHWND( (HWND)wParam, (HWND)lParam, TRUE );
798             rDef = FALSE;
799             break;
800         case SAL_MSG_DESTROYFRAME:
801             delete (SalFrame*)lParam;
802             rDef = FALSE;
803             break;
804         case SAL_MSG_DESTROYHWND:
805             //We only destroy the native window here. We do NOT destroy the SalFrame contained
806             //in the structure (GetWindowPtr()).
807             if (DestroyWindow((HWND)lParam) == 0)
808             {
809                 OSL_ENSURE(0, "DestroyWindow failed!");
810                 //Failure: We remove the SalFrame from the window structure. So we avoid that
811                 // the window structure may contain an invalid pointer, once the SalFrame is deleted.
812                SetWindowPtr((HWND)lParam, 0);
813             }
814             rDef = FALSE;
815             break;
816         case SAL_MSG_CREATEOBJECT:
817             nRet = (LRESULT)ImplSalCreateObject( GetSalData()->mpFirstInstance, (WinSalFrame*)lParam );
818             rDef = FALSE;
819             break;
820         case SAL_MSG_DESTROYOBJECT:
821             delete (SalObject*)lParam;
822             rDef = FALSE;
823             break;
824         case SAL_MSG_GETDC:
825             nRet = (LRESULT)GetDCEx( (HWND)wParam, 0, DCX_CACHE );
826             rDef = FALSE;
827             break;
828         case SAL_MSG_RELEASEDC:
829             ReleaseDC( (HWND)wParam, (HDC)lParam );
830             rDef = FALSE;
831             break;
832         case SAL_MSG_POSTTIMER:
833             SalTimerProc( 0, 0, SALTIMERPROC_RECURSIVE, lParam );
834             break;
835     }
836 
837     return nRet;
838 }
839 
SalComWndProcA(HWND hWnd,UINT nMsg,WPARAM wParam,LPARAM lParam)840 LRESULT CALLBACK SalComWndProcA( HWND hWnd, UINT nMsg, WPARAM wParam, LPARAM lParam )
841 {
842     int bDef = TRUE;
843     LRESULT nRet = 0;
844 #ifdef __MINGW32__
845     jmp_buf jmpbuf;
846     __SEHandler han;
847     if (__builtin_setjmp(jmpbuf) == 0)
848     {
849         han.Set(jmpbuf, NULL, (__SEHandler::PF)EXCEPTION_EXECUTE_HANDLER);
850 #else
851     __try
852     {
853 #endif
854         nRet = SalComWndProc( hWnd, nMsg, wParam, lParam, bDef );
855     }
856 #ifdef __MINGW32__
857     han.Reset();
858 #else
859     __except(WinSalInstance::WorkaroundExceptionHandlingInUSER32Lib(GetExceptionCode(), GetExceptionInformation()))
860     {
861     }
862 #endif
863     if ( bDef )
864     {
865         if ( !ImplHandleGlobalMsg( hWnd, nMsg, wParam, lParam, nRet ) )
866             nRet = DefWindowProcA( hWnd, nMsg, wParam, lParam );
867     }
868     return nRet;
869 }
870 
871 LRESULT CALLBACK SalComWndProcW( HWND hWnd, UINT nMsg, WPARAM wParam, LPARAM lParam )
872 {
873     int bDef = TRUE;
874     LRESULT nRet = 0;
875 #ifdef __MINGW32__
876     jmp_buf jmpbuf;
877     __SEHandler han;
878     if (__builtin_setjmp(jmpbuf) == 0)
879     {
880         han.Set(jmpbuf, NULL, (__SEHandler::PF)EXCEPTION_EXECUTE_HANDLER);
881 #else
882     __try
883     {
884 #endif
885         nRet = SalComWndProc( hWnd, nMsg, wParam, lParam, bDef );
886     }
887 #ifdef __MINGW32__
888     han.Reset();
889 #else
890     __except(WinSalInstance::WorkaroundExceptionHandlingInUSER32Lib(GetExceptionCode(), GetExceptionInformation()))
891     {
892     }
893 #endif
894     if ( bDef )
895     {
896         if ( !ImplHandleGlobalMsg( hWnd, nMsg, wParam, lParam, nRet ) )
897             nRet = DefWindowProcW( hWnd, nMsg, wParam, lParam );
898     }
899     return nRet;
900 }
901 
902 // -----------------------------------------------------------------------
903 
904 bool WinSalInstance::AnyInput( sal_uInt16 nType )
905 {
906     MSG aMsg;
907 
908     if ( (nType & (INPUT_ANY)) == (INPUT_ANY) )
909     {
910         // revert bugfix for #108919# which never reported timeouts when called from the timer handler
911         // which made the application completely unresponsive during background formatting
912         if ( ImplPeekMessage( &aMsg, 0, 0, 0, PM_NOREMOVE | PM_NOYIELD ) )
913             return true;
914     }
915     else
916     {
917         if ( nType & INPUT_MOUSE )
918         {
919             // Test for mouse input
920             if ( ImplPeekMessage( &aMsg, 0, WM_MOUSEFIRST, WM_MOUSELAST,
921                                   PM_NOREMOVE | PM_NOYIELD ) )
922                 return true;
923         }
924 
925         if ( nType & INPUT_KEYBOARD )
926         {
927             // Test for key input
928             if ( ImplPeekMessage( &aMsg, 0, WM_KEYDOWN, WM_KEYDOWN,
929                                   PM_NOREMOVE | PM_NOYIELD ) )
930             {
931                 if ( (aMsg.wParam == VK_SHIFT)   ||
932                      (aMsg.wParam == VK_CONTROL) ||
933                      (aMsg.wParam == VK_MENU) )
934                     return false;
935                 else
936                     return true;
937             }
938         }
939 
940         if ( nType & INPUT_PAINT )
941         {
942             // Test for paint input
943             if ( ImplPeekMessage( &aMsg, 0, WM_PAINT, WM_PAINT,
944                                   PM_NOREMOVE | PM_NOYIELD ) )
945                 return true;
946 
947             if ( ImplPeekMessage( &aMsg, 0, WM_SIZE, WM_SIZE,
948                                   PM_NOREMOVE | PM_NOYIELD ) )
949                 return true;
950 
951             if ( ImplPeekMessage( &aMsg, 0, SAL_MSG_POSTCALLSIZE, SAL_MSG_POSTCALLSIZE,
952                                   PM_NOREMOVE | PM_NOYIELD ) )
953                 return true;
954 
955             if ( ImplPeekMessage( &aMsg, 0, WM_MOVE, WM_MOVE,
956                                   PM_NOREMOVE | PM_NOYIELD ) )
957                 return true;
958 
959             if ( ImplPeekMessage( &aMsg, 0, SAL_MSG_POSTMOVE, SAL_MSG_POSTMOVE,
960                                   PM_NOREMOVE | PM_NOYIELD ) )
961                 return true;
962         }
963 
964         if ( nType & INPUT_TIMER )
965         {
966             // Test for timer input
967             if ( ImplPeekMessage( &aMsg, 0, WM_TIMER, WM_TIMER,
968                                   PM_NOREMOVE | PM_NOYIELD ) )
969                 return true;
970 
971         }
972 
973         if ( nType & INPUT_OTHER )
974         {
975             // Test for any input
976             if ( ImplPeekMessage( &aMsg, 0, 0, 0, PM_NOREMOVE | PM_NOYIELD ) )
977                 return true;
978         }
979     }
980 
981     return FALSE;
982 }
983 
984 // -----------------------------------------------------------------------
985 
986 void SalTimer::Start( sal_uLong nMS )
987 {
988     // Um auf Main-Thread umzuschalten
989     SalData* pSalData = GetSalData();
990     if ( pSalData->mpFirstInstance )
991     {
992         if ( pSalData->mnAppThreadId != GetCurrentThreadId() )
993             ImplPostMessage( pSalData->mpFirstInstance->mhComWnd, SAL_MSG_STARTTIMER, 0, (LPARAM)nMS );
994         else
995             ImplSendMessage( pSalData->mpFirstInstance->mhComWnd, SAL_MSG_STARTTIMER, 0, (LPARAM)nMS );
996     }
997     else
998         ImplSalStartTimer( nMS, FALSE );
999 }
1000 
1001 // -----------------------------------------------------------------------
1002 
1003 SalFrame* WinSalInstance::CreateChildFrame( SystemParentData* pSystemParentData, sal_uLong nSalFrameStyle )
1004 {
1005     // Um auf Main-Thread umzuschalten
1006     return (SalFrame*)ImplSendMessage( mhComWnd, SAL_MSG_CREATEFRAME, nSalFrameStyle, (LPARAM)pSystemParentData->hWnd );
1007 }
1008 
1009 // -----------------------------------------------------------------------
1010 
1011 SalFrame* WinSalInstance::CreateFrame( SalFrame* pParent, sal_uLong nSalFrameStyle )
1012 {
1013     // Um auf Main-Thread umzuschalten
1014     HWND hWndParent;
1015     if ( pParent )
1016         hWndParent = static_cast<WinSalFrame*>(pParent)->mhWnd;
1017     else
1018         hWndParent = 0;
1019     return (SalFrame*)ImplSendMessage( mhComWnd, SAL_MSG_CREATEFRAME, nSalFrameStyle, (LPARAM)hWndParent );
1020 }
1021 
1022 // -----------------------------------------------------------------------
1023 
1024 void WinSalInstance::DestroyFrame( SalFrame* pFrame )
1025 {
1026     ImplSendMessage( mhComWnd, SAL_MSG_DESTROYFRAME, 0, (LPARAM)pFrame );
1027 }
1028 
1029 // -----------------------------------------------------------------------
1030 
1031 SalObject* WinSalInstance::CreateObject( SalFrame* pParent,
1032                                          SystemWindowData* /*pWindowData*/, // SystemWindowData meaningless on Windows
1033                                          sal_Bool /*bShow*/ )
1034 {
1035     // Um auf Main-Thread umzuschalten
1036     return (SalObject*)ImplSendMessage( mhComWnd, SAL_MSG_CREATEOBJECT, 0, (LPARAM)static_cast<WinSalFrame*>(pParent) );
1037 }
1038 
1039 // -----------------------------------------------------------------------
1040 
1041 void WinSalInstance::DestroyObject( SalObject* pObject )
1042 {
1043     ImplSendMessage( mhComWnd, SAL_MSG_DESTROYOBJECT, 0, (LPARAM)pObject );
1044 }
1045 
1046 // -----------------------------------------------------------------------
1047 
1048 void* WinSalInstance::GetConnectionIdentifier( ConnectionIdentifierType& rReturnedType, int& rReturnedBytes )
1049 {
1050     rReturnedBytes  = 1;
1051     rReturnedType   = AsciiCString;
1052     return const_cast<char *>("");
1053 }
1054 
1055 // -----------------------------------------------------------------------
1056 
1057 /** Add a file to the system shells recent document list if there is any.
1058       This function may have no effect under Unix because there is no
1059       standard API among the different desktop managers.
1060 
1061       @param aFileUrl
1062                 The file url of the document.
1063 */
1064 void WinSalInstance::AddToRecentDocumentList(const rtl::OUString& rFileUrl, const rtl::OUString& /*rMimeType*/)
1065 {
1066     rtl::OUString system_path;
1067     osl::FileBase::RC rc = osl::FileBase::getSystemPathFromFileURL(rFileUrl, system_path);
1068 
1069     OSL_ENSURE(osl::FileBase::E_None == rc, "Invalid file url");
1070 
1071     if (osl::FileBase::E_None == rc)
1072         SHAddToRecentDocs(SHARD_PATHW, system_path.getStr());
1073 }
1074 
1075 // -----------------------------------------------------------------------
1076 
1077 SalTimer* WinSalInstance::CreateSalTimer()
1078 {
1079     return new WinSalTimer();
1080 }
1081 
1082 // -----------------------------------------------------------------------
1083 
1084 SalBitmap* WinSalInstance::CreateSalBitmap()
1085 {
1086     return new WinSalBitmap();
1087 }
1088 
1089 class WinImeStatus : public SalI18NImeStatus
1090 {
1091   public:
1092     WinImeStatus() {}
1093     virtual ~WinImeStatus() {}
1094 
1095     // asks whether there is a status window available
1096     // to toggle into menubar
1097     virtual bool canToggle() { return false; }
1098     virtual void toggle() {}
1099 };
1100 
1101 SalI18NImeStatus* WinSalInstance::CreateI18NImeStatus()
1102 {
1103     return new WinImeStatus();
1104 }
1105 
1106 // -----------------------------------------------------------------------
1107 
1108 const ::rtl::OUString& SalGetDesktopEnvironment()
1109 {
1110     static ::rtl::OUString aDesktopEnvironment( RTL_CONSTASCII_USTRINGPARAM( "Windows" ) );
1111     return aDesktopEnvironment;
1112 }
1113 
1114 SalSession* WinSalInstance::CreateSalSession()
1115 {
1116     return NULL;
1117 }
1118 
1119 #ifndef __MINGW32__
1120 // -----------------------------------------------------------------------
1121 int WinSalInstance::WorkaroundExceptionHandlingInUSER32Lib(int, LPEXCEPTION_POINTERS pExceptionInfo)
1122 {
1123     // Decide if an exception is a c++ (mostly UNO) exception or a process violation.
1124     // Depending on this information we pass process violations directly to our signal handler ...
1125     // and c++ (UNO) exceptions are sended to the following code on the current stack.
1126     // Problem behind: user32.dll sometime consumes exceptions/process violations .-)
1127     // see also #112221#
1128 
1129     static DWORD EXCEPTION_MSC_CPP_EXCEPTION = 0xE06D7363;
1130 
1131     if (pExceptionInfo->ExceptionRecord->ExceptionCode == EXCEPTION_MSC_CPP_EXCEPTION)
1132         return EXCEPTION_CONTINUE_SEARCH;
1133 
1134     return UnhandledExceptionFilter( pExceptionInfo );
1135 }
1136 #endif
1137