diff options
Diffstat (limited to 'src/VBox/Additions/WINNT/VBoxHook/VBoxHook.cpp')
-rw-r--r-- | src/VBox/Additions/WINNT/VBoxHook/VBoxHook.cpp | 205 |
1 files changed, 130 insertions, 75 deletions
diff --git a/src/VBox/Additions/WINNT/VBoxHook/VBoxHook.cpp b/src/VBox/Additions/WINNT/VBoxHook/VBoxHook.cpp index 553aae32..291a9d7c 100644 --- a/src/VBox/Additions/WINNT/VBoxHook/VBoxHook.cpp +++ b/src/VBox/Additions/WINNT/VBoxHook/VBoxHook.cpp @@ -1,8 +1,10 @@ +/* $Id: VBoxHook.cpp $ */ /** @file - * * VBoxHook -- Global windows hook dll - * - * Copyright (C) 2006-2007 Oracle Corporation + */ + +/* + * Copyright (C) 2006-2010 Oracle Corporation * * This file is part of VirtualBox Open Source Edition (OSE), as * available from http://www.virtualbox.org. This file is free software; @@ -12,29 +14,32 @@ * VirtualBox OSE distribution. VirtualBox OSE is distributed in the * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind. */ + #include <Windows.h> #include <VBoxHook.h> #include <VBox/VBoxGuestLib.h> #include <stdio.h> #pragma data_seg("SHARED") -static HWINEVENTHOOK hEventHook[2] = {0}; +static HWINEVENTHOOK hWinEventHook[2] = {0}; +static HWINEVENTHOOK hDesktopEventHook = NULL; #pragma data_seg() #pragma comment(linker, "/section:SHARED,RWS") -static HANDLE hNotifyEvent = 0; +static HANDLE hWinNotifyEvent = 0; +static HANDLE hDesktopNotifyEvent = 0; #ifdef DEBUG -void WriteLog(char *String, ...); -#define dprintf(a) do { WriteLog a; } while (0) +static void WriteLog(const char *pszFormat, ...); +# define dprintf(a) do { WriteLog a; } while (0) #else -#define dprintf(a) do {} while (0) -#endif /* DEBUG */ +# define dprintf(a) do {} while (0) +#endif /* !DEBUG */ -void CALLBACK VBoxHandleWinEvent(HWINEVENTHOOK hook, DWORD event, HWND hwnd, - LONG idObject, LONG idChild, - DWORD dwEventThread, DWORD dwmsEventTime) +static void CALLBACK VBoxHandleWinEvent(HWINEVENTHOOK hook, DWORD event, HWND hwnd, + LONG idObject, LONG idChild, + DWORD dwEventThread, DWORD dwmsEventTime) { DWORD dwStyle; if ( idObject != OBJID_WINDOW @@ -75,97 +80,147 @@ void CALLBACK VBoxHandleWinEvent(HWINEVENTHOOK hook, DWORD event, HWND hwnd, break; } #endif - if (!hNotifyEvent) + if (!hWinNotifyEvent) { - hNotifyEvent = OpenEvent(EVENT_MODIFY_STATE, FALSE, VBOXHOOK_GLOBAL_EVENT_NAME); - dprintf(("OpenEvent returned %x (last err=%x)\n", hNotifyEvent, GetLastError())); + hWinNotifyEvent = OpenEvent(EVENT_MODIFY_STATE, FALSE, VBOXHOOK_GLOBAL_WT_EVENT_NAME); + dprintf(("OpenEvent returned %x (last err=%x)\n", hWinNotifyEvent, GetLastError())); } - BOOL ret = SetEvent(hNotifyEvent); - dprintf(("SetEvent %x returned %d (last error %x)\n", hNotifyEvent, ret, GetLastError())); + BOOL ret = SetEvent(hWinNotifyEvent); + dprintf(("SetEvent %x returned %d (last error %x)\n", hWinNotifyEvent, ret, GetLastError())); break; } } +static void CALLBACK VBoxHandleDesktopEvent(HWINEVENTHOOK hook, DWORD event, HWND hwnd, + LONG idObject, LONG idChild, + DWORD dwEventThread, DWORD dwmsEventTime) +{ + if (!hDesktopNotifyEvent) + { + hDesktopNotifyEvent = OpenEvent(EVENT_MODIFY_STATE, FALSE, VBOXHOOK_GLOBAL_DT_EVENT_NAME); + dprintf(("OpenEvent returned %x (last err=%x)\n", hDesktopNotifyEvent, GetLastError())); + } + BOOL ret = SetEvent(hDesktopNotifyEvent); + dprintf(("SetEvent %x returned %d (last error %x)\n", hDesktopNotifyEvent, ret, GetLastError())); +} -/* Install the global message hook */ -BOOL VBoxInstallHook(HMODULE hDll) +BOOL VBoxHookInstallActiveDesktopTracker(HMODULE hDll) { - if (hEventHook[0] || hEventHook[1]) + if (hDesktopEventHook) return TRUE; CoInitialize(NULL); - hEventHook[0] = SetWinEventHook(EVENT_OBJECT_LOCATIONCHANGE, EVENT_OBJECT_LOCATIONCHANGE, - hDll, - VBoxHandleWinEvent, - 0, 0, - WINEVENT_INCONTEXT | WINEVENT_SKIPOWNPROCESS); - - hEventHook[1] = SetWinEventHook(EVENT_OBJECT_CREATE, EVENT_OBJECT_HIDE, - hDll, - VBoxHandleWinEvent, - 0, 0, - WINEVENT_INCONTEXT | WINEVENT_SKIPOWNPROCESS); - return !!hEventHook[0]; + hDesktopEventHook = SetWinEventHook(EVENT_SYSTEM_DESKTOPSWITCH, EVENT_SYSTEM_DESKTOPSWITCH, + hDll, + VBoxHandleDesktopEvent, + 0, 0, + 0); + + return !!hDesktopEventHook; + } -/* Remove the global message hook */ -BOOL VBoxRemoveHook() +BOOL VBoxHookRemoveActiveDesktopTracker() { - if (hEventHook[0] && hEventHook[1]) + if (hDesktopEventHook) { - UnhookWinEvent(hEventHook[0]); - UnhookWinEvent(hEventHook[1]); + UnhookWinEvent(hDesktopEventHook); CoUninitialize(); } - hEventHook[0] = hEventHook[1] = 0; - return true; + hDesktopEventHook = 0; + return TRUE; } +/** Install the global message hook */ +BOOL VBoxHookInstallWindowTracker(HMODULE hDll) +{ + if (hWinEventHook[0] || hWinEventHook[1]) + return TRUE; -#ifdef DEBUG -#include <VBox/VBoxGuest.h> -#include <VBox/VMMDev.h> - -static char LogBuffer[1024]; -static HANDLE gVBoxDriver = INVALID_HANDLE_VALUE; + CoInitialize(NULL); + hWinEventHook[0] = SetWinEventHook(EVENT_OBJECT_LOCATIONCHANGE, EVENT_OBJECT_LOCATIONCHANGE, + hDll, + VBoxHandleWinEvent, + 0, 0, + WINEVENT_INCONTEXT | WINEVENT_SKIPOWNPROCESS); + + hWinEventHook[1] = SetWinEventHook(EVENT_OBJECT_CREATE, EVENT_OBJECT_HIDE, + hDll, + VBoxHandleWinEvent, + 0, 0, + WINEVENT_INCONTEXT | WINEVENT_SKIPOWNPROCESS); + return !!hWinEventHook[0]; +} -VBGLR3DECL(int) VbglR3GRPerform(VMMDevRequestHeader *pReq) +/** Remove the global message hook */ +BOOL VBoxHookRemoveWindowTracker() { - DWORD cbReturned; - DeviceIoControl(gVBoxDriver, VBOXGUEST_IOCTL_VMMREQUEST(pReq->size), pReq, pReq->size, - pReq, pReq->size, &cbReturned, NULL); - return VINF_SUCCESS; + if (hWinEventHook[0] && hWinEventHook[1]) + { + UnhookWinEvent(hWinEventHook[0]); + UnhookWinEvent(hWinEventHook[1]); + CoUninitialize(); + } + hWinEventHook[0] = hWinEventHook[1] = 0; + return TRUE; } -void WriteLog(char *pszStr, ...) + +#ifdef DEBUG +# include <VBox/VBoxGuest.h> +# include <VBox/VMMDev.h> + +/** + * dprintf worker using VBoxGuest.sys and VMMDevReq_LogString. + */ +static void WriteLog(const char *pszFormat, ...) { - VMMDevReqLogString *pReq = (VMMDevReqLogString *)LogBuffer; - int rc; - - /* open VBox guest driver */ - if (gVBoxDriver == INVALID_HANDLE_VALUE) - gVBoxDriver = CreateFile(VBOXGUEST_DEVICE_NAME, - GENERIC_READ | GENERIC_WRITE, - FILE_SHARE_READ | FILE_SHARE_WRITE, - NULL, - OPEN_EXISTING, - FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED, - NULL); - - if (gVBoxDriver == INVALID_HANDLE_VALUE) - return; + /* + * Open VBox guest driver once. + */ + static HANDLE s_hVBoxGuest = INVALID_HANDLE_VALUE; + HANDLE hVBoxGuest = s_hVBoxGuest; + if (hVBoxGuest == INVALID_HANDLE_VALUE) + { + hVBoxGuest = CreateFile(VBOXGUEST_DEVICE_NAME, + GENERIC_READ | GENERIC_WRITE, + FILE_SHARE_READ | FILE_SHARE_WRITE, + NULL, + OPEN_EXISTING, + FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED, + NULL); + if (hVBoxGuest == INVALID_HANDLE_VALUE) + return; + s_hVBoxGuest = hVBoxGuest; + } - va_list va; + /* + * We're apparently afraid of using stack here, so we use a static buffer + * instead and pray we won't be here at the same time on two threads... + */ + static union + { + VMMDevReqLogString Req; + uint8_t abBuf[1024]; + } s_uBuf; - va_start(va, pszStr); + vmmdevInitRequest(&s_uBuf.Req.header, VMMDevReq_LogString); + + va_list va; + va_start(va, pszFormat); + size_t cch = vsprintf(s_uBuf.Req.szString, pszFormat, va); + va_end(va); - vmmdevInitRequest(&pReq->header, VMMDevReq_LogString); - vsprintf(pReq->szString, pszStr, va); - pReq->header.size += strlen(pReq->szString); - rc = VbglR3GRPerform(&pReq->header); + s_uBuf.Req.header.size += (uint32_t)cch; + if (s_uBuf.Req.header.size > sizeof(s_uBuf)) + __debugbreak(); - va_end (va); - return; + DWORD cbReturned; + DeviceIoControl(hVBoxGuest, VBOXGUEST_IOCTL_VMMREQUEST(s_uBuf.Req.size), + &s_uBuf.Req, s_uBuf.Req.header.size, + &s_uBuf.Req, s_uBuf.Req.header.size, + &cbReturned, NULL); } -#endif +#endif /* DEBUG */ + |