VirtualBox

Ignore:
Timestamp:
Jul 29, 2016 6:30:43 PM (8 years ago)
Author:
vboxsync
Message:

VBoxMain/svcmain : fix for ​​​​​​​bugref:8161: added processing of shutdown messages in Windows

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Main/src-server/win/svcmain.cpp

    r62679 r62701  
    4141#include <iprt/getopt.h>
    4242#include <iprt/message.h>
     43#include <iprt\asm.h>
    4344
    4445class CExeModule : public ATL::CComModule
     
    5051    void MonitorShutdown();
    5152    bool StartMonitor();
     53    bool HasActiveConnection();
    5254    bool bActivity;
    5355};
    5456
    55 const DWORD dwTimeOut = 5000; /* time for EXE to be idle before shutting down */
    56 const DWORD dwPause = 100; /* time to wait for threads to finish up */
     57/* Normal timeout usually used in Shutdown Monitor */
     58const DWORD dwNormalTimeout = 5000;
     59volatile uint32_t dwTimeOut = dwNormalTimeout; /* time for EXE to be idle before shutting down. Can be decreased at system shutdown phase. */
    5760
    5861/* Passed to CreateThread to monitor the shutdown event */
     
    7376    }
    7477    return l;
     78}
     79
     80bool CExeModule::HasActiveConnection()
     81{
     82    return bActivity || GetLockCount() > 0;
    7583}
    7684
     
    8896        } while (dwWait == WAIT_OBJECT_0);
    8997        /* timed out */
    90         if (!bActivity && GetLockCount() == 0) /* if no activity let's really bail */
     98        if (!HasActiveConnection()) /* if no activity let's really bail */
    9199        {
    92100            /* Disable log rotation at this point, worst case a log file
     
    112120#if _WIN32_WINNT >= 0x0400
    113121            CoSuspendClassObjects();
    114             if (!bActivity && GetLockCount() == 0)
     122            if (!HasActiveConnection())
    115123#endif
    116124                break;
     
    135143    OBJECT_ENTRY(CLSID_VirtualBox, VirtualBox)
    136144END_OBJECT_MAP()
     145
     146CExeModule _Module;
     147HWND g_hMainWindow = NULL;
     148HINSTANCE g_hInstance = NULL;
     149#define MAIN_WND_CLASS L"VirtualBox Interface"
     150
     151/*
     152* Wrapper for Win API function ShutdownBlockReasonCreate
     153* This function defined starting from Vista only.
     154*/
     155BOOL ShutdownBlockReasonCreateAPI(HWND hWnd,LPCWSTR pwszReason)
     156{
     157    BOOL result = FALSE;
     158    typedef BOOL(WINAPI *PFNSHUTDOWNBLOCKREASONCREATE)(HWND hWnd, LPCWSTR pwszReason);
     159
     160    PFNSHUTDOWNBLOCKREASONCREATE pfn = (PFNSHUTDOWNBLOCKREASONCREATE)GetProcAddress(
     161            GetModuleHandle(L"User32.dll"), "ShutdownBlockReasonCreate");
     162    _ASSERTE(pfn);
     163    if (pfn)
     164        result = pfn(hWnd, pwszReason);
     165    return result;
     166}
     167
     168/*
     169* Wrapper for Win API function ShutdownBlockReasonDestroy
     170* This function defined starting from Vista only.
     171*/
     172BOOL ShutdownBlockReasonDestroyAPI(HWND hWnd)
     173{
     174    BOOL result = FALSE;
     175    typedef BOOL(WINAPI *PFNSHUTDOWNBLOCKREASONDESTROY)(HWND hWnd);
     176   
     177    PFNSHUTDOWNBLOCKREASONDESTROY pfn = (PFNSHUTDOWNBLOCKREASONDESTROY)GetProcAddress(
     178        GetModuleHandle(L"User32.dll"), "ShutdownBlockReasonDestroy");
     179    _ASSERTE(pfn);
     180    if (pfn)
     181        result = pfn(hWnd);
     182    return result;
     183}
     184
     185
     186LRESULT CALLBACK WinMainWndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
     187{
     188    LRESULT rc = 0;
     189    switch (msg)
     190    {
     191    case WM_QUERYENDSESSION:
     192    {
     193        rc = !_Module.HasActiveConnection();
     194        if (!rc)
     195        {
     196            /* place the VBoxSVC into system shutdown list */
     197            ShutdownBlockReasonCreateAPI(hwnd, L"Has active connections.");
     198            /* decrease a latency of MonitorShutdown loop */
     199            ASMAtomicXchgU32(&dwTimeOut, 100);
     200            Log(("VBoxSVCWinMain: VBoxSvc has active connections. bActivity = %d. Loc count = %d\n",
     201                _Module.bActivity, _Module.GetLockCount()));
     202        }
     203        Log(("VBoxSVCWinMain: WM_QUERYENDSESSION msg: %d rc= %d\n", msg, rc));
     204    } break;
     205    case WM_ENDSESSION:
     206    {
     207        /* Restore timeout of Monitor Shutdown if user canceled system shutdown */
     208        if (wParam == FALSE)
     209        {
     210            ASMAtomicXchgU32(&dwTimeOut, dwNormalTimeout);
     211            Log(("VBoxSVCWinMain: user canceled system shutdown.\n"));
     212        }
     213        Log(("VBoxSVCWinMain: WM_ENDSESSION msg: %d. wParam: %d. lParam: %d\n", msg, wParam, lParam));
     214    } break;
     215    case WM_DESTROY:
     216    {
     217        Log(("VBoxSVCWinMain: WM_DESTROY \n"));
     218        ShutdownBlockReasonDestroyAPI(hwnd);
     219        PostQuitMessage(0);
     220    } break;
     221
     222    default:
     223    {
     224        Log(("VBoxSVCWinMain: msg %p\n", msg));
     225        rc = DefWindowProc(hwnd, msg, wParam, lParam);
     226    }
     227    }
     228    return rc;
     229}
     230
     231
     232int CreateMainWindow()
     233{
     234    int rc = VINF_SUCCESS;
     235    _ASSERTE(g_hMainWindow == NULL);
     236
     237    LogFlow(("CreateMainWindow\n"));
     238
     239    g_hInstance = (HINSTANCE)GetModuleHandle(NULL);
     240
     241    /* Register the Window Class. */
     242    WNDCLASS wc;
     243    RT_ZERO(wc);
     244
     245    wc.style = CS_NOCLOSE;
     246    wc.lpfnWndProc = WinMainWndProc;
     247    wc.hInstance = g_hInstance;
     248    wc.hbrBackground = (HBRUSH)(COLOR_BACKGROUND + 1);
     249    wc.lpszClassName = MAIN_WND_CLASS;
     250   
     251
     252    ATOM atomWindowClass = RegisterClass(&wc);
     253
     254    if (atomWindowClass == 0)
     255    {
     256        Log(("Failed to register main window class\n"));
     257        rc = VERR_NOT_SUPPORTED;
     258    }
     259    else
     260    {
     261        /* Create the window. */
     262        g_hMainWindow = CreateWindowEx(WS_EX_TOOLWINDOW |  WS_EX_TOPMOST,
     263            MAIN_WND_CLASS, MAIN_WND_CLASS,
     264            WS_POPUPWINDOW,
     265            0, 0, 1, 1, NULL, NULL, g_hInstance, NULL);
     266
     267        if (g_hMainWindow == NULL)
     268        {
     269            Log(("Failed to create main window\n"));
     270            rc = VERR_NOT_SUPPORTED;
     271        }
     272        else
     273        {
     274            SetWindowPos(g_hMainWindow, HWND_TOPMOST, -200, -200, 0, 0,
     275                SWP_NOACTIVATE | SWP_HIDEWINDOW | SWP_NOCOPYBITS | SWP_NOREDRAW | SWP_NOSIZE);
     276
     277        }
     278    }
     279    return 0;
     280}
     281
     282
     283void DestroyMainWindow()
     284{
     285    _ASSERTE(g_hMainWindow != NULL);
     286    Log(("SVCMain: DestroyMainWindow \n"));
     287    if (g_hMainWindow != NULL)
     288    {
     289        DestroyWindow(g_hMainWindow);
     290        g_hMainWindow = NULL;
     291
     292        if (g_hInstance != NULL)
     293        {
     294            UnregisterClass(MAIN_WND_CLASS, g_hInstance);
     295            g_hInstance = NULL;
     296        }
     297    }
     298}
    137299
    138300
     
    172334     */
    173335    RTR3InitExe(argc, &argv, 0);
    174     CExeModule _Module;
     336
    175337
    176338    /* Note that all options are given lowercase/camel case/uppercase to
     
    395557        _ASSERTE(SUCCEEDED(hRes));
    396558
     559        if (RT_SUCCESS(CreateMainWindow()))
     560        {
     561            Log(("SVCMain: Main window succesfully created\n"));
     562        }
     563        else
     564        {
     565            Log(("SVCMain: Failed to create main window\n"));
     566        }
     567
    397568        MSG msg;
    398         while (GetMessage(&msg, 0, 0, 0))
     569        while (GetMessage(&msg, 0, 0, 0) > 0)
     570        {
    399571            DispatchMessage(&msg);
     572            TranslateMessage(&msg);
     573        }
     574
     575        DestroyMainWindow();
    400576
    401577        _Module.RevokeClassObjects();
    402         Sleep(dwPause); //wait for any threads to finish
    403578    }
    404579
Note: See TracChangeset for help on using the changeset viewer.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette