VirtualBox

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

Last change on this file since 56293 was 56293, checked in by vboxsync, 10 years ago

HostDrivers: Updated (C) year.

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