USBIP解读及源码分析
+ -

USBIP 驱动入口DriverEntry和vhci_driverUnload函数

2022-02-23 689 0

无论该驱动被安装几次,DriverEntry和卸载函数只执行一次。

DriverEntry

Windows驱动和应用层一样,也有个入口函数,只是这个名字叫做DriverEntry。在DriverEntry中应实现的是该驱动各个IRP类类型的回调函数。

  1. PAGEABLE NTSTATUS
  2. DriverEntry(__in PDRIVER_OBJECT drvobj, __in PUNICODE_STRING RegistryPath)
  3. {
  4. KdBreakPoint();
  5. DBGI(DBG_GENERAL, "DriverEntry: Enter\n");
  6. ExInitializeNPagedLookasideList(&g_lookaside, NULL,NULL, 0, sizeof(struct urb_req), 'USBV', 0);
  7. // Save the RegistryPath for WMI.
  8. Globals.RegistryPath.MaximumLength = RegistryPath->Length + sizeof(UNICODE_NULL);
  9. Globals.RegistryPath.Length = RegistryPath->Length;
  10. Globals.RegistryPath.Buffer = ExAllocatePoolWithTag(PagedPool, Globals.RegistryPath.MaximumLength, USBIP_VHCI_POOL_TAG);
  11. if (!Globals.RegistryPath.Buffer) {
  12. ExDeleteNPagedLookasideList(&g_lookaside);
  13. return STATUS_INSUFFICIENT_RESOURCES;
  14. }
  15. DBGI(DBG_GENERAL, "RegistryPath %p\r\n", RegistryPath);
  16. RtlCopyUnicodeString(&Globals.RegistryPath, RegistryPath);
  17. // Set entry points into the driver
  18. drvobj->MajorFunction[IRP_MJ_CREATE] = vhci_create;
  19. drvobj->MajorFunction[IRP_MJ_CLEANUP] = vhci_cleanup;
  20. drvobj->MajorFunction[IRP_MJ_CLOSE] = vhci_close;
  21. drvobj->MajorFunction[IRP_MJ_READ] = vhci_read;
  22. drvobj->MajorFunction[IRP_MJ_WRITE] = vhci_write;
  23. drvobj->MajorFunction[IRP_MJ_PNP] = vhci_pnp;
  24. drvobj->MajorFunction[IRP_MJ_POWER] = vhci_power;
  25. drvobj->MajorFunction[IRP_MJ_DEVICE_CONTROL] = vhci_ioctl;
  26. drvobj->MajorFunction[IRP_MJ_INTERNAL_DEVICE_CONTROL] = vhci_internal_ioctl;
  27. drvobj->MajorFunction[IRP_MJ_SYSTEM_CONTROL] = vhci_system_control;
  28. drvobj->DriverUnload = vhci_driverUnload;
  29. drvobj->DriverExtension->AddDevice = vhci_add_device;
  30. DBGI(DBG_GENERAL, "DriverEntry: Leave\n");
  31. return STATUS_SUCCESS;
  32. }

DriverEntry的入口函数有两个,分别为该驱动的对象指针,另一个为该驱动的服务注册表路径。如这里的注册表路径为:

  1. \REGISTRY\MACHINE\SYSTEM\ControlSet001\Services\usbip_vhci

