diff --git a/reactos/drivers/network/afd/afd/connect.c b/reactos/drivers/network/afd/afd/connect.c index 66eeddac82e..56935b7f526 100644 --- a/reactos/drivers/network/afd/afd/connect.c +++ b/reactos/drivers/network/afd/afd/connect.c @@ -332,19 +332,19 @@ static NTSTATUS NTAPI StreamSocketConnectComplete return Status; } - FCB->FilledConnectData = MIN(FCB->ConnectInfo->UserDataLength, FCB->ConnectDataSize); + FCB->FilledConnectData = MIN(FCB->ConnectReturnInfo->UserDataLength, FCB->ConnectDataSize); if (FCB->FilledConnectData) { RtlCopyMemory(FCB->ConnectData, - FCB->ConnectInfo->UserData, + FCB->ConnectReturnInfo->UserData, FCB->FilledConnectData); } - FCB->FilledConnectOptions = MIN(FCB->ConnectInfo->OptionsLength, FCB->ConnectOptionsSize); + FCB->FilledConnectOptions = MIN(FCB->ConnectReturnInfo->OptionsLength, FCB->ConnectOptionsSize); if (FCB->FilledConnectOptions) { RtlCopyMemory(FCB->ConnectOptions, - FCB->ConnectInfo->Options, + FCB->ConnectReturnInfo->Options, FCB->FilledConnectOptions); } @@ -380,7 +380,6 @@ AfdStreamSocketConnect(PDEVICE_OBJECT DeviceObject, PIRP Irp, PFILE_OBJECT FileObject = IrpSp->FileObject; PAFD_FCB FCB = FileObject->FsContext; PAFD_CONNECT_INFO ConnectReq; - PTDI_CONNECTION_INFORMATION TargetAddress; AFD_DbgPrint(MID_TRACE,("Called on %x\n", FCB)); if( !SocketAcquireStateLock( FCB ) ) return LostSocket( Irp ); @@ -450,21 +449,25 @@ AfdStreamSocketConnect(PDEVICE_OBJECT DeviceObject, PIRP Irp, if( !NT_SUCCESS(Status) ) break; + if (FCB->ConnectReturnInfo) ExFreePool(FCB->ConnectReturnInfo); Status = TdiBuildConnectionInfo - ( &FCB->ConnectInfo, + ( &FCB->ConnectReturnInfo, &ConnectReq->RemoteAddress ); if( NT_SUCCESS(Status) ) - Status = TdiBuildConnectionInfo(&TargetAddress, + { + if (FCB->ConnectCallInfo) ExFreePool(FCB->ConnectCallInfo); + Status = TdiBuildConnectionInfo(&FCB->ConnectCallInfo, &ConnectReq->RemoteAddress); + } else break; if( NT_SUCCESS(Status) ) { - TargetAddress->UserData = FCB->ConnectData; - TargetAddress->UserDataLength = FCB->ConnectDataSize; - TargetAddress->Options = FCB->ConnectOptions; - TargetAddress->OptionsLength = FCB->ConnectOptionsSize; + FCB->ConnectCallInfo->UserData = FCB->ConnectData; + FCB->ConnectCallInfo->UserDataLength = FCB->ConnectDataSize; + FCB->ConnectCallInfo->Options = FCB->ConnectOptions; + FCB->ConnectCallInfo->OptionsLength = FCB->ConnectOptionsSize; FCB->State = SOCKET_STATE_CONNECTING; @@ -474,8 +477,8 @@ AfdStreamSocketConnect(PDEVICE_OBJECT DeviceObject, PIRP Irp, { Status = TdiConnect( &FCB->ConnectIrp.InFlightRequest, FCB->Connection.Object, - TargetAddress, - FCB->ConnectInfo, + FCB->ConnectCallInfo, + FCB->ConnectReturnInfo, &FCB->ConnectIrp.Iosb, StreamSocketConnectComplete, FCB ); @@ -483,8 +486,6 @@ AfdStreamSocketConnect(PDEVICE_OBJECT DeviceObject, PIRP Irp, if (Status != STATUS_PENDING) FCB->State = SOCKET_STATE_BOUND; - - ExFreePool(TargetAddress); SocketStateUnlock(FCB); diff --git a/reactos/drivers/network/afd/afd/listen.c b/reactos/drivers/network/afd/afd/listen.c index 734b440cf65..2ba75925a40 100644 --- a/reactos/drivers/network/afd/afd/listen.c +++ b/reactos/drivers/network/afd/afd/listen.c @@ -37,7 +37,10 @@ static NTSTATUS SatisfyAccept( PAFD_DEVICE_EXTENSION DeviceExt, Status = MakeSocketIntoConnection( FCB ); if (NT_SUCCESS(Status)) - Status = TdiBuildConnectionInfo(&FCB->ConnectInfo, FCB->RemoteAddress); + Status = TdiBuildConnectionInfo(&FCB->ConnectCallInfo, FCB->RemoteAddress); + + if (NT_SUCCESS(Status)) + Status = TdiBuildConnectionInfo(&FCB->ConnectReturnInfo, FCB->RemoteAddress); return UnlockAndMaybeComplete( FCB, Status, Irp, 0 ); } diff --git a/reactos/drivers/network/afd/afd/main.c b/reactos/drivers/network/afd/afd/main.c index ce1f90edd9a..c81d49c4dd6 100644 --- a/reactos/drivers/network/afd/afd/main.c +++ b/reactos/drivers/network/afd/afd/main.c @@ -472,8 +472,11 @@ AfdCloseSocket(PDEVICE_OBJECT DeviceObject, PIRP Irp, if( FCB->AddressFrom ) ExFreePool( FCB->AddressFrom ); - if( FCB->ConnectInfo ) - ExFreePool( FCB->ConnectInfo ); + if( FCB->ConnectCallInfo ) + ExFreePool( FCB->ConnectCallInfo ); + + if( FCB->ConnectReturnInfo ) + ExFreePool( FCB->ConnectReturnInfo ); if( FCB->ConnectData ) ExFreePool( FCB->ConnectData ); @@ -534,76 +537,101 @@ AfdCloseSocket(PDEVICE_OBJECT DeviceObject, PIRP Irp, static NTSTATUS -DoDisconnect(PAFD_FCB FCB, PIRP CurrentIrp) +NTAPI +DisconnectComplete(PDEVICE_OBJECT DeviceObject, + PIRP Irp, + PVOID Context) +{ + PAFD_FCB FCB = Context; + PIRP CurrentIrp; + PLIST_ENTRY CurrentEntry; + + if( !SocketAcquireStateLock( FCB ) ) + return STATUS_FILE_CLOSED; + + ASSERT(FCB->DisconnectIrp.InFlightRequest == Irp); + FCB->DisconnectIrp.InFlightRequest = NULL; + + ASSERT(FCB->DisconnectPending); + //ASSERT(IsListEmpty(&FCB->PendingIrpList[FUNCTION_SEND]) || (FCB->DisconnectFlags & TDI_DISCONNECT_ABORT)); + + if (NT_SUCCESS(Irp->IoStatus.Status) && (FCB->DisconnectFlags & TDI_DISCONNECT_RELEASE)) + { + FCB->FilledDisconnectData = MIN(FCB->DisconnectDataSize, FCB->ConnectReturnInfo->UserDataLength); + if (FCB->FilledDisconnectData) + { + RtlCopyMemory(FCB->DisconnectData, + FCB->ConnectReturnInfo->UserData, + FCB->FilledDisconnectData); + } + + FCB->FilledDisconnectOptions = MIN(FCB->DisconnectOptionsSize, FCB->ConnectReturnInfo->OptionsLength); + if (FCB->FilledDisconnectOptions) + { + RtlCopyMemory(FCB->DisconnectOptions, + FCB->ConnectReturnInfo->Options, + FCB->FilledDisconnectOptions); + } + } + + FCB->DisconnectPending = FALSE; + + while (!IsListEmpty(&FCB->PendingIrpList[FUNCTION_DISCONNECT])) + { + CurrentEntry = RemoveHeadList(&FCB->PendingIrpList[FUNCTION_DISCONNECT]); + CurrentIrp = CONTAINING_RECORD(CurrentEntry, IRP, Tail.Overlay.ListEntry); + CurrentIrp->IoStatus.Status = Irp->IoStatus.Status; + CurrentIrp->IoStatus.Information = 0; + UnlockRequest(CurrentIrp, IoGetCurrentIrpStackLocation(CurrentIrp)); + (void)IoSetCancelRoutine(CurrentIrp, NULL); + IoCompleteRequest(CurrentIrp, IO_NETWORK_INCREMENT ); + } + + if (FCB->DisconnectFlags & TDI_DISCONNECT_RELEASE) + FCB->PollState |= AFD_EVENT_DISCONNECT; + else + FCB->PollState |= AFD_EVENT_ABORT; + FCB->PollStatus[FD_CLOSE_BIT] = Irp->IoStatus.Status; + PollReeval(FCB->DeviceExt, FCB->FileObject); + + SocketStateUnlock(FCB); + + return Irp->IoStatus.Status; +} + +static +NTSTATUS +DoDisconnect(PAFD_FCB FCB) { PAFD_DISCONNECT_INFO DisReq; IO_STATUS_BLOCK Iosb; - PTDI_CONNECTION_INFORMATION ConnectionReturnInfo; - PIO_STACK_LOCATION CurrentIrpSp; - USHORT Flags = 0; NTSTATUS Status; - CurrentIrpSp = IoGetCurrentIrpStackLocation(CurrentIrp); - DisReq = GetLockedData(CurrentIrp, CurrentIrpSp); + ASSERT(FCB->DisconnectPending); - if( DisReq->DisconnectType & AFD_DISCONNECT_SEND ) - Flags |= TDI_DISCONNECT_RELEASE; - if( DisReq->DisconnectType & AFD_DISCONNECT_RECV || - DisReq->DisconnectType & AFD_DISCONNECT_ABORT ) - Flags |= TDI_DISCONNECT_ABORT; - - Status = TdiBuildNullConnectionInfo(&ConnectionReturnInfo, - FCB->RemoteAddress->Address[0].AddressType); - if (NT_SUCCESS(Status)) + if (FCB->DisconnectIrp.InFlightRequest) { - FCB->ConnectInfo->UserData = FCB->DisconnectData; - FCB->ConnectInfo->UserDataLength = FCB->DisconnectDataSize; - FCB->ConnectInfo->Options = FCB->DisconnectOptions; - FCB->ConnectInfo->OptionsLength = FCB->DisconnectOptionsSize; - - Status = TdiDisconnect(FCB->Connection.Object, - &DisReq->Timeout, - Flags, - &Iosb, - NULL, - NULL, - FCB->ConnectInfo, - ConnectionReturnInfo); - - if (NT_SUCCESS(Status)) { - FCB->FilledDisconnectData = MIN(FCB->DisconnectDataSize, ConnectionReturnInfo->UserDataLength); - if (FCB->FilledDisconnectData) - { - RtlCopyMemory(FCB->DisconnectData, - ConnectionReturnInfo->UserData, - FCB->FilledDisconnectData); - } - - FCB->FilledDisconnectOptions = MIN(FCB->DisconnectOptionsSize, ConnectionReturnInfo->OptionsLength); - if (FCB->FilledDisconnectOptions) - { - RtlCopyMemory(FCB->DisconnectOptions, - ConnectionReturnInfo->Options, - FCB->FilledDisconnectOptions); - } - } - - ExFreePool( ConnectionReturnInfo ); - - if (Flags & TDI_DISCONNECT_RELEASE) - FCB->PollState |= AFD_EVENT_DISCONNECT; - else - FCB->PollState |= AFD_EVENT_ABORT; - FCB->PollStatus[FD_CLOSE_BIT] = Status; - PollReeval( FCB->DeviceExt, FCB->FileObject ); + return STATUS_PENDING; + } + + FCB->ConnectCallInfo->UserData = FCB->DisconnectData; + FCB->ConnectCallInfo->UserDataLength = FCB->DisconnectDataSize; + FCB->ConnectCallInfo->Options = FCB->DisconnectOptions; + FCB->ConnectCallInfo->OptionsLength = FCB->DisconnectOptionsSize; + + Status = TdiDisconnect(&FCB->DisconnectIrp.InFlightRequest, + FCB->Connection.Object, + &DisReq->Timeout, + FCB->DisconnectFlags, + &Iosb, + DisconnectComplete, + FCB, + FCB->ConnectCallInfo, + FCB->ConnectReturnInfo); + if (Status != STATUS_PENDING) + { + FCB->DisconnectPending = FALSE; } - - CurrentIrp->IoStatus.Status = Status; - CurrentIrp->IoStatus.Information = 0; - UnlockRequest(CurrentIrp, CurrentIrpSp); - (void)IoSetCancelRoutine(CurrentIrp, NULL); - - IoCompleteRequest(CurrentIrp, IO_NETWORK_INCREMENT); return Status; } @@ -611,20 +639,12 @@ DoDisconnect(PAFD_FCB FCB, PIRP CurrentIrp) VOID RetryDisconnectCompletion(PAFD_FCB FCB) { - if (IsListEmpty(&FCB->PendingIrpList[FUNCTION_SEND])) + ASSERT(FCB->RemoteAddress); + + if (IsListEmpty(&FCB->PendingIrpList[FUNCTION_SEND]) && FCB->DisconnectPending) { - PIRP CurrentIrp; - PLIST_ENTRY CurrentEntry; - - ASSERT(FCB->RemoteAddress); - - while (!IsListEmpty(&FCB->PendingIrpList[FUNCTION_DISCONNECT])) - { - CurrentEntry = RemoveHeadList(&FCB->PendingIrpList[FUNCTION_DISCONNECT]); - CurrentIrp = CONTAINING_RECORD(CurrentEntry, IRP, Tail.Overlay.ListEntry); - - DoDisconnect(FCB, CurrentIrp); - } + /* Sends are done; fire off a TDI_DISCONNECT request */ + DoDisconnect(FCB); } } @@ -636,6 +656,8 @@ AfdDisconnect(PDEVICE_OBJECT DeviceObject, PIRP Irp, PAFD_DISCONNECT_INFO DisReq; NTSTATUS Status = STATUS_SUCCESS; USHORT Flags = 0; + PLIST_ENTRY CurrentEntry; + PIRP CurrentIrp; if( !SocketAcquireStateLock( FCB ) ) return LostSocket( Irp ); @@ -651,26 +673,54 @@ AfdDisconnect(PDEVICE_OBJECT DeviceObject, PIRP Irp, if (!(FCB->Flags & AFD_ENDPOINT_CONNECTIONLESS)) { - if( !FCB->ConnectInfo ) + if( !FCB->ConnectCallInfo ) return UnlockAndMaybeComplete( FCB, STATUS_INVALID_PARAMETER, Irp, 0 ); - - if (IsListEmpty(&FCB->PendingIrpList[FUNCTION_SEND]) || (Flags & TDI_DISCONNECT_ABORT)) + + if (FCB->DisconnectPending) { - /* Go ahead an execute the disconnect because we're ready for it */ - Status = DoDisconnect(FCB, Irp); + if (FCB->DisconnectIrp.InFlightRequest) + { + IoCancelIrp(FCB->DisconnectIrp.InFlightRequest); + ASSERT(!FCB->DisconnectIrp.InFlightRequest); + } + else + { + while (!IsListEmpty(&FCB->PendingIrpList[FUNCTION_DISCONNECT])) + { + CurrentEntry = RemoveHeadList(&FCB->PendingIrpList[FUNCTION_DISCONNECT]); + CurrentIrp = CONTAINING_RECORD(CurrentEntry, IRP, Tail.Overlay.ListEntry); + CurrentIrp->IoStatus.Status = STATUS_CANCELLED; + CurrentIrp->IoStatus.Information = 0; + UnlockRequest(CurrentIrp, IoGetCurrentIrpStackLocation(CurrentIrp)); + (void)IoSetCancelRoutine(CurrentIrp, NULL); + IoCompleteRequest(CurrentIrp, IO_NETWORK_INCREMENT ); + } + } + } + + FCB->DisconnectFlags = Flags; + FCB->DisconnectPending = TRUE; + + Status = QueueUserModeIrp(FCB, Irp, FUNCTION_DISCONNECT); + if (Status == STATUS_PENDING) + { + if (IsListEmpty(&FCB->PendingIrpList[FUNCTION_SEND]) || (FCB->DisconnectFlags & TDI_DISCONNECT_ABORT)) + { + /* Go ahead an execute the disconnect because we're ready for it */ + Status = DoDisconnect(FCB); + } - /* DoDisconnect takes care of the IRP */ + if (Status != STATUS_PENDING) + RemoveEntryList(&Irp->Tail.Overlay.ListEntry); + } + + if (Status == STATUS_PENDING) + { SocketStateUnlock(FCB); - + return Status; } - else - { - /* We have a graceful disconnect waiting on pending sends to complete */ - return LeaveIrpUntilLater(FCB, Irp, FUNCTION_DISCONNECT); - } - } else { diff --git a/reactos/drivers/network/afd/afd/tdi.c b/reactos/drivers/network/afd/afd/tdi.c index cb6e9ca2ab3..9a18dd21bdc 100644 --- a/reactos/drivers/network/afd/afd/tdi.c +++ b/reactos/drivers/network/afd/afd/tdi.c @@ -1228,6 +1228,7 @@ NTSTATUS TdiSendDatagram( } NTSTATUS TdiDisconnect( + PIRP *Irp, PFILE_OBJECT TransportObject, PLARGE_INTEGER Time, USHORT Flags, @@ -1237,10 +1238,6 @@ NTSTATUS TdiDisconnect( PTDI_CONNECTION_INFORMATION RequestConnectionInfo, PTDI_CONNECTION_INFORMATION ReturnConnectionInfo) { PDEVICE_OBJECT DeviceObject; - KEVENT Event; - PIRP Irp; - - KeInitializeEvent(&Event, NotificationEvent, FALSE); if (!TransportObject) { AFD_DbgPrint(MIN_TRACE, ("Bad transport object.\n")); @@ -1255,20 +1252,20 @@ NTSTATUS TdiDisconnect( return STATUS_INVALID_PARAMETER; } - Irp = TdiBuildInternalDeviceControlIrp + *Irp = TdiBuildInternalDeviceControlIrp ( TDI_DISCONNECT, /* Sub function */ DeviceObject, /* Device object */ TransportObject, /* File object */ - &Event, /* Event */ + NULL, /* Event */ Iosb ); /* Status */ - if (!Irp) { + if (!*Irp) { AFD_DbgPrint(MIN_TRACE, ("Insufficient resources.\n")); return STATUS_INSUFFICIENT_RESOURCES; } TdiBuildDisconnect - (Irp, /* I/O Request Packet */ + (*Irp, /* I/O Request Packet */ DeviceObject, /* Device object */ TransportObject, /* File object */ CompletionRoutine, /* Completion routine */ @@ -1278,7 +1275,9 @@ NTSTATUS TdiDisconnect( RequestConnectionInfo, /* Indication of who to disconnect */ ReturnConnectionInfo); /* Indication of who disconnected */ - return TdiCall(Irp, DeviceObject, &Event, Iosb); + TdiCall(*Irp, DeviceObject, NULL, Iosb); + + return STATUS_PENDING; } /* EOF */ diff --git a/reactos/drivers/network/afd/include/afd.h b/reactos/drivers/network/afd/include/afd.h index dfa7a3899db..72387d226d3 100644 --- a/reactos/drivers/network/afd/include/afd.h +++ b/reactos/drivers/network/afd/include/afd.h @@ -182,10 +182,12 @@ typedef struct _AFD_FCB { PAFD_DEVICE_EXTENSION DeviceExt; BOOLEAN DelayedAccept; UINT ConnSeq; + USHORT DisconnectFlags; + BOOLEAN DisconnectPending; PTRANSPORT_ADDRESS LocalAddress, RemoteAddress; - PTDI_CONNECTION_INFORMATION AddressFrom, ConnectInfo; + PTDI_CONNECTION_INFORMATION AddressFrom, ConnectCallInfo, ConnectReturnInfo; AFD_TDI_OBJECT AddressFile, Connection; - AFD_IN_FLIGHT_REQUEST ConnectIrp, ListenIrp, ReceiveIrp, SendIrp; + AFD_IN_FLIGHT_REQUEST ConnectIrp, ListenIrp, ReceiveIrp, SendIrp, DisconnectIrp; AFD_DATA_WINDOW Send, Recv; KMUTEX Mutex; PKEVENT EventSelect; diff --git a/reactos/drivers/network/afd/include/tdi_proto.h b/reactos/drivers/network/afd/include/tdi_proto.h index a70c810e697..277cf736bbb 100644 --- a/reactos/drivers/network/afd/include/tdi_proto.h +++ b/reactos/drivers/network/afd/include/tdi_proto.h @@ -16,7 +16,8 @@ NTSTATUS TdiCloseDevice(HANDLE Handle, PFILE_OBJECT FileObject); NTSTATUS TdiDisconnect -( PFILE_OBJECT TransportObject, +( PIRP *Irp, + PFILE_OBJECT TransportObject, PLARGE_INTEGER Time, USHORT Flags, PIO_STATUS_BLOCK Iosb,