chenxiansheng
驱动牛犊
驱动牛犊
  • 注册日期2008-03-25
  • 最后登录2009-06-06
  • 粉丝0
  • 关注0
  • 积分7分
  • 威望24点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
阅读:1595回复:0

求救,TDI 没法接收到数据,各位高手快帮帮我.

楼主#
更多 发布于:2009-03-31 00:50

我正在做一个虚拟串口驱动,按照论坛中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方式的回调函数是能成功的,唉,不知道问题出在哪,
游客

返回顶部