而驱动对象指针,可以通过windbg查看其对应的结构体

  1. 2: kd> dt _DRIVER_OBJECT 0xffffbc88`3db017d0
  2. usbip_vhci!_DRIVER_OBJECT
  3. +0x000 Type : 0n4
  4. +0x002 Size : 0n336
  5. +0x008 DeviceObject : (null)
  6. +0x010 Flags : 2
  7. +0x018 DriverStart : 0xfffff807`b5c30000 Void
  8. +0x020 DriverSize : 0x1f000
  9. +0x028 DriverSection : 0xffffbc88`3d0afb40 Void
  10. +0x030 DriverExtension : 0xffffbc88`3db01920 _DRIVER_EXTENSION
  11. +0x038 DriverName : _UNICODE_STRING "\Driver\usbip_vhci"
  12. +0x048 HardwareDatabase : 0xfffff803`655c2eb8 _UNICODE_STRING "\REGISTRY\MACHINE\HARDWARE\DESCRIPTION\SYSTEM"
  13. +0x050 FastIoDispatch : (null)
  14. +0x058 DriverInit : 0xfffff807`b5c38050 long usbip_vhci!FxDriverEntry+0
  15. +0x060 DriverStartIo : (null)
  16. +0x068 DriverUnload : (null)
  17. +0x070 MajorFunction : [28] 0xfffff803`64ebf6b4 long nt!KeInsertQueue+0
  1. 2: kd> dt _DRIVER_EXTENSION 0xffffbc88`3db01920
  2. usbip_vhci!_DRIVER_EXTENSION
  3. +0x000 DriverObject : 0xffffbc88`3db017d0 _DRIVER_OBJECT
  4. +0x008 AddDevice : (null)
  5. +0x010 Count : 0
  6. +0x018 ServiceKeyName : _UNICODE_STRING "usbip_vhci"

可以看到其成员变量MajorFunction是一个数组,用于指示各IRP类型的回调指针。

当然这里在入口函数中将注册表存在全局变量Globals中。

  1. typedef struct _GLOBALS
  2. {
  3. // Path to the driver's Services Key in the registry
  4. UNICODE_STRING RegistryPath;
  5. } GLOBALS;
  6. GLOBALS Globals;

vhci_driverUnload

该函数比较简单,其功能和DriverEntry对应,用于释放DriverEntry中申请的资源,这里为注册表存储的路径

  1. static PAGEABLE VOID
  2. vhci_driverUnload(__in PDRIVER_OBJECT drvobj)
  3. {
  4. UNREFERENCED_PARAMETER(drvobj);
  5. PAGED_CODE();
  6. DBGI(DBG_GENERAL, "Unload\n");
  7. ExDeleteNPagedLookasideList(&g_lookaside);
  8. //
  9. // All the device objects should be gone.
  10. //
  11. ASSERT(NULL == drvobj->DeviceObject);
  12. //
  13. // Here we free all the resources allocated in the DriverEntry
  14. //
  15. if (Globals.RegistryPath.Buffer)
  16. ExFreePool(Globals.RegistryPath.Buffer);
  17. }

NPAGED_LOOKASIDE_LIST

在DriverEntry和卸载函数中,可以看到也有一个变量NPAGED_LOOKASIDE_LIST,用于二级内存管理,适用于频繁的申请和释放内存。由于需要处理各种URB,故这里使用了NPAGED_LOOKASIDE_LIST

  1. NPAGED_LOOKASIDE_LIST g_lookaside;
HID人机交互QQ群:564808376    UAC音频QQ群:218581009    UVC相机QQ群:331552032    BOT&UASP大容量存储QQ群:258159197    STC-USB单片机QQ群:315457461    USB技术交流QQ群2:580684376    USB技术交流QQ群:952873936   

0 篇笔记 写笔记

USBIP 驱动入口DriverEntry和vhci_driverUnload函数
无论该驱动被安装几次,DriverEntry和卸载函数只执行一次。DriverEntryWindows驱动和应用层一样,也有个入口函数,只是这个名字叫做DriverEntry。在DriverEntry中应实现的是该驱动各个IRP类类型的回调函数。PAGEABLE NTSTATUSDriverE......
Windows系统USB相关注册表路径功能说明
usbflags计算机HKEY_LOCAL_MACHINESYSTEMCurrentControlSetControlusbflags这个路径下会把所以有USB设备按PID、VID和BCDDevice组成一段字符串来作为子目录存在:,如下图:040360100500中的0403是USB......
通过注册表自定义摄像头UVC名称
相机在设备管理器的照料相机或者图像设备分类下:Image :{6bdd1fc6-810f-11d0-bec7-08002be2092f}Camera :{ca3e7ab9-b4c3-4ae6-8251-579ef933890f}他们的历史关系详见:https://www.usbzh.com/ar......
USB音频设备注册表HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\MediaCategories下GUID分析
windows系统下的注册表:计算机HKEY_LOCAL_MACHINESYSTEMCurrentControlSetControlMediaCategories在很多的GUID,从MediaCategories来看,是多媒体设备的目录分类,所以以下的GUID应与多媒体设备相关。该目......
USB控制器驱动注册表键名称DriverKeyName
使用IOCTL_GET_HCD_DRIVERKEY_NAME获取USB驱动注册表键值名称。DriverKeyName是一个Windows驱动程序的注册表键名。在Windows操作系统中,驱动程序使用注册表来存储设备和驱动程序的相关信息。DriverKeyName指的是驱动程序在注册表中的键名,它通......
关注公众号
  • HID人机交互
  • Linux&USB
  • UAC音频
  • TYPE-C
  • USB规范
  • USB大容量存储
  • USB百科
  • USB周边
  • UVC摄像头
  • Windows系统USB
  • 音视频博客
  • 取消
    感谢您的支持,我会继续努力的!
    扫码支持
    扫码打赏,你说多少就多少

    打开支付宝扫一扫,即可进行扫码打赏哦

    您的支持,是我们前进的动力!