TDI
От: Zoya_Pobeda  
Дата: 03.12.06 04:00
Оценка:
Здраствуйте, мальчики

Есть драйвет виртуального ЛПТ-порта.Он получает данные от приложения — с этим все ОК!Добила!
Нужно эти данные отпралять по сети...Вот здесь не все мне понятно. Как я понимаю, нужно создать транспорт.файл, файл соединения, выстатвит события, ассоциировать, сохранить Irp Accept-a, по событию конект, отдать этот Irp — работаем...

Так вот вопрос: Нужно ли все это дело связанное с TDI, выносить в отдельный поток?
Re: TDI
От: TarasCo  
Дата: 03.12.06 10:35
Оценка: 1 (1)
Здравствуйте, Zoya_Pobeda, Вы писали:

Z_P>Здраствуйте, мальчики


Z_P>Есть драйвет виртуального ЛПТ-порта.Он получает данные от приложения — с этим все ОК!Добила!

Z_P>Нужно эти данные отпралять по сети...Вот здесь не все мне понятно. Как я понимаю, нужно создать транспорт.файл, файл соединения, выстатвит события, ассоциировать, сохранить Irp Accept-a, по событию конект, отдать этот Irp — работаем...

Z_P>Так вот вопрос: Нужно ли все это дело связанное с TDI, выносить в отдельный поток?


Вы довольно сумбурно изложили свои мысли, видимо сказалась радость победы на LPT .Ваш драйвер будет сетевым сервером или клиентом? Если клиентом, то когда должно устанавливтаься соединение? Короче говоря, не совсем ясна архитектура. Поэтому и ответ будет таким же неясным. Большинство вызовов (кроме создания транспортных объектов ) могут проходить на DISPATCH_LEVEL и могут быть сделаны в контексте любого потока.
Да пребудет с тобою сила
Re[2]: TDI
От: Zoya_Pobeda  
Дата: 03.12.06 11:12
Оценка:
Здравствуйте, TarasCo, Вы писали:


TC>Вы довольно сумбурно изложили свои мысли, видимо сказалась радость победы на LPT .Ваш драйвер будет сетевым сервером или клиентом? Если клиентом, то когда должно устанавливтаься соединение? Короче говоря, не совсем ясна архитектура. Поэтому и ответ будет таким же неясным. Большинство вызовов (кроме создания транспортных объектов ) могут проходить на DISPATCH_LEVEL и могут быть сделаны в контексте любого потока.


Может быть как сервером, так и клиентом, взависимости от настроек.Но в данном случае меня интересует серверная часть.

Архитектура такова: Девайс ЛПТ, при открытии должен(помимо каких то своих настроек), создавать поток, который будет работать с ТДИ. Все это дело у меня сейчас выглядит примерно так:


NTSTATUS ServerThreadStart(PLPT_DEVICE_EXTENSION  Context)
{
    NTSTATUS        status    = STATUS_SUCCESS;
    PSERVERDATA        pServer = NULL;




    KeInitializeSemaphore(&Context->Tdi_KillEvent, 0, MAXLONG);
    KeInitializeSemaphore(&Context->Tdi_TimeWait, 0, MAXLONG);
    KeInitializeSemaphore(&Context->Tdi_Send, 0, MAXLONG);
    KeInitializeSemaphore(&Context->Tdi_Recv, 0, MAXLONG);

    pServer = ExAllocatePool(NonPagedPool, sizeof(SERVERDATA));
    

    if( NULL == pServer )
    {
        return( STATUS_INSUFFICIENT_RESOURCES );
    }

    memset( pServer, 0, sizeof( SERVERDATA ) );

    pServer->pDevExt = Context;

    status = PsCreateSystemThread(
      &pServer->hTestThread,     // thread handle
      0L,               // desired access
      NULL,             // object attributes
      NULL,             // process handle
      NULL,             // client id
      ServerWorkerThread,  // start routine
      (PVOID )pServer  // start context
      );

    if( !NT_SUCCESS( status ) )
    {
    //    goto errorServerWorkerThread;
    }

    return status;



}

