阅读:1595回复:0
求救,TDI 没法接收到数据,各位高手快帮帮我.我正在做一个虚拟串口驱动,按照论坛中lingzjl大虾用 acidfish大虾的虚拟串口源码和TDIcln的例子思路,做一个串口转TCP的虚拟驱动,打开本地传输地址成功,连接成功,发数据成功,用SetEventHandler() 注册回调函数也成功,但是有数据过来时,回调函数没有被调用,我看了好多例子了,写的都和我差不多,好多方法都试过了,但就是没法找出错在哪里,高手们指点一下. 连接代码如下: NTSTATUS InitializeConnection( PDEVICE_EXTENSION deviceExtension ) /*++ Routine Description: 1. Open a transport address and get the highest deviceobject of the transport stack. 2. Build RecvContext in the DeviceExtension 3. SetTdiEventHandle, includes TDI_EVENT_RECEIVE_DATAGRAM and TDI_EVENT_ERROR Arguments: deviceExtension - pointer to a device object extension. Return Value: NT status code. --*/ { int port; int address1; int address2; int address3; int address4; NTSTATUS status; UNICODE_STRING TdiTransportDeviceName; OBJECT_ATTRIBUTES TdiAttributes; // HANDLE TdiAddressHandle; // HANDLE TdiEndpointHandle; IO_STATUS_BLOCK IoStatusBlock; PTA_IP_ADDRESS pAddress; CONNECTION_CONTEXT connectionContext = NULL; ULONG eaSize; PIRP pIrp; // PVOID pAddressFileObject; KEVENT irpCompleteEvent; KEVENT connectionEvent; TA_IP_ADDRESS controllerTaIpAddress; ULONG controllerIpAddress; USHORT controllerPort; TDI_CONNECTION_INFORMATION controllerConnection; LARGE_INTEGER timeout; static char eaBuffer[ sizeof(FILE_FULL_EA_INFORMATION) + TDI_TRANSPORT_ADDRESS_LENGTH + sizeof(TA_IP_ADDRESS)]; PFILE_FULL_EA_INFORMATION pEaBuffer = (PFILE_FULL_EA_INFORMATION)eaBuffer; // Build Unicode transport device name. RtlInitUnicodeString( &TdiTransportDeviceName, COMM_TCP_DEVICE_NAME ); // "/device/tcp" DbgPrint("Into -------Connect 12.54-----------------"); // create object attribs InitializeObjectAttributes( &TdiAttributes, &TdiTransportDeviceName, OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, 0, 0 ); pEaBuffer->NextEntryOffset = 0; pEaBuffer->Flags = 0; pEaBuffer->EaNameLength = TDI_TRANSPORT_ADDRESS_LENGTH; // Copy TdiTransportAddress memcpy( pEaBuffer->EaName, TdiTransportAddress, pEaBuffer->EaNameLength + 1 ); // EaValue represents of the local host IP address and port pEaBuffer->EaValueLength = sizeof(TA_IP_ADDRESS); pAddress = (PTA_IP_ADDRESS) (pEaBuffer->EaName + pEaBuffer->EaNameLength + 1); pAddress->TAAddressCount = 1; pAddress->Address[0].AddressLength = TDI_ADDRESS_LENGTH_IP; pAddress->Address[0].AddressType = TDI_ADDRESS_TYPE_IP; pAddress->Address[0].Address[0].sin_port = 0; // any port pAddress->Address[0].Address[0].in_addr = 0; // local address memset( pAddress->Address[0].Address[0].sin_zero, 0, sizeof(pAddress->Address[0].Address[0].sin_zero) ); // Get the transport device status = TDIOpenTransportAddress( COMM_TCP_DEVICE_NAME, &deviceExtension->hTransAddr, &deviceExtension->lpTransAddrFileObject, 0 ); DebugPrint(("OpenTransAddr: handle = %x, lpFileObj = %x, status = %x\n", deviceExtension->hTransAddr, deviceExtension->lpTransAddrFileObject, status )); if ( status != STATUS_SUCCESS ) { deviceExtension->lpTransAddrFileObject = NULL; deviceExtension->hTransAddr = NULL; return status; } // Open a TDI endpoint eaSize = FIELD_OFFSET(FILE_FULL_EA_INFORMATION, EaName) + TDI_CONNECTION_CONTEXT_LENGTH + 1 + sizeof(CONNECTION_CONTEXT); // Overwrite pEaBuffer pFileInfo = (PFILE_FULL_EA_INFORMATION)ExAllocatePool(NonPagedPool, eaSize); if( pFileInfo == NULL ) { DbgPrint("comint32: OpenTDIConnection() failed to allocate buffer"); return STATUS_INSUFFICIENT_RESOURCES; } // Set file info memset(pFileInfo, 0, eaSize); pFileInfo->NextEntryOffset = 0; pFileInfo->Flags = 0; pFileInfo->EaNameLength = TDI_CONNECTION_CONTEXT_LENGTH; memcpy( pFileInfo->EaName, TdiConnectionContext, pFileInfo->EaNameLength + 1 ); //includes NULL terminator // CONNECTION_CONTEXT is a user defined structure used to sort connections // There is only one connection in this example, so CONNECTION_CONTEXT is not used pFileInfo->EaValueLength = sizeof(CONNECTION_CONTEXT); *(CONNECTION_CONTEXT*)(pFileInfo->EaName+(pFileInfo->EaNameLength + 1)) = (CONNECTION_CONTEXT) connectionContext; status = ZwCreateFile( &deviceExtension->hConn, ////////////// GENERIC_READ | GENERIC_WRITE | SYNCHRONIZE, &TdiAttributes, &IoStatusBlock, 0, FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ, FILE_OPEN, 0, pFileInfo, sizeof(eaBuffer) ); if( !NT_SUCCESS( status ) ) { DbgPrint("comint32: OpenTDIConnection() ZwCreate 2 failed, Status = %0x", status); return STATUS_UNSUCCESSFUL; } // get object handle status = ObReferenceObjectByHandle( deviceExtension->hConn, //////////////// FILE_ANY_ACCESS, 0, KernelMode, (PVOID *)&deviceExtension->pFileObject,//////////pFileObject, NULL ); // Associate endpoint with address deviceExtension->TDILowerDeviceObject= IoGetRelatedDeviceObject( deviceExtension->lpTransAddrFileObject); ///////////// // Define a completion event KeInitializeEvent( &irpCompleteEvent, NotificationEvent, FALSE ); // Build IO Request Packet pIrp = TdiBuildInternalDeviceControlIrp( TDI_ASSOCIATE_ADDRESS, deviceExtension->TDILowerDeviceObject, deviceExtension->pFileObject, &irpCompleteEvent, &IoStatusBlock ); if( pIrp == NULL ) { DbgPrint("comint32: No IRP for TDI_ASSOCIATE_ADDRESS"); return( STATUS_INSUFFICIENT_RESOURCES ); } // Extend the IRP TdiBuildAssociateAddress(pIrp, deviceExtension->TDILowerDeviceObject, deviceExtension->pFileObject, NULL, NULL, deviceExtension->hTransAddr ); /////////////////////////// // set completion routine IoSetCompletionRoutine( pIrp, TDICompletionRoutine, &irpCompleteEvent, TRUE, TRUE, TRUE); // Send the packet status = IoCallDriver( deviceExtension->TDILowerDeviceObject, pIrp ); // Wait if( status == STATUS_PENDING ) { DbgPrint("comint32: OpenTDIConnection() Waiting on IRP (associate)..."); KeWaitForSingleObject(&irpCompleteEvent, Executive, KernelMode, FALSE, 0); } if( ( status != STATUS_SUCCESS) && ( status != STATUS_PENDING ) ) { DbgPrint("comint32: OpenTDIConnection() IoCallDriver 1 failed. Status = %0x", status); return STATUS_UNSUCCESSFUL; } // Connect to the remote controller KeInitializeEvent(&connectionEvent, NotificationEvent, FALSE); // build connection packet pIrp = TdiBuildInternalDeviceControlIrp( TDI_CONNECT, deviceExtension->TDILowerDeviceObject, deviceExtension->pFileObject, &connectionEvent, &IoStatusBlock ); if( pIrp == NULL ) { DbgPrint("comint32: OpenTDIConnection() could not get an IRP for TDI_CONNECT"); return( STATUS_INSUFFICIENT_RESOURCES ); } // Initialize controller data address1 = 192;//atoi(masterAddress1); address2 = 168;//atoi(masterAddress2); address3 = 1;//atoi(masterAddress3); address4 = 111;//atoi(masterAddress4); port = 10001;//atoi(masterPort); controllerPort = HTONS(port); controllerIpAddress = INETADDR(address1,address2,address3,address4); deviceExtension->RemoteAddress = controllerIpAddress; deviceExtension->RemotePort = controllerPort; DbgPrint("port = %0x, controllerPort = %0x ,deviceExtension->RemotePort = %0x", port,controllerPort,deviceExtension->RemotePort); controllerTaIpAddress.TAAddressCount = 1; controllerTaIpAddress.Address[0].AddressLength = TDI_ADDRESS_LENGTH_IP; controllerTaIpAddress.Address[0].AddressType = TDI_ADDRESS_TYPE_IP; controllerTaIpAddress.Address[0].Address[0].sin_port = controllerPort; controllerTaIpAddress.Address[0].Address[0].in_addr = controllerIpAddress; controllerConnection.UserDataLength = 0; controllerConnection.UserData = 0; controllerConnection.OptionsLength = 0; controllerConnection.Options = 0; controllerConnection.RemoteAddressLength = sizeof(controllerTaIpAddress); controllerConnection.RemoteAddress = &controllerTaIpAddress; // add controller data to the packet TdiBuildConnect( pIrp, deviceExtension->TDILowerDeviceObject, deviceExtension->pFileObject, NULL, NULL, NULL, &controllerConnection, 0 ); // set completion routine IoSetCompletionRoutine( pIrp, TDICompletionRoutine, &connectionEvent, TRUE, TRUE, TRUE); // Send the packet status = IoCallDriver( deviceExtension->TDILowerDeviceObject, pIrp ); // wait if( status == STATUS_PENDING ) { DbgPrint("comint32: OpenTDIConnection() waiting on IRP (connect)..."); KeWaitForSingleObject(&connectionEvent, Executive, KernelMode, FALSE, 0); } if( ( status != STATUS_SUCCESS ) && ( status != STATUS_PENDING ) ) { DbgPrint("comint32: OpenTDIConnection() Connection failed. Status = %0x", status); return( STATUS_UNSUCCESSFUL ); } // Start a Deferred Procedure Call // Objects must be non paged pKernelTimer = ExAllocatePool( NonPagedPool, sizeof( KTIMER ) ); pKernelDPC = ExAllocatePool( NonPagedPool, sizeof( KDPC ) ); timeout.QuadPart = -10; KeInitializeTimer( pKernelTimer ); KeInitializeDpc( pKernelDPC, timerDPC, NULL ); if( KeSetTimerEx( pKernelTimer, timeout, 500, pKernelDPC ) ) // 1/2 second { DbgPrint("comint32: OpenTDIConnection() Timer was already set."); } // TDIBuildRecvContext( &deviceExtension->recvContext ); DbgPrint(" IPAddress = %0x ,DestinationPort = %0x",deviceExtension->RemoteAddress,deviceExtension->RemotePort); deviceExtension->TDILowerDeviceObject = IoGetRelatedDeviceObject(deviceExtension->lpTransAddrFileObject); DbgPrint("first TDIClnSetEventHandler----------------"); TDIClnSetEventHandler( deviceExtension->lpTransAddrFileObject, deviceExtension->TDILowerDeviceObject, TDI_EVENT_RECEIVE, TDIClnEventReceive, deviceExtension ); DbgPrint("second TDIClnSetEventHandler---------------"); // deviceExtension->TDILowerDeviceObject = IoGetRelatedDeviceObject(deviceExtension->pFileObject); TDIClnSetEventHandler( deviceExtension->lpTransAddrFileObject, deviceExtension->TDILowerDeviceObject, TDI_EVENT_ERROR, TDIEventError, NULL ); DbgPrint("exit Initconnect 4"); return STATUS_SUCCESS; } 设置事件代码没变,如下, NTSTATUS TDIClnSetEventHandler( PFILE_OBJECT pAddrFileObj, // Address file object. PDEVICE_OBJECT pTcpDevObj, // TDI driver's device object. LONG EventType, // Type of event. PVOID pEventHandler, // Event handler routine. PVOID pEventContext // Context for event handler. ) /**************************************************************************************************/ /* */ /* Set up an event handler. */ /* */ /* Note: This routine is synchronous. */ /* */ /**************************************************************************************************/ { NTSTATUS status; KEVENT Event; IO_STATUS_BLOCK IoStatus; PIRP pIrp; do { // Single-iteration loop, to make possible escape via break. KeInitializeEvent(&Event, NotificationEvent, FALSE); // Get an Irp for internal device ioctl. pIrp = TdiBuildInternalDeviceControlIrp(TDI_SET_EVENT_HANDLER, pTcpDevObj, // TDI driver's device object. pAddrFileObj, // Address file object. &Event, // Event to be signalled when Irp completes. &IoStatus // I/O status block. ); if (NULL==pIrp) { status = STATUS_INSUFFICIENT_RESOURCES; break; } TdiBuildSetEventHandler(pIrp, pTcpDevObj, pAddrFileObj, NULL, // I/O completion routine. NULL, // Context for I/O completion routine. EventType, pEventHandler, // Event handler routine. pEventContext // Context for event handler routine. ); status = IoCallDriver(pTcpDevObj, pIrp); if (STATUS_PENDING==status) // Have to wait on this Irp? KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, 0); // Problem from IoCallDriver() or Problem discovered in completion? if ( ( STATUS_SUCCESS!=status && STATUS_PENDING!=status ) || ( STATUS_PENDING==status && 0!=IoStatus.Status ) ) { // Note: If problem was in IoCallDriver(), IoStatus.Status probably won't be meaningful. DebugPrint(("TDIClnSetEventHandler: Problem in IoCallDriver(). status = 0x%08x, IoStatus.Status = 0x%08x\n", STATUS_PENDING==status ? 0 : status , IoStatus.Status)); } } while(0); // End 'do-while' single-iteration loop. status = ((STATUS_SUCCESS==status) || (STATUS_PENDING==status)) ? IoStatus.Status : status; return status; } 但是我监测有网络数据包过来是,就是没有调用回调函数,不知道错在哪里,而且acidfish大虾的虚拟串口源码中UDP方式的回调函数是能成功的,唉,不知道问题出在哪, |
|