USBIP解读及源码分析
+ -

USBIP 驱动入口DriverEntry和vhci_driverUnload函数

2022-02-23 482 0

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

DriverEntry

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

PAGEABLE NTSTATUS
DriverEntry(__in PDRIVER_OBJECT drvobj, __in PUNICODE_STRING RegistryPath)
{
    KdBreakPoint();
    DBGI(DBG_GENERAL, "DriverEntry: Enter\n");

    ExInitializeNPagedLookasideList(&g_lookaside, NULL,NULL, 0, sizeof(struct urb_req), 'USBV', 0);

    // Save the RegistryPath for WMI.
    Globals.RegistryPath.MaximumLength = RegistryPath->Length + sizeof(UNICODE_NULL);
    Globals.RegistryPath.Length = RegistryPath->Length;
    Globals.RegistryPath.Buffer = ExAllocatePoolWithTag(PagedPool, Globals.RegistryPath.MaximumLength, USBIP_VHCI_POOL_TAG);

    if (!Globals.RegistryPath.Buffer) {
        ExDeleteNPagedLookasideList(&g_lookaside);
        return STATUS_INSUFFICIENT_RESOURCES;
    }

    DBGI(DBG_GENERAL, "RegistryPath %p\r\n", RegistryPath);

    RtlCopyUnicodeString(&Globals.RegistryPath, RegistryPath);

    // Set entry points into the driver
    drvobj->MajorFunction[IRP_MJ_CREATE] = vhci_create;
    drvobj->MajorFunction[IRP_MJ_CLEANUP] = vhci_cleanup;
    drvobj->MajorFunction[IRP_MJ_CLOSE] = vhci_close;
    drvobj->MajorFunction[IRP_MJ_READ] = vhci_read;
    drvobj->MajorFunction[IRP_MJ_WRITE] = vhci_write;
    drvobj->MajorFunction[IRP_MJ_PNP] = vhci_pnp;
    drvobj->MajorFunction[IRP_MJ_POWER] = vhci_power;
    drvobj->MajorFunction[IRP_MJ_DEVICE_CONTROL] = vhci_ioctl;
    drvobj->MajorFunction[IRP_MJ_INTERNAL_DEVICE_CONTROL] = vhci_internal_ioctl;
    drvobj->MajorFunction[IRP_MJ_SYSTEM_CONTROL] = vhci_system_control;
    drvobj->DriverUnload = vhci_driverUnload;
    drvobj->DriverExtension->AddDevice = vhci_add_device;

    DBGI(DBG_GENERAL, "DriverEntry: Leave\n");

    return STATUS_SUCCESS;
}

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

\REGISTRY\MACHINE\SYSTEM\ControlSet001\Services\usbip_vhci

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

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

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

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

typedef struct _GLOBALS
{
    // Path to the driver's Services Key in the registry
    UNICODE_STRING RegistryPath;
} GLOBALS;

GLOBALS Globals;

vhci_driverUnload

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

static PAGEABLE VOID
vhci_driverUnload(__in PDRIVER_OBJECT drvobj)
{
    UNREFERENCED_PARAMETER(drvobj);

    PAGED_CODE();

    DBGI(DBG_GENERAL, "Unload\n");

    ExDeleteNPagedLookasideList(&g_lookaside);

    //
    // All the device objects should be gone.
    //

    ASSERT(NULL == drvobj->DeviceObject);

    //
    // Here we free all the resources allocated in the DriverEntry
    //

    if (Globals.RegistryPath.Buffer)
        ExFreePool(Globals.RegistryPath.Buffer);
}

NPAGED_LOOKASIDE_LIST

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

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指的是驱动程序在注册表中的键名,它通......
关注公众号
取消
感谢您的支持,我会继续努力的!
扫码支持
扫码打赏,你说多少就多少

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

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