VirtualBox

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

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

usb: device capture filter & enum fixes

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 39.9 KB
Line 
1/* $Id: VBoxUsbMon.cpp 36998 2011-05-07 20:19:55Z 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 return VBoxUsbHookRequestPassDownHookCompletion(&g_VBoxUsbMonGlobals.UsbHubPnPHook.Hook, pDevObj, pIrp, VBoxUsbPnPCompletion, &pCompletion->Rq);
628}
629
630
631static NTSTATUS vboxUsbMonHookCheckInit()
632{
633 static bool fIsHookInited = false;
634 if (fIsHookInited)
635 return STATUS_SUCCESS;
636 PDRIVER_OBJECT pDrvObj = vboxUsbMonHookFindHubDrvObj();
637 Assert(pDrvObj);
638 if (pDrvObj)
639 {
640 VBoxUsbHookInit(&g_VBoxUsbMonGlobals.UsbHubPnPHook.Hook, pDrvObj, IRP_MJ_PNP, VBoxUsbMonPnPHook);
641 fIsHookInited = true;
642 return STATUS_SUCCESS;
643 }
644 return STATUS_UNSUCCESSFUL;
645}
646
647static NTSTATUS vboxUsbMonHookInstall()
648{
649 return VBoxUsbHookInstall(&g_VBoxUsbMonGlobals.UsbHubPnPHook.Hook);
650}
651
652static NTSTATUS vboxUsbMonHookUninstall()
653{
654 return VBoxUsbHookUninstall(&g_VBoxUsbMonGlobals.UsbHubPnPHook.Hook);
655}
656
657
658static NTSTATUS vboxUsbMonCheckTermStuff()
659{
660 NTSTATUS Status = KeWaitForSingleObject(&g_VBoxUsbMonGlobals.OpenSynchEvent,
661 Executive, KernelMode,
662 FALSE, /* BOOLEAN Alertable */
663 NULL /* IN PLARGE_INTEGER Timeout */
664 );
665 Assert(Status == STATUS_SUCCESS);
666 if (Status == STATUS_SUCCESS)
667 {
668 do
669 {
670 if (--g_VBoxUsbMonGlobals.cOpens)
671 break;
672
673 Status = vboxUsbMonHookUninstall();
674 if (NT_SUCCESS(Status))
675 {
676 Status = VBoxUsbFltTerm();
677 if (NT_SUCCESS(Status))
678 {
679 Status = STATUS_SUCCESS;
680 break;
681 }
682 else
683 {
684 AssertFailed();
685 }
686 }
687 else
688 {
689 AssertFailed();
690 }
691
692 ++g_VBoxUsbMonGlobals.cOpens;
693 Assert(g_VBoxUsbMonGlobals.cOpens == 1);
694 } while (0);
695
696 KeSetEvent(&g_VBoxUsbMonGlobals.OpenSynchEvent, 0, FALSE);
697 }
698 return Status;
699}
700
701static NTSTATUS vboxUsbMonCheckInitStuff()
702{
703 NTSTATUS Status = KeWaitForSingleObject(&g_VBoxUsbMonGlobals.OpenSynchEvent,
704 Executive, KernelMode,
705 FALSE, /* BOOLEAN Alertable */
706 NULL /* IN PLARGE_INTEGER Timeout */
707 );
708 Assert(Status == STATUS_SUCCESS);
709 if (Status == STATUS_SUCCESS)
710 {
711 do
712 {
713 if (g_VBoxUsbMonGlobals.cOpens++)
714 break;
715
716 Status = VBoxUsbFltInit();
717 if (NT_SUCCESS(Status))
718 {
719 vboxUsbMonHookCheckInit();
720 Status = vboxUsbMonHookInstall();
721 if (NT_SUCCESS(Status))
722 {
723 Status = STATUS_SUCCESS;
724 break;
725 }
726 else
727 {
728 AssertFailed();
729 }
730 VBoxUsbFltTerm();
731 }
732 else
733 {
734 AssertFailed();
735 }
736
737 --g_VBoxUsbMonGlobals.cOpens;
738 Assert(!g_VBoxUsbMonGlobals.cOpens);
739 } while (0);
740
741 KeSetEvent(&g_VBoxUsbMonGlobals.OpenSynchEvent, 0, FALSE);
742 }
743 return Status;
744}
745
746static NTSTATUS vboxUsbMonContextCreate(PVBOXUSBMONCTX *ppCtx)
747{
748 NTSTATUS Status;
749 *ppCtx = NULL;
750 PVBOXUSBMONCTX pFileCtx = (PVBOXUSBMONCTX)VBoxUsbMonMemAllocZ(sizeof (*pFileCtx));
751 if (pFileCtx)
752 {
753 Status = vboxUsbMonCheckInitStuff();
754 if (Status == STATUS_SUCCESS)
755 {
756 Status = VBoxUsbFltCreate(&pFileCtx->FltCtx);
757 if (Status == STATUS_SUCCESS)
758 {
759 *ppCtx = pFileCtx;
760 return STATUS_SUCCESS;
761 }
762 else
763 {
764 AssertFailed();
765 }
766 vboxUsbMonCheckTermStuff();
767 }
768 else
769 {
770 AssertFailed();
771 }
772 VBoxUsbMonMemFree(pFileCtx);
773 }
774 else
775 {
776 AssertFailed();
777 Status = STATUS_NO_MEMORY;
778 }
779
780 return Status;
781}
782
783static NTSTATUS vboxUsbMonContextClose(PVBOXUSBMONCTX pCtx)
784{
785 NTSTATUS Status = VBoxUsbFltClose(&pCtx->FltCtx);
786 if (Status == STATUS_SUCCESS)
787 {
788 Status = vboxUsbMonCheckTermStuff();
789 Assert(Status == STATUS_SUCCESS);
790 /* ignore the failure */
791 VBoxUsbMonMemFree(pCtx);
792 }
793
794 return Status;
795}
796
797static NTSTATUS _stdcall VBoxUsbMonClose(PDEVICE_OBJECT pDevObj, PIRP pIrp)
798{
799 PIO_STACK_LOCATION pStack = IoGetCurrentIrpStackLocation(pIrp);
800 PFILE_OBJECT pFileObj = pStack->FileObject;
801 Assert(pFileObj->FsContext);
802 PVBOXUSBMONCTX pCtx = (PVBOXUSBMONCTX)pFileObj->FsContext;
803 NTSTATUS Status = vboxUsbMonContextClose(pCtx);
804 Assert(Status == STATUS_SUCCESS);
805 pFileObj->FsContext = NULL;
806 pIrp->IoStatus.Status = Status;
807 pIrp->IoStatus.Information = 0;
808 IoCompleteRequest(pIrp, IO_NO_INCREMENT);
809 return Status;
810}
811
812
813static NTSTATUS _stdcall VBoxUsbMonCreate(PDEVICE_OBJECT pDevObj, PIRP pIrp)
814{
815 PIO_STACK_LOCATION pStack = IoGetCurrentIrpStackLocation(pIrp);
816 PFILE_OBJECT pFileObj = pStack->FileObject;
817 NTSTATUS Status;
818
819 Log(("VBoxUSBMonCreate\n"));
820
821 if (pStack->Parameters.Create.Options & FILE_DIRECTORY_FILE)
822 {
823 pIrp->IoStatus.Status = STATUS_NOT_A_DIRECTORY;
824 pIrp->IoStatus.Information = 0;
825 IoCompleteRequest(pIrp, IO_NO_INCREMENT);
826 return STATUS_NOT_A_DIRECTORY;
827 }
828
829 pFileObj->FsContext = NULL;
830 PVBOXUSBMONCTX pCtx = NULL;
831 Status = vboxUsbMonContextCreate(&pCtx);
832 if (Status == STATUS_SUCCESS)
833 {
834 Assert(pCtx);
835 pFileObj->FsContext = pCtx;
836 }
837
838 pIrp->IoStatus.Status = Status;
839 pIrp->IoStatus.Information = 0;
840 IoCompleteRequest(pIrp, IO_NO_INCREMENT);
841 return Status;
842}
843
844static int VBoxUsbMonSetNotifyEvent(PVBOXUSBMONCTX pContext, HANDLE hEvent)
845{
846 int rc = VBoxUsbFltSetNotifyEvent(&pContext->FltCtx, hEvent);
847 return rc;
848}
849
850static int VBoxUsbMonFltAdd(PVBOXUSBMONCTX pContext, PUSBFILTER pFilter, uintptr_t *pId)
851{
852 int rc = VBoxUsbFltAdd(&pContext->FltCtx, pFilter, pId);
853 return rc;
854}
855
856static int VBoxUsbMonFltRemove(PVBOXUSBMONCTX pContext, uintptr_t uId)
857{
858 int rc = VBoxUsbFltRemove(&pContext->FltCtx, uId);
859 return rc;
860}
861
862static NTSTATUS VBoxUsbMonRunFilters(PVBOXUSBMONCTX pContext)
863{
864 NTSTATUS Status = VBoxUsbFltFilterCheck(&pContext->FltCtx);
865 return Status;
866}
867
868static NTSTATUS VBoxUsbMonGetDevice(PVBOXUSBMONCTX pContext, HVBOXUSBDEVUSR hDevice, PUSBSUP_GETDEV_MON pInfo)
869{
870 NTSTATUS Status = VBoxUsbFltGetDevice(&pContext->FltCtx, hDevice, pInfo);
871 return Status;
872}
873
874static NTSTATUS vboxUsbMonIoctlDispatch(PVBOXUSBMONCTX pContext, ULONG Ctl, PVOID pvBuffer, ULONG cbInBuffer, ULONG cbOutBuffer, ULONG_PTR* pInfo)
875{
876 NTSTATUS Status = STATUS_SUCCESS;
877 ULONG_PTR Info = 0;
878 switch (Ctl)
879 {
880 case SUPUSBFLT_IOCTL_GET_VERSION:
881 {
882 PUSBSUP_VERSION pOut = (PUSBSUP_VERSION)pvBuffer;
883
884 Log(("SUPUSBFLT_IOCTL_GET_VERSION\n"));
885 if (!pvBuffer || cbOutBuffer != sizeof(*pOut) || cbInBuffer != 0)
886 {
887 AssertMsgFailed(("SUPUSBFLT_IOCTL_GET_VERSION: Invalid input/output sizes. cbIn=%d expected %d. cbOut=%d expected %d.\n",
888 cbInBuffer, 0, cbOutBuffer, sizeof (*pOut)));
889 Status = STATUS_INVALID_PARAMETER;
890 break;
891 }
892 pOut->u32Major = USBMON_MAJOR_VERSION;
893 pOut->u32Minor = USBMON_MINOR_VERSION;
894 Info = sizeof (*pOut);
895 break;
896 }
897
898 case SUPUSBFLT_IOCTL_ADD_FILTER:
899 {
900 PUSBFILTER pFilter = (PUSBFILTER)pvBuffer;
901 PUSBSUP_FLTADDOUT pOut = (PUSBSUP_FLTADDOUT)pvBuffer;
902 uintptr_t uId = 0;
903 int rc;
904 if (RT_UNLIKELY(!pvBuffer || cbInBuffer != sizeof (*pFilter) || cbOutBuffer != sizeof (*pOut)))
905 {
906 AssertMsgFailed(("SUPUSBFLT_IOCTL_ADD_FILTER: Invalid input/output sizes. cbIn=%d expected %d. cbOut=%d expected %d.\n",
907 cbInBuffer, sizeof (*pFilter), cbOutBuffer, sizeof (*pOut)));
908 Status = STATUS_INVALID_PARAMETER;
909 break;
910 }
911
912 rc = VBoxUsbMonFltAdd(pContext, pFilter, &uId);
913 pOut->rc = rc;
914 pOut->uId = uId;
915 Info = sizeof (*pOut);
916 break;
917 }
918
919 case SUPUSBFLT_IOCTL_REMOVE_FILTER:
920 {
921 uintptr_t *pIn = (uintptr_t *)pvBuffer;
922 int *pRc = (int *)pvBuffer;
923
924 if (!pvBuffer || cbInBuffer != sizeof (*pIn) || (cbOutBuffer && cbOutBuffer != sizeof (*pRc)))
925 {
926 AssertMsgFailed(("SUPUSBFLT_IOCTL_REMOVE_FILTER: Invalid input/output sizes. cbIn=%d expected %d. cbOut=%d expected %d.\n",
927 cbInBuffer, sizeof (*pIn), cbOutBuffer, 0));
928 Status = STATUS_INVALID_PARAMETER;
929 break;
930 }
931 Log(("SUPUSBFLT_IOCTL_REMOVE_FILTER %x\n", *pIn));
932 int rc = VBoxUsbMonFltRemove(pContext, *pIn);
933 if (cbOutBuffer)
934 {
935 /* we've validated that already */
936 Assert(cbOutBuffer == *pRc);
937 *pRc = rc;
938 Info = sizeof (*pRc);
939 }
940 break;
941 }
942
943 case SUPUSBFLT_IOCTL_RUN_FILTERS:
944 {
945 if (pvBuffer || cbInBuffer || cbOutBuffer)
946 {
947 AssertMsgFailed(("SUPUSBFLT_IOCTL_RUN_FILTERS: Invalid input/output sizes. cbIn=%d expected %d. cbOut=%d expected %d.\n",
948 cbInBuffer, 0, cbOutBuffer, 0));
949 Status = STATUS_INVALID_PARAMETER;
950 break;
951 }
952 Log(("SUPUSBFLT_IOCTL_RUN_FILTERS \n"));
953 Status = VBoxUsbMonRunFilters(pContext);
954 Assert(Status == STATUS_SUCCESS);
955 Assert(Status != STATUS_PENDING);
956 break;
957 }
958
959 case SUPUSBFLT_IOCTL_GET_DEVICE:
960 {
961 HVBOXUSBDEVUSR hDevice = *((HVBOXUSBDEVUSR*)pvBuffer);
962 PUSBSUP_GETDEV_MON pOut = (PUSBSUP_GETDEV_MON)pvBuffer;
963 if (!pvBuffer || cbInBuffer != sizeof (hDevice) || cbOutBuffer < sizeof (*pOut))
964 {
965 AssertMsgFailed(("SUPUSBFLT_IOCTL_GET_DEVICE: Invalid input/output sizes. cbIn=%d expected %d. cbOut=%d expected >= %d.\n",
966 cbInBuffer, sizeof (hDevice), cbOutBuffer, sizeof (*pOut)));
967 Status = STATUS_INVALID_PARAMETER;
968 break;
969 }
970
971 Status = VBoxUsbMonGetDevice(pContext, hDevice, pOut);
972
973 if (NT_SUCCESS(Status))
974 {
975 Info = sizeof (*pOut);
976 }
977 else
978 {
979 AssertFailed();
980 }
981 break;
982 }
983
984 case SUPUSBFLT_IOCTL_SET_NOTIFY_EVENT:
985 {
986 PUSBSUP_SET_NOTIFY_EVENT pSne = (PUSBSUP_SET_NOTIFY_EVENT)pvBuffer;
987 if (!pvBuffer || cbInBuffer != sizeof (*pSne) || cbOutBuffer != sizeof (*pSne))
988 {
989 AssertMsgFailed(("SUPUSBFLT_IOCTL_SET_NOTIFY_EVENT: Invalid input/output sizes. cbIn=%d expected %d. cbOut=%d expected %d.\n",
990 cbInBuffer, sizeof (*pSne), cbOutBuffer, sizeof (*pSne)));
991 Status = STATUS_INVALID_PARAMETER;
992 break;
993 }
994
995 pSne->u.rc = VBoxUsbMonSetNotifyEvent(pContext, pSne->u.hEvent);
996 Info = sizeof (*pSne);
997 break;
998 }
999
1000 default:
1001 Status = STATUS_INVALID_PARAMETER;
1002 break;
1003 }
1004
1005 Assert(Status != STATUS_PENDING);
1006
1007 *pInfo = Info;
1008 return Status;
1009}
1010
1011static NTSTATUS _stdcall VBoxUsbMonDeviceControl(PDEVICE_OBJECT pDevObj, PIRP pIrp)
1012{
1013 ULONG_PTR Info = 0;
1014 NTSTATUS Status = IoAcquireRemoveLock(&g_VBoxUsbMonGlobals.RmLock, pDevObj);
1015 if (NT_SUCCESS(Status))
1016 {
1017 PIO_STACK_LOCATION pSl = IoGetCurrentIrpStackLocation(pIrp);
1018 PFILE_OBJECT pFileObj = pSl->FileObject;
1019 Assert(pFileObj);
1020 Assert(pFileObj->FsContext);
1021 PVBOXUSBMONCTX pCtx = (PVBOXUSBMONCTX)pFileObj->FsContext;
1022 Assert(pCtx);
1023 Status = vboxUsbMonIoctlDispatch(pCtx,
1024 pSl->Parameters.DeviceIoControl.IoControlCode,
1025 pIrp->AssociatedIrp.SystemBuffer,
1026 pSl->Parameters.DeviceIoControl.InputBufferLength,
1027 pSl->Parameters.DeviceIoControl.OutputBufferLength,
1028 &Info);
1029 Assert(Status != STATUS_PENDING);
1030
1031 IoReleaseRemoveLock(&g_VBoxUsbMonGlobals.RmLock, pDevObj);
1032 }
1033
1034 pIrp->IoStatus.Information = Info;
1035 pIrp->IoStatus.Status = Status;
1036 IoCompleteRequest (pIrp, IO_NO_INCREMENT);
1037 return Status;
1038}
1039
1040static NTSTATUS vboxUsbMonInternalIoctlDispatch(ULONG Ctl, PVOID pvBuffer, ULONG_PTR *pInfo)
1041{
1042 NTSTATUS Status = STATUS_SUCCESS;
1043 *pInfo = 0;
1044 switch (Ctl)
1045 {
1046 case VBOXUSBIDC_INTERNAL_IOCTL_GET_VERSION:
1047 {
1048 PVBOXUSBIDC_VERSION pOut = (PVBOXUSBIDC_VERSION)pvBuffer;
1049
1050 Log(("VBOXUSBIDC_INTERNAL_IOCTL_GET_VERSION\n"));
1051 if (!pvBuffer)
1052 {
1053 AssertMsgFailed(("VBOXUSBIDC_INTERNAL_IOCTL_GET_VERSION: Buffer is NULL\n"));
1054 Status = STATUS_INVALID_PARAMETER;
1055 break;
1056 }
1057 pOut->u32Major = VBOXUSBIDC_VERSION_MAJOR;
1058 pOut->u32Minor = VBOXUSBIDC_VERSION_MINOR;
1059 break;
1060 }
1061
1062 case VBOXUSBIDC_INTERNAL_IOCTL_PROXY_STARTUP:
1063 {
1064 PVBOXUSBIDC_PROXY_STARTUP pOut = (PVBOXUSBIDC_PROXY_STARTUP)pvBuffer;
1065
1066 Log(("VBOXUSBIDC_INTERNAL_IOCTL_PROXY_STARTUP\n"));
1067 if (!pvBuffer)
1068 {
1069 AssertMsgFailed(("VBOXUSBIDC_INTERNAL_IOCTL_GET_VERSION: Buffer is NULL\n"));
1070 Status = STATUS_INVALID_PARAMETER;
1071 break;
1072 }
1073
1074 pOut->u.hDev = VBoxUsbFltProxyStarted(pOut->u.pPDO);
1075 break;
1076 }
1077
1078 case VBOXUSBIDC_INTERNAL_IOCTL_PROXY_TEARDOWN:
1079 {
1080 PVBOXUSBIDC_PROXY_TEARDOWN pOut = (PVBOXUSBIDC_PROXY_TEARDOWN)pvBuffer;
1081
1082 Log(("VBOXUSBIDC_INTERNAL_IOCTL_PROXY_TEARDOWN\n"));
1083 if (!pvBuffer)
1084 {
1085 AssertMsgFailed(("VBOXUSBIDC_INTERNAL_IOCTL_PROXY_TEARDOWN: Buffer is NULL\n"));
1086 Status = STATUS_INVALID_PARAMETER;
1087 break;
1088 }
1089
1090 VBoxUsbFltProxyStopped(pOut->hDev);
1091 break;
1092 }
1093
1094 default:
1095 {
1096 AssertFailed();
1097 Status = STATUS_INVALID_PARAMETER;
1098 break;
1099 }
1100 }
1101
1102 return Status;
1103}
1104
1105static NTSTATUS _stdcall VBoxUsbMonInternalDeviceControl(PDEVICE_OBJECT pDevObj, PIRP pIrp)
1106{
1107 ULONG_PTR Info = 0;
1108 NTSTATUS Status = IoAcquireRemoveLock(&g_VBoxUsbMonGlobals.RmLock, pDevObj);
1109 if (NT_SUCCESS(Status))
1110 {
1111 PIO_STACK_LOCATION pSl = IoGetCurrentIrpStackLocation(pIrp);
1112 Status = vboxUsbMonInternalIoctlDispatch(pSl->Parameters.DeviceIoControl.IoControlCode,
1113 pSl->Parameters.Others.Argument1,
1114 &Info);
1115 Assert(Status != STATUS_PENDING);
1116
1117 IoReleaseRemoveLock(&g_VBoxUsbMonGlobals.RmLock, pDevObj);
1118 }
1119
1120 pIrp->IoStatus.Information = Info;
1121 pIrp->IoStatus.Status = Status;
1122 IoCompleteRequest (pIrp, IO_NO_INCREMENT);
1123 return Status;
1124}
1125
1126/**
1127 * Unload the driver.
1128 *
1129 * @param pDrvObj Driver object.
1130 */
1131static void _stdcall VBoxUsbMonUnload(PDRIVER_OBJECT pDrvObj)
1132{
1133 Log(("VBoxUSBMonUnload pDrvObj (0x%p)\n", pDrvObj));
1134
1135 IoReleaseRemoveLockAndWait(&g_VBoxUsbMonGlobals.RmLock, &g_VBoxUsbMonGlobals);
1136
1137 Assert(!g_VBoxUsbMonGlobals.cOpens);
1138
1139 UNICODE_STRING DosName;
1140 RtlInitUnicodeString(&DosName, USBMON_DEVICE_NAME_DOS);
1141 NTSTATUS rc = IoDeleteSymbolicLink(&DosName);
1142
1143 IoDeleteDevice(g_VBoxUsbMonGlobals.pDevObj);
1144
1145 /* cleanup the logger */
1146 PRTLOGGER pLogger = RTLogRelSetDefaultInstance(NULL);
1147 if (pLogger)
1148 {
1149 RTLogDestroy(pLogger);
1150 }
1151 pLogger = RTLogSetDefaultInstance(NULL);
1152 if (pLogger)
1153 {
1154 RTLogDestroy(pLogger);
1155 }
1156}
1157
1158RT_C_DECLS_BEGIN
1159NTSTATUS _stdcall DriverEntry(PDRIVER_OBJECT pDrvObj, PUNICODE_STRING pRegPath);
1160RT_C_DECLS_END
1161
1162/**
1163 * Driver entry point.
1164 *
1165 * @returns appropriate status code.
1166 * @param pDrvObj Pointer to driver object.
1167 * @param pRegPath Registry base path.
1168 */
1169NTSTATUS _stdcall DriverEntry(PDRIVER_OBJECT pDrvObj, PUNICODE_STRING pRegPath)
1170{
1171#ifdef DEBUG_misha
1172 RTLogGroupSettings(0, "+default.e.l.f.l2.l3");;
1173#endif
1174
1175 Log(("VBoxUSBMon::DriverEntry\n"));
1176
1177 memset (&g_VBoxUsbMonGlobals, 0, sizeof (g_VBoxUsbMonGlobals));
1178 KeInitializeEvent(&g_VBoxUsbMonGlobals.OpenSynchEvent, SynchronizationEvent, TRUE /* signaled */);
1179 IoInitializeRemoveLock(&g_VBoxUsbMonGlobals.RmLock, VBOXUSBMON_MEMTAG, 1, 100);
1180 UNICODE_STRING DevName;
1181 PDEVICE_OBJECT pDevObj;
1182 /* create the device */
1183 RtlInitUnicodeString(&DevName, USBMON_DEVICE_NAME_NT);
1184 NTSTATUS Status = IoAcquireRemoveLock(&g_VBoxUsbMonGlobals.RmLock, &g_VBoxUsbMonGlobals);
1185 if (NT_SUCCESS(Status))
1186 {
1187 Status = IoCreateDevice(pDrvObj, sizeof (VBOXUSBMONINS), &DevName, FILE_DEVICE_UNKNOWN, 0, FALSE, &pDevObj);
1188 if (NT_SUCCESS(Status))
1189 {
1190 UNICODE_STRING DosName;
1191 RtlInitUnicodeString(&DosName, USBMON_DEVICE_NAME_DOS);
1192 Status = IoCreateSymbolicLink(&DosName, &DevName);
1193 if (NT_SUCCESS(Status))
1194 {
1195 PVBOXUSBMONINS pDevExt = (PVBOXUSBMONINS)pDevObj->DeviceExtension;
1196 memset(pDevExt, 0, sizeof(*pDevExt));
1197
1198 pDrvObj->DriverUnload = VBoxUsbMonUnload;
1199 pDrvObj->MajorFunction[IRP_MJ_CREATE] = VBoxUsbMonCreate;
1200 pDrvObj->MajorFunction[IRP_MJ_CLOSE] = VBoxUsbMonClose;
1201 pDrvObj->MajorFunction[IRP_MJ_DEVICE_CONTROL] = VBoxUsbMonDeviceControl;
1202 pDrvObj->MajorFunction[IRP_MJ_INTERNAL_DEVICE_CONTROL] = VBoxUsbMonInternalDeviceControl;
1203
1204 g_VBoxUsbMonGlobals.pDevObj = pDevObj;
1205 Log(("VBoxUSBMon::DriverEntry returning STATUS_SUCCESS\n"));
1206 return STATUS_SUCCESS;
1207 }
1208 IoDeleteDevice(pDevObj);
1209 }
1210 IoReleaseRemoveLockAndWait(&g_VBoxUsbMonGlobals.RmLock, &g_VBoxUsbMonGlobals);
1211 }
1212
1213 return Status;
1214}
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