xref: /core/vcl/win/app/salinst.cxx (revision 87ef004115d07c16fe4899b3d423cc16a12a0fce)
14905a190SSebastian Spaeth /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
244cfc7cbSMichael Meeks /*
344cfc7cbSMichael Meeks  * This file is part of the LibreOffice project.
48ab086b6SJens-Heiner Rechtien  *
544cfc7cbSMichael Meeks  * This Source Code Form is subject to the terms of the Mozilla Public
644cfc7cbSMichael Meeks  * License, v. 2.0. If a copy of the MPL was not distributed with this
744cfc7cbSMichael Meeks  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
877b6bbe4SRüdiger Timm  *
944cfc7cbSMichael Meeks  * This file incorporates work covered by the following license notice:
1077b6bbe4SRüdiger Timm  *
1144cfc7cbSMichael Meeks  *   Licensed to the Apache Software Foundation (ASF) under one or more
1244cfc7cbSMichael Meeks  *   contributor license agreements. See the NOTICE file distributed
1344cfc7cbSMichael Meeks  *   with this work for additional information regarding copyright
1444cfc7cbSMichael Meeks  *   ownership. The ASF licenses this file to you under the Apache
1544cfc7cbSMichael Meeks  *   License, Version 2.0 (the "License"); you may not use this file
1644cfc7cbSMichael Meeks  *   except in compliance with the License. You may obtain a copy of
1744cfc7cbSMichael Meeks  *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
1844cfc7cbSMichael Meeks  */
198ab086b6SJens-Heiner Rechtien 
208ab086b6SJens-Heiner Rechtien #include <string.h>
21a18b02e8SFridrich Štrba #include <svsys.h>
228ab086b6SJens-Heiner Rechtien #include <process.h>
2319ba1fafSPhilipp Lohmann [pl] 
24ce3951edSStephan Bergmann #include <osl/conditn.hxx>
259e18c9eeSVladimir Glazounov #include <osl/file.hxx>
26a43b79f6SGabor Kelemen #include <sal/log.hxx>
276256797dSGabor Kelemen #include <tools/debug.hxx>
28fa12f373SStephan Bergmann #include <tools/time.hxx>
2903157610SJan-Marek Glogowski #include <comphelper/processfactory.hxx>
3011fd73acSStephan Bergmann #include <comphelper/solarmutex.hxx>
31dbac52a2SJan-Marek Glogowski #include <comphelper/windowserrorstring.hxx>
3203157610SJan-Marek Glogowski #include <com/sun/star/uno/Reference.h>
331944e3ddSMike Kaganski #include <o3tl/char16_t2wchar_t.hxx>
340bcb62c6SMike Kaganski #include <o3tl/temporary.hxx>
3519ba1fafSPhilipp Lohmann [pl] 
3603157610SJan-Marek Glogowski #include <dndhelper.hxx>
37249e3d6dSChris Sherlock #include <vcl/inputtypes.hxx>
380bea1d80SMichael Meeks #include <vcl/opengl/OpenGLContext.hxx>
3903157610SJan-Marek Glogowski #include <vcl/sysdata.hxx>
40d9fbaf24SJan Holesovsky #include <vcl/timer.hxx>
411698debeSJan-Marek Glogowski #include <vclpluginapi.h>
4219ba1fafSPhilipp Lohmann [pl] 
4303157610SJan-Marek Glogowski #include <win/dnd_source.hxx>
4403157610SJan-Marek Glogowski #include <win/dnd_target.hxx>
45e0ac7685SStephan Bergmann #include <win/wincomp.hxx>
46e0ac7685SStephan Bergmann #include <win/salids.hrc>
47e0ac7685SStephan Bergmann #include <win/saldata.hxx>
48e0ac7685SStephan Bergmann #include <win/salinst.h>
49e0ac7685SStephan Bergmann #include <win/salframe.h>
50e0ac7685SStephan Bergmann #include <win/salobj.h>
51e0ac7685SStephan Bergmann #include <win/saltimer.h>
52e0ac7685SStephan Bergmann #include <win/salbmp.h>
53e0ac7685SStephan Bergmann #include <win/winlayout.hxx>
5419ba1fafSPhilipp Lohmann [pl] 
555c4f872aSLuboš Luňák #include <config_features.h>
565c4f872aSLuboš Luňák #include <vcl/skia/SkiaHelper.hxx>
57994b8e52SLuboš Luňák #include <config_skia.h>
585c4f872aSLuboš Luňák #include <skia/salbmp.hxx>
5931b2c104SLuboš Luňák #include <skia/win/gdiimpl.hxx>
605c4f872aSLuboš Luňák 
61e0ac7685SStephan Bergmann #include <salsys.hxx>
622f382d6cSJens-Heiner Rechtien 
631b206f37SMarkus Mohrhard #include <desktop/crashreport.hxx>
641b206f37SMarkus Mohrhard 
65e0ac7685SStephan Bergmann #include <prewin.h>
661a494d9aSAshod Nakashian 
671f7e587cSTor Lillqvist #include <gdiplus.h>
681f7e587cSTor Lillqvist #include <shlobj.h>
6950afe624SJens-Heiner Rechtien 
70e0ac7685SStephan Bergmann #include <postwin.h>
71ba68436eSMichael Stahl 
72928b1b04SStephan Bergmann static LRESULT CALLBACK SalComWndProcW( HWND hWnd, UINT nMsg, WPARAM wParam, LPARAM lParam );
738ab086b6SJens-Heiner Rechtien 
744c93de2cSNoel Grandin class SalYieldMutex : public comphelper::SolarMutex
758ab086b6SJens-Heiner Rechtien {
769771e616SStephan Bergmann public: // for ImplSalYield() and ImplSalYieldMutexAcquireWithWait()
779771e616SStephan Bergmann     osl::Condition            m_condition; /// for MsgWaitForMultipleObjects()
789771e616SStephan Bergmann 
793840aedeSJan-Marek Glogowski protected:
803840aedeSJan-Marek Glogowski     virtual void              doAcquire( sal_uInt32 nLockCount ) override;
813840aedeSJan-Marek Glogowski     virtual sal_uInt32        doRelease( bool bUnlockAll ) override;
823840aedeSJan-Marek Glogowski 
833840aedeSJan-Marek Glogowski     static void               BeforeReleaseHandler();
848ab086b6SJens-Heiner Rechtien 
858ab086b6SJens-Heiner Rechtien public:
863840aedeSJan-Marek Glogowski     explicit SalYieldMutex();
878ab086b6SJens-Heiner Rechtien 
883840aedeSJan-Marek Glogowski     virtual bool              IsCurrentThread() const override;
894baec725SJan-Marek Glogowski     virtual bool              tryToAcquire() override;
908ab086b6SJens-Heiner Rechtien };
918ab086b6SJens-Heiner Rechtien 
SalYieldMutex()923840aedeSJan-Marek Glogowski SalYieldMutex::SalYieldMutex()
938ab086b6SJens-Heiner Rechtien {
943840aedeSJan-Marek Glogowski     SetBeforeReleaseHandler( &SalYieldMutex::BeforeReleaseHandler );
958ab086b6SJens-Heiner Rechtien }
968ab086b6SJens-Heiner Rechtien 
BeforeReleaseHandler()973840aedeSJan-Marek Glogowski void SalYieldMutex::BeforeReleaseHandler()
989c997095SArmin Le Grand {
9916b0e217SMichael Meeks     OpenGLContext::prepareForYield();
1000bea1d80SMichael Meeks 
1013840aedeSJan-Marek Glogowski     if ( GetSalData()->mnAppThreadId != GetCurrentThreadId() )
102edac9385SMichael Stahl     {
1036bd12d86Sth         // If we don't call these message, the Output from the
1046bd12d86Sth         // Java clients doesn't come in the right order
1056bd12d86Sth         GdiFlush();
1068ab086b6SJens-Heiner Rechtien     }
1078ab086b6SJens-Heiner Rechtien }
1088ab086b6SJens-Heiner Rechtien 
109ea2be4efSMichael Stahl /// note: while VCL is fully up and running (other threads started and
110ea2be4efSMichael Stahl /// before shutdown), the main thread must acquire SolarMutex only via
111ea2be4efSMichael Stahl /// this function to avoid deadlock
doAcquire(sal_uInt32 nLockCount)1123840aedeSJan-Marek Glogowski void SalYieldMutex::doAcquire( sal_uInt32 nLockCount )
1138ab086b6SJens-Heiner Rechtien {
1147c52d86fSNoel Grandin     WinSalInstance* pInst = GetSalData()->mpInstance;
1159771e616SStephan Bergmann     if ( pInst && pInst->IsMainThread() )
1168ab086b6SJens-Heiner Rechtien     {
1179771e616SStephan Bergmann         if ( pInst->m_nNoYieldLock )
1184baec725SJan-Marek Glogowski             return;
1199771e616SStephan Bergmann         // tdf#96887 If this is the main thread, then we must wait for two things:
1209771e616SStephan Bergmann         // - the yield mutex being unlocked
1219771e616SStephan Bergmann         // - SendMessage() being triggered
1229771e616SStephan Bergmann         // This can nicely be done using MsgWaitForMultipleObjects, which is called in
1239771e616SStephan Bergmann         // m_condition.wait(). The 2nd one is
1249771e616SStephan Bergmann         // needed because if we don't reschedule, then we create deadlocks if a
1259771e616SStephan Bergmann         // Window's create/destroy is called via SendMessage() from another thread.
1269771e616SStephan Bergmann         // Have a look at the osl_waitCondition implementation for more info.
1279771e616SStephan Bergmann         do {
1287b4b032dSNoel Grandin             // Calling Condition::reset frequently turns out to be a little expensive,
1297b4b032dSNoel Grandin             // and the vast majority of the time there is no contention, so first
1307b4b032dSNoel Grandin             // try just acquiring the mutex.
1317b4b032dSNoel Grandin             if (m_aMutex.tryToAcquire())
1327b4b032dSNoel Grandin                 break;
1339771e616SStephan Bergmann             // reset condition *before* acquiring!
1349771e616SStephan Bergmann             m_condition.reset();
1359771e616SStephan Bergmann             if (m_aMutex.tryToAcquire())
1369771e616SStephan Bergmann                 break;
1379771e616SStephan Bergmann             // wait for SalYieldMutex::release() to set the condition
1389771e616SStephan Bergmann             osl::Condition::Result res = m_condition.wait();
1399771e616SStephan Bergmann             assert(osl::Condition::Result::result_ok == res);
14043768200SStephan Bergmann             (void) res;
1411b9d48f5SJan-Marek Glogowski         }
1429771e616SStephan Bergmann         while ( true );
1439771e616SStephan Bergmann     }
1449771e616SStephan Bergmann     else
1453840aedeSJan-Marek Glogowski         m_aMutex.acquire();
1463840aedeSJan-Marek Glogowski     ++m_nCount;
1473840aedeSJan-Marek Glogowski     --nLockCount;
1483840aedeSJan-Marek Glogowski 
1494c93de2cSNoel Grandin     comphelper::SolarMutex::doAcquire( nLockCount );
1503840aedeSJan-Marek Glogowski }
1513840aedeSJan-Marek Glogowski 
doRelease(const bool bUnlockAll)1523840aedeSJan-Marek Glogowski sal_uInt32 SalYieldMutex::doRelease( const bool bUnlockAll )
1533840aedeSJan-Marek Glogowski {
1547c52d86fSNoel Grandin     WinSalInstance* pInst = GetSalData()->mpInstance;
155bf0a63dcSJan-Marek Glogowski     if ( pInst && pInst->m_nNoYieldLock && pInst->IsMainThread() )
1564baec725SJan-Marek Glogowski         return 1;
1573840aedeSJan-Marek Glogowski 
1589771e616SStephan Bergmann     sal_uInt32 nCount = comphelper::SolarMutex::doRelease( bUnlockAll );
1599771e616SStephan Bergmann     // wake up ImplSalYieldMutexAcquireWithWait() after release
1609771e616SStephan Bergmann     if ( 0 == m_nCount )
1619771e616SStephan Bergmann         m_condition.set();
1629771e616SStephan Bergmann     return nCount;
1633840aedeSJan-Marek Glogowski }
1643840aedeSJan-Marek Glogowski 
tryToAcquire()1654baec725SJan-Marek Glogowski bool SalYieldMutex::tryToAcquire()
1664baec725SJan-Marek Glogowski {
1677c52d86fSNoel Grandin     WinSalInstance* pInst = GetSalData()->mpInstance;
1684baec725SJan-Marek Glogowski     if ( pInst )
1694baec725SJan-Marek Glogowski     {
170bf0a63dcSJan-Marek Glogowski         if ( pInst->m_nNoYieldLock && pInst->IsMainThread() )
1714baec725SJan-Marek Glogowski             return true;
1724baec725SJan-Marek Glogowski         else
1734c93de2cSNoel Grandin             return comphelper::SolarMutex::tryToAcquire();
1744baec725SJan-Marek Glogowski     }
1754baec725SJan-Marek Glogowski     else
1764baec725SJan-Marek Glogowski         return false;
1774baec725SJan-Marek Glogowski }
1784baec725SJan-Marek Glogowski 
ImplSalYieldMutexAcquireWithWait(sal_uInt32 nCount)179adbf7da7SStephan Bergmann void ImplSalYieldMutexAcquireWithWait( sal_uInt32 nCount )
1803840aedeSJan-Marek Glogowski {
1817c52d86fSNoel Grandin     WinSalInstance* pInst = GetSalData()->mpInstance;
1823840aedeSJan-Marek Glogowski     if ( pInst )
1830c27134fSJan-Marek Glogowski         pInst->GetYieldMutex()->acquire( nCount );
1849c997095SArmin Le Grand }
1858ab086b6SJens-Heiner Rechtien 
ImplSalYieldMutexTryToAcquire()186381f8a56SChris Sherlock bool ImplSalYieldMutexTryToAcquire()
1878ab086b6SJens-Heiner Rechtien {
1887c52d86fSNoel Grandin     WinSalInstance* pInst = GetSalData()->mpInstance;
1890c27134fSJan-Marek Glogowski     return pInst && pInst->GetYieldMutex()->tryToAcquire();
1908ab086b6SJens-Heiner Rechtien }
1918ab086b6SJens-Heiner Rechtien 
ImplSalYieldMutexRelease()1928ab086b6SJens-Heiner Rechtien void ImplSalYieldMutexRelease()
1938ab086b6SJens-Heiner Rechtien {
1947c52d86fSNoel Grandin     WinSalInstance* pInst = GetSalData()->mpInstance;
1958ab086b6SJens-Heiner Rechtien     if ( pInst )
1966bd12d86Sth     {
1976bd12d86Sth         GdiFlush();
1980c27134fSJan-Marek Glogowski         pInst->GetYieldMutex()->release();
1998ab086b6SJens-Heiner Rechtien     }
2006bd12d86Sth }
2018ab086b6SJens-Heiner Rechtien 
IsCurrentThread() const2023840aedeSJan-Marek Glogowski bool SalYieldMutex::IsCurrentThread() const
2038ab086b6SJens-Heiner Rechtien {
204bf0a63dcSJan-Marek Glogowski     if ( !GetSalData()->mpInstance->m_nNoYieldLock )
205ec3916d4SStephan Bergmann         return SolarMutex::IsCurrentThread();
2064baec725SJan-Marek Glogowski     else
2077c52d86fSNoel Grandin         return GetSalData()->mpInstance->IsMainThread();
2088ab086b6SJens-Heiner Rechtien }
2098ab086b6SJens-Heiner Rechtien 
initKeyCodeMap()21015641441SOliver Bolte void SalData::initKeyCodeMap()
2118ab086b6SJens-Heiner Rechtien {
212d6b1e563SMike Kaganski     auto initKey = [this](wchar_t ch, sal_uInt16 key)
213d6b1e563SMike Kaganski     {
214d6b1e563SMike Kaganski         if (UINT vkey = LOWORD(VkKeyScanW(ch)); vkey < 0xffff)
215d6b1e563SMike Kaganski             maVKMap[vkey] = key;
216d6b1e563SMike Kaganski     };
21715641441SOliver Bolte 
2180761614cSJuergen Funk     maVKMap.clear();
2190761614cSJuergen Funk 
220362a21d3SMike Kaganski     initKey( L'+', KEY_ADD );
221362a21d3SMike Kaganski     initKey( L'-', KEY_SUBTRACT );
222362a21d3SMike Kaganski     initKey( L'*', KEY_MULTIPLY );
223362a21d3SMike Kaganski     initKey( L'/', KEY_DIVIDE );
224362a21d3SMike Kaganski     initKey( L'.', KEY_POINT );
225362a21d3SMike Kaganski     initKey( L',', KEY_COMMA );
226362a21d3SMike Kaganski     initKey( L'<', KEY_LESS );
227362a21d3SMike Kaganski     initKey( L'>', KEY_GREATER );
228362a21d3SMike Kaganski     initKey( L'=', KEY_EQUAL );
229362a21d3SMike Kaganski     initKey( L'~', KEY_TILDE );
230362a21d3SMike Kaganski     initKey( L'`', KEY_QUOTELEFT );
231362a21d3SMike Kaganski     initKey( L'[', KEY_BRACKETLEFT );
232362a21d3SMike Kaganski     initKey( L']', KEY_BRACKETRIGHT );
233362a21d3SMike Kaganski     initKey( L';', KEY_SEMICOLON );
234362a21d3SMike Kaganski     initKey( L'\'', KEY_QUOTERIGHT );
235d156e891SNoel Grandin     initKey( L'}', KEY_RIGHTCURLYBRACKET );
236ca745119SGökay Şatır     initKey( L'#', KEY_NUMBERSIGN);
237e056c1ceSJulien Nabet     initKey( L':', KEY_COLON );
2388ab086b6SJens-Heiner Rechtien }
2398ab086b6SJens-Heiner Rechtien 
240a45bdc49SJens-Heiner Rechtien // SalData
2410ce0c369SAlexander Wilms 
SalData()242a45bdc49SJens-Heiner Rechtien SalData::SalData()
243c35f8114SMike Kaganski     : sal::systools::CoInitializeGuard(COINIT_APARTMENTTHREADED, false,
244c35f8114SMike Kaganski                                        sal::systools::CoInitializeGuard::WhenFailed::NoThrow)
245c35f8114SMike Kaganski          // put main thread in Single Threaded Apartment (STA)
246a45bdc49SJens-Heiner Rechtien {
24748b1c889SStephan Bergmann     mhInst = nullptr;           // default instance handle
248a45bdc49SJens-Heiner Rechtien     mnCmdShow = 0;              // default frame show style
24948b1c889SStephan Bergmann     mhSalObjMsgHook = nullptr;  // hook to get interesting msg for SalObject
25048b1c889SStephan Bergmann     mhWantLeaveMsg = nullptr;   // window handle, that want a MOUSELEAVE message
2517c52d86fSNoel Grandin     mpInstance = nullptr;  // pointer of first instance
25248b1c889SStephan Bergmann     mpFirstFrame = nullptr;     // pointer of first frame
25348b1c889SStephan Bergmann     mpFirstObject = nullptr;    // pointer of first object window
25448b1c889SStephan Bergmann     mpFirstVD = nullptr;        // first VirDev
25548b1c889SStephan Bergmann     mpFirstPrinter = nullptr;   // first printing printer
25648b1c889SStephan Bergmann     mh50Bmp = nullptr;          // 50% Bitmap
25748b1c889SStephan Bergmann     mh50Brush = nullptr;        // 50% Brush
258a45bdc49SJens-Heiner Rechtien     int i;
259a45bdc49SJens-Heiner Rechtien     for(i=0; i<MAX_STOCKPEN; i++)
260a45bdc49SJens-Heiner Rechtien     {
261a45bdc49SJens-Heiner Rechtien         maStockPenColorAry[i] = 0;
26248b1c889SStephan Bergmann         mhStockPenAry[i] = nullptr;
263a45bdc49SJens-Heiner Rechtien     }
264a45bdc49SJens-Heiner Rechtien     for(i=0; i<MAX_STOCKBRUSH; i++)
265a45bdc49SJens-Heiner Rechtien     {
266a45bdc49SJens-Heiner Rechtien         maStockBrushColorAry[i] = 0;
26748b1c889SStephan Bergmann         mhStockBrushAry[i] = nullptr;
268a45bdc49SJens-Heiner Rechtien     }
269a45bdc49SJens-Heiner Rechtien     mnStockPenCount = 0;        // count of static pens
270a45bdc49SJens-Heiner Rechtien     mnStockBrushCount = 0;      // count of static brushes
271275dbf60SChristian M. Heller     mnSalObjWantKeyEvt = 0;     // KeyEvent for the SalObj hook
2727790b6a4SMichael Stahl     mbObjClassInit = false;     // is SALOBJECTCLASS initialised
273b5a2dbdbSAndrea Gelmini     mnAppThreadId = 0;          // Id from Application-Thread
27448b1c889SStephan Bergmann     mpFirstIcon = nullptr;      // icon cache, points to first icon, NULL if none
275*87ef0041SMike Kaganski     mpTempFontItem = nullptr;
2767790b6a4SMichael Stahl     mbThemeChanged = false;     // true if visual theme was changed: throw away theme handles
2777790b6a4SMichael Stahl     mbThemeMenuSupport = false;
278a45bdc49SJens-Heiner Rechtien 
27950afe624SJens-Heiner Rechtien     // init with NULL
28050afe624SJens-Heiner Rechtien     gdiplusToken = 0;
28150afe624SJens-Heiner Rechtien 
28215641441SOliver Bolte     initKeyCodeMap();
28315641441SOliver Bolte 
284a45bdc49SJens-Heiner Rechtien     SetSalData( this );
285a45bdc49SJens-Heiner Rechtien     initNWF();
2861698debeSJan-Marek Glogowski 
2871698debeSJan-Marek Glogowski     static Gdiplus::GdiplusStartupInput gdiplusStartupInput;
2881698debeSJan-Marek Glogowski     Gdiplus::GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, nullptr);
289a45bdc49SJens-Heiner Rechtien }
290a45bdc49SJens-Heiner Rechtien 
~SalData()291a45bdc49SJens-Heiner Rechtien SalData::~SalData()
292a45bdc49SJens-Heiner Rechtien {
293a45bdc49SJens-Heiner Rechtien     deInitNWF();
29448b1c889SStephan Bergmann     SetSalData( nullptr );
2958ab086b6SJens-Heiner Rechtien 
2961698debeSJan-Marek Glogowski     if (gdiplusToken)
2971698debeSJan-Marek Glogowski         Gdiplus::GdiplusShutdown(gdiplusToken);
29850afe624SJens-Heiner Rechtien }
29950afe624SJens-Heiner Rechtien 
OSSupportsDarkMode()300a3f40088SCaolán McNamara bool OSSupportsDarkMode()
301a3f40088SCaolán McNamara {
3020bf5756bSMichael Weghorn     return WinSalInstance::getWindowsBuildNumber() >= 18362;
303a3f40088SCaolán McNamara }
304a3f40088SCaolán McNamara 
305a0202e0bSStephan Bergmann namespace {
306a0202e0bSStephan Bergmann 
307a3f40088SCaolán McNamara enum PreferredAppMode
308a3f40088SCaolán McNamara {
309a3f40088SCaolán McNamara     Default,
310a3f40088SCaolán McNamara     AllowDark,
311a3f40088SCaolán McNamara     ForceDark,
312a3f40088SCaolán McNamara     ForceLight,
313a3f40088SCaolán McNamara     Max
314a3f40088SCaolán McNamara };
315a3f40088SCaolán McNamara 
316a0202e0bSStephan Bergmann }
317a0202e0bSStephan Bergmann 
3181698debeSJan-Marek Glogowski extern "C" {
create_SalInstance()3191698debeSJan-Marek Glogowski VCLPLUG_WIN_PUBLIC SalInstance* create_SalInstance()
3201698debeSJan-Marek Glogowski {
3211698debeSJan-Marek Glogowski     SalData* pSalData = new SalData();
3228ab086b6SJens-Heiner Rechtien 
323e143c83bSMike Kaganski     STARTUPINFOW aSI{ .cb = sizeof(aSI) };
324362a21d3SMike Kaganski     GetStartupInfoW( &aSI );
3251698debeSJan-Marek Glogowski     pSalData->mhInst = GetModuleHandleW( nullptr );
3261698debeSJan-Marek Glogowski     pSalData->mnCmdShow = aSI.wShowWindow;
3278ab086b6SJens-Heiner Rechtien 
3288ab086b6SJens-Heiner Rechtien     pSalData->mnAppThreadId = GetCurrentThreadId();
3298ab086b6SJens-Heiner Rechtien 
330a3f40088SCaolán McNamara     static bool bSetAllowDarkMode = OSSupportsDarkMode(); // too early to additionally check LibreOffice's config
331a3f40088SCaolán McNamara     if (bSetAllowDarkMode)
332a3f40088SCaolán McNamara     {
333a3f40088SCaolán McNamara         typedef PreferredAppMode(WINAPI* SetPreferredAppMode_t)(PreferredAppMode);
334a3f40088SCaolán McNamara         if (HINSTANCE hUxthemeLib = LoadLibraryExW(L"uxtheme.dll", nullptr, LOAD_LIBRARY_SEARCH_SYSTEM32))
335a3f40088SCaolán McNamara         {
336a3f40088SCaolán McNamara             if (auto SetPreferredAppMode = reinterpret_cast<SetPreferredAppMode_t>(GetProcAddress(hUxthemeLib, MAKEINTRESOURCEA(135))))
337a3f40088SCaolán McNamara                 SetPreferredAppMode(AllowDark);
338a3f40088SCaolán McNamara             FreeLibrary(hUxthemeLib);
339a3f40088SCaolán McNamara         }
340a3f40088SCaolán McNamara     }
341a3f40088SCaolán McNamara 
3428ab086b6SJens-Heiner Rechtien     // register frame class
3438ab086b6SJens-Heiner Rechtien     WNDCLASSEXW aWndClassEx;
3448ab086b6SJens-Heiner Rechtien     aWndClassEx.cbSize          = sizeof( aWndClassEx );
3458ab086b6SJens-Heiner Rechtien     aWndClassEx.style           = CS_OWNDC;
3468ab086b6SJens-Heiner Rechtien     aWndClassEx.lpfnWndProc     = SalFrameWndProcW;
3478ab086b6SJens-Heiner Rechtien     aWndClassEx.cbClsExtra      = 0;
3488ab086b6SJens-Heiner Rechtien     aWndClassEx.cbWndExtra      = SAL_FRAME_WNDEXTRA;
3498ab086b6SJens-Heiner Rechtien     aWndClassEx.hInstance       = pSalData->mhInst;
35048b1c889SStephan Bergmann     aWndClassEx.hCursor         = nullptr;
35148b1c889SStephan Bergmann     aWndClassEx.hbrBackground   = nullptr;
35248b1c889SStephan Bergmann     aWndClassEx.lpszMenuName    = nullptr;
3538ab086b6SJens-Heiner Rechtien     aWndClassEx.lpszClassName   = SAL_FRAME_CLASSNAMEW;
35430febe79SJan Holesovsky     ImplLoadSalIcon( SAL_RESID_ICON_DEFAULT, aWndClassEx.hIcon, aWndClassEx.hIconSm );
35537c198cfSJesús Corrius     if ( !RegisterClassExW( &aWndClassEx ) )
35648b1c889SStephan Bergmann         return nullptr;
3570c2a2e1aSth 
35848b1c889SStephan Bergmann     aWndClassEx.hIcon           = nullptr;
35948b1c889SStephan Bergmann     aWndClassEx.hIconSm         = nullptr;
3608ab086b6SJens-Heiner Rechtien     aWndClassEx.style          |= CS_SAVEBITS;
3610c2a2e1aSth     aWndClassEx.lpszClassName   = SAL_SUBFRAME_CLASSNAMEW;
36237c198cfSJesús Corrius     if ( !RegisterClassExW( &aWndClassEx ) )
36348b1c889SStephan Bergmann         return nullptr;
3648ab086b6SJens-Heiner Rechtien 
3652f382d6cSJens-Heiner Rechtien     // shadow effect for popups on XP
3662f382d6cSJens-Heiner Rechtien     aWndClassEx.style          |= CS_DROPSHADOW;
3672f382d6cSJens-Heiner Rechtien     aWndClassEx.lpszClassName   = SAL_TMPSUBFRAME_CLASSNAMEW;
36837c198cfSJesús Corrius     if ( !RegisterClassExW( &aWndClassEx ) )
36948b1c889SStephan Bergmann         return nullptr;
3702f382d6cSJens-Heiner Rechtien 
3718ab086b6SJens-Heiner Rechtien     aWndClassEx.style           = 0;
3728ab086b6SJens-Heiner Rechtien     aWndClassEx.lpfnWndProc     = SalComWndProcW;
3738ab086b6SJens-Heiner Rechtien     aWndClassEx.cbWndExtra      = 0;
3748ab086b6SJens-Heiner Rechtien     aWndClassEx.lpszClassName   = SAL_COM_CLASSNAMEW;
37537c198cfSJesús Corrius     if ( !RegisterClassExW( &aWndClassEx ) )
37648b1c889SStephan Bergmann         return nullptr;
3778ab086b6SJens-Heiner Rechtien 
37837c198cfSJesús Corrius     HWND hComWnd = CreateWindowExW( WS_EX_TOOLWINDOW, SAL_COM_CLASSNAMEW,
37948b1c889SStephan Bergmann                                L"", WS_POPUP, 0, 0, 0, 0, nullptr, nullptr,
38048b1c889SStephan Bergmann                                pSalData->mhInst, nullptr );
3818ab086b6SJens-Heiner Rechtien     if ( !hComWnd )
38248b1c889SStephan Bergmann         return nullptr;
3838ab086b6SJens-Heiner Rechtien 
384f3d5aa2bSKurt Zenker     WinSalInstance* pInst = new WinSalInstance;
3858ab086b6SJens-Heiner Rechtien 
3868ab086b6SJens-Heiner Rechtien     // init instance (only one instance in this version !!!)
3877c52d86fSNoel Grandin     pSalData->mpInstance   = pInst;
388f3d5aa2bSKurt Zenker     pInst->mhInst    = pSalData->mhInst;
389f3d5aa2bSKurt Zenker     pInst->mhComWnd  = hComWnd;
3908ab086b6SJens-Heiner Rechtien 
3918ab086b6SJens-Heiner Rechtien     // init static GDI Data
3928ab086b6SJens-Heiner Rechtien     ImplInitSalGDI();
3938ab086b6SJens-Heiner Rechtien 
3948ab086b6SJens-Heiner Rechtien     return pInst;
3958ab086b6SJens-Heiner Rechtien }
3968ab086b6SJens-Heiner Rechtien }
3978ab086b6SJens-Heiner Rechtien 
WinSalInstance()398f3d5aa2bSKurt Zenker WinSalInstance::WinSalInstance()
39943635b47SGabor Kelemen     : SalInstance(std::make_unique<SalYieldMutex>())
400f222cec7SCaolán McNamara     , mhInst( nullptr )
4010c27134fSJan-Marek Glogowski     , mhComWnd( nullptr )
402bf0a63dcSJan-Marek Glogowski     , m_nNoYieldLock( 0 )
4038ab086b6SJens-Heiner Rechtien {
4041698debeSJan-Marek Glogowski     ImplSVData* pSVData = ImplGetSVData();
4051698debeSJan-Marek Glogowski     pSVData->maAppData.mxToolkitName = OUString("win");
40650238bddSJan-Marek Glogowski     m_bSupportsOpenGL = true;
407a3d3e076SLuboš Luňák     WinSkiaSalGraphicsImpl::prepareSkia();
4088ab086b6SJens-Heiner Rechtien }
4098ab086b6SJens-Heiner Rechtien 
~WinSalInstance()410f3d5aa2bSKurt Zenker WinSalInstance::~WinSalInstance()
4118ab086b6SJens-Heiner Rechtien {
4121698debeSJan-Marek Glogowski     ImplFreeSalGDI();
413f3d5aa2bSKurt Zenker     DestroyWindow( mhComWnd );
414ea5eb463SLuboš Luňák     SkiaHelper::cleanup();
4158ab086b6SJens-Heiner Rechtien }
4168ab086b6SJens-Heiner Rechtien 
AfterAppInit()4174ff2ee08SNoel Grandin void WinSalInstance::AfterAppInit()
4184ff2ee08SNoel Grandin {
4194ff2ee08SNoel Grandin // (1) Ideally this would be done at the place that creates the thread, but since this thread is normally
4204ff2ee08SNoel Grandin // just the default/main thread, that is not possible.
4214ff2ee08SNoel Grandin // (2) Don't do this on unix, where it causes tools like pstree on Linux to
4224ff2ee08SNoel Grandin // confusingly report soffice.bin as VCL Main instead.
4234ff2ee08SNoel Grandin     osl_setThreadName("VCL Main");
4244ff2ee08SNoel Grandin }
4254ff2ee08SNoel Grandin 
ImplSalDispatchMessage(const MSG * pMsg)4268ba60ca4SJan-Marek Glogowski static LRESULT ImplSalDispatchMessage( const MSG* pMsg )
4278ab086b6SJens-Heiner Rechtien {
4288ab086b6SJens-Heiner Rechtien     SalData* pSalData = GetSalData();
42947ee8098SJan-Marek Glogowski     if ( pSalData->mpFirstObject && ImplSalPreDispatchMsg( pMsg ) )
43047ee8098SJan-Marek Glogowski         return 0;
43150c62725STor Lillqvist     LRESULT lResult = DispatchMessageW( pMsg );
4328ab086b6SJens-Heiner Rechtien     if ( pSalData->mpFirstObject )
4338ba60ca4SJan-Marek Glogowski         ImplSalPostDispatchMsg( pMsg );
43447ee8098SJan-Marek Glogowski     return lResult;
4358ab086b6SJens-Heiner Rechtien }
4368ab086b6SJens-Heiner Rechtien 
437dbac52a2SJan-Marek Glogowski // probably can't be static, because of SalTimer friend? (static gives C4211)
ImplSalYield(const bool bWait,const bool bHandleAllCurrentEvents)438dbac52a2SJan-Marek Glogowski bool ImplSalYield(const bool bWait, const bool bHandleAllCurrentEvents)
4398ab086b6SJens-Heiner Rechtien {
440dbac52a2SJan-Marek Glogowski     // used to abort further message processing on tick count wraps
4419679fb26SJan-Marek Glogowski     static sal_uInt32 nLastTicks = 0;
44235a25475SJan-Marek Glogowski 
443dbac52a2SJan-Marek Glogowski     // we should never yield in m_nNoYieldLock mode!
444dbac52a2SJan-Marek Glogowski     const bool bNoYieldLock = (GetSalData()->mpInstance->m_nNoYieldLock > 0);
44535a25475SJan-Marek Glogowski     assert(!bNoYieldLock);
44635a25475SJan-Marek Glogowski     if (bNoYieldLock)
44735a25475SJan-Marek Glogowski         return false;
4488ab086b6SJens-Heiner Rechtien 
449dbac52a2SJan-Marek Glogowski     MSG aMsg;
450dbac52a2SJan-Marek Glogowski     bool bWasMsg = false, bWasTimeoutMsg = false;
451dbac52a2SJan-Marek Glogowski     WinSalTimer* pTimer = static_cast<WinSalTimer*>(ImplGetSVData()->maSchedCtx.mpSalTimer);
4529679fb26SJan-Marek Glogowski 
453dbac52a2SJan-Marek Glogowski     sal_uInt32 nCurTicks = GetTickCount();
454dbac52a2SJan-Marek Glogowski 
45576c27ae4SOliver Bolte     do
4568ab086b6SJens-Heiner Rechtien     {
457dbac52a2SJan-Marek Glogowski         if (!PeekMessageW(&aMsg, nullptr, 0, 0, PM_REMOVE))
458dbac52a2SJan-Marek Glogowski             break;
459dbac52a2SJan-Marek Glogowski 
46037436815SJan-Marek Glogowski         bWasMsg = true;
4618ab086b6SJens-Heiner Rechtien         TranslateMessage(&aMsg);
46247ee8098SJan-Marek Glogowski         LRESULT nRet = ImplSalDispatchMessage(&aMsg);
46347ee8098SJan-Marek Glogowski 
464dbac52a2SJan-Marek Glogowski         bWasTimeoutMsg |= (SAL_MSG_TIMER_CALLBACK == aMsg.message) && static_cast<bool>(nRet);
46547ee8098SJan-Marek Glogowski 
466dbac52a2SJan-Marek Glogowski         if (!bHandleAllCurrentEvents)
467dbac52a2SJan-Marek Glogowski             break;
468fb4e7be5SJan-Marek Glogowski 
469dbac52a2SJan-Marek Glogowski         if ((aMsg.time > nCurTicks) && (nLastTicks <= nCurTicks || aMsg.time < nLastTicks))
4709679fb26SJan-Marek Glogowski             break;
471448e9da1SJan-Marek Glogowski     }
4729679fb26SJan-Marek Glogowski     while( true );
4739679fb26SJan-Marek Glogowski 
474fb4e7be5SJan-Marek Glogowski     // 0ms timeouts are handled out-of-bounds to prevent busy-locking the
47596a0adacSAndrea Gelmini     // event loop with timeout messages.
4761a97b9abSAndrea Gelmini     // We ensure we never handle more than one timeout per call.
477fb4e7be5SJan-Marek Glogowski     // This way we'll always process a normal system message.
478fb4e7be5SJan-Marek Glogowski     if ( !bWasTimeoutMsg && pTimer && pTimer->IsDirectTimeout() )
479fb4e7be5SJan-Marek Glogowski     {
480fb4e7be5SJan-Marek Glogowski         pTimer->ImplHandleElapsedTimer();
481fb4e7be5SJan-Marek Glogowski         bWasMsg = true;
482fb4e7be5SJan-Marek Glogowski     }
483fb4e7be5SJan-Marek Glogowski 
4849679fb26SJan-Marek Glogowski     nLastTicks = nCurTicks;
48576c27ae4SOliver Bolte 
486fb4e7be5SJan-Marek Glogowski     if ( bWait && !bWasMsg )
48776c27ae4SOliver Bolte     {
488dbac52a2SJan-Marek Glogowski         switch (GetMessageW(&aMsg, nullptr, 0, 0))
48976c27ae4SOliver Bolte         {
490dbac52a2SJan-Marek Glogowski             case -1:
4912a20616dSvarshneydevansh                 SAL_WARN("vcl.schedule", "GetMessageW failed: " << comphelper::WindowsErrorString(GetLastError()));
492dbac52a2SJan-Marek Glogowski                 // should we std::abort() / SalAbort here?
493dbac52a2SJan-Marek Glogowski                 break;
494dbac52a2SJan-Marek Glogowski             case 0:
495dbac52a2SJan-Marek Glogowski                 SAL_INFO("vcl.schedule", "GetMessageW received WM_QUIT while waiting");
496dbac52a2SJan-Marek Glogowski                 break;
497dbac52a2SJan-Marek Glogowski             default:
498448e9da1SJan-Marek Glogowski                 bWasMsg = true;
49976c27ae4SOliver Bolte                 TranslateMessage(&aMsg);
50076c27ae4SOliver Bolte                 ImplSalDispatchMessage(&aMsg);
501dbac52a2SJan-Marek Glogowski                 break;
5028ab086b6SJens-Heiner Rechtien         }
5038ab086b6SJens-Heiner Rechtien     }
5049679fb26SJan-Marek Glogowski 
505c6ff20f1SAndrea Gelmini     // If we enabled ForceRealTimer mode skipping our direct timeout processing,
506c6ff20f1SAndrea Gelmini     // mainly because some Windows API call spawns its own nested message loop,
507dbac52a2SJan-Marek Glogowski     // switch back to our own processing (like after window resize or move)
508abe3af8eSJan-Marek Glogowski     if ( pTimer )
509abe3af8eSJan-Marek Glogowski         pTimer->SetForceRealTimer( false );
510abe3af8eSJan-Marek Glogowski 
511d348035aSJan-Marek Glogowski     return bWasMsg;
5128ab086b6SJens-Heiner Rechtien }
5138ab086b6SJens-Heiner Rechtien 
IsMainThread() const514c0710abfSJan-Marek Glogowski bool WinSalInstance::IsMainThread() const
515c0710abfSJan-Marek Glogowski {
516c0710abfSJan-Marek Glogowski     const SalData* pSalData = GetSalData();
517c0710abfSJan-Marek Glogowski     return pSalData->mnAppThreadId == GetCurrentThreadId();
518c0710abfSJan-Marek Glogowski }
519c0710abfSJan-Marek Glogowski 
DoYield(bool bWait,bool bHandleAllCurrentEvents)5204baec725SJan-Marek Glogowski bool WinSalInstance::DoYield(bool bWait, bool bHandleAllCurrentEvents)
5218ab086b6SJens-Heiner Rechtien {
522d348035aSJan-Marek Glogowski     bool bDidWork = false;
5234baec725SJan-Marek Glogowski     SolarMutexReleaser aReleaser;
524c0710abfSJan-Marek Glogowski     if ( !IsMainThread() )
5258ab086b6SJens-Heiner Rechtien     {
526ce8bbb78SJan-Marek Glogowski         bDidWork = SendMessageW( mhComWnd, SAL_MSG_THREADYIELD,
5279af8f190SStephan Bergmann                                  WPARAM(false), static_cast<LPARAM>(bHandleAllCurrentEvents) );
528ce8bbb78SJan-Marek Glogowski         if ( !bDidWork && bWait )
5294baec725SJan-Marek Glogowski         {
5304baec725SJan-Marek Glogowski             maWaitingYieldCond.reset();
5314baec725SJan-Marek Glogowski             maWaitingYieldCond.wait();
5324baec725SJan-Marek Glogowski             bDidWork = true;
5334baec725SJan-Marek Glogowski         }
5348ab086b6SJens-Heiner Rechtien     }
5358ab086b6SJens-Heiner Rechtien     else
5368ab086b6SJens-Heiner Rechtien     {
537d348035aSJan-Marek Glogowski         bDidWork = ImplSalYield( bWait, bHandleAllCurrentEvents );
5384baec725SJan-Marek Glogowski         if ( bDidWork )
5394baec725SJan-Marek Glogowski             maWaitingYieldCond.set();
540ea3ce0b3SMichael Stahl     }
5418ab086b6SJens-Heiner Rechtien 
542d348035aSJan-Marek Glogowski     return bDidWork;
5438ab086b6SJens-Heiner Rechtien }
5448ab086b6SJens-Heiner Rechtien 
545d6b1e563SMike Kaganski namespace
546d6b1e563SMike Kaganski {
547d6b1e563SMike Kaganski struct NoYieldLockGuard
548d6b1e563SMike Kaganski {
NoYieldLockGuard__anonc363b8950311::NoYieldLockGuard549d6b1e563SMike Kaganski     NoYieldLockGuard()
550d6b1e563SMike Kaganski         : counter(InSendMessage() ? GetSalData()->mpInstance->m_nNoYieldLock : dummy())
551d6b1e563SMike Kaganski     {
552d6b1e563SMike Kaganski         ++counter;
553d6b1e563SMike Kaganski     }
~NoYieldLockGuard__anonc363b8950311::NoYieldLockGuard554d6b1e563SMike Kaganski     ~NoYieldLockGuard() { --counter; }
dummy__anonc363b8950311::NoYieldLockGuard555d6b1e563SMike Kaganski     static decltype(WinSalInstance::m_nNoYieldLock)& dummy()
556d6b1e563SMike Kaganski     {
557d6b1e563SMike Kaganski         DBG_TESTSOLARMUTEX(); // called when !InSendMessage()
558d6b1e563SMike Kaganski         static decltype(WinSalInstance::m_nNoYieldLock) n = 0;
559d6b1e563SMike Kaganski         return n;
560d6b1e563SMike Kaganski     }
561d6b1e563SMike Kaganski     decltype(WinSalInstance::m_nNoYieldLock)& counter;
562d6b1e563SMike Kaganski };
563d6b1e563SMike Kaganski }
5648ba60ca4SJan-Marek Glogowski 
SalComWndProc(HWND,UINT nMsg,WPARAM wParam,LPARAM lParam,bool & rDef)5658ba60ca4SJan-Marek Glogowski LRESULT CALLBACK SalComWndProc( HWND, UINT nMsg, WPARAM wParam, LPARAM lParam, bool& rDef )
5668ab086b6SJens-Heiner Rechtien {
5678ab086b6SJens-Heiner Rechtien     LRESULT nRet = 0;
5688ba60ca4SJan-Marek Glogowski     WinSalTimer *const pTimer = static_cast<WinSalTimer*>( ImplGetSVData()->maSchedCtx.mpSalTimer );
5698ab086b6SJens-Heiner Rechtien 
57035a25475SJan-Marek Glogowski     SAL_INFO("vcl.gdi.wndproc", "SalComWndProc(nMsg=" << nMsg << ", wParam=" << wParam
571d6b1e563SMike Kaganski                                 << ", lParam=" << lParam << "); inSendMsg: " << InSendMessage());
572bb2443ccSThorsten Behrens 
57314eff34dSNoel Grandin     if (ImplGetSVData()->mbDeInit)
57414eff34dSNoel Grandin     {
57514eff34dSNoel Grandin         SAL_WARN("vcl.gdi.wndproc", "ignoring timer event because we are shutting down");
57614eff34dSNoel Grandin         return 0;
57714eff34dSNoel Grandin     }
57814eff34dSNoel Grandin 
5798ab086b6SJens-Heiner Rechtien     switch ( nMsg )
5808ab086b6SJens-Heiner Rechtien     {
5818ab086b6SJens-Heiner Rechtien         case SAL_MSG_THREADYIELD:
5829af8f190SStephan Bergmann             assert( !static_cast<bool>(wParam) );
5838ba60ca4SJan-Marek Glogowski             nRet = static_cast<LRESULT>(ImplSalYield(
5848ba60ca4SJan-Marek Glogowski                 false, static_cast<bool>( lParam ) ));
5858ab086b6SJens-Heiner Rechtien             break;
5868ba60ca4SJan-Marek Glogowski 
5878ab086b6SJens-Heiner Rechtien         case SAL_MSG_STARTTIMER:
5885229f159SJan-Marek Glogowski         {
589e23f811cSStephan Bergmann             auto const nParam = static_cast<sal_uInt64>( lParam );
590448e9da1SJan-Marek Glogowski             sal_uInt64 nTime = tools::Time::GetSystemTicks();
591e23f811cSStephan Bergmann             if ( nTime < nParam )
592e23f811cSStephan Bergmann                 nTime = nParam - nTime;
5935229f159SJan-Marek Glogowski             else
5945229f159SJan-Marek Glogowski                 nTime = 0;
5958ba60ca4SJan-Marek Glogowski             assert( pTimer != nullptr );
5968ba60ca4SJan-Marek Glogowski             pTimer->ImplStart( nTime );
5978ab086b6SJens-Heiner Rechtien             break;
5985229f159SJan-Marek Glogowski         }
5998ba60ca4SJan-Marek Glogowski 
6008a0e6b25SMichael Stahl         case SAL_MSG_STOPTIMER:
6018ba60ca4SJan-Marek Glogowski             assert( pTimer != nullptr );
6028ba60ca4SJan-Marek Glogowski             pTimer->ImplStop();
6038a0e6b25SMichael Stahl             break;
6048ba60ca4SJan-Marek Glogowski 
605d6b1e563SMike Kaganski         case (SAL_MSG_CREATEFRAME):
606d6b1e563SMike Kaganski             {
607d6b1e563SMike Kaganski                 NoYieldLockGuard g;
608d6b1e563SMike Kaganski                 nRet = reinterpret_cast<LRESULT>(
609d6b1e563SMike Kaganski                     ImplSalCreateFrame(GetSalData()->mpInstance, reinterpret_cast<HWND>(lParam),
610d6b1e563SMike Kaganski                                        static_cast<SalFrameStyleFlags>(wParam)));
611d6b1e563SMike Kaganski             }
612d6b1e563SMike Kaganski             break;
613d6b1e563SMike Kaganski         case (SAL_MSG_RECREATEHWND):
614d6b1e563SMike Kaganski             {
615d6b1e563SMike Kaganski                 NoYieldLockGuard g;
616d6b1e563SMike Kaganski                 nRet = reinterpret_cast<LRESULT>(ImplSalReCreateHWND(
617d6b1e563SMike Kaganski                     reinterpret_cast<HWND>(wParam), reinterpret_cast<HWND>(lParam), false));
618d6b1e563SMike Kaganski             }
619d6b1e563SMike Kaganski             break;
620d6b1e563SMike Kaganski         case (SAL_MSG_RECREATECHILDHWND):
621d6b1e563SMike Kaganski             {
622d6b1e563SMike Kaganski                 NoYieldLockGuard g;
623d6b1e563SMike Kaganski                 nRet = reinterpret_cast<LRESULT>(ImplSalReCreateHWND(
624d6b1e563SMike Kaganski                     reinterpret_cast<HWND>(wParam), reinterpret_cast<HWND>(lParam), true));
625d6b1e563SMike Kaganski             }
626d6b1e563SMike Kaganski             break;
627d6b1e563SMike Kaganski         case (SAL_MSG_DESTROYFRAME):
628d6b1e563SMike Kaganski             {
629d6b1e563SMike Kaganski                 NoYieldLockGuard g;
630d6b1e563SMike Kaganski                 delete reinterpret_cast<SalFrame*>(lParam);
631d6b1e563SMike Kaganski             }
632d6b1e563SMike Kaganski             break;
6338ba60ca4SJan-Marek Glogowski 
63427bb6f2bSOliver Bolte         case SAL_MSG_DESTROYHWND:
63527bb6f2bSOliver Bolte             // We only destroy the native window here. We do NOT destroy the SalFrame contained
63627bb6f2bSOliver Bolte             // in the structure (GetWindowPtr()).
63748b1c889SStephan Bergmann             if (DestroyWindow(reinterpret_cast<HWND>(lParam)) == 0)
63827bb6f2bSOliver Bolte             {
6390c35d637SThomas Arnhold                 OSL_FAIL("DestroyWindow failed!");
64027bb6f2bSOliver Bolte                 // Failure: We remove the SalFrame from the window structure. So we avoid that
64127bb6f2bSOliver Bolte                 // the window structure may contain an invalid pointer, once the SalFrame is deleted.
64248b1c889SStephan Bergmann                 SetWindowPtr(reinterpret_cast<HWND>(lParam), nullptr);
64327bb6f2bSOliver Bolte             }
64427bb6f2bSOliver Bolte             break;
6458ba60ca4SJan-Marek Glogowski 
646d6b1e563SMike Kaganski         case (SAL_MSG_CREATEOBJECT):
647d6b1e563SMike Kaganski             {
648d6b1e563SMike Kaganski                 NoYieldLockGuard g;
649d6b1e563SMike Kaganski                 nRet = reinterpret_cast<LRESULT>(ImplSalCreateObject(
650d6b1e563SMike Kaganski                     GetSalData()->mpInstance, reinterpret_cast<WinSalFrame*>(lParam)));
651d6b1e563SMike Kaganski             }
652d6b1e563SMike Kaganski             break;
653d6b1e563SMike Kaganski         case (SAL_MSG_DESTROYOBJECT):
654d6b1e563SMike Kaganski             {
655d6b1e563SMike Kaganski                 NoYieldLockGuard g;
656d6b1e563SMike Kaganski                 delete reinterpret_cast<SalObject*>(lParam);
657d6b1e563SMike Kaganski             }
658d6b1e563SMike Kaganski             break;
659fa5b2905SNoel Grandin         case (SAL_MSG_GETCACHEDDC):
660fa5b2905SNoel Grandin             {
661fa5b2905SNoel Grandin                 NoYieldLockGuard g;
662fa5b2905SNoel Grandin                 nRet = reinterpret_cast<LRESULT>(
663fa5b2905SNoel Grandin                     GetDCEx(reinterpret_cast<HWND>(wParam), nullptr, 0x00000002L));
664fa5b2905SNoel Grandin             }
665fa5b2905SNoel Grandin             break;
666d6b1e563SMike Kaganski         case (SAL_MSG_RELEASEDC):
667d6b1e563SMike Kaganski             {
668d6b1e563SMike Kaganski                 NoYieldLockGuard g;
669d6b1e563SMike Kaganski                 ReleaseDC(reinterpret_cast<HWND>(wParam), reinterpret_cast<HDC>(lParam));
670d6b1e563SMike Kaganski             }
671d6b1e563SMike Kaganski             break;
6728ba60ca4SJan-Marek Glogowski 
673211b3192SJan Holesovsky         case SAL_MSG_TIMER_CALLBACK:
674448e9da1SJan-Marek Glogowski             assert( pTimer != nullptr );
6754c356a3eSJan-Marek Glogowski             pTimer->ImplHandleTimerEvent( wParam );
676b0aec7c6SVladimir Glazounov             break;
6778ba60ca4SJan-Marek Glogowski 
678abe3af8eSJan-Marek Glogowski         case WM_TIMER:
679abe3af8eSJan-Marek Glogowski             assert( pTimer != nullptr );
6804c356a3eSJan-Marek Glogowski             pTimer->ImplHandle_WM_TIMER( wParam );
681abe3af8eSJan-Marek Glogowski             break;
6828ba60ca4SJan-Marek Glogowski 
6835bb798a9SJan-Marek Glogowski         case SAL_MSG_FORCE_REAL_TIMER:
6845bb798a9SJan-Marek Glogowski             assert(pTimer != nullptr);
6855bb798a9SJan-Marek Glogowski             pTimer->SetForceRealTimer(true);
6865bb798a9SJan-Marek Glogowski             break;
6875bb798a9SJan-Marek Glogowski 
6888ba60ca4SJan-Marek Glogowski         case SAL_MSG_DUMMY:
6898ba60ca4SJan-Marek Glogowski             break;
6908ba60ca4SJan-Marek Glogowski 
6918ba60ca4SJan-Marek Glogowski         default:
6928ba60ca4SJan-Marek Glogowski             rDef = true;
6938ba60ca4SJan-Marek Glogowski             break;
694448e9da1SJan-Marek Glogowski     }
6958ab086b6SJens-Heiner Rechtien 
6968ab086b6SJens-Heiner Rechtien     return nRet;
6978ab086b6SJens-Heiner Rechtien }
6988ab086b6SJens-Heiner Rechtien 
SalComWndProcW(HWND hWnd,UINT nMsg,WPARAM wParam,LPARAM lParam)6998ab086b6SJens-Heiner Rechtien LRESULT CALLBACK SalComWndProcW( HWND hWnd, UINT nMsg, WPARAM wParam, LPARAM lParam )
7008ab086b6SJens-Heiner Rechtien {
7018ba60ca4SJan-Marek Glogowski     bool bDef = false;
7026f221e09SJens-Heiner Rechtien     LRESULT nRet = 0;
7036f221e09SJens-Heiner Rechtien     __try
7046f221e09SJens-Heiner Rechtien     {
7056f221e09SJens-Heiner Rechtien         nRet = SalComWndProc( hWnd, nMsg, wParam, lParam, bDef );
7066f221e09SJens-Heiner Rechtien     }
707b2cf2780SOliver Bolte     __except(WinSalInstance::WorkaroundExceptionHandlingInUSER32Lib(GetExceptionCode(), GetExceptionInformation()))
7086f221e09SJens-Heiner Rechtien     {
7096f221e09SJens-Heiner Rechtien     }
7108ab086b6SJens-Heiner Rechtien     if ( bDef )
7118ab086b6SJens-Heiner Rechtien     {
7128ab086b6SJens-Heiner Rechtien         if ( !ImplHandleGlobalMsg( hWnd, nMsg, wParam, lParam, nRet ) )
71337c198cfSJesús Corrius             nRet = DefWindowProcW( hWnd, nMsg, wParam, lParam );
7148ab086b6SJens-Heiner Rechtien     }
7158ab086b6SJens-Heiner Rechtien     return nRet;
7168ab086b6SJens-Heiner Rechtien }
7178ab086b6SJens-Heiner Rechtien 
AnyInput(VclInputFlags nType)7188aa3cb98SNoel Grandin bool WinSalInstance::AnyInput( VclInputFlags nType )
7198ab086b6SJens-Heiner Rechtien {
7203bf6c970SJan-Marek Glogowski     if ( nType & VclInputFlags::TIMER )
7213bf6c970SJan-Marek Glogowski     {
7223bf6c970SJan-Marek Glogowski         const WinSalTimer* pTimer = static_cast<WinSalTimer*>( ImplGetSVData()->maSchedCtx.mpSalTimer );
7233bf6c970SJan-Marek Glogowski         if ( pTimer && pTimer->HasTimerElapsed() )
7243bf6c970SJan-Marek Glogowski             return true;
7253bf6c970SJan-Marek Glogowski     }
7263bf6c970SJan-Marek Glogowski 
727843af72bSLuboš Luňák     // Note: Do not use PeekMessage(), despite the name it may dispatch events,
728843af72bSLuboš Luňák     // even with PM_NOREMOVE specified, which may lead to unwanted recursion.
729843af72bSLuboš Luňák 
7308aa3cb98SNoel Grandin     if ( (nType & VCL_INPUT_ANY) == VCL_INPUT_ANY )
7318ab086b6SJens-Heiner Rechtien     {
732ca3ae26fSRüdiger Timm         // revert bugfix for #108919# which never reported timeouts when called from the timer handler
733ca3ae26fSRüdiger Timm         // which made the application completely unresponsive during background formatting
734843af72bSLuboš Luňák         if ( GetQueueStatus( QS_ALLEVENTS ))
735ca3ae26fSRüdiger Timm             return true;
7368ab086b6SJens-Heiner Rechtien     }
7378ab086b6SJens-Heiner Rechtien     else
7388ab086b6SJens-Heiner Rechtien     {
739843af72bSLuboš Luňák         UINT flags = 0;
7403bf6c970SJan-Marek Glogowski 
741843af72bSLuboš Luňák         // This code previously considered modifier keys as OTHER,
742843af72bSLuboš Luňák         // but that makes this hard to do without PeekMessage,
743843af72bSLuboš Luňák         // is inconsistent with the X11 backend, and I see no good reason.
744843af72bSLuboš Luňák         if ( nType & VclInputFlags::KEYBOARD )
745843af72bSLuboš Luňák             flags |= QS_KEY;
7463bf6c970SJan-Marek Glogowski 
7478aa3cb98SNoel Grandin         if ( nType & VclInputFlags::MOUSE )
748843af72bSLuboš Luňák             flags |= QS_MOUSE;
7498ab086b6SJens-Heiner Rechtien 
7508aa3cb98SNoel Grandin         if ( nType & VclInputFlags::PAINT )
751843af72bSLuboš Luňák             flags |= QS_PAINT;
752f244634bSJens-Heiner Rechtien 
753843af72bSLuboš Luňák         if ( nType & VclInputFlags::TIMER )
754843af72bSLuboš Luňák             flags |= QS_TIMER;
755f244634bSJens-Heiner Rechtien 
756843af72bSLuboš Luňák         if( nType & VclInputFlags::OTHER )
757843af72bSLuboš Luňák             flags |= QS_ALLEVENTS & ~QS_KEY & ~QS_MOUSE & ~QS_PAINT & ~QS_TIMER;
758f244634bSJens-Heiner Rechtien 
759843af72bSLuboš Luňák         if( GetQueueStatus( flags ))
760f244634bSJens-Heiner Rechtien             return true;
7618ab086b6SJens-Heiner Rechtien     }
7628ab086b6SJens-Heiner Rechtien 
7637790b6a4SMichael Stahl     return false;
7648ab086b6SJens-Heiner Rechtien }
7658ab086b6SJens-Heiner Rechtien 
CreateChildFrame(SystemParentData * pSystemParentData,SalFrameStyleFlags nSalFrameStyle)7660e30af6fSNoel Grandin SalFrame* WinSalInstance::CreateChildFrame( SystemParentData* pSystemParentData, SalFrameStyleFlags nSalFrameStyle )
7678ab086b6SJens-Heiner Rechtien {
768275dbf60SChristian M. Heller     // to switch to Main-Thread
7699af8f190SStephan Bergmann     return reinterpret_cast<SalFrame*>(static_cast<sal_IntPtr>(SendMessageW( mhComWnd, SAL_MSG_CREATEFRAME, static_cast<WPARAM>(nSalFrameStyle), reinterpret_cast<LPARAM>(pSystemParentData->hWnd) )));
7708ab086b6SJens-Heiner Rechtien }
7718ab086b6SJens-Heiner Rechtien 
CreateFrame(SalFrame * pParent,SalFrameStyleFlags nSalFrameStyle)7720e30af6fSNoel Grandin SalFrame* WinSalInstance::CreateFrame( SalFrame* pParent, SalFrameStyleFlags nSalFrameStyle )
7738ab086b6SJens-Heiner Rechtien {
774275dbf60SChristian M. Heller     // to switch to Main-Thread
7758ab086b6SJens-Heiner Rechtien     HWND hWndParent;
7768ab086b6SJens-Heiner Rechtien     if ( pParent )
777f3d5aa2bSKurt Zenker         hWndParent = static_cast<WinSalFrame*>(pParent)->mhWnd;
7788ab086b6SJens-Heiner Rechtien     else
77948b1c889SStephan Bergmann         hWndParent = nullptr;
7809af8f190SStephan Bergmann     return reinterpret_cast<SalFrame*>(static_cast<sal_IntPtr>(SendMessageW( mhComWnd, SAL_MSG_CREATEFRAME, static_cast<WPARAM>(nSalFrameStyle), reinterpret_cast<LPARAM>(hWndParent) )));
7818ab086b6SJens-Heiner Rechtien }
7828ab086b6SJens-Heiner Rechtien 
DestroyFrame(SalFrame * pFrame)783f3d5aa2bSKurt Zenker void WinSalInstance::DestroyFrame( SalFrame* pFrame )
7848ab086b6SJens-Heiner Rechtien {
78529ec512eSMiklos Vajna     OpenGLContext::prepareForYield();
78648b1c889SStephan Bergmann     SendMessageW( mhComWnd, SAL_MSG_DESTROYFRAME, 0, reinterpret_cast<LPARAM>(pFrame) );
7878ab086b6SJens-Heiner Rechtien }
7888ab086b6SJens-Heiner Rechtien 
CreateObject(SalFrame * pParent,SystemWindowData *,bool)7890f1a0371SKurt Zenker SalObject* WinSalInstance::CreateObject( SalFrame* pParent,
7904bd692d1SVladimir Glazounov                                          SystemWindowData* /*pWindowData*/, // SystemWindowData meaningless on Windows
791381f8a56SChris Sherlock                                          bool /*bShow*/ )
7928ab086b6SJens-Heiner Rechtien {
793275dbf60SChristian M. Heller     // to switch to Main-Thread
7949af8f190SStephan Bergmann     return reinterpret_cast<SalObject*>(static_cast<sal_IntPtr>(SendMessageW( mhComWnd, SAL_MSG_CREATEOBJECT, 0, reinterpret_cast<LPARAM>(static_cast<WinSalFrame*>(pParent)) )));
7958ab086b6SJens-Heiner Rechtien }
7968ab086b6SJens-Heiner Rechtien 
DestroyObject(SalObject * pObject)797f3d5aa2bSKurt Zenker void WinSalInstance::DestroyObject( SalObject* pObject )
7988ab086b6SJens-Heiner Rechtien {
79948b1c889SStephan Bergmann     SendMessageW( mhComWnd, SAL_MSG_DESTROYOBJECT, 0, reinterpret_cast<LPARAM>(pObject) );
8008ab086b6SJens-Heiner Rechtien }
801489c112aSPhilipp Lohmann 
8029e18c9eeSVladimir Glazounov /** Add a file to the system shells recent document list if there is any.
8039e18c9eeSVladimir Glazounov       This function may have no effect under Unix because there is no
8049e18c9eeSVladimir Glazounov       standard API among the different desktop managers.
8059e18c9eeSVladimir Glazounov 
8069e18c9eeSVladimir Glazounov       @param aFileUrl
8079e18c9eeSVladimir Glazounov                 The file url of the document.
8089e18c9eeSVladimir Glazounov */
AddToRecentDocumentList(const OUString & rFileUrl,const OUString &,const OUString & rDocumentService)809e62fec40SJesús Corrius void WinSalInstance::AddToRecentDocumentList(const OUString& rFileUrl, const OUString& /*rMimeType*/, const OUString& rDocumentService)
8109e18c9eeSVladimir Glazounov {
811b07e8a7eSMichael Stahl     if (Application::IsHeadlessModeEnabled())
81294c26485SMichael Stahl         return;
81394c26485SMichael Stahl 
8141946794aSLuboš Luňák     OUString system_path;
8159e18c9eeSVladimir Glazounov     osl::FileBase::RC rc = osl::FileBase::getSystemPathFromFileURL(rFileUrl, system_path);
8169e18c9eeSVladimir Glazounov 
8179e18c9eeSVladimir Glazounov     OSL_ENSURE(osl::FileBase::E_None == rc, "Invalid file url");
8189e18c9eeSVladimir Glazounov 
8199e18c9eeSVladimir Glazounov     if (osl::FileBase::E_None == rc)
820e62fec40SJesús Corrius     {
82148b1c889SStephan Bergmann         IShellItem* pShellItem = nullptr;
822e62fec40SJesús Corrius 
8231944e3ddSMike Kaganski         HRESULT hr = SHCreateItemFromParsingName(o3tl::toW(system_path.getStr()), nullptr, IID_PPV_ARGS(&pShellItem));
824e62fec40SJesús Corrius 
825e62fec40SJesús Corrius         if ( SUCCEEDED(hr) && pShellItem )
826e62fec40SJesús Corrius         {
827e62fec40SJesús Corrius             OUString sApplicationName;
828e62fec40SJesús Corrius 
829e62fec40SJesús Corrius             if ( rDocumentService == "com.sun.star.text.TextDocument" ||
830e62fec40SJesús Corrius                  rDocumentService == "com.sun.star.text.GlobalDocument" ||
831e62fec40SJesús Corrius                  rDocumentService == "com.sun.star.text.WebDocument" ||
832e62fec40SJesús Corrius                  rDocumentService == "com.sun.star.xforms.XMLFormDocument" )
833e62fec40SJesús Corrius                 sApplicationName = "Writer";
834e62fec40SJesús Corrius             else if ( rDocumentService == "com.sun.star.sheet.SpreadsheetDocument" ||
835e62fec40SJesús Corrius                  rDocumentService == "com.sun.star.chart2.ChartDocument" )
836e62fec40SJesús Corrius                 sApplicationName = "Calc";
837e62fec40SJesús Corrius             else if ( rDocumentService == "com.sun.star.presentation.PresentationDocument" )
838e62fec40SJesús Corrius                 sApplicationName = "Impress";
839e62fec40SJesús Corrius             else if ( rDocumentService == "com.sun.star.drawing.DrawingDocument" )
840e62fec40SJesús Corrius                 sApplicationName = "Draw";
841e62fec40SJesús Corrius             else if ( rDocumentService == "com.sun.star.formula.FormulaProperties" )
842e62fec40SJesús Corrius                 sApplicationName = "Math";
843e62fec40SJesús Corrius             else if ( rDocumentService == "com.sun.star.sdb.DatabaseDocument" ||
844e62fec40SJesús Corrius                  rDocumentService == "com.sun.star.sdb.OfficeDatabaseDocument" ||
845e62fec40SJesús Corrius                  rDocumentService == "com.sun.star.sdb.RelationDesign" ||
846e62fec40SJesús Corrius                  rDocumentService == "com.sun.star.sdb.QueryDesign" ||
847e62fec40SJesús Corrius                  rDocumentService == "com.sun.star.sdb.TableDesign" ||
848e62fec40SJesús Corrius                  rDocumentService == "com.sun.star.sdb.DataSourceBrowser" )
849e62fec40SJesús Corrius                 sApplicationName = "Base";
850e62fec40SJesús Corrius 
851e62fec40SJesús Corrius             if ( !sApplicationName.isEmpty() )
852e62fec40SJesús Corrius             {
853044eba71SStephan Bergmann                 OUString sApplicationID("TheDocumentFoundation.LibreOffice." + sApplicationName);
854e62fec40SJesús Corrius 
855b411470bSMichael Stahl                 SHARDAPPIDINFO info;
856e62fec40SJesús Corrius                 info.psi = pShellItem;
8571944e3ddSMike Kaganski                 info.pszAppID = o3tl::toW(sApplicationID.getStr());
858e62fec40SJesús Corrius 
859e62fec40SJesús Corrius                 SHAddToRecentDocs ( SHARD_APPIDINFO, &info );
860e62fec40SJesús Corrius                 return;
861e62fec40SJesús Corrius             }
862e62fec40SJesús Corrius         }
863918ddde5SFridrich Štrba         // For whatever reason, we could not use the SHARD_APPIDINFO semantics
86448b1c889SStephan Bergmann         SHAddToRecentDocs(SHARD_PATHW, system_path.getStr());
8659e18c9eeSVladimir Glazounov     }
866e62fec40SJesús Corrius }
8679e18c9eeSVladimir Glazounov 
CreateSalTimer()868f3d5aa2bSKurt Zenker SalTimer* WinSalInstance::CreateSalTimer()
869f3d5aa2bSKurt Zenker {
870f3d5aa2bSKurt Zenker     return new WinSalTimer();
871f3d5aa2bSKurt Zenker }
872f3d5aa2bSKurt Zenker 
CreateSalBitmap()8738447d31eSNoel Grandin std::shared_ptr<SalBitmap> WinSalInstance::CreateSalBitmap()
874f3d5aa2bSKurt Zenker {
87507f480b7SNoel Grandin     assert(SkiaHelper::isVCLSkiaEnabled() && "Windows requires skia");
87671a07e88SLuboš Luňák     return std::make_shared<SkiaSalBitmap>();
877f3d5aa2bSKurt Zenker }
878f3d5aa2bSKurt Zenker 
WorkaroundExceptionHandlingInUSER32Lib(int,LPEXCEPTION_POINTERS pExceptionInfo)8792bd4648bSJens-Heiner Rechtien int WinSalInstance::WorkaroundExceptionHandlingInUSER32Lib(int, LPEXCEPTION_POINTERS pExceptionInfo)
880b2cf2780SOliver Bolte {
881b2cf2780SOliver Bolte     // Decide if an exception is a c++ (mostly UNO) exception or a process violation.
882b2cf2780SOliver Bolte     // Depending on this information we pass process violations directly to our signal handler ...
883b2cf2780SOliver Bolte     // and c++ (UNO) exceptions are sended to the following code on the current stack.
884b2cf2780SOliver Bolte     // Problem behind: user32.dll sometime consumes exceptions/process violations .-)
885b2cf2780SOliver Bolte     // see also #112221#
886b2cf2780SOliver Bolte 
88722767810STakeshi Abe     static const DWORD EXCEPTION_MSC_CPP_EXCEPTION = 0xE06D7363;
888b2cf2780SOliver Bolte 
889b2cf2780SOliver Bolte     if (pExceptionInfo->ExceptionRecord->ExceptionCode == EXCEPTION_MSC_CPP_EXCEPTION)
890b2cf2780SOliver Bolte         return EXCEPTION_CONTINUE_SEARCH;
891b2cf2780SOliver Bolte 
8928f461cd1SKurt Zenker     return UnhandledExceptionFilter( pExceptionInfo );
893b2cf2780SOliver Bolte }
89456a95946SMichael Meeks 
895b7e4e851SMike Kaganski typedef LONG NTSTATUS;
896b7e4e851SMike Kaganski typedef NTSTATUS(WINAPI* RtlGetVersion_t)(PRTL_OSVERSIONINFOW);
897b7e4e851SMike Kaganski constexpr NTSTATUS STATUS_SUCCESS = 0x00000000;
898b7e4e851SMike Kaganski 
getWinArch()8990bcb62c6SMike Kaganski static OUString getWinArch()
9000bcb62c6SMike Kaganski {
9010bcb62c6SMike Kaganski     USHORT nNativeMachine = IMAGE_FILE_MACHINE_UNKNOWN;
9020bcb62c6SMike Kaganski 
9030bcb62c6SMike Kaganski     using LPFN_ISWOW64PROCESS2 = BOOL(WINAPI*)(HANDLE, USHORT*, USHORT*);
9040bcb62c6SMike Kaganski     auto fnIsWow64Process2 = reinterpret_cast<LPFN_ISWOW64PROCESS2>(
9050bcb62c6SMike Kaganski         GetProcAddress(GetModuleHandleW(L"kernel32.dll"), "IsWow64Process2"));
9060bcb62c6SMike Kaganski     if (fnIsWow64Process2)
9070bcb62c6SMike Kaganski         fnIsWow64Process2(GetCurrentProcess(), &o3tl::temporary(USHORT()), &nNativeMachine);
9080bcb62c6SMike Kaganski 
9090bcb62c6SMike Kaganski     if (nNativeMachine == IMAGE_FILE_MACHINE_UNKNOWN)
910dc03e4fdSkubak     {
911dc03e4fdSkubak #if _WIN64
912dc03e4fdSkubak 
9130bcb62c6SMike Kaganski         nNativeMachine = IMAGE_FILE_MACHINE_AMD64;
914dc03e4fdSkubak 
915dc03e4fdSkubak #else
916dc03e4fdSkubak 
917dc03e4fdSkubak         BOOL isWow64 = FALSE;
918dc03e4fdSkubak 
919dc03e4fdSkubak         IsWow64Process(GetCurrentProcess(), &isWow64);
920dc03e4fdSkubak 
921dc03e4fdSkubak         if (isWow64)
9220bcb62c6SMike Kaganski             nNativeMachine = IMAGE_FILE_MACHINE_AMD64; // 32-bit process on 64-bit Windows
923dc03e4fdSkubak         else
9240bcb62c6SMike Kaganski             nNativeMachine = IMAGE_FILE_MACHINE_I386;
925dc03e4fdSkubak 
926dc03e4fdSkubak #endif
927dc03e4fdSkubak     }
928dc03e4fdSkubak 
9290bcb62c6SMike Kaganski     switch (nNativeMachine)
9300bcb62c6SMike Kaganski     {
9310bcb62c6SMike Kaganski         case IMAGE_FILE_MACHINE_I386:
9320bcb62c6SMike Kaganski             return u" X86_32"_ustr;
9330bcb62c6SMike Kaganski         case IMAGE_FILE_MACHINE_R3000:
9340bcb62c6SMike Kaganski             return u" R3000"_ustr;
9350bcb62c6SMike Kaganski         case IMAGE_FILE_MACHINE_R4000:
9360bcb62c6SMike Kaganski             return u" R4000"_ustr;
9370bcb62c6SMike Kaganski         case IMAGE_FILE_MACHINE_R10000:
9380bcb62c6SMike Kaganski             return u" R10000"_ustr;
9390bcb62c6SMike Kaganski         case IMAGE_FILE_MACHINE_WCEMIPSV2:
9400bcb62c6SMike Kaganski             return u" WCEMIPSV2"_ustr;
9410bcb62c6SMike Kaganski         case IMAGE_FILE_MACHINE_ALPHA:
9420bcb62c6SMike Kaganski             return u" ALPHA"_ustr;
9430bcb62c6SMike Kaganski         case IMAGE_FILE_MACHINE_SH3:
9440bcb62c6SMike Kaganski             return u" SH3"_ustr;
9450bcb62c6SMike Kaganski         case IMAGE_FILE_MACHINE_SH3DSP:
9460bcb62c6SMike Kaganski             return u" SH3DSP"_ustr;
9470bcb62c6SMike Kaganski         case IMAGE_FILE_MACHINE_SH3E:
9480bcb62c6SMike Kaganski             return u" SH3E"_ustr;
9490bcb62c6SMike Kaganski         case IMAGE_FILE_MACHINE_SH4:
9500bcb62c6SMike Kaganski             return u" SH4"_ustr;
9510bcb62c6SMike Kaganski         case IMAGE_FILE_MACHINE_SH5:
9520bcb62c6SMike Kaganski             return u" SH5"_ustr;
9530bcb62c6SMike Kaganski         case IMAGE_FILE_MACHINE_ARM:
9540bcb62c6SMike Kaganski             return u" ARM"_ustr;
9550bcb62c6SMike Kaganski         case IMAGE_FILE_MACHINE_THUMB:
9560bcb62c6SMike Kaganski             return u" THUMB"_ustr;
9570bcb62c6SMike Kaganski         case IMAGE_FILE_MACHINE_ARMNT:
9580bcb62c6SMike Kaganski             return u" ARMNT"_ustr;
9590bcb62c6SMike Kaganski         case IMAGE_FILE_MACHINE_AM33:
9600bcb62c6SMike Kaganski             return u" AM33"_ustr;
9610bcb62c6SMike Kaganski         case IMAGE_FILE_MACHINE_POWERPC:
9620bcb62c6SMike Kaganski             return u" POWERPC"_ustr;
9630bcb62c6SMike Kaganski         case IMAGE_FILE_MACHINE_POWERPCFP:
9640bcb62c6SMike Kaganski             return u" POWERPCFP"_ustr;
9650bcb62c6SMike Kaganski         case IMAGE_FILE_MACHINE_IA64:
9660bcb62c6SMike Kaganski             return u" IA64"_ustr;
9670bcb62c6SMike Kaganski         case IMAGE_FILE_MACHINE_MIPS16:
9680bcb62c6SMike Kaganski             return u" MIPS16"_ustr;
9690bcb62c6SMike Kaganski         case IMAGE_FILE_MACHINE_ALPHA64:
9700bcb62c6SMike Kaganski             return u" ALPHA64"_ustr;
9710bcb62c6SMike Kaganski         case IMAGE_FILE_MACHINE_MIPSFPU:
9720bcb62c6SMike Kaganski             return u" MIPSFPU"_ustr;
9730bcb62c6SMike Kaganski         case IMAGE_FILE_MACHINE_MIPSFPU16:
9740bcb62c6SMike Kaganski             return u" MIPSFPU16"_ustr;
9750bcb62c6SMike Kaganski         case IMAGE_FILE_MACHINE_TRICORE:
9760bcb62c6SMike Kaganski             return u" TRICORE"_ustr;
9770bcb62c6SMike Kaganski         case IMAGE_FILE_MACHINE_CEF:
9780bcb62c6SMike Kaganski             return u" CEF"_ustr;
9790bcb62c6SMike Kaganski         case IMAGE_FILE_MACHINE_EBC:
9800bcb62c6SMike Kaganski             return u" EBC"_ustr;
9810bcb62c6SMike Kaganski         case IMAGE_FILE_MACHINE_AMD64:
9820bcb62c6SMike Kaganski             return u" X86_64"_ustr;
9830bcb62c6SMike Kaganski         case IMAGE_FILE_MACHINE_M32R:
9840bcb62c6SMike Kaganski             return u" M32R"_ustr;
9850bcb62c6SMike Kaganski         case IMAGE_FILE_MACHINE_ARM64:
9860bcb62c6SMike Kaganski             return u" ARM64"_ustr;
9870bcb62c6SMike Kaganski         case IMAGE_FILE_MACHINE_CEE:
9880bcb62c6SMike Kaganski             return u" CEE"_ustr;
9890bcb62c6SMike Kaganski         default:
9900bcb62c6SMike Kaganski             assert(!"Yet unhandled case");
9910bcb62c6SMike Kaganski             return OUString();
9920bcb62c6SMike Kaganski     }
9930bcb62c6SMike Kaganski }
9940bcb62c6SMike Kaganski 
getOSVersionString(DWORD nBuildNumber)9955f00b748SMichael Weghorn static OUString getOSVersionString(DWORD nBuildNumber)
9962db558b5Skubak {
9970bcb62c6SMike Kaganski     OUStringBuffer result = u"Windows";
9982db558b5Skubak     if (nBuildNumber >= 22000)
9990bcb62c6SMike Kaganski         result.append(" 11");
10005f00b748SMichael Weghorn     else if (nBuildNumber > 0)
10010bcb62c6SMike Kaganski         result.append(" 10");
10020bcb62c6SMike Kaganski     else // We don't know what Windows it is
10030bcb62c6SMike Kaganski         result.append(" unknown");
10040bcb62c6SMike Kaganski 
10050bcb62c6SMike Kaganski     result.append(getWinArch());
10060bcb62c6SMike Kaganski 
10070bcb62c6SMike Kaganski     if (nBuildNumber)
10085f00b748SMichael Weghorn         result.append(" (build " + OUString::number(nBuildNumber) + ")");
10090bcb62c6SMike Kaganski 
10100bcb62c6SMike Kaganski     return result.makeStringAndClear();
10112db558b5Skubak }
10122db558b5Skubak 
getWindowsBuildNumber()10135f00b748SMichael Weghorn DWORD WinSalInstance::getWindowsBuildNumber()
101456a95946SMichael Meeks {
10155f00b748SMichael Weghorn     static const DWORD nResult = []
10160bcb62c6SMike Kaganski     {
10175f00b748SMichael Weghorn         DWORD nBuildNumber = 0;
10185f00b748SMichael Weghorn         // use RtlGetVersion to get build number
1019b7e4e851SMike Kaganski         if (HMODULE h_ntdll = GetModuleHandleW(L"ntdll.dll"))
1020b7e4e851SMike Kaganski         {
1021b7e4e851SMike Kaganski             if (auto RtlGetVersion
1022b7e4e851SMike Kaganski                 = reinterpret_cast<RtlGetVersion_t>(GetProcAddress(h_ntdll, "RtlGetVersion")))
1023b7e4e851SMike Kaganski             {
1024b7e4e851SMike Kaganski                 RTL_OSVERSIONINFOW vi2{}; // initialize with zeroes - a better alternative to memset
1025b7e4e851SMike Kaganski                 vi2.dwOSVersionInfoSize = sizeof(vi2);
1026b7e4e851SMike Kaganski                 if (STATUS_SUCCESS == RtlGetVersion(&vi2))
1027b7e4e851SMike Kaganski                 {
10285f00b748SMichael Weghorn                     nBuildNumber = vi2.dwBuildNumber;
1029b7e4e851SMike Kaganski                 }
1030b7e4e851SMike Kaganski             }
1031b7e4e851SMike Kaganski         }
10325f00b748SMichael Weghorn         return nBuildNumber;
10330bcb62c6SMike Kaganski     }();
10345f00b748SMichael Weghorn     return nResult;
1035a43b5e3dSMichael Weghorn }
1036a43b5e3dSMichael Weghorn 
getOSVersion()1037a43b5e3dSMichael Weghorn OUString WinSalInstance::getOSVersion()
1038a43b5e3dSMichael Weghorn {
10395f00b748SMichael Weghorn     return getOSVersionString(getWindowsBuildNumber());
104056a95946SMichael Meeks }
10414905a190SSebastian Spaeth 
BeforeAbort(const OUString &,bool)1042b6518bebSJan-Marek Glogowski void WinSalInstance::BeforeAbort(const OUString&, bool)
1043b6518bebSJan-Marek Glogowski {
1044b6518bebSJan-Marek Glogowski     ImplFreeSalGDI();
1045b6518bebSJan-Marek Glogowski }
1046b6518bebSJan-Marek Glogowski 
10475016881dSMichael Weghorn css::uno::Reference<css::datatransfer::dnd::XDragSource>
ImplCreateDragSource(const SystemEnvData & rSysEnv)10486003d197SMichael Weghorn WinSalInstance::ImplCreateDragSource(const SystemEnvData& rSysEnv)
104903157610SJan-Marek Glogowski {
105055f6bd0aSMichael Weghorn     rtl::Reference<DragSource> xDragSource = new DragSource(comphelper::getProcessComponentContext());
10516003d197SMichael Weghorn     vcl::OleDnDHelper(xDragSource, reinterpret_cast<sal_IntPtr>(rSysEnv.hWnd), vcl::DragOrDrop::Drag);
10525016881dSMichael Weghorn     return xDragSource;
105303157610SJan-Marek Glogowski }
105403157610SJan-Marek Glogowski 
1055828b8f91SMichael Weghorn css::uno::Reference<css::datatransfer::dnd::XDropTarget>
ImplCreateDropTarget(const SystemEnvData & rSysEnv)10566003d197SMichael Weghorn WinSalInstance::ImplCreateDropTarget(const SystemEnvData& rSysEnv)
105703157610SJan-Marek Glogowski {
105855f6bd0aSMichael Weghorn     rtl::Reference<DropTarget> xDropTarget = new DropTarget(comphelper::getProcessComponentContext());
10596003d197SMichael Weghorn     vcl::OleDnDHelper(xDropTarget, reinterpret_cast<sal_IntPtr>(rSysEnv.hWnd), vcl::DragOrDrop::Drop);
1060828b8f91SMichael Weghorn     return xDropTarget;
106103157610SJan-Marek Glogowski }
106203157610SJan-Marek Glogowski 
10634905a190SSebastian Spaeth /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
1064