VBoxHook.cpp revision a16eb14ad7a4b5ef91ddc22d3e8e92d930f736fc
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync/** @file
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync *
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * VBoxHook -- Global windows hook dll
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync *
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * Copyright (C) 2006-2007 innotek GmbH
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync *
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * This file is part of VirtualBox Open Source Edition (OSE), as
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * available from http://www.virtualbox.org. This file is free software;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * you can redistribute it and/or modify it under the terms of the GNU
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * General Public License (GPL) as published by the Free Software
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * Foundation, in version 2 as it comes in the "COPYING" file of the
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync */
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync#include <windows.h>
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync#include <VBoxHook.h>
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync#include <stdio.h>
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync#pragma data_seg("SHARED")
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsyncstatic HWINEVENTHOOK hEventHook[2] = {0};
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync#pragma data_seg()
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync#pragma comment(linker, "/section:SHARED,RWS")
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsyncstatic HANDLE hNotifyEvent = 0;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync#ifdef DEBUG
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsyncvoid WriteLog(char *String, ...);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync#define dprintf(a) do { WriteLog a; } while (0)
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync#else
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync#define dprintf(a) do {} while (0)
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync#endif /* DEBUG */
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsyncvoid CALLBACK VBoxHandleWinEvent(HWINEVENTHOOK hook, DWORD event, HWND hwnd,
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync LONG idObject, LONG idChild,
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync DWORD dwEventThread, DWORD dwmsEventTime)
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync{
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync DWORD dwStyle;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync if ( idObject != OBJID_WINDOW
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync || !hwnd)
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync return;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync dwStyle = GetWindowLong(hwnd, GWL_STYLE);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync if (dwStyle & WS_CHILD)
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync return;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync switch(event)
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync {
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync case EVENT_OBJECT_LOCATIONCHANGE:
40839c441cb305d84420565f7ca25403d8177413vboxsync if (!(dwStyle & WS_VISIBLE))
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync return;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync case EVENT_OBJECT_CREATE:
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync case EVENT_OBJECT_DESTROY:
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync case EVENT_OBJECT_HIDE:
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync case EVENT_OBJECT_SHOW:
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync#ifdef DEBUG
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync switch(event)
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync {
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync case EVENT_OBJECT_LOCATIONCHANGE:
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync dprintf(("VBoxHandleWinEvent EVENT_OBJECT_LOCATIONCHANGE for window %x\n", hwnd));
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync break;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync case EVENT_OBJECT_CREATE:
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync dprintf(("VBoxHandleWinEvent EVENT_OBJECT_CREATE for window %x\n", hwnd));
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync break;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync case EVENT_OBJECT_HIDE:
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync dprintf(("VBoxHandleWinEvent EVENT_OBJECT_HIDE for window %x\n", hwnd));
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync break;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync case EVENT_OBJECT_SHOW:
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync dprintf(("VBoxHandleWinEvent EVENT_OBJECT_SHOW for window %x\n", hwnd));
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync break;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync case EVENT_OBJECT_DESTROY:
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync dprintf(("VBoxHandleWinEvent EVENT_OBJECT_DESTROY for window %x\n", hwnd));
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync break;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync }
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync#endif
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync if (!hNotifyEvent)
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync {
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync hNotifyEvent = OpenEvent(EVENT_MODIFY_STATE, FALSE, VBOXHOOK_GLOBAL_EVENT_NAME);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync dprintf(("OpenEvent returned %x (last err=%x)\n", hNotifyEvent, GetLastError()));
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync }
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync BOOL ret = SetEvent(hNotifyEvent);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync dprintf(("SetEvent %x returned %d (last error %x)\n", hNotifyEvent, ret, GetLastError()));
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync break;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync }
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync}
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync/* Install the global message hook */
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsyncBOOL VBoxInstallHook(HMODULE hDll)
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync{
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync if (hEventHook[0] || hEventHook[1])
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync return TRUE;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync CoInitialize(NULL);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync hEventHook[0] = SetWinEventHook(EVENT_OBJECT_LOCATIONCHANGE, EVENT_OBJECT_LOCATIONCHANGE,
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync hDll,
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync VBoxHandleWinEvent,
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync 0, 0,
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync WINEVENT_INCONTEXT | WINEVENT_SKIPOWNPROCESS);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync hEventHook[1] = SetWinEventHook(EVENT_OBJECT_CREATE, EVENT_OBJECT_HIDE,
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync hDll,
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync VBoxHandleWinEvent,
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync 0, 0,
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync WINEVENT_INCONTEXT | WINEVENT_SKIPOWNPROCESS);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync return !!hEventHook[0];
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync}
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync/* Remove the global message hook */
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsyncBOOL VBoxRemoveHook()
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync{
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync if (hEventHook[0] && hEventHook[1])
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync {
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync UnhookWinEvent(hEventHook[0]);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync UnhookWinEvent(hEventHook[1]);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync CoUninitialize();
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync }
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync hEventHook[0] = hEventHook[1] = 0;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync return true;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync}
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync#ifdef DEBUG
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync#include <VBox/VBoxGuest.h>
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsyncstatic char LogBuffer[1024];
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsyncstatic HANDLE gVBoxDriver = INVALID_HANDLE_VALUE;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsyncVBGLR3DECL(int) VbglR3GRPerform(VMMDevRequestHeader *pReq)
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync{
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync DWORD cbReturned;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync DeviceIoControl(gVBoxDriver, IOCTL_VBOXGUEST_VMMREQUEST, pReq, pReq->size,
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync pReq, pReq->size, &cbReturned, NULL);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync return VINF_SUCCESS;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync}
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsyncvoid WriteLog(char *pszStr, ...)
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync{
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync VMMDevReqLogString *pReq = (VMMDevReqLogString *)LogBuffer;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync int rc;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync /* open VBox guest driver */
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync if (gVBoxDriver == INVALID_HANDLE_VALUE)
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync gVBoxDriver = CreateFile(VBOXGUEST_DEVICE_NAME,
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync GENERIC_READ | GENERIC_WRITE,
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync FILE_SHARE_READ | FILE_SHARE_WRITE,
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync NULL,
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync OPEN_EXISTING,
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED,
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync NULL);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync if (gVBoxDriver == INVALID_HANDLE_VALUE)
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync return;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync va_list va;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync va_start(va, pszStr);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync vmmdevInitRequest(&pReq->header, VMMDevReq_LogString);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync vsprintf(pReq->szString, pszStr, va);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync pReq->header.size += strlen(pReq->szString);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync rc = VbglR3GRPerform(&pReq->header);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync va_end (va);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync return;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync}
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync#endif
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync