VirtualBox

source: vbox/trunk/src/VBox/HostDrivers/VBoxUSB/win/dev/VBoxUsbDev.cpp@ 97405

Last change on this file since 97405 was 96407, checked in by vboxsync, 2 years ago

scm copyright and license note update

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 11.3 KB
Line 
1/* $Id: VBoxUsbDev.cpp 96407 2022-08-22 17:43:14Z vboxsync $ */
2/** @file
3 * VBoxUsbDev.cpp - USB device.
4 */
5
6/*
7 * Copyright (C) 2011-2022 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 * The contents of this file may alternatively be used under the terms
26 * of the Common Development and Distribution License Version 1.0
27 * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
28 * in the VirtualBox distribution, in which case the provisions of the
29 * CDDL are applicable instead of those of the GPL.
30 *
31 * You may elect to license modified versions of this file under the
32 * terms and conditions of either the GPL or the CDDL or both.
33 *
34 * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
35 */
36
37
38/*********************************************************************************************************************************
39* Header Files *
40*********************************************************************************************************************************/
41#include "VBoxUsbCmn.h"
42#include <iprt/assert.h>
43#include <VBox/log.h>
44
45
46/*********************************************************************************************************************************
47* Defined Constants And Macros *
48*********************************************************************************************************************************/
49#define VBOXUSB_MEMTAG 'bUBV'
50
51
52
53DECLHIDDEN(PVOID) vboxUsbMemAlloc(SIZE_T cbBytes)
54{
55 PVOID pvMem = ExAllocatePoolWithTag(NonPagedPool, cbBytes, VBOXUSB_MEMTAG);
56 Assert(pvMem);
57 return pvMem;
58}
59
60DECLHIDDEN(PVOID) vboxUsbMemAllocZ(SIZE_T cbBytes)
61{
62 PVOID pvMem = vboxUsbMemAlloc(cbBytes);
63 if (pvMem)
64 {
65 RtlZeroMemory(pvMem, cbBytes);
66 }
67 return pvMem;
68}
69
70DECLHIDDEN(VOID) vboxUsbMemFree(PVOID pvMem)
71{
72 ExFreePoolWithTag(pvMem, VBOXUSB_MEMTAG);
73}
74
75VBOXUSB_GLOBALS g_VBoxUsbGlobals = {0};
76
77static NTSTATUS vboxUsbDdiAddDevice(PDRIVER_OBJECT pDriverObject,
78 PDEVICE_OBJECT pPDO)
79{
80 PDEVICE_OBJECT pFDO = NULL;
81 NTSTATUS Status = IoCreateDevice(pDriverObject,
82 sizeof (VBOXUSBDEV_EXT),
83 NULL, /* IN PUNICODE_STRING pDeviceName OPTIONAL */
84 FILE_DEVICE_UNKNOWN, /* IN DEVICE_TYPE DeviceType */
85 FILE_AUTOGENERATED_DEVICE_NAME, /* IN ULONG DeviceCharacteristics */
86 FALSE, /* IN BOOLEAN fExclusive */
87 &pFDO);
88 Assert(Status == STATUS_SUCCESS);
89 if (Status == STATUS_SUCCESS)
90 {
91 PVBOXUSBDEV_EXT pDevExt = (PVBOXUSBDEV_EXT)pFDO->DeviceExtension;
92 /* init Device Object bits */
93 pFDO->Flags |= DO_DIRECT_IO;
94 if (pPDO->Flags & DO_POWER_PAGABLE)
95 pFDO->Flags |= DO_POWER_PAGABLE;
96
97
98 /* now init our state bits */
99
100 pDevExt->cHandles = 0;
101
102 pDevExt->pFDO = pFDO;
103 pDevExt->pPDO = pPDO;
104 pDevExt->pLowerDO = IoAttachDeviceToDeviceStack(pFDO, pPDO);
105 Assert(pDevExt->pLowerDO);
106 if (pDevExt->pLowerDO)
107 {
108 vboxUsbDdiStateInit(pDevExt);
109 Status = vboxUsbRtInit(pDevExt);
110 if (Status == STATUS_SUCCESS)
111 {
112 /* we're done! */
113 pFDO->Flags &= ~DO_DEVICE_INITIALIZING;
114 return STATUS_SUCCESS;
115 }
116
117 IoDetachDevice(pDevExt->pLowerDO);
118 }
119 else
120 Status = STATUS_NO_SUCH_DEVICE;
121
122 IoDeleteDevice(pFDO);
123 }
124
125 return Status;
126}
127
128static VOID vboxUsbDdiUnload(PDRIVER_OBJECT pDriverObject)
129{
130 RT_NOREF1(pDriverObject);
131 LogRel(("VBoxUsb::DriverUnload. Built Date (%s) Time (%s)\n", __DATE__, __TIME__));
132 VBoxDrvToolStrFree(&g_VBoxUsbGlobals.RegPath);
133
134 vboxUsbRtGlobalsTerm();
135
136 PRTLOGGER pLogger = RTLogRelSetDefaultInstance(NULL);
137 if (pLogger)
138 {
139 RTLogDestroy(pLogger);
140 }
141 pLogger = RTLogSetDefaultInstance(NULL);
142 if (pLogger)
143 {
144 RTLogDestroy(pLogger);
145 }
146}
147
148static NTSTATUS vboxUsbDispatchCreate(IN PDEVICE_OBJECT pDeviceObject, IN PIRP pIrp)
149{
150 PVBOXUSBDEV_EXT pDevExt = (PVBOXUSBDEV_EXT)pDeviceObject->DeviceExtension;
151 NTSTATUS Status = STATUS_INVALID_HANDLE;
152 do
153 {
154 if (vboxUsbPnPStateGet(pDevExt) != ENMVBOXUSB_PNPSTATE_STARTED)
155 {
156 Status = STATUS_INVALID_DEVICE_STATE;
157 break;
158 }
159
160 PIO_STACK_LOCATION pSl = IoGetCurrentIrpStackLocation(pIrp);
161 PFILE_OBJECT pFObj = pSl->FileObject;
162 if (!pFObj)
163 {
164 Status = STATUS_INVALID_PARAMETER;
165 break;
166 }
167
168 pFObj->FsContext = NULL;
169
170 if (pFObj->FileName.Length)
171 {
172 Status = STATUS_INVALID_PARAMETER;
173 break;
174 }
175
176 Status = vboxUsbRtCreate(pDevExt, pIrp);
177 if (!NT_SUCCESS(Status))
178 {
179 AssertFailed();
180 break;
181 }
182
183 ASMAtomicIncU32(&pDevExt->cHandles);
184 Status = STATUS_SUCCESS;
185 break;
186 } while (0);
187
188 Status = VBoxDrvToolIoComplete(pIrp, Status, 0);
189 return Status;
190}
191
192static NTSTATUS vboxUsbDispatchClose(IN PDEVICE_OBJECT pDeviceObject, IN PIRP pIrp)
193{
194 PVBOXUSBDEV_EXT pDevExt = (PVBOXUSBDEV_EXT)pDeviceObject->DeviceExtension;
195 NTSTATUS Status = STATUS_SUCCESS;
196#ifdef VBOX_STRICT
197 PIO_STACK_LOCATION pSl = IoGetCurrentIrpStackLocation(pIrp);
198 PFILE_OBJECT pFObj = pSl->FileObject;
199 Assert(pFObj);
200 Assert(!pFObj->FileName.Length);
201#endif
202 Status = vboxUsbRtClose(pDevExt, pIrp);
203 if (NT_SUCCESS(Status))
204 {
205 ASMAtomicDecU32(&pDevExt->cHandles);
206 }
207 else
208 {
209 AssertFailed();
210 }
211 Status = VBoxDrvToolIoComplete(pIrp, Status, 0);
212 return Status;
213}
214
215static NTSTATUS vboxUsbDispatchDeviceControl(IN PDEVICE_OBJECT pDeviceObject, IN PIRP pIrp)
216{
217 PVBOXUSBDEV_EXT pDevExt = (PVBOXUSBDEV_EXT)pDeviceObject->DeviceExtension;
218 if (vboxUsbDdiStateRetainIfStarted(pDevExt))
219 return vboxUsbRtDispatch(pDevExt, pIrp);
220 return VBoxDrvToolIoComplete(pIrp, STATUS_INVALID_DEVICE_STATE, 0);
221}
222
223static NTSTATUS vboxUsbDispatchCleanup(IN PDEVICE_OBJECT pDeviceObject, IN PIRP pIrp)
224{
225 RT_NOREF1(pDeviceObject);
226 return VBoxDrvToolIoComplete(pIrp, STATUS_SUCCESS, 0);
227}
228
229static NTSTATUS vboxUsbDevAccessDeviedDispatchStub(IN PDEVICE_OBJECT pDeviceObject, IN PIRP pIrp)
230{
231 PVBOXUSBDEV_EXT pDevExt = (PVBOXUSBDEV_EXT)pDeviceObject->DeviceExtension;
232 if (!vboxUsbDdiStateRetainIfNotRemoved(pDevExt))
233 {
234 VBoxDrvToolIoComplete(pIrp, STATUS_DELETE_PENDING, 0);
235 return STATUS_DELETE_PENDING;
236 }
237
238 NTSTATUS Status = VBoxDrvToolIoComplete(pIrp, STATUS_ACCESS_DENIED, 0);
239
240 vboxUsbDdiStateRelease(pDevExt);
241
242 return Status;
243}
244
245static NTSTATUS vboxUsbDispatchSystemControl(IN PDEVICE_OBJECT pDeviceObject, IN PIRP pIrp)
246{
247 PVBOXUSBDEV_EXT pDevExt = (PVBOXUSBDEV_EXT)pDeviceObject->DeviceExtension;
248 if (!vboxUsbDdiStateRetainIfNotRemoved(pDevExt))
249 {
250 VBoxDrvToolIoComplete(pIrp, STATUS_DELETE_PENDING, 0);
251 return STATUS_DELETE_PENDING;
252 }
253
254 IoSkipCurrentIrpStackLocation(pIrp);
255
256 NTSTATUS Status = IoCallDriver(pDevExt->pLowerDO, pIrp);
257
258 vboxUsbDdiStateRelease(pDevExt);
259
260 return Status;
261}
262
263static NTSTATUS vboxUsbDispatchRead(IN PDEVICE_OBJECT pDeviceObject, IN PIRP pIrp)
264{
265#ifdef DEBUG_misha
266 AssertFailed();
267#endif
268 return vboxUsbDevAccessDeviedDispatchStub(pDeviceObject, pIrp);
269}
270
271static NTSTATUS vboxUsbDispatchWrite(IN PDEVICE_OBJECT pDeviceObject, IN PIRP pIrp)
272{
273#ifdef DEBUG_misha
274 AssertFailed();
275#endif
276 return vboxUsbDevAccessDeviedDispatchStub(pDeviceObject, pIrp);
277}
278
279RT_C_DECLS_BEGIN
280
281NTSTATUS DriverEntry(IN PDRIVER_OBJECT pDriverObject, IN PUNICODE_STRING pRegistryPath);
282
283RT_C_DECLS_END
284
285NTSTATUS DriverEntry(IN PDRIVER_OBJECT pDriverObject, IN PUNICODE_STRING pRegistryPath)
286{
287 LogRel(("VBoxUsb::DriverEntry. Built Date (%s) Time (%s)\n", __DATE__, __TIME__));
288
289 NTSTATUS Status = vboxUsbRtGlobalsInit();
290 Assert(Status == STATUS_SUCCESS);
291 if (Status == STATUS_SUCCESS)
292 {
293 Status = VBoxDrvToolStrCopy(&g_VBoxUsbGlobals.RegPath, pRegistryPath);
294 Assert(Status == STATUS_SUCCESS);
295 if (Status == STATUS_SUCCESS)
296 {
297 g_VBoxUsbGlobals.pDrvObj = pDriverObject;
298
299 pDriverObject->DriverExtension->AddDevice = vboxUsbDdiAddDevice;
300
301 pDriverObject->DriverUnload = vboxUsbDdiUnload;
302
303 pDriverObject->MajorFunction[IRP_MJ_CREATE] = vboxUsbDispatchCreate;
304 pDriverObject->MajorFunction[IRP_MJ_CLOSE] = vboxUsbDispatchClose;
305 pDriverObject->MajorFunction[IRP_MJ_READ] = vboxUsbDispatchRead;
306 pDriverObject->MajorFunction[IRP_MJ_WRITE] = vboxUsbDispatchWrite;
307 pDriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = vboxUsbDispatchDeviceControl;
308 pDriverObject->MajorFunction[IRP_MJ_CLEANUP] = vboxUsbDispatchCleanup;
309 pDriverObject->MajorFunction[IRP_MJ_POWER] = vboxUsbDispatchPower;
310 pDriverObject->MajorFunction[IRP_MJ_SYSTEM_CONTROL] = vboxUsbDispatchSystemControl;
311 pDriverObject->MajorFunction[IRP_MJ_PNP] = vboxUsbDispatchPnP;
312
313 return STATUS_SUCCESS;
314 }
315 vboxUsbRtGlobalsTerm();
316 }
317
318 LogRel(("VBoxUsb::DriverEntry. failed with Status (0x%x)\n", Status));
319
320 return Status;
321}
322
323#ifdef VBOX_STRICT
324DECLHIDDEN(VOID) vboxUsbPnPStateGbgChange(ENMVBOXUSB_PNPSTATE enmOldState, ENMVBOXUSB_PNPSTATE enmNewState)
325{
326 /* *ensure the state change is valid */
327 switch (enmNewState)
328 {
329 case ENMVBOXUSB_PNPSTATE_STARTED:
330 Assert( enmOldState == ENMVBOXUSB_PNPSTATE_START_PENDING
331 || enmOldState == ENMVBOXUSB_PNPSTATE_REMOVE_PENDING
332 || enmOldState == ENMVBOXUSB_PNPSTATE_STOPPED
333 || enmOldState == ENMVBOXUSB_PNPSTATE_STOP_PENDING);
334 break;
335 case ENMVBOXUSB_PNPSTATE_STOP_PENDING:
336 Assert(enmOldState == ENMVBOXUSB_PNPSTATE_STARTED);
337 break;
338 case ENMVBOXUSB_PNPSTATE_STOPPED:
339 Assert(enmOldState == ENMVBOXUSB_PNPSTATE_STOP_PENDING);
340 break;
341 case ENMVBOXUSB_PNPSTATE_SURPRISE_REMOVED:
342 Assert(enmOldState == ENMVBOXUSB_PNPSTATE_STARTED);
343 break;
344 case ENMVBOXUSB_PNPSTATE_REMOVE_PENDING:
345 Assert(enmOldState == ENMVBOXUSB_PNPSTATE_STARTED);
346 break;
347 case ENMVBOXUSB_PNPSTATE_REMOVED:
348 Assert( enmOldState == ENMVBOXUSB_PNPSTATE_REMOVE_PENDING
349 || enmOldState == ENMVBOXUSB_PNPSTATE_SURPRISE_REMOVED);
350 break;
351 default:
352 AssertFailed();
353 break;
354 }
355
356}
357#endif
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