Здравствуйте, 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 );
}
Я думаю теперь намного стало понятнее? Возможен ли такой вариан вообще?