// tdi.c // // // Requires DDK Only // File created on 2/2/2005 // #include "pch.h" #ifdef CPR_WMI_TRACE #include "tdi.tmh" #endif // helper structure, used to pass information from // CprTdiEventConnect to CprTdiEventConnectComplete typedef struct _CPR_CONNECT_CONTEXT { PCPR_TDI_SOCKET Socket; PTDI_CONNECTION_INFORMATION ConnectionInformation; PCPR_DEVICE_EXTENSION DeviceExtension; USHORT rem_sin_port; ULONG rem_in_addr; } CPR_CONNECT_CONTEXT, *PCPR_CONNECT_CONTEXT; typedef struct _CPR_REMOTECONNECT_CONTEXT { PCPR_DEVICE_EXTENSION DeviceExtension; PIO_WORKITEM WorkItem; USHORT rem_sin_port; ULONG rem_in_addr; } CPR_REMOTECONNECT_CONTEXT, *PCPR_REMOTECONNECT_CONTEXT; /////////////////////////////////////////////////////////////////////////////////////////////////// // CprTdiRemoteConnectWorkerRoutine // remote connect callback routine // // Arguments: // IN DeviceObject // device object pointer // // IN Context // disconnect context // // Return Value: // None // VOID CprTdiRemoteConnectWorkerRoutine( IN PDEVICE_OBJECT DeviceObject, IN PVOID Context ) { NTSTATUS status; PCPR_REMOTECONNECT_CONTEXT remConContext; PCPR_DEVICE_EXTENSION pDevExt = NULL; KIRQL oldIrql; CPR_BUFFER_TYPE toNetBuf; BOOLEAN deviceVerified = FALSE; toNetBuf.WrPos = 0; remConContext = (PCPR_REMOTECONNECT_CONTEXT)Context; if (remConContext) { pDevExt = remConContext->DeviceExtension; CprDebugPrint2(pDevExt, DBG_TDI, DBG_TRACE, __FUNCTION__"++. DEVEXT %p %X", pDevExt, remConContext->rem_in_addr); if (pDevExt) { if (pDevExt->Closing) { CprDebugPrint(pDevExt, DBG_TDI, DBG_TRACE, __FUNCTION__"--. Closing"); return; } // enable event handling CprUartWriteIER(&pDevExt->Uart, CPR_UART_IER_RDA | CPR_UART_IER_THR | CPR_UART_IER_RLS | CPR_UART_IER_MS); pDevExt->ListenMode_in_addr = remConContext->rem_in_addr; pDevExt->ListenMode_sin_port = remConContext->rem_sin_port; deviceVerified = CprUartIsLantronixDevice(&pDevExt->Uart, remConContext->rem_in_addr, TRUE); if (deviceVerified == FALSE) { status = STATUS_CONNECTION_REFUSED; } else { status = STATUS_SUCCESS; } CprAcquireSerialSpinLock(pDevExt, &oldIrql); // // Negotiations of options occur in the normal // send/receive functions after this routine returns. // // We need to send the desired com port settings // to the connect device server. // // Should I do this all here and block, or return // and do it in the background. If we are not // connected to an RFC2217 compliant device, we // need to abort the connection. We probably should // block and find out before we return. // if (pDevExt->UseRFC2217 && (status == STATUS_SUCCESS)) { if (pDevExt->ToNetBuf.WrPos) { // We have some pending sends. // Save off and send after successful negotiation. toNetBuf = pDevExt->ToNetBuf; } InitBuffer(&pDevExt->ToNetBuf); //pDevExt->ToNetBuf.RdPos = pDevExt->ToNetBuf.WrPos = 0; NetworkStatusChange(pDevExt, CPR_NETWORK_STATUS_NEGOTIATING); pDevExt->IsDeviceNegotiating = TRUE; CprReleaseSerialSpinLock(pDevExt, oldIrql); status = CprRfc2217_Negotiate(pDevExt); CprAcquireSerialSpinLock(pDevExt, &oldIrql); } if (status == STATUS_SUCCESS) { if (pDevExt->UseRFC2217) { CprRfc2217_SendPortSettings(pDevExt); if (toNetBuf.WrPos) { int length; unsigned char *buffer; CprRfc2217_GetBuffer(&toNetBuf, &buffer, &length); if (buffer != NULL) { // Send pending RFC 2217 commands to the device server on the network. CprUartWriteDirect(&pDevExt->Uart, buffer, length, TRUE, TRUE); } } } // Set up event handlers CprTdiSetEventHandler(pDevExt->socket, TDI_EVENT_ERROR, CprTdiEventError, pDevExt->socket); CprTdiSetEventHandler(pDevExt->socket, TDI_EVENT_ERROR_EX, CprTdiEventErrorEx, pDevExt->socket); CprTdiSetEventHandler(pDevExt->socket, TDI_EVENT_RECEIVE, CprTdiEventReceive, pDevExt->socket); pDevExt->DpcThreadId = PsGetCurrentThreadId(); // mark device as enabled pDevExt->IsDeviceEnabled = TRUE; // make sure that our virtual uart is in a known state CprUartWriteLCR(&pDevExt->Uart, pDevExt->LineControl); CprSerialSetupNewHandFlow(pDevExt, &pDevExt->SerialHandFlow); CprSerialHandleModemUpdate(pDevExt, FALSE); // Set ComStatus for this port NetworkStatusChange(pDevExt, CPR_NETWORK_STATUS_CONNECTED); pDevExt->DpcThreadId = NULL; if (pDevExt->KeepAliveOnOff == TRUE) { CprReleaseSerialSpinLock(pDevExt, oldIrql); CprTdiSetKeepAlive(pDevExt->socket, TRUE); CprAcquireSerialSpinLock(pDevExt, &oldIrql); } } else if (pDevExt->Closing == FALSE) { //if ((pDevExt->ListenMode == LISTEN_MODE_NONE) || (deviceVerified == FALSE)) //{ SOCKET socket = pDevExt->socket; pDevExt->socket = NULL; // The device server on the other end is not running // RFC2217, or is not a Lantronix device server. Refuse the connection; CprDebugPrint2(pDevExt, DBG_CREATECLOSE, DBG_TRACE, __FUNCTION__". Disconnecting from '%ws:%d'", pDevExt->Services[pDevExt->CurService].Address, pDevExt->Services[pDevExt->CurService].Port); // disable event handling CprUartWriteIER(&pDevExt->Uart, 0); if (socket) { CprReleaseSerialSpinLock(pDevExt, oldIrql); CprTdiDisconnect(socket, FALSE, NULL, NULL); CprTdiFreeConnectSocket(socket); CprAcquireSerialSpinLock(pDevExt, &oldIrql); } pDevExt->IsDeviceEnabled = FALSE; NetworkStatusChange(pDevExt, CPR_NETWORK_STATUS_LISTENING); // NetworkStatusChange(pDevExt, CPR_NETWORK_STATUS_DISCONNECTED); //} //else if (pDevExt->ListenMode != LISTEN_MODE_NONE) //{ // NetworkStatusChange(pDevExt, CPR_NETWORK_STATUS_LISTENING); //} } pDevExt->IsDeviceNegotiating = FALSE; pDevExt->IsDeviceOpening = FALSE; CprReleaseSerialSpinLock(pDevExt, oldIrql); IoFreeWorkItem(remConContext->WorkItem); ExFreePool(remConContext); } CprDebugPrint1(pDevExt, DBG_TDI, DBG_TRACE, __FUNCTION__"-- ENABLED %d", pDevExt->IsDeviceEnabled); } return; } /////////////////////////////////////////////////////////////////////////////////////////////////// // CprTdiEventConnectComplete // connect complete completion routine // // Arguments: // IN DeviceObject // transport device object // // IN Irp // TDI_ACCEPT irp // // IN Context // connection context // // // Return Value: // Status // NTSTATUS CprTdiEventConnectComplete( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp, IN PVOID Context ) { NTSTATUS status; PCPR_CONNECT_CONTEXT connectContext; PCPR_DEVICE_EXTENSION pDevExt; KIRQL oldIrql; PCPR_REMOTECONNECT_CONTEXT remConContext; PDEVICE_OBJECT deviceObject; status = Irp->IoStatus.Status; connectContext = (PCPR_CONNECT_CONTEXT)Context; if (connectContext) { pDevExt = connectContext->DeviceExtension; CprDebugPrint2(pDevExt, DBG_TDI, DBG_TRACE, __FUNCTION__"++. STATUS %X %X", status, connectContext->rem_in_addr); // free TDI_ACCEPT irp CprTdiFreeIrp(connectContext->Socket, Irp); if (pDevExt) { // Clear event handlers // DOES NOT SEEM TO HELP!! //CprTdiSetEventHandler(connectContext->Socket, TDI_EVENT_ERROR, NULL, NULL); //CprTdiSetEventHandler(connectContext->Socket, TDI_EVENT_ERROR_EX, NULL, NULL); //CprTdiSetEventHandler(connectContext->Socket, TDI_EVENT_RECEIVE, NULL, NULL); // if connection failed free connection socket or we are closing if (!NT_SUCCESS(status) || pDevExt->Closing) { CprTdiFreeConnectSocket(connectContext->Socket); pDevExt->socket = NULL; } else { pDevExt->socket = connectContext->Socket; // // If performing RFC 2217, Initialize session data // and perform negotiations here // if (pDevExt->UseRFC2217 || (CprUartIsLantronixDevice(&pDevExt->Uart, connectContext->rem_in_addr, FALSE) == FALSE)) { // allocate connect context remConContext = (PCPR_REMOTECONNECT_CONTEXT)ExAllocatePoolWithTag( NonPagedPool, sizeof(CPR_REMOTECONNECT_CONTEXT), CPR_POOL_TAG_REM_CONTEXT ); if (remConContext != NULL) { deviceObject = IoGetRelatedDeviceObject(pDevExt->socket->ConnectionFileObject); remConContext->WorkItem = IoAllocateWorkItem(deviceObject); remConContext->DeviceExtension = pDevExt; remConContext->rem_sin_port = connectContext->rem_sin_port; remConContext->rem_in_addr = connectContext->rem_in_addr; if (remConContext->WorkItem != NULL) { IoQueueWorkItem( remConContext->WorkItem, CprTdiRemoteConnectWorkerRoutine, DelayedWorkQueue, remConContext); } else { ExFreePool(remConContext); } } } else { // enable event handling CprUartWriteIER(&pDevExt->Uart, CPR_UART_IER_RDA | CPR_UART_IER_THR | CPR_UART_IER_RLS | CPR_UART_IER_MS); // mark device as enabled pDevExt->IsDeviceEnabled = TRUE; pDevExt->IsDeviceOpening = FALSE; status = STATUS_SUCCESS; } if (pDevExt->IsDeviceEnabled) { // Set up event handlers CprTdiSetEventHandler(pDevExt->socket, TDI_EVENT_ERROR, CprTdiEventError, pDevExt->socket); CprTdiSetEventHandler(pDevExt->socket, TDI_EVENT_ERROR_EX, CprTdiEventErrorEx, pDevExt->socket); CprTdiSetEventHandler(pDevExt->socket, TDI_EVENT_RECEIVE, CprTdiEventReceive, pDevExt->socket); CprAcquireSerialSpinLock(pDevExt, &oldIrql); pDevExt->DpcThreadId = PsGetCurrentThreadId(); // make sure that our virtual uart is in a known state CprUartWriteLCR(&pDevExt->Uart, pDevExt->LineControl); CprSerialSetupNewHandFlow(pDevExt, &pDevExt->SerialHandFlow); CprSerialHandleModemUpdate(pDevExt, FALSE); // Set ComStatus for this port NetworkStatusChange(pDevExt, CPR_NETWORK_STATUS_CONNECTED); pDevExt->DpcThreadId = NULL; CprReleaseSerialSpinLock(pDevExt, oldIrql); if (pDevExt->KeepAliveOnOff == TRUE) { CprTdiSetKeepAlive(pDevExt->socket, TRUE); } } } } // free connection context ExFreePool(connectContext->ConnectionInformation); ExFreePool(connectContext); } CprDebugPrint(pDevExt, DBG_TDI, DBG_TRACE, __FUNCTION__"--"); return STATUS_MORE_PROCESSING_REQUIRED; } /////////////////////////////////////////////////////////////////////////////////////////////////// // CprTdiEventConnect // connection request event handler // // Arguments: // IN TdiEventContext // our server socket // // IN RemoteAddressLength // size of remote address buffer // // IN RemoteAddress // address of a remote node trying to connect // // IN UserDataLength // size of user data buffer // // IN UserData // additional user data send with connection request // // IN OptionsLength // size of options buffer // // IN Options // transport specific options // // OUT ConnectionContext // connection context // // OUT AcceptIrp // pre-allocated TDI_ACCEPT irp // // // Return Value: // Status // NTSTATUS CprTdiEventConnect( IN PVOID TdiEventContext, IN LONG RemoteAddressLength, IN PVOID RemoteAddress, IN LONG UserDataLength, IN PVOID UserData, IN LONG OptionsLength, IN PVOID Options, OUT CONNECTION_CONTEXT* ConnectionContext, OUT PIRP* AcceptIrp ) { NTSTATUS status; PIRP irp; PTDI_CONNECTION_INFORMATION connectionInformation; PCPR_CONNECT_CONTEXT connectContext; PCPR_TDI_SOCKET listenSocket; PCPR_TDI_SOCKET connectSocket; PCPR_DEVICE_EXTENSION pDevExt = NULL; TA_IP_ADDRESS* pIpAddress; listenSocket = (PCPR_TDI_SOCKET)TdiEventContext; if (listenSocket && listenSocket->Uart) pDevExt = listenSocket->Uart->DeviceExtension; pIpAddress = (TA_IP_ADDRESS*)RemoteAddress; CprDebugPrint1(pDevExt, DBG_TDI, DBG_TRACE, __FUNCTION__"++ %X", pIpAddress->Address[0].Address[0].in_addr); *ConnectionContext = NULL; *AcceptIrp = NULL; //***************************************************************** //***************************************************************** // TODO: check if we accept this connection // DAG: What would I check here?? //***************************************************************** //***************************************************************** if (TRUE) { // allocate a connection socket connectSocket = CprTdiAllocConnectSocket(listenSocket); if (connectSocket != NULL) { // allocate TDI_ACCEPT irp irp = CprTdiAllocIrp(connectSocket); if (irp != NULL) { // allocate connect context connectContext = (PCPR_CONNECT_CONTEXT)ExAllocatePoolWithTag( NonPagedPool, sizeof(CPR_CONNECT_CONTEXT), CPR_POOL_TAG_CON_CONTEXT ); if (connectContext != NULL) { // allocate connection info structure connectionInformation = (PTDI_CONNECTION_INFORMATION)ExAllocatePoolWithTag( NonPagedPool, sizeof(TDI_CONNECTION_INFORMATION) + RemoteAddressLength, CPR_POOL_TAG_CON_INFO ); if (connectionInformation != NULL) { RtlZeroMemory(connectionInformation, sizeof(TDI_CONNECTION_INFORMATION) + RemoteAddressLength); // save remote-node connection info connectionInformation->UserData = UserData; connectionInformation->UserDataLength = UserDataLength; connectionInformation->Options = Options; connectionInformation->OptionsLength = OptionsLength; connectionInformation->RemoteAddress = connectionInformation + 1; connectionInformation->RemoteAddressLength = RemoteAddressLength; RtlCopyMemory(connectionInformation + 1, RemoteAddress, RemoteAddressLength); // initialize TDI_ACCEPT irp TdiBuildAccept( irp, IoGetRelatedDeviceObject(connectSocket->ConnectionFileObject), connectSocket->ConnectionFileObject, CprTdiEventConnectComplete, connectContext, connectionInformation, NULL ); connectContext->Socket = connectSocket; connectContext->ConnectionInformation = connectionInformation; connectContext->DeviceExtension = pDevExt; connectContext->rem_sin_port = pIpAddress->Address[0].Address[0].sin_port; connectContext->rem_in_addr = pIpAddress->Address[0].Address[0].in_addr; // we are not calling IoCallDriver, thus we need to advance // the current stack location manually IoSetNextIrpStackLocation(irp); *AcceptIrp = irp; *ConnectionContext = connectSocket; status = STATUS_MORE_PROCESSING_REQUIRED; } else { status = STATUS_INSUFFICIENT_RESOURCES; ExFreePool(connectContext); CprTdiFreeIrp(connectSocket, irp); CprTdiFreeConnectSocket(connectSocket); } } else { status = STATUS_INSUFFICIENT_RESOURCES; CprTdiFreeIrp(connectSocket, irp); CprTdiFreeConnectSocket(connectSocket); } } else { status = STATUS_INSUFFICIENT_RESOURCES; CprTdiFreeConnectSocket(connectSocket); } } else { status = STATUS_INSUFFICIENT_RESOURCES; } } else { status = STATUS_CONNECTION_REFUSED; } CprDebugPrint1(pDevExt, DBG_TDI, DBG_TRACE, __FUNCTION__"--. STATUS %x", status); return status; } // helper context structure used to pass information from // CprTdiEventDisconnect to CprTdiWorkerDisconnect typedef struct _CPR_DISCONNECT_CONTEXT { PCPR_TDI_SOCKET Socket; PIO_WORKITEM WorkItem; } CPR_DISCONNECT_CONTEXT, *PCPR_DISCONNECT_CONTEXT; /////////////////////////////////////////////////////////////////////////////////////////////////// // CprTdiWorkerDisconnect // disconnect request callback routine // // Arguments: // IN DeviceObject // device object pointer // // IN Context // disconnect context // // Return Value: // None // VOID CprTdiWorkerDisconnect( IN PDEVICE_OBJECT DeviceObject, IN PVOID Context ) { NTSTATUS status; PCPR_DISCONNECT_CONTEXT disconnectContext; PCPR_DEVICE_EXTENSION pDevExt = NULL; KIRQL oldIrql; SOCKET connectSocket; disconnectContext = (PCPR_DISCONNECT_CONTEXT)Context; if (disconnectContext) { if (disconnectContext->Socket && disconnectContext->Socket->Uart) pDevExt = disconnectContext->Socket->Uart->DeviceExtension; if (pDevExt) { // send disconnect request CprDebugPrint2(pDevExt, DBG_CREATECLOSE, DBG_TRACE, __FUNCTION__" Disconnecting from '%ws:%d'", pDevExt->Services[pDevExt->CurService].Address, pDevExt->Services[pDevExt->CurService].Port); if (pDevExt->AutoReconPeer) { //NetworkStatusChange(pDevExt, CPR_NETWORK_STATUS_RECONNECTING); CprTdiStartReconnect(pDevExt); } else if (pDevExt->ListenMode == LISTEN_MODE_AUTO) { NetworkStatusChange(pDevExt, CPR_NETWORK_STATUS_LISTENING); CprAcquireSerialSpinLock(pDevExt, &oldIrql); connectSocket = pDevExt->socket; pDevExt->socket = NULL; CprReleaseSerialSpinLock(pDevExt, oldIrql); if (connectSocket != NULL) { CprTdiDisconnect(connectSocket, FALSE, NULL, NULL); CprTdiFreeConnectSocket(connectSocket); } } else if (pDevExt->IsDeviceEnabled || pDevExt->IsDeviceOpening) { NetworkStatusChange(pDevExt, CPR_NETWORK_STATUS_DISCONNECTED); CprCleanupPort(pDevExt, NULL); CprClosePort(pDevExt); } } IoFreeWorkItem(disconnectContext->WorkItem); ExFreePool(disconnectContext); } return; } /////////////////////////////////////////////////////////////////////////////////////////////////// // CprTdiEventDisconnect // disconnect request event handler // // Arguments: // IN TdiEventContext // our server socket // // IN ConnectionContext // our connection socket // // IN DisconnectDataLength // size of disconnect data buffer // // IN DisconnectData // additional user data send with disconnect request // // IN DisconnectInformationLength // size of disconnect information buffer // // IN DisconnectInformation // additional transport specific disconnect information // // IN DisconnectFlags // TDI_DISCONNECT_ABORT, TDI_DISCONNECT_RELEASE, etc. // // Return Value: // Status // NTSTATUS CprTdiEventDisconnect( IN PVOID TdiEventContext, IN CONNECTION_CONTEXT ConnectionContext, IN LONG DisconnectDataLength, IN PVOID DisconnectData, IN LONG DisconnectInformationLength, IN PVOID DisconnectInformation, IN ULONG DisconnectFlags ) { PDEVICE_OBJECT deviceObject; PCPR_TDI_SOCKET socket; PCPR_DISCONNECT_CONTEXT disconnectContext; PCPR_DEVICE_EXTENSION pDevExt; socket = (PCPR_TDI_SOCKET)ConnectionContext; if (socket) { pDevExt = socket->Uart->DeviceExtension; CprDebugPrint(pDevExt, DBG_TDI, DBG_TRACE, __FUNCTION__"++"); if (pDevExt && (pDevExt->IsDeviceEnabled || pDevExt->IsDeviceOpening)) { // allocate disconnect context disconnectContext = (PCPR_DISCONNECT_CONTEXT)ExAllocatePoolWithTag( NonPagedPool, sizeof(CPR_DISCONNECT_CONTEXT), CPR_POOL_TAG ); if (disconnectContext != NULL) { deviceObject = IoGetRelatedDeviceObject(socket->ConnectionFileObject); disconnectContext->WorkItem = IoAllocateWorkItem(deviceObject); disconnectContext->Socket = socket; if (disconnectContext->WorkItem != NULL) { IoQueueWorkItem(disconnectContext->WorkItem, CprTdiWorkerDisconnect, DelayedWorkQueue, disconnectContext); } else { ExFreePool(disconnectContext); } } } } CprDebugPrint(pDevExt, DBG_TDI, DBG_TRACE, __FUNCTION__"--"); return STATUS_SUCCESS; } /////////////////////////////////////////////////////////////////////////////////////////////////// // CprTdiRemainComplete // Remaining data left over from CprTdiEventReceive // CprTdiEventReceive is not supposted to be called // until CprTdiRemainComplete returns. // // Arguments: // IN DeviceObject // transport device object // // IN Irp // our irp // // IN Context // our socket // // Return Value: // Status // NTSTATUS CprTdiRemainComplete( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp, IN PVOID Context ) { PCPR_TDI_SOCKET socket; NTSTATUS status; PCPR_UART Uart; PMDL mdl; PUCHAR inBuf; ULONG inBufSize; ULONG rxBytesAtEnd; ULONG rxBytesAtBeg; ULONG bytesToWrite; LARGE_INTEGER delay; PCPR_DEVICE_EXTENSION pDevExt; KIRQL oldIrql; PCPR_PROCESS_OVERFLOW_CONTEXT poCtx = (PCPR_PROCESS_OVERFLOW_CONTEXT)Context; if (poCtx == NULL) return STATUS_MORE_PROCESSING_REQUIRED; socket = poCtx->socket; ASSERT(socket != NULL); ASSERT(socket->Uart != NULL); if ((socket == NULL) || (socket->Uart == NULL)) return STATUS_MORE_PROCESSING_REQUIRED; if (Irp == NULL) return STATUS_MORE_PROCESSING_REQUIRED; status = Irp->IoStatus.Status; mdl = Irp->MdlAddress; ASSERT(mdl != NULL); Irp->MdlAddress = NULL; if (mdl == NULL) return STATUS_MORE_PROCESSING_REQUIRED; Uart = socket->Uart; inBufSize = MmGetMdlByteCount(mdl); inBuf = (PUCHAR)MmGetSystemAddressForMdlSafe(mdl, NormalPagePriority); pDevExt = Uart->DeviceExtension; CprDebugPrint6(pDevExt, DBG_TDI, DBG_TRACE, __FUNCTION__"++. (XYZ) Irp %p socket %p status %x mdl %p nBufSize %d Buf %p", Irp, socket, status, mdl, inBufSize, inBuf); CprDebugPrint3(pDevExt, DBG_TDI, DBG_INFO, __FUNCTION__" OverflowSize %d RxCount %d RxAvailCount %d", Uart->OverflowSize, RxCount(Uart), RxAvailableCount(Uart)); CprDebugPrint2(pDevExt, DBG_TDI, DBG_INFO, __FUNCTION__" RxReadPtr %p RxWritePtr %p", Uart->RxReadPtr, Uart->RxWritePtr); ASSERT(inBufSize != 0); ASSERT(inBuf != NULL); //ASSERT(KeGetCurrentIrql() == DISPATCH_LEVEL); // CprAcquireSerialSpinLockAtDpcLevel(Uart->DeviceExtension); CprAcquireSerialSpinLock(Uart->DeviceExtension, &oldIrql); if (Uart->RxWritePtr >= Uart->RxReadPtr) { // First, write data to end of buffer rxBytesAtEnd = (ULONG)(Uart->RxEndBuffer - Uart->RxWritePtr); rxBytesAtBeg = (ULONG)(Uart->RxReadPtr - Uart->RxBuffer); // Need to leave room for one wasted byte // because an increment could make the // write == read and that is the empty state if (rxBytesAtBeg != 0) rxBytesAtBeg--; } else { rxBytesAtEnd = (ULONG)(Uart->RxReadPtr - Uart->RxWritePtr) - 1; rxBytesAtBeg = 0; } if (inBufSize <= (rxBytesAtEnd + rxBytesAtBeg)) { // // We now have enough room for the data. // bytesToWrite = inBufSize; if (bytesToWrite > rxBytesAtEnd) bytesToWrite = rxBytesAtEnd; if (bytesToWrite > 0) { // Copy Tsdu data to Uart receive buffer RtlCopyMemory(Uart->RxWritePtr, inBuf, bytesToWrite); Uart->RxWritePtr += bytesToWrite; } // Now see if we need to write the data to the beginning of the buffer if (bytesToWrite < inBufSize) { // // More data to write // inBuf = inBuf + bytesToWrite; bytesToWrite = inBufSize - bytesToWrite; ASSERT(bytesToWrite <= rxBytesAtBeg); // If we were at the end of the buffer, // wrap around. if (Uart->RxWritePtr == Uart->RxEndBuffer) Uart->RxWritePtr = Uart->RxBuffer; // Copy Tsdu data to Uart receive buffer RtlCopyMemory(Uart->RxWritePtr, inBuf, bytesToWrite); Uart->RxWritePtr += bytesToWrite; } } CprReleaseSerialSpinLock(Uart->DeviceExtension, oldIrql); CprDebugPrint(pDevExt, DBG_TDI, DBG_TRACE, __FUNCTION__" CLEANUP"); if (Irp->UserEvent) { KeSetEvent(Irp->UserEvent, IO_NO_INCREMENT, FALSE); } if (Irp->UserIosb) { *Irp->UserIosb = Irp->IoStatus; } CprTdiFreeIrp(poCtx->socket, Irp); CprTdiRelease(poCtx->socket); IoFreeMdl(poCtx->mdl); ExFreePool(poCtx->remainBuf); ExFreePool(poCtx); Uart->RxDataEvent = TRUE; CprUartCheckEvents(Uart); CprDebugPrint3(pDevExt, DBG_TDI, DBG_TRACE, __FUNCTION__"-- OverflowSize %d RxCount %d RxAvailCount %d", Uart->OverflowSize, RxCount(Uart), RxAvailableCount(Uart)); return STATUS_MORE_PROCESSING_REQUIRED; // return STATUS_SUCCESS; } /////////////////////////////////////////////////////////////////////////////////////////////////// // CprTdiEventReceive // data received event handler // // Arguments: // IN TdiEventContext // our server socket // // IN ConnectionContext // our connection socket // // IN ReceiveFlags // TDI_RECEIVE_NORMAL, TDI_RECEIVE_EXPEDITED, TDI_RECEIVE_ENTIRE_MESSAGE, ... // // IN BytesIndicated // size of TSDU currently available // // IN BytesAvailable // total size of TSDU // // OUT BytesTaken // count of bytes copied out of TSDU // // IN Tsdu // received data buffer // // OUT Irp // TdiBuildReceive irp // // Return Value: // Status // NTSTATUS CprTdiEventReceive( IN PVOID TdiEventContext, IN CONNECTION_CONTEXT ConnectionContext, IN ULONG ReceiveFlags, IN ULONG BytesIndicated, IN ULONG BytesAvailable, OUT PULONG BytesTaken, IN PVOID Tsdu, OUT PIRP* Irp ) { PCPR_TDI_SOCKET socket; NTSTATUS status; PCPR_UART Uart; PUCHAR inBuf; PIO_STACK_LOCATION irpStack; ULONG rxBytesAtEnd; ULONG rxBytesAtBeg; ULONG bytesToWrite; PUCHAR rxReadPtrSave; PUCHAR rxWritePtrSave; PCPR_DEVICE_EXTENSION pDevExt = NULL; int nAesBytes = 0; KIRQL oldIrql; socket = (PCPR_TDI_SOCKET)TdiEventContext; ASSERT(socket != NULL); ASSERT(socket->Uart != NULL); ASSERT(socket->Uart->DeviceExtension != NULL); if (!socket) { CprDebugPrint2(pDevExt, DBG_READ | DBG_IO | DBG_TDI, DBG_ERR, __FUNCTION__"++--. ERROR: Socket is NULL. IRP %p BytesIndicated %d", Irp, BytesIndicated); return STATUS_UNSUCCESSFUL; } Uart = socket->Uart; if (!Uart) { CprDebugPrint2(pDevExt, DBG_READ | DBG_IO | DBG_TDI, DBG_ERR, __FUNCTION__"++--. ERROR: Uart is NULL. IRP %p BytesIndicated %d", Irp, BytesIndicated); return STATUS_UNSUCCESSFUL; } pDevExt = Uart->DeviceExtension; if (!pDevExt) { CprDebugPrint2(pDevExt, DBG_READ | DBG_IO | DBG_TDI, DBG_ERR, __FUNCTION__"++--. ERROR: DeviceExtension is NULL. IRP %p BytesIndicated %d", Irp, BytesIndicated); return STATUS_UNSUCCESSFUL; } CprDebugPrint2(pDevExt, DBG_READ | DBG_IO | DBG_TDI, DBG_TRACE, __FUNCTION__"++. IRP %p BytesIndicated %d", Irp, BytesIndicated); CprDebugPrint2(pDevExt, DBG_READ | DBG_IO | DBG_TDI, DBG_INFO, " ReceiveFlags 0x%X BytesAvailable %d", ReceiveFlags, BytesAvailable); inBuf = (PUCHAR)Tsdu; *BytesTaken = 0; if (pDevExt->Validated[pDevExt->CurService] == FALSE) { *BytesTaken = BytesAvailable; return STATUS_SUCCESS; } if ((g_DebugArea & (DBG_READ | DBG_IO | DBG_TDI)) && (DBG_INFO <= g_DebugLevel)) { CprDebugPrint3(pDevExt, DBG_READ | DBG_IO | DBG_TDI, DBG_INFO, __FUNCTION__" OverflowSize %d RxCount %d RxAvailCount %d", Uart->OverflowSize, RxCount(Uart), RxAvailableCount(Uart)); CprDumpBuffer("CprTdiEventReceive", inBuf, BytesIndicated); } #ifdef CPR_DBG_PRINT CprDumpBuffer("CprTdiEventReceive", inBuf, BytesIndicated); #endif CprAcquireSerialSpinLock(Uart->DeviceExtension, &oldIrql); rxReadPtrSave = Uart->RxReadPtr; rxWritePtrSave = Uart->RxWritePtr; if ((pDevExt->ListenMode != LISTEN_MODE_NONE) && pDevExt->AES && (pDevExt->InitRcvLen < AES_INIT_VECTOR_SIZE)) { nAesBytes = BytesIndicated; if (nAesBytes > AES_INIT_VECTOR_SIZE - pDevExt->InitRcvLen) { nAesBytes = AES_INIT_VECTOR_SIZE - pDevExt->InitRcvLen; } #ifdef SCPR CprUpdateAESInitVector (pDevExt, inBuf, nAesBytes); #endif *BytesTaken = nAesBytes; CprDebugPrint3(pDevExt, DBG_READ | DBG_IO | DBG_TDI, DBG_TRACE, __FUNCTION__"--. AES & ListenMode: processed, Bytes Indicated %d Taken %d nAesBytes %d", BytesIndicated, *BytesTaken, nAesBytes); if (nAesBytes == BytesIndicated) { // No more data in input buffer. CprReleaseSerialSpinLock(Uart->DeviceExtension, oldIrql); return STATUS_SUCCESS; } BytesIndicated -= nAesBytes; inBuf = &inBuf[nAesBytes]; } CprDebugPrint1(pDevExt, DBG_READ | DBG_IO | DBG_TDI, DBG_INFO, " curIrp %p", Uart->DeviceExtension->ReadQueue.CurrentIrp); if (Uart->RxWritePtr >= Uart->RxReadPtr) { // First, write data to end of buffer rxBytesAtEnd = (ULONG)(Uart->RxEndBuffer - Uart->RxWritePtr); rxBytesAtBeg = (ULONG)(Uart->RxReadPtr - Uart->RxBuffer); // Need to leave room for one wasted byte // because an increment could make the // write == read and that is the empty state if (rxBytesAtBeg != 0) rxBytesAtBeg--; } else { rxBytesAtEnd = (ULONG)(Uart->RxReadPtr - Uart->RxWritePtr) - 1; rxBytesAtBeg = 0; } bytesToWrite = BytesIndicated; if (bytesToWrite > rxBytesAtEnd) bytesToWrite = rxBytesAtEnd; if (pDevExt->IsDeviceEnabled || pDevExt->IsDeviceOpening) { if (bytesToWrite > 0) { // Copy Tsdu data to Uart receive buffer RtlCopyMemory(Uart->RxWritePtr, inBuf, bytesToWrite); Uart->RxWritePtr += bytesToWrite; *BytesTaken += bytesToWrite; } // Now see if we need to write the data to the beginning of the buffer if ((bytesToWrite < BytesIndicated) && (rxBytesAtBeg != 0)) { // More data to write inBuf = inBuf + bytesToWrite; bytesToWrite = BytesIndicated - bytesToWrite; if (bytesToWrite > rxBytesAtBeg) bytesToWrite = rxBytesAtBeg; if (bytesToWrite > 0) { // If we were at the end of the buffer, // wrap around. if (Uart->RxWritePtr == Uart->RxEndBuffer) Uart->RxWritePtr = Uart->RxBuffer; // Copy Tsdu data to Uart receive buffer RtlCopyMemory(Uart->RxWritePtr, inBuf, bytesToWrite); Uart->RxWritePtr += bytesToWrite; *BytesTaken += bytesToWrite; } } if (*BytesTaken > 0) { Uart->RxDataEvent = TRUE; pDevExt->RxOverrun = FALSE; CprUartCheckEvents(Uart); } if (*BytesTaken < BytesAvailable) { // There is more data from the transport than was sent // in this Tsdu buffer. We need to process the rest of // the data in the overflow processing section. // CprTdiEventReceive is guaranteed to not be called // again until the rest of the data (OverflowSize amount) // has been read. // Uart->OverflowSize = BytesAvailable - *BytesTaken; } } else { // Device is not enabled!! CprDebugPrint(pDevExt, DBG_READ | DBG_IO | DBG_TDI, DBG_INFO, __FUNCTION__"Device is not enabled."); } CprReleaseSerialSpinLock(Uart->DeviceExtension, oldIrql); CprDebugPrint4(pDevExt, DBG_READ | DBG_IO | DBG_TDI, DBG_INFO, __FUNCTION__" Uart %p OverflowSize %d RxCount %d RxAvailCount %d", Uart, Uart->OverflowSize, RxCount(Uart), RxAvailableCount(Uart)); CprDebugPrint2(pDevExt, DBG_READ | DBG_IO | DBG_TDI, DBG_INFO, __FUNCTION__" RxReadPtr %p RxWritePtr %p", Uart->RxReadPtr, Uart->RxWritePtr); CprDebugPrint3(pDevExt, DBG_READ | DBG_IO | DBG_TDI, DBG_TRACE, __FUNCTION__"--. BytesTaken %d (Indicated-Taken) %d (Available-Taken) %d", *BytesTaken, BytesIndicated-*BytesTaken, BytesAvailable-*BytesTaken); return STATUS_SUCCESS; } /////////////////////////////////////////////////////////////////////////////////////////////////// // CprTdiEventChainedReceive // data received event handler // // Arguments: // IN TdiEventContext // our server socket // // IN ConnectionContext // our connection socket // // IN ReceiveFlags // TDI_RECEIVE_NORMAL, TDI_RECEIVE_EXPEDITED, TDI_RECEIVE_ENTIRE_MESSAGE, ... // // IN ReceiveLength // size of TSDU data // // IN StartingOffset // offset of data in TSDU // // IN Tsdu // pointer to chain of data MDLs // // IN TsduDescriptor // descriptor for TdiReturnChainedReceives // // Return Value: // Status // NTSTATUS CprTdiEventChainedReceive( IN PVOID TdiEventContext, IN CONNECTION_CONTEXT ConnectionContext, IN ULONG ReceiveFlags, IN ULONG ReceiveLength, IN ULONG StartingOffset, IN PMDL Tsdu, IN PVOID TsduDescriptor ) { CprDebugPrint(NULL, DBG_READ | DBG_IO | DBG_TDI, DBG_TRACE, __FUNCTION__"++"); CprDebugPrint(NULL, DBG_READ | DBG_IO | DBG_TDI, DBG_TRACE, __FUNCTION__"--"); return STATUS_SUCCESS; } /////////////////////////////////////////////////////////////////////////////////////////////////// // CprTdiEventReceiveExpedited // data received event handler // // Arguments: // IN TdiEventContext // our server socket // // IN ConnectionContext // our connection socket // // IN ReceiveFlags // TDI_RECEIVE_EXPEDITED, TDI_RECEIVE_ENTIRE_MESSAGE, ... // // IN BytesIndicated // size of TSDU currently available // // IN BytesAvailable // total size of TSDU // // OUT BytesTaken // count of bytes copied out of TSDU // // IN Tsdu // received data buffer // // OUT Irp // TdiBuildReceive irp // // Return Value: // Status // NTSTATUS CprTdiEventReceiveExpedited( IN PVOID TdiEventContext, IN CONNECTION_CONTEXT ConnectionContext, IN ULONG ReceiveFlags, IN ULONG BytesIndicated, IN ULONG BytesAvailable, OUT PULONG BytesTaken, IN PVOID Tsdu, OUT PIRP* IoRequestPacket ) { CprDebugPrint(NULL, DBG_READ | DBG_IO | DBG_TDI, DBG_TRACE, __FUNCTION__"++"); *BytesTaken = BytesIndicated; CprDebugPrint(NULL, DBG_READ | DBG_IO | DBG_TDI, DBG_TRACE, __FUNCTION__"--"); return STATUS_SUCCESS; } /////////////////////////////////////////////////////////////////////////////////////////////////// // CprTdiEventChainedReceiveExpedited // data received event handler // // Arguments: // IN TdiEventContext // our server socket // // IN ConnectionContext // our connection socket // // IN ReceiveFlags // TDI_RECEIVE_EXPEDITED, TDI_RECEIVE_ENTIRE_MESSAGE, ... // // IN ReceiveLength // size of TSDU data // // IN StartingOffset // offset of data in TSDU // // IN Tsdu // pointer to chain of data MDLs // // IN TsduDescriptor // descriptor for TdiReturnChainedReceives // // Return Value: // Status // NTSTATUS CprTdiEventChainedReceiveExpedited( IN PVOID TdiEventContext, IN CONNECTION_CONTEXT ConnectionContext, IN ULONG ReceiveFlags, IN ULONG ReceiveLength, IN ULONG StartingOffset, IN PMDL Tsdu, IN PVOID TsduDescriptor ) { CprDebugPrint(NULL, DBG_READ | DBG_IO | DBG_TDI, DBG_TRACE, __FUNCTION__"++"); CprDebugPrint(NULL, DBG_READ | DBG_IO | DBG_TDI, DBG_TRACE, __FUNCTION__"--"); return STATUS_SUCCESS; } /////////////////////////////////////////////////////////////////////////////////////////////////// // CprTdiEventReceiveDatagram // datagram receive event handler // // Arguments: // IN TdiEventContext // our socket // // IN SourceAddressLength // size of source address buffer // // IN SourceAddress // address of a remote node, which sent the datagram // // IN OptionsLength // size of options buffer // // IN Options // transport specific options // // IN ReceiveDatagramFlags // TDI_RECEIVE_ENTIRE_MESSAGE, TDI_RECEIVE_COPY_LOOKAHEAD, TDI_RECEIVE_BROADCAST, ... // // IN BytesIndicated // size of TSDU currently available // // OUT BytesAvailable // total size of TSDU // // OUT BytesTaken // count of bytes copied out of TSDU // // IN Tsdu // received data buffer // // OUT Irp // TdiBuildReceiveDatagram irp // // // Return Value: // Status // NTSTATUS CprTdiEventReceiveDatagram( IN PVOID TdiEventContext, IN LONG SourceAddressLength, IN PVOID SourceAddress, IN LONG OptionsLength, IN PVOID Options, IN ULONG ReceiveDatagramFlags, IN ULONG BytesIndicated, IN ULONG BytesAvailable, OUT PULONG BytesTaken, IN PVOID Tsdu, OUT PIRP* Irp ) { CprDebugPrint(NULL, DBG_READ | DBG_IO | DBG_TDI, DBG_TRACE, __FUNCTION__"++"); *BytesTaken = BytesIndicated; CprDebugPrint(NULL, DBG_READ | DBG_IO | DBG_TDI, DBG_TRACE, __FUNCTION__"--"); return STATUS_SUCCESS; } /////////////////////////////////////////////////////////////////////////////////////////////////// // CprTdiEventReceiveConfigDatagram // datagram receive event handler // // Arguments: // IN TdiEventContext // our socket // // IN SourceAddressLength // size of source address buffer // // IN SourceAddress // address of a remote node, which sent the datagram // // IN OptionsLength // size of options buffer // // IN Options // transport specific options // // IN ReceiveDatagramFlags // TDI_RECEIVE_ENTIRE_MESSAGE, TDI_RECEIVE_COPY_LOOKAHEAD, TDI_RECEIVE_BROADCAST, ... // // IN BytesIndicated // size of TSDU currently available // // OUT BytesAvailable // total size of TSDU // // OUT BytesTaken // count of bytes copied out of TSDU // // IN Tsdu // received data buffer // // OUT Irp // TdiBuildReceiveDatagram irp // // // Return Value: // Status // NTSTATUS CprTdiEventReceiveConfigDatagram( IN PVOID TdiEventContext, IN LONG SourceAddressLength, IN PVOID SourceAddress, IN LONG OptionsLength, IN PVOID Options, IN ULONG ReceiveDatagramFlags, IN ULONG BytesIndicated, IN ULONG BytesAvailable, OUT PULONG BytesTaken, IN PVOID Tsdu, OUT PIRP* Irp ) { PCPR_TDI_SOCKET socket; PCPR_DEVICE_EXTENSION pDevExt; PUCHAR inBuf = (PUCHAR)Tsdu; socket = (PCPR_TDI_SOCKET)TdiEventContext; ASSERT(socket != NULL); //KeSetEvent(&socket->LtxLockEvent, IO_NO_INCREMENT, FALSE); if (socket == NULL || socket->Uart == NULL) return STATUS_SUCCESS; pDevExt = socket->Uart->DeviceExtension; if ((g_DebugArea & (DBG_READ | DBG_IO | DBG_TDI)) && (DBG_INFO <= g_DebugLevel)) { CprDebugPrint(pDevExt, DBG_READ | DBG_IO | DBG_TDI, DBG_TRACE, __FUNCTION__"++"); CprDumpBuffer(__FUNCTION__, inBuf, BytesIndicated); } if ((BytesIndicated == 30) && (inBuf[3] == 0xF7) && (inBuf[0] == 0x0) && (inBuf[2] == 0x0)) { // Cobos pDevExt->MacAddress[0] = inBuf[24]; pDevExt->MacAddress[1] = inBuf[25]; pDevExt->MacAddress[2] = inBuf[26]; pDevExt->MacAddress[3] = inBuf[27]; pDevExt->MacAddress[4] = inBuf[28]; pDevExt->MacAddress[5] = inBuf[29]; pDevExt->DeviceId[0] = inBuf[8]; pDevExt->DeviceId[1] = inBuf[9]; pDevExt->DeviceId[2] = '\0'; } else if ((BytesIndicated >= 5) && (inBuf[3] == 0x50) && (inBuf[0] == 0x0) && (inBuf[2] == 0x0)) { // purge response // inBuf[4] == 0x81 means success pDevExt->PurgeResponse = inBuf[4]; } else if ((BytesIndicated > 11) && (inBuf[0] == 1) && (inBuf[1] == 4)) { // Gordian //KdPrint(("* * * * * * Source Address %X, Contents %X, Length %X\n", // SourceAddress, *((ULONG*)SourceAddress), SourceAddressLength)); if (TRUE) { // I think I need to use a broadcast on Gordian devices. // Therefore, I need to check the IP address also. pDevExt->MacAddress[0] = inBuf[6]; pDevExt->MacAddress[1] = inBuf[7]; pDevExt->MacAddress[2] = inBuf[8]; pDevExt->MacAddress[3] = inBuf[9]; pDevExt->MacAddress[4] = inBuf[10]; pDevExt->MacAddress[5] = inBuf[11]; if (BytesIndicated > 102) { pDevExt->DeviceId[0] = inBuf[100]; pDevExt->DeviceId[1] = inBuf[101]; pDevExt->DeviceId[2] = inBuf[102]; pDevExt->DeviceId[3] = '\0'; } } } //DbgPrint(" ******* %X %X %X %X\n", pDevExt->DeviceId[0], pDevExt->DeviceId[1], pDevExt->DeviceId[2], pDevExt->DeviceId[3]); KeSetEvent(&socket->LtxLockEvent, IO_NO_INCREMENT, FALSE); *BytesTaken = BytesIndicated; CprDebugPrint(pDevExt, DBG_READ | DBG_IO | DBG_TDI, DBG_TRACE, __FUNCTION__"--"); return STATUS_SUCCESS; } /////////////////////////////////////////////////////////////////////////////////////////////////// // CprTdiEventReceiveMacResolutionDatagram // datagram receive event handler // // Arguments: // IN TdiEventContext // our socket // // IN SourceAddressLength // size of source address buffer // // IN SourceAddress // address of a remote node, which sent the datagram // // IN OptionsLength // size of options buffer // // IN Options // transport specific options // // IN ReceiveDatagramFlags // TDI_RECEIVE_ENTIRE_MESSAGE, TDI_RECEIVE_COPY_LOOKAHEAD, TDI_RECEIVE_BROADCAST, ... // // IN BytesIndicated // size of TSDU currently available // // OUT BytesAvailable // total size of TSDU // // OUT BytesTaken // count of bytes copied out of TSDU // // IN Tsdu // received data buffer // // OUT Irp // TdiBuildReceiveDatagram irp // // // Return Value: // Status // NTSTATUS CprTdiEventReceiveMacResolutionDatagram( IN PVOID TdiEventContext, IN LONG SourceAddressLength, IN PVOID SourceAddress, IN LONG OptionsLength, IN PVOID Options, IN ULONG ReceiveDatagramFlags, IN ULONG BytesIndicated, IN ULONG BytesAvailable, OUT PULONG BytesTaken, IN PVOID Tsdu, OUT PIRP* Irp ) { PCPR_TDI_SOCKET socket; PCPR_DEVICE_EXTENSION pDevExt; PUCHAR inBuf = (PUCHAR)Tsdu; socket = (PCPR_TDI_SOCKET)TdiEventContext; ASSERT(socket != NULL); //KeSetEvent(&socket->LtxLockEvent, IO_NO_INCREMENT, FALSE); pDevExt = socket->Uart->DeviceExtension; if ((g_DebugArea & (DBG_READ | DBG_IO | DBG_TDI)) && (DBG_INFO <= g_DebugLevel)) { CprDebugPrint(pDevExt, DBG_READ | DBG_IO | DBG_TDI, DBG_TRACE, __FUNCTION__"++"); CprDumpBuffer(__FUNCTION__, inBuf, BytesIndicated); } if ((BytesIndicated == 30) && (inBuf[3] == 0xF7) && (inBuf[0] == 0x0) && (inBuf[2] == 0x0)) { // Cobos UCHAR *mac = pDevExt->MacAddress; if ((mac[0] == inBuf[24]) && (mac[1] == inBuf[25]) && (mac[2] == inBuf[26]) && (mac[3] == inBuf[27]) && (mac[4] == inBuf[28]) && (mac[5] == inBuf[29])) { pDevExt->ResolvedIpAddress = *((ULONG*)SourceAddress); KeSetEvent(&socket->LtxLockEvent, IO_NO_INCREMENT, FALSE); } } else if ((BytesIndicated >= 5) && (inBuf[3] == 0x50) && (inBuf[0] == 0x0) && (inBuf[2] == 0x0)) { // purge response // inBuf[4] == 0x81 means success pDevExt->PurgeResponse = inBuf[4]; } else if ((BytesIndicated > 11) && (inBuf[0] == 1) && (inBuf[1] == 4)) { // Gordian UCHAR *mac = pDevExt->MacAddress; if ((mac[0] == inBuf[6]) && (mac[1] == inBuf[7]) && (mac[2] == inBuf[8]) && (mac[3] == inBuf[9]) && (mac[4] == inBuf[10]) && (mac[5] == inBuf[11])) { pDevExt->ResolvedIpAddress = *((ULONG*)SourceAddress); KeSetEvent(&socket->LtxLockEvent, IO_NO_INCREMENT, FALSE); } } *BytesTaken = BytesIndicated; CprDebugPrint(pDevExt, DBG_READ | DBG_IO | DBG_TDI, DBG_TRACE, __FUNCTION__"--"); return STATUS_SUCCESS; } /////////////////////////////////////////////////////////////////////////////////////////////////// // CprTdiEventChainedReceiveDatagram // datagram receive event handler // // Arguments: // IN TdiEventContext // our socket // // IN SourceAddressLength // size of source address buffer // // IN SourceAddress // address of a remote node, which sent the datagram // // IN OptionsLength // size of options buffer // // IN Options // transport specific options // // IN ReceiveDatagramFlags // TDI_RECEIVE_ENTIRE_MESSAGE, TDI_RECEIVE_BROADCAST, ... // // IN ReceiveDatagramLength // size of TSDU data // // IN StartingOffset // offset of data in TSDU // // IN Tsdu // pointer to chain of data MDLs // // IN TsduDescriptor // descriptor for TdiReturnChainedReceives // // Return Value: // Status // NTSTATUS CprTdiEventChainedReceiveDatagram( IN PVOID TdiEventContext, IN LONG SourceAddressLength, IN PVOID SourceAddress, IN LONG OptionsLength, IN PVOID Options, IN ULONG ReceiveDatagramFlags, IN ULONG ReceiveDatagramLength, IN ULONG StartingOffset, IN PMDL Tsdu, IN PVOID TsduDescriptor ) { CprDebugPrint(NULL, DBG_READ | DBG_IO | DBG_TDI, DBG_TRACE, __FUNCTION__"++"); CprDebugPrint(NULL, DBG_READ | DBG_IO | DBG_TDI, DBG_TRACE, __FUNCTION__"--"); return STATUS_SUCCESS; } /////////////////////////////////////////////////////////////////////////////////////////////////// // CprTdiEventSendPossible // device ready to handle send event handler // // Arguments: // IN TdiEventContext // our server socket // // IN ConnectionContext // our connection socket // // IN BytesAvailable // size of available send buffer // // Return Value: // Status // NTSTATUS CprTdiEventSendPossible( IN PVOID TdiEventContext, IN PVOID ConnectionContext, IN ULONG BytesAvailable ) { CprDebugPrint(NULL, DBG_TDI | DBG_IO, DBG_TRACE, __FUNCTION__"++"); CprDebugPrint(NULL, DBG_TDI | DBG_IO, DBG_TRACE, __FUNCTION__"--"); return STATUS_SUCCESS; } /////////////////////////////////////////////////////////////////////////////////////////////////// // CprTdiEventError // error event handler // // Arguments: // IN TdiEventContext // our socket // // IN Status // error status // // Return Value: // Status // NTSTATUS CprTdiEventError( IN PVOID TdiEventContext, IN NTSTATUS Status ) { CprDebugPrint1(NULL, DBG_IO | DBG_IO, DBG_TRACE, __FUNCTION__"++. STATUS %x", Status); // TODO: Should close down connection, something catastrophic has happened. CprDebugPrint(NULL, DBG_IO | DBG_IO, DBG_TRACE, __FUNCTION__"--"); return STATUS_SUCCESS; } /////////////////////////////////////////////////////////////////////////////////////////////////// // CprTdiEventErrorEx // error event handler // // Arguments: // IN TdiEventContext // our socket // // IN Status // error status // // IN Buffer // transport specific error information // // Return Value: // Status // NTSTATUS CprTdiEventErrorEx( IN PVOID TdiEventContext, IN NTSTATUS Status, IN PVOID Buffer ) { CprDebugPrint1(NULL, DBG_IO | DBG_IO, DBG_TRACE, __FUNCTION__"++. STATUS %x", Status); // TODO: Should close down connection, something catastrophic has happened. // If this is registered, should CprTdiEventError be register? CprDebugPrint(NULL, DBG_IO | DBG_IO, DBG_TRACE, __FUNCTION__"--"); return STATUS_SUCCESS; }