VirtualBox

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

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

usb: prevent the monitor from being unload, when unhook fails

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

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette