VirtualBox

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

Last change on this file was 98103, checked in by vboxsync, 16 months ago

Copyright year updates by scm.

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

© 2023 Oracle
ContactPrivacy policyTerms of Use