VirtualBox

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

Last change on this file since 47511 was 38616, checked in by vboxsync, 13 years ago

usb/win: missing ObDereference

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 57.4 KB
Line 
1/* $Id: VBoxUsbMon.cpp 38616 2011-09-02 18:24: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 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)", _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 WARN(("IoBuildDeviceIoControlRequest failed!!"));
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!!"));
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", pRel));
193 if (VALID_PTR(pRel))
194 {
195 *pDevRelations = pRel;
196 }
197 else
198 {
199 WARN(("Invalid pointer %p", pRel));
200 }
201 }
202 else
203 {
204 WARN(("IRP_MN_QUERY_DEVICE_RELATIONS failed Status(0x%x)", Status));
205 }
206
207 LOG(("IoCallDriver returned %x", Status));
208 return Status;
209}
210
211RT_C_DECLS_BEGIN
212/* these two come from IFS Kit, which is not included in 2K DDK we use,
213 * although they are documented and exported in ntoskrnl,
214 * and both should be present for >= XP according to MSDN */
215NTKERNELAPI
216NTSTATUS
217ObQueryNameString(
218 __in PVOID Object,
219 __out_bcount_opt(Length) POBJECT_NAME_INFORMATION ObjectNameInfo,
220 __in ULONG Length,
221 __out PULONG ReturnLength
222 );
223
224NTKERNELAPI
225PDEVICE_OBJECT
226IoGetLowerDeviceObject(
227 __in PDEVICE_OBJECT DeviceObject
228 );
229
230RT_C_DECLS_END
231
232typedef DECLCALLBACK(VOID) FNVBOXUSBDEVNAMEMATCHER(PDEVICE_OBJECT pDo, PUNICODE_STRING pName, PVOID pvMatcher);
233typedef FNVBOXUSBDEVNAMEMATCHER *PFNVBOXUSBDEVNAMEMATCHER;
234
235static NTSTATUS vboxUsbObjCheckName(PDEVICE_OBJECT pDo, PFNVBOXUSBDEVNAMEMATCHER pfnMatcher, PVOID pvMatcher)
236{
237 union
238 {
239 OBJECT_NAME_INFORMATION Info;
240 char buf[1024];
241 } buf;
242 ULONG cbLength = 0;
243
244 POBJECT_NAME_INFORMATION pInfo = &buf.Info;
245 NTSTATUS Status = ObQueryNameString(pDo, &buf.Info, sizeof (buf), &cbLength);
246 if (!NT_SUCCESS(Status))
247 {
248 if (STATUS_INFO_LENGTH_MISMATCH != Status)
249 {
250 WARN(("ObQueryNameString failed 0x%x", Status));
251 return Status;
252 }
253
254 LOG(("ObQueryNameString returned STATUS_INFO_LENGTH_MISMATCH, required size %d", cbLength));
255
256 pInfo = (POBJECT_NAME_INFORMATION)VBoxUsbMonMemAlloc(cbLength);
257 if (!pInfo)
258 {
259 WARN(("VBoxUsbMonMemAlloc failed"));
260 return STATUS_NO_MEMORY;
261 }
262 Status = ObQueryNameString(pDo, pInfo, cbLength, &cbLength);
263 if (!NT_SUCCESS(Status))
264 {
265 WARN(("ObQueryNameString second try failed 0x%x", Status));
266 VBoxUsbMonMemFree(pInfo);
267 return Status;
268 }
269 }
270
271 /* we've got the name! */
272 LOG(("got the name:"));
273 LOG_USTR(&pInfo->Name);
274 pfnMatcher(pDo, &pInfo->Name, pvMatcher);
275
276 if (&buf.Info != pInfo)
277 {
278 LOG(("freeing allocated pInfo(0x%p)", pInfo));
279 VBoxUsbMonMemFree(pInfo);
280 }
281 else
282 {
283 LOG(("no freeing info needed"));
284 }
285
286 return STATUS_SUCCESS;
287}
288
289
290typedef DECLCALLBACK(BOOLEAN) FNVBOXUSBDEVSTACKWALKER(PDEVICE_OBJECT pTopDo, PDEVICE_OBJECT pCurDo, PVOID pvContext);
291typedef FNVBOXUSBDEVSTACKWALKER *PFNVBOXUSBDEVSTACKWALKER;
292
293VOID vboxUsbObjDevStackWalk(PDEVICE_OBJECT pDo, PFNVBOXUSBDEVSTACKWALKER pfnWalker, PVOID pvWalker)
294{
295 LOG(("==>tree walk for Do 0x%p", pDo));
296 PDEVICE_OBJECT pCurDo = pDo;
297 ObReferenceObject(pCurDo); /* <- to make sure the dereferencing logic below works correctly */
298 do
299 {
300 LOG(("==Do 0x%p", pCurDo));
301#ifdef VBOX_USB_WITH_VERBOSE_LOGGING
302 {
303 union
304 {
305 OBJECT_NAME_INFORMATION Info;
306 char buf[1024];
307 } buf;
308 ULONG cbLength = 0;
309
310 NTSTATUS tmpStatus = ObQueryNameString(pCurDo, &buf.Info, sizeof (buf), &cbLength);
311 if (NT_SUCCESS(tmpStatus))
312 {
313 LOG((" Obj name:"));
314 LOG_USTR(&buf.Info.Name);
315 }
316 else
317 {
318 if (STATUS_INFO_LENGTH_MISMATCH != tmpStatus)
319 {
320 WARN(("ObQueryNameString failed 0x%x", tmpStatus));
321 }
322 else
323 {
324 WARN(("ObQueryNameString STATUS_INFO_LENGTH_MISMATCH, required %d", cbLength));
325 }
326 }
327
328 if (pCurDo->DriverObject
329 && pCurDo->DriverObject->DriverName.Buffer
330 && pCurDo->DriverObject->DriverName.Length)
331 {
332 LOG((" Drv Obj(0x%p), name:", pCurDo->DriverObject));
333 LOG_USTR(&pCurDo->DriverObject->DriverName);
334 }
335 else
336 {
337 LOG((" No Drv Name, Drv Obj(0x%p)", pCurDo->DriverObject));
338 if (pCurDo->DriverObject)
339 {
340 LOG((" driver name is zero, Length(%d), Buffer(0x%p)",
341 pCurDo->DriverObject->DriverName.Length, pCurDo->DriverObject->DriverName.Buffer));
342 }
343 else
344 {
345 LOG((" driver object is NULL"));
346 }
347 }
348 }
349#endif
350 if (!pfnWalker(pDo, pCurDo, pvWalker))
351 {
352 LOG(("the walker said to stop"));
353 ObDereferenceObject(pCurDo);
354 break;
355 }
356
357 PDEVICE_OBJECT pLowerDo = IoGetLowerDeviceObject(pCurDo);
358 ObDereferenceObject(pCurDo);
359 if (!pLowerDo)
360 {
361 LOG(("IoGetLowerDeviceObject returnned NULL, stop"));
362 break;
363 }
364 pCurDo = pLowerDo;
365 } while (1);
366
367 LOG(("<==tree walk"));
368}
369
370static DECLCALLBACK(BOOLEAN) vboxUsbObjNamePrefixMatch(PUNICODE_STRING pName, PUNICODE_STRING pNamePrefix, BOOLEAN fCaseInSensitive)
371{
372 LOG(("Matching prefix:"));
373 LOG_USTR(pNamePrefix);
374 if (pNamePrefix->Length > pName->Length)
375 {
376 LOG(("Pregix Length(%d) > Name Length(%d)", pNamePrefix->Length, pName->Length));
377 return FALSE;
378 }
379
380 LOG(("Pregix Length(%d) <= Name Length(%d)", pNamePrefix->Length, pName->Length));
381
382 UNICODE_STRING NamePrefix = *pName;
383 NamePrefix.Length = pNamePrefix->Length;
384 LONG rc = RtlCompareUnicodeString(&NamePrefix, pNamePrefix, fCaseInSensitive);
385
386 if (!rc)
387 {
388 LOG(("prefix MATCHED!"));
389 return TRUE;
390 }
391
392 LOG(("prefix NOT matched!"));
393 return FALSE;
394}
395
396typedef struct VBOXUSBOBJNAMEPREFIXMATCHER
397{
398 PUNICODE_STRING pNamePrefix;
399 BOOLEAN fMatched;
400} VBOXUSBOBJNAMEPREFIXMATCHER, *PVBOXUSBOBJNAMEPREFIXMATCHER;
401
402static DECLCALLBACK(VOID) vboxUsbObjDevNamePrefixMatcher(PDEVICE_OBJECT pDo, PUNICODE_STRING pName, PVOID pvMatcher)
403{
404 PVBOXUSBOBJNAMEPREFIXMATCHER pData = (PVBOXUSBOBJNAMEPREFIXMATCHER)pvMatcher;
405 PUNICODE_STRING pNamePrefix = pData->pNamePrefix;
406 ASSERT_WARN(!pData->fMatched, ("match flag already set!"));
407 pData->fMatched = vboxUsbObjNamePrefixMatch(pName, pNamePrefix, TRUE /* fCaseInSensitive */);
408 LOG(("match result (%d)", (int)pData->fMatched));
409}
410
411typedef struct VBOXUSBOBJDRVOBJSEARCHER
412{
413 PDEVICE_OBJECT pDevObj;
414 PUNICODE_STRING pDrvName;
415 PUNICODE_STRING pPdoNamePrefix;
416 ULONG fFlags;
417} VBOXUSBOBJDRVOBJSEARCHER, *PVBOXUSBOBJDRVOBJSEARCHER;
418
419static DECLCALLBACK(BOOLEAN) vboxUsbObjDevObjSearcherWalker(PDEVICE_OBJECT pTopDo, PDEVICE_OBJECT pCurDo, PVOID pvContext)
420{
421 PVBOXUSBOBJDRVOBJSEARCHER pData = (PVBOXUSBOBJDRVOBJSEARCHER)pvContext;
422 ASSERT_WARN(!pData->pDevObj, ("non-null dev object (0x%p) on enter", pData->pDevObj));
423 pData->pDevObj = NULL;
424 if (pCurDo->DriverObject
425 && pCurDo->DriverObject->DriverName.Buffer
426 && pCurDo->DriverObject->DriverName.Length
427 && !RtlCompareUnicodeString(pData->pDrvName, &pCurDo->DriverObject->DriverName, TRUE /* case insensitive */))
428 {
429 LOG(("MATCHED driver:"));
430 LOG_USTR(&pCurDo->DriverObject->DriverName);
431 if ((pData->fFlags & VBOXUSBMONHUBWALK_F_ALL) != VBOXUSBMONHUBWALK_F_ALL)
432 {
433 VBOXUSBOBJNAMEPREFIXMATCHER Data = {0};
434 Data.pNamePrefix = pData->pPdoNamePrefix;
435 NTSTATUS Status = vboxUsbObjCheckName(pCurDo, vboxUsbObjDevNamePrefixMatcher, &Data);
436 if (!NT_SUCCESS(Status))
437 {
438 WARN(("vboxUsbObjCheckName failed Status (0x%x)", Status));
439 return TRUE;
440 }
441
442
443 LOG(("prefix match result (%d)", Data.fMatched));
444 if ((pData->fFlags & VBOXUSBMONHUBWALK_F_FDO) == VBOXUSBMONHUBWALK_F_FDO)
445 {
446 LOG(("VBOXUSBMONHUBWALK_F_FDO"));
447 if (Data.fMatched)
448 {
449 LOG(("this is a PDO object, skip it and stop search"));
450 /* stop search as we will not find FDO here */
451 return FALSE;
452 }
453
454 LOG(("this is a FDO object, MATCHED!!"));
455 }
456 else if ((pData->fFlags & VBOXUSBMONHUBWALK_F_PDO) == VBOXUSBMONHUBWALK_F_PDO)
457 {
458 LOG(("VBOXUSBMONHUBWALK_F_PDO"));
459 if (!Data.fMatched)
460 {
461 LOG(("this is a FDO object, skip it and continue search"));
462 /* continue seach since since this could be a nested hub that would have a usbhub-originated PDO */
463 return TRUE;
464 }
465
466 LOG(("this is a PDO object, MATCHED!!"));
467 }
468
469 }
470 else
471 {
472 LOG(("VBOXUSBMONHUBWALK_F_ALL"));
473 LOG(("either PDO or FDO, MATCHED!!"));
474 }
475
476 /* ensure the dev object is not destroyed */
477 ObReferenceObject(pCurDo);
478 pData->pDevObj = pCurDo;
479 /* we are done */
480 return FALSE;
481 }
482 else
483 {
484 LOG(("driver object (0x%p) no match", pCurDo->DriverObject));
485 if (pCurDo->DriverObject)
486 {
487 if ( pCurDo->DriverObject->DriverName.Buffer
488 && pCurDo->DriverObject->DriverName.Length)
489 {
490 LOG(("driver name not match, was:"));
491 LOG_USTR(&pCurDo->DriverObject->DriverName);
492 LOG(("but expected:"));
493 LOG_USTR(pData->pDrvName);
494 }
495 else
496 {
497 LOG(("driver name is zero, Length(%d), Buffer(0x%p)",
498 pCurDo->DriverObject->DriverName.Length, pCurDo->DriverObject->DriverName.Buffer));
499 }
500 }
501 else
502 {
503 LOG(("driver object is NULL"));
504 }
505 }
506 return TRUE;
507}
508
509VOID vboxUsbMonHubDevWalk(PFNVBOXUSBMONDEVWALKER pfnWalker, PVOID pvWalker, ULONG fFlags)
510{
511 NTSTATUS Status = STATUS_UNSUCCESSFUL;
512 UNICODE_STRING szStandardHubName;
513 PDRIVER_OBJECT pDrvObj = NULL;
514 szStandardHubName.Length = 0;
515 szStandardHubName.MaximumLength = 0;
516 szStandardHubName.Buffer = 0;
517 RtlInitUnicodeString(&szStandardHubName, L"\\Driver\\usbhub");
518 UNICODE_STRING szStandardHubPdoNamePrefix;
519 szStandardHubPdoNamePrefix.Length = 0;
520 szStandardHubPdoNamePrefix.MaximumLength = 0;
521 szStandardHubPdoNamePrefix.Buffer = 0;
522 RtlInitUnicodeString(&szStandardHubPdoNamePrefix, L"\\Device\\USBPDO-");
523
524 for (int i = 0; i < 16; i++)
525 {
526 WCHAR szwHubName[32] = {0};
527 char szHubName[32] = {0};
528 ANSI_STRING AnsiName;
529 UNICODE_STRING UnicodeName;
530 PDEVICE_OBJECT pHubDevObj;
531 PFILE_OBJECT pHubFileObj;
532
533 sprintf(szHubName, "\\Device\\USBPDO-%d", i);
534
535 RtlInitAnsiString(&AnsiName, szHubName);
536
537 UnicodeName.Length = 0;
538 UnicodeName.MaximumLength = sizeof (szwHubName);
539 UnicodeName.Buffer = szwHubName;
540
541 RtlInitAnsiString(&AnsiName, szHubName);
542 Status = RtlAnsiStringToUnicodeString(&UnicodeName, &AnsiName, FALSE);
543 if (Status == STATUS_SUCCESS)
544 {
545 Status = IoGetDeviceObjectPointer(&UnicodeName, FILE_READ_DATA, &pHubFileObj, &pHubDevObj);
546 if (Status == STATUS_SUCCESS)
547 {
548 LOG(("IoGetDeviceObjectPointer for %S returned %p %p", szwHubName, pHubDevObj, pHubFileObj));
549
550 VBOXUSBOBJDRVOBJSEARCHER Data = {0};
551 Data.pDrvName = &szStandardHubName;
552 Data.pPdoNamePrefix = &szStandardHubPdoNamePrefix;
553 Data.fFlags = fFlags;
554
555 vboxUsbObjDevStackWalk(pHubDevObj, vboxUsbObjDevObjSearcherWalker, &Data);
556 if (Data.pDevObj)
557 {
558 LOG(("found hub dev obj (0x%p)", Data.pDevObj));
559 if (!pfnWalker(pHubFileObj, pHubDevObj, Data.pDevObj, pvWalker))
560 {
561 LOG(("the walker said to stop"));
562 ObDereferenceObject(Data.pDevObj);
563 ObDereferenceObject(pHubFileObj);
564 break;
565 }
566
567 LOG(("going forward.."));
568 ObDereferenceObject(Data.pDevObj);
569 }
570 else
571 {
572 LOG(("no hub driver obj found"));
573 ASSERT_WARN(!Data.pDevObj, ("non-null dev obj poiter returned (0x%p)", Data.pDevObj));
574 }
575
576 /* this will dereference both file and dev obj */
577 ObDereferenceObject(pHubFileObj);
578 }
579 else
580 {
581 LOG(("IoGetDeviceObjectPointer returned Status (0x%x) for (%S)", Status, szwHubName));
582 }
583 }
584 else
585 {
586 WARN(("RtlAnsiStringToUnicodeString failed, Status (0x%x) for Ansu name (%s)", Status, szHubName));
587 }
588 }
589}
590
591typedef struct VBOXUSBMONFINDHUBWALKER
592{
593 PDRIVER_OBJECT pDrvObj;
594} VBOXUSBMONFINDHUBWALKER, *PVBOXUSBMONFINDHUBWALKER;
595
596static DECLCALLBACK(BOOLEAN) vboxUsbMonFindHubDrvObjWalker(PFILE_OBJECT pFile, PDEVICE_OBJECT pTopDo, PDEVICE_OBJECT pHubDo, PVOID pvContext)
597{
598 PVBOXUSBMONFINDHUBWALKER pData = (PVBOXUSBMONFINDHUBWALKER)pvContext;
599 PDRIVER_OBJECT pDrvObj = pHubDo->DriverObject;
600
601 ASSERT_WARN(!pData->pDrvObj, ("pDrvObj expected null on enter, but was(0x%p)", pData->pDrvObj));
602 if(pDrvObj)
603 {
604 LOG(("found driver object 0x%p", pDrvObj));
605 ObReferenceObject(pDrvObj);
606 pData->pDrvObj = pDrvObj;
607 return FALSE;
608 }
609
610 WARN(("null pDrvObj!"));
611 return TRUE;
612}
613
614static PDRIVER_OBJECT vboxUsbMonHookFindHubDrvObj()
615{
616 NTSTATUS Status = STATUS_UNSUCCESSFUL;
617 UNICODE_STRING szStandardHubName;
618 PDRIVER_OBJECT pDrvObj = NULL;
619 szStandardHubName.Length = 0;
620 szStandardHubName.MaximumLength = 0;
621 szStandardHubName.Buffer = 0;
622 RtlInitUnicodeString(&szStandardHubName, L"\\Driver\\usbhub");
623
624 LOG(("Search USB hub"));
625 VBOXUSBMONFINDHUBWALKER Data = {0};
626 vboxUsbMonHubDevWalk(vboxUsbMonFindHubDrvObjWalker, &Data, VBOXUSBMONHUBWALK_F_ALL);
627 if (Data.pDrvObj)
628 {
629 LOG(("returning driver object 0x%p", Data.pDrvObj));
630 }
631 else
632 {
633 WARN(("no hub driver object found!"));
634 }
635 return Data.pDrvObj;
636}
637
638/* NOTE: the stack location data is not the "actual" IRP stack location,
639 * but a copy being preserved on the IRP way down.
640 * See the note in VBoxUsbPnPCompletion for detail */
641static NTSTATUS vboxUsbMonHandlePnPIoctl(PDEVICE_OBJECT pDevObj, PIO_STACK_LOCATION pSl, PIO_STATUS_BLOCK pIoStatus)
642{
643 LOG(("IRQL = %d", KeGetCurrentIrql()));
644 switch(pSl->MinorFunction)
645 {
646 case IRP_MN_QUERY_DEVICE_TEXT:
647 {
648 LOG(("IRP_MN_QUERY_DEVICE_TEXT: pIoStatus->Status = %x", pIoStatus->Status));
649 if (pIoStatus->Status == STATUS_SUCCESS)
650 {
651 WCHAR *pId = (WCHAR *)pIoStatus->Information;
652 if (VALID_PTR(pId))
653 {
654 KIRQL Iqrl = KeGetCurrentIrql();
655 /* IRQL should be always passive here */
656 ASSERT_WARN(Iqrl == PASSIVE_LEVEL, ("irql is not PASSIVE"));
657 switch(pSl->Parameters.QueryDeviceText.DeviceTextType)
658 {
659 case DeviceTextLocationInformation:
660 LOG(("DeviceTextLocationInformation"));
661 LOG_STRW(pId);
662 break;
663
664 case DeviceTextDescription:
665 LOG(("DeviceTextDescription"));
666 LOG_STRW(pId);
667 if (VBoxUsbFltPdoIsFiltered(pDevObj))
668 {
669 LOG(("PDO (0x%p) is filtered", pDevObj));
670 WCHAR *pId = (WCHAR *)ExAllocatePool(PagedPool, sizeof(szDeviceTextDescription));
671 if (!pId)
672 {
673 AssertFailed();
674 break;
675 }
676 memcpy(pId, szDeviceTextDescription, sizeof(szDeviceTextDescription));
677 LOG(("NEW szDeviceTextDescription"));
678 LOG_STRW(pId);
679 ExFreePool((PVOID)pIoStatus->Information);
680 pIoStatus->Information = (ULONG_PTR)pId;
681 }
682 else
683 {
684 LOG(("PDO (0x%p) is NOT filtered", pDevObj));
685 }
686 break;
687 default:
688 LOG(("DeviceText %d", pSl->Parameters.QueryDeviceText.DeviceTextType));
689 break;
690 }
691 }
692 else
693 LOG(("Invalid pointer %p", pId));
694 }
695 break;
696 }
697
698 case IRP_MN_QUERY_ID:
699 {
700 LOG(("IRP_MN_QUERY_ID: Irp->pIoStatus->Status = %x", pIoStatus->Status));
701 if (pIoStatus->Status == STATUS_SUCCESS && pDevObj)
702 {
703 WCHAR *pId = (WCHAR *)pIoStatus->Information;
704#ifdef VBOX_USB_WITH_VERBOSE_LOGGING
705 WCHAR *pTmp;
706#endif
707 if (VALID_PTR(pId))
708 {
709 KIRQL Iqrl = KeGetCurrentIrql();
710 /* IRQL should be always passive here */
711 ASSERT_WARN(Iqrl == PASSIVE_LEVEL, ("irql is not PASSIVE"));
712
713 switch (pSl->Parameters.QueryDeviceRelations.Type)
714 {
715 case BusQueryInstanceID:
716 LOG(("BusQueryInstanceID"));
717 LOG_STRW(pId);
718 break;
719
720 case BusQueryDeviceID:
721 {
722 LOG(("BusQueryDeviceID"));
723 pId = (WCHAR *)ExAllocatePool(PagedPool, sizeof(szBusQueryDeviceId));
724 if (!pId)
725 {
726 WARN(("ExAllocatePool failed"));
727 break;
728 }
729
730 BOOLEAN bFiltered = FALSE;
731 NTSTATUS Status = VBoxUsbFltPdoAdd(pDevObj, &bFiltered);
732 if (Status != STATUS_SUCCESS || !bFiltered)
733 {
734 if(Status == STATUS_SUCCESS)
735 {
736 LOG(("PDO (0x%p) is NOT filtered", pDevObj));
737 }
738 else
739 {
740 WARN(("VBoxUsbFltPdoAdd for PDO (0x%p) failed Status 0x%x", pDevObj, Status));
741 }
742 ExFreePool(pId);
743 break;
744 }
745
746 LOG(("PDO (0x%p) is filtered", pDevObj));
747 ExFreePool((PVOID)pIoStatus->Information);
748 memcpy(pId, szBusQueryDeviceId, sizeof(szBusQueryDeviceId));
749 pIoStatus->Information = (ULONG_PTR)pId;
750 break;
751 }
752 case BusQueryHardwareIDs:
753 {
754 LOG(("BusQueryHardwareIDs"));
755#ifdef VBOX_USB_WITH_VERBOSE_LOGGING
756 while(*pId) //MULTI_SZ
757 {
758 LOG_STRW(pId);
759 while(*pId) pId++;
760 pId++;
761 }
762#endif
763 pId = (WCHAR *)ExAllocatePool(PagedPool, sizeof(szBusQueryHardwareIDs));
764 if (!pId)
765 {
766 WARN(("ExAllocatePool failed"));
767 break;
768 }
769
770 BOOLEAN bFiltered = FALSE;
771 NTSTATUS Status = VBoxUsbFltPdoAdd(pDevObj, &bFiltered);
772 if (Status != STATUS_SUCCESS || !bFiltered)
773 {
774 if(Status == STATUS_SUCCESS)
775 {
776 LOG(("PDO (0x%p) is NOT filtered", pDevObj));
777 }
778 else
779 {
780 WARN(("VBoxUsbFltPdoAdd for PDO (0x%p) failed Status 0x%x", pDevObj, Status));
781 }
782 ExFreePool(pId);
783 break;
784 }
785
786 LOG(("PDO (0x%p) is filtered", pDevObj));
787
788 memcpy(pId, szBusQueryHardwareIDs, sizeof(szBusQueryHardwareIDs));
789#ifdef VBOX_USB_WITH_VERBOSE_LOGGING
790 LOG(("NEW BusQueryHardwareIDs"));
791 pTmp = pId;
792 while(*pTmp) //MULTI_SZ
793 {
794
795 LOG_STRW(pTmp);
796 while(*pTmp) pTmp++;
797 pTmp++;
798 }
799#endif
800 ExFreePool((PVOID)pIoStatus->Information);
801 pIoStatus->Information = (ULONG_PTR)pId;
802 break;
803 }
804 case BusQueryCompatibleIDs:
805 LOG(("BusQueryCompatibleIDs"));
806#ifdef VBOX_USB_WITH_VERBOSE_LOGGING
807 while(*pId) //MULTI_SZ
808 {
809 LOG_STRW(pId);
810 while(*pId) pId++;
811 pId++;
812 }
813#endif
814 if (VBoxUsbFltPdoIsFiltered(pDevObj))
815 {
816 LOG(("PDO (0x%p) is filtered", pDevObj));
817 pId = (WCHAR *)ExAllocatePool(PagedPool, sizeof(szBusQueryCompatibleIDs));
818 if (!pId)
819 {
820 WARN(("ExAllocatePool failed"));
821 break;
822 }
823 memcpy(pId, szBusQueryCompatibleIDs, sizeof(szBusQueryCompatibleIDs));
824#ifdef VBOX_USB_WITH_VERBOSE_LOGGING
825 LOG(("NEW BusQueryCompatibleIDs"));
826 pTmp = pId;
827 while(*pTmp) //MULTI_SZ
828 {
829 LOG_STRW(pTmp);
830 while(*pTmp) pTmp++;
831 pTmp++;
832 }
833#endif
834 ExFreePool((PVOID)pIoStatus->Information);
835 pIoStatus->Information = (ULONG_PTR)pId;
836 }
837 else
838 {
839 LOG(("PDO (0x%p) is NOT filtered", pDevObj));
840 }
841 break;
842 }
843 }
844 else
845 {
846 LOG(("Invalid pointer %p", pId));
847 }
848 }
849 break;
850 }
851
852#ifdef VBOX_USB_WITH_VERBOSE_LOGGING
853 case IRP_MN_QUERY_DEVICE_RELATIONS:
854 {
855 switch(pSl->Parameters.QueryDeviceRelations.Type)
856 {
857 case BusRelations:
858 {
859 LOG(("BusRelations"));
860
861 if (pIoStatus->Status == STATUS_SUCCESS)
862 {
863 PDEVICE_RELATIONS pRel = (PDEVICE_RELATIONS)pIoStatus->Information;
864 LOG(("pRel = %p", pRel));
865 if (VALID_PTR(pRel))
866 {
867 for (unsigned i=0;i<pRel->Count;i++)
868 {
869 if (VBoxUsbFltPdoIsFiltered(pDevObj))
870 LOG(("New PDO %p", pRel->Objects[i]));
871 }
872 }
873 else
874 LOG(("Invalid pointer %p", pRel));
875 }
876 break;
877 }
878 case TargetDeviceRelation:
879 LOG(("TargetDeviceRelation"));
880 break;
881 case RemovalRelations:
882 LOG(("RemovalRelations"));
883 break;
884 case EjectionRelations:
885 LOG(("EjectionRelations"));
886 break;
887 }
888 break;
889 }
890
891 case IRP_MN_QUERY_CAPABILITIES:
892 {
893 LOG(("IRP_MN_QUERY_CAPABILITIES: pIoStatus->Status = %x", pIoStatus->Status));
894 if (pIoStatus->Status == STATUS_SUCCESS)
895 {
896 PDEVICE_CAPABILITIES pCaps = pSl->Parameters.DeviceCapabilities.Capabilities;
897 if (VALID_PTR(pCaps))
898 {
899 LOG(("Caps.SilentInstall = %d", pCaps->SilentInstall));
900 LOG(("Caps.UniqueID = %d", pCaps->UniqueID ));
901 LOG(("Caps.Address = %d", pCaps->Address ));
902 LOG(("Caps.UINumber = %d", pCaps->UINumber ));
903 }
904 else
905 LOG(("Invalid pointer %p", pCaps));
906 }
907 break;
908 }
909
910 default:
911 break;
912#endif
913 } /*switch */
914
915 LOG(("Done returns %x (IRQL = %d)", pIoStatus->Status, KeGetCurrentIrql()));
916 return pIoStatus->Status;
917}
918
919NTSTATUS _stdcall VBoxUsbPnPCompletion(DEVICE_OBJECT *pDevObj, IRP *pIrp, void *pvContext)
920{
921 LOG(("Completion PDO(0x%p), IRP(0x%p), Status(0x%x)", pDevObj, pIrp, pIrp->IoStatus.Status));
922 ASSERT_WARN(pvContext, ("zero context"));
923
924 PVBOXUSBHOOK_REQUEST pRequest = (PVBOXUSBHOOK_REQUEST)pvContext;
925 /* NOTE: despite a regular IRP processing the stack location in our completion
926 * differs from those of the PnP hook since the hook is invoked in the "context" of the calle,
927 * while the completion is in the "coller" context in terms of IRP,
928 * so the completion stack location is one level "up" here.
929 *
930 * Moreover we CAN NOT access irp stack location in the completion because we might not have one at all
931 * in case the hooked driver is at the top of the irp call stack
932 *
933 * This is why we use the stack location we saved on IRP way down.
934 * */
935 PIO_STACK_LOCATION pSl = &pRequest->OldLocation;
936 ASSERT_WARN(pIrp == pRequest->pIrp, ("completed IRP(0x%x) not match request IRP(0x%x)", pIrp, pRequest->pIrp));
937 /* NOTE: we can not rely on pDevObj passed in IoCompletion since it may be zero
938 * in case IRP was created with extra stack locations and the caller did not initialize
939 * the IO_STACK_LOCATION::DeviceObject */
940 DEVICE_OBJECT *pRealDevObj = pRequest->pDevObj;
941// Assert(!pDevObj || pDevObj == pRealDevObj);
942// Assert(pSl->DeviceObject == pDevObj);
943
944 switch(pSl->MinorFunction)
945 {
946 case IRP_MN_QUERY_DEVICE_TEXT:
947 case IRP_MN_QUERY_ID:
948#ifdef VBOX_USB_WITH_VERBOSE_LOGGING
949 case IRP_MN_QUERY_DEVICE_RELATIONS:
950 case IRP_MN_QUERY_CAPABILITIES:
951#endif
952 if (NT_SUCCESS(pIrp->IoStatus.Status))
953 {
954 vboxUsbMonHandlePnPIoctl(pRealDevObj, pSl, &pIrp->IoStatus);
955 }
956 else
957 {
958 ASSERT_WARN(pIrp->IoStatus.Status == STATUS_NOT_SUPPORTED, ("Irp failed with status(0x%x)", pIrp->IoStatus.Status));
959 }
960 break;
961
962 case IRP_MN_SURPRISE_REMOVAL:
963 case IRP_MN_REMOVE_DEVICE:
964 if (NT_SUCCESS(pIrp->IoStatus.Status))
965 {
966 VBoxUsbFltPdoRemove(pRealDevObj);
967 }
968 else
969 {
970 AssertFailed();
971 }
972 break;
973
974 /* These two IRPs are received when the PnP subsystem has determined the id of the newly arrived device */
975 /* IRP_MN_START_DEVICE only arrives if it's a USB device of a known class or with a present host driver */
976 case IRP_MN_QUERY_RESOURCE_REQUIREMENTS:
977 case IRP_MN_QUERY_RESOURCES:
978 if (NT_SUCCESS(pIrp->IoStatus.Status) || pIrp->IoStatus.Status == STATUS_NOT_SUPPORTED)
979 {
980 VBoxUsbFltPdoAddCompleted(pRealDevObj);
981 }
982 else
983 {
984 AssertFailed();
985 }
986 break;
987
988 default:
989 break;
990 }
991
992 LOG(("<==PnP: Mn(%s), PDO(0x%p), IRP(0x%p), Status(0x%x), Sl PDO(0x%p), Compl PDO(0x%p)",
993 vboxUsbDbgStrPnPMn(pSl->MinorFunction),
994 pRealDevObj, pIrp, pIrp->IoStatus.Status,
995 pSl->DeviceObject, pDevObj));
996#ifdef DEBUG_misha
997 NTSTATUS tmpStatus = pIrp->IoStatus.Status;
998#endif
999 NTSTATUS Status = VBoxUsbHookRequestComplete(&g_VBoxUsbMonGlobals.UsbHubPnPHook.Hook, pDevObj, pIrp, pRequest);
1000 VBoxUsbMonMemFree(pRequest);
1001#ifdef DEBUG_misha
1002 if (Status != STATUS_MORE_PROCESSING_REQUIRED)
1003 {
1004 Assert(pIrp->IoStatus.Status == tmpStatus);
1005 }
1006#endif
1007 VBoxUsbHookRelease(&g_VBoxUsbMonGlobals.UsbHubPnPHook.Hook);
1008 return Status;
1009}
1010
1011/**
1012 * Device PnP hook
1013 *
1014 * @param pDevObj Device object.
1015 * @param pIrp Request packet.
1016 */
1017NTSTATUS _stdcall VBoxUsbMonPnPHook(IN PDEVICE_OBJECT pDevObj, IN PIRP pIrp)
1018{
1019 LOG(("==>PnP: Mn(%s), PDO(0x%p), IRP(0x%p), Status(0x%x)", vboxUsbDbgStrPnPMn(IoGetCurrentIrpStackLocation(pIrp)->MinorFunction), pDevObj, pIrp, pIrp->IoStatus.Status));
1020
1021 if(!VBoxUsbHookRetain(&g_VBoxUsbMonGlobals.UsbHubPnPHook.Hook))
1022 {
1023 WARN(("VBoxUsbHookRetain failed"));
1024 return VBoxUsbHookRequestPassDownHookSkip(&g_VBoxUsbMonGlobals.UsbHubPnPHook.Hook, pDevObj, pIrp);
1025 }
1026
1027 PVBOXUSBHUB_PNPHOOK_COMPLETION pCompletion = (PVBOXUSBHUB_PNPHOOK_COMPLETION)VBoxUsbMonMemAlloc(sizeof (*pCompletion));
1028 if (!pCompletion)
1029 {
1030 WARN(("VBoxUsbMonMemAlloc failed"));
1031 VBoxUsbHookRelease(&g_VBoxUsbMonGlobals.UsbHubPnPHook.Hook);
1032 pIrp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES;
1033 pIrp->IoStatus.Information = 0;
1034 IoCompleteRequest(pIrp, IO_NO_INCREMENT);
1035 return STATUS_INSUFFICIENT_RESOURCES;
1036 }
1037
1038 NTSTATUS Status = VBoxUsbHookRequestPassDownHookCompletion(&g_VBoxUsbMonGlobals.UsbHubPnPHook.Hook, pDevObj, pIrp, VBoxUsbPnPCompletion, &pCompletion->Rq);
1039#ifdef VBOX_USB_WITH_VERBOSE_LOGGING
1040 if (Status != STATUS_PENDING)
1041 {
1042 LOG(("Request completed, Status(0x%x)", Status));
1043 VBoxUsbHookVerifyCompletion(&g_VBoxUsbMonGlobals.UsbHubPnPHook.Hook, &pCompletion->Rq, pIrp);
1044 }
1045 else
1046 {
1047 LOG(("Request pending"));
1048 }
1049#endif
1050 return Status;
1051}
1052
1053
1054static NTSTATUS vboxUsbMonHookCheckInit()
1055{
1056 static bool fIsHookInited = false;
1057 if (fIsHookInited)
1058 {
1059 LOG(("hook inited already, success"));
1060 return STATUS_SUCCESS;
1061 }
1062 PDRIVER_OBJECT pDrvObj = vboxUsbMonHookFindHubDrvObj();
1063 if (pDrvObj)
1064 {
1065 VBoxUsbHookInit(&g_VBoxUsbMonGlobals.UsbHubPnPHook.Hook, pDrvObj, IRP_MJ_PNP, VBoxUsbMonPnPHook);
1066 fIsHookInited = true;
1067 LOG(("SUCCESS"));
1068 return STATUS_SUCCESS;
1069 }
1070 WARN(("hub drv obj not found, fail"));
1071 return STATUS_UNSUCCESSFUL;
1072}
1073
1074static NTSTATUS vboxUsbMonHookInstall()
1075{
1076#ifdef VBOXUSBMON_DBG_NO_PNPHOOK
1077 return STATUS_SUCCESS;
1078#else
1079 if (g_VBoxUsbMonGlobals.UsbHubPnPHook.fUninitFailed)
1080 {
1081 WARN(("trying to hook usbhub pnp after the unhook failed, do nothing & pretend success"));
1082 return STATUS_SUCCESS;
1083 }
1084 return VBoxUsbHookInstall(&g_VBoxUsbMonGlobals.UsbHubPnPHook.Hook);
1085#endif
1086}
1087
1088static NTSTATUS vboxUsbMonHookUninstall()
1089{
1090#ifdef VBOXUSBMON_DBG_NO_PNPHOOK
1091 return STATUS_SUCCESS;
1092#else
1093 NTSTATUS Status = VBoxUsbHookUninstall(&g_VBoxUsbMonGlobals.UsbHubPnPHook.Hook);
1094 if (!NT_SUCCESS(Status))
1095 {
1096 AssertMsgFailed(("usbhub pnp unhook failed, setting the fUninitFailed flag, the current value of fUninitFailed (%d)", g_VBoxUsbMonGlobals.UsbHubPnPHook.fUninitFailed));
1097 g_VBoxUsbMonGlobals.UsbHubPnPHook.fUninitFailed = true;
1098 }
1099 return Status;
1100#endif
1101}
1102
1103
1104static NTSTATUS vboxUsbMonCheckTermStuff()
1105{
1106 NTSTATUS Status = KeWaitForSingleObject(&g_VBoxUsbMonGlobals.OpenSynchEvent,
1107 Executive, KernelMode,
1108 FALSE, /* BOOLEAN Alertable */
1109 NULL /* IN PLARGE_INTEGER Timeout */
1110 );
1111 AssertRelease(Status == STATUS_SUCCESS);
1112
1113 do
1114 {
1115 if (--g_VBoxUsbMonGlobals.cOpens)
1116 break;
1117
1118 Status = vboxUsbMonHookUninstall();
1119
1120 NTSTATUS tmpStatus = VBoxUsbFltTerm();
1121 if (!NT_SUCCESS(tmpStatus))
1122 {
1123 /* this means a driver state is screwed up, KeBugCheckEx here ? */
1124 AssertReleaseFailed();
1125 }
1126 } while (0);
1127
1128 KeSetEvent(&g_VBoxUsbMonGlobals.OpenSynchEvent, 0, FALSE);
1129
1130 return Status;
1131}
1132
1133static NTSTATUS vboxUsbMonCheckInitStuff()
1134{
1135 NTSTATUS Status = KeWaitForSingleObject(&g_VBoxUsbMonGlobals.OpenSynchEvent,
1136 Executive, KernelMode,
1137 FALSE, /* BOOLEAN Alertable */
1138 NULL /* IN PLARGE_INTEGER Timeout */
1139 );
1140 if (Status == STATUS_SUCCESS)
1141 {
1142 do
1143 {
1144 if (g_VBoxUsbMonGlobals.cOpens++)
1145 {
1146 LOG(("opens: %d, success", g_VBoxUsbMonGlobals.cOpens));
1147 break;
1148 }
1149
1150 Status = VBoxUsbFltInit();
1151 if (NT_SUCCESS(Status))
1152 {
1153 Status = vboxUsbMonHookCheckInit();
1154 if (NT_SUCCESS(Status))
1155 {
1156 Status = vboxUsbMonHookInstall();
1157 if (NT_SUCCESS(Status))
1158 {
1159 Status = STATUS_SUCCESS;
1160 LOG(("succeded!!"));
1161 break;
1162 }
1163 else
1164 {
1165 WARN(("vboxUsbMonHookInstall failed, Status (0x%x)", Status));
1166 }
1167 }
1168 else
1169 {
1170 WARN(("vboxUsbMonHookCheckInit failed, Status (0x%x)", Status));
1171 }
1172 VBoxUsbFltTerm();
1173 }
1174 else
1175 {
1176 WARN(("VBoxUsbFltInit failed, Status (0x%x)", Status));
1177 }
1178
1179 --g_VBoxUsbMonGlobals.cOpens;
1180 Assert(!g_VBoxUsbMonGlobals.cOpens);
1181 } while (0);
1182
1183 KeSetEvent(&g_VBoxUsbMonGlobals.OpenSynchEvent, 0, FALSE);
1184 }
1185 else
1186 {
1187 WARN(("KeWaitForSingleObject failed, Status (0x%x)", Status));
1188 }
1189 return Status;
1190}
1191
1192static NTSTATUS vboxUsbMonContextCreate(PVBOXUSBMONCTX *ppCtx)
1193{
1194 NTSTATUS Status;
1195 *ppCtx = NULL;
1196 PVBOXUSBMONCTX pFileCtx = (PVBOXUSBMONCTX)VBoxUsbMonMemAllocZ(sizeof (*pFileCtx));
1197 if (pFileCtx)
1198 {
1199 Status = vboxUsbMonCheckInitStuff();
1200 if (Status == STATUS_SUCCESS)
1201 {
1202 Status = VBoxUsbFltCreate(&pFileCtx->FltCtx);
1203 if (Status == STATUS_SUCCESS)
1204 {
1205 *ppCtx = pFileCtx;
1206 LOG(("succeeded!!"));
1207 return STATUS_SUCCESS;
1208 }
1209 else
1210 {
1211 WARN(("VBoxUsbFltCreate failed"));
1212 }
1213 vboxUsbMonCheckTermStuff();
1214 }
1215 else
1216 {
1217 WARN(("vboxUsbMonCheckInitStuff failed"));
1218 }
1219 VBoxUsbMonMemFree(pFileCtx);
1220 }
1221 else
1222 {
1223 WARN(("VBoxUsbMonMemAllocZ failed"));
1224 Status = STATUS_NO_MEMORY;
1225 }
1226
1227 return Status;
1228}
1229
1230static NTSTATUS vboxUsbMonContextClose(PVBOXUSBMONCTX pCtx)
1231{
1232 NTSTATUS Status = VBoxUsbFltClose(&pCtx->FltCtx);
1233 if (Status == STATUS_SUCCESS)
1234 {
1235 Status = vboxUsbMonCheckTermStuff();
1236 Assert(Status == STATUS_SUCCESS);
1237 /* ignore the failure */
1238 VBoxUsbMonMemFree(pCtx);
1239 }
1240
1241 return Status;
1242}
1243
1244static NTSTATUS _stdcall VBoxUsbMonClose(PDEVICE_OBJECT pDevObj, PIRP pIrp)
1245{
1246 PIO_STACK_LOCATION pStack = IoGetCurrentIrpStackLocation(pIrp);
1247 PFILE_OBJECT pFileObj = pStack->FileObject;
1248 Assert(pFileObj->FsContext);
1249 PVBOXUSBMONCTX pCtx = (PVBOXUSBMONCTX)pFileObj->FsContext;
1250
1251 LOG(("VBoxUsbMonClose"));
1252
1253 NTSTATUS Status = vboxUsbMonContextClose(pCtx);
1254 if (Status != STATUS_SUCCESS)
1255 {
1256 WARN(("vboxUsbMonContextClose failed, Status (0x%x), prefent unload", Status));
1257 if (!InterlockedExchange(&g_VBoxUsbMonGlobals.ulPreventUnloadOn, 1))
1258 {
1259 LOGREL(("ulPreventUnloadOn not set, preventing unload"));
1260 UNICODE_STRING UniName;
1261 PDEVICE_OBJECT pTmpDevObj;
1262 RtlInitUnicodeString(&UniName, USBMON_DEVICE_NAME_NT);
1263 NTSTATUS tmpStatus = IoGetDeviceObjectPointer(&UniName, FILE_ALL_ACCESS, &g_VBoxUsbMonGlobals.pPreventUnloadFileObj, &pTmpDevObj);
1264 AssertRelease(NT_SUCCESS(tmpStatus));
1265 AssertRelease(pTmpDevObj == pDevObj);
1266 }
1267 else
1268 {
1269 WARN(("ulPreventUnloadOn already set"));
1270 }
1271 LOG(("success!!"));
1272 Status = STATUS_SUCCESS;
1273 }
1274 pFileObj->FsContext = NULL;
1275 pIrp->IoStatus.Status = Status;
1276 pIrp->IoStatus.Information = 0;
1277 IoCompleteRequest(pIrp, IO_NO_INCREMENT);
1278 return Status;
1279}
1280
1281
1282static NTSTATUS _stdcall VBoxUsbMonCreate(PDEVICE_OBJECT pDevObj, PIRP pIrp)
1283{
1284 PIO_STACK_LOCATION pStack = IoGetCurrentIrpStackLocation(pIrp);
1285 PFILE_OBJECT pFileObj = pStack->FileObject;
1286 NTSTATUS Status;
1287
1288 LOG(("VBoxUSBMonCreate"));
1289
1290 if (pStack->Parameters.Create.Options & FILE_DIRECTORY_FILE)
1291 {
1292 WARN(("trying to open as a directory"));
1293 pIrp->IoStatus.Status = STATUS_NOT_A_DIRECTORY;
1294 pIrp->IoStatus.Information = 0;
1295 IoCompleteRequest(pIrp, IO_NO_INCREMENT);
1296 return STATUS_NOT_A_DIRECTORY;
1297 }
1298
1299 pFileObj->FsContext = NULL;
1300 PVBOXUSBMONCTX pCtx = NULL;
1301 Status = vboxUsbMonContextCreate(&pCtx);
1302 if (Status == STATUS_SUCCESS)
1303 {
1304 Assert(pCtx);
1305 pFileObj->FsContext = pCtx;
1306 }
1307 else
1308 {
1309 WARN(("vboxUsbMonContextCreate failed Status (0x%x)", Status));
1310 }
1311
1312 pIrp->IoStatus.Status = Status;
1313 pIrp->IoStatus.Information = 0;
1314 IoCompleteRequest(pIrp, IO_NO_INCREMENT);
1315 return Status;
1316}
1317
1318static int VBoxUsbMonSetNotifyEvent(PVBOXUSBMONCTX pContext, HANDLE hEvent)
1319{
1320 int rc = VBoxUsbFltSetNotifyEvent(&pContext->FltCtx, hEvent);
1321 return rc;
1322}
1323
1324static int VBoxUsbMonFltAdd(PVBOXUSBMONCTX pContext, PUSBFILTER pFilter, uintptr_t *pId)
1325{
1326#ifdef VBOXUSBMON_DBG_NO_FILTERS
1327 static uintptr_t idDummy = 1;
1328 *pId = idDummy;
1329 ++idDummy;
1330 return VINF_SUCCESS;
1331#else
1332 int rc = VBoxUsbFltAdd(&pContext->FltCtx, pFilter, pId);
1333 return rc;
1334#endif
1335}
1336
1337static int VBoxUsbMonFltRemove(PVBOXUSBMONCTX pContext, uintptr_t uId)
1338{
1339#ifdef VBOXUSBMON_DBG_NO_FILTERS
1340 return VINF_SUCCESS;
1341#else
1342 int rc = VBoxUsbFltRemove(&pContext->FltCtx, uId);
1343 return rc;
1344#endif
1345}
1346
1347static NTSTATUS VBoxUsbMonRunFilters(PVBOXUSBMONCTX pContext)
1348{
1349 NTSTATUS Status = VBoxUsbFltFilterCheck(&pContext->FltCtx);
1350 return Status;
1351}
1352
1353static NTSTATUS VBoxUsbMonGetDevice(PVBOXUSBMONCTX pContext, HVBOXUSBDEVUSR hDevice, PUSBSUP_GETDEV_MON pInfo)
1354{
1355 NTSTATUS Status = VBoxUsbFltGetDevice(&pContext->FltCtx, hDevice, pInfo);
1356 return Status;
1357}
1358
1359static NTSTATUS vboxUsbMonIoctlDispatch(PVBOXUSBMONCTX pContext, ULONG Ctl, PVOID pvBuffer, ULONG cbInBuffer, ULONG cbOutBuffer, ULONG_PTR* pInfo)
1360{
1361 NTSTATUS Status = STATUS_SUCCESS;
1362 ULONG_PTR Info = 0;
1363 switch (Ctl)
1364 {
1365 case SUPUSBFLT_IOCTL_GET_VERSION:
1366 {
1367 PUSBSUP_VERSION pOut = (PUSBSUP_VERSION)pvBuffer;
1368
1369 LOG(("SUPUSBFLT_IOCTL_GET_VERSION"));
1370 if (!pvBuffer || cbOutBuffer != sizeof(*pOut) || cbInBuffer != 0)
1371 {
1372 WARN(("SUPUSBFLT_IOCTL_GET_VERSION: Invalid input/output sizes. cbIn=%d expected %d. cbOut=%d expected %d.",
1373 cbInBuffer, 0, cbOutBuffer, sizeof (*pOut)));
1374 Status = STATUS_INVALID_PARAMETER;
1375 break;
1376 }
1377 pOut->u32Major = USBMON_MAJOR_VERSION;
1378 pOut->u32Minor = USBMON_MINOR_VERSION;
1379 Info = sizeof (*pOut);
1380 ASSERT_WARN(Status == STATUS_SUCCESS, ("unexpected status, 0x%x", Status));
1381 break;
1382 }
1383
1384 case SUPUSBFLT_IOCTL_ADD_FILTER:
1385 {
1386 PUSBFILTER pFilter = (PUSBFILTER)pvBuffer;
1387 PUSBSUP_FLTADDOUT pOut = (PUSBSUP_FLTADDOUT)pvBuffer;
1388 uintptr_t uId = 0;
1389 int rc;
1390 if (RT_UNLIKELY(!pvBuffer || cbInBuffer != sizeof (*pFilter) || cbOutBuffer != sizeof (*pOut)))
1391 {
1392 WARN(("SUPUSBFLT_IOCTL_ADD_FILTER: Invalid input/output sizes. cbIn=%d expected %d. cbOut=%d expected %d.",
1393 cbInBuffer, sizeof (*pFilter), cbOutBuffer, sizeof (*pOut)));
1394 Status = STATUS_INVALID_PARAMETER;
1395 break;
1396 }
1397
1398 rc = VBoxUsbMonFltAdd(pContext, pFilter, &uId);
1399 pOut->rc = rc;
1400 pOut->uId = uId;
1401 Info = sizeof (*pOut);
1402 ASSERT_WARN(Status == STATUS_SUCCESS, ("unexpected status, 0x%x", Status));
1403 break;
1404 }
1405
1406 case SUPUSBFLT_IOCTL_REMOVE_FILTER:
1407 {
1408 uintptr_t *pIn = (uintptr_t *)pvBuffer;
1409 int *pRc = (int *)pvBuffer;
1410
1411 if (!pvBuffer || cbInBuffer != sizeof (*pIn) || (cbOutBuffer && cbOutBuffer != sizeof (*pRc)))
1412 {
1413 WARN(("SUPUSBFLT_IOCTL_REMOVE_FILTER: Invalid input/output sizes. cbIn=%d expected %d. cbOut=%d expected %d.",
1414 cbInBuffer, sizeof (*pIn), cbOutBuffer, 0));
1415 Status = STATUS_INVALID_PARAMETER;
1416 break;
1417 }
1418 LOG(("SUPUSBFLT_IOCTL_REMOVE_FILTER %x", *pIn));
1419 int rc = VBoxUsbMonFltRemove(pContext, *pIn);
1420 if (cbOutBuffer)
1421 {
1422 /* we've validated that already */
1423 Assert(cbOutBuffer == *pRc);
1424 *pRc = rc;
1425 Info = sizeof (*pRc);
1426 }
1427 ASSERT_WARN(Status == STATUS_SUCCESS, ("unexpected status, 0x%x", Status));
1428 break;
1429 }
1430
1431 case SUPUSBFLT_IOCTL_RUN_FILTERS:
1432 {
1433 if (pvBuffer || cbInBuffer || cbOutBuffer)
1434 {
1435 WARN(("SUPUSBFLT_IOCTL_RUN_FILTERS: Invalid input/output sizes. cbIn=%d expected %d. cbOut=%d expected %d.",
1436 cbInBuffer, 0, cbOutBuffer, 0));
1437 Status = STATUS_INVALID_PARAMETER;
1438 break;
1439 }
1440 LOG(("SUPUSBFLT_IOCTL_RUN_FILTERS "));
1441 Status = VBoxUsbMonRunFilters(pContext);
1442 ASSERT_WARN(Status != STATUS_PENDING, ("status pending!"));
1443 break;
1444 }
1445
1446 case SUPUSBFLT_IOCTL_GET_DEVICE:
1447 {
1448 HVBOXUSBDEVUSR hDevice = *((HVBOXUSBDEVUSR*)pvBuffer);
1449 PUSBSUP_GETDEV_MON pOut = (PUSBSUP_GETDEV_MON)pvBuffer;
1450 if (!pvBuffer || cbInBuffer != sizeof (hDevice) || cbOutBuffer < sizeof (*pOut))
1451 {
1452 WARN(("SUPUSBFLT_IOCTL_GET_DEVICE: Invalid input/output sizes. cbIn=%d expected %d. cbOut=%d expected >= %d.",
1453 cbInBuffer, sizeof (hDevice), cbOutBuffer, sizeof (*pOut)));
1454 Status = STATUS_INVALID_PARAMETER;
1455 break;
1456 }
1457
1458 Status = VBoxUsbMonGetDevice(pContext, hDevice, pOut);
1459
1460 if (NT_SUCCESS(Status))
1461 {
1462 Info = sizeof (*pOut);
1463 }
1464 else
1465 {
1466 WARN(("VBoxUsbMonGetDevice fail 0x%x", Status));
1467 }
1468 break;
1469 }
1470
1471 case SUPUSBFLT_IOCTL_SET_NOTIFY_EVENT:
1472 {
1473 PUSBSUP_SET_NOTIFY_EVENT pSne = (PUSBSUP_SET_NOTIFY_EVENT)pvBuffer;
1474 if (!pvBuffer || cbInBuffer != sizeof (*pSne) || cbOutBuffer != sizeof (*pSne))
1475 {
1476 WARN(("SUPUSBFLT_IOCTL_SET_NOTIFY_EVENT: Invalid input/output sizes. cbIn=%d expected %d. cbOut=%d expected %d.",
1477 cbInBuffer, sizeof (*pSne), cbOutBuffer, sizeof (*pSne)));
1478 Status = STATUS_INVALID_PARAMETER;
1479 break;
1480 }
1481
1482 pSne->u.rc = VBoxUsbMonSetNotifyEvent(pContext, pSne->u.hEvent);
1483 Info = sizeof (*pSne);
1484 ASSERT_WARN(Status == STATUS_SUCCESS, ("unexpected status, 0x%x", Status));
1485 break;
1486 }
1487
1488 default:
1489 WARN(("Unknown code 0x%x", Ctl));
1490 Status = STATUS_INVALID_PARAMETER;
1491 break;
1492 }
1493
1494 ASSERT_WARN(Status != STATUS_PENDING, ("Status pending!"));
1495
1496 *pInfo = Info;
1497 return Status;
1498}
1499
1500static NTSTATUS _stdcall VBoxUsbMonDeviceControl(PDEVICE_OBJECT pDevObj, PIRP pIrp)
1501{
1502 ULONG_PTR Info = 0;
1503 NTSTATUS Status = IoAcquireRemoveLock(&g_VBoxUsbMonGlobals.RmLock, pDevObj);
1504 if (NT_SUCCESS(Status))
1505 {
1506 PIO_STACK_LOCATION pSl = IoGetCurrentIrpStackLocation(pIrp);
1507 PFILE_OBJECT pFileObj = pSl->FileObject;
1508 Assert(pFileObj);
1509 Assert(pFileObj->FsContext);
1510 PVBOXUSBMONCTX pCtx = (PVBOXUSBMONCTX)pFileObj->FsContext;
1511 Assert(pCtx);
1512 Status = vboxUsbMonIoctlDispatch(pCtx,
1513 pSl->Parameters.DeviceIoControl.IoControlCode,
1514 pIrp->AssociatedIrp.SystemBuffer,
1515 pSl->Parameters.DeviceIoControl.InputBufferLength,
1516 pSl->Parameters.DeviceIoControl.OutputBufferLength,
1517 &Info);
1518 ASSERT_WARN(Status != STATUS_PENDING, ("Status pending"));
1519
1520 IoReleaseRemoveLock(&g_VBoxUsbMonGlobals.RmLock, pDevObj);
1521 }
1522 else
1523 {
1524 WARN(("IoAcquireRemoveLock failed Status (0x%x)", Status));
1525 }
1526
1527 pIrp->IoStatus.Information = Info;
1528 pIrp->IoStatus.Status = Status;
1529 IoCompleteRequest (pIrp, IO_NO_INCREMENT);
1530 return Status;
1531}
1532
1533static NTSTATUS vboxUsbMonInternalIoctlDispatch(ULONG Ctl, PVOID pvBuffer, ULONG_PTR *pInfo)
1534{
1535 NTSTATUS Status = STATUS_SUCCESS;
1536 *pInfo = 0;
1537 switch (Ctl)
1538 {
1539 case VBOXUSBIDC_INTERNAL_IOCTL_GET_VERSION:
1540 {
1541 PVBOXUSBIDC_VERSION pOut = (PVBOXUSBIDC_VERSION)pvBuffer;
1542
1543 LOG(("VBOXUSBIDC_INTERNAL_IOCTL_GET_VERSION"));
1544 if (!pvBuffer)
1545 {
1546 WARN(("VBOXUSBIDC_INTERNAL_IOCTL_GET_VERSION: Buffer is NULL"));
1547 Status = STATUS_INVALID_PARAMETER;
1548 break;
1549 }
1550 pOut->u32Major = VBOXUSBIDC_VERSION_MAJOR;
1551 pOut->u32Minor = VBOXUSBIDC_VERSION_MINOR;
1552 ASSERT_WARN(Status == STATUS_SUCCESS, ("unexpected status, 0x%x", Status));
1553 break;
1554 }
1555
1556 case VBOXUSBIDC_INTERNAL_IOCTL_PROXY_STARTUP:
1557 {
1558 PVBOXUSBIDC_PROXY_STARTUP pOut = (PVBOXUSBIDC_PROXY_STARTUP)pvBuffer;
1559
1560 LOG(("VBOXUSBIDC_INTERNAL_IOCTL_PROXY_STARTUP"));
1561 if (!pvBuffer)
1562 {
1563 WARN(("VBOXUSBIDC_INTERNAL_IOCTL_PROXY_STARTUP: Buffer is NULL"));
1564 Status = STATUS_INVALID_PARAMETER;
1565 break;
1566 }
1567
1568 pOut->u.hDev = VBoxUsbFltProxyStarted(pOut->u.pPDO);
1569 ASSERT_WARN(pOut->u.hDev, ("zero hDev"));
1570 ASSERT_WARN(Status == STATUS_SUCCESS, ("unexpected status, 0x%x", Status));
1571 break;
1572 }
1573
1574 case VBOXUSBIDC_INTERNAL_IOCTL_PROXY_TEARDOWN:
1575 {
1576 PVBOXUSBIDC_PROXY_TEARDOWN pOut = (PVBOXUSBIDC_PROXY_TEARDOWN)pvBuffer;
1577
1578 LOG(("VBOXUSBIDC_INTERNAL_IOCTL_PROXY_TEARDOWN"));
1579 if (!pvBuffer)
1580 {
1581 WARN(("VBOXUSBIDC_INTERNAL_IOCTL_PROXY_TEARDOWN: Buffer is NULL"));
1582 Status = STATUS_INVALID_PARAMETER;
1583 break;
1584 }
1585
1586 ASSERT_WARN(pOut->hDev, ("zero hDev"));
1587 VBoxUsbFltProxyStopped(pOut->hDev);
1588 ASSERT_WARN(Status == STATUS_SUCCESS, ("unexpected status, 0x%x", Status));
1589 break;
1590 }
1591
1592 default:
1593 {
1594 WARN(("Unknown code 0x%x", Ctl));
1595 Status = STATUS_INVALID_PARAMETER;
1596 break;
1597 }
1598 }
1599
1600 return Status;
1601}
1602
1603static NTSTATUS _stdcall VBoxUsbMonInternalDeviceControl(PDEVICE_OBJECT pDevObj, PIRP pIrp)
1604{
1605 ULONG_PTR Info = 0;
1606 NTSTATUS Status = IoAcquireRemoveLock(&g_VBoxUsbMonGlobals.RmLock, pDevObj);
1607 if (NT_SUCCESS(Status))
1608 {
1609 PIO_STACK_LOCATION pSl = IoGetCurrentIrpStackLocation(pIrp);
1610 Status = vboxUsbMonInternalIoctlDispatch(pSl->Parameters.DeviceIoControl.IoControlCode,
1611 pSl->Parameters.Others.Argument1,
1612 &Info);
1613 Assert(Status != STATUS_PENDING);
1614
1615 IoReleaseRemoveLock(&g_VBoxUsbMonGlobals.RmLock, pDevObj);
1616 }
1617
1618 pIrp->IoStatus.Information = Info;
1619 pIrp->IoStatus.Status = Status;
1620 IoCompleteRequest (pIrp, IO_NO_INCREMENT);
1621 return Status;
1622}
1623
1624/**
1625 * Unload the driver.
1626 *
1627 * @param pDrvObj Driver object.
1628 */
1629static void _stdcall VBoxUsbMonUnload(PDRIVER_OBJECT pDrvObj)
1630{
1631 LOG(("VBoxUSBMonUnload pDrvObj (0x%p)", pDrvObj));
1632
1633 IoReleaseRemoveLockAndWait(&g_VBoxUsbMonGlobals.RmLock, &g_VBoxUsbMonGlobals);
1634
1635 Assert(!g_VBoxUsbMonGlobals.cOpens);
1636
1637 UNICODE_STRING DosName;
1638 RtlInitUnicodeString(&DosName, USBMON_DEVICE_NAME_DOS);
1639 NTSTATUS rc = IoDeleteSymbolicLink(&DosName);
1640
1641 IoDeleteDevice(g_VBoxUsbMonGlobals.pDevObj);
1642
1643 /* cleanup the logger */
1644 PRTLOGGER pLogger = RTLogRelSetDefaultInstance(NULL);
1645 if (pLogger)
1646 {
1647 RTLogDestroy(pLogger);
1648 }
1649 pLogger = RTLogSetDefaultInstance(NULL);
1650 if (pLogger)
1651 {
1652 RTLogDestroy(pLogger);
1653 }
1654}
1655
1656RT_C_DECLS_BEGIN
1657NTSTATUS _stdcall DriverEntry(PDRIVER_OBJECT pDrvObj, PUNICODE_STRING pRegPath);
1658RT_C_DECLS_END
1659
1660/**
1661 * Driver entry point.
1662 *
1663 * @returns appropriate status code.
1664 * @param pDrvObj Pointer to driver object.
1665 * @param pRegPath Registry base path.
1666 */
1667NTSTATUS _stdcall DriverEntry(PDRIVER_OBJECT pDrvObj, PUNICODE_STRING pRegPath)
1668{
1669#ifdef VBOX_USB_WITH_VERBOSE_LOGGING
1670 RTLogGroupSettings(0, "+default.e.l.f.l2.l3");
1671 RTLogDestinations(0, "debugger");
1672#endif
1673
1674 LOGREL(("Built %s %s", __DATE__, __TIME__));
1675
1676 memset (&g_VBoxUsbMonGlobals, 0, sizeof (g_VBoxUsbMonGlobals));
1677 KeInitializeEvent(&g_VBoxUsbMonGlobals.OpenSynchEvent, SynchronizationEvent, TRUE /* signaled */);
1678 IoInitializeRemoveLock(&g_VBoxUsbMonGlobals.RmLock, VBOXUSBMON_MEMTAG, 1, 100);
1679 UNICODE_STRING DevName;
1680 PDEVICE_OBJECT pDevObj;
1681 /* create the device */
1682 RtlInitUnicodeString(&DevName, USBMON_DEVICE_NAME_NT);
1683 NTSTATUS Status = IoAcquireRemoveLock(&g_VBoxUsbMonGlobals.RmLock, &g_VBoxUsbMonGlobals);
1684 if (NT_SUCCESS(Status))
1685 {
1686 Status = IoCreateDevice(pDrvObj, sizeof (VBOXUSBMONINS), &DevName, FILE_DEVICE_UNKNOWN, 0, FALSE, &pDevObj);
1687 if (NT_SUCCESS(Status))
1688 {
1689 UNICODE_STRING DosName;
1690 RtlInitUnicodeString(&DosName, USBMON_DEVICE_NAME_DOS);
1691 Status = IoCreateSymbolicLink(&DosName, &DevName);
1692 if (NT_SUCCESS(Status))
1693 {
1694 PVBOXUSBMONINS pDevExt = (PVBOXUSBMONINS)pDevObj->DeviceExtension;
1695 memset(pDevExt, 0, sizeof(*pDevExt));
1696
1697 pDrvObj->DriverUnload = VBoxUsbMonUnload;
1698 pDrvObj->MajorFunction[IRP_MJ_CREATE] = VBoxUsbMonCreate;
1699 pDrvObj->MajorFunction[IRP_MJ_CLOSE] = VBoxUsbMonClose;
1700 pDrvObj->MajorFunction[IRP_MJ_DEVICE_CONTROL] = VBoxUsbMonDeviceControl;
1701 pDrvObj->MajorFunction[IRP_MJ_INTERNAL_DEVICE_CONTROL] = VBoxUsbMonInternalDeviceControl;
1702
1703 g_VBoxUsbMonGlobals.pDevObj = pDevObj;
1704 LOG(("VBoxUSBMon::DriverEntry returning STATUS_SUCCESS"));
1705 return STATUS_SUCCESS;
1706 }
1707 IoDeleteDevice(pDevObj);
1708 }
1709 IoReleaseRemoveLockAndWait(&g_VBoxUsbMonGlobals.RmLock, &g_VBoxUsbMonGlobals);
1710 }
1711
1712 return Status;
1713}
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