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

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

This topic contains 4 replies, has 2 voices, and was last updated by  Vadim Smirnov 7 years, 6 months ago.

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
    Moderator

    В данном случае 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
    Moderator

    В общем да…

Viewing 5 posts - 1 through 5 (of 5 total)

You must be logged in to reply to this topic.