PtRegisterDevice的时候指定:
DispatchTable[IRP_MJ_CREATE] = DevOpen;
即,由devOpen函数处理major code 为IRP_MJ_CREATE 的 IRP请求;
用户态的CreateFile直接导致I/O Manager产生一个major code 为IRP_MJ_CREATE 的 IRP
送往passthru的驱动。因此,每次CreateFile都会“调用”devOpen函数。
而这个DevOpen函数只是在收到IRP后返回success,并不做更多其它事情。
------------------
用户态若发送一个DeviceIoControl请求,如下:
DeviceIoControl(
hAdapter,
(DWORD)IOCTL_PTUSERIO_OPEN_ADAPTER, //major code
pszAdapterName, // 物理NIC名称,作为输入参数
nBufferLength,
&NdisStatus,
sizeof( NdisStatus ),
&bytesReturned,
NULL
);
请求代码为:IOCTL_PTUSERIO_OPEN_ADAPTER,那将首先导致内核态的DevIoControl发生,
因为:
DispatchTable[IRP_MJ_DEVICE_CONTROL] = DevIoControl;
--------------------------
在DevIoControl中判断major code,如果是IOCTL_PTUSERIO_OPEN_ADAPTER,则导致执行D
evOpenAdapter函数。
-------------------------
在DevOpenAdapter函数中,主要用到IRP,根据这个IRP,可以得到一些其他信息(比如Dev
iceIoControl的输入参数,是哪个用户态的FileObject发送的这个IRP等)。
(1)由于,I/O Manager构造IRP包的时候,会把把输入参数(即物理NIC名称)存放在
irp.AssociatedIrp.SystemBuffer中,这是一个内核态的缓冲区。
所以在DevOpenAdapter函数中,根据IRP就可以得到物理NIC的名称,并调用PtL
ookupAdapterByName,找到一个Adapter,这个Adapter指向的是虚拟NIC!!
(注意,PtLookupAdapterByName中作了转换,输入的是物理NIC的名称,在函数中进行寻找
,找到匹配的虚拟NIC(该虚拟NIC的lowerdevice == 输入的物理NIC),返回的是该虚拟NI
C的handle.)
(2)接着,为这个虚拟NIC Adapter分配一个上下文环境:DevAllocateOpenContext
,做了一个指针交换,最后的结果是:
pIRP->FileObject->FsContext指向刚刚为虚拟网卡分配的上下文环境,并且可
以通过pIRP->FileObject->FsContext->adapter访问虚拟网卡。
(3)返回虚拟NIC的adapter。
DispatchTable[IRP_MJ_CREATE] = DevOpen;
即,由devOpen函数处理major code 为IRP_MJ_CREATE 的 IRP请求;
用户态的CreateFile直接导致I/O Manager产生一个major code 为IRP_MJ_CREATE 的 IRP
送往passthru的驱动。因此,每次CreateFile都会“调用”devOpen函数。
而这个DevOpen函数只是在收到IRP后返回success,并不做更多其它事情。
------------------
用户态若发送一个DeviceIoControl请求,如下:
DeviceIoControl(
hAdapter,
(DWORD)IOCTL_PTUSERIO_OPEN_ADAPTER, //major code
pszAdapterName, // 物理NIC名称,作为输入参数
nBufferLength,
&NdisStatus,
sizeof( NdisStatus ),
&bytesReturned,
NULL
);
请求代码为:IOCTL_PTUSERIO_OPEN_ADAPTER,那将首先导致内核态的DevIoControl发生,
因为:
DispatchTable[IRP_MJ_DEVICE_CONTROL] = DevIoControl;
--------------------------
在DevIoControl中判断major code,如果是IOCTL_PTUSERIO_OPEN_ADAPTER,则导致执行D
evOpenAdapter函数。
-------------------------
在DevOpenAdapter函数中,主要用到IRP,根据这个IRP,可以得到一些其他信息(比如Dev
iceIoControl的输入参数,是哪个用户态的FileObject发送的这个IRP等)。
(1)由于,I/O Manager构造IRP包的时候,会把把输入参数(即物理NIC名称)存放在
irp.AssociatedIrp.SystemBuffer中,这是一个内核态的缓冲区。
所以在DevOpenAdapter函数中,根据IRP就可以得到物理NIC的名称,并调用PtL
ookupAdapterByName,找到一个Adapter,这个Adapter指向的是虚拟NIC!!
(注意,PtLookupAdapterByName中作了转换,输入的是物理NIC的名称,在函数中进行寻找
,找到匹配的虚拟NIC(该虚拟NIC的lowerdevice == 输入的物理NIC),返回的是该虚拟NI
C的handle.)
(2)接着,为这个虚拟NIC Adapter分配一个上下文环境:DevAllocateOpenContext
,做了一个指针交换,最后的结果是:
pIRP->FileObject->FsContext指向刚刚为虚拟网卡分配的上下文环境,并且可
以通过pIRP->FileObject->FsContext->adapter访问虚拟网卡。
(3)返回虚拟NIC的adapter。