NTSTATUS NTAPI AfdGetContext( PDEVICE_OBJECT DeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp ) { NTSTATUS Status = STATUS_INVALID_PARAMETER; PFILE_OBJECT FileObject = IrpSp->FileObject; PAFD_FCB FCB = FileObject->FsContext; UINT ContextSize = IrpSp->Parameters.DeviceIoControl.OutputBufferLength; UNREFERENCED_PARAMETER(DeviceObject); if( !SocketAcquireStateLock( FCB ) ) return LostSocket( Irp ); if( FCB->ContextSize < ContextSize ) ContextSize = FCB->ContextSize; if( FCB->Context ) { RtlCopyMemory( Irp->UserBuffer, FCB->Context, ContextSize ); Status = STATUS_SUCCESS; } AFD_DbgPrint(MID_TRACE,("Returning %x\n", Status)); return UnlockAndMaybeComplete( FCB, Status, Irp, ContextSize ); }
NTSTATUS NTAPI AfdSetContext( PDEVICE_OBJECT DeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp ) { PFILE_OBJECT FileObject = IrpSp->FileObject; PAFD_FCB FCB = FileObject->FsContext; PVOID Context = LockRequest(Irp, IrpSp); if( !SocketAcquireStateLock( FCB ) ) return LostSocket( Irp ); if (!Context) return UnlockAndMaybeComplete(FCB, STATUS_NO_MEMORY, Irp, 0); if( FCB->Context ) { ExFreePool( FCB->Context ); FCB->ContextSize = 0; } FCB->Context = ExAllocatePool( PagedPool, IrpSp->Parameters.DeviceIoControl.InputBufferLength ); if( !FCB->Context ) return UnlockAndMaybeComplete( FCB, STATUS_NO_MEMORY, Irp, 0 ); FCB->ContextSize = IrpSp->Parameters.DeviceIoControl.InputBufferLength; RtlCopyMemory( FCB->Context, Context, FCB->ContextSize ); return UnlockAndMaybeComplete( FCB, STATUS_SUCCESS, Irp, 0 ); }
static NTSTATUS SatisfyAccept( PAFD_DEVICE_EXTENSION DeviceExt, PIRP Irp, PFILE_OBJECT NewFileObject, PAFD_TDI_OBJECT_QELT Qelt ) { PAFD_FCB FCB = NewFileObject->FsContext; NTSTATUS Status; UNREFERENCED_PARAMETER(DeviceExt); if( !SocketAcquireStateLock( FCB ) ) return LostSocket( Irp ); /* Transfer the connection to the new socket, launch the opening read */ AFD_DbgPrint(MID_TRACE,("Completing a real accept (FCB %p)\n", FCB)); FCB->Connection = Qelt->Object; if( FCB->RemoteAddress ) ExFreePool( FCB->RemoteAddress ); FCB->RemoteAddress = TaCopyTransportAddress( Qelt->ConnInfo->RemoteAddress ); if( !FCB->RemoteAddress ) Status = STATUS_NO_MEMORY; else Status = MakeSocketIntoConnection( FCB ); if (NT_SUCCESS(Status)) Status = TdiBuildConnectionInfo(&FCB->ConnectCallInfo, FCB->RemoteAddress); if (NT_SUCCESS(Status)) Status = TdiBuildConnectionInfo(&FCB->ConnectReturnInfo, FCB->RemoteAddress); return UnlockAndMaybeComplete( FCB, Status, Irp, 0 ); }
NTSTATUS NTAPI AfdGetConnectOptions(PDEVICE_OBJECT DeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp) { PFILE_OBJECT FileObject = IrpSp->FileObject; PAFD_FCB FCB = FileObject->FsContext; UINT BufferSize = IrpSp->Parameters.DeviceIoControl.OutputBufferLength; UNREFERENCED_PARAMETER(DeviceObject); if (!SocketAcquireStateLock(FCB)) return LostSocket(Irp); if (FCB->ConnectOptionsSize == 0) { AFD_DbgPrint(MIN_TRACE,("Invalid parameter\n")); return UnlockAndMaybeComplete(FCB, STATUS_INVALID_PARAMETER, Irp, 0); } ASSERT(FCB->ConnectOptions); if (FCB->FilledConnectOptions < BufferSize) BufferSize = FCB->FilledConnectOptions; RtlCopyMemory(Irp->UserBuffer, FCB->ConnectOptions, BufferSize); return UnlockAndMaybeComplete(FCB, STATUS_SUCCESS, Irp, BufferSize); }
NTSTATUS NTAPI AfdEnumEvents( PDEVICE_OBJECT DeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp ) { PFILE_OBJECT FileObject = IrpSp->FileObject; PAFD_ENUM_NETWORK_EVENTS_INFO EnumReq = (PAFD_ENUM_NETWORK_EVENTS_INFO)LockRequest( Irp, IrpSp, TRUE, NULL ); PAFD_FCB FCB = FileObject->FsContext; PKEVENT UserEvent; NTSTATUS Status; UNREFERENCED_PARAMETER(DeviceObject); AFD_DbgPrint(MID_TRACE,("Called (FCB %p)\n", FCB)); if( !SocketAcquireStateLock( FCB ) ) { return LostSocket( Irp ); } if ( !EnumReq ) { return UnlockAndMaybeComplete( FCB, STATUS_NO_MEMORY, Irp, 0 ); } Status = ObReferenceObjectByHandle(EnumReq->Event, EVENT_ALL_ACCESS, ExEventObjectType, UserMode, (PVOID *)&UserEvent, NULL); if (!NT_SUCCESS(Status)) { AFD_DbgPrint(MIN_TRACE,("Unable to reference event %x\n", Status)); return UnlockAndMaybeComplete(FCB, Status, Irp, 0); } /* Clear the event */ KeClearEvent(UserEvent); ObDereferenceObject(UserEvent); /* Copy the poll state, masking out disabled events */ EnumReq->PollEvents = (FCB->PollState & ~FCB->EventSelectDisabled); RtlCopyMemory( EnumReq->EventStatus, FCB->PollStatus, sizeof(EnumReq->EventStatus) ); /* Disable the events that triggered the select until the reenabling function is called */ FCB->EventSelectDisabled |= (FCB->PollState & FCB->EventSelectTriggers); return UnlockAndMaybeComplete( FCB, STATUS_SUCCESS, Irp, 0 ); }
NTSTATUS NTAPI AfdBindSocket(PDEVICE_OBJECT DeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp) { NTSTATUS Status = STATUS_SUCCESS; PFILE_OBJECT FileObject = IrpSp->FileObject; PAFD_FCB FCB = FileObject->FsContext; PAFD_BIND_DATA BindReq; HANDLE UserHandle = NULL; UNREFERENCED_PARAMETER(DeviceObject); AFD_DbgPrint(MID_TRACE,("Called\n")); if( !SocketAcquireStateLock( FCB ) ) return LostSocket( Irp ); if( !(BindReq = LockRequest( Irp, IrpSp, FALSE, NULL )) ) return UnlockAndMaybeComplete( FCB, STATUS_NO_MEMORY, Irp, 0 ); if( FCB->LocalAddress ) ExFreePool( FCB->LocalAddress ); FCB->LocalAddress = TaCopyTransportAddress( &BindReq->Address ); if( FCB->LocalAddress ) Status = TdiBuildConnectionInfo( &FCB->AddressFrom, FCB->LocalAddress ); if( NT_SUCCESS(Status) ) Status = WarmSocketForBind( FCB, BindReq->ShareType ); AFD_DbgPrint(MID_TRACE,("FCB->Flags %x\n", FCB->Flags)); if (NT_SUCCESS(Status)) { Status = ObOpenObjectByPointer(FCB->AddressFile.Object, 0, NULL, MAXIMUM_ALLOWED, *IoFileObjectType, Irp->RequestorMode, &UserHandle); if (NT_SUCCESS(Status)) FCB->State = SOCKET_STATE_BOUND; } /* MSAFD relies on us returning the address file handle in the IOSB */ return UnlockAndMaybeComplete( FCB, Status, Irp, (ULONG_PTR)UserHandle); }
NTSTATUS AfdWaitForListen( PDEVICE_OBJECT DeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp ) { PFILE_OBJECT FileObject = IrpSp->FileObject; PAFD_FCB FCB = FileObject->FsContext; NTSTATUS Status; UNREFERENCED_PARAMETER(DeviceObject); AFD_DbgPrint(MID_TRACE,("Called\n")); if( !SocketAcquireStateLock( FCB ) ) return LostSocket( Irp ); if( !IsListEmpty( &FCB->PendingConnections ) ) { PLIST_ENTRY PendingConn = FCB->PendingConnections.Flink; /* We have a pending connection ... complete this irp right away */ Status = SatisfyPreAccept ( Irp, CONTAINING_RECORD ( PendingConn, AFD_TDI_OBJECT_QELT, ListEntry ) ); AFD_DbgPrint(MID_TRACE,("Completed a wait for accept\n")); if ( !IsListEmpty( &FCB->PendingConnections ) ) { FCB->PollState |= AFD_EVENT_ACCEPT; FCB->PollStatus[FD_ACCEPT_BIT] = STATUS_SUCCESS; PollReeval( FCB->DeviceExt, FCB->FileObject ); } else FCB->PollState &= ~AFD_EVENT_ACCEPT; SocketStateUnlock( FCB ); return Status; } else if (FCB->NonBlocking) { AFD_DbgPrint(MIN_TRACE,("No connection ready on a non-blocking socket\n")); return UnlockAndMaybeComplete(FCB, STATUS_CANT_WAIT, Irp, 0); } else { AFD_DbgPrint(MID_TRACE,("Holding\n")); return LeaveIrpUntilLater( FCB, Irp, FUNCTION_PREACCEPT ); } }
NTSTATUS NTAPI AfdGetContextSize( PDEVICE_OBJECT DeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp ) { PFILE_OBJECT FileObject = IrpSp->FileObject; PAFD_FCB FCB = FileObject->FsContext; if( !SocketAcquireStateLock( FCB ) ) return LostSocket( Irp ); if (IrpSp->Parameters.DeviceIoControl.OutputBufferLength < sizeof(ULONG)) { AFD_DbgPrint(MIN_TRACE,("Buffer too small\n")); return UnlockAndMaybeComplete(FCB, STATUS_BUFFER_TOO_SMALL, Irp, sizeof(ULONG)); } RtlCopyMemory(Irp->UserBuffer, &FCB->ContextSize, sizeof(ULONG)); return UnlockAndMaybeComplete(FCB, STATUS_SUCCESS, Irp, sizeof(ULONG)); }
NTSTATUS NTAPI AfdGetSockName( PDEVICE_OBJECT DeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp ) { NTSTATUS Status = STATUS_SUCCESS; PFILE_OBJECT FileObject = IrpSp->FileObject; PAFD_FCB FCB = FileObject->FsContext; PMDL Mdl = NULL; UNREFERENCED_PARAMETER(DeviceObject); if( !SocketAcquireStateLock( FCB ) ) return LostSocket( Irp ); if( FCB->AddressFile.Object == NULL && FCB->Connection.Object == NULL ) { return UnlockAndMaybeComplete( FCB, STATUS_INVALID_PARAMETER, Irp, 0 ); } Mdl = IoAllocateMdl( Irp->UserBuffer, IrpSp->Parameters.DeviceIoControl.OutputBufferLength, FALSE, FALSE, NULL ); if( Mdl != NULL ) { _SEH2_TRY { MmProbeAndLockPages( Mdl, Irp->RequestorMode, IoModifyAccess ); } _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) { AFD_DbgPrint(MIN_TRACE, ("MmProbeAndLockPages() failed.\n")); Status = _SEH2_GetExceptionCode(); } _SEH2_END; if( NT_SUCCESS(Status) ) { Status = TdiQueryInformation( FCB->Connection.Object ? FCB->Connection.Object : FCB->AddressFile.Object, TDI_QUERY_ADDRESS_INFO, Mdl ); } } else
NTSTATUS NTAPI AfdSetConnectOptions(PDEVICE_OBJECT DeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp) { PFILE_OBJECT FileObject = IrpSp->FileObject; PAFD_FCB FCB = FileObject->FsContext; PVOID ConnectOptions = LockRequest(Irp, IrpSp, FALSE, NULL); UINT ConnectOptionsSize = IrpSp->Parameters.DeviceIoControl.InputBufferLength; UNREFERENCED_PARAMETER(DeviceObject); if (!SocketAcquireStateLock(FCB)) return LostSocket(Irp); if (!ConnectOptions) return UnlockAndMaybeComplete(FCB, STATUS_NO_MEMORY, Irp, 0); if (FCB->ConnectOptions) { ExFreePool(FCB->ConnectOptions); FCB->ConnectOptions = NULL; FCB->ConnectOptionsSize = 0; FCB->FilledConnectOptions = 0; } FCB->ConnectOptions = ExAllocatePool(PagedPool, ConnectOptionsSize); if (!FCB->ConnectOptions) return UnlockAndMaybeComplete(FCB, STATUS_NO_MEMORY, Irp, 0); RtlCopyMemory(FCB->ConnectOptions, ConnectOptions, ConnectOptionsSize); FCB->ConnectOptionsSize = ConnectOptionsSize; return UnlockAndMaybeComplete(FCB, STATUS_SUCCESS, Irp, 0); }
NTSTATUS NTAPI AfdSetConnectOptionsSize(PDEVICE_OBJECT DeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp) { PFILE_OBJECT FileObject = IrpSp->FileObject; PAFD_FCB FCB = FileObject->FsContext; PUINT ConnectOptionsSize = LockRequest(Irp, IrpSp, FALSE, NULL); UINT BufferSize = IrpSp->Parameters.DeviceIoControl.InputBufferLength; UNREFERENCED_PARAMETER(DeviceObject); if (!SocketAcquireStateLock(FCB)) return LostSocket(Irp); if (!ConnectOptionsSize) return UnlockAndMaybeComplete(FCB, STATUS_NO_MEMORY, Irp, 0); if (BufferSize < sizeof(UINT)) { AFD_DbgPrint(MIN_TRACE,("Buffer too small\n")); return UnlockAndMaybeComplete(FCB, STATUS_BUFFER_TOO_SMALL, Irp, 0); } if (FCB->ConnectOptions) { ExFreePool(FCB->ConnectOptions); FCB->ConnectOptionsSize = 0; FCB->FilledConnectOptions = 0; } FCB->ConnectOptions = ExAllocatePool(PagedPool, *ConnectOptionsSize); if (!FCB->ConnectOptions) return UnlockAndMaybeComplete(FCB, STATUS_NO_MEMORY, Irp, 0); FCB->ConnectOptionsSize = *ConnectOptionsSize; return UnlockAndMaybeComplete(FCB, STATUS_SUCCESS, Irp, 0); }
NTSTATUS NTAPI AfdPacketSocketReadData(PDEVICE_OBJECT DeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp ) { NTSTATUS Status = STATUS_SUCCESS; PFILE_OBJECT FileObject = IrpSp->FileObject; PAFD_FCB FCB = FileObject->FsContext; PAFD_RECV_INFO_UDP RecvReq; PLIST_ENTRY ListEntry; PAFD_STORED_DATAGRAM DatagramRecv; KPROCESSOR_MODE LockMode; UNREFERENCED_PARAMETER(DeviceObject); AFD_DbgPrint(MID_TRACE,("Called on %p\n", FCB)); if( !SocketAcquireStateLock( FCB ) ) return LostSocket( Irp ); FCB->EventSelectDisabled &= ~AFD_EVENT_RECEIVE; /* Check that the socket is bound */ if( FCB->State != SOCKET_STATE_BOUND ) { AFD_DbgPrint(MIN_TRACE,("Invalid socket state\n")); return UnlockAndMaybeComplete(FCB, STATUS_INVALID_PARAMETER, Irp, 0); } if (FCB->TdiReceiveClosed) { AFD_DbgPrint(MIN_TRACE,("Receive closed\n")); return UnlockAndMaybeComplete(FCB, STATUS_FILE_CLOSED, Irp, 0); } if( !(RecvReq = LockRequest( Irp, IrpSp, FALSE, &LockMode )) ) return UnlockAndMaybeComplete(FCB, STATUS_NO_MEMORY, Irp, 0); AFD_DbgPrint(MID_TRACE,("Recv flags %x\n", RecvReq->AfdFlags)); RecvReq->BufferArray = LockBuffers( RecvReq->BufferArray, RecvReq->BufferCount, RecvReq->Address, RecvReq->AddressLength, TRUE, TRUE, LockMode ); if( !RecvReq->BufferArray ) { /* access violation in userspace */ return UnlockAndMaybeComplete(FCB, STATUS_ACCESS_VIOLATION, Irp, 0); } if (!IsListEmpty(&FCB->DatagramList)) { ListEntry = RemoveHeadList(&FCB->DatagramList); DatagramRecv = CONTAINING_RECORD(ListEntry, AFD_STORED_DATAGRAM, ListEntry); Status = SatisfyPacketRecvRequest(FCB, Irp, DatagramRecv, (PUINT)&Irp->IoStatus.Information); if (RecvReq->TdiFlags & TDI_RECEIVE_PEEK) { InsertHeadList(&FCB->DatagramList, &DatagramRecv->ListEntry); } if (!IsListEmpty(&FCB->DatagramList)) { FCB->PollState |= AFD_EVENT_RECEIVE; FCB->PollStatus[FD_READ_BIT] = STATUS_SUCCESS; PollReeval( FCB->DeviceExt, FCB->FileObject ); } else FCB->PollState &= ~AFD_EVENT_RECEIVE; UnlockBuffers(RecvReq->BufferArray, RecvReq->BufferCount, TRUE); return UnlockAndMaybeComplete(FCB, Status, Irp, Irp->IoStatus.Information); } else if (!(RecvReq->AfdFlags & AFD_OVERLAPPED) && ((RecvReq->AfdFlags & AFD_IMMEDIATE) || (FCB->NonBlocking))) { AFD_DbgPrint(MID_TRACE,("Nonblocking\n")); Status = STATUS_CANT_WAIT; FCB->PollState &= ~AFD_EVENT_RECEIVE; UnlockBuffers( RecvReq->BufferArray, RecvReq->BufferCount, TRUE ); return UnlockAndMaybeComplete( FCB, Status, Irp, 0 ); } else { FCB->PollState &= ~AFD_EVENT_RECEIVE; return LeaveIrpUntilLater( FCB, Irp, FUNCTION_RECV ); } }
NTSTATUS NTAPI AfdConnectedSocketReadData(PDEVICE_OBJECT DeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp, BOOLEAN Short) { NTSTATUS Status = STATUS_INVALID_PARAMETER; PFILE_OBJECT FileObject = IrpSp->FileObject; PAFD_FCB FCB = FileObject->FsContext; PAFD_RECV_INFO RecvReq; UINT TotalBytesCopied = 0; PAFD_STORED_DATAGRAM DatagramRecv; PLIST_ENTRY ListEntry; KPROCESSOR_MODE LockMode; UNREFERENCED_PARAMETER(DeviceObject); UNREFERENCED_PARAMETER(Short); AFD_DbgPrint(MID_TRACE,("Called on %p\n", FCB)); if( !SocketAcquireStateLock( FCB ) ) return LostSocket( Irp ); FCB->EventSelectDisabled &= ~AFD_EVENT_RECEIVE; if( !(FCB->Flags & AFD_ENDPOINT_CONNECTIONLESS) && FCB->State != SOCKET_STATE_CONNECTED && FCB->State != SOCKET_STATE_CONNECTING ) { AFD_DbgPrint(MIN_TRACE,("Called recv on wrong kind of socket (s%x)\n", FCB->State)); return UnlockAndMaybeComplete( FCB, STATUS_INVALID_PARAMETER, Irp, 0 ); } if( !(RecvReq = LockRequest( Irp, IrpSp, FALSE, &LockMode )) ) return UnlockAndMaybeComplete( FCB, STATUS_NO_MEMORY, Irp, 0 ); AFD_DbgPrint(MID_TRACE,("Recv flags %x\n", RecvReq->AfdFlags)); RecvReq->BufferArray = LockBuffers( RecvReq->BufferArray, RecvReq->BufferCount, NULL, NULL, TRUE, FALSE, LockMode ); if( !RecvReq->BufferArray ) { return UnlockAndMaybeComplete( FCB, STATUS_ACCESS_VIOLATION, Irp, 0 ); } if( FCB->Flags & AFD_ENDPOINT_CONNECTIONLESS ) { if (!IsListEmpty(&FCB->DatagramList)) { ListEntry = RemoveHeadList(&FCB->DatagramList); DatagramRecv = CONTAINING_RECORD(ListEntry, AFD_STORED_DATAGRAM, ListEntry); Status = SatisfyPacketRecvRequest(FCB, Irp, DatagramRecv, (PUINT)&Irp->IoStatus.Information); if (RecvReq->TdiFlags & TDI_RECEIVE_PEEK) { InsertHeadList(&FCB->DatagramList, &DatagramRecv->ListEntry); } if (!IsListEmpty(&FCB->DatagramList)) { FCB->PollState |= AFD_EVENT_RECEIVE; FCB->PollStatus[FD_READ_BIT] = STATUS_SUCCESS; PollReeval( FCB->DeviceExt, FCB->FileObject ); } else FCB->PollState &= ~AFD_EVENT_RECEIVE; UnlockBuffers(RecvReq->BufferArray, RecvReq->BufferCount, FALSE); return UnlockAndMaybeComplete(FCB, Status, Irp, Irp->IoStatus.Information); } else if (!(RecvReq->AfdFlags & AFD_OVERLAPPED) && ((RecvReq->AfdFlags & AFD_IMMEDIATE) || (FCB->NonBlocking))) { AFD_DbgPrint(MID_TRACE,("Nonblocking\n")); Status = STATUS_CANT_WAIT; FCB->PollState &= ~AFD_EVENT_RECEIVE; UnlockBuffers( RecvReq->BufferArray, RecvReq->BufferCount, FALSE ); return UnlockAndMaybeComplete( FCB, Status, Irp, 0 ); } else { FCB->PollState &= ~AFD_EVENT_RECEIVE; return LeaveIrpUntilLater( FCB, Irp, FUNCTION_RECV ); } } Irp->IoStatus.Status = STATUS_PENDING; Irp->IoStatus.Information = 0; InsertTailList( &FCB->PendingIrpList[FUNCTION_RECV], &Irp->Tail.Overlay.ListEntry ); /************ From this point, the IRP is not ours ************/ Status = ReceiveActivity( FCB, Irp ); if( Status == STATUS_PENDING && !(RecvReq->AfdFlags & AFD_OVERLAPPED) && ((RecvReq->AfdFlags & AFD_IMMEDIATE) || (FCB->NonBlocking))) { AFD_DbgPrint(MID_TRACE,("Nonblocking\n")); Status = STATUS_CANT_WAIT; TotalBytesCopied = 0; RemoveEntryList( &Irp->Tail.Overlay.ListEntry ); UnlockBuffers( RecvReq->BufferArray, RecvReq->BufferCount, FALSE ); return UnlockAndMaybeComplete( FCB, Status, Irp, TotalBytesCopied ); } else if( Status == STATUS_PENDING ) { AFD_DbgPrint(MID_TRACE,("Leaving read irp\n")); IoMarkIrpPending( Irp ); (void)IoSetCancelRoutine(Irp, AfdCancelHandler); } else { AFD_DbgPrint(MID_TRACE,("Completed with status %x\n", Status)); } SocketStateUnlock( FCB ); return Status; }
NTSTATUS NTAPI AfdConnectedSocketWriteData(PDEVICE_OBJECT DeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp, BOOLEAN Short) { NTSTATUS Status = STATUS_SUCCESS; PFILE_OBJECT FileObject = IrpSp->FileObject; PAFD_FCB FCB = FileObject->FsContext; PAFD_SEND_INFO SendReq; UINT TotalBytesCopied = 0, i, SpaceAvail = 0; BOOLEAN NoSpace = FALSE; AFD_DbgPrint(MID_TRACE,("Called on %x\n", FCB)); if( !SocketAcquireStateLock( FCB ) ) return LostSocket( Irp ); if( FCB->Flags & AFD_ENDPOINT_CONNECTIONLESS ) { PAFD_SEND_INFO_UDP SendReq; PTDI_CONNECTION_INFORMATION TargetAddress; /* Check that the socket is bound */ if( FCB->State != SOCKET_STATE_BOUND || !FCB->RemoteAddress ) { AFD_DbgPrint(MIN_TRACE,("Invalid parameter\n")); return UnlockAndMaybeComplete( FCB, STATUS_INVALID_PARAMETER, Irp, 0 ); } if( !(SendReq = LockRequest( Irp, IrpSp )) ) return UnlockAndMaybeComplete( FCB, STATUS_NO_MEMORY, Irp, 0 ); /* Must lock buffers before handing off user data */ SendReq->BufferArray = LockBuffers( SendReq->BufferArray, SendReq->BufferCount, NULL, NULL, FALSE, FALSE ); if( !SendReq->BufferArray ) { return UnlockAndMaybeComplete( FCB, STATUS_ACCESS_VIOLATION, Irp, 0 ); } Status = TdiBuildConnectionInfo( &TargetAddress, FCB->RemoteAddress ); if( NT_SUCCESS(Status) ) { FCB->EventSelectDisabled &= ~AFD_EVENT_SEND; FCB->PollState &= ~AFD_EVENT_SEND; Status = QueueUserModeIrp(FCB, Irp, FUNCTION_SEND); if (Status == STATUS_PENDING) { TdiSendDatagram(&FCB->SendIrp.InFlightRequest, FCB->AddressFile.Object, SendReq->BufferArray[0].buf, SendReq->BufferArray[0].len, TargetAddress, &FCB->SendIrp.Iosb, PacketSocketSendComplete, FCB); } ExFreePool( TargetAddress ); SocketStateUnlock(FCB); return STATUS_PENDING; } else { UnlockBuffers(SendReq->BufferArray, SendReq->BufferCount, FALSE); return UnlockAndMaybeComplete( FCB, Status, Irp, 0 ); } } if (FCB->PollState & AFD_EVENT_CLOSE) { AFD_DbgPrint(MIN_TRACE,("Connection reset by remote peer\n")); /* This is an unexpected remote disconnect */ return UnlockAndMaybeComplete(FCB, FCB->PollStatus[FD_CLOSE_BIT], Irp, 0); } if (FCB->PollState & AFD_EVENT_ABORT) { AFD_DbgPrint(MIN_TRACE,("Connection aborted\n")); /* This is an abortive socket closure on our side */ return UnlockAndMaybeComplete(FCB, FCB->PollStatus[FD_CLOSE_BIT], Irp, 0); } if (FCB->SendClosed) { AFD_DbgPrint(MIN_TRACE,("No more sends\n")); /* This is a graceful send closure */ return UnlockAndMaybeComplete(FCB, STATUS_FILE_CLOSED, Irp, 0); } if( !(SendReq = LockRequest( Irp, IrpSp )) ) return UnlockAndMaybeComplete ( FCB, STATUS_NO_MEMORY, Irp, TotalBytesCopied ); SendReq->BufferArray = LockBuffers( SendReq->BufferArray, SendReq->BufferCount, NULL, NULL, FALSE, FALSE ); if( !SendReq->BufferArray ) { return UnlockAndMaybeComplete( FCB, STATUS_ACCESS_VIOLATION, Irp, 0 ); } AFD_DbgPrint(MID_TRACE,("Socket state %d\n", FCB->State)); if( FCB->State != SOCKET_STATE_CONNECTED ) { if( (SendReq->AfdFlags & AFD_IMMEDIATE) || (FCB->NonBlocking) ) { AFD_DbgPrint(MID_TRACE,("Nonblocking\n")); UnlockBuffers( SendReq->BufferArray, SendReq->BufferCount, FALSE ); return UnlockAndMaybeComplete ( FCB, STATUS_CANT_WAIT, Irp, 0 ); } else { AFD_DbgPrint(MID_TRACE,("Queuing request\n")); return LeaveIrpUntilLater( FCB, Irp, FUNCTION_SEND ); } } AFD_DbgPrint(MID_TRACE,("FCB->Send.BytesUsed = %d\n", FCB->Send.BytesUsed)); SpaceAvail = FCB->Send.Size - FCB->Send.BytesUsed; AFD_DbgPrint(MID_TRACE,("We can accept %d bytes\n", SpaceAvail)); for( i = 0; FCB->Send.BytesUsed < FCB->Send.Size && i < SendReq->BufferCount; i++ ) { if (SpaceAvail < SendReq->BufferArray[i].len) { if (TotalBytesCopied + SendReq->BufferArray[i].len > FCB->Send.Size) { UnlockBuffers( SendReq->BufferArray, SendReq->BufferCount, FALSE ); return UnlockAndMaybeComplete(FCB, STATUS_BUFFER_OVERFLOW, Irp, 0); } SpaceAvail += TotalBytesCopied; NoSpace = TRUE; break; } AFD_DbgPrint(MID_TRACE,("Copying Buffer %d, %x:%d to %x\n", i, SendReq->BufferArray[i].buf, SendReq->BufferArray[i].len, FCB->Send.Window + FCB->Send.BytesUsed)); RtlCopyMemory( FCB->Send.Window + FCB->Send.BytesUsed, SendReq->BufferArray[i].buf, SendReq->BufferArray[i].len ); TotalBytesCopied += SendReq->BufferArray[i].len; SpaceAvail -= SendReq->BufferArray[i].len; } FCB->EventSelectDisabled &= ~AFD_EVENT_SEND; if( TotalBytesCopied == 0 ) { AFD_DbgPrint(MID_TRACE,("Empty send\n")); UnlockBuffers( SendReq->BufferArray, SendReq->BufferCount, FALSE ); return UnlockAndMaybeComplete ( FCB, STATUS_SUCCESS, Irp, TotalBytesCopied ); } if (SpaceAvail) { FCB->PollState |= AFD_EVENT_SEND; FCB->PollStatus[FD_WRITE_BIT] = STATUS_SUCCESS; PollReeval( FCB->DeviceExt, FCB->FileObject ); } else { FCB->PollState &= ~AFD_EVENT_SEND; } if (!NoSpace) { FCB->Send.BytesUsed += TotalBytesCopied; AFD_DbgPrint(MID_TRACE,("Copied %d bytes\n", TotalBytesCopied)); Status = QueueUserModeIrp(FCB, Irp, FUNCTION_SEND); if (Status == STATUS_PENDING && !FCB->SendIrp.InFlightRequest) { TdiSend(&FCB->SendIrp.InFlightRequest, FCB->Connection.Object, 0, FCB->Send.Window, FCB->Send.BytesUsed, &FCB->SendIrp.Iosb, SendComplete, FCB); } SocketStateUnlock(FCB); return STATUS_PENDING; } else { FCB->PollState &= ~AFD_EVENT_SEND; if( (SendReq->AfdFlags & AFD_IMMEDIATE) || (FCB->NonBlocking) ) { AFD_DbgPrint(MID_TRACE,("Nonblocking\n")); UnlockBuffers( SendReq->BufferArray, SendReq->BufferCount, FALSE ); return UnlockAndMaybeComplete ( FCB, STATUS_CANT_WAIT, Irp, 0 ); } else { AFD_DbgPrint(MID_TRACE,("Queuing request\n")); return LeaveIrpUntilLater( FCB, Irp, FUNCTION_SEND ); } } }
NTSTATUS NTAPI AfdEventSelect( PDEVICE_OBJECT DeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp ) { PFILE_OBJECT FileObject = IrpSp->FileObject; NTSTATUS Status = STATUS_NO_MEMORY; PAFD_EVENT_SELECT_INFO EventSelectInfo = (PAFD_EVENT_SELECT_INFO)LockRequest( Irp, IrpSp, FALSE, NULL ); PAFD_FCB FCB = FileObject->FsContext; UNREFERENCED_PARAMETER(DeviceObject); if( !SocketAcquireStateLock( FCB ) ) { return LostSocket( Irp ); } if ( !EventSelectInfo ) { return UnlockAndMaybeComplete( FCB, STATUS_NO_MEMORY, Irp, 0 ); } AFD_DbgPrint(MID_TRACE,("Called (Event %p Triggers %u)\n", EventSelectInfo->EventObject, EventSelectInfo->Events)); if( FCB->EventSelect ) ObDereferenceObject( FCB->EventSelect ); FCB->EventSelect = NULL; if( EventSelectInfo->EventObject && EventSelectInfo->Events ) { Status = ObReferenceObjectByHandle( (PVOID)EventSelectInfo-> EventObject, EVENT_ALL_ACCESS, ExEventObjectType, UserMode, (PVOID *)&FCB->EventSelect, NULL ); if( !NT_SUCCESS(Status) ) { AFD_DbgPrint(MIN_TRACE,("Failed reference event (0x%x)\n", Status)); FCB->EventSelect = NULL; } else FCB->EventSelectTriggers = EventSelectInfo->Events; } else { FCB->EventSelect = NULL; FCB->EventSelectTriggers = 0; Status = STATUS_SUCCESS; } if((FCB->EventSelect) && (FCB->PollState & (FCB->EventSelectTriggers & ~FCB->EventSelectDisabled))) { AFD_DbgPrint(MID_TRACE,("Setting event %p\n", FCB->EventSelect)); /* Set the application's event */ KeSetEvent( FCB->EventSelect, IO_NETWORK_INCREMENT, FALSE ); } AFD_DbgPrint(MID_TRACE,("Returning %x\n", Status)); return UnlockAndMaybeComplete( FCB, Status, Irp, 0 ); }
NTSTATUS NTAPI AfdConnectedSocketWriteData(PDEVICE_OBJECT DeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp, BOOLEAN Short) { NTSTATUS Status = STATUS_SUCCESS; PFILE_OBJECT FileObject = IrpSp->FileObject; PAFD_FCB FCB = FileObject->FsContext; PAFD_SEND_INFO SendReq; UINT TotalBytesCopied = 0, i, SpaceAvail = 0, BytesCopied, SendLength; KPROCESSOR_MODE LockMode; UNREFERENCED_PARAMETER(DeviceObject); UNREFERENCED_PARAMETER(Short); AFD_DbgPrint(MID_TRACE,("Called on %p\n", FCB)); if( !SocketAcquireStateLock( FCB ) ) return LostSocket( Irp ); FCB->EventSelectDisabled &= ~AFD_EVENT_SEND; if( FCB->Flags & AFD_ENDPOINT_CONNECTIONLESS ) { PAFD_SEND_INFO_UDP SendReq; PTDI_CONNECTION_INFORMATION TargetAddress; /* Check that the socket is bound */ if( FCB->State != SOCKET_STATE_BOUND || !FCB->RemoteAddress ) { AFD_DbgPrint(MIN_TRACE,("Invalid parameter\n")); return UnlockAndMaybeComplete( FCB, STATUS_INVALID_PARAMETER, Irp, 0 ); } if( !(SendReq = LockRequest( Irp, IrpSp, FALSE, &LockMode )) ) return UnlockAndMaybeComplete( FCB, STATUS_NO_MEMORY, Irp, 0 ); /* Must lock buffers before handing off user data */ SendReq->BufferArray = LockBuffers( SendReq->BufferArray, SendReq->BufferCount, NULL, NULL, FALSE, FALSE, LockMode ); if( !SendReq->BufferArray ) { return UnlockAndMaybeComplete( FCB, STATUS_ACCESS_VIOLATION, Irp, 0 ); } Status = TdiBuildConnectionInfo( &TargetAddress, FCB->RemoteAddress ); if( NT_SUCCESS(Status) ) { FCB->PollState &= ~AFD_EVENT_SEND; Status = QueueUserModeIrp(FCB, Irp, FUNCTION_SEND); if (Status == STATUS_PENDING) { TdiSendDatagram(&FCB->SendIrp.InFlightRequest, FCB->AddressFile.Object, SendReq->BufferArray[0].buf, SendReq->BufferArray[0].len, TargetAddress, PacketSocketSendComplete, FCB); } ExFreePool( TargetAddress ); SocketStateUnlock(FCB); return STATUS_PENDING; } else { UnlockBuffers(SendReq->BufferArray, SendReq->BufferCount, FALSE); return UnlockAndMaybeComplete( FCB, Status, Irp, 0 ); } } if (FCB->PollState & AFD_EVENT_CLOSE) { AFD_DbgPrint(MIN_TRACE,("Connection reset by remote peer\n")); /* This is an unexpected remote disconnect */ return UnlockAndMaybeComplete(FCB, FCB->PollStatus[FD_CLOSE_BIT], Irp, 0); } if (FCB->PollState & AFD_EVENT_ABORT) { AFD_DbgPrint(MIN_TRACE,("Connection aborted\n")); /* This is an abortive socket closure on our side */ return UnlockAndMaybeComplete(FCB, FCB->PollStatus[FD_CLOSE_BIT], Irp, 0); } if (FCB->SendClosed) { AFD_DbgPrint(MIN_TRACE,("No more sends\n")); /* This is a graceful send closure */ return UnlockAndMaybeComplete(FCB, STATUS_FILE_CLOSED, Irp, 0); } if( !(SendReq = LockRequest( Irp, IrpSp, FALSE, &LockMode )) ) return UnlockAndMaybeComplete ( FCB, STATUS_NO_MEMORY, Irp, 0 ); SendReq->BufferArray = LockBuffers( SendReq->BufferArray, SendReq->BufferCount, NULL, NULL, FALSE, FALSE, LockMode ); if( !SendReq->BufferArray ) { return UnlockAndMaybeComplete( FCB, STATUS_ACCESS_VIOLATION, Irp, 0 ); } AFD_DbgPrint(MID_TRACE,("Socket state %u\n", FCB->State)); if( FCB->State != SOCKET_STATE_CONNECTED ) { if (!(SendReq->AfdFlags & AFD_OVERLAPPED) && ((SendReq->AfdFlags & AFD_IMMEDIATE) || (FCB->NonBlocking))) { AFD_DbgPrint(MID_TRACE,("Nonblocking\n")); UnlockBuffers( SendReq->BufferArray, SendReq->BufferCount, FALSE ); return UnlockAndMaybeComplete( FCB, STATUS_CANT_WAIT, Irp, 0 ); } else { AFD_DbgPrint(MID_TRACE,("Queuing request\n")); return LeaveIrpUntilLater( FCB, Irp, FUNCTION_SEND ); } } AFD_DbgPrint(MID_TRACE,("FCB->Send.BytesUsed = %u\n", FCB->Send.BytesUsed)); SpaceAvail = FCB->Send.Size - FCB->Send.BytesUsed; AFD_DbgPrint(MID_TRACE,("We can accept %u bytes\n", SpaceAvail)); /* Count the total transfer size */ SendLength = 0; for (i = 0; i < SendReq->BufferCount; i++) { SendLength += SendReq->BufferArray[i].len; } /* Make sure we've got the space */ if (SendLength > SpaceAvail) { /* Blocking sockets have to wait here */ if (SendLength <= FCB->Send.Size && !((SendReq->AfdFlags & AFD_IMMEDIATE) || (FCB->NonBlocking))) { FCB->PollState &= ~AFD_EVENT_SEND; return LeaveIrpUntilLater(FCB, Irp, FUNCTION_SEND); } /* Check if we can send anything */ if (SpaceAvail == 0) { FCB->PollState &= ~AFD_EVENT_SEND; /* Non-overlapped sockets will fail if we can send nothing */ if (!(SendReq->AfdFlags & AFD_OVERLAPPED)) { UnlockBuffers( SendReq->BufferArray, SendReq->BufferCount, FALSE ); return UnlockAndMaybeComplete( FCB, STATUS_CANT_WAIT, Irp, 0 ); } else { /* Overlapped sockets just pend */ return LeaveIrpUntilLater(FCB, Irp, FUNCTION_SEND); } } } for ( i = 0; SpaceAvail > 0 && i < SendReq->BufferCount; i++ ) { BytesCopied = MIN(SendReq->BufferArray[i].len, SpaceAvail); AFD_DbgPrint(MID_TRACE,("Copying Buffer %u, %p:%u to %p\n", i, SendReq->BufferArray[i].buf, BytesCopied, FCB->Send.Window + FCB->Send.BytesUsed)); RtlCopyMemory(FCB->Send.Window + FCB->Send.BytesUsed, SendReq->BufferArray[i].buf, BytesCopied); TotalBytesCopied += BytesCopied; SpaceAvail -= BytesCopied; FCB->Send.BytesUsed += BytesCopied; } Irp->IoStatus.Information = TotalBytesCopied; if( TotalBytesCopied == 0 ) { AFD_DbgPrint(MID_TRACE,("Empty send\n")); UnlockBuffers( SendReq->BufferArray, SendReq->BufferCount, FALSE ); return UnlockAndMaybeComplete ( FCB, STATUS_SUCCESS, Irp, TotalBytesCopied ); } if (SpaceAvail) { FCB->PollState |= AFD_EVENT_SEND; FCB->PollStatus[FD_WRITE_BIT] = STATUS_SUCCESS; PollReeval( FCB->DeviceExt, FCB->FileObject ); } else { FCB->PollState &= ~AFD_EVENT_SEND; } /* We use the IRP tail for some temporary storage here */ Irp->Tail.Overlay.DriverContext[3] = (PVOID)Irp->IoStatus.Information; Status = QueueUserModeIrp(FCB, Irp, FUNCTION_SEND); if (Status == STATUS_PENDING && !FCB->SendIrp.InFlightRequest) { TdiSend(&FCB->SendIrp.InFlightRequest, FCB->Connection.Object, 0, FCB->Send.Window, FCB->Send.BytesUsed, SendComplete, FCB); } SocketStateUnlock(FCB); return STATUS_PENDING; }
NTSTATUS NTAPI AfdGetInfo( PDEVICE_OBJECT DeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp ) { NTSTATUS Status = STATUS_SUCCESS; PAFD_INFO InfoReq = LockRequest(Irp, IrpSp, TRUE, NULL); PFILE_OBJECT FileObject = IrpSp->FileObject; PAFD_FCB FCB = FileObject->FsContext; PLIST_ENTRY CurrentEntry; UNREFERENCED_PARAMETER(DeviceObject); AFD_DbgPrint(MID_TRACE,("Called %p %x\n", InfoReq, InfoReq ? InfoReq->InformationClass : 0)); if( !SocketAcquireStateLock( FCB ) ) return LostSocket( Irp ); if (!InfoReq) return UnlockAndMaybeComplete(FCB, STATUS_NO_MEMORY, Irp, 0); _SEH2_TRY { switch( InfoReq->InformationClass ) { case AFD_INFO_RECEIVE_WINDOW_SIZE: InfoReq->Information.Ulong = FCB->Recv.Size; break; case AFD_INFO_SEND_WINDOW_SIZE: InfoReq->Information.Ulong = FCB->Send.Size; AFD_DbgPrint(MID_TRACE,("Send window size %u\n", FCB->Send.Size)); break; case AFD_INFO_GROUP_ID_TYPE: InfoReq->Information.LargeInteger.u.HighPart = FCB->GroupType; InfoReq->Information.LargeInteger.u.LowPart = FCB->GroupID; AFD_DbgPrint(MID_TRACE, ("Group ID: %u Group Type: %u\n", FCB->GroupID, FCB->GroupType)); break; case AFD_INFO_BLOCKING_MODE: InfoReq->Information.Boolean = FCB->NonBlocking; break; case AFD_INFO_INLINING_MODE: InfoReq->Information.Boolean = FCB->OobInline; break; case AFD_INFO_RECEIVE_CONTENT_SIZE: InfoReq->Information.Ulong = FCB->Recv.Content - FCB->Recv.BytesUsed; break; case AFD_INFO_SENDS_IN_PROGRESS: InfoReq->Information.Ulong = 0; /* Count the queued sends */ CurrentEntry = FCB->PendingIrpList[FUNCTION_SEND].Flink; while (CurrentEntry != &FCB->PendingIrpList[FUNCTION_SEND]) { InfoReq->Information.Ulong++; CurrentEntry = CurrentEntry->Flink; } /* This needs to count too because when this is dispatched * the user-mode IRP has already been completed and therefore * will NOT be in our pending IRP list. We count this as one send * outstanding although it could be multiple since we batch sends * when waiting for the in flight request to return, so this number * may not be accurate but it really doesn't matter that much since * it's more or less a zero/non-zero comparison to determine whether * we can shutdown the socket */ if (FCB->SendIrp.InFlightRequest) InfoReq->Information.Ulong++; break; default: AFD_DbgPrint(MIN_TRACE,("Unknown info id %x\n", InfoReq->InformationClass)); Status = STATUS_INVALID_PARAMETER; break; } } _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) { AFD_DbgPrint(MIN_TRACE,("Exception executing GetInfo\n")); Status = STATUS_INVALID_PARAMETER; } _SEH2_END; AFD_DbgPrint(MID_TRACE,("Returning %x\n", Status)); return UnlockAndMaybeComplete( FCB, Status, Irp, 0 ); }
NTSTATUS NTAPI AfdPacketSocketWriteData(PDEVICE_OBJECT DeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp) { NTSTATUS Status = STATUS_SUCCESS; PTDI_CONNECTION_INFORMATION TargetAddress; PFILE_OBJECT FileObject = IrpSp->FileObject; PAFD_FCB FCB = FileObject->FsContext; PAFD_SEND_INFO_UDP SendReq; KPROCESSOR_MODE LockMode; UNREFERENCED_PARAMETER(DeviceObject); AFD_DbgPrint(MID_TRACE,("Called on %p\n", FCB)); if( !SocketAcquireStateLock( FCB ) ) return LostSocket( Irp ); FCB->EventSelectDisabled &= ~AFD_EVENT_SEND; /* Check that the socket is bound */ if( FCB->State != SOCKET_STATE_BOUND && FCB->State != SOCKET_STATE_CREATED) { AFD_DbgPrint(MIN_TRACE,("Invalid socket state\n")); return UnlockAndMaybeComplete(FCB, STATUS_INVALID_PARAMETER, Irp, 0); } if (FCB->SendClosed) { AFD_DbgPrint(MIN_TRACE,("No more sends\n")); return UnlockAndMaybeComplete(FCB, STATUS_FILE_CLOSED, Irp, 0); } if( !(SendReq = LockRequest( Irp, IrpSp, FALSE, &LockMode )) ) return UnlockAndMaybeComplete(FCB, STATUS_NO_MEMORY, Irp, 0); if (FCB->State == SOCKET_STATE_CREATED) { if( FCB->LocalAddress ) ExFreePool( FCB->LocalAddress ); FCB->LocalAddress = TaBuildNullTransportAddress( ((PTRANSPORT_ADDRESS)SendReq->TdiConnection.RemoteAddress)-> Address[0].AddressType ); if( FCB->LocalAddress ) { Status = WarmSocketForBind( FCB, AFD_SHARE_WILDCARD ); if( NT_SUCCESS(Status) ) FCB->State = SOCKET_STATE_BOUND; else return UnlockAndMaybeComplete( FCB, Status, Irp, 0 ); } else return UnlockAndMaybeComplete ( FCB, STATUS_NO_MEMORY, Irp, 0 ); } SendReq->BufferArray = LockBuffers( SendReq->BufferArray, SendReq->BufferCount, NULL, NULL, FALSE, FALSE, LockMode ); if( !SendReq->BufferArray ) return UnlockAndMaybeComplete( FCB, STATUS_ACCESS_VIOLATION, Irp, 0 ); AFD_DbgPrint (MID_TRACE,("RemoteAddress #%d Type %u\n", ((PTRANSPORT_ADDRESS)SendReq->TdiConnection.RemoteAddress)-> TAAddressCount, ((PTRANSPORT_ADDRESS)SendReq->TdiConnection.RemoteAddress)-> Address[0].AddressType)); Status = TdiBuildConnectionInfo( &TargetAddress, ((PTRANSPORT_ADDRESS)SendReq->TdiConnection.RemoteAddress) ); /* Check the size of the Address given ... */ if( NT_SUCCESS(Status) ) { FCB->PollState &= ~AFD_EVENT_SEND; Status = QueueUserModeIrp(FCB, Irp, FUNCTION_SEND); if (Status == STATUS_PENDING) { TdiSendDatagram(&FCB->SendIrp.InFlightRequest, FCB->AddressFile.Object, SendReq->BufferArray[0].buf, SendReq->BufferArray[0].len, TargetAddress, PacketSocketSendComplete, FCB); } ExFreePool(TargetAddress); SocketStateUnlock(FCB); return STATUS_PENDING; } else { UnlockBuffers(SendReq->BufferArray, SendReq->BufferCount, FALSE); return UnlockAndMaybeComplete( FCB, Status, Irp, 0 ); } }
NTSTATUS AfdListenSocket( PDEVICE_OBJECT DeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp ) { NTSTATUS Status = STATUS_SUCCESS; PFILE_OBJECT FileObject = IrpSp->FileObject; PAFD_FCB FCB = FileObject->FsContext; PAFD_LISTEN_DATA ListenReq; UNREFERENCED_PARAMETER(DeviceObject); AFD_DbgPrint(MID_TRACE,("Called on %p\n", FCB)); if( !SocketAcquireStateLock( FCB ) ) return LostSocket( Irp ); if( !(ListenReq = LockRequest( Irp, IrpSp, FALSE, NULL )) ) return UnlockAndMaybeComplete( FCB, STATUS_NO_MEMORY, Irp, 0 ); if( FCB->State != SOCKET_STATE_BOUND ) { Status = STATUS_INVALID_PARAMETER; AFD_DbgPrint(MIN_TRACE,("Could not listen an unbound socket\n")); return UnlockAndMaybeComplete( FCB, Status, Irp, 0 ); } FCB->DelayedAccept = ListenReq->UseDelayedAcceptance; AFD_DbgPrint(MID_TRACE,("ADDRESSFILE: %p\n", FCB->AddressFile.Handle)); Status = WarmSocketForConnection( FCB ); AFD_DbgPrint(MID_TRACE,("Status from warmsocket %x\n", Status)); if( !NT_SUCCESS(Status) ) return UnlockAndMaybeComplete( FCB, Status, Irp, 0 ); Status = TdiBuildNullConnectionInfo ( &FCB->ListenIrp.ConnectionCallInfo, FCB->LocalAddress->Address[0].AddressType ); if (!NT_SUCCESS(Status)) return UnlockAndMaybeComplete(FCB, Status, Irp, 0); Status = TdiBuildNullConnectionInfo ( &FCB->ListenIrp.ConnectionReturnInfo, FCB->LocalAddress->Address[0].AddressType ); if (!NT_SUCCESS(Status)) { ExFreePool(FCB->ListenIrp.ConnectionCallInfo); FCB->ListenIrp.ConnectionCallInfo = NULL; return UnlockAndMaybeComplete(FCB, Status, Irp, 0); } FCB->State = SOCKET_STATE_LISTENING; Status = TdiListen( &FCB->ListenIrp.InFlightRequest, FCB->Connection.Object, &FCB->ListenIrp.ConnectionCallInfo, &FCB->ListenIrp.ConnectionReturnInfo, ListenComplete, FCB ); if( Status == STATUS_PENDING ) Status = STATUS_SUCCESS; AFD_DbgPrint(MID_TRACE,("Returning %x\n", Status)); return UnlockAndMaybeComplete( FCB, Status, Irp, 0 ); }
/* Return the socket object for ths request only if it is a connected or stream type. */ NTSTATUS NTAPI AfdStreamSocketConnect(PDEVICE_OBJECT DeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp) { NTSTATUS Status = STATUS_INVALID_PARAMETER; PFILE_OBJECT FileObject = IrpSp->FileObject; PAFD_FCB FCB = FileObject->FsContext; PAFD_CONNECT_INFO ConnectReq; AFD_DbgPrint(MID_TRACE,("Called on %p\n", FCB)); UNREFERENCED_PARAMETER(DeviceObject); if( !SocketAcquireStateLock( FCB ) ) return LostSocket( Irp ); if( !(ConnectReq = LockRequest( Irp, IrpSp, FALSE, NULL )) ) return UnlockAndMaybeComplete( FCB, STATUS_NO_MEMORY, Irp, 0 ); AFD_DbgPrint(MID_TRACE,("Connect request:\n")); #if 0 OskitDumpBuffer ( (PCHAR)ConnectReq, IrpSp->Parameters.DeviceIoControl.InputBufferLength ); #endif if( FCB->Flags & AFD_ENDPOINT_CONNECTIONLESS ) { if( FCB->RemoteAddress ) ExFreePool( FCB->RemoteAddress ); FCB->RemoteAddress = TaCopyTransportAddress( &ConnectReq->RemoteAddress ); if( !FCB->RemoteAddress ) Status = STATUS_NO_MEMORY; else Status = STATUS_SUCCESS; return UnlockAndMaybeComplete( FCB, Status, Irp, 0 ); } switch( FCB->State ) { case SOCKET_STATE_CONNECTED: Status = STATUS_SUCCESS; break; case SOCKET_STATE_CONNECTING: return LeaveIrpUntilLater( FCB, Irp, FUNCTION_CONNECT ); case SOCKET_STATE_CREATED: if( FCB->LocalAddress ) ExFreePool( FCB->LocalAddress ); FCB->LocalAddress = TaBuildNullTransportAddress( ConnectReq->RemoteAddress.Address[0].AddressType ); if( FCB->LocalAddress ) { Status = WarmSocketForBind( FCB, AFD_SHARE_WILDCARD ); if( NT_SUCCESS(Status) ) FCB->State = SOCKET_STATE_BOUND; else return UnlockAndMaybeComplete( FCB, Status, Irp, 0 ); } else return UnlockAndMaybeComplete ( FCB, STATUS_NO_MEMORY, Irp, 0 ); /* Drop through to SOCKET_STATE_BOUND */ case SOCKET_STATE_BOUND: if( FCB->RemoteAddress ) ExFreePool( FCB->RemoteAddress ); FCB->RemoteAddress = TaCopyTransportAddress( &ConnectReq->RemoteAddress ); if( !FCB->RemoteAddress ) { Status = STATUS_NO_MEMORY; break; } Status = WarmSocketForConnection( FCB ); if( !NT_SUCCESS(Status) ) break; if (FCB->ConnectReturnInfo) ExFreePool(FCB->ConnectReturnInfo); Status = TdiBuildConnectionInfo ( &FCB->ConnectReturnInfo, &ConnectReq->RemoteAddress ); if( NT_SUCCESS(Status) ) { if (FCB->ConnectCallInfo) ExFreePool(FCB->ConnectCallInfo); Status = TdiBuildConnectionInfo(&FCB->ConnectCallInfo, &ConnectReq->RemoteAddress); } else break; if( NT_SUCCESS(Status) ) { 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; AFD_DbgPrint(MID_TRACE,("Queueing IRP %p\n", Irp)); Status = QueueUserModeIrp( FCB, Irp, FUNCTION_CONNECT ); if (Status == STATUS_PENDING) { Status = TdiConnect( &FCB->ConnectIrp.InFlightRequest, FCB->Connection.Object, FCB->ConnectCallInfo, FCB->ConnectReturnInfo, &FCB->ConnectIrp.Iosb, StreamSocketConnectComplete, FCB ); } if (Status != STATUS_PENDING) FCB->State = SOCKET_STATE_BOUND; SocketStateUnlock(FCB); return Status; } break; default: AFD_DbgPrint(MIN_TRACE,("Inappropriate socket state %u for connect\n", FCB->State)); break; } return UnlockAndMaybeComplete( FCB, Status, Irp, 0 ); }
NTSTATUS AfdAccept( PDEVICE_OBJECT DeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp ) { NTSTATUS Status = STATUS_SUCCESS; PFILE_OBJECT FileObject = IrpSp->FileObject; PAFD_DEVICE_EXTENSION DeviceExt = (PAFD_DEVICE_EXTENSION)DeviceObject->DeviceExtension; PAFD_FCB FCB = FileObject->FsContext; PAFD_ACCEPT_DATA AcceptData = Irp->AssociatedIrp.SystemBuffer; PLIST_ENTRY PendingConn; AFD_DbgPrint(MID_TRACE,("Called\n")); if( !SocketAcquireStateLock( FCB ) ) return LostSocket( Irp ); FCB->EventSelectDisabled &= ~AFD_EVENT_ACCEPT; for( PendingConn = FCB->PendingConnections.Flink; PendingConn != &FCB->PendingConnections; PendingConn = PendingConn->Flink ) { PAFD_TDI_OBJECT_QELT PendingConnObj = CONTAINING_RECORD( PendingConn, AFD_TDI_OBJECT_QELT, ListEntry ); AFD_DbgPrint(MID_TRACE,("Comparing Seq %u to Q %u\n", AcceptData->SequenceNumber, PendingConnObj->Seq)); if( PendingConnObj->Seq == AcceptData->SequenceNumber ) { PFILE_OBJECT NewFileObject = NULL; RemoveEntryList( PendingConn ); Status = ObReferenceObjectByHandle ( AcceptData->ListenHandle, FILE_ALL_ACCESS, NULL, KernelMode, (PVOID *)&NewFileObject, NULL ); if( !NT_SUCCESS(Status) ) return UnlockAndMaybeComplete( FCB, Status, Irp, 0 ); ASSERT(NewFileObject != FileObject); ASSERT(NewFileObject->FsContext != FCB); /* We have a pending connection ... complete this irp right away */ Status = SatisfyAccept( DeviceExt, Irp, NewFileObject, PendingConnObj ); ObDereferenceObject( NewFileObject ); AFD_DbgPrint(MID_TRACE,("Completed a wait for accept\n")); ExFreePool( PendingConnObj ); if( !IsListEmpty( &FCB->PendingConnections ) ) { FCB->PollState |= AFD_EVENT_ACCEPT; FCB->PollStatus[FD_ACCEPT_BIT] = STATUS_SUCCESS; PollReeval( FCB->DeviceExt, FCB->FileObject ); } else FCB->PollState &= ~AFD_EVENT_ACCEPT; SocketStateUnlock( FCB ); return Status; } } AFD_DbgPrint(MIN_TRACE,("No connection waiting\n")); return UnlockAndMaybeComplete( FCB, STATUS_UNSUCCESSFUL, Irp, 0 ); }
NTSTATUS NTAPI AfdSetInfo( PDEVICE_OBJECT DeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp ) { NTSTATUS Status = STATUS_SUCCESS; PAFD_INFO InfoReq = LockRequest(Irp, IrpSp, FALSE, NULL); PFILE_OBJECT FileObject = IrpSp->FileObject; PAFD_FCB FCB = FileObject->FsContext; PCHAR NewBuffer; UNREFERENCED_PARAMETER(DeviceObject); if (!SocketAcquireStateLock(FCB)) return LostSocket(Irp); if (!InfoReq) return UnlockAndMaybeComplete(FCB, STATUS_NO_MEMORY, Irp, 0); _SEH2_TRY { switch (InfoReq->InformationClass) { case AFD_INFO_BLOCKING_MODE: AFD_DbgPrint(MID_TRACE,("Blocking mode set to %u\n", InfoReq->Information.Boolean)); FCB->NonBlocking = InfoReq->Information.Boolean; break; case AFD_INFO_INLINING_MODE: FCB->OobInline = InfoReq->Information.Boolean; break; case AFD_INFO_RECEIVE_WINDOW_SIZE: NewBuffer = ExAllocatePool(PagedPool, InfoReq->Information.Ulong); if (NewBuffer) { if (FCB->Recv.Content > InfoReq->Information.Ulong) FCB->Recv.Content = InfoReq->Information.Ulong; if (FCB->Recv.Window) { RtlCopyMemory(NewBuffer, FCB->Recv.Window, FCB->Recv.Content); ExFreePool(FCB->Recv.Window); } FCB->Recv.Size = InfoReq->Information.Ulong; FCB->Recv.Window = NewBuffer; Status = STATUS_SUCCESS; } else { Status = STATUS_NO_MEMORY; } break; case AFD_INFO_SEND_WINDOW_SIZE: NewBuffer = ExAllocatePool(PagedPool, InfoReq->Information.Ulong); if (NewBuffer) { if (FCB->Send.BytesUsed > InfoReq->Information.Ulong) FCB->Send.BytesUsed = InfoReq->Information.Ulong; if (FCB->Send.Window) { RtlCopyMemory(NewBuffer, FCB->Send.Window, FCB->Send.BytesUsed); ExFreePool(FCB->Send.Window); } FCB->Send.Size = InfoReq->Information.Ulong; FCB->Send.Window = NewBuffer; Status = STATUS_SUCCESS; } else { Status = STATUS_NO_MEMORY; } break; default: AFD_DbgPrint(MIN_TRACE,("Unknown request %u\n", InfoReq->InformationClass)); break; } } _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) { AFD_DbgPrint(MIN_TRACE,("Exception executing SetInfo\n")); Status = STATUS_INVALID_PARAMETER; } _SEH2_END; AFD_DbgPrint(MID_TRACE,("Returning %x\n", Status)); return UnlockAndMaybeComplete(FCB, Status, Irp, 0); }