static VOID DisplayBuffer( PVOID Buffer, ULONG Size) { ULONG i; PCHAR p; if ((DebugTraceLevel & MAX_TRACE) == 0) return; if (!Buffer) { AFD_DbgPrint(MIN_TRACE, ("Cannot display null buffer.\n")); return; } AFD_DbgPrint(MID_TRACE, ("Displaying buffer at (0x%X) Size (%d).\n", Buffer, Size)); p = (PCHAR)Buffer; for (i = 0; i < Size; i++) { if (i % 16 == 0) DbgPrint("\n"); DbgPrint("%02X ", (p[i]) & 0xFF); } DbgPrint("\n"); }
static VOID NTAPI SelectTimeout( PKDPC Dpc, PVOID DeferredContext, PVOID SystemArgument1, PVOID SystemArgument2 ) { PAFD_ACTIVE_POLL Poll = DeferredContext; PAFD_POLL_INFO PollReq; PIRP Irp; KIRQL OldIrql; PAFD_DEVICE_EXTENSION DeviceExt; UNREFERENCED_PARAMETER(Dpc); UNREFERENCED_PARAMETER(SystemArgument1); UNREFERENCED_PARAMETER(SystemArgument2); AFD_DbgPrint(MID_TRACE,("Called\n")); Irp = Poll->Irp; DeviceExt = Poll->DeviceExt; PollReq = Irp->AssociatedIrp.SystemBuffer; ZeroEvents( PollReq->Handles, PollReq->HandleCount ); KeAcquireSpinLock( &DeviceExt->Lock, &OldIrql ); SignalSocket( Poll, NULL, PollReq, STATUS_TIMEOUT ); KeReleaseSpinLock( &DeviceExt->Lock, OldIrql ); AFD_DbgPrint(MID_TRACE,("Timeout\n")); }
NTSTATUS WarmSocketForBind( PAFD_FCB FCB, ULONG ShareType ) { NTSTATUS Status; AFD_DbgPrint(MID_TRACE,("Called (AF %u)\n", FCB->LocalAddress->Address[0].AddressType)); if( !FCB->TdiDeviceName.Length || !FCB->TdiDeviceName.Buffer ) { AFD_DbgPrint(MIN_TRACE,("Null Device\n")); return STATUS_NO_SUCH_DEVICE; } if( !FCB->LocalAddress ) { AFD_DbgPrint(MIN_TRACE,("No local address\n")); return STATUS_INVALID_PARAMETER; } Status = TdiOpenAddressFile(&FCB->TdiDeviceName, FCB->LocalAddress, ShareType, &FCB->AddressFile.Handle, &FCB->AddressFile.Object ); if (!NT_SUCCESS(Status)) return Status; if (FCB->Flags & AFD_ENDPOINT_CONNECTIONLESS) { if (!FCB->Recv.Size) { Status = TdiQueryMaxDatagramLength(FCB->AddressFile.Object, &FCB->Recv.Size); } if (NT_SUCCESS(Status) && !FCB->Recv.Window) { FCB->Recv.Window = ExAllocatePool(PagedPool, FCB->Recv.Size); if (!FCB->Recv.Window) Status = STATUS_NO_MEMORY; } if (NT_SUCCESS(Status)) { Status = TdiReceiveDatagram(&FCB->ReceiveIrp.InFlightRequest, FCB->AddressFile.Object, 0, FCB->Recv.Window, FCB->Recv.Size, FCB->AddressFrom, &FCB->ReceiveIrp.Iosb, PacketSocketRecvComplete, FCB); /* We don't want to wait for this read to complete. */ if( Status == STATUS_PENDING ) Status = STATUS_SUCCESS; } } AFD_DbgPrint(MID_TRACE,("Returning %x\n", Status)); return Status; }
NTSTATUS TdiQueryDeviceControl( PFILE_OBJECT FileObject, ULONG IoControlCode, PVOID InputBuffer, ULONG InputBufferLength, PVOID OutputBuffer, ULONG OutputBufferLength, PULONG Return) /* * FUNCTION: Queries a device for information * ARGUMENTS: * FileObject = Pointer to file object * IoControlCode = I/O control code * InputBuffer = Pointer to buffer with input data * InputBufferLength = Length of InputBuffer * OutputBuffer = Address of buffer to place output data * OutputBufferLength = Length of OutputBuffer * RETURNS: * Status of operation */ { PDEVICE_OBJECT DeviceObject; IO_STATUS_BLOCK Iosb; NTSTATUS Status; KEVENT Event; PIRP Irp; if (!FileObject) { AFD_DbgPrint(MIN_TRACE, ("Bad file object.\n")); return STATUS_INVALID_PARAMETER; } DeviceObject = IoGetRelatedDeviceObject(FileObject); if (!DeviceObject) { AFD_DbgPrint(MIN_TRACE, ("Bad device object.\n")); return STATUS_INVALID_PARAMETER; } KeInitializeEvent(&Event, NotificationEvent, FALSE); Irp = IoBuildDeviceIoControlRequest(IoControlCode, DeviceObject, InputBuffer, InputBufferLength, OutputBuffer, OutputBufferLength, FALSE, &Event, &Iosb); if (!Irp) return STATUS_INSUFFICIENT_RESOURCES; Status = TdiCall(Irp, DeviceObject, &Event, &Iosb); if (Return) *Return = Iosb.Information; return Status; }
NTSTATUS TdiSetEventHandler( PFILE_OBJECT FileObject, LONG EventType, PVOID Handler, PVOID Context) /* * FUNCTION: Sets or resets an event handler * ARGUMENTS: * FileObject = Pointer to file object * EventType = Event code * Handler = Event handler to be called when the event occurs * Context = Context input to handler when the event occurs * RETURNS: * Status of operation * NOTES: * Specify NULL for Handler to stop calling event handler */ { PDEVICE_OBJECT DeviceObject; IO_STATUS_BLOCK Iosb; KEVENT Event; PIRP Irp; AFD_DbgPrint(MAX_TRACE, ("Called\n")); if (!FileObject) { AFD_DbgPrint(MIN_TRACE, ("Bad file object.\n")); return STATUS_INVALID_PARAMETER; } DeviceObject = IoGetRelatedDeviceObject(FileObject); if (!DeviceObject) { AFD_DbgPrint(MIN_TRACE, ("Bad device object.\n")); return STATUS_INVALID_PARAMETER; } KeInitializeEvent(&Event, NotificationEvent, FALSE); Irp = TdiBuildInternalDeviceControlIrp(TDI_SET_EVENT_HANDLER, /* Sub function */ DeviceObject, /* Device object */ FileObject, /* File object */ &Event, /* Event */ &Iosb); /* Status */ if (!Irp) return STATUS_INSUFFICIENT_RESOURCES; TdiBuildSetEventHandler(Irp, DeviceObject, FileObject, NULL, NULL, EventType, Handler, Context); return TdiCall(Irp, DeviceObject, &Event, &Iosb); }
static NTSTATUS TryToSatisfyRecvRequestFromBuffer( PAFD_FCB FCB, PAFD_RECV_INFO RecvReq, PUINT TotalBytesCopied ) { UINT i, BytesToCopy = 0, FcbBytesCopied = FCB->Recv.BytesUsed, BytesAvailable = FCB->Recv.Content - FCB->Recv.BytesUsed; PAFD_MAPBUF Map; *TotalBytesCopied = 0; AFD_DbgPrint(MID_TRACE,("Called, BytesAvailable = %u\n", BytesAvailable)); if( CantReadMore(FCB) ) return STATUS_SUCCESS; if( !BytesAvailable ) return STATUS_PENDING; Map = (PAFD_MAPBUF)(RecvReq->BufferArray + RecvReq->BufferCount); AFD_DbgPrint(MID_TRACE,("Buffer Count: %u @ %p\n", RecvReq->BufferCount, RecvReq->BufferArray)); for( i = 0; RecvReq->BufferArray && BytesAvailable && i < RecvReq->BufferCount; i++ ) { BytesToCopy = MIN( RecvReq->BufferArray[i].len, BytesAvailable ); if( Map[i].Mdl ) { Map[i].BufferAddress = MmMapLockedPages( Map[i].Mdl, KernelMode ); AFD_DbgPrint(MID_TRACE,("Buffer %u: %p:%u\n", i, Map[i].BufferAddress, BytesToCopy)); RtlCopyMemory( Map[i].BufferAddress, FCB->Recv.Window + FcbBytesCopied, BytesToCopy ); MmUnmapLockedPages( Map[i].BufferAddress, Map[i].Mdl ); *TotalBytesCopied += BytesToCopy; FcbBytesCopied += BytesToCopy; BytesAvailable -= BytesToCopy; if (!(RecvReq->TdiFlags & TDI_RECEIVE_PEEK)) FCB->Recv.BytesUsed += BytesToCopy; } } /* Issue another receive IRP to keep the buffer well stocked */ RefillSocketBuffer(FCB); return STATUS_SUCCESS; }
NTSTATUS TdiConnect( PIRP *Irp, PFILE_OBJECT ConnectionObject, PTDI_CONNECTION_INFORMATION ConnectionCallInfo, PTDI_CONNECTION_INFORMATION ConnectionReturnInfo, PIO_COMPLETION_ROUTINE CompletionRoutine, PVOID CompletionContext) /* * FUNCTION: Connect a connection endpoint to a remote peer * ARGUMENTS: * ConnectionObject = Pointer to connection endpoint file object * RemoteAddress = Pointer to remote address * RETURNS: * Status of operation */ { PDEVICE_OBJECT DeviceObject; AFD_DbgPrint(MAX_TRACE, ("Called\n")); ASSERT(*Irp == NULL); if (!ConnectionObject) { AFD_DbgPrint(MIN_TRACE, ("Bad connection object.\n")); return STATUS_INVALID_PARAMETER; } DeviceObject = IoGetRelatedDeviceObject(ConnectionObject); if (!DeviceObject) { AFD_DbgPrint(MIN_TRACE, ("Bad device object.\n")); return STATUS_INVALID_PARAMETER; } *Irp = TdiBuildInternalDeviceControlIrp(TDI_CONNECT, /* Sub function */ DeviceObject, /* Device object */ ConnectionObject, /* File object */ NULL, /* Event */ NULL); /* Status */ if (!*Irp) { return STATUS_INSUFFICIENT_RESOURCES; } TdiBuildConnect(*Irp, /* IRP */ DeviceObject, /* Device object */ ConnectionObject, /* File object */ CompletionRoutine, /* Completion routine */ CompletionContext, /* Completion routine context */ NULL, /* Time */ ConnectionCallInfo, /* Request connection information */ ConnectionReturnInfo); /* Return connection information */ TdiCall(*Irp, DeviceObject, NULL, NULL); return STATUS_PENDING; }
NTSTATUS TdiListen( PIRP *Irp, PFILE_OBJECT ConnectionObject, PTDI_CONNECTION_INFORMATION *RequestConnectionInfo, PTDI_CONNECTION_INFORMATION *ReturnConnectionInfo, PIO_COMPLETION_ROUTINE CompletionRoutine, PVOID CompletionContext) /* * FUNCTION: Listen on a connection endpoint for a connection request from a remote peer * ARGUMENTS: * CompletionRoutine = Routine to be called when IRP is completed * CompletionContext = Context for CompletionRoutine * RETURNS: * Status of operation * May return STATUS_PENDING */ { PDEVICE_OBJECT DeviceObject; AFD_DbgPrint(MAX_TRACE, ("Called\n")); ASSERT(*Irp == NULL); if (!ConnectionObject) { AFD_DbgPrint(MIN_TRACE, ("Bad connection object.\n")); return STATUS_INVALID_PARAMETER; } DeviceObject = IoGetRelatedDeviceObject(ConnectionObject); if (!DeviceObject) { AFD_DbgPrint(MIN_TRACE, ("Bad device object.\n")); return STATUS_INVALID_PARAMETER; } *Irp = TdiBuildInternalDeviceControlIrp(TDI_LISTEN, /* Sub function */ DeviceObject, /* Device object */ ConnectionObject, /* File object */ NULL, /* Event */ NULL); /* Status */ if (*Irp == NULL) return STATUS_INSUFFICIENT_RESOURCES; TdiBuildListen(*Irp, /* IRP */ DeviceObject, /* Device object */ ConnectionObject, /* File object */ CompletionRoutine, /* Completion routine */ CompletionContext, /* Completion routine context */ 0, /* Flags */ *RequestConnectionInfo, /* Request connection information */ *ReturnConnectionInfo); /* Return connection information */ TdiCall(*Irp, DeviceObject, NULL /* Don't wait for completion */, NULL); return STATUS_PENDING; }
NTSTATUS AfdEventReceive( IN PVOID TdiEventContext, IN CONNECTION_CONTEXT ConnectionContext, IN ULONG ReceiveFlags, IN ULONG BytesIndicated, IN ULONG BytesAvailable, OUT ULONG *BytesTaken, IN PVOID Tsdu, OUT PIRP *IoRequestPacket) { PAFDFCB FCB = (PAFDFCB)TdiEventContext; PVOID ReceiveBuffer; PAFD_BUFFER Buffer; KIRQL OldIrql; AFD_DbgPrint(MAX_TRACE, ("Called.\n")); AFD_DbgPrint(MID_TRACE, ("Receiving (%d) bytes on socket\n", BytesAvailable)); ReceiveBuffer = ExAllocatePool(NonPagedPool, BytesAvailable); if (!ReceiveBuffer) return STATUS_INSUFFICIENT_RESOURCES; /*Buffer = (PAFD_BUFFER)ExAllocateFromNPagedLookasideList( &BufferLookasideList);*/ Buffer = (PAFD_BUFFER)ExAllocatePool(NonPagedPool, sizeof(AFD_BUFFER)); if (!Buffer) { ExFreePool(ReceiveBuffer); return STATUS_INSUFFICIENT_RESOURCES; } /* Copy the data to a local buffer */ RtlCopyMemory(ReceiveBuffer, Tsdu, BytesAvailable); Buffer->Buffer.len = BytesAvailable; Buffer->Buffer.buf = ReceiveBuffer; Buffer->Offset = 0; KeAcquireSpinLock(&FCB->ReceiveQueueLock, &OldIrql); InsertTailList( &FCB->ReceiveQueue, &Buffer->ListEntry ); TryToSatisfyRecvRequest( FCB, TRUE ); KeReleaseSpinLock(&FCB->ReceiveQueueLock, OldIrql); *BytesTaken = BytesAvailable; AFD_DbgPrint(MAX_TRACE, ("Leaving.\n")); return STATUS_SUCCESS; }
NTSTATUS TdiQueryInformation( PFILE_OBJECT FileObject, LONG QueryType, PMDL MdlBuffer) /* * FUNCTION: Query for information * ARGUMENTS: * FileObject = Pointer to file object * QueryType = Query type * MdlBuffer = Pointer to MDL buffer specific for query type * RETURNS: * Status of operation */ { PDEVICE_OBJECT DeviceObject; IO_STATUS_BLOCK Iosb; KEVENT Event; PIRP Irp; if (!FileObject) { AFD_DbgPrint(MIN_TRACE, ("Bad file object.\n")); return STATUS_INVALID_PARAMETER; } DeviceObject = IoGetRelatedDeviceObject(FileObject); if (!DeviceObject) { AFD_DbgPrint(MIN_TRACE, ("Bad device object.\n")); return STATUS_INVALID_PARAMETER; } KeInitializeEvent(&Event, NotificationEvent, FALSE); Irp = TdiBuildInternalDeviceControlIrp(TDI_QUERY_INFORMATION, /* Sub function */ DeviceObject, /* Device object */ ConnectionObject, /* File object */ &Event, /* Event */ &Iosb); /* Status */ if (!Irp) { return STATUS_INSUFFICIENT_RESOURCES; } TdiBuildQueryInformation(Irp, DeviceObject, FileObject, NULL, NULL, QueryType, MdlBuffer); return TdiCall(Irp, DeviceObject, &Event, &Iosb); }
NTSTATUS TdiAssociateAddressFile( HANDLE AddressHandle, PFILE_OBJECT ConnectionObject) /* * FUNCTION: Associates a connection endpoint to an address file object * ARGUMENTS: * AddressHandle = Handle to address file object * ConnectionObject = Connection endpoint file object * RETURNS: * Status of operation */ { PDEVICE_OBJECT DeviceObject; IO_STATUS_BLOCK Iosb; KEVENT Event; PIRP Irp; AFD_DbgPrint(MAX_TRACE, ("Called. AddressHandle (%p) ConnectionObject (%p)\n", AddressHandle, ConnectionObject)); if (!ConnectionObject) { AFD_DbgPrint(MIN_TRACE, ("Bad connection object.\n")); return STATUS_INVALID_PARAMETER; } DeviceObject = IoGetRelatedDeviceObject(ConnectionObject); if (!DeviceObject) { AFD_DbgPrint(MIN_TRACE, ("Bad device object.\n")); return STATUS_INVALID_PARAMETER; } KeInitializeEvent(&Event, NotificationEvent, FALSE); Irp = TdiBuildInternalDeviceControlIrp(TDI_ASSOCIATE_ADDRESS, /* Sub function */ DeviceObject, /* Device object */ ConnectionObject, /* File object */ &Event, /* Event */ &Iosb); /* Status */ if (!Irp) return STATUS_INSUFFICIENT_RESOURCES; TdiBuildAssociateAddress(Irp, DeviceObject, ConnectionObject, NULL, NULL, AddressHandle); return TdiCall(Irp, DeviceObject, &Event, &Iosb); }
NTSTATUS NTAPI ReceiveComplete ( PDEVICE_OBJECT DeviceObject, PIRP Irp, PVOID Context ) { PAFD_FCB FCB = (PAFD_FCB)Context; PLIST_ENTRY NextIrpEntry; PIRP NextIrp; PAFD_RECV_INFO RecvReq; PIO_STACK_LOCATION NextIrpSp; UNREFERENCED_PARAMETER(DeviceObject); AFD_DbgPrint(MID_TRACE,("Called\n")); if( !SocketAcquireStateLock( FCB ) ) return STATUS_FILE_CLOSED; ASSERT(FCB->ReceiveIrp.InFlightRequest == Irp); FCB->ReceiveIrp.InFlightRequest = NULL; if( FCB->State == SOCKET_STATE_CLOSED ) { /* Cleanup our IRP queue because the FCB is being destroyed */ while( !IsListEmpty( &FCB->PendingIrpList[FUNCTION_RECV] ) ) { NextIrpEntry = RemoveHeadList(&FCB->PendingIrpList[FUNCTION_RECV]); NextIrp = CONTAINING_RECORD(NextIrpEntry, IRP, Tail.Overlay.ListEntry); NextIrpSp = IoGetCurrentIrpStackLocation(NextIrp); RecvReq = GetLockedData(NextIrp, NextIrpSp); NextIrp->IoStatus.Status = STATUS_FILE_CLOSED; NextIrp->IoStatus.Information = 0; UnlockBuffers(RecvReq->BufferArray, RecvReq->BufferCount, FALSE); if( NextIrp->MdlAddress ) UnlockRequest( NextIrp, IoGetCurrentIrpStackLocation( NextIrp ) ); (void)IoSetCancelRoutine(NextIrp, NULL); IoCompleteRequest( NextIrp, IO_NETWORK_INCREMENT ); } SocketStateUnlock( FCB ); return STATUS_FILE_CLOSED; } else if( FCB->State == SOCKET_STATE_LISTENING ) { AFD_DbgPrint(MIN_TRACE,("!!! LISTENER GOT A RECEIVE COMPLETE !!!\n")); SocketStateUnlock( FCB ); return STATUS_INVALID_PARAMETER; } HandleReceiveComplete( FCB, Irp->IoStatus.Status, Irp->IoStatus.Information ); ReceiveActivity( FCB, NULL ); SocketStateUnlock( FCB ); return STATUS_SUCCESS; }
NTSTATUS TdiDisconnect( PIRP *Irp, PFILE_OBJECT TransportObject, PLARGE_INTEGER Time, USHORT Flags, PIO_COMPLETION_ROUTINE CompletionRoutine, PVOID CompletionContext, PTDI_CONNECTION_INFORMATION RequestConnectionInfo, PTDI_CONNECTION_INFORMATION ReturnConnectionInfo) { PDEVICE_OBJECT DeviceObject; if (!TransportObject) { AFD_DbgPrint(MIN_TRACE, ("Bad transport object.\n")); return STATUS_INVALID_PARAMETER; } AFD_DbgPrint(MID_TRACE,("Called(TransportObject %p)\n", TransportObject)); DeviceObject = IoGetRelatedDeviceObject(TransportObject); if (!DeviceObject) { AFD_DbgPrint(MIN_TRACE, ("Bad device object.\n")); return STATUS_INVALID_PARAMETER; } *Irp = TdiBuildInternalDeviceControlIrp(TDI_DISCONNECT, /* Sub function */ DeviceObject, /* Device object */ TransportObject, /* File object */ NULL, /* Event */ NULL); /* Status */ if (!*Irp) { AFD_DbgPrint(MIN_TRACE, ("Insufficient resources.\n")); return STATUS_INSUFFICIENT_RESOURCES; } TdiBuildDisconnect(*Irp, /* I/O Request Packet */ DeviceObject, /* Device object */ TransportObject, /* File object */ CompletionRoutine, /* Completion routine */ CompletionContext, /* Completion context */ Time, /* Time */ Flags, /* Disconnect flags */ RequestConnectionInfo, /* Indication of who to disconnect */ ReturnConnectionInfo); /* Indication of who disconnected */ TdiCall(*Irp, DeviceObject, NULL, NULL); return STATUS_PENDING; }
VOID PollReeval( PAFD_DEVICE_EXTENSION DeviceExt, PFILE_OBJECT FileObject ) { PAFD_ACTIVE_POLL Poll = NULL; PLIST_ENTRY ThePollEnt = NULL; PAFD_FCB FCB; KIRQL OldIrql; PAFD_POLL_INFO PollReq; AFD_DbgPrint(MID_TRACE,("Called: DeviceExt %p FileObject %p\n", DeviceExt, FileObject)); KeAcquireSpinLock( &DeviceExt->Lock, &OldIrql ); /* Take care of any event select signalling */ FCB = (PAFD_FCB)FileObject->FsContext; if( !FCB ) { KeReleaseSpinLock( &DeviceExt->Lock, OldIrql ); return; } /* Now signal normal select irps */ ThePollEnt = DeviceExt->Polls.Flink; while( ThePollEnt != &DeviceExt->Polls ) { Poll = CONTAINING_RECORD( ThePollEnt, AFD_ACTIVE_POLL, ListEntry ); PollReq = Poll->Irp->AssociatedIrp.SystemBuffer; AFD_DbgPrint(MID_TRACE,("Checking poll %p\n", Poll)); if( UpdatePollWithFCB( Poll, FileObject ) ) { ThePollEnt = ThePollEnt->Flink; AFD_DbgPrint(MID_TRACE,("Signalling socket\n")); SignalSocket( Poll, NULL, PollReq, STATUS_SUCCESS ); } else ThePollEnt = ThePollEnt->Flink; } KeReleaseSpinLock( &DeviceExt->Lock, OldIrql ); 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,("Leaving\n")); }
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 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 TdiBuildNullConnectionInfoInPlace ( PTDI_CONNECTION_INFORMATION ConnInfo, ULONG Type ) /* * FUNCTION: Builds a NULL TDI connection information structure * ARGUMENTS: * ConnectionInfo = Address of buffer to place connection information * Type = TDI style address type (TDI_ADDRESS_TYPE_XXX). * RETURNS: * Status of operation */ { ULONG TdiAddressSize; PTRANSPORT_ADDRESS TransportAddress; TdiAddressSize = TaLengthOfTransportAddressByType(Type); if (!TdiAddressSize) { AFD_DbgPrint(MIN_TRACE,("Invalid parameter\n")); return STATUS_INVALID_PARAMETER; } RtlZeroMemory(ConnInfo, sizeof(TDI_CONNECTION_INFORMATION) + TdiAddressSize); ConnInfo->OptionsLength = sizeof(ULONG); ConnInfo->RemoteAddressLength = TdiAddressSize; ConnInfo->RemoteAddress = TransportAddress = (PTRANSPORT_ADDRESS)&ConnInfo[1]; return TdiBuildNullTransportAddressInPlace(TransportAddress, Type); }
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 ); }
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 AfdEventError( IN PVOID TdiEventContext, IN NTSTATUS Status) { AFD_DbgPrint(MAX_TRACE, ("Called.\n")); return STATUS_SUCCESS; }
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 TdiOpenAddressFile( PUNICODE_STRING DeviceName, PTRANSPORT_ADDRESS Name, ULONG ShareType, PHANDLE AddressHandle, PFILE_OBJECT *AddressObject) /* * FUNCTION: Opens an IPv4 address file object * ARGUMENTS: * DeviceName = Pointer to counted string with name of device * Name = Pointer to socket name (IPv4 address family) * AddressHandle = Address of buffer to place address file handle * AddressObject = Address of buffer to place address file object * RETURNS: * Status of operation */ { PFILE_FULL_EA_INFORMATION EaInfo; NTSTATUS Status; ULONG EaLength; PTRANSPORT_ADDRESS Address; AFD_DbgPrint(MAX_TRACE, ("Called. DeviceName (%wZ) Name (%p)\n", DeviceName, Name)); /* EaName must be 0-terminated, even though TDI_TRANSPORT_ADDRESS_LENGTH does *not* include the 0 */ EaLength = sizeof(FILE_FULL_EA_INFORMATION) + TDI_TRANSPORT_ADDRESS_LENGTH + TaLengthOfTransportAddress( Name ) + 1; EaInfo = (PFILE_FULL_EA_INFORMATION)ExAllocatePool(NonPagedPool, EaLength); if (!EaInfo) return STATUS_INSUFFICIENT_RESOURCES; RtlZeroMemory(EaInfo, EaLength); EaInfo->EaNameLength = TDI_TRANSPORT_ADDRESS_LENGTH; /* Don't copy the terminating 0; we have already zeroed it */ RtlCopyMemory(EaInfo->EaName, TdiTransportAddress, TDI_TRANSPORT_ADDRESS_LENGTH); EaInfo->EaValueLength = sizeof(TA_IP_ADDRESS); Address = (PTRANSPORT_ADDRESS)(EaInfo->EaName + TDI_TRANSPORT_ADDRESS_LENGTH + 1); /* 0-terminated */ TaCopyTransportAddressInPlace( Address, Name ); Status = TdiOpenDevice(DeviceName, EaLength, EaInfo, ShareType, AddressHandle, AddressObject); ExFreePool(EaInfo); return Status; }
static NTSTATUS TdiCall( PIRP Irp, PDEVICE_OBJECT DeviceObject, PKEVENT Event, PIO_STATUS_BLOCK Iosb) /* * FUNCTION: Calls a transport driver device * ARGUMENTS: * Irp = Pointer to I/O Request Packet * DeviceObject = Pointer to device object to call * Event = An optional pointer to an event handle that will be * waited upon * Iosb = Pointer to an IO status block * RETURNS: * Status of operation */ { NTSTATUS Status; AFD_DbgPrint(MID_TRACE, ("Called\n")); AFD_DbgPrint(MID_TRACE, ("Irp->UserEvent = %p\n", Irp->UserEvent)); Status = IoCallDriver(DeviceObject, Irp); AFD_DbgPrint(MID_TRACE, ("IoCallDriver: %08x\n", Status)); if ((Status == STATUS_PENDING) && (Event != NULL)) { AFD_DbgPrint(MAX_TRACE, ("Waiting on transport.\n")); KeWaitForSingleObject(Event, Executive, KernelMode, FALSE, NULL); Status = Iosb->Status; } AFD_DbgPrint(MAX_TRACE, ("Status (0x%X).\n", Status)); return Status; }
NTSTATUS AfdEventDisconnect( IN PVOID TdiEventContext, IN CONNECTION_CONTEXT ConnectionContext, IN LONG DisconnectDataLength, IN PVOID DisconnectData, IN LONG DisconnectInformationLength, IN PVOID DisconnectInformation, IN ULONG DisconnectFlags) { AFD_DbgPrint(MAX_TRACE, ("Called.\n")); return STATUS_SUCCESS; }
UINT TaLengthOfAddress( PTA_ADDRESS Addr ) { UINT AddrLen = Addr->AddressLength; if (!AddrLen) return 0; AddrLen += 2 * sizeof( USHORT ); AFD_DbgPrint(MID_TRACE,("AddrLen %x\n", AddrLen)); return AddrLen; }
UINT TaLengthOfTransportAddress( PTRANSPORT_ADDRESS Addr ) { UINT AddrLen = TaLengthOfAddress(&Addr->Address[0]); if (!AddrLen) return 0; AddrLen += sizeof(ULONG); AFD_DbgPrint(MID_TRACE,("AddrLen %x\n", AddrLen)); return AddrLen; }
UINT TaLengthOfTransportAddressByType(UINT AddressType) { UINT AddrLen = TdiAddressSizeFromType(AddressType); if (!AddrLen) return 0; AddrLen += sizeof(ULONG) + 2 * sizeof(USHORT); AFD_DbgPrint(MID_TRACE,("AddrLen %x\n", AddrLen)); return AddrLen; }
NTSTATUS ClientEventChainedReceive( IN PVOID TdiEventContext, IN CONNECTION_CONTEXT ConnectionContext, IN ULONG ReceiveFlags, IN ULONG ReceiveLength, IN ULONG StartingOffset, IN PMDL Tsdu, IN PVOID TsduDescriptor) { AFD_DbgPrint(MAX_TRACE, ("Called.\n")); return STATUS_SUCCESS; }
NTSTATUS TdiQueryMaxDatagramLength( PFILE_OBJECT FileObject, PUINT MaxDatagramLength) { PMDL Mdl; PTDI_MAX_DATAGRAM_INFO Buffer; NTSTATUS Status = STATUS_SUCCESS; Buffer = ExAllocatePool(NonPagedPool, sizeof(TDI_MAX_DATAGRAM_INFO)); if (!Buffer) return STATUS_NO_MEMORY; Mdl = IoAllocateMdl(Buffer, sizeof(TDI_MAX_DATAGRAM_INFO), FALSE, FALSE, NULL); if (!Mdl) { ExFreePool(Buffer); return STATUS_NO_MEMORY; } _SEH2_TRY { MmProbeAndLockPages(Mdl, KernelMode, IoModifyAccess); } _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) { Status = _SEH2_GetExceptionCode(); } _SEH2_END; if (!NT_SUCCESS(Status)) { AFD_DbgPrint(MIN_TRACE,("Failed to lock pages\n")); IoFreeMdl(Mdl); ExFreePool(Buffer); return Status; } Status = TdiQueryInformation(FileObject, TDI_QUERY_MAX_DATAGRAM_INFO, Mdl); if (!NT_SUCCESS(Status)) { ExFreePool(Buffer); return Status; } *MaxDatagramLength = Buffer->MaxDatagramSize; ExFreePool(Buffer); return STATUS_SUCCESS; }