VirtualBox

Changeset 45703 in vbox for trunk/src/VBox/Additions


Ignore:
Timestamp:
Apr 24, 2013 2:31:56 PM (12 years ago)
Author:
vboxsync
Message:

VBoxTray/Seamless: disable seamless on desktop change (UAC, Lock)

Location:
trunk/src/VBox/Additions/WINNT
Files:
7 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Additions/WINNT/VBoxHook/VBoxHook.cpp

    r44528 r45703  
    1919
    2020#pragma data_seg("SHARED")
    21 static HWINEVENTHOOK    hEventHook[2]    = {0};
     21static HWINEVENTHOOK    hWinEventHook[2]    = {0};
     22static HWINEVENTHOOK    hDesktopEventHook   = NULL;
    2223#pragma data_seg()
    2324#pragma comment(linker, "/section:SHARED,RWS")
    2425
    25 static HANDLE   hNotifyEvent = 0;
     26static HANDLE   hWinNotifyEvent = 0;
     27static HANDLE   hDesktopNotifyEvent = 0;
    2628
    2729#ifdef DEBUG
     
    3335
    3436
    35 void CALLBACK VBoxHandleWinEvent(HWINEVENTHOOK hook, DWORD event, HWND hwnd,
     37static void CALLBACK VBoxHandleWinEvent(HWINEVENTHOOK hook, DWORD event, HWND hwnd,
    3638                                 LONG idObject, LONG idChild,
    3739                                 DWORD dwEventThread, DWORD dwmsEventTime)
     
    7678        }
    7779#endif
    78         if (!hNotifyEvent)
     80        if (!hWinNotifyEvent)
    7981        {
    80             hNotifyEvent = OpenEvent(EVENT_MODIFY_STATE, FALSE, VBOXHOOK_GLOBAL_EVENT_NAME);
    81             dprintf(("OpenEvent returned %x (last err=%x)\n", hNotifyEvent, GetLastError()));
     82            hWinNotifyEvent = OpenEvent(EVENT_MODIFY_STATE, FALSE, VBOXHOOK_GLOBAL_WT_EVENT_NAME);
     83            dprintf(("OpenEvent returned %x (last err=%x)\n", hWinNotifyEvent, GetLastError()));
    8284        }
    83         BOOL ret = SetEvent(hNotifyEvent);
    84         dprintf(("SetEvent %x returned %d (last error %x)\n", hNotifyEvent, ret, GetLastError()));
     85        BOOL ret = SetEvent(hWinNotifyEvent);
     86        dprintf(("SetEvent %x returned %d (last error %x)\n", hWinNotifyEvent, ret, GetLastError()));
    8587        break;
    8688    }
    8789}
    8890
     91static void CALLBACK VBoxHandleDesktopEvent(HWINEVENTHOOK hook, DWORD event, HWND hwnd,
     92                                 LONG idObject, LONG idChild,
     93                                 DWORD dwEventThread, DWORD dwmsEventTime)
     94{
     95    if (!hDesktopNotifyEvent)
     96    {
     97        hDesktopNotifyEvent = OpenEvent(EVENT_MODIFY_STATE, FALSE, VBOXHOOK_GLOBAL_DT_EVENT_NAME);
     98        dprintf(("OpenEvent returned %x (last err=%x)\n", hDesktopNotifyEvent, GetLastError()));
     99    }
     100    BOOL ret = SetEvent(hDesktopNotifyEvent);
     101    dprintf(("SetEvent %x returned %d (last error %x)\n", hDesktopNotifyEvent, ret, GetLastError()));
     102}
     103
     104BOOL VBoxHookInstallActiveDesktopTracker(HMODULE hDll)
     105{
     106    if (hDesktopEventHook)
     107        return TRUE;
     108
     109    CoInitialize(NULL);
     110    hDesktopEventHook = SetWinEventHook(EVENT_SYSTEM_DESKTOPSWITCH, EVENT_SYSTEM_DESKTOPSWITCH,
     111                                    hDll,
     112                                    VBoxHandleDesktopEvent,
     113                                    0, 0,
     114                                    0);
     115
     116    return !!hDesktopEventHook;
     117
     118}
     119
     120BOOL VBoxHookRemoveActiveDesktopTracker()
     121{
     122    if (hDesktopEventHook)
     123    {
     124        UnhookWinEvent(hDesktopEventHook);
     125        CoUninitialize();
     126    }
     127    hDesktopEventHook = 0;
     128    return TRUE;
     129}
    89130
    90131/* Install the global message hook */
    91 BOOL VBoxInstallHook(HMODULE hDll)
    92 {
    93     if (hEventHook[0] || hEventHook[1])
     132BOOL VBoxHookInstallWindowTracker(HMODULE hDll)
     133{
     134    if (hWinEventHook[0] || hWinEventHook[1])
    94135        return TRUE;
    95136
    96137    CoInitialize(NULL);
    97     hEventHook[0] = SetWinEventHook(EVENT_OBJECT_LOCATIONCHANGE, EVENT_OBJECT_LOCATIONCHANGE,
     138    hWinEventHook[0] = SetWinEventHook(EVENT_OBJECT_LOCATIONCHANGE, EVENT_OBJECT_LOCATIONCHANGE,
    98139                                    hDll,
    99140                                    VBoxHandleWinEvent,
     
    101142                                    WINEVENT_INCONTEXT | WINEVENT_SKIPOWNPROCESS);
    102143
    103     hEventHook[1] = SetWinEventHook(EVENT_OBJECT_CREATE, EVENT_OBJECT_HIDE,
     144    hWinEventHook[1] = SetWinEventHook(EVENT_OBJECT_CREATE, EVENT_OBJECT_HIDE,
    104145                                    hDll,
    105146                                    VBoxHandleWinEvent,
    106147                                    0, 0,
    107148                                    WINEVENT_INCONTEXT | WINEVENT_SKIPOWNPROCESS);
    108     return !!hEventHook[0];
     149    return !!hWinEventHook[0];
    109150}
    110151
    111152/* Remove the global message hook */
    112 BOOL VBoxRemoveHook()
    113 {
    114     if (hEventHook[0] && hEventHook[1])
    115     {
    116         UnhookWinEvent(hEventHook[0]);
    117         UnhookWinEvent(hEventHook[1]);
     153BOOL VBoxHookRemoveWindowTracker()
     154{
     155    if (hWinEventHook[0] && hWinEventHook[1])
     156    {
     157        UnhookWinEvent(hWinEventHook[0]);
     158        UnhookWinEvent(hWinEventHook[1]);
    118159        CoUninitialize();
    119160    }
    120     hEventHook[0]  = hEventHook[1] = 0;
    121     return true;
     161    hWinEventHook[0]  = hWinEventHook[1] = 0;
     162    return TRUE;
    122163}
    123164
  • trunk/src/VBox/Additions/WINNT/VBoxHook/VBoxHook.def

    r44528 r45703  
    1919
    2020EXPORTS
    21    VBoxInstallHook
    22    VBoxRemoveHook
     21    VBoxHookInstallActiveDesktopTracker
     22    VBoxHookRemoveActiveDesktopTracker
     23    VBoxHookInstallWindowTracker
     24    VBoxHookRemoveWindowTracker
  • trunk/src/VBox/Additions/WINNT/VBoxHook/testcase/tstHook.cpp

    r44528 r45703  
    2222    printf("Enabling global hook\n");
    2323
    24     HANDLE hEvent = CreateEvent(NULL, FALSE, FALSE, VBOXHOOK_GLOBAL_EVENT_NAME);
     24    HANDLE hEvent = CreateEvent(NULL, FALSE, FALSE, VBOXHOOK_GLOBAL_WT_EVENT_NAME);
    2525
    26     VBoxInstallHook(GetModuleHandle("VBoxHook.dll"));
     26    VBoxHookInstallWindowTracker(GetModuleHandle("VBoxHook.dll"));
    2727    getchar();
    2828
    2929    printf("Disabling global hook\n");
    30     VBoxRemoveHook();
     30    VBoxHookRemoveWindowTracker();
    3131    return 0;
    3232}
  • trunk/src/VBox/Additions/WINNT/VBoxTray/VBoxSeamless.cpp

    r45676 r45703  
    3333    HMODULE    hModule;
    3434
    35     BOOL    (* pfnVBoxInstallHook)(HMODULE hDll);
    36     BOOL    (* pfnVBoxRemoveHook)();
     35    BOOL    (* pfnVBoxHookInstallWindowTracker)(HMODULE hDll);
     36    BOOL    (* pfnVBoxHookRemoveWindowTracker)();
    3737
    3838    PVBOXDISPIFESCAPE lpEscapeData;
     
    7575        if (gCtx.hModule)
    7676        {
    77             *(uintptr_t *)&gCtx.pfnVBoxInstallHook = (uintptr_t)GetProcAddress(gCtx.hModule, "VBoxInstallHook");
    78             *(uintptr_t *)&gCtx.pfnVBoxRemoveHook  = (uintptr_t)GetProcAddress(gCtx.hModule, "VBoxRemoveHook");
    79 
    80             /* Inform the host that we support the seamless window mode. */
    81             rc = VbglR3SetGuestCaps(VMMDEV_GUEST_SUPPORTS_SEAMLESS, 0);
     77            *(uintptr_t *)&gCtx.pfnVBoxHookInstallWindowTracker = (uintptr_t)GetProcAddress(gCtx.hModule, "VBoxHookInstallWindowTracker");
     78            *(uintptr_t *)&gCtx.pfnVBoxHookRemoveWindowTracker  = (uintptr_t)GetProcAddress(gCtx.hModule, "VBoxHookRemoveWindowTracker");
     79
     80            /* rc should contain success status */
     81            AssertRC(rc);
     82
     83            if (VBoxSeamlessIsAllowed())
     84            {
     85                rc = VBoxSeamlessOnAllowChange(TRUE);
     86                if (!RT_SUCCESS(rc))
     87                    Log(("VBoxTray: VBoxSeamlessInit: Failed to set seamless capability\n"));
     88            }
     89
    8290            if (RT_SUCCESS(rc))
    8391            {
     
    8593                *ppInstance = &gCtx;
    8694            }
    87             else
    88                 Log(("VBoxTray: VBoxSeamlessInit: Failed to set seamless capability\n"));
    8995        }
    9096        else
     
    108114        Log(("VBoxTray: VBoxSeamlessDestroy: Failed to unset seamless capability, rc=%Rrc\n", rc));
    109115
    110     if (gCtx.pfnVBoxRemoveHook)
    111         gCtx.pfnVBoxRemoveHook();
     116    if (gCtx.pfnVBoxHookRemoveWindowTracker)
     117        gCtx.pfnVBoxHookRemoveWindowTracker();
    112118    if (gCtx.hModule)
    113119        FreeLibrary(gCtx.hModule);
     
    118124void VBoxSeamlessInstallHook()
    119125{
    120     if (gCtx.pfnVBoxInstallHook)
     126    if (gCtx.pfnVBoxHookInstallWindowTracker)
    121127    {
    122128        /* Check current visible region state */
    123129        VBoxSeamlessCheckWindows();
    124130
    125         gCtx.pfnVBoxInstallHook(gCtx.hModule);
     131        gCtx.pfnVBoxHookInstallWindowTracker(gCtx.hModule);
    126132    }
    127133}
     
    129135void VBoxSeamlessRemoveHook()
    130136{
    131     if (gCtx.pfnVBoxRemoveHook)
    132         gCtx.pfnVBoxRemoveHook();
     137    if (gCtx.pfnVBoxHookRemoveWindowTracker)
     138        gCtx.pfnVBoxHookRemoveWindowTracker();
    133139
    134140    if (gCtx.lpEscapeData)
     
    376382                                    Log(("VBoxTray: SystemParametersInfo SPI_SETSCREENSAVEACTIVE failed with %d\n", GetLastError()));
    377383                            }
    378                             PostMessage(ghwndToolWindow, WM_VBOX_REMOVE_SEAMLESS_HOOK, 0, 0);
     384                            PostMessage(ghwndToolWindow, WM_VBOX_SEAMLESS_DISABLE, 0, 0);
    379385                            break;
    380386
     
    390396                            if (!ret)
    391397                                Log(("VBoxTray: SystemParametersInfo SPI_SETSCREENSAVEACTIVE failed with %d\n", GetLastError()));
    392                             PostMessage(ghwndToolWindow, WM_VBOX_INSTALL_SEAMLESS_HOOK, 0, 0);
     398                            PostMessage(ghwndToolWindow, WM_VBOX_SEAMLESS_ENABLE, 0, 0);
    393399                            break;
    394400
  • trunk/src/VBox/Additions/WINNT/VBoxTray/VBoxSeamless.h

    r44528 r45703  
    2828void VBoxSeamlessCheckWindows();
    2929
     30/* NOTE: both can only be called from Main thread only! */
     31BOOL VBoxSeamlessIsAllowed();
     32int VBoxSeamlessOnAllowChange(BOOL fEnable);
     33
    3034#endif /* __VBOXSERVICESEAMLESS__H */
  • trunk/src/VBox/Additions/WINNT/VBoxTray/VBoxTray.cpp

    r44528 r45703  
    4242#include <iprt/buildconfig.h>
    4343
     44/* Default desktop state tracking */
     45#include <Wtsapi32.h>
     46
     47#ifdef DEBUG_misha
     48#define WARN(_m) do { \
     49            Assert(0); \
     50            Log(_m); \
     51        } while (0)
     52#else
     53#define WARN(_m) do { \
     54            Log(_m); \
     55        } while (0)
     56#endif
     57
     58/*
     59 * St (session [state] tracking) functionality API
     60 *
     61 * !!!NOTE: this API is NOT thread-safe!!!
     62 * it is supposed to be called & used from within the window message handler thread
     63 * of the window passed to vboxStInit */
     64static int vboxStInit(HWND hWnd);
     65static void vboxStTerm();
     66/* @returns true on "IsActiveConsole" state change */
     67static BOOL vboxStHandleEvent(WPARAM EventID, LPARAM SessionID);
     68static BOOL vboxStIsActiveConsole();
     69
     70/*
     71 * Dt (desktop [state] tracking) functionality API
     72 *
     73 * !!!NOTE: this API is NOT thread-safe!!!
     74 * */
     75static int vboxDtInit();
     76static void vboxDtTerm();
     77/* @returns true on "IsInputDesktop" state change */
     78static BOOL vboxDtHandleEvent();
     79/* @returns true iff the application (VBoxTray) desktop is input */
     80static BOOL vboxDtIsInputDesktop();
     81static HANDLE vboxDtGetNotifyEvent();
     82
    4483
    4584/*******************************************************************************
     
    5998HANDLE                ghVBoxDriver;
    6099HANDLE                ghStopSem;
    61 HANDLE                ghSeamlessNotifyEvent = 0;
     100HANDLE                ghSeamlessWtNotifyEvent = 0;
    62101SERVICE_STATUS        gVBoxServiceStatus;
    63102SERVICE_STATUS_HANDLE gVBoxServiceStatusHandle;
     
    66105NOTIFYICONDATA        gNotifyIconData;
    67106DWORD                 gMajorVersion;
     107BOOL                  gfIsSeamlessOn = FALSE;
    68108
    69109
     
    525565            && gMajorVersion >= 5) /* Only for W2K and up ... */
    526566        {
    527             ghSeamlessNotifyEvent = CreateEvent(&SecAttr, FALSE, FALSE, VBOXHOOK_GLOBAL_EVENT_NAME);
    528             if (ghSeamlessNotifyEvent == NULL)
     567            ghSeamlessWtNotifyEvent = CreateEvent(&SecAttr, FALSE, FALSE, VBOXHOOK_GLOBAL_WT_EVENT_NAME);
     568            if (ghSeamlessWtNotifyEvent == NULL)
    529569            {
    530570                dwErr = GetLastError();
     
    538578static void vboxTrayShutdownSeamless(void)
    539579{
    540     if (ghSeamlessNotifyEvent)
    541     {
    542         CloseHandle(ghSeamlessNotifyEvent);
    543         ghSeamlessNotifyEvent = NULL;
     580    if (ghSeamlessWtNotifyEvent)
     581    {
     582        CloseHandle(ghSeamlessWtNotifyEvent);
     583        ghSeamlessWtNotifyEvent = NULL;
    544584    }
    545585}
     
    617657                 */
    618658
    619                 DWORD dwEventCount = 2;
    620                 HANDLE hWaitEvent[2] = { ghStopSem, ghSeamlessNotifyEvent };
    621 
    622                 if (0 == ghSeamlessNotifyEvent) /* If seamless mode is not active / supported, reduce event array count. */
     659                HANDLE hWaitEvent[3] = { ghStopSem, ghSeamlessWtNotifyEvent, vboxDtGetNotifyEvent() };
     660                DWORD dwEventCount = RT_ELEMENTS(hWaitEvent);
     661
     662                if (0 == ghSeamlessWtNotifyEvent) /* If seamless mode is not active / supported, reduce event array count. */
    623663                    dwEventCount = 1;
    624664
     
    639679                    }
    640680                    else if (   waitResult == 1
    641                              && ghSeamlessNotifyEvent != 0) /* Only jump in, if seamless is active! */
     681                             && ghSeamlessWtNotifyEvent != 0) /* Only jump in, if seamless is active! */
    642682                    {
    643683                        Log(("VBoxTray: Event 'Seamless' triggered\n"));
     
    645685                        /* seamless window notification */
    646686                        VBoxSeamlessCheckWindows();
     687                    }
     688                    else if (   waitResult == 2
     689                             && vboxDtGetNotifyEvent() != 0) /* Only jump in, if Dt is active! */
     690                    {
     691                        BOOL fOldSeamlessAllowedState = VBoxSeamlessIsAllowed();
     692                        if (vboxDtHandleEvent())
     693                        {
     694                            if (!VBoxSeamlessIsAllowed() != !fOldSeamlessAllowedState)
     695                            {
     696                                rc = VBoxSeamlessOnAllowChange(!fOldSeamlessAllowedState);
     697                                if (!RT_SUCCESS(rc))
     698                                    Log(("VBoxTray: WndProc: Failed to set seamless capability\n"));
     699                            }
     700                        }
    647701                    }
    648702                    else
     
    713767        if (RT_SUCCESS(rc))
    714768        {
     769            rc = vboxStInit(ghwndToolWindow);
     770            if (!RT_SUCCESS(rc))
     771            {
     772                WARN(("VBoxTray: vboxStInit failed, rc %d"));
     773                /* ignore the St Init failure. this can happen for < XP win that do not support WTS API
     774                 * in that case the session is treated as active connected to the physical console
     775                 * (i.e. fallback to the old behavior that was before introduction of VBoxSt) */
     776                Assert(vboxStIsActiveConsole());
     777            }
     778
     779            rc = vboxDtInit();
     780            if (!RT_SUCCESS(rc))
     781            {
     782                WARN(("VBoxTray: vboxDtInit failed, rc %d"));
     783                /* ignore the Dt Init failure. this can happen for < XP win that do not support WTS API
     784                 * in that case the session is treated as active connected to the physical console
     785                 * (i.e. fallback to the old behavior that was before introduction of VBoxSt) */
     786                Assert(vboxDtIsInputDesktop());
     787            }
     788
    715789            rc = vboxTraySetupSeamless();
    716790            if (RT_SUCCESS(rc))
     
    722796                vboxTrayShutdownSeamless();
    723797            }
     798
     799            /* it should be safe to call vboxDtTerm even if vboxStInit above failed */
     800            vboxDtTerm();
     801
     802            /* it should be safe to call vboxStTerm even if vboxStInit above failed */
     803            vboxStTerm();
     804
    724805            vboxTrayDestroyToolWindow();
    725806        }
     
    799880            return 0;
    800881
    801         case WM_VBOX_INSTALL_SEAMLESS_HOOK:
    802             VBoxSeamlessInstallHook();
     882        case WM_VBOX_SEAMLESS_ENABLE:
     883            gfIsSeamlessOn = TRUE;
     884            if (VBoxSeamlessIsAllowed())
     885                VBoxSeamlessInstallHook();
    803886            return 0;
    804887
    805         case WM_VBOX_REMOVE_SEAMLESS_HOOK:
    806             VBoxSeamlessRemoveHook();
     888        case WM_VBOX_SEAMLESS_DISABLE:
     889            gfIsSeamlessOn = FALSE;
     890            if (VBoxSeamlessIsAllowed())
     891                VBoxSeamlessRemoveHook();
    807892            return 0;
    808893
    809894        case WM_VBOX_SEAMLESS_UPDATE:
    810             VBoxSeamlessCheckWindows();
     895            if (gfIsSeamlessOn && VBoxSeamlessIsAllowed())
     896                VBoxSeamlessCheckWindows();
    811897            return 0;
    812898
     
    819905            return 0;
    820906
     907        case WM_WTSSESSION_CHANGE:
     908        {
     909            BOOL fOldSeamlessAllowedState = VBoxSeamlessIsAllowed();
     910            if (vboxStHandleEvent(wParam, lParam))
     911            {
     912                if (!VBoxSeamlessIsAllowed() != !fOldSeamlessAllowedState)
     913                {
     914                    int rc = VBoxSeamlessOnAllowChange(!fOldSeamlessAllowedState);
     915                    if (!RT_SUCCESS(rc))
     916                        Log(("VBoxTray: WndProc: Failed to set seamless capability\n"));
     917                }
     918            }
     919            return 0;
     920        }
    821921        default:
    822922
     
    835935}
    836936
     937/* St (session [state] tracking) functionality API impl */
     938
     939typedef struct VBOXST
     940{
     941    HWND hWTSAPIWnd;
     942    HMODULE hWTSAPI32;
     943    BOOL fIsConsole;
     944    WTS_CONNECTSTATE_CLASS enmConnectState;
     945    BOOL (WINAPI * pfnWTSRegisterSessionNotification)(HWND hWnd, DWORD dwFlags);
     946    BOOL (WINAPI * pfnWTSUnRegisterSessionNotification)(HWND hWnd);
     947    BOOL (WINAPI * pfnWTSQuerySessionInformationA)(HANDLE hServer, DWORD SessionId, WTS_INFO_CLASS WTSInfoClass, LPTSTR *ppBuffer, DWORD *pBytesReturned);
     948} VBOXST;
     949
     950static VBOXST gVBoxSt;
     951
     952static int vboxStInit(HWND hWnd)
     953{
     954    int rc = VINF_SUCCESS;
     955    memset(&gVBoxSt, 0, sizeof (gVBoxSt));
     956    gVBoxSt.hWTSAPI32 = LoadLibrary("WTSAPI32.DLL");
     957    if (gVBoxSt.hWTSAPI32)
     958    {
     959        *(uintptr_t *)&gVBoxSt.pfnWTSRegisterSessionNotification = (uintptr_t)GetProcAddress(gVBoxSt.hWTSAPI32, "WTSRegisterSessionNotification");
     960        if (!gVBoxSt.pfnWTSRegisterSessionNotification)
     961        {
     962            WARN(("VBoxTray: WTSRegisterSessionNotification not found\n"));
     963            rc = VERR_NOT_SUPPORTED;
     964        }
     965
     966        *(uintptr_t *)&gVBoxSt.pfnWTSUnRegisterSessionNotification = (uintptr_t)GetProcAddress(gVBoxSt.hWTSAPI32, "WTSUnRegisterSessionNotification");
     967        if (!gVBoxSt.pfnWTSUnRegisterSessionNotification)
     968        {
     969            WARN(("VBoxTray: WTSUnRegisterSessionNotification not found\n"));
     970            rc = VERR_NOT_SUPPORTED;
     971        }
     972
     973        *(uintptr_t *)&gVBoxSt.pfnWTSQuerySessionInformationA = (uintptr_t)GetProcAddress(gVBoxSt.hWTSAPI32, "WTSQuerySessionInformationA");
     974        if (!gVBoxSt.pfnWTSQuerySessionInformationA)
     975        {
     976            WARN(("VBoxTray: WTSQuerySessionInformationA not found\n"));
     977            rc = VERR_NOT_SUPPORTED;
     978        }
     979
     980        if (rc == VINF_SUCCESS)
     981        {
     982            gVBoxSt.hWTSAPIWnd = hWnd;
     983            if (gVBoxSt.pfnWTSRegisterSessionNotification(gVBoxSt.hWTSAPIWnd, NOTIFY_FOR_THIS_SESSION))
     984            {
     985                WTS_CONNECTSTATE_CLASS *penmConnectState = NULL;
     986                USHORT *pProtocolType = NULL;
     987                DWORD cbBuf = 0;
     988                if (gVBoxSt.pfnWTSQuerySessionInformationA(WTS_CURRENT_SERVER_HANDLE, WTS_CURRENT_SESSION, WTSConnectState, (LPTSTR *)&penmConnectState, &cbBuf))
     989                {
     990                    if (gVBoxSt.pfnWTSQuerySessionInformationA(WTS_CURRENT_SERVER_HANDLE, WTS_CURRENT_SESSION, WTSClientProtocolType, (LPTSTR *)&pProtocolType, &cbBuf))
     991                    {
     992                        gVBoxSt.fIsConsole = (*pProtocolType == 0);
     993                        gVBoxSt.enmConnectState = *penmConnectState;
     994                    }
     995                    else
     996                    {
     997                        DWORD dwErr = GetLastError();
     998                        WARN(("VBoxTray: WTSQuerySessionInformationA WTSClientProtocolType failed, error = %08X\n", dwErr));
     999                        rc = RTErrConvertFromWin32(dwErr);
     1000                    }
     1001                }
     1002                else
     1003                {
     1004                    DWORD dwErr = GetLastError();
     1005                    WARN(("VBoxTray: WTSQuerySessionInformationA WTSConnectState failed, error = %08X\n", dwErr));
     1006                    rc = RTErrConvertFromWin32(dwErr);
     1007                }
     1008                return VINF_SUCCESS;
     1009            }
     1010            else
     1011            {
     1012                DWORD dwErr = GetLastError();
     1013                WARN(("VBoxTray: WTSRegisterSessionNotification failed, error = %08X\n", dwErr));
     1014                rc = RTErrConvertFromWin32(dwErr);
     1015            }
     1016        }
     1017
     1018        FreeLibrary(gVBoxSt.hWTSAPI32);
     1019    }
     1020    else
     1021    {
     1022        DWORD dwErr = GetLastError();
     1023        WARN(("VBoxTray: WTSAPI32 load failed, error = %08X\n", dwErr));
     1024        rc = RTErrConvertFromWin32(dwErr);
     1025    }
     1026
     1027    memset(&gVBoxSt, 0, sizeof (gVBoxSt));
     1028    gVBoxSt.fIsConsole = TRUE;
     1029    gVBoxSt.enmConnectState = WTSActive;
     1030    return rc;
     1031}
     1032
     1033static void vboxStTerm()
     1034{
     1035    if (gVBoxSt.hWTSAPIWnd)
     1036    {
     1037        WARN(("VBoxTray: vboxStTerm called for non-initialized St\n"));
     1038        return;
     1039    }
     1040
     1041    if (!gVBoxSt.pfnWTSUnRegisterSessionNotification(gVBoxSt.hWTSAPIWnd))
     1042    {
     1043        DWORD dwErr = GetLastError();
     1044        WARN(("VBoxTray: WTSAPI32 load failed, error = %08X\n", dwErr));
     1045    }
     1046
     1047    FreeLibrary(gVBoxSt.hWTSAPI32);
     1048    memset(&gVBoxSt, 0, sizeof (gVBoxSt));
     1049}
     1050
     1051#define VBOXST_DBG_MAKECASE(_val) case _val: return #_val;
     1052
     1053static const char* vboxStDbgGetString(DWORD val)
     1054{
     1055    switch (val)
     1056    {
     1057        VBOXST_DBG_MAKECASE(WTS_CONSOLE_CONNECT);
     1058        VBOXST_DBG_MAKECASE(WTS_CONSOLE_DISCONNECT);
     1059        VBOXST_DBG_MAKECASE(WTS_REMOTE_CONNECT);
     1060        VBOXST_DBG_MAKECASE(WTS_REMOTE_DISCONNECT);
     1061        VBOXST_DBG_MAKECASE(WTS_SESSION_LOGON);
     1062        VBOXST_DBG_MAKECASE(WTS_SESSION_LOGOFF);
     1063        VBOXST_DBG_MAKECASE(WTS_SESSION_LOCK);
     1064        VBOXST_DBG_MAKECASE(WTS_SESSION_UNLOCK);
     1065        VBOXST_DBG_MAKECASE(WTS_SESSION_REMOTE_CONTROL);
     1066        default:
     1067            WARN(("VBoxTray: invalid WTS state %d", val));
     1068            return "Unknown";
     1069    }
     1070}
     1071
     1072static BOOL vboxStHandleEvent(WPARAM wEvent, LPARAM SessionID)
     1073{
     1074    WARN(("VBoxTray: WTS Event: %s\n", vboxStDbgGetString(wEvent)));
     1075    BOOL fOldIsActiveConsole = vboxStIsActiveConsole();
     1076    switch (wEvent)
     1077    {
     1078        case WTS_CONSOLE_CONNECT:
     1079            gVBoxSt.enmConnectState = WTSConnected;
     1080            gVBoxSt.fIsConsole = TRUE;
     1081            break;
     1082        case WTS_CONSOLE_DISCONNECT:
     1083            gVBoxSt.enmConnectState = WTSDisconnected;
     1084            break;
     1085        case WTS_REMOTE_CONNECT:
     1086            gVBoxSt.enmConnectState = WTSConnected;
     1087            gVBoxSt.fIsConsole = FALSE;
     1088            break;
     1089        case WTS_REMOTE_DISCONNECT:
     1090            gVBoxSt.enmConnectState = WTSDisconnected;
     1091            break;
     1092        case WTS_SESSION_LOGON:
     1093            Assert(gVBoxSt.enmConnectState == WTSConnected);
     1094            gVBoxSt.enmConnectState = WTSActive;
     1095            break;
     1096        case WTS_SESSION_LOGOFF:
     1097            Assert(gVBoxSt.enmConnectState == WTSActive);
     1098            gVBoxSt.enmConnectState = WTSConnected;
     1099            break;
     1100        case WTS_SESSION_LOCK:
     1101            Assert(gVBoxSt.enmConnectState == WTSActive);
     1102            gVBoxSt.enmConnectState = WTSConnected;
     1103            break;
     1104        case WTS_SESSION_UNLOCK:
     1105            Assert(gVBoxSt.enmConnectState == WTSConnected);
     1106            gVBoxSt.enmConnectState = WTSActive;
     1107            break;
     1108        case WTS_SESSION_REMOTE_CONTROL:
     1109            /* todo */
     1110            WARN(("WTS_SESSION_REMOTE_CONTROL handling not implemented!"));
     1111            break;
     1112        default:
     1113            WARN(("unexpected session change notification %d", (DWORD)wEvent));
     1114            break;
     1115    }
     1116
     1117    return !vboxStIsActiveConsole() != !fOldIsActiveConsole;
     1118}
     1119
     1120static BOOL vboxStIsActiveConsole()
     1121{
     1122    return (gVBoxSt.enmConnectState == WTSActive && gVBoxSt.fIsConsole);
     1123}
     1124
     1125/*
     1126 * Dt (desktop [state] tracking) functionality API impl
     1127 *
     1128 * !!!NOTE: this API is NOT thread-safe!!!
     1129 * */
     1130
     1131typedef struct VBOXDT
     1132{
     1133    HANDLE hNotifyEvent;
     1134    BOOL fIsInputDesktop;
     1135    HMODULE hHookModule;
     1136    BOOL (* pfnVBoxHookInstallActiveDesktopTracker)(HMODULE hDll);
     1137    BOOL (* pfnVBoxHookRemoveActiveDesktopTracker)();
     1138    HMODULE hUSER32;
     1139    HDESK (WINAPI * pfnGetThreadDesktop)(DWORD dwThreadId);
     1140    HDESK (WINAPI * pfnOpenInputDesktop)(DWORD dwFlags, BOOL fInherit, ACCESS_MASK dwDesiredAccess);
     1141    BOOL (WINAPI * pfnCloseDesktop)(HDESK hDesktop);
     1142} VBOXDT;
     1143
     1144static VBOXDT gVBoxDt;
     1145
     1146static BOOL vboxDtCalculateIsInputDesktop()
     1147{
     1148    BOOL fIsInputDt = FALSE;
     1149    HDESK hInput = gVBoxDt.pfnOpenInputDesktop(0, FALSE, DESKTOP_CREATEWINDOW);
     1150    if (hInput)
     1151    {
     1152//        DWORD dwThreadId = GetCurrentThreadId();
     1153//        HDESK hThreadDt = gVBoxDt.pfnGetThreadDesktop(dwThreadId);
     1154//        if (hThreadDt)
     1155//        {
     1156            fIsInputDt = TRUE;
     1157//        }
     1158//        else
     1159//        {
     1160//            DWORD dwErr = GetLastError();
     1161//            WARN(("VBoxTray: pfnGetThreadDesktop for Seamless failed, last error = %08X\n", dwErr));
     1162//        }
     1163
     1164        gVBoxDt.pfnCloseDesktop(hInput);
     1165    }
     1166    else
     1167    {
     1168        DWORD dwErr = GetLastError();
     1169        WARN(("VBoxTray: pfnOpenInputDesktop for Seamless failed, last error = %08X\n", dwErr));
     1170    }
     1171    return fIsInputDt;
     1172}
     1173static int vboxDtInit()
     1174{
     1175    int rc = VINF_SUCCESS;
     1176    OSVERSIONINFO info;
     1177    gMajorVersion = 5; /* Default to Windows XP. */
     1178    info.dwOSVersionInfoSize = sizeof(info);
     1179    if (GetVersionEx(&info))
     1180    {
     1181        WARN(("VBoxTray: Windows version %ld.%ld\n", info.dwMajorVersion, info.dwMinorVersion));
     1182        gMajorVersion = info.dwMajorVersion;
     1183    }
     1184
     1185    memset(&gVBoxDt, 0, sizeof (gVBoxDt));
     1186
     1187    /* For Vista and up we need to change the integrity of the security descriptor, too. */
     1188    if (gMajorVersion >= 6)
     1189    {
     1190        gVBoxDt.hNotifyEvent = CreateEvent(NULL, FALSE, FALSE, VBOXHOOK_GLOBAL_DT_EVENT_NAME);
     1191        if (gVBoxDt.hNotifyEvent != NULL)
     1192        {
     1193            gVBoxDt.hHookModule = LoadLibrary(VBOXHOOK_DLL_NAME);
     1194            if (gVBoxDt.hHookModule)
     1195            {
     1196                *(uintptr_t *)&gVBoxDt.pfnVBoxHookInstallActiveDesktopTracker = (uintptr_t)GetProcAddress(gVBoxDt.hHookModule, "VBoxHookInstallActiveDesktopTracker");
     1197                if (!gVBoxDt.pfnVBoxHookInstallActiveDesktopTracker)
     1198                {
     1199                    WARN(("VBoxTray: VBoxHookInstallActiveDesktopTracker not found\n"));
     1200                    rc = VERR_NOT_SUPPORTED;
     1201                }
     1202
     1203                *(uintptr_t *)&gVBoxDt.pfnVBoxHookRemoveActiveDesktopTracker  = (uintptr_t)GetProcAddress(gVBoxDt.hHookModule, "VBoxHookInstallActiveDesktopTracker");
     1204                if (!gVBoxDt.pfnVBoxHookRemoveActiveDesktopTracker)
     1205                {
     1206                    WARN(("VBoxTray: VBoxHookRemoveActiveDesktopTracker not found\n"));
     1207                    rc = VERR_NOT_SUPPORTED;
     1208                }
     1209
     1210                if (VINF_SUCCESS == rc)
     1211                {
     1212                    gVBoxDt.hUSER32 = LoadLibrary("User32.dll");
     1213                    if (gVBoxDt.hUSER32)
     1214                    {
     1215                        *(uintptr_t *)&gVBoxDt.pfnGetThreadDesktop = (uintptr_t)GetProcAddress(gVBoxDt.hUSER32, "GetThreadDesktop");
     1216                        if (!gVBoxDt.pfnGetThreadDesktop)
     1217                        {
     1218                            WARN(("VBoxTray: GetThreadDesktop not found\n"));
     1219                            rc = VERR_NOT_SUPPORTED;
     1220                        }
     1221
     1222                        *(uintptr_t *)&gVBoxDt.pfnOpenInputDesktop = (uintptr_t)GetProcAddress(gVBoxDt.hUSER32, "OpenInputDesktop");
     1223                        if (!gVBoxDt.pfnOpenInputDesktop)
     1224                        {
     1225                            WARN(("VBoxTray: OpenInputDesktop not found\n"));
     1226                            rc = VERR_NOT_SUPPORTED;
     1227                        }
     1228
     1229                        *(uintptr_t *)&gVBoxDt.pfnCloseDesktop = (uintptr_t)GetProcAddress(gVBoxDt.hUSER32, "CloseDesktop");
     1230                        if (!gVBoxDt.pfnCloseDesktop)
     1231                        {
     1232                            WARN(("VBoxTray: CloseDesktop not found\n"));
     1233                            rc = VERR_NOT_SUPPORTED;
     1234                        }
     1235
     1236                        if (VINF_SUCCESS == rc)
     1237                        {
     1238                            gVBoxDt.pfnVBoxHookInstallActiveDesktopTracker(gVBoxDt.hHookModule);
     1239                            gVBoxDt.fIsInputDesktop = vboxDtCalculateIsInputDesktop();
     1240                            return VINF_SUCCESS;
     1241                        }
     1242                        FreeLibrary(gVBoxDt.hUSER32);
     1243                    }
     1244                }
     1245
     1246                FreeLibrary(gVBoxDt.hHookModule);
     1247            }
     1248            else
     1249            {
     1250                DWORD dwErr = GetLastError();
     1251                WARN(("VBoxTray: CreateEvent for Seamless failed, last error = %08X\n", dwErr));
     1252                rc = RTErrConvertFromWin32(dwErr);
     1253            }
     1254
     1255            CloseHandle(gVBoxDt.hNotifyEvent);
     1256        }
     1257        else
     1258        {
     1259            DWORD dwErr = GetLastError();
     1260            WARN(("VBoxTray: CreateEvent for Seamless failed, last error = %08X\n", dwErr));
     1261            rc = RTErrConvertFromWin32(dwErr);
     1262        }
     1263    }
     1264
     1265    memset(&gVBoxDt, 0, sizeof (gVBoxDt));
     1266    gVBoxDt.fIsInputDesktop = TRUE;
     1267
     1268    return rc;
     1269}
     1270
     1271static void vboxDtTerm()
     1272{
     1273    if (!gVBoxDt.hHookModule)
     1274        return;
     1275
     1276    gVBoxDt.pfnVBoxHookRemoveActiveDesktopTracker();
     1277
     1278    FreeLibrary(gVBoxDt.hUSER32);
     1279    FreeLibrary(gVBoxDt.hHookModule);
     1280    CloseHandle(gVBoxDt.hNotifyEvent);
     1281
     1282    memset(&gVBoxDt, 0, sizeof (gVBoxDt));
     1283}
     1284/* @returns true on "IsInputDesktop" state change */
     1285static BOOL vboxDtHandleEvent()
     1286{
     1287    BOOL fIsInputDesktop = gVBoxDt.fIsInputDesktop;
     1288    gVBoxDt.fIsInputDesktop = vboxDtCalculateIsInputDesktop();
     1289    return !fIsInputDesktop != !gVBoxDt.fIsInputDesktop;
     1290}
     1291
     1292static HANDLE vboxDtGetNotifyEvent()
     1293{
     1294    return gVBoxDt.hNotifyEvent;
     1295}
     1296
     1297/* @returns true iff the application (VBoxTray) desktop is input */
     1298static BOOL vboxDtIsInputDesktop()
     1299{
     1300    return gVBoxDt.fIsInputDesktop;
     1301}
     1302
     1303
     1304/* helper state tracking API */
     1305BOOL VBoxSeamlessIsAllowed()
     1306{
     1307    return vboxDtIsInputDesktop() && vboxStIsActiveConsole();
     1308}
     1309
     1310int VBoxSeamlessOnAllowChange(BOOL fAllowed)
     1311{
     1312    int rc;
     1313    if (fAllowed)
     1314    {
     1315        rc = VbglR3SetGuestCaps(VMMDEV_GUEST_SUPPORTS_SEAMLESS, 0);
     1316        if (gfIsSeamlessOn)
     1317            VBoxSeamlessInstallHook();
     1318    }
     1319    else
     1320    {
     1321        if (gfIsSeamlessOn)
     1322            VBoxSeamlessRemoveHook();
     1323        rc = VbglR3SetGuestCaps(0, VMMDEV_GUEST_SUPPORTS_SEAMLESS);
     1324    }
     1325    if (!RT_SUCCESS(rc))
     1326        WARN(("VBoxTray: VMMDEV_GUEST_SUPPORTS_SEAMLESS: Failed to %s seamless capability\n", fAllowed ? "set" : "clear" ));
     1327
     1328    return rc;
     1329}
  • trunk/src/VBox/Additions/WINNT/include/VBoxHook.h

    r44528 r45703  
    1717
    1818/* custom messages as we must install the hook from the main thread */
    19 #define WM_VBOX_INSTALL_SEAMLESS_HOOK               0x2001
    20 #define WM_VBOX_REMOVE_SEAMLESS_HOOK                0x2002
     19#define WM_VBOX_SEAMLESS_ENABLE                     0x2001
     20#define WM_VBOX_SEAMLESS_DISABLE                    0x2002
    2121#define WM_VBOX_SEAMLESS_UPDATE                     0x2003
    2222
    2323
    2424#define VBOXHOOK_DLL_NAME           "VBoxHook.dll"
    25 #define VBOXHOOK_GLOBAL_EVENT_NAME  "Local\\VBoxHookNotifyEvent"
     25#define VBOXHOOK_GLOBAL_DT_EVENT_NAME  "Local\\VBoxHookDtNotifyEvent"
     26#define VBOXHOOK_GLOBAL_WT_EVENT_NAME  "Local\\VBoxHookWtNotifyEvent"
    2627
    27 /* Install the global message hook */
    28 BOOL VBoxInstallHook(HMODULE hDll);
     28BOOL VBoxHookInstallActiveDesktopTracker(HMODULE hDll);
     29BOOL VBoxHookRemoveActiveDesktopTracker();
    2930
    30 /* Remove the global message hook */
    31 BOOL VBoxRemoveHook();
     31BOOL VBoxHookInstallWindowTracker(HMODULE hDll);
     32BOOL VBoxHookRemoveWindowTracker();
    3233
    3334#endif /* __VBoxHook_h__ */
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