Changeset 45703 in vbox for trunk/src/VBox/Additions
- Timestamp:
- Apr 24, 2013 2:31:56 PM (12 years ago)
- Location:
- trunk/src/VBox/Additions/WINNT
- Files:
-
- 7 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Additions/WINNT/VBoxHook/VBoxHook.cpp
r44528 r45703 19 19 20 20 #pragma data_seg("SHARED") 21 static HWINEVENTHOOK hEventHook[2] = {0}; 21 static HWINEVENTHOOK hWinEventHook[2] = {0}; 22 static HWINEVENTHOOK hDesktopEventHook = NULL; 22 23 #pragma data_seg() 23 24 #pragma comment(linker, "/section:SHARED,RWS") 24 25 25 static HANDLE hNotifyEvent = 0; 26 static HANDLE hWinNotifyEvent = 0; 27 static HANDLE hDesktopNotifyEvent = 0; 26 28 27 29 #ifdef DEBUG … … 33 35 34 36 35 void CALLBACK VBoxHandleWinEvent(HWINEVENTHOOK hook, DWORD event, HWND hwnd,37 static void CALLBACK VBoxHandleWinEvent(HWINEVENTHOOK hook, DWORD event, HWND hwnd, 36 38 LONG idObject, LONG idChild, 37 39 DWORD dwEventThread, DWORD dwmsEventTime) … … 76 78 } 77 79 #endif 78 if (!h NotifyEvent)80 if (!hWinNotifyEvent) 79 81 { 80 h NotifyEvent = OpenEvent(EVENT_MODIFY_STATE, FALSE, VBOXHOOK_GLOBAL_EVENT_NAME);81 dprintf(("OpenEvent returned %x (last err=%x)\n", h NotifyEvent, GetLastError()));82 hWinNotifyEvent = OpenEvent(EVENT_MODIFY_STATE, FALSE, VBOXHOOK_GLOBAL_WT_EVENT_NAME); 83 dprintf(("OpenEvent returned %x (last err=%x)\n", hWinNotifyEvent, GetLastError())); 82 84 } 83 BOOL ret = SetEvent(h NotifyEvent);84 dprintf(("SetEvent %x returned %d (last error %x)\n", h NotifyEvent, ret, GetLastError()));85 BOOL ret = SetEvent(hWinNotifyEvent); 86 dprintf(("SetEvent %x returned %d (last error %x)\n", hWinNotifyEvent, ret, GetLastError())); 85 87 break; 86 88 } 87 89 } 88 90 91 static 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 104 BOOL 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 120 BOOL VBoxHookRemoveActiveDesktopTracker() 121 { 122 if (hDesktopEventHook) 123 { 124 UnhookWinEvent(hDesktopEventHook); 125 CoUninitialize(); 126 } 127 hDesktopEventHook = 0; 128 return TRUE; 129 } 89 130 90 131 /* Install the global message hook */ 91 BOOL VBox InstallHook(HMODULE hDll)92 { 93 if (h EventHook[0] || hEventHook[1])132 BOOL VBoxHookInstallWindowTracker(HMODULE hDll) 133 { 134 if (hWinEventHook[0] || hWinEventHook[1]) 94 135 return TRUE; 95 136 96 137 CoInitialize(NULL); 97 h EventHook[0] = SetWinEventHook(EVENT_OBJECT_LOCATIONCHANGE, EVENT_OBJECT_LOCATIONCHANGE,138 hWinEventHook[0] = SetWinEventHook(EVENT_OBJECT_LOCATIONCHANGE, EVENT_OBJECT_LOCATIONCHANGE, 98 139 hDll, 99 140 VBoxHandleWinEvent, … … 101 142 WINEVENT_INCONTEXT | WINEVENT_SKIPOWNPROCESS); 102 143 103 h EventHook[1] = SetWinEventHook(EVENT_OBJECT_CREATE, EVENT_OBJECT_HIDE,144 hWinEventHook[1] = SetWinEventHook(EVENT_OBJECT_CREATE, EVENT_OBJECT_HIDE, 104 145 hDll, 105 146 VBoxHandleWinEvent, 106 147 0, 0, 107 148 WINEVENT_INCONTEXT | WINEVENT_SKIPOWNPROCESS); 108 return !!h EventHook[0];149 return !!hWinEventHook[0]; 109 150 } 110 151 111 152 /* Remove the global message hook */ 112 BOOL VBox RemoveHook()113 { 114 if (h EventHook[0] && hEventHook[1])115 { 116 UnhookWinEvent(h EventHook[0]);117 UnhookWinEvent(h EventHook[1]);153 BOOL VBoxHookRemoveWindowTracker() 154 { 155 if (hWinEventHook[0] && hWinEventHook[1]) 156 { 157 UnhookWinEvent(hWinEventHook[0]); 158 UnhookWinEvent(hWinEventHook[1]); 118 159 CoUninitialize(); 119 160 } 120 h EventHook[0] = hEventHook[1] = 0;121 return true;161 hWinEventHook[0] = hWinEventHook[1] = 0; 162 return TRUE; 122 163 } 123 164 -
trunk/src/VBox/Additions/WINNT/VBoxHook/VBoxHook.def
r44528 r45703 19 19 20 20 EXPORTS 21 VBoxInstallHook 22 VBoxRemoveHook 21 VBoxHookInstallActiveDesktopTracker 22 VBoxHookRemoveActiveDesktopTracker 23 VBoxHookInstallWindowTracker 24 VBoxHookRemoveWindowTracker -
trunk/src/VBox/Additions/WINNT/VBoxHook/testcase/tstHook.cpp
r44528 r45703 22 22 printf("Enabling global hook\n"); 23 23 24 HANDLE hEvent = CreateEvent(NULL, FALSE, FALSE, VBOXHOOK_GLOBAL_ EVENT_NAME);24 HANDLE hEvent = CreateEvent(NULL, FALSE, FALSE, VBOXHOOK_GLOBAL_WT_EVENT_NAME); 25 25 26 VBox InstallHook(GetModuleHandle("VBoxHook.dll"));26 VBoxHookInstallWindowTracker(GetModuleHandle("VBoxHook.dll")); 27 27 getchar(); 28 28 29 29 printf("Disabling global hook\n"); 30 VBox RemoveHook();30 VBoxHookRemoveWindowTracker(); 31 31 return 0; 32 32 } -
trunk/src/VBox/Additions/WINNT/VBoxTray/VBoxSeamless.cpp
r45676 r45703 33 33 HMODULE hModule; 34 34 35 BOOL (* pfnVBox InstallHook)(HMODULE hDll);36 BOOL (* pfnVBox RemoveHook)();35 BOOL (* pfnVBoxHookInstallWindowTracker)(HMODULE hDll); 36 BOOL (* pfnVBoxHookRemoveWindowTracker)(); 37 37 38 38 PVBOXDISPIFESCAPE lpEscapeData; … … 75 75 if (gCtx.hModule) 76 76 { 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 82 90 if (RT_SUCCESS(rc)) 83 91 { … … 85 93 *ppInstance = &gCtx; 86 94 } 87 else88 Log(("VBoxTray: VBoxSeamlessInit: Failed to set seamless capability\n"));89 95 } 90 96 else … … 108 114 Log(("VBoxTray: VBoxSeamlessDestroy: Failed to unset seamless capability, rc=%Rrc\n", rc)); 109 115 110 if (gCtx.pfnVBox RemoveHook)111 gCtx.pfnVBox RemoveHook();116 if (gCtx.pfnVBoxHookRemoveWindowTracker) 117 gCtx.pfnVBoxHookRemoveWindowTracker(); 112 118 if (gCtx.hModule) 113 119 FreeLibrary(gCtx.hModule); … … 118 124 void VBoxSeamlessInstallHook() 119 125 { 120 if (gCtx.pfnVBox InstallHook)126 if (gCtx.pfnVBoxHookInstallWindowTracker) 121 127 { 122 128 /* Check current visible region state */ 123 129 VBoxSeamlessCheckWindows(); 124 130 125 gCtx.pfnVBox InstallHook(gCtx.hModule);131 gCtx.pfnVBoxHookInstallWindowTracker(gCtx.hModule); 126 132 } 127 133 } … … 129 135 void VBoxSeamlessRemoveHook() 130 136 { 131 if (gCtx.pfnVBox RemoveHook)132 gCtx.pfnVBox RemoveHook();137 if (gCtx.pfnVBoxHookRemoveWindowTracker) 138 gCtx.pfnVBoxHookRemoveWindowTracker(); 133 139 134 140 if (gCtx.lpEscapeData) … … 376 382 Log(("VBoxTray: SystemParametersInfo SPI_SETSCREENSAVEACTIVE failed with %d\n", GetLastError())); 377 383 } 378 PostMessage(ghwndToolWindow, WM_VBOX_ REMOVE_SEAMLESS_HOOK, 0, 0);384 PostMessage(ghwndToolWindow, WM_VBOX_SEAMLESS_DISABLE, 0, 0); 379 385 break; 380 386 … … 390 396 if (!ret) 391 397 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); 393 399 break; 394 400 -
trunk/src/VBox/Additions/WINNT/VBoxTray/VBoxSeamless.h
r44528 r45703 28 28 void VBoxSeamlessCheckWindows(); 29 29 30 /* NOTE: both can only be called from Main thread only! */ 31 BOOL VBoxSeamlessIsAllowed(); 32 int VBoxSeamlessOnAllowChange(BOOL fEnable); 33 30 34 #endif /* __VBOXSERVICESEAMLESS__H */ -
trunk/src/VBox/Additions/WINNT/VBoxTray/VBoxTray.cpp
r44528 r45703 42 42 #include <iprt/buildconfig.h> 43 43 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 */ 64 static int vboxStInit(HWND hWnd); 65 static void vboxStTerm(); 66 /* @returns true on "IsActiveConsole" state change */ 67 static BOOL vboxStHandleEvent(WPARAM EventID, LPARAM SessionID); 68 static BOOL vboxStIsActiveConsole(); 69 70 /* 71 * Dt (desktop [state] tracking) functionality API 72 * 73 * !!!NOTE: this API is NOT thread-safe!!! 74 * */ 75 static int vboxDtInit(); 76 static void vboxDtTerm(); 77 /* @returns true on "IsInputDesktop" state change */ 78 static BOOL vboxDtHandleEvent(); 79 /* @returns true iff the application (VBoxTray) desktop is input */ 80 static BOOL vboxDtIsInputDesktop(); 81 static HANDLE vboxDtGetNotifyEvent(); 82 44 83 45 84 /******************************************************************************* … … 59 98 HANDLE ghVBoxDriver; 60 99 HANDLE ghStopSem; 61 HANDLE ghSeamless NotifyEvent = 0;100 HANDLE ghSeamlessWtNotifyEvent = 0; 62 101 SERVICE_STATUS gVBoxServiceStatus; 63 102 SERVICE_STATUS_HANDLE gVBoxServiceStatusHandle; … … 66 105 NOTIFYICONDATA gNotifyIconData; 67 106 DWORD gMajorVersion; 107 BOOL gfIsSeamlessOn = FALSE; 68 108 69 109 … … 525 565 && gMajorVersion >= 5) /* Only for W2K and up ... */ 526 566 { 527 ghSeamless NotifyEvent = CreateEvent(&SecAttr, FALSE, FALSE, VBOXHOOK_GLOBAL_EVENT_NAME);528 if (ghSeamless NotifyEvent == NULL)567 ghSeamlessWtNotifyEvent = CreateEvent(&SecAttr, FALSE, FALSE, VBOXHOOK_GLOBAL_WT_EVENT_NAME); 568 if (ghSeamlessWtNotifyEvent == NULL) 529 569 { 530 570 dwErr = GetLastError(); … … 538 578 static void vboxTrayShutdownSeamless(void) 539 579 { 540 if (ghSeamless NotifyEvent)541 { 542 CloseHandle(ghSeamless NotifyEvent);543 ghSeamless NotifyEvent = NULL;580 if (ghSeamlessWtNotifyEvent) 581 { 582 CloseHandle(ghSeamlessWtNotifyEvent); 583 ghSeamlessWtNotifyEvent = NULL; 544 584 } 545 585 } … … 617 657 */ 618 658 619 DWORD dwEventCount = 2;620 HANDLE hWaitEvent[2] = { ghStopSem, ghSeamlessNotifyEvent };621 622 if (0 == ghSeamless NotifyEvent) /* 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. */ 623 663 dwEventCount = 1; 624 664 … … 639 679 } 640 680 else if ( waitResult == 1 641 && ghSeamless NotifyEvent != 0) /* Only jump in, if seamless is active! */681 && ghSeamlessWtNotifyEvent != 0) /* Only jump in, if seamless is active! */ 642 682 { 643 683 Log(("VBoxTray: Event 'Seamless' triggered\n")); … … 645 685 /* seamless window notification */ 646 686 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 } 647 701 } 648 702 else … … 713 767 if (RT_SUCCESS(rc)) 714 768 { 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 715 789 rc = vboxTraySetupSeamless(); 716 790 if (RT_SUCCESS(rc)) … … 722 796 vboxTrayShutdownSeamless(); 723 797 } 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 724 805 vboxTrayDestroyToolWindow(); 725 806 } … … 799 880 return 0; 800 881 801 case WM_VBOX_INSTALL_SEAMLESS_HOOK: 802 VBoxSeamlessInstallHook(); 882 case WM_VBOX_SEAMLESS_ENABLE: 883 gfIsSeamlessOn = TRUE; 884 if (VBoxSeamlessIsAllowed()) 885 VBoxSeamlessInstallHook(); 803 886 return 0; 804 887 805 case WM_VBOX_REMOVE_SEAMLESS_HOOK: 806 VBoxSeamlessRemoveHook(); 888 case WM_VBOX_SEAMLESS_DISABLE: 889 gfIsSeamlessOn = FALSE; 890 if (VBoxSeamlessIsAllowed()) 891 VBoxSeamlessRemoveHook(); 807 892 return 0; 808 893 809 894 case WM_VBOX_SEAMLESS_UPDATE: 810 VBoxSeamlessCheckWindows(); 895 if (gfIsSeamlessOn && VBoxSeamlessIsAllowed()) 896 VBoxSeamlessCheckWindows(); 811 897 return 0; 812 898 … … 819 905 return 0; 820 906 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 } 821 921 default: 822 922 … … 835 935 } 836 936 937 /* St (session [state] tracking) functionality API impl */ 938 939 typedef 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 950 static VBOXST gVBoxSt; 951 952 static 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 1033 static 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 1053 static 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 1072 static 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 1120 static 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 1131 typedef 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 1144 static VBOXDT gVBoxDt; 1145 1146 static 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 } 1173 static 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 1271 static 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 */ 1285 static BOOL vboxDtHandleEvent() 1286 { 1287 BOOL fIsInputDesktop = gVBoxDt.fIsInputDesktop; 1288 gVBoxDt.fIsInputDesktop = vboxDtCalculateIsInputDesktop(); 1289 return !fIsInputDesktop != !gVBoxDt.fIsInputDesktop; 1290 } 1291 1292 static HANDLE vboxDtGetNotifyEvent() 1293 { 1294 return gVBoxDt.hNotifyEvent; 1295 } 1296 1297 /* @returns true iff the application (VBoxTray) desktop is input */ 1298 static BOOL vboxDtIsInputDesktop() 1299 { 1300 return gVBoxDt.fIsInputDesktop; 1301 } 1302 1303 1304 /* helper state tracking API */ 1305 BOOL VBoxSeamlessIsAllowed() 1306 { 1307 return vboxDtIsInputDesktop() && vboxStIsActiveConsole(); 1308 } 1309 1310 int 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 17 17 18 18 /* custom messages as we must install the hook from the main thread */ 19 #define WM_VBOX_ INSTALL_SEAMLESS_HOOK0x200120 #define WM_VBOX_ REMOVE_SEAMLESS_HOOK0x200219 #define WM_VBOX_SEAMLESS_ENABLE 0x2001 20 #define WM_VBOX_SEAMLESS_DISABLE 0x2002 21 21 #define WM_VBOX_SEAMLESS_UPDATE 0x2003 22 22 23 23 24 24 #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" 26 27 27 /* Install the global message hook */ 28 BOOL VBox InstallHook(HMODULE hDll);28 BOOL VBoxHookInstallActiveDesktopTracker(HMODULE hDll); 29 BOOL VBoxHookRemoveActiveDesktopTracker(); 29 30 30 /* Remove the global message hook */ 31 BOOL VBox RemoveHook();31 BOOL VBoxHookInstallWindowTracker(HMODULE hDll); 32 BOOL VBoxHookRemoveWindowTracker(); 32 33 33 34 #endif /* __VBoxHook_h__ */
Note:
See TracChangeset
for help on using the changeset viewer.