VirtualBox

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

Last change on this file since 66295 was 62717, checked in by vboxsync, 9 years ago

HostDrivers: warnings

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