VirtualBox

source: vbox/trunk/src/VBox/HostDrivers/VBoxUSB/win/mon/VBoxUsbHook.cpp@ 79846

Last change on this file since 79846 was 76553, checked in by vboxsync, 6 years ago

scm --update-copyright-year

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 7.8 KB
Line 
1/* $Id: VBoxUsbHook.cpp 76553 2019-01-01 01:45:53Z vboxsync $ */
2/** @file
3 * Driver Dispatch Table Hooking API
4 */
5
6/*
7 * Copyright (C) 2011-2019 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 * The contents of this file may alternatively be used under the terms
18 * of the Common Development and Distribution License Version 1.0
19 * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
20 * VirtualBox OSE distribution, in which case the provisions of the
21 * CDDL are applicable instead of those of the GPL.
22 *
23 * You may elect to license modified versions of this file under the
24 * terms and conditions of either the GPL or the CDDL or both.
25 */
26
27
28/*********************************************************************************************************************************
29* Header Files *
30*********************************************************************************************************************************/
31#include "VBoxUsbMon.h"
32
33
34/*********************************************************************************************************************************
35* Defined Constants And Macros *
36*********************************************************************************************************************************/
37#define VBOXUSBHOOK_MEMTAG 'HUBV'
38
39
40NTSTATUS VBoxUsbHookInstall(PVBOXUSBHOOK_ENTRY pHook)
41{
42 KIRQL Irql;
43 KeAcquireSpinLock(&pHook->Lock, &Irql);
44 if (pHook->fIsInstalled)
45 {
46 WARN(("hook is marked installed, returning failure"));
47 KeReleaseSpinLock(&pHook->Lock, Irql);
48 return STATUS_UNSUCCESSFUL;
49 }
50
51 pHook->pfnOldHandler = (PDRIVER_DISPATCH)InterlockedExchangePointer((PVOID*)&pHook->pDrvObj->MajorFunction[pHook->iMjFunction], pHook->pfnHook);
52 Assert(pHook->pfnOldHandler);
53 Assert(pHook->pfnHook != pHook->pfnOldHandler);
54 pHook->fIsInstalled = TRUE;
55 KeReleaseSpinLock(&pHook->Lock, Irql);
56 return STATUS_SUCCESS;
57
58}
59NTSTATUS VBoxUsbHookUninstall(PVBOXUSBHOOK_ENTRY pHook)
60{
61 KIRQL Irql;
62 KeAcquireSpinLock(&pHook->Lock, &Irql);
63 if (!pHook->fIsInstalled)
64 {
65 KeReleaseSpinLock(&pHook->Lock, Irql);
66 return STATUS_SUCCESS;
67 }
68
69 PDRIVER_DISPATCH pfnOldVal = (PDRIVER_DISPATCH)InterlockedCompareExchangePointer((PVOID*)&pHook->pDrvObj->MajorFunction[pHook->iMjFunction], pHook->pfnOldHandler, pHook->pfnHook);
70 Assert(pfnOldVal == pHook->pfnHook);
71 if (pfnOldVal != pHook->pfnHook)
72 {
73 AssertMsgFailed(("unhook failed!!!\n"));
74 /* this is bad! this could happen if someone else has chained another hook,
75 * or (which is even worse) restored the "initial" entry value it saved when doing a hooking before us
76 * return the failure and don't do anything else
77 * the best thing to do if this happens is to leave everything as is
78 * and to prevent the driver from being unloaded to ensure no one references our unloaded hook routine */
79 KeReleaseSpinLock(&pHook->Lock, Irql);
80 return STATUS_UNSUCCESSFUL;
81 }
82
83 pHook->fIsInstalled = FALSE;
84 KeReleaseSpinLock(&pHook->Lock, Irql);
85
86 /* wait for the current handlers to exit */
87 VBoxDrvToolRefWaitEqual(&pHook->HookRef, 1);
88
89 return STATUS_SUCCESS;
90}
91
92BOOLEAN VBoxUsbHookIsInstalled(PVBOXUSBHOOK_ENTRY pHook)
93{
94 KIRQL Irql;
95 BOOLEAN fIsInstalled;
96 KeAcquireSpinLock(&pHook->Lock, &Irql);
97 fIsInstalled = pHook->fIsInstalled;
98 KeReleaseSpinLock(&pHook->Lock, Irql);
99 return fIsInstalled;
100}
101
102VOID VBoxUsbHookInit(PVBOXUSBHOOK_ENTRY pHook, PDRIVER_OBJECT pDrvObj, UCHAR iMjFunction, PDRIVER_DISPATCH pfnHook)
103{
104 Assert(pDrvObj);
105 Assert(iMjFunction <= IRP_MJ_MAXIMUM_FUNCTION);
106 Assert(pfnHook);
107 memset(pHook, 0, sizeof (*pHook));
108 InitializeListHead(&pHook->RequestList);
109 KeInitializeSpinLock(&pHook->Lock);
110 VBoxDrvToolRefInit(&pHook->HookRef);
111 pHook->pDrvObj = pDrvObj;
112 pHook->iMjFunction = iMjFunction;
113 pHook->pfnHook = pfnHook;
114 Assert(!pHook->pfnOldHandler);
115 Assert(!pHook->fIsInstalled);
116
117}
118
119static void vboxUsbHookRequestRegisterCompletion(PVBOXUSBHOOK_ENTRY pHook, PDEVICE_OBJECT pDevObj, PIRP pIrp, PIO_COMPLETION_ROUTINE pfnCompletion, PVBOXUSBHOOK_REQUEST pRequest)
120{
121 Assert(pfnCompletion);
122 Assert(pRequest);
123 Assert(pDevObj);
124 Assert(pIrp);
125 PIO_STACK_LOCATION pSl = IoGetCurrentIrpStackLocation(pIrp);
126 memset(pRequest, 0, sizeof (*pRequest));
127 pRequest->pHook = pHook;
128 pRequest->OldLocation = *pSl;
129 pRequest->pDevObj = pDevObj;
130 pRequest->pIrp = pIrp;
131 pRequest->bCompletionStopped = FALSE;
132 pSl->CompletionRoutine = pfnCompletion;
133 pSl->Context = pRequest;
134 pSl->Control = SL_INVOKE_ON_SUCCESS | SL_INVOKE_ON_ERROR | SL_INVOKE_ON_CANCEL;
135
136 KIRQL oldIrql;
137 KeAcquireSpinLock(&pHook->Lock, &oldIrql);
138 InsertTailList(&pHook->RequestList, &pRequest->ListEntry);
139 KeReleaseSpinLock(&pHook->Lock, oldIrql);
140}
141
142NTSTATUS VBoxUsbHookRequestPassDownHookCompletion(PVBOXUSBHOOK_ENTRY pHook, PDEVICE_OBJECT pDevObj, PIRP pIrp, PIO_COMPLETION_ROUTINE pfnCompletion, PVBOXUSBHOOK_REQUEST pRequest)
143{
144 Assert(pfnCompletion);
145 vboxUsbHookRequestRegisterCompletion(pHook, pDevObj, pIrp, pfnCompletion, pRequest);
146 return pHook->pfnOldHandler(pDevObj, pIrp);
147}
148
149NTSTATUS VBoxUsbHookRequestPassDownHookSkip(PVBOXUSBHOOK_ENTRY pHook, PDEVICE_OBJECT pDevObj, PIRP pIrp)
150{
151 return pHook->pfnOldHandler(pDevObj, pIrp);
152}
153
154NTSTATUS VBoxUsbHookRequestMoreProcessingRequired(PVBOXUSBHOOK_ENTRY pHook, PDEVICE_OBJECT pDevObj, PIRP pIrp,
155 PVBOXUSBHOOK_REQUEST pRequest)
156{
157 RT_NOREF3(pHook, pDevObj, pIrp);
158 Assert(!pRequest->bCompletionStopped);
159 pRequest->bCompletionStopped = TRUE;
160 return STATUS_MORE_PROCESSING_REQUIRED;
161}
162
163NTSTATUS VBoxUsbHookRequestComplete(PVBOXUSBHOOK_ENTRY pHook, PDEVICE_OBJECT pDevObj, PIRP pIrp, PVBOXUSBHOOK_REQUEST pRequest)
164{
165 NTSTATUS Status = STATUS_SUCCESS;
166
167 if (pRequest->OldLocation.CompletionRoutine && pRequest->OldLocation.Control)
168 {
169 Status = pRequest->OldLocation.CompletionRoutine(pDevObj, pIrp, pRequest->OldLocation.Context);
170 }
171
172 if (Status != STATUS_MORE_PROCESSING_REQUIRED)
173 {
174 if (pRequest->bCompletionStopped)
175 {
176 IoCompleteRequest(pIrp, IO_NO_INCREMENT);
177 }
178 }
179 /*
180 * else - in case driver returned STATUS_MORE_PROCESSING_REQUIRED,
181 * it will call IoCompleteRequest itself
182 */
183
184 KIRQL oldIrql;
185 KeAcquireSpinLock(&pHook->Lock, &oldIrql);
186 RemoveEntryList(&pRequest->ListEntry);
187 KeReleaseSpinLock(&pHook->Lock, oldIrql);
188 return Status;
189}
190
191#define PVBOXUSBHOOK_REQUEST_FROM_LE(_pLe) ( (PVBOXUSBHOOK_REQUEST)( ((uint8_t*)(_pLe)) - RT_OFFSETOF(VBOXUSBHOOK_REQUEST, ListEntry) ) )
192
193VOID VBoxUsbHookVerifyCompletion(PVBOXUSBHOOK_ENTRY pHook, PVBOXUSBHOOK_REQUEST pRequest, PIRP pIrp)
194{
195 KIRQL oldIrql;
196 KeAcquireSpinLock(&pHook->Lock, &oldIrql);
197 for (PLIST_ENTRY pLe = pHook->RequestList.Flink; pLe != &pHook->RequestList; pLe = pLe->Flink)
198 {
199 PVBOXUSBHOOK_REQUEST pCur = PVBOXUSBHOOK_REQUEST_FROM_LE(pLe);
200 if (pCur != pRequest)
201 continue;
202 if (pCur->pIrp != pIrp)
203 continue;
204 WARN(("found pending IRP(0x%p) when it should not be", pIrp));
205 }
206 KeReleaseSpinLock(&pHook->Lock, oldIrql);
207
208}
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