阅读:2557回复:15
请问,NDIS的下两层驱动能不能直接与外部应用程序通信??
不是通过协议驱动层。而是直接通过中间驱动或者微端口驱动。
谢谢赐教! |
|
沙发#
发布于:2007-10-11 23:40
ddk里有专门的例子。
|
|
板凳#
发布于:2007-10-01 14:30
NDIS_STATUS PtRegisterDevice( VOID )
NTSTATUS PtDispatch( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp ) NDIS_STATUS PtDeregisterDevice( VOID ) VOID PtUnload( IN PDRIVER_OBJECT DriverObject ) 楼上的意思这几个函数是为了和应用层程序通讯而设立的 ? 可以帮忙解释下NTSTATUS PtDispatch 这个函数的作用吗? |
|
|
地板#
发布于:2003-07-27 18:56
这是最easy的:
1.通讯 在NDIS IMD中用NdisMRegisterDevice,注册一个设备。然后可以通过 DeviceIoControl和应用层通讯 2。当你在APP调用API比如CreateFile ,等等时系统将你的请求转化为IRP转入KENEL中 IP都的定义如下: /*the internet paket header */ typedef struct{ u_char vandhl; /*contain the version and the internet packet header length*/ u_char tos; /* type of server */ u_short iplen; /* the internet length=internet header length+data */ u_short id; /* datagram id use to caption the only datagram */ u_short flags; /*commonly is zero */ u_char ttl; /* time to live */ u_char ipp; /* the next pocotol is udp or tcp */ u_short cksum; /* Internet header checksum */ u_long saddr; /* the source ip address */ u_long daddr; /* detination addresss */ }iphdr; /////////////////////////////////////////////////////////// w2k下的PassThru和用户态交互修改说明 一.参考资料为winXP DDK下的PassThru。如果熟悉的话就不要浪费时间看我的修改过程(太简陋了,怕大家笑话),很容易搞定的。 二.内核态的修改过程: 1.在Passthru.c中增加如下的变量定义 #define LINKNAME_STRING L\"\\\\DosDevices\\\\Passthru\" #define NTDEVICE_STRING L\"\\\\Device\\\\Passthru\" NDIS_HANDLE NdisDeviceHandle = NULL; PDEVICE_OBJECT ControlDeviceObject = NULL; enum _DEVICE_STATE { PS_DEVICE_STATE_READY = 0, // ready for create/delete PS_DEVICE_STATE_CREATING, // create operation in progress PS_DEVICE_STATE_DELETING // delete operation in progress } ControlDeviceState = PS_DEVICE_STATE_READY; /////////////////////////////////////////////////////////////////////////////////////// 2.在Passthru.c增加如下函数 NDIS_STATUS PtRegisterDevice( VOID ) /*++ Routine Description: Register an ioctl interface - a device object to be used for this purpose is created by NDIS when we call NdisMRegisterDevice. This routine is called whenever a new miniport instance is initialized. However, we only create one global device object, when the first miniport instance is initialized. This routine handles potential race conditions with PtDeregisterDevice via the ControlDeviceState and MiniportCount variables. NOTE: do not call this from DriverEntry; it will prevent the driver from being unloaded (e.g. on uninstall). Arguments: None Return Value: NDIS_STATUS_SUCCESS if we successfully register a device object. --*/ { NDIS_STATUS Status = NDIS_STATUS_SUCCESS; UNICODE_STRING DeviceName; UNICODE_STRING DeviceLinkUnicodeString; PDRIVER_DISPATCH DispatchTable[IRP_MJ_MAXIMUM_FUNCTION]; UINT i; DBGPRINT((\"==>PtRegisterDevice\\n\")); NdisAcquireSpinLock(&GlobalLock); ++MiniportCount; if (1 == MiniportCount) { ASSERT(ControlDeviceState != PS_DEVICE_STATE_CREATING); // // Another thread could be running PtDeregisterDevice on // behalf of another miniport instance. If so, wait for // it to exit. // while (ControlDeviceState != PS_DEVICE_STATE_READY) { NdisReleaseSpinLock(&GlobalLock); NdisMSleep(1); NdisAcquireSpinLock(&GlobalLock); } ControlDeviceState = PS_DEVICE_STATE_CREATING; NdisReleaseSpinLock(&GlobalLock); for (i = 0; i < IRP_MJ_MAXIMUM_FUNCTION; i++) { DispatchTable = PtDispatch; } NdisInitUnicodeString(&DeviceName, NTDEVICE_STRING); NdisInitUnicodeString(&DeviceLinkUnicodeString, LINKNAME_STRING); // // Create a device object and register our dispatch handlers // Status = NdisMRegisterDevice( NdisWrapperHandle, &DeviceName, &DeviceLinkUnicodeString, &DispatchTable[0], &ControlDeviceObject, &NdisDeviceHandle ); NdisAcquireSpinLock(&GlobalLock); ControlDeviceState = PS_DEVICE_STATE_READY; } NdisReleaseSpinLock(&GlobalLock); //DBGPRINT((\"<==PtRegisterDevice: %x\\n\", Status)); DBGPRINT(\"<==PtRegisterDevice\"); return (Status); } NTSTATUS PtDispatch( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp ) /*++ Routine Description: Process IRPs sent to this device. Arguments: DeviceObject - pointer to a device object Irp - pointer to an I/O Request Packet Return Value: NTSTATUS - STATUS_SUCCESS always - change this when adding real code to handle ioctls. --*/ { PIO_STACK_LOCATION irpStack; NTSTATUS status = STATUS_SUCCESS; DBGPRINT((\"==>Pt Dispatch\\n\")); irpStack = IoGetCurrentIrpStackLocation(Irp); switch (irpStack->MajorFunction) { case IRP_MJ_CREATE: break; case IRP_MJ_CLOSE: break; case IRP_MJ_DEVICE_CONTROL: // // Add code here to handle ioctl commands sent to passthru. // break; default: break; } Irp->IoStatus.Status = status; IoCompleteRequest(Irp, IO_NO_INCREMENT); DBGPRINT((\"<== Pt Dispatch\\n\")); return status; } NDIS_STATUS PtDeregisterDevice( VOID ) /*++ Routine Description: Deregister the ioctl interface. This is called whenever a miniport instance is halted. When the last miniport instance is halted, we request NDIS to delete the device object Arguments: NdisDeviceHandle - Handle returned by NdisMRegisterDevice Return Value: NDIS_STATUS_SUCCESS if everything worked ok --*/ { NDIS_STATUS Status = NDIS_STATUS_SUCCESS; DBGPRINT((\"==>PassthruDeregisterDevice\\n\")); NdisAcquireSpinLock(&GlobalLock); ASSERT(MiniportCount > 0); --MiniportCount; if (0 == MiniportCount) { // // All miniport instances have been halted. Deregister // the control device. // ASSERT(ControlDeviceState == PS_DEVICE_STATE_READY); // // Block PtRegisterDevice() while we release the control // device lock and deregister the device. // ControlDeviceState = PS_DEVICE_STATE_DELETING; NdisReleaseSpinLock(&GlobalLock); if (NdisDeviceHandle != NULL) { Status = NdisMDeregisterDevice(NdisDeviceHandle); NdisDeviceHandle = NULL; } NdisAcquireSpinLock(&GlobalLock); ControlDeviceState = PS_DEVICE_STATE_READY; } NdisReleaseSpinLock(&GlobalLock); //DBGPRINT((\"<== PassthruDeregisterDevice: %x\\n\", Status)); DBGPRINT(\"<== PassthruDeregisterDevice\"); return Status; } VOID PtUnloadProtocol( VOID ) { NDIS_STATUS Status; if (ProtHandle != NULL) { NdisDeregisterProtocol(&Status, ProtHandle); ProtHandle = NULL; } DBGPRINT((\"PtUnloadProtocol: done!\\n\")); } /////////////////////////////////////////////////////////////////////////////////////// 3.在passthru.h文件中增加上述函数的声明 NTSTATUS PtDispatch( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp ); NDIS_STATUS PtRegisterDevice( VOID ); NDIS_STATUS PtDeregisterDevice( VOID ); VOID PtUnloadProtocol( VOID ); ///////////////////////////////////////////////////////////////////////////////////// 4.在precomp.h文件的第一行增加如下定义 #define NDIS_WDM 1 ///////////////////////////////////////////////////////////////////////////////////// 5.把passthru.c文件中的函数DriverEntry中的PChars.UnloadHandler = NULL;改为 PChars.UnloadHandler = PtUnloadProtocol; ///////////////////////////////////////////////////////////////////////////////////// 6.在miniport.h文件中的函数MPInitialize的代码:Status = NDIS_STATUS_SUCCESS;前增加 // // Create an ioctl interface // (VOID)PtRegisterDevice(); ///////////////////////////////////////////////////////////////////////////////////// 7.在miniport.h文件中的函数MPHalt的代码:if (pAdapt->BindingHandle != NULL)前增加 NdisReleaseSpinLock(&GlobalLock); // // Delete the ioctl interface that was created when the miniport // was created. // (VOID)PtDeregisterDevice(); ///////////////////////////////////////////////////////////////////////////////////// 8.把protocol.c文件中的函数PtUnload的内容改为如下: DBGPRINT((\"PtUnload: entered\\n\")); PtUnloadProtocol(); DBGPRINT((\"PtUnload: done!\\n\")); ///////////////////////////////////////////////////////////////////////////////////// 9.把passthru.c文件中的函数DriverEntry的变量定义的后面加上如下代码: NdisAllocateSpinLock(&GlobalLock); ///////////////////////////////////////////////////////////////////////////////////// 10.修改完毕后编译装载并重起机器就可以了. 三.用户态的代码很简单如下: #include \"stdafx.h\" #include <windows.h> #include <stdio.h> int main(int argc, char* argv[]) { HANDLE hdevice = CreateFile(\"\\\\\\\\.\\\\Passthru\", GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL); if (hdevice == INVALID_HANDLE_VALUE) { printf(\"Unable to open PassThru device - error %d\\n\", GetLastError()); return 1; } CloseHandle(hdevice); return 0; } 运行用户态程序,用DebugView就可以看到内核态和用户态的交互情况。 祝你好运! ____________________ “今天心情好,中午刚刚吃了顿饱饭,吃得我坐在草地上喘了 半个小时的气还没有缓过劲来,其实也就是双份蛋炒饭,不过 感觉很爽。”----Huyg 学习,学习,再学习 |
|
|
地下室#
发布于:2003-07-27 15:07
说的good,这也方便我等菜鸟更快入门 :D
|
|
|
5楼#
发布于:2003-07-27 13:53
该成立个精华区了 现在问题重复的好多
|
|
|
6楼#
发布于:2003-07-27 13:46
学习 :D
|
|
|
7楼#
发布于:2003-04-30 16:21
就是这个例子。
|
|
|
8楼#
发布于:2003-04-30 15:07
mikeluo 看fracker说的那个例子就ok了:) 那个codeguru 网址是英文的么 我怎么都看不懂 是不是那个 没找到呜呜 |
|
9楼#
发布于:2003-04-29 17:08
Mikeluo : 由应用层发消息到驱动 我知道用IoControl 可以的 但是我由驱动向 应用层发消息 使用事件莱完成 我在应用层里面等待 在驱动里面设置信号 应用层根本获得不了这个信号 求教了 能解答一下么 看fracker说的那个例子就ok了:) |
|
|
10楼#
发布于:2003-04-29 16:48
www.codeguru.com上面有个一个guidevice的例子,去抄吧。
|
|
11楼#
发布于:2003-04-29 16:32
无论如何,非常感谢你的帮助。
我打算最近全心研究驱动,具体问题希望能再向你咨询,再次感谢你热心的帮助和建议。 |
|
12楼#
发布于:2003-04-29 10:53
Mikeluo : 由应用层发消息到驱动 我知道用IoControl 可以的 但是我由驱动向 应用层发消息 使用事件莱完成 我在应用层里面等待 在驱动里面设置信号 应用层根本获得不了这个信号 求教了 能解答一下么
|
|
13楼#
发布于:2003-04-28 17:19
解决你的问题有两个方法:一是你看看驱动开发的书,估计那本都会讲应用程序和驱动程序通信的问题;二是你可以在这个版上查找以前的帖子,有很多人问过这个问题了。
如果这两种方式你都不想,那我也没有办法了。 |
|
|
14楼#
发布于:2003-04-28 17:09
我想做的东西是这样,协议层仍然是TCP/IP,在中间层(或者微端口层)申请一片缓存区,友它接受或发送外部程序的数据包,比如来自串口应用程序的数据包。问题是一个处于核心态,一个处在用户态,其数据交互的接口函数是什么,还是CreateFile、WriteFile、ReadFile吗?
|
|
15楼#
发布于:2003-04-28 13:27
当然可以了,很多帖子讨论这个问题,你找一下看看就知道了
|
|
|