VirtualBox

source: vbox/trunk/src/VBox/HostDrivers/VBoxUSB/win/mon/VBoxUsbMon.cpp@ 37042

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

usb: back out r71658 as it's not correct; some additional debugging

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 40.4 KB
Line 
1/* $Id: VBoxUsbMon.cpp 37042 2011-05-11 19:04:07Z vboxsync $ */
2/** @file
3 * VBox USB Monitor
4 */
5/*
6 * Copyright (C) 2011 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
17#include "VBoxUsbMon.h"
18#include "../cmn/VBoxUsbIdc.h"
19#include <vbox/err.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
43typedef struct VBOXUSBMONINS
44{
45 void * pvDummy;
46} VBOXUSBMONINS, *PVBOXUSBMONINS;
47
48typedef struct VBOXUSBMONCTX
49{
50 VBOXUSBFLTCTX FltCtx;
51} VBOXUSBMONCTX, *PVBOXUSBMONCTX;
52
53typedef struct VBOXUSBHUB_PNPHOOK
54{
55 VBOXUSBHOOK_ENTRY Hook;
56} VBOXUSBHUB_PNPHOOK, *PVBOXUSBHUB_PNPHOOK;
57
58typedef struct VBOXUSBHUB_PNPHOOK_COMPLETION
59{
60 VBOXUSBHOOK_REQUEST Rq;
61} VBOXUSBHUB_PNPHOOK_COMPLETION, *PVBOXUSBHUB_PNPHOOK_COMPLETION;
62
63typedef struct VBOXUSBMONGLOBALS
64{
65 PDEVICE_OBJECT pDevObj;
66 VBOXUSBHUB_PNPHOOK UsbHubPnPHook;
67 KEVENT OpenSynchEvent;
68 IO_REMOVE_LOCK RmLock;
69 uint32_t cOpens;
70} VBOXUSBMONGLOBALS, *PVBOXUSBMONGLOBALS;
71
72static VBOXUSBMONGLOBALS g_VBoxUsbMonGlobals;
73
74#define VBOXUSBMON_MEMTAG 'MUBV'
75
76PVOID VBoxUsbMonMemAlloc(SIZE_T cbBytes)
77{
78 PVOID pvMem = ExAllocatePoolWithTag(NonPagedPool, cbBytes, VBOXUSBMON_MEMTAG);
79 Assert(pvMem);
80 return pvMem;
81}
82
83PVOID VBoxUsbMonMemAllocZ(SIZE_T cbBytes)
84{
85 PVOID pvMem = VBoxUsbMonMemAlloc(cbBytes);
86 if (pvMem)
87 {
88 RtlZeroMemory(pvMem, cbBytes);
89 }
90 return pvMem;
91}
92
93VOID VBoxUsbMonMemFree(PVOID pvMem)
94{
95 ExFreePoolWithTag(pvMem, VBOXUSBMON_MEMTAG);
96}
97
98#define VBOXUSBDBG_STRCASE(_t) \
99 case _t: return #_t
100#define VBOXUSBDBG_STRCASE_UNKNOWN(_v) \
101 default: Log((__FUNCTION__": Unknown Value (0n%d), (0x%x)\n", _v, _v)); return "Unknown"
102
103static const char* vboxUsbDbgStrPnPMn(UCHAR uMn)
104{
105 switch (uMn)
106 {
107 VBOXUSBDBG_STRCASE(IRP_MN_START_DEVICE);
108 VBOXUSBDBG_STRCASE(IRP_MN_QUERY_REMOVE_DEVICE);
109 VBOXUSBDBG_STRCASE(IRP_MN_REMOVE_DEVICE);
110 VBOXUSBDBG_STRCASE(IRP_MN_CANCEL_REMOVE_DEVICE);
111 VBOXUSBDBG_STRCASE(IRP_MN_STOP_DEVICE);
112 VBOXUSBDBG_STRCASE(IRP_MN_QUERY_STOP_DEVICE);
113 VBOXUSBDBG_STRCASE(IRP_MN_CANCEL_STOP_DEVICE);
114 VBOXUSBDBG_STRCASE(IRP_MN_QUERY_DEVICE_RELATIONS);
115 VBOXUSBDBG_STRCASE(IRP_MN_QUERY_INTERFACE);
116 VBOXUSBDBG_STRCASE(IRP_MN_QUERY_CAPABILITIES);
117 VBOXUSBDBG_STRCASE(IRP_MN_QUERY_RESOURCES);
118 VBOXUSBDBG_STRCASE(IRP_MN_QUERY_RESOURCE_REQUIREMENTS);
119 VBOXUSBDBG_STRCASE(IRP_MN_QUERY_DEVICE_TEXT);
120 VBOXUSBDBG_STRCASE(IRP_MN_FILTER_RESOURCE_REQUIREMENTS);
121 VBOXUSBDBG_STRCASE(IRP_MN_READ_CONFIG);
122 VBOXUSBDBG_STRCASE(IRP_MN_WRITE_CONFIG);
123 VBOXUSBDBG_STRCASE(IRP_MN_EJECT);
124 VBOXUSBDBG_STRCASE(IRP_MN_SET_LOCK);
125 VBOXUSBDBG_STRCASE(IRP_MN_QUERY_ID);
126 VBOXUSBDBG_STRCASE(IRP_MN_QUERY_PNP_DEVICE_STATE);
127 VBOXUSBDBG_STRCASE(IRP_MN_QUERY_BUS_INFORMATION);
128 VBOXUSBDBG_STRCASE(IRP_MN_DEVICE_USAGE_NOTIFICATION);
129 VBOXUSBDBG_STRCASE(IRP_MN_SURPRISE_REMOVAL);
130 VBOXUSBDBG_STRCASE_UNKNOWN(uMn);
131 }
132}
133
134void vboxUsbDbgPrintUnicodeString(PUNICODE_STRING pUnicodeString)
135{
136 PWSTR pStr = pUnicodeString->Buffer;
137 for (int i = 0; i < pUnicodeString->Length/2; ++i)
138 {
139 Log(("%c", *pStr++));
140 }
141}
142
143/**
144 * Send IRP_MN_QUERY_DEVICE_RELATIONS
145 *
146 * @returns NT Status
147 * @param pDevObj USB device pointer
148 * @param pFileObj Valid file object pointer
149 * @param pDevRelations Pointer to DEVICE_RELATIONS pointer (out)
150 */
151NTSTATUS VBoxUsbMonQueryBusRelations(PDEVICE_OBJECT pDevObj, PFILE_OBJECT pFileObj, PDEVICE_RELATIONS *pDevRelations)
152{
153 IO_STATUS_BLOCK IoStatus;
154 KEVENT Event;
155 NTSTATUS Status;
156 PIRP pIrp;
157 PIO_STACK_LOCATION pSl;
158
159 KeInitializeEvent(&Event, NotificationEvent, FALSE);
160
161 Assert(pDevRelations);
162 *pDevRelations = NULL;
163
164 pIrp = IoBuildSynchronousFsdRequest(IRP_MJ_PNP, pDevObj, NULL, 0, NULL, &Event, &IoStatus);
165 if (!pIrp)
166 {
167 AssertMsgFailed(("IoBuildDeviceIoControlRequest failed!!\n"));
168 return STATUS_INSUFFICIENT_RESOURCES;
169 }
170 IoStatus.Status = STATUS_NOT_SUPPORTED;
171
172 pSl = IoGetNextIrpStackLocation(pIrp);
173 pSl->MajorFunction = IRP_MJ_PNP;
174 pSl->MinorFunction = IRP_MN_QUERY_DEVICE_RELATIONS;
175 pSl->Parameters.QueryDeviceRelations.Type = BusRelations;
176 pSl->FileObject = pFileObj;
177
178 Status = IoCallDriver(pDevObj, pIrp);
179 if (Status == STATUS_PENDING)
180 {
181 Log(("IoCallDriver returned STATUS_PENDING!!\n"));
182 KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL);
183 Status = IoStatus.Status;
184 }
185
186 if (Status == STATUS_SUCCESS)
187 {
188 PDEVICE_RELATIONS pRel = (PDEVICE_RELATIONS)IoStatus.Information;
189 Log(("pRel = %p\n", pRel));
190 if (VALID_PTR(pRel))
191 {
192 *pDevRelations = pRel;
193 }
194 else
195 Log(("Invalid pointer %p\n", pRel));
196 }
197
198 Log(("IoCallDriver returned %x\n", Status));
199 return Status;
200}
201
202static PDRIVER_OBJECT vboxUsbMonHookFindHubDrvObj()
203{
204 NTSTATUS Status = STATUS_UNSUCCESSFUL;
205 UNICODE_STRING szStandardHubName;
206 PDRIVER_OBJECT pDrvObj = NULL;
207 szStandardHubName.Length = 0;
208 szStandardHubName.MaximumLength = 0;
209 szStandardHubName.Buffer = 0;
210 RtlInitUnicodeString(&szStandardHubName, L"\\Driver\\usbhub");
211
212 Log(("Search USB hub\n"));
213 for (int i = 0; i < 16; i++)
214 {
215 WCHAR szwHubName[32];
216 char szHubName[32];
217 ANSI_STRING AnsiName;
218 UNICODE_STRING UnicodeName;
219 PDEVICE_OBJECT pHubDevObj;
220 PFILE_OBJECT pHubFileObj;
221
222 sprintf(szHubName, "\\Device\\USBPDO-%d", i);
223
224 RtlInitAnsiString(&AnsiName, szHubName);
225
226 UnicodeName.Length = 0;
227 UnicodeName.MaximumLength = sizeof (szwHubName);
228 UnicodeName.Buffer = szwHubName;
229
230 RtlInitAnsiString(&AnsiName, szHubName);
231 Status = RtlAnsiStringToUnicodeString(&UnicodeName, &AnsiName, FALSE);
232 if (Status == STATUS_SUCCESS)
233 {
234 Status = IoGetDeviceObjectPointer(&UnicodeName, FILE_READ_DATA, &pHubFileObj, &pHubDevObj);
235 if (Status == STATUS_SUCCESS)
236 {
237 Log(("IoGetDeviceObjectPointer for %S returned %p %p\n", szwHubName, pHubDevObj, pHubFileObj));
238
239 if (pHubDevObj->DriverObject
240 && pHubDevObj->DriverObject->DriverName.Buffer
241 && pHubDevObj->DriverObject->DriverName.Length
242 && !RtlCompareUnicodeString(&szStandardHubName, &pHubDevObj->DriverObject->DriverName, TRUE /* case insensitive */))
243 {
244#if 0
245 Log(("Associated driver"));
246 Log(("%S\n", &pHubDevObj->DriverObject->DriverName.Buffer));
247#endif
248 Log(("pnp handler %p\n", pHubDevObj->DriverObject->MajorFunction[IRP_MJ_PNP]));
249
250 pDrvObj = pHubDevObj->DriverObject;
251 break;
252 }
253 ObDereferenceObject(pHubFileObj);
254 }
255 else
256 {
257 AssertFailed();
258 }
259 }
260 else
261 {
262 AssertFailed();
263 }
264 }
265
266 return pDrvObj;
267}
268
269/* NOTE: the stack location data is not the "actual" IRP stack location,
270 * but a copy being preserved on the IRP way down.
271 * See the note in VBoxUsbPnPCompletion for detail */
272static NTSTATUS vboxUsbMonHandlePnPIoctl(PDEVICE_OBJECT pDevObj, PIO_STACK_LOCATION pSl, PIO_STATUS_BLOCK pIoStatus)
273{
274 Log(("VBoxUSBMonHandlePnPIoctl IRQL = %d\n", KeGetCurrentIrql()));
275 switch(pSl->MinorFunction)
276 {
277 case IRP_MN_QUERY_DEVICE_TEXT:
278 {
279 Log(("IRP_MN_QUERY_DEVICE_TEXT: pIoStatus->Status = %x\n", pIoStatus->Status));
280 if (pIoStatus->Status == STATUS_SUCCESS)
281 {
282 WCHAR *pId = (WCHAR *)pIoStatus->Information;
283 if (VALID_PTR(pId))
284 {
285 KIRQL Iqrl = KeGetCurrentIrql();
286 /* IRQL should be always passive here */
287 Assert(Iqrl == PASSIVE_LEVEL);
288 switch(pSl->Parameters.QueryDeviceText.DeviceTextType)
289 {
290 case DeviceTextLocationInformation:
291 Log(("DeviceTextLocationInformation %ws\n", pId));
292 break;
293
294 case DeviceTextDescription:
295 Log(("DeviceTextDescription %ws\n", pId));
296 if (VBoxUsbFltPdoIsFiltered(pDevObj))
297 {
298 WCHAR *pId = (WCHAR *)ExAllocatePool(PagedPool, sizeof(szDeviceTextDescription));
299 if (!pId)
300 {
301 AssertFailed();
302 break;
303 }
304 memcpy(pId, szDeviceTextDescription, sizeof(szDeviceTextDescription));
305 Log(("NEW szDeviceTextDescription %ws\n", pId));
306 ExFreePool((PVOID)pIoStatus->Information);
307 pIoStatus->Information = (ULONG_PTR)pId;
308 }
309 break;
310 default:
311 break;
312 }
313 }
314 else
315 Log(("Invalid pointer %p\n", pId));
316 }
317 break;
318 }
319
320 case IRP_MN_QUERY_ID:
321 {
322 Log(("IRP_MN_QUERY_ID: Irp->pIoStatus->Status = %x\n", pIoStatus->Status));
323 if (pIoStatus->Status == STATUS_SUCCESS && pDevObj)
324 {
325 WCHAR *pId = (WCHAR *)pIoStatus->Information;
326#ifdef DEBUG
327 WCHAR *pTmp;
328#endif
329 if (VALID_PTR(pId))
330 {
331 KIRQL Iqrl = KeGetCurrentIrql();
332 /* IRQL should be always passive here */
333 Assert(Iqrl == PASSIVE_LEVEL);
334
335 switch (pSl->Parameters.QueryDeviceRelations.Type)
336 {
337 case BusQueryInstanceID:
338 Log(("BusQueryInstanceID %ws\n", pId));
339 break;
340
341 case BusQueryDeviceID:
342 {
343 pId = (WCHAR *)ExAllocatePool(PagedPool, sizeof(szBusQueryDeviceId));
344 if (!pId)
345 {
346 AssertFailed();
347 break;
348 }
349
350 BOOLEAN bFiltered = FALSE;
351 NTSTATUS Status = VBoxUsbFltPdoAdd(pDevObj, &bFiltered);
352 if (Status != STATUS_SUCCESS || !bFiltered)
353 {
354 Assert(Status == STATUS_SUCCESS);
355 ExFreePool(pId);
356 break;
357 }
358
359 ExFreePool((PVOID)pIoStatus->Information);
360 memcpy(pId, szBusQueryDeviceId, sizeof(szBusQueryDeviceId));
361 pIoStatus->Information = (ULONG_PTR)pId;
362 break;
363 }
364 case BusQueryHardwareIDs:
365 {
366#ifdef DEBUG
367 while(*pId) //MULTI_SZ
368 {
369 Log(("BusQueryHardwareIDs %ws\n", pId));
370 while(*pId) pId++;
371 pId++;
372 }
373#endif
374 pId = (WCHAR *)ExAllocatePool(PagedPool, sizeof(szBusQueryHardwareIDs));
375 if (!pId)
376 {
377 AssertFailed();
378 break;
379 }
380
381 BOOLEAN bFiltered = FALSE;
382 NTSTATUS Status = VBoxUsbFltPdoAdd(pDevObj, &bFiltered);
383 if (Status != STATUS_SUCCESS || !bFiltered)
384 {
385 Assert(Status == STATUS_SUCCESS);
386 ExFreePool(pId);
387 break;
388 }
389
390 memcpy(pId, szBusQueryHardwareIDs, sizeof(szBusQueryHardwareIDs));
391#ifdef DEBUG
392 pTmp = pId;
393 while(*pTmp) //MULTI_SZ
394 {
395 Log(("NEW BusQueryHardwareIDs %ws\n", pTmp));
396 while(*pTmp) pTmp++;
397 pTmp++;
398 }
399#endif
400 ExFreePool((PVOID)pIoStatus->Information);
401 pIoStatus->Information = (ULONG_PTR)pId;
402 break;
403 }
404 case BusQueryCompatibleIDs:
405#ifdef DEBUG
406 while(*pId) //MULTI_SZ
407 {
408 Log(("BusQueryCompatibleIDs %ws\n", pId));
409 while(*pId) pId++;
410 pId++;
411 }
412#endif
413 if (VBoxUsbFltPdoIsFiltered(pDevObj))
414 {
415 pId = (WCHAR *)ExAllocatePool(PagedPool, sizeof(szBusQueryCompatibleIDs));
416 if (!pId)
417 {
418 AssertFailed();
419 break;
420 }
421 memcpy(pId, szBusQueryCompatibleIDs, sizeof(szBusQueryCompatibleIDs));
422#ifdef DEBUG
423 pTmp = pId;
424 while(*pTmp) //MULTI_SZ
425 {
426 Log(("NEW BusQueryCompatibleIDs %ws\n", pTmp));
427 while(*pTmp) pTmp++;
428 pTmp++;
429 }
430#endif
431 ExFreePool((PVOID)pIoStatus->Information);
432 pIoStatus->Information = (ULONG_PTR)pId;
433 }
434 break;
435 }
436 }
437 else
438 Log(("Invalid pointer %p\n", pId));
439 }
440 break;
441 }
442
443#ifdef DEBUG
444 case IRP_MN_QUERY_DEVICE_RELATIONS:
445 {
446 switch(pSl->Parameters.QueryDeviceRelations.Type)
447 {
448 case BusRelations:
449 {
450 Log(("BusRelations\n"));
451
452 if (pIoStatus->Status == STATUS_SUCCESS)
453 {
454 PDEVICE_RELATIONS pRel = (PDEVICE_RELATIONS)pIoStatus->Information;
455 Log(("pRel = %p\n", pRel));
456 if (VALID_PTR(pRel))
457 {
458 for (unsigned i=0;i<pRel->Count;i++)
459 {
460 if (VBoxUsbFltPdoIsFiltered(pDevObj))
461 Log(("New PDO %p\n", pRel->Objects[i]));
462 }
463 }
464 else
465 Log(("Invalid pointer %p\n", pRel));
466 }
467 break;
468 }
469 case TargetDeviceRelation:
470 Log(("TargetDeviceRelation\n"));
471 break;
472 case RemovalRelations:
473 Log(("RemovalRelations\n"));
474 break;
475 case EjectionRelations:
476 Log(("EjectionRelations\n"));
477 break;
478 }
479 break;
480 }
481
482 case IRP_MN_QUERY_CAPABILITIES:
483 {
484 Log(("IRP_MN_QUERY_CAPABILITIES: pIoStatus->Status = %x\n", pIoStatus->Status));
485 if (pIoStatus->Status == STATUS_SUCCESS)
486 {
487 PDEVICE_CAPABILITIES pCaps = pSl->Parameters.DeviceCapabilities.Capabilities;
488 if (VALID_PTR(pCaps))
489 {
490 Log(("Caps.SilentInstall = %d\n", pCaps->SilentInstall));
491 Log(("Caps.UniqueID = %d\n", pCaps->UniqueID ));
492 Log(("Caps.Address = %d\n", pCaps->Address ));
493 Log(("Caps.UINumber = %d\n", pCaps->UINumber ));
494 }
495 else
496 Log(("Invalid pointer %p\n", pCaps));
497 }
498 break;
499 }
500
501 default:
502 break;
503#endif
504 } /*switch */
505
506 Log(("VBoxUSBMonHandlePnPIoctl returns %x (IRQL = %d)\n", pIoStatus->Status, KeGetCurrentIrql()));
507 return pIoStatus->Status;
508}
509
510NTSTATUS _stdcall VBoxUsbPnPCompletion(DEVICE_OBJECT *pDevObj, IRP *pIrp, void *pvContext)
511{
512 Assert(pvContext);
513
514 PVBOXUSBHOOK_REQUEST pRequest = (PVBOXUSBHOOK_REQUEST)pvContext;
515 /* NOTE: despite a regular IRP processing the stack location in our completion
516 * differs from those of the PnP hook since the hook is invoked in the "context" of the calle,
517 * while the completion is in the "coller" context in terms of IRP,
518 * so the completion stack location is one level "up" here.
519 *
520 * Moreover we CAN NOT access irp stack location in the completion because we might not have one at all
521 * in case the hooked driver is at the top of the irp call stack
522 *
523 * This is why we use the stack location we saved on IRP way down.
524 * */
525 PIO_STACK_LOCATION pSl = &pRequest->OldLocation;
526 Assert(pIrp == pRequest->pIrp);
527 /* NOTE: we can not rely on pDevObj passed in IoCompletion since it may be zero
528 * in case IRP was created with extra stack locations and the caller did not initialize
529 * the IO_STACK_LOCATION::DeviceObject */
530 DEVICE_OBJECT *pRealDevObj = pRequest->pDevObj;
531// Assert(!pDevObj || pDevObj == pRealDevObj);
532// Assert(pSl->DeviceObject == pDevObj);
533
534 switch(pSl->MinorFunction)
535 {
536 case IRP_MN_QUERY_DEVICE_TEXT:
537 case IRP_MN_QUERY_ID:
538#ifdef DEBUG
539 case IRP_MN_QUERY_DEVICE_RELATIONS:
540 case IRP_MN_QUERY_CAPABILITIES:
541#endif
542 if (NT_SUCCESS(pIrp->IoStatus.Status))
543 {
544 vboxUsbMonHandlePnPIoctl(pRealDevObj, pSl, &pIrp->IoStatus);
545 }
546 else
547 {
548 Assert(pIrp->IoStatus.Status == STATUS_NOT_SUPPORTED);
549 }
550 break;
551
552 case IRP_MN_SURPRISE_REMOVAL:
553 case IRP_MN_REMOVE_DEVICE:
554 if (NT_SUCCESS(pIrp->IoStatus.Status))
555 {
556 VBoxUsbFltPdoRemove(pRealDevObj);
557 }
558 else
559 {
560 AssertFailed();
561 }
562 break;
563
564 /* These two IRPs are received when the PnP subsystem has determined the id of the newly arrived device */
565 /* IRP_MN_START_DEVICE only arrives if it's a USB device of a known class or with a present host driver */
566 case IRP_MN_QUERY_RESOURCE_REQUIREMENTS:
567 case IRP_MN_QUERY_RESOURCES:
568 if (NT_SUCCESS(pIrp->IoStatus.Status) || pIrp->IoStatus.Status == STATUS_NOT_SUPPORTED)
569 {
570 VBoxUsbFltPdoAddCompleted(pRealDevObj);
571 }
572 else
573 {
574 AssertFailed();
575 }
576 break;
577
578 default:
579 break;
580 }
581
582 Log(("<==PnP: Mn(%s), PDO(0x%p), IRP(0x%p), Status(0x%x), Sl PDO(0x%p), Compl PDO(0x%p)\n",
583 vboxUsbDbgStrPnPMn(pSl->MinorFunction),
584 pRealDevObj, pIrp, pIrp->IoStatus.Status,
585 pSl->DeviceObject, pDevObj));
586#ifdef DEBUG_misha
587 NTSTATUS tmpStatus = pIrp->IoStatus.Status;
588#endif
589 NTSTATUS Status = VBoxUsbHookRequestComplete(&g_VBoxUsbMonGlobals.UsbHubPnPHook.Hook, pDevObj, pIrp, pRequest);
590 VBoxUsbMonMemFree(pRequest);
591#ifdef DEBUG_misha
592 if (Status != STATUS_MORE_PROCESSING_REQUIRED)
593 {
594 Assert(pIrp->IoStatus.Status == tmpStatus);
595 }
596#endif
597 VBoxUsbHookRelease(&g_VBoxUsbMonGlobals.UsbHubPnPHook.Hook);
598 return Status;
599}
600
601/**
602 * Device PnP hook
603 *
604 * @param pDevObj Device object.
605 * @param pIrp Request packet.
606 */
607NTSTATUS _stdcall VBoxUsbMonPnPHook(IN PDEVICE_OBJECT pDevObj, IN PIRP pIrp)
608{
609 if(!VBoxUsbHookRetain(&g_VBoxUsbMonGlobals.UsbHubPnPHook.Hook))
610 {
611 return VBoxUsbHookRequestPassDownHookSkip(&g_VBoxUsbMonGlobals.UsbHubPnPHook.Hook, pDevObj, pIrp);
612 }
613
614 PVBOXUSBHUB_PNPHOOK_COMPLETION pCompletion = (PVBOXUSBHUB_PNPHOOK_COMPLETION)VBoxUsbMonMemAlloc(sizeof (*pCompletion));
615 if (!pCompletion)
616 {
617 AssertFailed();
618 VBoxUsbHookRelease(&g_VBoxUsbMonGlobals.UsbHubPnPHook.Hook);
619 pIrp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES;
620 pIrp->IoStatus.Information = 0;
621 IoCompleteRequest(pIrp, IO_NO_INCREMENT);
622 return STATUS_INSUFFICIENT_RESOURCES;
623 }
624
625 Log(("==>PnP: Mn(%s), PDO(0x%p), IRP(0x%p), Status(0x%x)\n", vboxUsbDbgStrPnPMn(IoGetCurrentIrpStackLocation(pIrp)->MinorFunction), pDevObj, pIrp, pIrp->IoStatus.Status));
626
627 NTSTATUS Status = VBoxUsbHookRequestPassDownHookCompletion(&g_VBoxUsbMonGlobals.UsbHubPnPHook.Hook, pDevObj, pIrp, VBoxUsbPnPCompletion, &pCompletion->Rq);
628#ifdef DEBUG
629 if (Status != STATUS_PENDING)
630 {
631 VBoxUsbHookVerifyCompletion(&g_VBoxUsbMonGlobals.UsbHubPnPHook.Hook, &pCompletion->Rq, pIrp);
632 }
633#endif
634 return Status;
635}
636
637
638static NTSTATUS vboxUsbMonHookCheckInit()
639{
640 static bool fIsHookInited = false;
641 if (fIsHookInited)
642 return STATUS_SUCCESS;
643 PDRIVER_OBJECT pDrvObj = vboxUsbMonHookFindHubDrvObj();
644 Assert(pDrvObj);
645 if (pDrvObj)
646 {
647 VBoxUsbHookInit(&g_VBoxUsbMonGlobals.UsbHubPnPHook.Hook, pDrvObj, IRP_MJ_PNP, VBoxUsbMonPnPHook);
648 fIsHookInited = true;
649 return STATUS_SUCCESS;
650 }
651 return STATUS_UNSUCCESSFUL;
652}
653
654static NTSTATUS vboxUsbMonHookInstall()
655{
656#ifdef VBOXUSBMON_DBG_NO_PNPHOOK
657 return STATUS_SUCCESS;
658#else
659 return VBoxUsbHookInstall(&g_VBoxUsbMonGlobals.UsbHubPnPHook.Hook);
660#endif
661}
662
663static NTSTATUS vboxUsbMonHookUninstall()
664{
665#ifdef VBOXUSBMON_DBG_NO_PNPHOOK
666 return STATUS_SUCCESS;
667#else
668 return VBoxUsbHookUninstall(&g_VBoxUsbMonGlobals.UsbHubPnPHook.Hook);
669#endif
670}
671
672
673static NTSTATUS vboxUsbMonCheckTermStuff()
674{
675 NTSTATUS Status = KeWaitForSingleObject(&g_VBoxUsbMonGlobals.OpenSynchEvent,
676 Executive, KernelMode,
677 FALSE, /* BOOLEAN Alertable */
678 NULL /* IN PLARGE_INTEGER Timeout */
679 );
680 Assert(Status == STATUS_SUCCESS);
681 if (Status == STATUS_SUCCESS)
682 {
683 do
684 {
685 if (--g_VBoxUsbMonGlobals.cOpens)
686 break;
687
688 Status = vboxUsbMonHookUninstall();
689 if (NT_SUCCESS(Status))
690 {
691 Status = VBoxUsbFltTerm();
692 if (NT_SUCCESS(Status))
693 {
694 Status = STATUS_SUCCESS;
695 break;
696 }
697 else
698 {
699 AssertFailed();
700 }
701 }
702 else
703 {
704 AssertFailed();
705 }
706
707 ++g_VBoxUsbMonGlobals.cOpens;
708 Assert(g_VBoxUsbMonGlobals.cOpens == 1);
709 } while (0);
710
711 KeSetEvent(&g_VBoxUsbMonGlobals.OpenSynchEvent, 0, FALSE);
712 }
713 return Status;
714}
715
716static NTSTATUS vboxUsbMonCheckInitStuff()
717{
718 NTSTATUS Status = KeWaitForSingleObject(&g_VBoxUsbMonGlobals.OpenSynchEvent,
719 Executive, KernelMode,
720 FALSE, /* BOOLEAN Alertable */
721 NULL /* IN PLARGE_INTEGER Timeout */
722 );
723 Assert(Status == STATUS_SUCCESS);
724 if (Status == STATUS_SUCCESS)
725 {
726 do
727 {
728 if (g_VBoxUsbMonGlobals.cOpens++)
729 break;
730
731 Status = VBoxUsbFltInit();
732 if (NT_SUCCESS(Status))
733 {
734 vboxUsbMonHookCheckInit();
735 Status = vboxUsbMonHookInstall();
736 if (NT_SUCCESS(Status))
737 {
738 Status = STATUS_SUCCESS;
739 break;
740 }
741 else
742 {
743 AssertFailed();
744 }
745 VBoxUsbFltTerm();
746 }
747 else
748 {
749 AssertFailed();
750 }
751
752 --g_VBoxUsbMonGlobals.cOpens;
753 Assert(!g_VBoxUsbMonGlobals.cOpens);
754 } while (0);
755
756 KeSetEvent(&g_VBoxUsbMonGlobals.OpenSynchEvent, 0, FALSE);
757 }
758 return Status;
759}
760
761static NTSTATUS vboxUsbMonContextCreate(PVBOXUSBMONCTX *ppCtx)
762{
763 NTSTATUS Status;
764 *ppCtx = NULL;
765 PVBOXUSBMONCTX pFileCtx = (PVBOXUSBMONCTX)VBoxUsbMonMemAllocZ(sizeof (*pFileCtx));
766 if (pFileCtx)
767 {
768 Status = vboxUsbMonCheckInitStuff();
769 if (Status == STATUS_SUCCESS)
770 {
771 Status = VBoxUsbFltCreate(&pFileCtx->FltCtx);
772 if (Status == STATUS_SUCCESS)
773 {
774 *ppCtx = pFileCtx;
775 return STATUS_SUCCESS;
776 }
777 else
778 {
779 AssertFailed();
780 }
781 vboxUsbMonCheckTermStuff();
782 }
783 else
784 {
785 AssertFailed();
786 }
787 VBoxUsbMonMemFree(pFileCtx);
788 }
789 else
790 {
791 AssertFailed();
792 Status = STATUS_NO_MEMORY;
793 }
794
795 return Status;
796}
797
798static NTSTATUS vboxUsbMonContextClose(PVBOXUSBMONCTX pCtx)
799{
800 NTSTATUS Status = VBoxUsbFltClose(&pCtx->FltCtx);
801 if (Status == STATUS_SUCCESS)
802 {
803 Status = vboxUsbMonCheckTermStuff();
804 Assert(Status == STATUS_SUCCESS);
805 /* ignore the failure */
806 VBoxUsbMonMemFree(pCtx);
807 }
808
809 return Status;
810}
811
812static NTSTATUS _stdcall VBoxUsbMonClose(PDEVICE_OBJECT pDevObj, PIRP pIrp)
813{
814 PIO_STACK_LOCATION pStack = IoGetCurrentIrpStackLocation(pIrp);
815 PFILE_OBJECT pFileObj = pStack->FileObject;
816 Assert(pFileObj->FsContext);
817 PVBOXUSBMONCTX pCtx = (PVBOXUSBMONCTX)pFileObj->FsContext;
818 NTSTATUS Status = vboxUsbMonContextClose(pCtx);
819 Assert(Status == STATUS_SUCCESS);
820 pFileObj->FsContext = NULL;
821 pIrp->IoStatus.Status = Status;
822 pIrp->IoStatus.Information = 0;
823 IoCompleteRequest(pIrp, IO_NO_INCREMENT);
824 return Status;
825}
826
827
828static NTSTATUS _stdcall VBoxUsbMonCreate(PDEVICE_OBJECT pDevObj, PIRP pIrp)
829{
830 PIO_STACK_LOCATION pStack = IoGetCurrentIrpStackLocation(pIrp);
831 PFILE_OBJECT pFileObj = pStack->FileObject;
832 NTSTATUS Status;
833
834 Log(("VBoxUSBMonCreate\n"));
835
836 if (pStack->Parameters.Create.Options & FILE_DIRECTORY_FILE)
837 {
838 pIrp->IoStatus.Status = STATUS_NOT_A_DIRECTORY;
839 pIrp->IoStatus.Information = 0;
840 IoCompleteRequest(pIrp, IO_NO_INCREMENT);
841 return STATUS_NOT_A_DIRECTORY;
842 }
843
844 pFileObj->FsContext = NULL;
845 PVBOXUSBMONCTX pCtx = NULL;
846 Status = vboxUsbMonContextCreate(&pCtx);
847 if (Status == STATUS_SUCCESS)
848 {
849 Assert(pCtx);
850 pFileObj->FsContext = pCtx;
851 }
852
853 pIrp->IoStatus.Status = Status;
854 pIrp->IoStatus.Information = 0;
855 IoCompleteRequest(pIrp, IO_NO_INCREMENT);
856 return Status;
857}
858
859static int VBoxUsbMonSetNotifyEvent(PVBOXUSBMONCTX pContext, HANDLE hEvent)
860{
861 int rc = VBoxUsbFltSetNotifyEvent(&pContext->FltCtx, hEvent);
862 return rc;
863}
864
865static int VBoxUsbMonFltAdd(PVBOXUSBMONCTX pContext, PUSBFILTER pFilter, uintptr_t *pId)
866{
867#ifdef VBOXUSBMON_DBG_NO_FILTERS
868 static uintptr_t idDummy = 1;
869 *pId = idDummy;
870 ++idDummy;
871 return VINF_SUCCESS;
872#else
873 int rc = VBoxUsbFltAdd(&pContext->FltCtx, pFilter, pId);
874 return rc;
875#endif
876}
877
878static int VBoxUsbMonFltRemove(PVBOXUSBMONCTX pContext, uintptr_t uId)
879{
880#ifdef VBOXUSBMON_DBG_NO_FILTERS
881 return VINF_SUCCESS;
882#else
883 int rc = VBoxUsbFltRemove(&pContext->FltCtx, uId);
884 return rc;
885#endif
886}
887
888static NTSTATUS VBoxUsbMonRunFilters(PVBOXUSBMONCTX pContext)
889{
890 NTSTATUS Status = VBoxUsbFltFilterCheck(&pContext->FltCtx);
891 return Status;
892}
893
894static NTSTATUS VBoxUsbMonGetDevice(PVBOXUSBMONCTX pContext, HVBOXUSBDEVUSR hDevice, PUSBSUP_GETDEV_MON pInfo)
895{
896 NTSTATUS Status = VBoxUsbFltGetDevice(&pContext->FltCtx, hDevice, pInfo);
897 return Status;
898}
899
900static NTSTATUS vboxUsbMonIoctlDispatch(PVBOXUSBMONCTX pContext, ULONG Ctl, PVOID pvBuffer, ULONG cbInBuffer, ULONG cbOutBuffer, ULONG_PTR* pInfo)
901{
902 NTSTATUS Status = STATUS_SUCCESS;
903 ULONG_PTR Info = 0;
904 switch (Ctl)
905 {
906 case SUPUSBFLT_IOCTL_GET_VERSION:
907 {
908 PUSBSUP_VERSION pOut = (PUSBSUP_VERSION)pvBuffer;
909
910 Log(("SUPUSBFLT_IOCTL_GET_VERSION\n"));
911 if (!pvBuffer || cbOutBuffer != sizeof(*pOut) || cbInBuffer != 0)
912 {
913 AssertMsgFailed(("SUPUSBFLT_IOCTL_GET_VERSION: Invalid input/output sizes. cbIn=%d expected %d. cbOut=%d expected %d.\n",
914 cbInBuffer, 0, cbOutBuffer, sizeof (*pOut)));
915 Status = STATUS_INVALID_PARAMETER;
916 break;
917 }
918 pOut->u32Major = USBMON_MAJOR_VERSION;
919 pOut->u32Minor = USBMON_MINOR_VERSION;
920 Info = sizeof (*pOut);
921 break;
922 }
923
924 case SUPUSBFLT_IOCTL_ADD_FILTER:
925 {
926 PUSBFILTER pFilter = (PUSBFILTER)pvBuffer;
927 PUSBSUP_FLTADDOUT pOut = (PUSBSUP_FLTADDOUT)pvBuffer;
928 uintptr_t uId = 0;
929 int rc;
930 if (RT_UNLIKELY(!pvBuffer || cbInBuffer != sizeof (*pFilter) || cbOutBuffer != sizeof (*pOut)))
931 {
932 AssertMsgFailed(("SUPUSBFLT_IOCTL_ADD_FILTER: Invalid input/output sizes. cbIn=%d expected %d. cbOut=%d expected %d.\n",
933 cbInBuffer, sizeof (*pFilter), cbOutBuffer, sizeof (*pOut)));
934 Status = STATUS_INVALID_PARAMETER;
935 break;
936 }
937
938 rc = VBoxUsbMonFltAdd(pContext, pFilter, &uId);
939 pOut->rc = rc;
940 pOut->uId = uId;
941 Info = sizeof (*pOut);
942 break;
943 }
944
945 case SUPUSBFLT_IOCTL_REMOVE_FILTER:
946 {
947 uintptr_t *pIn = (uintptr_t *)pvBuffer;
948 int *pRc = (int *)pvBuffer;
949
950 if (!pvBuffer || cbInBuffer != sizeof (*pIn) || (cbOutBuffer && cbOutBuffer != sizeof (*pRc)))
951 {
952 AssertMsgFailed(("SUPUSBFLT_IOCTL_REMOVE_FILTER: Invalid input/output sizes. cbIn=%d expected %d. cbOut=%d expected %d.\n",
953 cbInBuffer, sizeof (*pIn), cbOutBuffer, 0));
954 Status = STATUS_INVALID_PARAMETER;
955 break;
956 }
957 Log(("SUPUSBFLT_IOCTL_REMOVE_FILTER %x\n", *pIn));
958 int rc = VBoxUsbMonFltRemove(pContext, *pIn);
959 if (cbOutBuffer)
960 {
961 /* we've validated that already */
962 Assert(cbOutBuffer == *pRc);
963 *pRc = rc;
964 Info = sizeof (*pRc);
965 }
966 break;
967 }
968
969 case SUPUSBFLT_IOCTL_RUN_FILTERS:
970 {
971 if (pvBuffer || cbInBuffer || cbOutBuffer)
972 {
973 AssertMsgFailed(("SUPUSBFLT_IOCTL_RUN_FILTERS: Invalid input/output sizes. cbIn=%d expected %d. cbOut=%d expected %d.\n",
974 cbInBuffer, 0, cbOutBuffer, 0));
975 Status = STATUS_INVALID_PARAMETER;
976 break;
977 }
978 Log(("SUPUSBFLT_IOCTL_RUN_FILTERS \n"));
979 Status = VBoxUsbMonRunFilters(pContext);
980 Assert(Status == STATUS_SUCCESS);
981 Assert(Status != STATUS_PENDING);
982 break;
983 }
984
985 case SUPUSBFLT_IOCTL_GET_DEVICE:
986 {
987 HVBOXUSBDEVUSR hDevice = *((HVBOXUSBDEVUSR*)pvBuffer);
988 PUSBSUP_GETDEV_MON pOut = (PUSBSUP_GETDEV_MON)pvBuffer;
989 if (!pvBuffer || cbInBuffer != sizeof (hDevice) || cbOutBuffer < sizeof (*pOut))
990 {
991 AssertMsgFailed(("SUPUSBFLT_IOCTL_GET_DEVICE: Invalid input/output sizes. cbIn=%d expected %d. cbOut=%d expected >= %d.\n",
992 cbInBuffer, sizeof (hDevice), cbOutBuffer, sizeof (*pOut)));
993 Status = STATUS_INVALID_PARAMETER;
994 break;
995 }
996
997 Status = VBoxUsbMonGetDevice(pContext, hDevice, pOut);
998
999 if (NT_SUCCESS(Status))
1000 {
1001 Info = sizeof (*pOut);
1002 }
1003 else
1004 {
1005 AssertFailed();
1006 }
1007 break;
1008 }
1009
1010 case SUPUSBFLT_IOCTL_SET_NOTIFY_EVENT:
1011 {
1012 PUSBSUP_SET_NOTIFY_EVENT pSne = (PUSBSUP_SET_NOTIFY_EVENT)pvBuffer;
1013 if (!pvBuffer || cbInBuffer != sizeof (*pSne) || cbOutBuffer != sizeof (*pSne))
1014 {
1015 AssertMsgFailed(("SUPUSBFLT_IOCTL_SET_NOTIFY_EVENT: Invalid input/output sizes. cbIn=%d expected %d. cbOut=%d expected %d.\n",
1016 cbInBuffer, sizeof (*pSne), cbOutBuffer, sizeof (*pSne)));
1017 Status = STATUS_INVALID_PARAMETER;
1018 break;
1019 }
1020
1021 pSne->u.rc = VBoxUsbMonSetNotifyEvent(pContext, pSne->u.hEvent);
1022 Info = sizeof (*pSne);
1023 break;
1024 }
1025
1026 default:
1027 Status = STATUS_INVALID_PARAMETER;
1028 break;
1029 }
1030
1031 Assert(Status != STATUS_PENDING);
1032
1033 *pInfo = Info;
1034 return Status;
1035}
1036
1037static NTSTATUS _stdcall VBoxUsbMonDeviceControl(PDEVICE_OBJECT pDevObj, PIRP pIrp)
1038{
1039 ULONG_PTR Info = 0;
1040 NTSTATUS Status = IoAcquireRemoveLock(&g_VBoxUsbMonGlobals.RmLock, pDevObj);
1041 if (NT_SUCCESS(Status))
1042 {
1043 PIO_STACK_LOCATION pSl = IoGetCurrentIrpStackLocation(pIrp);
1044 PFILE_OBJECT pFileObj = pSl->FileObject;
1045 Assert(pFileObj);
1046 Assert(pFileObj->FsContext);
1047 PVBOXUSBMONCTX pCtx = (PVBOXUSBMONCTX)pFileObj->FsContext;
1048 Assert(pCtx);
1049 Status = vboxUsbMonIoctlDispatch(pCtx,
1050 pSl->Parameters.DeviceIoControl.IoControlCode,
1051 pIrp->AssociatedIrp.SystemBuffer,
1052 pSl->Parameters.DeviceIoControl.InputBufferLength,
1053 pSl->Parameters.DeviceIoControl.OutputBufferLength,
1054 &Info);
1055 Assert(Status != STATUS_PENDING);
1056
1057 IoReleaseRemoveLock(&g_VBoxUsbMonGlobals.RmLock, pDevObj);
1058 }
1059
1060 pIrp->IoStatus.Information = Info;
1061 pIrp->IoStatus.Status = Status;
1062 IoCompleteRequest (pIrp, IO_NO_INCREMENT);
1063 return Status;
1064}
1065
1066static NTSTATUS vboxUsbMonInternalIoctlDispatch(ULONG Ctl, PVOID pvBuffer, ULONG_PTR *pInfo)
1067{
1068 NTSTATUS Status = STATUS_SUCCESS;
1069 *pInfo = 0;
1070 switch (Ctl)
1071 {
1072 case VBOXUSBIDC_INTERNAL_IOCTL_GET_VERSION:
1073 {
1074 PVBOXUSBIDC_VERSION pOut = (PVBOXUSBIDC_VERSION)pvBuffer;
1075
1076 Log(("VBOXUSBIDC_INTERNAL_IOCTL_GET_VERSION\n"));
1077 if (!pvBuffer)
1078 {
1079 AssertMsgFailed(("VBOXUSBIDC_INTERNAL_IOCTL_GET_VERSION: Buffer is NULL\n"));
1080 Status = STATUS_INVALID_PARAMETER;
1081 break;
1082 }
1083 pOut->u32Major = VBOXUSBIDC_VERSION_MAJOR;
1084 pOut->u32Minor = VBOXUSBIDC_VERSION_MINOR;
1085 break;
1086 }
1087
1088 case VBOXUSBIDC_INTERNAL_IOCTL_PROXY_STARTUP:
1089 {
1090 PVBOXUSBIDC_PROXY_STARTUP pOut = (PVBOXUSBIDC_PROXY_STARTUP)pvBuffer;
1091
1092 Log(("VBOXUSBIDC_INTERNAL_IOCTL_PROXY_STARTUP\n"));
1093 if (!pvBuffer)
1094 {
1095 AssertMsgFailed(("VBOXUSBIDC_INTERNAL_IOCTL_GET_VERSION: Buffer is NULL\n"));
1096 Status = STATUS_INVALID_PARAMETER;
1097 break;
1098 }
1099
1100 pOut->u.hDev = VBoxUsbFltProxyStarted(pOut->u.pPDO);
1101 break;
1102 }
1103
1104 case VBOXUSBIDC_INTERNAL_IOCTL_PROXY_TEARDOWN:
1105 {
1106 PVBOXUSBIDC_PROXY_TEARDOWN pOut = (PVBOXUSBIDC_PROXY_TEARDOWN)pvBuffer;
1107
1108 Log(("VBOXUSBIDC_INTERNAL_IOCTL_PROXY_TEARDOWN\n"));
1109 if (!pvBuffer)
1110 {
1111 AssertMsgFailed(("VBOXUSBIDC_INTERNAL_IOCTL_PROXY_TEARDOWN: Buffer is NULL\n"));
1112 Status = STATUS_INVALID_PARAMETER;
1113 break;
1114 }
1115
1116 VBoxUsbFltProxyStopped(pOut->hDev);
1117 break;
1118 }
1119
1120 default:
1121 {
1122 AssertFailed();
1123 Status = STATUS_INVALID_PARAMETER;
1124 break;
1125 }
1126 }
1127
1128 return Status;
1129}
1130
1131static NTSTATUS _stdcall VBoxUsbMonInternalDeviceControl(PDEVICE_OBJECT pDevObj, PIRP pIrp)
1132{
1133 ULONG_PTR Info = 0;
1134 NTSTATUS Status = IoAcquireRemoveLock(&g_VBoxUsbMonGlobals.RmLock, pDevObj);
1135 if (NT_SUCCESS(Status))
1136 {
1137 PIO_STACK_LOCATION pSl = IoGetCurrentIrpStackLocation(pIrp);
1138 Status = vboxUsbMonInternalIoctlDispatch(pSl->Parameters.DeviceIoControl.IoControlCode,
1139 pSl->Parameters.Others.Argument1,
1140 &Info);
1141 Assert(Status != STATUS_PENDING);
1142
1143 IoReleaseRemoveLock(&g_VBoxUsbMonGlobals.RmLock, pDevObj);
1144 }
1145
1146 pIrp->IoStatus.Information = Info;
1147 pIrp->IoStatus.Status = Status;
1148 IoCompleteRequest (pIrp, IO_NO_INCREMENT);
1149 return Status;
1150}
1151
1152/**
1153 * Unload the driver.
1154 *
1155 * @param pDrvObj Driver object.
1156 */
1157static void _stdcall VBoxUsbMonUnload(PDRIVER_OBJECT pDrvObj)
1158{
1159 Log(("VBoxUSBMonUnload pDrvObj (0x%p)\n", pDrvObj));
1160
1161 IoReleaseRemoveLockAndWait(&g_VBoxUsbMonGlobals.RmLock, &g_VBoxUsbMonGlobals);
1162
1163 Assert(!g_VBoxUsbMonGlobals.cOpens);
1164
1165 UNICODE_STRING DosName;
1166 RtlInitUnicodeString(&DosName, USBMON_DEVICE_NAME_DOS);
1167 NTSTATUS rc = IoDeleteSymbolicLink(&DosName);
1168
1169 IoDeleteDevice(g_VBoxUsbMonGlobals.pDevObj);
1170
1171 /* cleanup the logger */
1172 PRTLOGGER pLogger = RTLogRelSetDefaultInstance(NULL);
1173 if (pLogger)
1174 {
1175 RTLogDestroy(pLogger);
1176 }
1177 pLogger = RTLogSetDefaultInstance(NULL);
1178 if (pLogger)
1179 {
1180 RTLogDestroy(pLogger);
1181 }
1182}
1183
1184RT_C_DECLS_BEGIN
1185NTSTATUS _stdcall DriverEntry(PDRIVER_OBJECT pDrvObj, PUNICODE_STRING pRegPath);
1186RT_C_DECLS_END
1187
1188/**
1189 * Driver entry point.
1190 *
1191 * @returns appropriate status code.
1192 * @param pDrvObj Pointer to driver object.
1193 * @param pRegPath Registry base path.
1194 */
1195NTSTATUS _stdcall DriverEntry(PDRIVER_OBJECT pDrvObj, PUNICODE_STRING pRegPath)
1196{
1197#ifdef DEBUG_misha
1198 RTLogGroupSettings(0, "+default.e.l.f.l2.l3");;
1199#endif
1200
1201 Log(("VBoxUSBMon::DriverEntry\n"));
1202
1203 memset (&g_VBoxUsbMonGlobals, 0, sizeof (g_VBoxUsbMonGlobals));
1204 KeInitializeEvent(&g_VBoxUsbMonGlobals.OpenSynchEvent, SynchronizationEvent, TRUE /* signaled */);
1205 IoInitializeRemoveLock(&g_VBoxUsbMonGlobals.RmLock, VBOXUSBMON_MEMTAG, 1, 100);
1206 UNICODE_STRING DevName;
1207 PDEVICE_OBJECT pDevObj;
1208 /* create the device */
1209 RtlInitUnicodeString(&DevName, USBMON_DEVICE_NAME_NT);
1210 NTSTATUS Status = IoAcquireRemoveLock(&g_VBoxUsbMonGlobals.RmLock, &g_VBoxUsbMonGlobals);
1211 if (NT_SUCCESS(Status))
1212 {
1213 Status = IoCreateDevice(pDrvObj, sizeof (VBOXUSBMONINS), &DevName, FILE_DEVICE_UNKNOWN, 0, FALSE, &pDevObj);
1214 if (NT_SUCCESS(Status))
1215 {
1216 UNICODE_STRING DosName;
1217 RtlInitUnicodeString(&DosName, USBMON_DEVICE_NAME_DOS);
1218 Status = IoCreateSymbolicLink(&DosName, &DevName);
1219 if (NT_SUCCESS(Status))
1220 {
1221 PVBOXUSBMONINS pDevExt = (PVBOXUSBMONINS)pDevObj->DeviceExtension;
1222 memset(pDevExt, 0, sizeof(*pDevExt));
1223
1224 pDrvObj->DriverUnload = VBoxUsbMonUnload;
1225 pDrvObj->MajorFunction[IRP_MJ_CREATE] = VBoxUsbMonCreate;
1226 pDrvObj->MajorFunction[IRP_MJ_CLOSE] = VBoxUsbMonClose;
1227 pDrvObj->MajorFunction[IRP_MJ_DEVICE_CONTROL] = VBoxUsbMonDeviceControl;
1228 pDrvObj->MajorFunction[IRP_MJ_INTERNAL_DEVICE_CONTROL] = VBoxUsbMonInternalDeviceControl;
1229
1230 g_VBoxUsbMonGlobals.pDevObj = pDevObj;
1231 Log(("VBoxUSBMon::DriverEntry returning STATUS_SUCCESS\n"));
1232 return STATUS_SUCCESS;
1233 }
1234 IoDeleteDevice(pDevObj);
1235 }
1236 IoReleaseRemoveLockAndWait(&g_VBoxUsbMonGlobals.RmLock, &g_VBoxUsbMonGlobals);
1237 }
1238
1239 return Status;
1240}
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