阅读:4270回复:9
w2k下的PassThru和用户态交互修改说明
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就可以看到内核态和用户态的交互情况。 祝你好运! |
|
沙发#
发布于:2002-01-13 20:23
同志们何不去看看xp ddk中的passthru sample?嘿嘿
w2k下的PassThru和用户态交互修改说明 |
|
|
板凳#
发布于:2002-01-14 13:00
我不太明白这样做有什么必要,直接用xp passthru在2k ddk下就可以build啊。
对了,xp passthru说自己可以在98/se/me下build ,怎么我build不了??也不知道怎么安装。 ........................................................... (TARGETNAME=passthru TARGETPATH=obj TARGETTYPE=DRIVER C_DEFINES=$(C_DEFINES) -DNDIS_MINIPORT_DRIVER -DNDIS_WDM=1 # C_DEFINES=$(C_DEFINES) -DNDIS51_MINIPORT=1 # C_DEFINES=$(C_DEFINES) -DNDIS51=1 # Comment out the two lines above and uncomment the following # two lines to build for Win2000 or Win98/SE or WinMe C_DEFINES=$(C_DEFINES) -DNDIS40_MINIPORT=1 C_DEFINES=$(C_DEFINES) -DNDIS40=1 # Uncomment the following to build for Win98/SE/WinMe # This causes several APIs that are not present in Win9X to be # ifdef\'ed out. # C_DEFINES=$(C_DEFINES) -DWIN9X=1 ........................................................... |
|
|
地板#
发布于:2002-01-14 14:22
我写此文的目的如下:
1.是为了没有xpDDK的xdjm,(本网站的xpDDK需要高级用户才能download),另外此问题以前多次被问,始终没有完整的解答。 2.在我的机器上,系统为中文w2k Server 2195 SP2,对xp的passthru的source文件修改前后,编译装载(两次都重起了机器),每次都会出现蓝屏。我想给出现类似问题的xdjm提供一个思路。 3.我在原文的开头已经说明了,如果您熟悉,就不要看我的修改, 也不会浪费您的时间。 另外, XP的passtrhu能否在98/se/me下build 的,我也不想试了,我觉得好像即使编译了也不可能在此在这样的条件下使用。passthru的安装,它的passthru.htm上很清楚,再说本网站以前已经讨论过了,可以去看看。 [编辑 - 1/14/02 作者: condor] |
|
地下室#
发布于:2002-01-14 18:26
浏览了这么久,终于有了一个值得大加讨论的话题。
xp passthru是source compatible 的imd,兼容 win98se/me/xp/2k,注意不兼容win98,95是ndis3,不支持 imd。 在win98se/me下编译方法: 首先修改source文件,source文件中有注释,因为 基本上不用我多说,注意,编译的时候使用win2k 的环境,就是说,用win2k chk build env,然后 使用98ddk中的build -cZ。也就是说,使用w2k的 头文件/库,但是用98ddk的build编译。 值得注意的一点:2k ddk中的ndis函数很多都是 宏,例如ndissend,但是win98se/me中要求是函数, 因此,source文件中加一条环境变量:-DBINARY_COMPATIBLE。 不加也能编译过,但是加载的时候不知道会发生什么。 在98se/me中调试的话,强烈建议有vxdldr的chkbuild。 此外,ndis.vxd的sym也有必要。 关于w2k 的ndis driver port to win9x的问题,还有 一个地方值得考虑,w2k是unicode string,win9x是 asci string,注意看ndis.h中的PNDIS_STRING的定义。 为什么这个SAMPLE能够兼容WIN98SE/ME,但是却不能 兼容win98?因为所有win98se/me中不能用的函数都 用条件编译保护了,但是还有5到6个98下不能用的函数, 没有保护,结果系统加载的时候找不到入口,无法加载。 如果是98 chkbuild,可以在softice中看到dbgprint信息。 \"xxx fun canot found entry...\" 因此,有98 chkbuild就比较容易移植。因为你可以找到 所有不支持的函数然后用条件编译去掉。 最后谈安装,我的经验,安装会带来一场恶梦,如果不是 两场的话。 9x下的inf文件和2k的完全不同,倒是有点类似nt,而且 文档也不太详细,唯一可以找到的系统一点的描述在95ddk, vs6附带的msdn里面有。可是95并不支持imd,因此,这方面 的内容一点都没有。目前internnet上能找到的信息只有 RS_PPPOE的实现,里面有一个WINPPPOE.INF,此外,98系统 自带一个ATMLANE.INF和ATMLANM.INF,这两个都是MUX IMD, 和filter imd的情况还有不同,目前我无法找到任何关于 filter imd for 9x的inf的资料。而且由于9x似乎并不打算 方便的支持imd,因此,没有象2k那样,直接支持imd filter 的安装。因此,即使写出了一个inf也没有用,有3个问题 无法简单的解决: 1、循环绑定。因为imd有miniport也有protocol,因此, 会导致循环绑定。就是imd的protocol会绑定自己的miniport。 2、无法象2k的imd filter安装一样,打断原有的协议和 miniport的绑定,绑定效果会是tcp->real miniport tcp->imd\'s miniport并存,这是mux filter的效果,并不是 imd filter的效果。 3、对于拨号的支持。 目前我只能手动编辑注册表,使得它工作,但是系统如果一旦 再次安装了一个别的协议或者pppoe之类的东西,我就必须再次 编辑注册表,卸载其它协议也无法干净。因为我只能根据非常 有限的资料摸索98注册表中到底都有些什么东西,每个健值 是什么含义。rs_pppoe做得不错,最令我感到神奇的是,他 居然binary compatible。不知道是否使用了动态寻找入口的 技术。rs_pppoe的wi9x安装有一个dll,这个dll就是解决所有 安装卸载问题的。这方面我正在摸索,前两天刚刚下载了一个 vc1.52,就是为了编译安装dll,这玩艺是个16bit的dll,9x 下的netdi.dll也是16bit的。现在还是无法达到我手动编辑 注册表的效果,而且完美的支持更加不知道何时能够搞定, 还好这只是自娱自乐。 关于这个问题,我希望有在9x下写过网络安装dll的兄弟能够 提供一些技术支持。我没有写过16 bit的驱动程序,也没有 写过16bit的dll,这倒不是什么大问题,ddk和msdn中多次 有不少描述,但是安装的那些函数令我颇感困惑,98ddk 中有两个sample,但是都颇令人困惑。 我不太明白这样做有什么必要,直接用xp passthru在2k ddk下就可以build啊。 |
|
|
5楼#
发布于:2002-02-08 15:37
感谢condor大虾,为我们这些新手着想。(我没有xp ddk)。 :D
|
|
6楼#
发布于:2004-06-24 09:08
mark
|
|
|
7楼#
发布于:2004-06-24 10:46
深表感谢!我一直在寻找试验这东西!
|
|
|
8楼#
发布于:2004-07-27 14:35
有人做过这个实验吗?我做这个实验为什么没有成功,而且不能自动地将驱动与网卡进行绑定,其他人呢?
|
|
驱动牛犊
![]() |
9楼#
发布于:2007-01-09 22:00
好东西,感谢各位大虾!
|