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