I’m newbie in kernel programming, TDI program please help!:(

Home Forums Discussions General Discussion I’m newbie in kernel programming, TDI program please help!:(

This topic contains 9 replies, has 2 voices, and was last updated by  rvd 13 years, 2 months ago.

Viewing 10 posts - 1 through 10 (of 10 total)
  • Author
    Posts
  • #4883

    rvd
    Participant

    I have struggled with a sea of difficulties. Pass a error, other errors occur.
    My TDI kernel socket driver (export driver) there are steps as following:
    1. Create a endpoint connection (OK).
    2. Create a tdi transport address handle (OK).
    3. Set Event Handle for connection (OK).
    4. Bind endpoint connection to transport address handle (OK)
    (TdiBuildAssociateAddress).
    5. Connect to Server (TdiBuildConnect OK).
    6. Send data (TdiBuidSend OK).
    7. Receive data (TdiBuidReceive OK).
    8. Disconnect (TdiBuildDisconnect OK).
    9. Close connection file object, address object, connection handle,
    address handle OK.

    But only success in the firt time. After disconnecting in the first connection session, do new session again and error always happend at “ASSERT( KeGetCurrentIrql() == PASSIVE_LEVEL )” command line. If remove this line, error will happend at the first connection session after closing the connection. I post some my code follow, please spend your time to see and help me.
    ////////////////////////////////////////////////
    ////Set event handle function ////
    __declspec(dllexport) NTSTATUS
    SetEventHandler(PFILE_OBJECT FileObject,LONG EventType, PVOID EventHandler, PVOID EventContext)
    {
    NTSTATUS status;
    KEVENT Event;
    PIRP Irp;
    PDEVICE_OBJECT DeviceObject;
    IO_STATUS_BLOCK IoStatus;

    DeviceObject = IoGetRelatedDeviceObject(FileObject);

    pIrp = TdiBuildInternalDeviceControlIrp(TDI_SET_EVENT_HANDLER, DeviceObject, FileObject, &Event, &IoStatus);

    if (pIrp == 0)
    {
    DbgPrint(“VLSD: Set event handle fail.n”);
    return STATUS_INSUFFICIENT_RESOURCES;
    }

    do{
    TdiBuildSetEventHandler(Irp, DeviceObject, FileObject, NULL, NULL, EventType, EventHandler, EventContext);

    DbgPrint(“VLSD: Set event handle OK.n”);

    ASSERT( KeGetCurrentIrql() == PASSIVE_LEVEL );
    KeInitializeEvent(&Event, NotificationEvent, FALSE);

    IoSetCompletionRoutine( Irp, // The IRP
    VLSDSimpleTdiRequestComplete, // The completion routine
    &Event, // The completion context
    TRUE, // Invoke On Success
    TRUE, // Invoke On Error
    TRUE // Invoke On Cancel
    );

    status = IoCallDriver(DeviceObject, Irp);

    if(status == STATUS_PENDING)
    {
    ASSERT( KeGetCurrentIrql() == PASSIVE_LEVEL );
    status = KeWaitForSingleObject(&Event, Executive,
    KernelMode, FALSE, 0);
    if(!NT_SUCCESS(status))
    break;
    }
    else if(!NT_SUCCESS(status))
    break;

    }while(0);

    return status == STATUS_SUCCESS ? IoStatus.Status : status;
    }

    ///// Receiving event handle function /////
    __declspec(dllexport) NTSTATUS
    EventReceive(PVOID eventContext,
    CONNECTION_CONTEXT connectionContext,
    ULONG Flags,
    ULONG Indicated,
    ULONG Available,
    PULONG Taken,
    PVOID tsduBuff,
    PIRP *Irp)
    {
    DbgPrint(“VLSD: Receive Flags = %lx, Ind = %ld, Avl = %ld.n”,
    Flags, Indicated, Available);

    //*Taken = Available; *Irp = 0;

    return STATUS_SUCCESS;
    }

    //////// Receiving data function /////////
    __declspec(dllexport) NTSTATUS Recv(PFILE_OBJECT FileObject, PVOID Data, ULONG Length)
    {
    NTSTATUS status;
    PIRP Irp;
    PDEVICE_OBJECT DeviceObject;
    PMDL Mdl;
    KEVENT Event;
    IO_STATUS_BLOCK IoStatus;

    ULONG tsize = 0;
    ULONG len = 0;
    PUCHAR rBuf;

    rBuf = (PUCHAR)ExAllocatePool(PagedPool, Length + 1);
    RtlZeroMemory(rBuf, Length + 1);
    while(tsize < Length)
    {
    PUCHAR buff;
    ULONG i;
    if(Length – tsize < 1024)
    len = Length – tsize;
    else
    len = 1024;
    buff = (PUCHAR)ExAllocatePool(PagedPool, len + 1);
    RtlZeroMemory(buff, len + 1);

    ASSERT( KeGetCurrentIrql() == PASSIVE_LEVEL );
    KeInitializeEvent(&Event, NotificationEvent,FALSE);

    DeviceObject = IoGetRelatedDeviceObject(FileObject);

    Irp = TdiBuildInternalDeviceControlIrp(TDI_RECEIVE,
    DeviceObject,
    FileObject,
    &Event, &IoStatus);
    if (Irp == NULL)
    {
    DbgPrint(“VLSD: Receiving data fail because of insufficient MDL resources.n”);
    status = STATUS_INSUFFICIENT_RESOURCES;
    break;
    }

    Mdl = IoAllocateMdl(buff, len, FALSE, FALSE, Irp);

    if (Mdl == NULL)
    {
    DbgPrint(“VLSD: Receiving data fail because of insufficient MDL resources.n”);
    status = STATUS_INSUFFICIENT_RESOURCES;
    break;
    }

    Mdl->Next = NULL;

    __try{
    MmProbeAndLockPages ( Mdl, KernelMode, IoModifyAccess );
    } __except ( EXCEPTION_EXECUTE_HANDLER ) {
    DbgPrint ( “VLSD: Exception at MmProbeAndLockPagesn” );
    IoFreeMdl(Mdl);
    Mdl = NULL;
    status = STATUS_INSUFFICIENT_RESOURCES;
    break;
    }

    TdiBuildReceive(Irp, DeviceObject, FileObject, NULL, NULL, Mdl,
    TDI_RECEIVE_NORMAL, len);

    DbgPrint ( “VLSD: Begin read data n” );

    status = IoCallDriver(DeviceObject, Irp);
    if ((status == STATUS_SUCCESS) || (status == STATUS_PENDING))
    {
    DbgPrint(“VLSD: Wait a moment for receiving data.n”);

    ASSERT( KeGetCurrentIrql() == PASSIVE_LEVEL );
    status = KeWaitForSingleObject(&Event, Executive,
    KernelMode, FALSE, NULL);
    if(!NT_SUCCESS(status))
    {
    DbgPrint(“VLSD: Cannot wait, time out or error.n”);
    }
    }

    buff[len] = ‘’;
    RtlCopyMemory(rBuf + tsize, buff, len);

    DbgPrint(“VLSD: Buffer value = “);
    for(i=0; i
    DbgPrint(“%c”, *(buff+i));
    DbgPrint(“n”);

    MmUnlockPages(Mdl);
    //if (Irp->MdlAddress != NULL) {
    // IoFreeMdl(Irp->MdlAddress);
    // Irp->MdlAddress = NULL;
    //}
    IoFreeMdl(Mdl);

    ExFreePool(buff);

    tsize = tsize + len;

    DbgPrint(“VLSD: Status = %lx, IoStatus.Status = %lx, IoStatus.Information = %ld.n”,
    status, Irp->IoStatus.Status, Irp->IoStatus.Information);
    status == STATUS_SUCCESS ? Irp->IoStatus.Status : status;
    if(status != STATUS_SUCCESS)
    break;
    }

    rBuf[Length] = ‘’;
    RtlCopyMemory(Data, rBuf, Length);
    ExFreePool(rBuf);

    return status;
    }

    Anyone can help me, please give me some advice. I’m newbie in this area. Thanks in adv.

    #5642

    Vijender
    Participant

    Hi,

    I’ll forward you some of the code that I wrote for a kernel socket library. But please note that the code will be for learning purpose only.

    But I am not able to find any options here to send attachments. So fwd me your mail-id, I’ll mail the files directly to you.

    and remember “TDI is not so bad”. 😀

    #5643

    rvd
    Participant

    Hi Vijender,
    This module I try test with VarpoCD driver (Virtual CD driver – open source), learning kernel programming purpose only. If work fine, I will post it to soureforge.net. Thank you for replying me and help me. My email is tranvietlong@yahoo.com.

    Thanks in adv.

    #5644

    rvd
    Participant

    Can anyone help me? How about you Mr.Vijender? I’m waiting reply from you.

    In virtual disk driver there is a function ReadOffset(ULONG offset, PVOID dest, ULONG length) for get data from socket driver. What happend in my program, what solution for my case, plsease help me.

    #5645

    Vijender
    Participant

    Hello Rvd,

    Your problem is not clear to me. Not much idea about virtual disk drivers. Please elaborate, what does your driver do and what you want to do now.

    #5646

    rvd
    Participant

    My virtual disk have a routine function

    CDReadIN PDEVICE_OBJECT DeviceObject, IN PIRP Irp).

    This routine is called by the I/O system to read or write to a device that we control. When Interupt major function in case IRP_MJ_READ will call to function ReadDataOffset(Filename, offset, length, buffer) for read data from iso file (CD image file). If iso file is local, run OK, but now read iso file from server (Unix) need a socket driver (TDI), a export driver for get data from server. I build a kernel socket driver from TDI use TCP protocol.

    In function ReadDataOffset of virtual disk driver I call socket driver functions for make a session with server.

    – Create enpoint connection
    – Create transport address handle
    – Set event handle
    – Bind enpoint connection and transport address handle (associate a tdi transport connection)
    – Connect to server
    – Send command
    – Get data to buffer
    – Disconnect
    – Close enpoint connection handle
    – Close transport address handle

    After finish the first session (finish the first call to ReadDataOffset function), virtual disk request next session (call to ReadDataOffset again), error happend when running at the first command line ASSERT( KeGetCurrentIrql() == PASSIVE_LEVEL ) in socket driver code (the first time no problem). If I remove these command lines, happend will happend immediatly when finnish the first session. Now I can not know what happend and have no solution for it. I’m looking forward to hearing from you, experts.

    Thanks in adv.

    #5647

    Vijender
    Participant

    Hi Rvd,

    The statetement that you are refering to, at which your driver is crashing, indicates that you are running at higher irql than PASSIVE_LEVEL.
    There could be many reasons for that:
    1. Your function is called at high irql by I/O system.
    2. You have raised your irql by say acquireing some lock but forgot to release.

    Your driver will crash at that statement if IRQL > PASSIVE_LEVEL no matter it is called first time or any time.

    #5648

    rvd
    Participant

    Hi Vijender,

    I think you ‘re right, I’m newbie in this case, so spend more time for solve it. A my friend give me Idea that make a system thread and call all socket driver function in this thread. But I don’t know how to get data from thread because I need to get data to virtual disk driver buffer. Can you have any solution or if you can spend your time, I would like to send my code to you, you can see it and help me where i’m wrong.

    Thanks so much.

    #5649

    Vijender
    Participant

    Hi Rvd,

    I am very busy these days. So can’t spend much time on the code.
    But I’ll suggest you a solution for now.

    First check it is not possible to call your routine at dispatch level. Check in DDK . Because if it can call your routine at DISPATCH_LEVEL there is problem.
    Now when your function is called by I/O manager, enqueue a work item adn you wait here till your worker thread has read the data for you. For that you will have to create a work item and enqueue it in system queue. A system thread will than carry out all of your work at PASSIVE_LEVEL.

    #5650

    rvd
    Participant

    Thank you, I’ll try with your solution you suggest. Hope it will help me pass this problem.

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

You must be logged in to reply to this topic.