NDIS IM - problems with NdisSend

Discussion in 'Windows Vista Drivers' started by arek.ploski, Jul 23, 2006.

  1. arek.ploski

    arek.ploski Guest

    Hi,
    I am developing application to encypt / decrypt TCP/IP packets data. I
    know that the fastest way is to change date in a driver, but one of the
    requirements is to make it possible to change cryptographic algorithm
    in an easy way. I decided to change PassThru driver extended by Thomas
    F. Divine (part 2 of his article) and I pass interesting packets to my
    application and block them in the driver. Then I want to change the
    data there and resend packets as a new ones (from a driver's point of
    view). And here is my problem. When I create a new NDIS_PACKET and try
    to send it with NdisSend (or even NdisSendPackets, as in NDISPROT DDK
    example) I've got bluescreen. Here is a piece of my code (without any
    debug and other additional lines), please tell me where is my
    misunderstanding of this subject.

    FltDevIoControl(){
    (...)
    PNDIS_PACKET pNdisPacket;
    PNDIS_BUFFER pNdisBuffer;
    (...)
    ioBuffer = pIrp->AssociatedIrp.SystemBuffer;
    inputBufferLength =
    pIrpSp->Parameters.DeviceIoControl.InputBufferLength;
    (...)
    case MY_IOCTL_CODE:

    pNdisPacket = NULL;
    pNdisBuffer = NULL;

    NdisAcquireSpinLock(&(pFilterContext->PacketListSpinLock));
    NdisAllocatePacket(&Status, &pNdisPacket,
    pAdapt->SendPacketPoolHandle);
    NdisAllocateBuffer(&Status, &pNdisBuffer,
    pAdapt->SendBufferPoolHandle, ioBuffer, inputBufferLength );
    NdisChainBufferAtFront(pNdisPacket, pNdisBuffer);
    NdisSend(&Status, pAdapt->BindingHandle, pNdisPacket );
    if (Status != NDIS_STATUS_PENDING){
    NdisFreeBuffer(pNdisBuffer);
    NdisFreePacket(pNdisPacket);
    }
    NdisReleaseSpinLock(&(pFilterContext->PacketListSpinLock));
    break;
    }

    It seems to me that there is nothing to go wrong. Maybe I can't see
    some important issues. Thank you for any advice in advance.
    Arek
     
    arek.ploski, Jul 23, 2006
    #1
    1. Advertisements

  2. Arek,

    If you are writing a device driver, saying "I've got a bluescreen" is
    unacceptable. You must have a debugger attached then you will know more
    about the crash.

    In code below, don't hold spinlock while calling NdisSend.

    What happens if NdisSend returns STATUS_PENDING? Will the data from
    user-mode go away while NDIS is using it?

    Do you understand that ProtocolSendComplete will be called eventually? Do
    you realize that ProtocolSendComplete must do somethings differently for
    packets that you send this way?

    Please use a debugger.

    Thomas F. Divine
     
    Thomas F. Divine [DDK MVP], Jul 23, 2006
    #2
    1. Advertisements

  3. arek.ploski

    arek.ploski Guest

    Thomas,

    First of all thank you for such an impressively fast reply.

    To be honest I must admit (but I am sure that it's quite obvious :)
    that I am a newbie in drivers' subject.

    Your remarks gave me a lot to think. I've changed my code, added my own
    packets and buffers pools, so that I can tell apart which packets are
    mine and which are not (in PTSendComplete).
    Moreover I implemented solution from NDISPROT example, so now I suspend
    irp call and keep it with packet and after all I can complete it in
    PTSendComplete.
    Now it seems like it works fine for me.

    In short, my code now looks like below (again I overlooked some extra
    code):

    filter.c:

    NdisAcquireSpinLock(&(pFilterContext->PacketListSpinLock));
    NdisAllocatePacket(&Status, &pNdisPacket, pAdapt->OutPacketPoolHandle
    );
    NdisAllocateBuffer(&Status, &pNdisBuffer, pAdapt->OutBufferPoolHandle,
    ioBuffer, inputBufferLength );
    NdisChainBufferAtFront(pNdisPacket, pNdisBuffer);
    NdisReleaseSpinLock(&(pFilterContext->PacketListSpinLock));

    NdisInterlockedIncrement( &pAdapt->RefCount );
    IoMarkIrpPending(pIrp);
    InsertTailList(&(pAdapt->OutPendedListHead),
    &pIrp->Tail.Overlay.ListEntry);
    IoSetCancelRoutine(pIrp, CancelOutIrp);
    NPROT_IRP_FROM_SEND_PKT(pNdisPacket) = pIrp;

    NdisSend(&Status, pAdapt->BindingHandle, pNdisPacket );
    if (Status == NDIS_STATUS_PENDING){
    NtStatus = STATUS_PENDING;
    }
    break;

    protocol.c:

    if (PoolHandle == pAdapt->OutPacketPoolHandle) {
    PIRP pIrp;
    PIO_STACK_LOCATION pIrpSp;
    UINT nBufferCount;
    PNDIS_BUFFER pCurrentBuffer;
    UINT TotalPacketLength;

    pIrp = NPROT_IRP_FROM_SEND_PKT(Packet);
    NdisAcquireSpinLock(&pAdapt->Lock);
    RemoveEntryList(&pIrp->Tail.Overlay.ListEntry);
    NdisReleaseSpinLock(&pAdapt->Lock);
    IoSetCancelRoutine(pIrp, NULL);

    pIrpSp = IoGetCurrentIrpStackLocation(pIrp);
    if (Status == NDIS_STATUS_SUCCESS) {
    pIrp->IoStatus.Information = pIrpSp->Parameters.Write.Length;
    pIrp->IoStatus.Status = STATUS_SUCCESS;
    } else {
    pIrp->IoStatus.Information = 0;
    pIrp->IoStatus.Status = STATUS_UNSUCCESSFUL;
    }

    NdisQueryPacket( (PNDIS_PACKET )Packet, NULL, (PUINT)&nBufferCount,
    &pCurrentBuffer, &TotalPacketLength );
    // my packets always have only one buffer
    if (pCurrentBuffer)
    NdisFreeBuffer(pCurrentBuffer);
    NdisFreePacket(Packet);

    IoCompleteRequest(pIrp, IO_NO_INCREMENT);
    NdisInterlockedDecrement( &pAdapt->RefCount );
    }

    Thanks again for Your help and I'll apreciate it if you have any
    further comments.
    Arek
     
    arek.ploski, Jul 23, 2006
    #3
    1. Advertisements

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments (here). After that, you can post your question and our members will help you out.