VirtualBox

source: vbox/trunk/src/VBox/HostDrivers/VBoxUSB/win/Monitor/USBMon.cpp@ 31907

Last change on this file since 31907 was 31898, checked in by vboxsync, 14 years ago

OSE header fixes

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 34.6 KB
Line 
1/** @file
2 *
3 * VBox USB drivers - USB Monitor driver - Win32 host:
4 */
5
6/*
7 * Copyright (C) 2006-2007 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#include "USBMon.h"
20#include <VBox/usblib.h>
21#include <excpt.h>
22#include <stdio.h>
23
24/*
25 * Note: Must match the VID & PID in the USB driver .inf file!!
26 */
27/*
28 BusQueryDeviceID USB\Vid_80EE&Pid_CAFE
29 BusQueryInstanceID 2
30 BusQueryHardwareIDs USB\Vid_80EE&Pid_CAFE&Rev_0100
31 BusQueryHardwareIDs USB\Vid_80EE&Pid_CAFE
32 BusQueryCompatibleIDs USB\Class_ff&SubClass_00&Prot_00
33 BusQueryCompatibleIDs USB\Class_ff&SubClass_00
34 BusQueryCompatibleIDs USB\Class_ff
35*/
36
37#define szBusQueryDeviceId L"USB\\Vid_80EE&Pid_CAFE"
38#define szBusQueryHardwareIDs L"USB\\Vid_80EE&Pid_CAFE&Rev_0100\0USB\\Vid_80EE&Pid_CAFE\0\0"
39#define szBusQueryCompatibleIDs L"USB\\Class_ff&SubClass_00&Prot_00\0USB\\Class_ff&SubClass_00\0USB\\Class_ff\0\0"
40
41#define szDeviceTextDescription L"VirtualBox USB"
42
43static PDEVICE_OBJECT ControlDeviceObject = NULL;
44static PDRIVER_DISPATCH pfnOldPnPHandler = 0;
45
46static struct
47{
48 bool fValid;
49} InstalledPDOHooks[16] = {0};
50
51/**
52 * Driver entry point.
53 *
54 * @returns appropriate status code.
55 * @param pDrvObj Pointer to driver object.
56 * @param pRegPath Registry base path.
57 */
58NTSTATUS _stdcall DriverEntry(PDRIVER_OBJECT pDrvObj, PUNICODE_STRING pRegPath)
59{
60 NTSTATUS rc;
61 UNICODE_STRING DevName;
62 PDEVICE_OBJECT pDevObj;
63
64 DebugPrint(("VBoxUSBMon::DriverEntry\n"));
65
66 /*
67 * Create device.
68 * (That means creating a device object and a symbolic link so the DOS
69 * subsystems (OS/2, win32, ++) can access the device.)
70 */
71 RtlInitUnicodeString(&DevName, USBMON_DEVICE_NAME_NT);
72 rc = IoCreateDevice(pDrvObj, sizeof(DEVICE_EXTENSION), &DevName, FILE_DEVICE_UNKNOWN, 0, FALSE, &pDevObj);
73 if (NT_SUCCESS(rc))
74 {
75 UNICODE_STRING DosName;
76
77 /* Save device object pointer in order to check whether we're being called in the entry points we register. */
78 ControlDeviceObject = pDevObj;
79
80 RtlInitUnicodeString(&DosName, USBMON_DEVICE_NAME_DOS);
81 rc = IoCreateSymbolicLink(&DosName, &DevName);
82 if (NT_SUCCESS(rc))
83 {
84 ULONG ulIndex;
85 PDRIVER_DISPATCH *dispatch;
86
87 /*
88 * Initialize the device extension.
89 */
90 PDEVICE_EXTENSION pDevExt = (PDEVICE_EXTENSION)pDevObj->DeviceExtension;
91 memset(pDevExt, 0, sizeof(*pDevExt));
92
93 /*
94 * Setup the driver entry points in pDrvObj.
95 */
96 for (ulIndex = 0, dispatch = pDrvObj->MajorFunction;
97 ulIndex <= IRP_MJ_MAXIMUM_FUNCTION;
98 ulIndex++, dispatch++) {
99
100 *dispatch = VBoxUSBMonStub;
101 }
102
103 pDrvObj->DriverUnload = VBoxUSBMonUnload;
104 pDrvObj->MajorFunction[IRP_MJ_CREATE] = VBoxUSBMonCreate;
105 pDrvObj->MajorFunction[IRP_MJ_CLOSE] = VBoxUSBMonClose;
106 pDrvObj->MajorFunction[IRP_MJ_DEVICE_CONTROL] = VBoxUSBMonDeviceControl;
107
108// pDrvObj->MajorFunction[IRP_MJ_PNP] = VBoxUSBMonDispatchPnp;
109// pDrvObj->MajorFunction[IRP_MJ_POWER] = VBoxUSBMonDispatchPower;
110 /* Note: unable to unload driver if this is set: */
111//// pDrvObj->DriverExtension->AddDevice = VBoxUSBMonAddDevice;
112
113 VBoxUSBInit();
114 DebugPrint(("VBoxUSBMon::DriverEntry returning STATUS_SUCCESS\n"));
115 return STATUS_SUCCESS;
116 }
117 else
118 DebugPrint(("IoCreateSymbolicLink failed with rc=%#x!\n", rc));
119
120 IoDeleteDevice(pDevObj);
121 }
122 else
123 DebugPrint(("IoCreateDevice failed with rc=%#x!\n", rc));
124
125 if (NT_SUCCESS(rc))
126 rc = STATUS_INVALID_PARAMETER;
127 DebugPrint(("VBoxUSBMon::DriverEntry returning %#x\n", rc));
128 return rc;
129}
130
131/**
132 * Uninstall the PnP irp hook
133 *
134 * @param pDevExt Device extension
135 */
136void VBoxUSBUninstallPnPHook(PDEVICE_EXTENSION pDevExt)
137{
138 NTSTATUS status;
139 UNICODE_STRING szStandardHubName;
140
141 szStandardHubName.Length = 0;
142 szStandardHubName.MaximumLength = 0;
143 szStandardHubName.Buffer = 0;
144 RtlInitUnicodeString(&szStandardHubName, L"\\Driver\\usbhub");
145
146 DebugPrint(("Unhook USB hub drivers\n"));
147 for (int i = 0; i < RT_ELEMENTS(InstalledPDOHooks); i++)
148 {
149 char szHubName[32];
150 UNICODE_STRING UnicodeName;
151 ANSI_STRING AnsiName;
152 PDEVICE_OBJECT pHubDevObj;
153 PFILE_OBJECT pHubFileObj;
154
155 /* Don't bother to check PDO's that we haven't hooked; might even lead to host crashes during shutdown as IoGetDeviceObjectPointer can reopen a driver. */
156 if (!InstalledPDOHooks[i].fValid)
157 continue;
158
159 sprintf(szHubName, "\\Device\\USBPDO-%d", i);
160
161 UnicodeName.Length = 0;
162 UnicodeName.MaximumLength = 0;
163 UnicodeName.Buffer = 0;
164
165 RtlInitAnsiString(&AnsiName, szHubName);
166 RtlAnsiStringToUnicodeString(&UnicodeName, &AnsiName, TRUE);
167
168 status = IoGetDeviceObjectPointer(&UnicodeName, FILE_READ_DATA, &pHubFileObj, &pHubDevObj);
169 if (status == STATUS_SUCCESS)
170 {
171 DebugPrint(("IoGetDeviceObjectPointer for %s returned %p %p\n", szHubName, pHubDevObj, pHubFileObj));
172
173 if ( pHubDevObj->DriverObject
174 && pHubDevObj->DriverObject->DriverName.Buffer
175 && pHubDevObj->DriverObject->DriverName.Length
176 && !RtlCompareUnicodeString(&szStandardHubName, &pHubDevObj->DriverObject->DriverName, TRUE /* case insensitive */))
177 {
178#if 0
179 DebugPrint(("Associated driver"));
180 DebugPrintUnicodeString(&pHubDevObj->DriverObject->DriverName);
181#endif
182 DebugPrint(("pnp handler %p\n", pHubDevObj->DriverObject->MajorFunction[IRP_MJ_PNP]));
183 InterlockedCompareExchangePointer((PVOID *)&pHubDevObj->DriverObject->MajorFunction[IRP_MJ_PNP], pfnOldPnPHandler, VBoxUSBMonPnPHook);
184 }
185 ObDereferenceObject(pHubFileObj);
186 }
187// else
188// DebugPrint(("IoGetDeviceObjectPointer for %s returned %x\n", szHubName, status));
189
190 RtlFreeUnicodeString(&UnicodeName);
191 }
192 pDevExt->fHookDevice = FALSE;
193 pfnOldPnPHandler = NULL;
194}
195
196/**
197 * Unload the driver.
198 *
199 * @param pDrvObj Driver object.
200 */
201void _stdcall VBoxUSBMonUnload(PDRIVER_OBJECT pDrvObj)
202{
203 PDEVICE_EXTENSION pDevExt = (PDEVICE_EXTENSION)pDrvObj->DeviceObject->DeviceExtension;
204
205 DebugPrint(("VBoxUSBMonUnload pDevExt=%p ControlDeviceObject=%p\n", pDevExt, ControlDeviceObject));
206
207 Assert(!pfnOldPnPHandler);
208 if (pfnOldPnPHandler) /* very bad! */
209 VBoxUSBUninstallPnPHook(pDevExt);
210
211 /* Clean up the filter manager */
212 VBoxUSBTerm();
213
214 /*
215 * We ASSUME that it's not possible to unload a driver with open handles.
216 * Start by deleting the symbolic link
217 */
218 UNICODE_STRING DosName;
219 RtlInitUnicodeString(&DosName, USBMON_DEVICE_NAME_DOS);
220 NTSTATUS rc = IoDeleteSymbolicLink(&DosName);
221
222 IoDeleteDevice(pDrvObj->DeviceObject);
223}
224
225
226/**
227 * Create (i.e. Open) file entry point.
228 *
229 * @param pDevObj Device object.
230 * @param pIrp Request packet.
231 */
232NTSTATUS _stdcall VBoxUSBMonCreate(PDEVICE_OBJECT pDevObj, PIRP pIrp)
233{
234 PIO_STACK_LOCATION pStack = IoGetCurrentIrpStackLocation(pIrp);
235 PDEVICE_EXTENSION pDevExt = (PDEVICE_EXTENSION)pDevObj->DeviceExtension;
236 NTSTATUS status;
237
238 DebugPrint(("VBoxUSBMonCreate\n"));
239
240 /*
241 * We are not remotely similar to a directory...
242 * (But this is possible.)
243 */
244 if (pStack->Parameters.Create.Options & FILE_DIRECTORY_FILE)
245 {
246 pIrp->IoStatus.Status = STATUS_NOT_A_DIRECTORY;
247 pIrp->IoStatus.Information = 0;
248 IoCompleteRequest(pIrp, IO_NO_INCREMENT);
249 return STATUS_NOT_A_DIRECTORY;
250 }
251
252 VBoxUSBCreate();
253
254 if (InterlockedIncrement(&pDevExt->cOpened) == 1)
255 {
256 UNICODE_STRING szStandardHubName;
257
258 pDevExt->fHookDevice = TRUE;
259
260 szStandardHubName.Length = 0;
261 szStandardHubName.MaximumLength = 0;
262 szStandardHubName.Buffer = 0;
263 RtlInitUnicodeString(&szStandardHubName, L"\\Driver\\usbhub");
264
265 DebugPrint(("Hook USB hub drivers\n"));
266 for (int i = 0; i < RT_ELEMENTS(InstalledPDOHooks); i++)
267 {
268 char szHubName[32];
269 UNICODE_STRING UnicodeName;
270 ANSI_STRING AnsiName;
271 PDEVICE_OBJECT pHubDevObj;
272 PFILE_OBJECT pHubFileObj;
273
274 sprintf(szHubName, "\\Device\\USBPDO-%d", i);
275
276 InstalledPDOHooks[i].fValid = false;
277
278 UnicodeName.Length = 0;
279 UnicodeName.MaximumLength = 0;
280 UnicodeName.Buffer = 0;
281
282 RtlInitAnsiString(&AnsiName, szHubName);
283 RtlAnsiStringToUnicodeString(&UnicodeName, &AnsiName, TRUE);
284
285 status = IoGetDeviceObjectPointer(&UnicodeName, FILE_READ_DATA, &pHubFileObj, &pHubDevObj);
286 if (status == STATUS_SUCCESS)
287 {
288 DebugPrint(("IoGetDeviceObjectPointer for %s returned %p %p\n", szHubName, pHubDevObj, pHubFileObj));
289
290 if ( pHubDevObj->DriverObject
291 && pHubDevObj->DriverObject->DriverName.Buffer
292 && pHubDevObj->DriverObject->DriverName.Length
293 && !RtlCompareUnicodeString(&szStandardHubName, &pHubDevObj->DriverObject->DriverName, TRUE /* case insensitive */))
294 {
295#if 0
296 DebugPrint(("Associated driver"));
297 DebugPrintUnicodeString(&pHubDevObj->DriverObject->DriverName);
298#endif
299 DebugPrint(("pnp handler %p\n", pHubDevObj->DriverObject->MajorFunction[IRP_MJ_PNP]));
300 if ( !pfnOldPnPHandler
301 || pHubDevObj->DriverObject->MajorFunction[IRP_MJ_PNP] == pfnOldPnPHandler)
302 {
303 InstalledPDOHooks[i].fValid = true;
304 pfnOldPnPHandler = (PDRIVER_DISPATCH)InterlockedExchangePointer((PVOID *)&pHubDevObj->DriverObject->MajorFunction[IRP_MJ_PNP], VBoxUSBMonPnPHook);
305 }
306 }
307 ObDereferenceObject(pHubFileObj);
308 }
309// else
310// DebugPrint(("IoGetDeviceObjectPointer for %s returned %x\n", szHubName, status));
311
312 RtlFreeUnicodeString(&UnicodeName);
313 }
314
315 //
316 // Let us use remove lock to keep count of IRPs so that we don't
317 // detach and delete our deviceobject until all pending I/Os in our
318 // devstack are completed. Remlock is required to protect us from
319 // various race conditions where our driver can get unloaded while we
320 // are still running dispatch or completion code.
321 //
322
323 IoInitializeRemoveLock (&pDevExt->RemoveLock , POOL_TAG,
324 1, // MaxLockedMinutes
325 100); // HighWatermark, this parameter is
326 // used only on checked build. Specifies
327 // the maximum number of outstanding
328 // acquisitions allowed on the lock
329
330 DebugPrint(("VBoxUSBMon: remove lock = %x\n", pDevExt->RemoveLock.Common.RemoveEvent));
331 }
332
333 status = IoAcquireRemoveLock(&pDevExt->RemoveLock, ControlDeviceObject);
334 if (!NT_SUCCESS(status))
335 {
336 DebugPrint(("IoAcquireRemoveLock failed with %x\n", status));
337 pIrp->IoStatus.Status = status;
338 IoCompleteRequest(pIrp, IO_NO_INCREMENT);
339 return status;
340 }
341
342 pIrp->IoStatus.Information = 0;
343 IoCompleteRequest(pIrp, IO_NO_INCREMENT);
344
345 return STATUS_SUCCESS;
346}
347
348
349/**
350 * Close file entry point.
351 *
352 * @param pDevObj Device object.
353 * @param pIrp Request packet.
354 */
355NTSTATUS _stdcall VBoxUSBMonClose(PDEVICE_OBJECT pDevObj, PIRP pIrp)
356{
357 PDEVICE_EXTENSION pDevExt = (PDEVICE_EXTENSION)pDevObj->DeviceExtension;
358 PIO_STACK_LOCATION pStack = IoGetCurrentIrpStackLocation(pIrp);
359 PFILE_OBJECT pFileObj = pStack->FileObject;
360
361 DebugPrint(("VBoxUSBMonClose: pDevExt=%p pFileObj=%p pSession=%p\n", pDevExt, pFileObj, pFileObj->FsContext));
362
363 /* Uninstall hook when we close the last instance. */
364 if (InterlockedDecrement(&pDevExt->cOpened) == 0)
365 VBoxUSBUninstallPnPHook(pDevExt);
366
367 VBoxUSBClose();
368
369 /* Wait for all outstanding requests to complete */
370 /* We're supposed to use it in the remove device function. During unload
371 * is no option as that crashes Vista64
372 */
373 DebugPrint(("Waiting for outstanding requests\n"));
374 IoReleaseRemoveLockAndWait(&pDevExt->RemoveLock, ControlDeviceObject);
375
376 DebugPrint(("Done waiting.\n"));
377 pFileObj->FsContext = NULL;
378 pIrp->IoStatus.Information = 0;
379 pIrp->IoStatus.Status = STATUS_SUCCESS;
380 IoCompleteRequest(pIrp, IO_NO_INCREMENT);
381
382 return STATUS_SUCCESS;
383}
384
385
386/**
387 * Device I/O Control entry point.
388 *
389 * @param pDevObj Device object.
390 * @param pIrp Request packet.
391 */
392NTSTATUS _stdcall VBoxUSBMonDeviceControl(PDEVICE_OBJECT pDevObj, PIRP pIrp)
393{
394 PDEVICE_EXTENSION pDevExt = (PDEVICE_EXTENSION)pDevObj->DeviceExtension;
395 PIO_STACK_LOCATION pStack = IoGetCurrentIrpStackLocation(pIrp);
396 NTSTATUS status = STATUS_SUCCESS;
397
398 status = IoAcquireRemoveLock(&pDevExt->RemoveLock, ControlDeviceObject);
399 if (!NT_SUCCESS(status))
400 {
401 DebugPrint(("IoAcquireRemoveLock failed with %x\n", status));
402 pIrp->IoStatus.Status = status;
403 IoCompleteRequest(pIrp, IO_NO_INCREMENT);
404 return status;
405 }
406
407 /* Handle ioctl meant for us */
408 pIrp->IoStatus.Information = 0;
409 status = VBoxUSBDispatchIO(pDevObj, pIrp);
410 pIrp->IoStatus.Status = status;
411 IoCompleteRequest (pIrp, IO_NO_INCREMENT);
412
413 /* Release the remove lock */
414 IoReleaseRemoveLock(&pDevExt->RemoveLock, ControlDeviceObject);
415 return status;
416}
417
418/**
419 * Pass on or refuse entry point
420 *
421 * @param pDevObj Device object.
422 * @param pIrp Request packet.
423 */
424NTSTATUS _stdcall VBoxUSBMonStub(IN PDEVICE_OBJECT DeviceObject, IN PIRP pIrp)
425{
426#ifdef DEBUG
427 PIO_STACK_LOCATION irpStack;
428
429 irpStack = IoGetCurrentIrpStackLocation(pIrp);
430 DebugPrint (("VBoxUSBMonStub %x\n", irpStack->MinorFunction));
431#endif
432
433 /* Meant for us; report error */
434 pIrp->IoStatus.Information = 0;
435 pIrp->IoStatus.Status = STATUS_NOT_SUPPORTED;
436 IoCompleteRequest(pIrp, IO_NO_INCREMENT);
437
438 return STATUS_NOT_SUPPORTED;
439}
440
441
442/**
443 * Handle the specific PnP ioctls we need for stealing devices.
444 *
445 * @param irpStack Device object
446 * @param pIoStatus IO status of finished IRP
447 */
448NTSTATUS _stdcall VBoxUSBMonHandlePnPIoctl(PIO_STACK_LOCATION irpStack, PIO_STATUS_BLOCK pIoStatus)
449{
450 DebugPrint(("VBoxUSBMonHandlePnPIoctl IRQL = %d\n", KeGetCurrentIrql()));
451 switch(irpStack->MinorFunction)
452 {
453 case IRP_MN_QUERY_DEVICE_TEXT:
454 {
455 DebugPrint(("IRP_MN_QUERY_DEVICE_TEXT: pIoStatus->Status = %x\n", pIoStatus->Status));
456 if (pIoStatus->Status == STATUS_SUCCESS)
457 {
458 WCHAR *pId = (WCHAR *)pIoStatus->Information;
459 if (VALID_PTR(pId))
460 {
461 switch(irpStack->Parameters.QueryDeviceText.DeviceTextType)
462 {
463 case DeviceTextLocationInformation:
464 DebugPrint(("DeviceTextLocationInformation %ws\n", pId));
465 break;
466
467 case DeviceTextDescription:
468 DebugPrint(("DeviceTextDescription %ws\n", pId));
469 if (VBoxUSBDeviceIsCaptured(irpStack->DeviceObject))
470 {
471 WCHAR *pId = (WCHAR *)ExAllocatePool(PagedPool, sizeof(szDeviceTextDescription));
472 if (!pId)
473 {
474 AssertFailed();
475 break;
476 }
477 memcpy(pId, szDeviceTextDescription, sizeof(szDeviceTextDescription));
478 DebugPrint(("NEW szDeviceTextDescription %ws\n", pId));
479 ExFreePool((PVOID)pIoStatus->Information);
480 pIoStatus->Information = (ULONG_PTR)pId;
481 }
482 break;
483 }
484 }
485 else
486 DebugPrint(("Invalid pointer %p\n", pId));
487 }
488 break;
489 }
490
491 case IRP_MN_QUERY_ID:
492 {
493 DebugPrint(("IRP_MN_QUERY_ID: Irp->pIoStatus->Status = %x\n", pIoStatus->Status));
494 if ( pIoStatus->Status == STATUS_SUCCESS
495 && irpStack->DeviceObject)
496 {
497 WCHAR *pId = (WCHAR *)pIoStatus->Information;
498#ifdef DEBUG
499 WCHAR *pTmp;
500#endif
501 if (VALID_PTR(pId))
502 {
503 switch(irpStack->Parameters.QueryDeviceRelations.Type)
504 {
505 case BusQueryInstanceID:
506 DebugPrint(("BusQueryInstanceID %ws\n", pId));
507 break;
508
509 case BusQueryDeviceID:
510 VBoxUSBAddDevice(irpStack->DeviceObject);
511 if (VBoxMatchFilter(irpStack->DeviceObject) == true)
512 {
513 pId = (WCHAR *)ExAllocatePool(PagedPool, sizeof(szBusQueryDeviceId));
514 if (!pId)
515 {
516 AssertFailed();
517 break;
518 }
519 memcpy(pId, szBusQueryDeviceId, sizeof(szBusQueryDeviceId));
520 DebugPrint(("NEW BusQueryDeviceID %ws\n", pId));
521 ExFreePool((PVOID)pIoStatus->Information);
522 pIoStatus->Information = (ULONG_PTR)pId;
523 VBoxUSBCaptureDevice(irpStack->DeviceObject);
524 }
525 break;
526
527 case BusQueryHardwareIDs:
528#ifdef DEBUG
529 while(*pId) //MULTI_SZ
530 {
531 DebugPrint(("BusQueryHardwareIDs %ws\n", pId));
532 while(*pId) pId++;
533 pId++;
534 }
535#endif
536 VBoxUSBAddDevice(irpStack->DeviceObject);
537 if (VBoxMatchFilter(irpStack->DeviceObject) == true)
538 {
539 pId = (WCHAR *)ExAllocatePool(PagedPool, sizeof(szBusQueryHardwareIDs));
540 if (!pId)
541 {
542 AssertFailed();
543 break;
544 }
545 memcpy(pId, szBusQueryHardwareIDs, sizeof(szBusQueryHardwareIDs));
546#ifdef DEBUG
547 pTmp = pId;
548 while(*pTmp) //MULTI_SZ
549 {
550 DebugPrint(("NEW BusQueryHardwareIDs %ws\n", pTmp));
551 while(*pTmp) pTmp++;
552 pTmp++;
553 }
554#endif
555 ExFreePool((PVOID)pIoStatus->Information);
556 pIoStatus->Information = (ULONG_PTR)pId;
557 VBoxUSBCaptureDevice(irpStack->DeviceObject);
558 }
559 break;
560
561 case BusQueryCompatibleIDs:
562#ifdef DEBUG
563 while(*pId) //MULTI_SZ
564 {
565 DebugPrint(("BusQueryCompatibleIDs %ws\n", pId));
566 while(*pId) pId++;
567 pId++;
568 }
569#endif
570 if (VBoxUSBDeviceIsCaptured(irpStack->DeviceObject))
571 {
572 pId = (WCHAR *)ExAllocatePool(PagedPool, sizeof(szBusQueryCompatibleIDs));
573 if (!pId)
574 {
575 AssertFailed();
576 break;
577 }
578 memcpy(pId, szBusQueryCompatibleIDs, sizeof(szBusQueryCompatibleIDs));
579#ifdef DEBUG
580 pTmp = pId;
581 while(*pTmp) //MULTI_SZ
582 {
583 DebugPrint(("NEW BusQueryCompatibleIDs %ws\n", pTmp));
584 while(*pTmp) pTmp++;
585 pTmp++;
586 }
587#endif
588 ExFreePool((PVOID)pIoStatus->Information);
589 pIoStatus->Information = (ULONG_PTR)pId;
590 }
591 break;
592 }
593 }
594 else
595 DebugPrint(("Invalid pointer %p\n", pId));
596 }
597 break;
598 }
599
600#ifdef DEBUG
601 case IRP_MN_QUERY_DEVICE_RELATIONS:
602 {
603 switch(irpStack->Parameters.QueryDeviceRelations.Type)
604 {
605 case BusRelations:
606 {
607 DebugPrint(("BusRelations\n"));
608
609 if (pIoStatus->Status == STATUS_SUCCESS)
610 {
611 PDEVICE_RELATIONS pRel = (PDEVICE_RELATIONS)pIoStatus->Information;
612 DebugPrint(("pRel = %p\n", pRel));
613 if (VALID_PTR(pRel))
614 {
615 for (unsigned i=0;i<pRel->Count;i++)
616 {
617 if (VBoxUSBDeviceIsCaptured(irpStack->DeviceObject))
618 DebugPrint(("New PDO %p\n", pRel->Objects[i]));
619 }
620 }
621 else
622 DebugPrint(("Invalid pointer %p\n", pRel));
623 }
624 break;
625 }
626 case TargetDeviceRelation:
627 DebugPrint(("TargetDeviceRelation\n"));
628 break;
629 case RemovalRelations:
630 DebugPrint(("RemovalRelations\n"));
631 break;
632 case EjectionRelations:
633 DebugPrint(("EjectionRelations\n"));
634 break;
635 }
636 break;
637 }
638
639 case IRP_MN_QUERY_CAPABILITIES:
640 {
641 DebugPrint(("IRP_MN_QUERY_CAPABILITIES: pIoStatus->Status = %x\n", pIoStatus->Status));
642 if (pIoStatus->Status == STATUS_SUCCESS)
643 {
644 PDEVICE_CAPABILITIES pCaps = irpStack->Parameters.DeviceCapabilities.Capabilities;
645 if (VALID_PTR(pCaps))
646 {
647 DebugPrint(("Caps.SilentInstall = %d\n", pCaps->SilentInstall));
648 DebugPrint(("Caps.UniqueID = %d\n", pCaps->UniqueID ));
649 DebugPrint(("Caps.Address = %d\n", pCaps->Address ));
650 DebugPrint(("Caps.UINumber = %d\n", pCaps->UINumber ));
651 }
652 else
653 DebugPrint(("Invalid pointer %p\n", pCaps));
654 }
655 break;
656 }
657#endif
658 } /*switch */
659 DebugPrint(("VBoxUSBMonHandlePnPIoctl returns %x (IRQL = %d)\n", pIoStatus->Status, KeGetCurrentIrql()));
660 return pIoStatus->Status;
661}
662
663/**
664 * IRP completion notification callback. Used for selected PNP irps.
665 *
666 * @param pDevObj Device object.(always NULL!)
667 * @param pIrp Request packet.
668 * @param context User parameter (old IRP)
669 */
670NTSTATUS _stdcall VBoxUSBPnPCompletion(DEVICE_OBJECT *pDevObj, IRP *pIrp, void *context)
671{
672 /* Note: pDevObj is NULL! */
673 PIRP pOrgIrp = (PIRP)context;
674 PIO_STACK_LOCATION irpStack = IoGetCurrentIrpStackLocation(pOrgIrp);
675 PDEVICE_EXTENSION pDevExt = (PDEVICE_EXTENSION)ControlDeviceObject->DeviceExtension;
676
677 DebugPrint(("VBoxUSBPnPCompletion %p %p %p minor=%x\n", pDevObj, pIrp, context, irpStack->MinorFunction));
678
679#ifdef USBMON_ASYNC
680 VBoxUSBMonHandlePnPIoctl(irpStack, &pIrp->IoStatus);
681
682 /* Copy back the result to the original IRP. */
683 pOrgIrp->IoStatus.Information = pIrp->IoStatus.Information;
684 pOrgIrp->IoStatus.Status = pIrp->IoStatus.Status;
685
686 /* Unlock & free mdls of our duplicate IRP. */
687 while (pIrp->MdlAddress != NULL)
688 {
689 PMDL nextMdl;
690 nextMdl = pIrp->MdlAddress->Next;
691 DebugPrint(("Unlock & free MDL %p\n", pIrp->MdlAddress));
692 MmUnlockPages(pIrp->MdlAddress);
693 IoFreeMdl(pIrp->MdlAddress);
694 pIrp->MdlAddress = nextMdl;
695 }
696 /* Free our duplicate IRP */
697 IoFreeIrp(pIrp);
698
699 /* Release the remove lock */
700 IoReleaseRemoveLock(&pDevExt->RemoveLock, ControlDeviceObject);
701
702 /* Complete the original request */
703 IoCompleteRequest(pOrgIrp, IO_NO_INCREMENT);
704
705 return STATUS_MORE_PROCESSING_REQUIRED; /* must return this as we allocated the IRP with IoBuildAsynchronousFsdRequest! */
706#else
707 return STATUS_CONTINUE_COMPLETION;
708#endif
709}
710
711/**
712 * Device PnP hook
713 *
714 * @param pDevObj Device object.
715 * @param pIrp Request packet.
716 */
717NTSTATUS _stdcall VBoxUSBMonPnPHook(IN PDEVICE_OBJECT pDevObj, IN PIRP pIrp)
718{
719 PIO_STACK_LOCATION irpStack = IoGetCurrentIrpStackLocation(pIrp);
720 PDEVICE_EXTENSION pDevExt = (PDEVICE_EXTENSION)ControlDeviceObject->DeviceExtension;
721 NTSTATUS status;
722
723 DebugPrint(("VBoxUSBMonPnPHook pDevObj=%p %s IRP:%p \n", pDevObj, PnPMinorFunctionString(irpStack->MinorFunction), pIrp));
724
725 status = IoAcquireRemoveLock(&pDevExt->RemoveLock, ControlDeviceObject);
726 if (!NT_SUCCESS(status))
727 {
728 DebugPrint(("IoAcquireRemoveLock failed with %x\n", status));
729 pIrp->IoStatus.Status = status;
730 IoCompleteRequest(pIrp, IO_NO_INCREMENT);
731 return status;
732 }
733
734 if (pDevExt->fHookDevice == TRUE)
735 {
736 switch(irpStack->MinorFunction)
737 {
738 case IRP_MN_QUERY_DEVICE_TEXT:
739 case IRP_MN_QUERY_ID:
740#ifdef DEBUG
741 /* hooking this IRP causes problems for some reason */
742 //case IRP_MN_QUERY_DEVICE_RELATIONS:
743 case IRP_MN_QUERY_CAPABILITIES:
744#endif
745 {
746#ifdef USBMON_ASYNC
747 PIRP pNewIrp;
748 PIO_STACK_LOCATION newIrpStack;
749
750 /* The driver verifier claims all PNP irps must have Status preset to STATUS_NOT_SUPPORTED */
751 IoStatus.Status = STATUS_NOT_SUPPORTED;
752
753 pNewIrp = IoBuildAsynchronousFsdRequest(IRP_MJ_PNP, pDevObj, NULL, 0, NULL, NULL);
754 Assert(pNewIrp);
755 if (!pNewIrp)
756 break;
757
758 /* Get the next stack location as that is used for the new irp */
759 newIrpStack = IoGetNextIrpStackLocation(pNewIrp);
760 Assert(newIrpStack);
761 if (newIrpStack)
762 {
763 /* Make a copy of the original IRP */
764 newIrpStack->MajorFunction = irpStack->MajorFunction;
765 newIrpStack->MinorFunction = irpStack->MinorFunction;
766 newIrpStack->Parameters = irpStack->Parameters;
767 newIrpStack->FileObject = irpStack->FileObject;
768
769 IoSetCompletionRoutine(pNewIrp, VBoxUSBPnPCompletion, pIrp, TRUE, TRUE, TRUE);
770
771 /* Mark the original Irp as pending; will be completed above */
772 IoMarkIrpPending(pIrp);
773
774 pDevExt->fHookDevice = FALSE;
775 status = IoCallDriver(pDevObj, pNewIrp);
776 pDevExt->fHookDevice = TRUE;
777 return STATUS_PENDING; /* always return this! */
778 }
779 else
780 {
781 IoFreeIrp(pNewIrp);
782 break;
783 }
784#else
785 PIRP pNewIrp;
786 PIO_STACK_LOCATION newIrpStack;
787 KEVENT event;
788 IO_STATUS_BLOCK IoStatus;
789
790 KeInitializeEvent(&event, NotificationEvent, FALSE);
791
792 /* The driver verifier claims all PNP irps must have Status preset to STATUS_NOT_SUPPORTED */
793 IoStatus.Status = STATUS_NOT_SUPPORTED;
794
795 pNewIrp = IoBuildSynchronousFsdRequest(IRP_MJ_PNP, pDevObj, NULL, 0, NULL, &event, &IoStatus);
796 Assert(pNewIrp);
797 if (!pNewIrp)
798 break;
799
800 /* Get the next stack location as that is used for the new irp */
801 newIrpStack = IoGetNextIrpStackLocation(pNewIrp);
802 Assert(newIrpStack);
803 if (newIrpStack)
804 {
805 /* Make a copy of the original IRP */
806 newIrpStack->MajorFunction = irpStack->MajorFunction;
807 newIrpStack->MinorFunction = irpStack->MinorFunction;
808 newIrpStack->Parameters = irpStack->Parameters;
809 newIrpStack->FileObject = irpStack->FileObject;
810
811 IoSetCompletionRoutine(pNewIrp, VBoxUSBPnPCompletion, pIrp, TRUE, TRUE, TRUE);
812
813 pDevExt->fHookDevice = FALSE;
814 status = IoCallDriver(pDevObj, pNewIrp);
815 pDevExt->fHookDevice = TRUE;
816
817 if (status == STATUS_PENDING)
818 {
819 KeWaitForSingleObject(&event, Executive, KernelMode, FALSE, NULL);
820 status = IoStatus.Status;
821 }
822
823 if (status == STATUS_SUCCESS)
824 {
825 VBoxUSBMonHandlePnPIoctl(irpStack, &IoStatus);
826 }
827 /* Copy back the result to the original IRP. */
828 pIrp->IoStatus.Information = IoStatus.Information;
829 pIrp->IoStatus.Status = IoStatus.Status;
830
831 /* Complete the original request */
832 IoCompleteRequest(pIrp, IO_NO_INCREMENT);
833
834 /* Release the remove lock */
835 IoReleaseRemoveLock(&pDevExt->RemoveLock, ControlDeviceObject);
836
837 return status;
838 }
839 else
840 {
841 IoFreeIrp(pNewIrp);
842 break;
843 }
844#endif
845 }
846
847 case IRP_MN_SURPRISE_REMOVAL:
848 case IRP_MN_REMOVE_DEVICE:
849 VBoxUSBRemoveDevice(irpStack->DeviceObject);
850 break;
851
852 /* These two IRPs are received when the PnP subsystem has determined the id of the newly arrived device */
853 /* IRP_MN_START_DEVICE only arrives if it's a USB device of a known class or with a present host driver */
854 case IRP_MN_QUERY_RESOURCE_REQUIREMENTS:
855 case IRP_MN_QUERY_RESOURCES:
856 VBoxUSBDeviceArrived(irpStack->DeviceObject);
857 break;
858
859 default:
860 break;
861 }
862 }
863 status = pfnOldPnPHandler(pDevObj, pIrp);
864 IoReleaseRemoveLock(&pDevExt->RemoveLock, ControlDeviceObject);
865 return status;
866}
867
868
869/**
870 * Send IRP_MN_QUERY_DEVICE_RELATIONS
871 *
872 * @returns NT Status
873 * @param pDevObj USB device pointer
874 * @param pFileObj Valid file object pointer
875 * @param pDevRelations Pointer to DEVICE_RELATIONS pointer (out)
876 */
877NTSTATUS VBoxUSBQueryBusRelations(PDEVICE_OBJECT pDevObj, PFILE_OBJECT pFileObj, PDEVICE_RELATIONS *pDevRelations)
878{
879 PDEVICE_EXTENSION pDevExt = (PDEVICE_EXTENSION)ControlDeviceObject->DeviceExtension;
880 IO_STATUS_BLOCK IoStatus;
881 KEVENT event;
882 NTSTATUS status;
883 IRP *pIrp;
884 PIO_STACK_LOCATION irpStack;
885
886 KeInitializeEvent(&event, NotificationEvent, FALSE);
887
888 Assert(pDevRelations);
889 *pDevRelations = NULL;
890
891 pIrp = IoBuildSynchronousFsdRequest(IRP_MJ_PNP, pDevObj, NULL, 0, NULL, &event, &IoStatus);
892 if (!pIrp)
893 {
894 AssertMsgFailed(("IoBuildDeviceIoControlRequest failed!!\n"));
895 return STATUS_INSUFFICIENT_RESOURCES;
896 }
897 IoStatus.Status = STATUS_NOT_SUPPORTED;
898
899 /* Get the next stack location as that is used for the new irp */
900 irpStack = IoGetNextIrpStackLocation(pIrp);
901 irpStack->MajorFunction = IRP_MJ_PNP;
902 irpStack->MinorFunction = IRP_MN_QUERY_DEVICE_RELATIONS;
903 irpStack->Parameters.QueryDeviceRelations.Type = BusRelations;
904 irpStack->FileObject = pFileObj;
905
906 pDevExt->fHookDevice = FALSE;
907 status = IoCallDriver(pDevObj, pIrp);
908 pDevExt->fHookDevice = TRUE;
909 if (status == STATUS_PENDING)
910 {
911 DebugPrint(("IoCallDriver returned STATUS_PENDING!!\n"));
912 KeWaitForSingleObject(&event, Executive, KernelMode, FALSE, NULL);
913 status = IoStatus.Status;
914 }
915
916 if (status == STATUS_SUCCESS)
917 {
918 PDEVICE_RELATIONS pRel = (PDEVICE_RELATIONS)IoStatus.Information;
919 DebugPrint(("pRel = %p\n", pRel));
920 if (VALID_PTR(pRel))
921 {
922 *pDevRelations = pRel;
923 }
924 else
925 DebugPrint(("Invalid pointer %p\n", pRel));
926 }
927
928 DebugPrint(("IoCallDriver returned %x\n", status));
929 return status;
930}
931
932#ifdef DEBUG
933
934PCHAR PnPMinorFunctionString(UCHAR MinorFunction)
935{
936 switch (MinorFunction)
937 {
938 case IRP_MN_START_DEVICE:
939 return "IRP_MN_START_DEVICE";
940 case IRP_MN_QUERY_REMOVE_DEVICE:
941 return "IRP_MN_QUERY_REMOVE_DEVICE";
942 case IRP_MN_REMOVE_DEVICE:
943 return "IRP_MN_REMOVE_DEVICE";
944 case IRP_MN_CANCEL_REMOVE_DEVICE:
945 return "IRP_MN_CANCEL_REMOVE_DEVICE";
946 case IRP_MN_STOP_DEVICE:
947 return "IRP_MN_STOP_DEVICE";
948 case IRP_MN_QUERY_STOP_DEVICE:
949 return "IRP_MN_QUERY_STOP_DEVICE";
950 case IRP_MN_CANCEL_STOP_DEVICE:
951 return "IRP_MN_CANCEL_STOP_DEVICE";
952 case IRP_MN_QUERY_DEVICE_RELATIONS:
953 return "IRP_MN_QUERY_DEVICE_RELATIONS";
954 case IRP_MN_QUERY_INTERFACE:
955 return "IRP_MN_QUERY_INTERFACE";
956 case IRP_MN_QUERY_CAPABILITIES:
957 return "IRP_MN_QUERY_CAPABILITIES";
958 case IRP_MN_QUERY_RESOURCES:
959 return "IRP_MN_QUERY_RESOURCES";
960 case IRP_MN_QUERY_RESOURCE_REQUIREMENTS:
961 return "IRP_MN_QUERY_RESOURCE_REQUIREMENTS";
962 case IRP_MN_QUERY_DEVICE_TEXT:
963 return "IRP_MN_QUERY_DEVICE_TEXT";
964 case IRP_MN_FILTER_RESOURCE_REQUIREMENTS:
965 return "IRP_MN_FILTER_RESOURCE_REQUIREMENTS";
966 case IRP_MN_READ_CONFIG:
967 return "IRP_MN_READ_CONFIG";
968 case IRP_MN_WRITE_CONFIG:
969 return "IRP_MN_WRITE_CONFIG";
970 case IRP_MN_EJECT:
971 return "IRP_MN_EJECT";
972 case IRP_MN_SET_LOCK:
973 return "IRP_MN_SET_LOCK";
974 case IRP_MN_QUERY_ID:
975 return "IRP_MN_QUERY_ID";
976 case IRP_MN_QUERY_PNP_DEVICE_STATE:
977 return "IRP_MN_QUERY_PNP_DEVICE_STATE";
978 case IRP_MN_QUERY_BUS_INFORMATION:
979 return "IRP_MN_QUERY_BUS_INFORMATION";
980 case IRP_MN_DEVICE_USAGE_NOTIFICATION:
981 return "IRP_MN_DEVICE_USAGE_NOTIFICATION";
982 case IRP_MN_SURPRISE_REMOVAL:
983 return "IRP_MN_SURPRISE_REMOVAL";
984
985 default:
986 return "unknown_pnp_irp";
987 }
988}
989
990void DebugPrintUnicodeString(PUNICODE_STRING pString)
991{
992 int i;
993
994 for (i=0;i<pString->Length/2;i++)
995 {
996 DebugPrint(("%c", pString->Buffer[i]));
997 }
998}
999
1000#endif
1001
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