VOID ServerWorkerThread(IN PVOID Context)
{
    NTSTATUS                status    = STATUS_SUCCESS;
    LARGE_INTEGER            DelayTime;
    PVOID                    pEvents[6];
    KWAIT_BLOCK                waitBlocks[6];
    BOOLEAN                    bDeadThread = FALSE;
    PIRP                    pIrp        = NULL;
    IO_STATUS_BLOCK            IoStatus;


    PSERVERDATA                pServer        = (PSERVERDATA)Context;
    PLPT_DEVICE_EXTENSION    pDevExt        = (PLPT_DEVICE_EXTENSION)pServer->pDevExt;

    pServer->pTDIClient = ExAllocatePool(NonPagedPool, sizeof( TDIClientExtension ));

    if( NULL == pServer->pTDIClient )
    {
        status = STATUS_INSUFFICIENT_RESOURCES;
        goto errorTDIClient;
    }

    pServer->pTDIClient->hAddr = INVALID_HANDLE_VALUE;
    pServer->pTDIClient->pAddrFileObj = NULL;
    pServer->pTDIClient->pReqElemsArr = NULL;
    pServer->pTDIClient->pBufferBase = NULL;
    pServer->pTDIClient->pTDIClnConnArr = NULL;

    InitIPAddress(    &pServer->pTDIClient->LocalAddress,
                    INADDR_ANY,
                    ntohs(pDevExt->m_port));

    

    status = TDIClnOpenTransAddr(                    
                                    TCP_DEVICE_NAME_W,
                                    pServer->pTDIClient,
                                    &pServer->pTDIClient->hAddr,
                                    &pServer->pTDIClient->pAddrFileObj
                                 );

    if( !NT_SUCCESS( status ) )
    {
        goto errorOpenTransportAddress;
    }


    pServer->pTDIClient->pTDIClnConnArr =                       
        (pTDIClnConn)ExAllocatePool(
                                   NonPagedPool,
                                   sizeof(TDIClnConn)
                                  );

    if( NULL == pServer->pTDIClient->pTDIClnConnArr )
    {
        status = STATUS_INSUFFICIENT_RESOURCES;
        goto errorOpenConnection;
    }

    pServer->pTDIClient->pTDIClnConnArr->pDevExt = pServer->pTDIClient;
    pServer->pTDIClient->pTDIClnConnArr->hConn = INVALID_HANDLE_VALUE;


    status = TDIClnOpenConnEndPt(    TCP_DEVICE_NAME_W,
                                    &pServer->pTDIClient->pTDIClnConnArr->hConn,
                                    &pServer->pTDIClient->pTDIClnConnArr->pConnFileObj,
                                    pServer->pTDIClient->pTDIClnConnArr);

    if( !NT_SUCCESS( status ) )
    {
        goto errorOpenConnectionEndpoint;
    }

    KeInitializeEvent(&pServer->pTDIClient->pTDIClnConnArr->AccEvent, NotificationEvent, FALSE);                               
    KeInitializeEvent(&pServer->pTDIClient->pTDIClnConnArr->AccEvent, NotificationEvent, FALSE);

    pServer->pTDIClient->pTcpDevObj = IoGetRelatedDeviceObject(pServer->pTDIClient->pAddrFileObj);


    status =                                         
        TDIClnSetEventHandler    (
                                pServer->pTDIClient->pAddrFileObj,
                                pServer->pTDIClient->pTcpDevObj,
                                TDI_EVENT_RECEIVE,
                                TDISrvEventReceive,     
                                NULL                     
                                );

    if( !NT_SUCCESS( status ) )
    {
        goto errorEvent;
    }

    status =                                        
        TDIClnSetEventHandler    (
                                pServer->pTDIClient->pAddrFileObj,
                                pServer->pTDIClient->pTcpDevObj,
                                TDI_EVENT_DISCONNECT,
                                TDISrvEventDisconnect,     
                                NULL                     
                                );

    if( !NT_SUCCESS( status ) )
    {
        goto errorEvent;
    }

    status =                                        
        TDIClnSetEventHandler    (
                                pServer->pTDIClient->pAddrFileObj,
                                pServer->pTDIClient->pTcpDevObj,
                                TDI_EVENT_ERROR_EX,
                                TDISrvEventErrorEx,     
                                NULL                     
                                );

    if( !NT_SUCCESS( status ) )
    {
        goto errorEvent;
    }

    status = TDIClnAssocAddr(                     
                                 pServer->pTDIClient->pTDIClnConnArr->pConnFileObj,
                                 pServer->pTDIClient->pTcpDevObj,
                                 pServer->pTDIClient->hAddr
                                );

    if( !NT_SUCCESS( status ) )
    {
        goto errorEvent;
    }


    pIrp = TdiBuildInternalDeviceControlIrp(TDI_ACCEPT,
                            pServer->pTDIClient->pTcpDevObj,    
                            pServer->pTDIClient->pTDIClnConnArr->pConnFileObj,
                            &pServer->pTDIClient->pTDIClnConnArr->AccEvent, 
                            &IoStatus               
                            );

    if (NULL==pIrp)
    {
        KdPrint(("Error TdiBuildInternalDeviceControlIrp"));
        status = STATUS_INSUFFICIENT_RESOURCES;
        goto errorBuildTDIAccept;
    }

    pServer->pTDIClient->pIrpAccept = pIrp;                      
    status =                                         
            TDIClnSetEventHandler(    pServer->pTDIClient->pAddrFileObj,
                                    pServer->pTDIClient->pTcpDevObj,
                                    TDI_EVENT_CONNECT,
                                    TDISrvEventConnect,
                                    pServer->pTDIClient->pTDIClnConnArr             
                                    );

    if (!NT_SUCCESS(status))
    {
        KdPrint(("Error TDIClnSetEventHandler: TDI_EVENT_CONNECT"));
        goto errorBuildTDIAccept;
    }


    KdPrint(("ServerWorkerThread: Starting... \r\n"));

    pEvents[EV_KILLEVENT]    = (PVOID)&pDevExt->Tdi_KillEvent;
    pEvents[EV_TIMEWAIT]    = (PVOID)&pDevExt->Tdi_TimeWait;
    pEvents[EV_SEND]        = (PVOID)&pDevExt->Tdi_Send;
    pEvents[EV_RECV]        = (PVOID)&pDevExt->Tdi_Recv;

    pEvents[EV_ACC]        = (PVOID)&pServer->pTDIClient->pTDIClnConnArr->AccEvent;
    pEvents[EV_DIS]        = (PVOID)&pServer->pTDIClient->pTDIClnConnArr->DiscEvent;

    while(!bDeadThread)
    {

        

        switch(KeWaitForMultipleObjects(6, pEvents, WaitAny, Executive, KernelMode, FALSE, NULL, waitBlocks))
        {
        case EV_ACC:
            {
                break;
            }
        case EV_DIS:
            {
                break;
            }
        case EV_KILLEVENT:
            {
                bDeadThread = TRUE;
                break;
            }
        case EV_TIMEWAIT:
            {

                break;
            }
        case EV_SEND:
            {
                
                

                break;
            }
        case EV_RECV:
            {

                break;
            }
        }


    }
    KdPrint(("Server Thread: Exiting...\n") );

errorBuildTDIAccept:
    TDIClnDisassocAddr(pServer->pTDIClient->pTDIClnConnArr->pConnFileObj, pServer->pTDIClient->pTcpDevObj);

errorEvent:
    if (INVALID_HANDLE_VALUE!=pServer->pTDIClient->pTDIClnConnArr->hConn) 
     {
         ZwClose(pServer->pTDIClient->pTDIClnConnArr->hConn);
         pServer->pTDIClient->pTDIClnConnArr->hConn = INVALID_HANDLE_VALUE;
     }

     if (NULL!=pServer->pTDIClient->pTDIClnConnArr->pConnFileObj) 
     {
         ObDereferenceObject(pServer->pTDIClient->pTDIClnConnArr->pConnFileObj);
         pServer->pTDIClient->pTDIClnConnArr->pConnFileObj = NULL;
     }


errorOpenConnectionEndpoint:
    ExFreePool( pServer->pTDIClient->pTDIClnConnArr );


errorOpenConnection:
     if (INVALID_HANDLE_VALUE!=pServer->pTDIClient->hAddr) 
     {
         ZwClose(pServer->pTDIClient->hAddr);
         pServer->pTDIClient->hAddr = INVALID_HANDLE_VALUE;
     }

     if (NULL!=pServer->pTDIClient->pAddrFileObj) 
     {
         ObDereferenceObject(pServer->pTDIClient->pAddrFileObj);
         pServer->pTDIClient->pAddrFileObj = NULL;
     }


errorOpenTransportAddress:
    ExFreePool( pServer->pTDIClient );

errorTDIClient:
    ExFreePool( pServer);

    (void)PsTerminateSystemThread( STATUS_SUCCESS );
}


