TDI-фильтр и ClientEventChainedReceive(Expedited)

Home Forums Discussions Support TDI-фильтр и ClientEventChainedReceive(Expedited)

Viewing 5 posts - 1 through 5 (of 5 total)
  • Author
    Posts
  • #5308
    prus
    Participant

      Всем привет!

      Имеется TDI-фильтр.
      Подменяю ClientEventChainedReceive(Expedited) на свой обработчик при TDI_SET_EVENT_HANDLER (TDI_EVENT_CHAINED_RECEIVE(_EXPEDITED)). Вот как выглядит мой обработчик:


      NTSTATUS NewClientEventChainedReceive(
      IN PVOID TdiEventContext,
      IN CONNECTION_CONTEXT ConnectionContext,
      IN ULONG ReceiveFlags,
      IN ULONG ReceiveLength,
      IN ULONG StartingOffset,
      IN PMDL Tsdu,
      IN PVOID TsduDescriptor
      )
      {

      KIRQL oldIrql;
      NTSTATUS ntStatus;
      PCLIENT_EVENT_CONTEXT_INFO pClientEventContextInfo;
      CLIENTEVENTCHAINEDRECEIVE RealClientEventChainedReceive;

      //__asm int 3

      KeAcquireSpinLock(&g_ClientEventReceiveSpinLock, &oldIrql);
      pClientEventContextInfo = (PCLIENT_EVENT_CONTEXT_INFO)TdiEventContext;
      RealClientEventChainedReceive = (CLIENTEVENTCHAINEDRECEIVE)pClientEventContextInfo->EventRealHandler;
      KeReleaseSpinLock(&g_ClientEventReceiveSpinLock, oldIrql);

      ntStatus = RealClientEventChainedReceive(pClientEventContextInfo->EventRealContext,
      ConnectionContext,
      ReceiveFlags,
      ReceiveLength,
      StartingOffset,
      Tsdu,
      TsduDescriptor);

      TCPMODULE_KDPRINT(("In NewClientEventChainedReceive: ReceiveLength=%lu ntStatus=0x%08Xn", ReceiveLength, ntStatus));

      return ntStatus;

      }

      RealClientEventChainedReceive возвращает мне STATUS_PENDING.
      Вопрос такой… Будет ли при этом Tsdu содержать данные? Т.е. смогу я их прочитать при STATUS_PENDING? Проверить сейчас прям не могу… Вот и решил спросить теоритически.

      #6847
      Vadim Smirnov
      Keymaster

        В данном случае STATUS_PENDING означает, что TDI клиент обработает полученные из сети данные позже и затем вернет переданный ему буфер. Данные из Tsdu лучше забрать до вызова оригинального обработчика, так как если это сделать позже, то можно получить race condition.

        #6848
        prus
        Participant

          Большое спасибо!

          #6849
          prus
          Participant

            Вот… Поправил немного:


            NTSTATUS NewClientEventChainedReceive(
            IN PVOID TdiEventContext,
            IN CONNECTION_CONTEXT ConnectionContext,
            IN ULONG ReceiveFlags,
            IN ULONG ReceiveLength,
            IN ULONG StartingOffset,
            IN PMDL Tsdu,
            IN PVOID TsduDescriptor
            )
            {

            BOOLEAN bReceiveFlag = FALSE;
            KIRQL oldIrql;
            NTSTATUS ntStatus;
            ULONG ulTcpDataType = 0;
            PUCHAR puchData = NULL;
            PUCHAR puchMdlData = NULL;
            PCLIENT_EVENT_CONTEXT_INFO pClientEventContextInfo;
            CLIENTEVENTCHAINEDRECEIVE RealClientEventChainedReceive;

            /*__asm int 3*/

            KeAcquireSpinLock(&g_ClientEventReceiveSpinLock, &oldIrql);
            pClientEventContextInfo = (PCLIENT_EVENT_CONTEXT_INFO)TdiEventContext;
            RealClientEventChainedReceive = (CLIENTEVENTCHAINEDRECEIVE)pClientEventContextInfo->EventRealHandler;
            KeReleaseSpinLock(&g_ClientEventReceiveSpinLock, oldIrql);

            do {

            if( Tsdu == NULL || ReceiveLength == 0 )
            break;

            puchMdlData = (PUCHAR)MmGetSystemAddressForMdlSafe(Tsdu, LowPagePriority);

            if( puchMdlData == NULL )
            break;

            puchData = (PUCHAR)ExAllocatePool(NonPagedPool, ReceiveLength);

            if( puchData == NULL )
            break;

            RtlZeroMemory(puchData, ReceiveLength);
            RtlCopyMemory(puchData, puchMdlData, ReceiveLength);

            ...
            ...

            bReceiveFlag = TRUE;

            } while( FALSE );

            ntStatus = RealClientEventChainedReceive(pClientEventContextInfo->EventRealContext,
            ConnectionContext,
            ReceiveFlags,
            ReceiveLength,
            StartingOffset,
            Tsdu,
            TsduDescriptor);

            TCPMODULE_KDPRINT(("In NewClientEventChainedReceive [RealClientEventChainedReceive]: ReceiveLength=%lu ntStatus=0x%08Xn", ReceiveLength, ntStatus));

            if( bReceiveFlag ) {

            if( ntStatus == STATUS_SUCCESS || ntStatus == STATUS_PENDING ) {

            // Сохраняем данные для дальнейшего использования

            }
            else {

            // Если статус STATUS_DATA_NOT_ACCEPTED, то чистим ранее выделенные ресурсы

            }

            }

            return ntStatus;

            }

            т.е. в puchData у меня будет копия принятых данных. В случае, если реальный нотификатор вернет STATUS_DATA_NOT_ACCEPTED, то клиенту данные не нужны и я очищаю память… Если же реальный нотификатор вернет STATUS_SUCCESS или STATUS_PENDING, то сохраняею данные.
            Я правильно все понял?

            #6850
            Vadim Smirnov
            Keymaster

              В общем да…

            Viewing 5 posts - 1 through 5 (of 5 total)
            • You must be logged in to reply to this topic.