*/
#include "precomp.h"
+#include <pseh/pseh.h>
+
+extern VOID DeleteConnectionEndpoint( PCONNECTION_ENDPOINT Endpoint );
NTSTATUS DispPrepareIrpForCancel(
PTRANSPORT_CONTEXT Context,
if (!Irp->Cancel) {
IoMarkIrpPending(Irp);
IoSetCancelRoutine(Irp, CancelRoutine);
- Context->RefCount++;
IoReleaseCancelSpinLock(OldIrql);
TI_DbgPrint(DEBUG_IRP, ("Leaving (IRP at 0x%X can now be cancelled).\n", Irp));
}
/* IRP has already been cancelled */
-
+
IoReleaseCancelSpinLock(OldIrql);
Irp->IoStatus.Status = STATUS_CANCELLED;
* Context = Pointer to context information (FILE_OBJECT)
*/
{
- KIRQL OldIrql;
+ /*KIRQL OldIrql;*/
PFILE_OBJECT FileObject;
PTRANSPORT_CONTEXT TranContext;
-
+
TI_DbgPrint(DEBUG_IRP, ("Called.\n"));
FileObject = (PFILE_OBJECT)Context;
TranContext = (PTRANSPORT_CONTEXT)FileObject->FsContext;
-
+
+ /* Set the cleanup event */
+ KeSetEvent(&TranContext->CleanupEvent, 0, FALSE);
+
+ /* We are expected to release the cancel spin lock */
+ /*IoReleaseCancelSpinLock(OldIrql);*/
+
+ TI_DbgPrint(DEBUG_IRP, ("Leaving.\n"));
+}
+
+
+VOID DispDataRequestComplete(
+ PVOID Context,
+ NTSTATUS Status,
+ ULONG Count)
+/*
+ * FUNCTION: Completes a send/receive IRP
+ * ARGUMENTS:
+ * Context = Pointer to context information (IRP)
+ * Status = Status of the request
+ * Count = Number of bytes sent or received
+ */
+{
+ PIRP Irp;
+ PIO_STACK_LOCATION IrpSp;
+ PTRANSPORT_CONTEXT TranContext;
+ KIRQL OldIrql;
+
+ TI_DbgPrint(DEBUG_IRP, ("Called for irp %x (%x, %d).\n",
+ Context, Status, Count));
+
+ Irp = Context;
+ IrpSp = IoGetCurrentIrpStackLocation(Irp);
+ TranContext = (PTRANSPORT_CONTEXT)IrpSp->FileObject->FsContext;
+
IoAcquireCancelSpinLock(&OldIrql);
- /* Remove the reference taken by the cancel routine */
- TranContext->RefCount--;
+ IoSetCancelRoutine(Irp, NULL);
- if (TranContext->RefCount == 0) {
- TI_DbgPrint(DEBUG_IRP, ("Setting TranContext->CleanupEvent to signaled.\n"));
- /* Set the cleanup event */
- KeSetEvent(&TranContext->CleanupEvent, 0, FALSE);
- }
+ if (Irp->Cancel || TranContext->CancelIrps) {
+ /* The IRP has been cancelled */
- TI_DbgPrint(DEBUG_REFCOUNT, ("TranContext->RefCount (%d).\n", TranContext->RefCount));
+ TI_DbgPrint(DEBUG_IRP, ("IRP is cancelled.\n"));
+
+ Status = STATUS_CANCELLED;
+ Count = 0;
+ }
IoReleaseCancelSpinLock(OldIrql);
- TI_DbgPrint(DEBUG_IRP, ("Leaving.\n"));
+ Irp->IoStatus.Status = Status;
+ Irp->IoStatus.Information = Count;
+
+ TI_DbgPrint(MID_TRACE, ("Irp->IoStatus.Status = %x\n",
+ Irp->IoStatus.Status));
+ TI_DbgPrint(MID_TRACE, ("Irp->IoStatus.Information = %d\n",
+ Irp->IoStatus.Information));
+ TI_DbgPrint(DEBUG_IRP, ("Completing IRP at (0x%X).\n", Irp));
+
+ IRPFinish(Irp, Irp->IoStatus.Status);
+
+ TI_DbgPrint(DEBUG_IRP, ("Done Completing IRP\n"));
}
+VOID DDKAPI CancelQueuePassiveHandler( PVOID CancelRequestVoid )
+{
+ KIRQL OldIrql;
+ PCANCEL_REQUEST CancelReq;
+ PLIST_ENTRY CqEntry;
+
+ KeAcquireSpinLock( &CancelQueueLock, &OldIrql );
+
+ TI_DbgPrint(DEBUG_IRP,("CANCEL QUEUE: Starting\n"));
+
+ for( CqEntry = CancelQueue.Flink;
+ CqEntry != &CancelQueue;
+ ) {
+ CancelReq = CONTAINING_RECORD(CqEntry, CANCEL_REQUEST, Entry);
+ ExInterlockedRemoveHeadList( &CancelQueue, &CancelQueueLock );
+ CqEntry = CancelQueue.Flink;
+
+ KeReleaseSpinLock( &CancelQueueLock, OldIrql );
+
+ TI_DbgPrint(DEBUG_IRP,("CANCEL QUEUE: Executing %x\n", CancelReq));
+
+ switch( CancelReq->Type ) {
+ case TCP_CANCEL_DISCONNECT:
+ TCPDisconnect
+ ( CancelReq->Context,
+ CancelReq->Flags,
+ NULL,
+ NULL,
+ DispDataRequestComplete,
+ CancelReq->Irp );
+ break;
+
+ case TCP_CANCEL_CLOSE:
+ TCPClose( CancelReq->Context );
+ DeleteConnectionEndpoint( CancelReq->Context );
+ break;
+ }
+
+ TCPMarkForDisconnect( CancelReq->Context, FALSE );
+
+ ExFreePool( CancelReq );
+
+ KeAcquireSpinLock( &CancelQueueLock, &OldIrql );
+ }
+
+ TI_DbgPrint(DEBUG_IRP,("CANCEL QUEUE: Ending\n"));
+
+ KeReleaseSpinLock( &CancelQueueLock, OldIrql );
+}
-VOID DispCancelRequest(
+VOID DDKAPI DispCancelRequest(
PDEVICE_OBJECT Device,
PIRP Irp)
/*
PTRANSPORT_CONTEXT TranContext;
PFILE_OBJECT FileObject;
UCHAR MinorFunction;
- NTSTATUS Status = STATUS_SUCCESS;
+ PCANCEL_REQUEST CancelRequest;
+ /*NTSTATUS Status = STATUS_SUCCESS;*/
TI_DbgPrint(DEBUG_IRP, ("Called.\n"));
TI_DbgPrint(MIN_TRACE, ("Irp->Cancel is FALSE, should be TRUE.\n"));
#endif
- /* Increase reference count to prevent accidential closure
- of the object while inside the cancel routine */
- TranContext->RefCount++;
-
- IoReleaseCancelSpinLock(Irp->CancelIrql);
-
/* Try canceling the request */
switch(MinorFunction) {
case TDI_SEND:
-
case TDI_RECEIVE:
- /* FIXME: Close connection */
+ CancelRequest = ExAllocatePoolWithTag
+ ( sizeof(CANCEL_REQUEST), NonPagedPool, FOURCC('T','c','k','O') );
+ TCPMarkForDisconnect( TranContext->Handle.ConnectionContext, TRUE );
+ if( CancelRequest ) {
+ TI_DbgPrint(DEBUG_IRP,("CANCEL QUEUE:-> %x\n", CancelRequest));
+ CancelRequest->Flags = TDI_DISCONNECT_RELEASE |
+ (MinorFunction == TDI_RECEIVE) ? TDI_DISCONNECT_ABORT : 0;
+ CancelRequest->Context = TranContext->Handle.ConnectionContext;
+ CancelRequest->Irp = Irp;
+ CancelRequest->Type = TCP_CANCEL_DISCONNECT;
+ ExInterlockedInsertTailList
+ ( &CancelQueue, &CancelRequest->Entry, &CancelQueueLock );
+ ExQueueWorkItem( &CancelQueueWork, CriticalWorkQueue );
+ }
break;
case TDI_SEND_DATAGRAM:
break;
}
- DGCancelSendRequest(TranContext->Handle.AddressHandle, Irp);
+ /*DGCancelSendRequest(TranContext->Handle.AddressHandle, Irp);*/
break;
case TDI_RECEIVE_DATAGRAM:
break;
}
- DGCancelReceiveRequest(TranContext->Handle.AddressHandle, Irp);
+ /*DGCancelReceiveRequest(TranContext->Handle.AddressHandle, Irp);*/
break;
default:
break;
}
- if (Status != STATUS_PENDING)
- DispCancelComplete(FileObject);
+ IoReleaseCancelSpinLock(Irp->CancelIrql);
+
+ DispCancelComplete(FileObject);
TI_DbgPrint(MAX_TRACE, ("Leaving.\n"));
}
-VOID DispDataRequestComplete(
- PVOID Context,
- NTSTATUS Status,
- ULONG Count)
+VOID DDKAPI DispCancelListenRequest(
+ PDEVICE_OBJECT Device,
+ PIRP Irp)
/*
- * FUNCTION: Completes a send/receive IRP
+ * FUNCTION: Cancels a listen IRP
* ARGUMENTS:
- * Context = Pointer to context information (IRP)
- * Status = Status of the request
- * Count = Number of bytes sent or received
+ * Device = Pointer to device object
+ * Irp = Pointer to an I/O request packet
*/
{
- PIRP Irp;
PIO_STACK_LOCATION IrpSp;
PTRANSPORT_CONTEXT TranContext;
- KIRQL OldIrql;
-
- TI_DbgPrint(DEBUG_IRP, ("Called for irp %x (%x, %d).\n",
- Context, Status, Count));
-
- Irp = Context;
- IrpSp = IoGetCurrentIrpStackLocation(Irp);
- TranContext = (PTRANSPORT_CONTEXT)IrpSp->FileObject->FsContext;
-
- IoAcquireCancelSpinLock(&OldIrql);
+ PFILE_OBJECT FileObject;
+ PCONNECTION_ENDPOINT Connection;
+ /*NTSTATUS Status = STATUS_SUCCESS;*/
- IoSetCancelRoutine(Irp, NULL);
- TranContext->RefCount--;
- TI_DbgPrint(DEBUG_REFCOUNT, ("TranContext->RefCount (%d).\n", TranContext->RefCount));
- if (TranContext->RefCount == 0) {
- TI_DbgPrint(DEBUG_IRP, ("Setting TranContext->CleanupEvent to signaled.\n"));
+ TI_DbgPrint(DEBUG_IRP, ("Called.\n"));
- KeSetEvent(&TranContext->CleanupEvent, 0, FALSE);
- }
+ IrpSp = IoGetCurrentIrpStackLocation(Irp);
+ FileObject = IrpSp->FileObject;
+ TranContext = (PTRANSPORT_CONTEXT)FileObject->FsContext;
+ ASSERT( TDI_LISTEN == IrpSp->MinorFunction);
- if (Irp->Cancel || TranContext->CancelIrps) {
- /* The IRP has been cancelled */
+ TI_DbgPrint(DEBUG_IRP, ("IRP at (0x%X).\n", Irp));
- TI_DbgPrint(DEBUG_IRP, ("IRP is cancelled.\n"));
+#ifdef DBG
+ if (!Irp->Cancel)
+ TI_DbgPrint(MIN_TRACE, ("Irp->Cancel is FALSE, should be TRUE.\n"));
+#endif
- Status = STATUS_CANCELLED;
- Count = 0;
- }
+ /* Try canceling the request */
+ Connection = (PCONNECTION_ENDPOINT)TranContext->Handle.ConnectionContext;
+ TCPAbortListenForSocket(
+ Connection->AddressFile->Listener,
+ Connection );
- IoReleaseCancelSpinLock(OldIrql);
+ IoReleaseCancelSpinLock(Irp->CancelIrql);
- Irp->IoStatus.Status = Status;
- Irp->IoStatus.Information = Count;
+ DispDataRequestComplete(Irp, STATUS_CANCELLED, 0);
- TI_DbgPrint(MID_TRACE, ("Irp->IoStatus.Status = %x\n",
- Irp->IoStatus.Status));
- TI_DbgPrint(MID_TRACE, ("Irp->IoStatus.Information = %d\n",
- Irp->IoStatus.Information));
- TI_DbgPrint(DEBUG_IRP, ("Completing IRP at (0x%X).\n", Irp));
+ DispCancelComplete(FileObject);
- IRPFinish(Irp, STATUS_SUCCESS);
+ TI_DbgPrint(MAX_TRACE, ("Leaving.\n"));
}
(PVOID*)&FileObject,
NULL);
if (!NT_SUCCESS(Status)) {
- TI_DbgPrint(MID_TRACE, ("Bad address file object handle (0x%X).\n",
- Parameters->AddressHandle));
+ TI_DbgPrint(MID_TRACE, ("Bad address file object handle (0x%X): %x.\n",
+ Parameters->AddressHandle, Status));
return STATUS_INVALID_PARAMETER;
}
TI_DbgPrint(MID_TRACE, ("No address file object.\n"));
return STATUS_INVALID_PARAMETER;
}
- /* The connection endpoint references the address file object */
- ReferenceObject(AddrFile);
+
Connection->AddressFile = AddrFile;
/* Add connection endpoint to the address file */
/* FIXME: Maybe do this in DispTdiDisassociateAddress() instead? */
ObDereferenceObject(FileObject);
- return Status;
+ return Status;
}
PTDI_REQUEST_KERNEL Parameters;
PTRANSPORT_CONTEXT TranContext;
PIO_STACK_LOCATION IrpSp;
- TDI_REQUEST Request;
NTSTATUS Status;
TI_DbgPrint(DEBUG_IRP, ("Called.\n"));
Parameters = (PTDI_REQUEST_KERNEL)&IrpSp->Parameters;
- /* Initialize a connect request */
- Request.Handle.ConnectionContext = TranContext->Handle.ConnectionContext;
- Request.RequestNotifyObject = DispDataRequestComplete;
- Request.RequestContext = Irp;
-
-#if 0
- Status = TCPBind( Connection,
- &Connection->SocketContext,
- Parameters->RequestConnectionInformation );
-
- TI_DbgPrint(MID_TRACE, ("TCP Bind returned %08x\n", Status));
-
- if( NT_SUCCESS(Status) )
-#endif
+ Status = TCPConnect(
+ TranContext->Handle.ConnectionContext,
+ Parameters->RequestConnectionInformation,
+ Parameters->ReturnConnectionInformation,
+ DispDataRequestComplete,
+ Irp );
- Status = TCPConnect(
- &Request,
- Parameters->RequestConnectionInformation,
- Parameters->ReturnConnectionInformation);
-
TI_DbgPrint(MAX_TRACE, ("TCP Connect returned %08x\n", Status));
return Status;
PCONNECTION_ENDPOINT Connection;
PTRANSPORT_CONTEXT TranContext;
PIO_STACK_LOCATION IrpSp;
- KIRQL OldIrql;
TI_DbgPrint(DEBUG_IRP, ("Called.\n"));
return STATUS_INVALID_PARAMETER;
}
- /* Remove the reference put on the address file object */
- KeAcquireSpinLock(&Connection->Lock, &OldIrql);
- DereferenceObject(Connection->AddressFile);
- KeReleaseSpinLock(&Connection->Lock, OldIrql);
-
return STATUS_SUCCESS;
}
* Status of operation
*/
{
- PTDI_REQUEST_KERNEL_QUERY_INFORMATION Parameters;
+ NTSTATUS Status;
+ PTDI_REQUEST_KERNEL_DISCONNECT DisReq;
+ PCONNECTION_ENDPOINT Connection;
PTRANSPORT_CONTEXT TranContext;
PIO_STACK_LOCATION IrpSp;
TI_DbgPrint(DEBUG_IRP, ("Called.\n"));
IrpSp = IoGetCurrentIrpStackLocation(Irp);
- Parameters = (PTDI_REQUEST_KERNEL_QUERY_INFORMATION)&IrpSp->Parameters;
+ DisReq = (PTDI_REQUEST_KERNEL_DISCONNECT)&IrpSp->Parameters;
+
+ /* Get associated connection endpoint file object. Quit if none exists */
TranContext = IrpSp->FileObject->FsContext;
if (!TranContext) {
return STATUS_INVALID_CONNECTION;
}
- switch (Parameters->QueryType)
- {
- case TDI_QUERY_ADDRESS_INFO:
- {
- PTDI_ADDRESS_INFO AddressInfo;
- PADDRESS_FILE AddrFile;
- PTA_IP_ADDRESS Address;
-
- AddressInfo = (PTDI_ADDRESS_INFO)MmGetSystemAddressForMdl(Irp->MdlAddress);
-
- switch ((ULONG)IrpSp->FileObject->FsContext2) {
- case TDI_TRANSPORT_ADDRESS_FILE:
- AddrFile = (PADDRESS_FILE)TranContext->Handle.AddressHandle;
- break;
-
- case TDI_CONNECTION_FILE:
- AddrFile = ((PCONNECTION_ENDPOINT)TranContext->Handle.ConnectionContext)->AddressFile;
- break;
-
- default:
- TI_DbgPrint(MIN_TRACE, ("Invalid transport context\n"));
- return STATUS_INVALID_PARAMETER;
- }
-
- if (!AddrFile) {
- TI_DbgPrint(MID_TRACE, ("No address file object.\n"));
- return STATUS_INVALID_PARAMETER;
- }
-
- if (MmGetMdlByteCount(Irp->MdlAddress) <
- (sizeof(TDI_ADDRESS_INFO) + sizeof(TDI_ADDRESS_IP))) {
- TI_DbgPrint(MID_TRACE, ("MDL buffer too small.\n"));
- return STATUS_BUFFER_OVERFLOW;
- }
-
- /* FIXME: Is this count really the one we should return? */
- AddressInfo->ActivityCount = AddrFile->RefCount;
+ Connection = (PCONNECTION_ENDPOINT)TranContext->Handle.ConnectionContext;
+ if (!Connection) {
+ TI_DbgPrint(MID_TRACE, ("No connection endpoint file object.\n"));
+ return STATUS_INVALID_CONNECTION;
+ }
- Address = (PTA_IP_ADDRESS)&AddressInfo->Address;
- Address->TAAddressCount = 1;
- Address->Address[0].AddressLength = TDI_ADDRESS_LENGTH_IP;
- Address->Address[0].AddressType = TDI_ADDRESS_TYPE_IP;
- Address->Address[0].Address[0].sin_port = AddrFile->Port;
- Address->Address[0].Address[0].in_addr = AddrFile->ADE->Address->Address.IPv4Address;
- RtlZeroMemory(
- &Address->Address[0].Address[0].sin_zero,
- sizeof(Address->Address[0].Address[0].sin_zero));
+ Status = TCPDisconnect(
+ TranContext->Handle.ConnectionContext,
+ DisReq->RequestFlags,
+ DisReq->RequestConnectionInformation,
+ DisReq->ReturnConnectionInformation,
+ DispDataRequestComplete,
+ Irp );
- return STATUS_SUCCESS;
- }
- }
+ TI_DbgPrint(MAX_TRACE, ("TCP Connect returned %08x\n", Status));
- return STATUS_NOT_IMPLEMENTED;
+ return Status;
}
PTDI_REQUEST_KERNEL Parameters;
PTRANSPORT_CONTEXT TranContext;
PIO_STACK_LOCATION IrpSp;
- PTDI_REQUEST Request;
- NTSTATUS Status;
+ NTSTATUS Status = STATUS_SUCCESS;
TI_DbgPrint(DEBUG_IRP, ("Called.\n"));
Parameters = (PTDI_REQUEST_KERNEL)&IrpSp->Parameters;
- Status = TCPListen( Request, 1024 /* BACKLOG */ );
+ TI_DbgPrint(MIN_TRACE, ("Connection->AddressFile: %x\n",
+ Connection->AddressFile ));
+ if( Connection->AddressFile ) {
+ TI_DbgPrint(MIN_TRACE, ("Connection->AddressFile->Listener: %x\n",
+ Connection->AddressFile->Listener));
+ }
+
+ /* Listening will require us to create a listening socket and store it in
+ * the address file. It will be signalled, and attempt to complete an irp
+ * when a new connection arrives. */
+ /* The important thing to note here is that the irp we'll complete belongs
+ * to the socket to be accepted onto, not the listener */
+ if( !Connection->AddressFile->Listener ) {
+ Connection->AddressFile->Listener =
+ TCPAllocateConnectionEndpoint( NULL );
+
+ if( !Connection->AddressFile->Listener )
+ Status = STATUS_NO_MEMORY;
+
+ if( NT_SUCCESS(Status) ) {
+ Connection->AddressFile->Listener->AddressFile =
+ Connection->AddressFile;
+
+ Status = TCPSocket( Connection->AddressFile->Listener,
+ Connection->AddressFile->Family,
+ SOCK_STREAM,
+ Connection->AddressFile->Protocol );
+ }
+
+ if( NT_SUCCESS(Status) )
+ Status = TCPListen( Connection->AddressFile->Listener, 1024 );
+ /* BACKLOG */
+ }
+ if( NT_SUCCESS(Status) ) {
+ Status = DispPrepareIrpForCancel
+ (TranContext->Handle.ConnectionContext,
+ Irp,
+ (PDRIVER_CANCEL)DispCancelListenRequest);
+ }
+
+ if( NT_SUCCESS(Status) ) {
+ Status = TCPAccept
+ ( (PTDI_REQUEST)Parameters,
+ Connection->AddressFile->Listener,
+ Connection,
+ DispDataRequestComplete,
+ Irp );
+ }
+
+ TI_DbgPrint(MID_TRACE,("Leaving %x\n", Status));
return Status;
}
break;
case TDI_CONNECTION_FILE:
- AddrFile = ((PCONNECTION_ENDPOINT)TranContext->Handle.ConnectionContext)->AddressFile;
+ AddrFile =
+ ((PCONNECTION_ENDPOINT)TranContext->Handle.ConnectionContext)->
+ AddressFile;
break;
default:
}
if (MmGetMdlByteCount(Irp->MdlAddress) <
- (sizeof(TDI_ADDRESS_INFO) + sizeof(TDI_ADDRESS_IP))) {
+ (FIELD_OFFSET(TDI_ADDRESS_INFO, Address.Address[0].Address) +
+ sizeof(TDI_ADDRESS_IP))) {
TI_DbgPrint(MID_TRACE, ("MDL buffer too small.\n"));
return STATUS_BUFFER_OVERFLOW;
}
- /* FIXME: Is this count really the one we should return? */
- AddressInfo->ActivityCount = AddrFile->RefCount;
-
Address = (PTA_IP_ADDRESS)&AddressInfo->Address;
Address->TAAddressCount = 1;
Address->Address[0].AddressLength = TDI_ADDRESS_LENGTH_IP;
Address->Address[0].AddressType = TDI_ADDRESS_TYPE_IP;
Address->Address[0].Address[0].sin_port = AddrFile->Port;
- Address->Address[0].Address[0].in_addr = AddrFile->ADE->Address->Address.IPv4Address;
+ Address->Address[0].Address[0].in_addr =
+ AddrFile->Address.Address.IPv4Address;
RtlZeroMemory(
&Address->Address[0].Address[0].sin_zero,
sizeof(Address->Address[0].Address[0].sin_zero));
return STATUS_SUCCESS;
}
+
+ case TDI_QUERY_CONNECTION_INFO:
+ {
+ PTDI_CONNECTION_INFORMATION AddressInfo;
+ PADDRESS_FILE AddrFile;
+ PCONNECTION_ENDPOINT Endpoint = NULL;
+
+ AddressInfo = (PTDI_CONNECTION_INFORMATION)
+ MmGetSystemAddressForMdl(Irp->MdlAddress);
+
+ switch ((ULONG)IrpSp->FileObject->FsContext2) {
+ case TDI_TRANSPORT_ADDRESS_FILE:
+ AddrFile = (PADDRESS_FILE)TranContext->Handle.AddressHandle;
+ break;
+
+ case TDI_CONNECTION_FILE:
+ Endpoint =
+ (PCONNECTION_ENDPOINT)TranContext->Handle.ConnectionContext;
+ break;
+
+ default:
+ TI_DbgPrint(MIN_TRACE, ("Invalid transport context\n"));
+ return STATUS_INVALID_PARAMETER;
+ }
+
+ if (!Endpoint) {
+ TI_DbgPrint(MID_TRACE, ("No connection object.\n"));
+ return STATUS_INVALID_PARAMETER;
+ }
+
+ if (MmGetMdlByteCount(Irp->MdlAddress) <
+ (FIELD_OFFSET(TDI_CONNECTION_INFORMATION, RemoteAddress) +
+ sizeof(PVOID))) {
+ TI_DbgPrint(MID_TRACE, ("MDL buffer too small (ptr).\n"));
+ return STATUS_BUFFER_OVERFLOW;
+ }
+
+ return TCPGetPeerAddress( Endpoint, AddressInfo->RemoteAddress );
+ }
}
return STATUS_NOT_IMPLEMENTED;
PIO_STACK_LOCATION IrpSp;
PTDI_REQUEST_KERNEL_RECEIVE ReceiveInfo;
PTRANSPORT_CONTEXT TranContext;
- TDI_REQUEST Request;
NTSTATUS Status;
ULONG BytesReceived;
}
/* Initialize a receive request */
- Request.Handle.ConnectionContext = TranContext->Handle.ConnectionContext;
- Request.RequestNotifyObject = DispDataRequestComplete;
- Request.RequestContext = Irp;
- Status = DispPrepareIrpForCancel(
- IrpSp->FileObject->FsContext,
- Irp,
- (PDRIVER_CANCEL)DispCancelRequest);
+ Status = DispPrepareIrpForCancel
+ (TranContext->Handle.ConnectionContext,
+ Irp,
+ (PDRIVER_CANCEL)DispCancelRequest);
+
TI_DbgPrint(MID_TRACE,("TCPIP<<< Got an MDL: %x\n", Irp->MdlAddress));
if (NT_SUCCESS(Status))
{
Status = TCPReceiveData(
- &Request,
- (PNDIS_BUFFER)Irp->MdlAddress,
- ReceiveInfo->ReceiveLength,
- ReceiveInfo->ReceiveFlags,
- &BytesReceived);
+ TranContext->Handle.ConnectionContext,
+ (PNDIS_BUFFER)Irp->MdlAddress,
+ ReceiveInfo->ReceiveLength,
+ &BytesReceived,
+ ReceiveInfo->ReceiveFlags,
+ DispDataRequestComplete,
+ Irp);
if (Status != STATUS_PENDING)
{
DispDataRequestComplete(Irp, Status, BytesReceived);
- }
- }
-
- if (Status != STATUS_PENDING)
- {
- IrpSp->Control &= ~SL_PENDING_RETURNED;
+ } else
+ IoMarkIrpPending(Irp);
}
TI_DbgPrint(DEBUG_IRP, ("Leaving. Status is (0x%X)\n", Status));
Request.Handle.AddressHandle = TranContext->Handle.AddressHandle;
Request.RequestNotifyObject = DispDataRequestComplete;
Request.RequestContext = Irp;
+
Status = DispPrepareIrpForCancel(
IrpSp->FileObject->FsContext,
Irp,
(PDRIVER_CANCEL)DispCancelRequest);
+
if (NT_SUCCESS(Status))
{
+ PCHAR DataBuffer;
+ UINT BufferSize;
+
+ NdisQueryBuffer( (PNDIS_BUFFER)Irp->MdlAddress,
+ &DataBuffer,
+ &BufferSize );
+
Status = UDPReceiveDatagram(
- &Request,
- DgramInfo->ReceiveDatagramInformation,
- (PNDIS_BUFFER)Irp->MdlAddress,
- DgramInfo->ReceiveLength,
- DgramInfo->ReceiveFlags,
- DgramInfo->ReturnDatagramInformation,
- &BytesReceived);
- if (Status != STATUS_PENDING)
- {
+ Request.Handle.AddressHandle,
+ DgramInfo->ReceiveDatagramInformation,
+ DataBuffer,
+ DgramInfo->ReceiveLength,
+ DgramInfo->ReceiveFlags,
+ DgramInfo->ReturnDatagramInformation,
+ &BytesReceived,
+ (PDATAGRAM_COMPLETION_ROUTINE)DispDataRequestComplete,
+ Irp);
+ if (Status != STATUS_PENDING) {
DispDataRequestComplete(Irp, Status, BytesReceived);
- }
- }
-
- if (Status != STATUS_PENDING)
- {
- IrpSp->Control &= ~SL_PENDING_RETURNED;
+ } else
+ IoMarkIrpPending(Irp);
}
TI_DbgPrint(DEBUG_IRP, ("Leaving. Status is (0x%X)\n", Status));
PIO_STACK_LOCATION IrpSp;
PTDI_REQUEST_KERNEL_RECEIVE ReceiveInfo;
PTRANSPORT_CONTEXT TranContext;
- TDI_REQUEST Request;
NTSTATUS Status;
ULONG BytesReceived;
return STATUS_INVALID_CONNECTION;
}
- /* Initialize a receive request */
- Request.Handle.ConnectionContext = TranContext->Handle.ConnectionContext;
- Request.RequestNotifyObject = DispDataRequestComplete;
- Request.RequestContext = Irp;
Status = DispPrepareIrpForCancel(
IrpSp->FileObject->FsContext,
Irp,
(PDRIVER_CANCEL)DispCancelRequest);
+
TI_DbgPrint(MID_TRACE,("TCPIP<<< Got an MDL: %x\n", Irp->MdlAddress));
if (NT_SUCCESS(Status))
{
+ PCHAR Data;
+ UINT Len;
+
+ NdisQueryBuffer( Irp->MdlAddress, &Data, &Len );
+
TI_DbgPrint(MID_TRACE,("About to TCPSendData\n"));
Status = TCPSendData(
- &Request,
- (PNDIS_BUFFER)Irp->MdlAddress,
+ TranContext->Handle.ConnectionContext,
+ Data,
ReceiveInfo->ReceiveLength,
- ReceiveInfo->ReceiveFlags,
- &BytesReceived);
+ &BytesReceived,
+ ReceiveInfo->ReceiveFlags);
if (Status != STATUS_PENDING)
{
DispDataRequestComplete(Irp, Status, BytesReceived);
- }
- }
-
- if (Status != STATUS_PENDING)
- {
- IrpSp->Control &= ~SL_PENDING_RETURNED;
+ } else
+ IoMarkIrpPending( Irp );
}
TI_DbgPrint(DEBUG_IRP, ("Leaving. Status is (0x%X)\n", Status));
IrpSp->FileObject->FsContext,
Irp,
(PDRIVER_CANCEL)DispCancelRequest);
+
if (NT_SUCCESS(Status)) {
+ PCHAR DataBuffer;
+ UINT BufferSize;
+
+ TI_DbgPrint(MID_TRACE,("About to query buffer %x\n", Irp->MdlAddress));
- /* FIXME: DgramInfo->SendDatagramInformation->RemoteAddress
+ NdisQueryBuffer( (PNDIS_BUFFER)Irp->MdlAddress,
+ &DataBuffer,
+ &BufferSize );
+
+ /* FIXME: DgramInfo->SendDatagramInformation->RemoteAddress
must be of type PTDI_ADDRESS_IP */
+ TI_DbgPrint(MID_TRACE,
+ ("About to call send routine %x\n",
+ (*((PADDRESS_FILE)Request.Handle.AddressHandle)->Send)));
+
+ if( (*((PADDRESS_FILE)Request.Handle.AddressHandle)->Send) )
+ Status = (*((PADDRESS_FILE)Request.Handle.AddressHandle)->Send)(
+ Request.Handle.AddressHandle,
+ DgramInfo->SendDatagramInformation,
+ DataBuffer,
+ BufferSize,
+ &Irp->IoStatus.Information);
+ else
+ Status = STATUS_UNSUCCESSFUL;
- Status = (*((PADDRESS_FILE)Request.Handle.AddressHandle)->Send)(
- &Request, DgramInfo->SendDatagramInformation,
- (PNDIS_BUFFER)Irp->MdlAddress, DgramInfo->SendLength,
- &Irp->IoStatus.Information);
if (Status != STATUS_PENDING) {
DispDataRequestComplete(Irp, Status, Irp->IoStatus.Information);
/* Return STATUS_PENDING because DispPrepareIrpForCancel
marks Irp as pending */
Status = STATUS_PENDING;
- }
+ } else
+ IoMarkIrpPending( Irp );
}
TI_DbgPrint(DEBUG_IRP, ("Leaving.\n"));
}
-NTSTATUS DispTdiSetEventHandler(
- PIRP Irp)
+NTSTATUS DispTdiSetEventHandler(PIRP Irp)
/*
* FUNCTION: TDI_SET_EVENT_HANDER handler
* ARGUMENTS:
Parameters = (PTDI_REQUEST_KERNEL_SET_EVENT)&IrpSp->Parameters;
Status = STATUS_SUCCESS;
-
- KeAcquireSpinLock(&AddrFile->Lock, &OldIrql);
+
+ TcpipAcquireSpinLock(&AddrFile->Lock, &OldIrql);
/* Set the event handler. if an event handler is associated with
a specific event, it's flag (RegisteredXxxHandler) is TRUE.
Status = STATUS_INVALID_PARAMETER;
}
- KeReleaseSpinLock(&AddrFile->Lock, OldIrql);
+ TcpipReleaseSpinLock(&AddrFile->Lock, OldIrql);
return Status;
}
Count = CopyBufferToBufferChain(
QueryContext->InputMdl,
FIELD_OFFSET(TCP_REQUEST_QUERY_INFORMATION_EX, Context),
- (PUCHAR)&QueryContext->QueryInfo.Context,
+ (PCHAR)&QueryContext->QueryInfo.Context,
CONTEXT_SIZE);
}
MmUnlockPages(QueryContext->InputMdl);
IoFreeMdl(QueryContext->InputMdl);
- MmUnlockPages(QueryContext->OutputMdl);
- IoFreeMdl(QueryContext->OutputMdl);
+ if( QueryContext->OutputMdl ) {
+ MmUnlockPages(QueryContext->OutputMdl);
+ IoFreeMdl(QueryContext->OutputMdl);
+ }
QueryContext->Irp->IoStatus.Information = ByteCount;
QueryContext->Irp->IoStatus.Status = Status;
QueryContext = ExAllocatePool(NonPagedPool, sizeof(TI_QUERY_CONTEXT));
if (QueryContext) {
-#ifdef _MSC_VER
- try {
-#endif
+ _SEH_TRY {
InputMdl = IoAllocateMdl(InputBuffer,
sizeof(TCP_REQUEST_QUERY_INFORMATION_EX),
FALSE, TRUE, NULL);
RtlCopyMemory(&QueryContext->QueryInfo,
InputBuffer, sizeof(TCP_REQUEST_QUERY_INFORMATION_EX));
-
} else
Status = STATUS_INSUFFICIENT_RESOURCES;
-#ifdef _MSC_VER
- } except(EXCEPTION_EXECUTE_HANDLER) {
- Status = GetExceptionCode();
- }
-#endif
+ } _SEH_HANDLE {
+ Status = _SEH_GetExceptionCode();
+ } _SEH_END;
+
if (NT_SUCCESS(Status)) {
Size = MmGetMdlByteCount(OutputMdl);
ExFreePool(QueryContext);
} else
Status = STATUS_INSUFFICIENT_RESOURCES;
- } else
- Status = STATUS_INVALID_PARAMETER;
+ } else if( InputBufferLength ==
+ sizeof(TCP_REQUEST_QUERY_INFORMATION_EX) ) {
+ /* Handle the case where the user is probing the buffer for length */
+ TI_DbgPrint(MAX_TRACE, ("InputBufferLength %d OutputBufferLength %d\n",
+ InputBufferLength, OutputBufferLength));
+ InputBuffer = (PTCP_REQUEST_QUERY_INFORMATION_EX)
+ IrpSp->Parameters.DeviceIoControl.Type3InputBuffer;
+
+ Size = 0;
+
+ QueryContext = ExAllocatePool(NonPagedPool, sizeof(TI_QUERY_CONTEXT));
+ if (!QueryContext) return STATUS_INSUFFICIENT_RESOURCES;
+
+ _SEH_TRY {
+ InputMdl = IoAllocateMdl(InputBuffer,
+ sizeof(TCP_REQUEST_QUERY_INFORMATION_EX),
+ FALSE, TRUE, NULL);
+
+ MmProbeAndLockPages(InputMdl, Irp->RequestorMode,
+ IoModifyAccess);
+
+ InputMdlLocked = TRUE;
+ Status = STATUS_SUCCESS;
+ } _SEH_HANDLE {
+ TI_DbgPrint(MAX_TRACE, ("Failed to acquire client buffer\n"));
+ Status = _SEH_GetExceptionCode();
+ } _SEH_END;
+
+ if( !NT_SUCCESS(Status) || !InputMdl ) {
+ if( InputMdl ) IoFreeMdl( InputMdl );
+ ExFreePool(QueryContext);
+ return Status;
+ }
+
+ RtlCopyMemory(&QueryContext->QueryInfo,
+ InputBuffer, sizeof(TCP_REQUEST_QUERY_INFORMATION_EX));
+
+ QueryContext->Irp = Irp;
+ QueryContext->InputMdl = InputMdl;
+ QueryContext->OutputMdl = NULL;
+
+ Request.RequestNotifyObject = DispTdiQueryInformationExComplete;
+ Request.RequestContext = QueryContext;
+ Status = InfoTdiQueryInformationEx(&Request,
+ &QueryContext->QueryInfo.ID,
+ NULL,
+ &Size,
+ &QueryContext->QueryInfo.Context);
+ DispTdiQueryInformationExComplete(QueryContext, Status, Size);
+ TI_DbgPrint(MAX_TRACE, ("Leaving. Status = (0x%X)\n", Status));
+ } else Status = STATUS_INVALID_PARAMETER;
TI_DbgPrint(MIN_TRACE, ("Leaving. Status = (0x%X)\n", Status));
return Status;
}
+/* TODO: Support multiple addresses per interface.
+ * For now just set the nte context to the interface index.
+ *
+ * Later on, create an NTE context and NTE instance
+ */
+
+NTSTATUS DispTdiSetIPAddress( PIRP Irp, PIO_STACK_LOCATION IrpSp ) {
+ NTSTATUS Status = STATUS_DEVICE_DOES_NOT_EXIST;
+ PIP_SET_ADDRESS IpAddrChange =
+ (PIP_SET_ADDRESS)Irp->AssociatedIrp.SystemBuffer;
+ IF_LIST_ITER(IF);
+
+ ForEachInterface(IF) {
+ if( IF->Unicast.Address.IPv4Address == IpAddrChange->Address ) {
+ Status = STATUS_DUPLICATE_OBJECTID;
+ break;
+ }
+ if( IF->Index == IpAddrChange->NteIndex ) {
+ IPRemoveInterfaceRoute( IF );
+
+ IF->Unicast.Type = IP_ADDRESS_V4;
+ IF->Unicast.Address.IPv4Address = IpAddrChange->Address;
+ IF->Netmask.Type = IP_ADDRESS_V4;
+ IF->Netmask.Address.IPv4Address = IpAddrChange->Netmask;
+
+ TI_DbgPrint(MID_TRACE,("New Unicast Address: %x\n",
+ IF->Unicast.Address.IPv4Address));
+ TI_DbgPrint(MID_TRACE,("New Netmask : %x\n",
+ IF->Netmask.Address.IPv4Address));
+
+ IPAddInterfaceRoute( IF );
+
+ IpAddrChange->Address = IF->Index;
+ Status = STATUS_SUCCESS;
+ Irp->IoStatus.Information = IF->Index;
+ break;
+ }
+ } EndFor(IF);
+
+ Irp->IoStatus.Status = Status;
+ return Status;
+}
+
+NTSTATUS DispTdiDeleteIPAddress( PIRP Irp, PIO_STACK_LOCATION IrpSp ) {
+ NTSTATUS Status = STATUS_UNSUCCESSFUL;
+ PUSHORT NteIndex = Irp->AssociatedIrp.SystemBuffer;
+ IF_LIST_ITER(IF);
+
+ ForEachInterface(IF) {
+ if( IF->Index == *NteIndex ) {
+ IF->Unicast.Type = IP_ADDRESS_V4;
+ IF->Unicast.Address.IPv4Address = 0;
+ IF->Netmask.Type = IP_ADDRESS_V4;
+ IF->Netmask.Address.IPv4Address = 0;
+ Status = STATUS_SUCCESS;
+ }
+ } EndFor(IF);
+
+ Irp->IoStatus.Status = Status;
+ return Status;
+}
+
/* EOF */