Я думаю теперь намного стало понятнее? Возможен ли такой вариан вообще?
Re[3]: TDI
От: TarasCo  
Дата: 06.12.06 12:07
Оценка:
Здравствуйте, Zoya_Pobeda, Вы писали:

Если не вдаваться в подробности, то код в принципе рабочий. Мне не вполне ясна сама идея выноса в отдельный поток, но возможно, так удобнее. В этом случае ( использование потока ), нет нужды устанавливать нотификаторы ( это мое частное мнение ), можно обойтись посылкой управляющих IRP и всю работу проводить на PASSIVE_LEVEL, но это дело вкуса .
Да пребудет с тобою сила
Re[3]: TDI
От: IID Россия  
Дата: 07.12.06 09:29
Оценка:
У вас в коде 2 бага.
1) при создании потоков нигде не освобождается по ZwClose описатель потоков => утечка

ThreadHandle
Points to a variable that will receive the handle. The driver must close the handle with ZwClose once the handle is no longer in use.


2) при анлоаде никто не ждет завершения потоков, и тут как карта ляжет: кто быстрее кончится — поток или driverunload. Возможен BSOD.

никто не ждет завершения, потому что никто не спрашивает объект потока, так как единственное место, куда пишется хэндл — это структура Server, передающаяся только потоку и им же освобождающаяся

по идее анлоад должен ждать поток после сигнализирования (PVOID)&pDevExt->Tdi_KillEvent;
kalsarikännit
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.