VirtualBox

source: vbox/trunk/src/VBox/Additions/WINNT/VBoxHook/VBoxHook.cpp@ 86186

Last change on this file since 86186 was 85121, checked in by vboxsync, 4 years ago

iprt/cdefs.h: Refactored the typedef use of DECLCALLBACK as well as DECLCALLBACKMEMBER to wrap the whole expression, similar to the DECLR?CALLBACKMEMBER macros. This allows adding a throw() at the end when compiling with the VC++ compiler to indicate that the callbacks won't throw anything, so we can stop supressing the C5039 warning about passing functions that can potential throw C++ exceptions to extern C code that can't necessarily cope with such (unwind,++). Introduced a few _EX variations that allows specifying different/no calling convention too, as that's handy when dynamically resolving host APIs. Fixed numerous places missing DECLCALLBACK and such. Left two angry @todos regarding use of CreateThread. bugref:9794

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 8.6 KB
Line 
1/* $Id: VBoxHook.cpp 85121 2020-07-08 19:33:26Z vboxsync $ */
2/** @file
3 * VBoxHook -- Global windows hook dll
4 */
5
6/*
7 * Copyright (C) 2006-2020 Oracle Corporation
8 *
9 * This file is part of VirtualBox Open Source Edition (OSE), as
10 * available from http://www.virtualbox.org. This file is free software;
11 * you can redistribute it and/or modify it under the terms of the GNU
12 * General Public License (GPL) as published by the Free Software
13 * Foundation, in version 2 as it comes in the "COPYING" file of the
14 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
15 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
16 */
17
18
19/*********************************************************************************************************************************
20* Header Files *
21*********************************************************************************************************************************/
22#include <iprt/win/windows.h>
23#include <VBoxHook.h>
24#include <VBox/VBoxGuestLib.h>
25#ifdef DEBUG
26# include <stdio.h>
27#endif
28
29
30/*********************************************************************************************************************************
31* Global Variables *
32*********************************************************************************************************************************/
33#pragma data_seg("SHARED")
34static HWINEVENTHOOK g_ahWinEventHook[2] = { NULL, NULL };
35static HWINEVENTHOOK g_hDesktopEventHook = NULL;
36#pragma data_seg()
37#pragma comment(linker, "/section:SHARED,RWS")
38
39static HANDLE g_hWinNotifyEvent = NULL;
40static HANDLE g_hDesktopNotifyEvent = NULL;
41
42
43/*********************************************************************************************************************************
44* Internal Functions *
45*********************************************************************************************************************************/
46#ifdef DEBUG
47static void WriteLog(const char *pszFormat, ...);
48# define dprintf(a) do { WriteLog a; } while (0)
49#else
50# define dprintf(a) do {} while (0)
51#endif /* !DEBUG */
52
53
54static void CALLBACK VBoxHandleWinEvent(HWINEVENTHOOK hWinEventHook, DWORD event, HWND hwnd,
55 LONG idObject, LONG idChild,
56 DWORD dwEventThread, DWORD dwmsEventTime) RT_NOTHROW_DEF
57{
58 RT_NOREF(hWinEventHook, idChild, dwEventThread, dwmsEventTime);
59 DWORD dwStyle;
60 if ( idObject != OBJID_WINDOW
61 || !hwnd)
62 return;
63
64 dwStyle = GetWindowLong(hwnd, GWL_STYLE);
65 if (dwStyle & WS_CHILD)
66 return;
67
68 switch(event)
69 {
70 case EVENT_OBJECT_LOCATIONCHANGE:
71 if (!(dwStyle & WS_VISIBLE))
72 return;
73
74 case EVENT_OBJECT_CREATE:
75 case EVENT_OBJECT_DESTROY:
76 case EVENT_OBJECT_HIDE:
77 case EVENT_OBJECT_SHOW:
78#ifdef DEBUG
79 switch(event)
80 {
81 case EVENT_OBJECT_LOCATIONCHANGE:
82 dprintf(("VBoxHandleWinEvent EVENT_OBJECT_LOCATIONCHANGE for window %x\n", hwnd));
83 break;
84 case EVENT_OBJECT_CREATE:
85 dprintf(("VBoxHandleWinEvent EVENT_OBJECT_CREATE for window %x\n", hwnd));
86 break;
87 case EVENT_OBJECT_HIDE:
88 dprintf(("VBoxHandleWinEvent EVENT_OBJECT_HIDE for window %x\n", hwnd));
89 break;
90 case EVENT_OBJECT_SHOW:
91 dprintf(("VBoxHandleWinEvent EVENT_OBJECT_SHOW for window %x\n", hwnd));
92 break;
93 case EVENT_OBJECT_DESTROY:
94 dprintf(("VBoxHandleWinEvent EVENT_OBJECT_DESTROY for window %x\n", hwnd));
95 break;
96 }
97#endif
98 if (!g_hWinNotifyEvent)
99 {
100 g_hWinNotifyEvent = OpenEvent(EVENT_MODIFY_STATE, FALSE, VBOXHOOK_GLOBAL_WT_EVENT_NAME);
101 dprintf(("OpenEvent returned %x (last err=%x)\n", g_hWinNotifyEvent, GetLastError()));
102 }
103 BOOL fRc = SetEvent(g_hWinNotifyEvent);
104 dprintf(("SetEvent %x returned %d (last error %x)\n", g_hWinNotifyEvent, fRc, GetLastError())); NOREF(fRc);
105 break;
106 }
107}
108
109static void CALLBACK VBoxHandleDesktopEvent(HWINEVENTHOOK hWinEventHook, DWORD event, HWND hwnd,
110 LONG idObject, LONG idChild,
111 DWORD dwEventThread, DWORD dwmsEventTime) RT_NOTHROW_DEF
112{
113 RT_NOREF(hWinEventHook, event, hwnd, idObject, idChild, dwEventThread, dwmsEventTime);
114 if (!g_hDesktopNotifyEvent)
115 {
116 g_hDesktopNotifyEvent = OpenEvent(EVENT_MODIFY_STATE, FALSE, VBOXHOOK_GLOBAL_DT_EVENT_NAME);
117 dprintf(("OpenEvent returned %x (last err=%x)\n", g_hDesktopNotifyEvent, GetLastError()));
118 }
119 BOOL fRc = SetEvent(g_hDesktopNotifyEvent);
120 dprintf(("SetEvent %x returned %d (last error %x)\n", g_hDesktopNotifyEvent, fRc, GetLastError())); NOREF(fRc);
121}
122
123BOOL VBoxHookInstallActiveDesktopTracker(HMODULE hDll)
124{
125 if (g_hDesktopEventHook)
126 return TRUE;
127
128 CoInitialize(NULL);
129 g_hDesktopEventHook = SetWinEventHook(EVENT_SYSTEM_DESKTOPSWITCH, EVENT_SYSTEM_DESKTOPSWITCH,
130 hDll,
131 VBoxHandleDesktopEvent,
132 0, 0,
133 0);
134
135 return !!g_hDesktopEventHook;
136
137}
138
139BOOL VBoxHookRemoveActiveDesktopTracker()
140{
141 if (g_hDesktopEventHook)
142 {
143 UnhookWinEvent(g_hDesktopEventHook);
144 CoUninitialize();
145 }
146 g_hDesktopEventHook = 0;
147 return TRUE;
148}
149
150/** Install the global message hook */
151BOOL VBoxHookInstallWindowTracker(HMODULE hDll)
152{
153 if (g_ahWinEventHook[0] || g_ahWinEventHook[1])
154 return TRUE;
155
156 CoInitialize(NULL);
157 g_ahWinEventHook[0] = SetWinEventHook(EVENT_OBJECT_LOCATIONCHANGE, EVENT_OBJECT_LOCATIONCHANGE,
158 hDll,
159 VBoxHandleWinEvent,
160 0, 0,
161 WINEVENT_INCONTEXT | WINEVENT_SKIPOWNPROCESS);
162
163 g_ahWinEventHook[1] = SetWinEventHook(EVENT_OBJECT_CREATE, EVENT_OBJECT_HIDE,
164 hDll,
165 VBoxHandleWinEvent,
166 0, 0,
167 WINEVENT_INCONTEXT | WINEVENT_SKIPOWNPROCESS);
168 return !!g_ahWinEventHook[0];
169}
170
171/** Remove the global message hook */
172BOOL VBoxHookRemoveWindowTracker()
173{
174 if (g_ahWinEventHook[0] && g_ahWinEventHook[1])
175 {
176 UnhookWinEvent(g_ahWinEventHook[0]);
177 UnhookWinEvent(g_ahWinEventHook[1]);
178 CoUninitialize();
179 }
180 g_ahWinEventHook[0] = g_ahWinEventHook[1] = 0;
181 return TRUE;
182}
183
184
185#ifdef DEBUG
186# include <VBox/VBoxGuest.h>
187# include <VBox/VMMDev.h>
188
189/**
190 * dprintf worker using VBoxGuest.sys and VMMDevReq_LogString.
191 */
192static void WriteLog(const char *pszFormat, ...)
193{
194 /*
195 * Open VBox guest driver once.
196 */
197 static HANDLE s_hVBoxGuest = INVALID_HANDLE_VALUE;
198 HANDLE hVBoxGuest = s_hVBoxGuest;
199 if (hVBoxGuest == INVALID_HANDLE_VALUE)
200 {
201 hVBoxGuest = CreateFile(VBOXGUEST_DEVICE_NAME,
202 GENERIC_READ | GENERIC_WRITE,
203 FILE_SHARE_READ | FILE_SHARE_WRITE,
204 NULL,
205 OPEN_EXISTING,
206 FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED,
207 NULL);
208 if (hVBoxGuest == INVALID_HANDLE_VALUE)
209 return;
210 s_hVBoxGuest = hVBoxGuest;
211 }
212
213 /*
214 * We're apparently afraid of using stack here, so we use a static buffer
215 * instead and pray we won't be here at the same time on two threads...
216 */
217 static union
218 {
219 VMMDevReqLogString Req;
220 uint8_t abBuf[1024];
221 } s_uBuf;
222
223 vmmdevInitRequest(&s_uBuf.Req.header, VMMDevReq_LogString);
224
225 va_list va;
226 va_start(va, pszFormat);
227 size_t cch = vsprintf(s_uBuf.Req.szString, pszFormat, va);
228 va_end(va);
229
230 s_uBuf.Req.header.size += (uint32_t)cch;
231 if (s_uBuf.Req.header.size > sizeof(s_uBuf))
232 __debugbreak();
233
234 DWORD cbReturned;
235 DeviceIoControl(hVBoxGuest, VBGL_IOCTL_VMMDEV_REQUEST(s_uBuf.Req.size),
236 &s_uBuf.Req, s_uBuf.Req.header.size,
237 &s_uBuf.Req, s_uBuf.Req.header.size,
238 &cbReturned, NULL);
239}
240
241#endif /* DEBUG */
242
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette