First commit of afd and msafd onto head.

tcpip: Turned off debug info in CVS.

svn path=/trunk/; revision=10210
This commit is contained in:
Art Yerkes 2004-07-18 22:49:18 +00:00
parent cd35daab59
commit 0f1eb55991
32 changed files with 4654 additions and 4259 deletions

View file

@ -1,219 +0,0 @@
/*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS Ancillary Function Driver
* FILE: afd/afd.c
* PURPOSE: MSAFD kernel mode module
* PROGRAMMERS: Casper S. Hornstrup (chorns@users.sourceforge.net)
* REVISIONS:
* CSH 01/09-2000 Created
*/
#include <afd.h>
#include <rosrtl/string.h>
#ifdef DBG
/* See debug.h for debug/trace constants */
//DWORD DebugTraceLevel = MID_TRACE;
DWORD DebugTraceLevel = DEBUG_ULTRA;
#endif /* DBG */
NPAGED_LOOKASIDE_LIST BufferLookasideList;
NPAGED_LOOKASIDE_LIST ReadRequestLookasideList;
NPAGED_LOOKASIDE_LIST ListenRequestLookasideList;
NTSTATUS
STDCALL
AfdFileSystemControl(
PDEVICE_OBJECT DeviceObject,
PIRP Irp)
{
UNIMPLEMENTED
Irp->IoStatus.Status = STATUS_UNSUCCESSFUL;
Irp->IoStatus.Information = 0;
return STATUS_UNSUCCESSFUL;
}
NTSTATUS
STDCALL
AfdDispatch(
PDEVICE_OBJECT DeviceObject,
PIRP Irp)
/*
* FUNCTION: IOCTL dispatch routine
* ARGUMENTS:
* DeviceObject = Pointer to a device object for this driver
* Irp = Pointer to a I/O request packet
* RETURNS:
* Status of the operation
*/
{
NTSTATUS Status;
PIO_STACK_LOCATION IrpSp;
BOOL DoComplete = TRUE;
IrpSp = IoGetCurrentIrpStackLocation(Irp);
AFD_DbgPrint(MAX_TRACE, ("Called. DeviceObject is at (0x%X), IRP is at (0x%X), IrpSp->FileObject (0x%X).\n",
DeviceObject, Irp, IrpSp->FileObject));
Irp->IoStatus.Information = IrpSp->Parameters.DeviceIoControl.OutputBufferLength;
switch (IrpSp->Parameters.DeviceIoControl.IoControlCode) {
case IOCTL_AFD_BIND:
Status = AfdDispBind(Irp, IrpSp);
break;
case IOCTL_AFD_LISTEN:
Status = AfdDispListen(Irp, IrpSp);
break;
case IOCTL_AFD_SENDTO:
Status = AfdDispSendTo(Irp, IrpSp);
break;
case IOCTL_AFD_RECVFROM:
Status = AfdDispRecvFrom(Irp, IrpSp);
break;
case IOCTL_AFD_SELECT:
Status = AfdDispSelect(Irp, IrpSp);
break;
case IOCTL_AFD_EVENTSELECT:
Status = AfdDispEventSelect(Irp, IrpSp);
break;
case IOCTL_AFD_ENUMNETWORKEVENTS:
Status = AfdDispEnumNetworkEvents(Irp, IrpSp);
break;
case IOCTL_AFD_RECV:
Status = AfdDispRecv(Irp, IrpSp);
DoComplete = FALSE;
break;
case IOCTL_AFD_SEND:
Status = AfdDispSend(Irp, IrpSp);
break;
case IOCTL_AFD_CONNECT:
Status = AfdDispConnect(Irp, IrpSp);
break;
case IOCTL_AFD_GETNAME:
Status = AfdDispGetName(Irp, IrpSp);
break;
default:
Irp->IoStatus.Information = 0;
AFD_DbgPrint(MIN_TRACE, ("Unknown IOCTL (0x%X).\n",
IrpSp->Parameters.DeviceIoControl.IoControlCode));
Status = STATUS_NOT_IMPLEMENTED;
break;
}
if (Status != STATUS_PENDING && DoComplete) {
Irp->IoStatus.Status = Status;
IoCompleteRequest(Irp, IO_NETWORK_INCREMENT);
}
AFD_DbgPrint(MAX_TRACE, ("Leaving. Status (0x%X).\n", Status));
return Status;
}
VOID STDCALL AfdUnload(
PDRIVER_OBJECT DriverObject)
/*
* FUNCTION: Unloads the driver
* ARGUMENTS:
* DriverObject = Pointer to driver object created by the system
*/
{
}
NTSTATUS
STDCALL
DriverEntry(
PDRIVER_OBJECT DriverObject,
PUNICODE_STRING RegistryPath)
/*
* FUNCTION: Called by the system to initialize the driver
* ARGUMENTS:
* DriverObject = object describing this driver
* RegistryPath = path to our configuration entries
* RETURNS:
* Status of operation
*/
{
PDEVICE_EXTENSION DeviceExt;
PDEVICE_OBJECT DeviceObject;
UNICODE_STRING DeviceName = ROS_STRING_INITIALIZER(L"\\Device\\Afd");
NTSTATUS Status;
Status = IoCreateDevice(DriverObject,
sizeof(DEVICE_EXTENSION),
&DeviceName,
FILE_DEVICE_NAMED_PIPE,
0,
FALSE,
&DeviceObject);
if (!NT_SUCCESS(Status)) {
AFD_DbgPrint(MIN_TRACE, ("Could not create device (0x%X).\n", Status));
return Status;
}
DeviceObject->Flags |= DO_DIRECT_IO;
DeviceExt = DeviceObject->DeviceExtension;
KeInitializeSpinLock(&DeviceExt->FCBListLock);
InitializeListHead(&DeviceExt->FCBListHead);
DriverObject->MajorFunction[IRP_MJ_CREATE] = AfdCreate;
DriverObject->MajorFunction[IRP_MJ_CLOSE] = AfdClose;
DriverObject->MajorFunction[IRP_MJ_READ] = AfdRead;
DriverObject->MajorFunction[IRP_MJ_WRITE] = AfdWrite;
DriverObject->MajorFunction[IRP_MJ_FILE_SYSTEM_CONTROL] = AfdFileSystemControl;
DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = AfdDispatch;
DriverObject->MajorFunction[IRP_MJ_CLEANUP] = AfdClose;
DriverObject->DriverUnload = AfdUnload;
/* ExInitializeNPagedLookasideList(
&BufferLookasideList,
NULL,
NULL,
0,
sizeof(AFD_BUFFER),
TAG('A', 'F', 'D', 'B'),
0);*/
/* ExInitializeNPagedLookasideList(
&ReadRequestLookasideList,
NULL,
NULL,
0,
sizeof(AFD_READ_REQUEST),
TAG('A', 'F', 'D', 'R'),
0);*/
ExInitializeNPagedLookasideList(
&ListenRequestLookasideList,
NULL,
NULL,
0,
sizeof(AFD_LISTEN_REQUEST),
TAG('A', 'F', 'D', 'L'),
0);
return STATUS_SUCCESS;
}
/* EOF */

View file

@ -0,0 +1,87 @@
/* $Id: bind.c,v 1.2 2004/07/18 22:49:17 arty Exp $
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel
* FILE: drivers/net/afd/afd/bind.c
* PURPOSE: Ancillary functions driver
* PROGRAMMER: Art Yerkes (ayerkes@speakeasy.net)
* UPDATE HISTORY:
* 20040708 Created
*/
#include "afd.h"
#include "tdi_proto.h"
#include "tdiconn.h"
#include "debug.h"
NTSTATUS WarmSocketForBind( PAFD_FCB FCB ) {
NTSTATUS Status = STATUS_UNSUCCESSFUL;
AFD_DbgPrint(MID_TRACE,("Called\n"));
if( FCB->LocalAddress ) {
Status = TdiOpenAddressFile
( &FCB->TdiDeviceName,
FCB->LocalAddress,
&FCB->AddressFile.Handle,
&FCB->AddressFile.Object );
}
if( !NT_SUCCESS(Status) ) {
TdiCloseDevice( &FCB->AddressFile.Handle,
FCB->AddressFile.Object );
RtlZeroMemory( &FCB->AddressFile, sizeof( FCB->AddressFile ) );
}
AFD_DbgPrint(MID_TRACE,("Returning %x\n", Status));
return Status;
}
NTSTATUS STDCALL
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;
AFD_DbgPrint(MID_TRACE,("Called\n"));
if( !SocketAcquireStateLock( FCB ) ) return LostSocket( Irp );
if( !(BindReq = LockRequest( Irp, IrpSp )) )
return UnlockAndMaybeComplete( FCB, STATUS_NO_MEMORY,
Irp, 0, NULL, FALSE );
FCB->LocalAddress = TaCopyTransportAddress( &BindReq->Address );
if( FCB->LocalAddress )
Status = WarmSocketForBind( FCB );
else Status = STATUS_NO_MEMORY;
if( NT_SUCCESS(Status) )
FCB->State = SOCKET_STATE_BOUND;
if( FCB->Flags & SGID_CONNECTIONLESS ) {
/* This will be the from address for subsequent recvfrom calls */
TdiBuildConnectionInfo( &FCB->AddressFrom,
&FCB->LocalAddress->Address[0] );
/* Allocate our backup buffer */
FCB->Recv.Window = ExAllocatePool( NonPagedPool, FCB->Recv.Size );
FCB->PollState |= AFD_EVENT_SEND;
/* A datagram socket is always sendable */
Status = TdiReceiveDatagram
( &FCB->ReceiveIrp.InFlightRequest,
FCB->AddressFile.Object,
0,
FCB->Recv.Window,
FCB->Recv.Size,
FCB->AddressFrom,
&FCB->ReceiveIrp.Iosb,
PacketSocketRecvComplete,
FCB );
}
return UnlockAndMaybeComplete( FCB, Status, Irp, 0, NULL, TRUE );
}

View file

@ -0,0 +1,201 @@
/* $Id: connect.c,v 1.2 2004/07/18 22:49:17 arty Exp $
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel
* FILE: drivers/net/afd/afd/connect.c
* PURPOSE: Ancillary functions driver
* PROGRAMMER: Art Yerkes (ayerkes@speakeasy.net)
* UPDATE HISTORY:
* 20040708 Created
*/
#include "afd.h"
#include "tdi_proto.h"
#include "tdiconn.h"
#include "debug.h"
NTSTATUS WarmSocketForConnection( PAFD_FCB FCB ) {
NTSTATUS Status = TdiOpenConnectionEndpointFile
( &FCB->TdiDeviceName,
&FCB->Connection.Handle,
&FCB->Connection.Object );
if( NT_SUCCESS(Status) ) {
Status = TdiAssociateAddressFile
( FCB->AddressFile.Handle,
FCB->Connection.Object );
}
if( !NT_SUCCESS(Status) ) {
TdiCloseDevice( &FCB->Connection.Handle,
FCB->Connection.Object );
RtlZeroMemory( &FCB->Connection, sizeof(FCB->Connection) );
}
return Status;
}
NTSTATUS DDKAPI StreamSocketConnectComplete
( PDEVICE_OBJECT DeviceObject,
PIRP Irp,
PVOID Context ) {
NTSTATUS Status = Irp->IoStatus.Status;
PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation(Irp);
PAFD_FCB FCB = (PAFD_FCB)Context;
PLIST_ENTRY NextIrpEntry;
PIRP NextIrp;
AFD_DbgPrint(MID_TRACE,("Called: FCB %x, FO %x\n",
Context, FCB->FileObject));
/* Check the result of the connect operation */
/* Since the previous does not return until we come through here, we do
* not need to relock. */
/* if( !SocketAcquireStateLock( FCB ) ) return LostSocket( Irp ); */
AFD_DbgPrint(MID_TRACE,("Irp->IoStatus.Status = %x\n",
Irp->IoStatus.Status));
if( NT_SUCCESS(Irp->IoStatus.Status) ) {
FCB->PollState |= AFD_EVENT_CONNECT;
FCB->State = SOCKET_STATE_CONNECTED;
AFD_DbgPrint(MID_TRACE,("Going to connected state %d\n", FCB->State));
PollReeval( FCB->DeviceExt, FCB->FileObject );
} else {
FCB->PollState |= AFD_EVENT_CONNECT_FAIL;
AFD_DbgPrint(MID_TRACE,("Going to bound state\n"));
FCB->State = SOCKET_STATE_BOUND;
PollReeval( FCB->DeviceExt, FCB->FileObject );
}
/* Succeed pending irps on the FUNCTION_CONNECT list */
while( !IsListEmpty( &FCB->PendingIrpList[FUNCTION_CONNECT] ) ) {
NextIrpEntry = RemoveHeadList(&FCB->PendingIrpList[FUNCTION_CONNECT]);
NextIrp = CONTAINING_RECORD(NextIrpEntry, IRP, Tail.Overlay.ListEntry);
AFD_DbgPrint(MID_TRACE,("Completing connect %x\n", NextIrp));
NextIrp->IoStatus.Status = Status;
NextIrp->IoStatus.Information = 0;
IoCompleteRequest( NextIrp, IO_NETWORK_INCREMENT );
}
if( NT_SUCCESS(Status) ) {
/* Allocate the receive area and start receiving */
FCB->Recv.Window =
ExAllocatePool( NonPagedPool, FCB->Recv.Size );
FCB->Send.Window =
ExAllocatePool( NonPagedPool, FCB->Send.Size );
if( FCB->Recv.Window ) {
Status = TdiReceive( &FCB->ReceiveIrp.InFlightRequest,
IrpSp->FileObject,
TDI_RECEIVE_NORMAL,
FCB->Recv.Window,
FCB->Recv.Size,
&FCB->ReceiveIrp.Iosb,
ReceiveComplete,
FCB );
}
if( FCB->Send.Window &&
!IsListEmpty( &FCB->PendingIrpList[FUNCTION_SEND] ) ) {
NextIrpEntry = RemoveHeadList(&FCB->PendingIrpList[FUNCTION_SEND]);
NextIrp = CONTAINING_RECORD(NextIrpEntry, IRP,
Tail.Overlay.ListEntry);
AFD_DbgPrint(MID_TRACE,("Launching send request %x\n", NextIrp));
Status = AfdConnectedSocketWriteData
( DeviceObject,
NextIrp,
IoGetCurrentIrpStackLocation( NextIrp ),
FALSE );
}
if( Status == STATUS_PENDING )
Status = STATUS_SUCCESS;
}
/* SocketStateUnlock( FCB ); */
AFD_DbgPrint(MID_TRACE,("Returning %x\n", Status));
return Status;
}
/* Return the socket object for ths request only if it is a connected or
stream type. */
NTSTATUS STDCALL
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 %x\n", FCB));
if( !SocketAcquireStateLock( FCB ) ) return LostSocket( Irp );
if( !(ConnectReq = LockRequest( Irp, IrpSp )) )
return UnlockAndMaybeComplete( FCB, STATUS_NO_MEMORY, Irp,
0, NULL, TRUE );
AFD_DbgPrint(MID_TRACE,("Connect request:\n"));
OskitDumpBuffer
( (PCHAR)ConnectReq,
IrpSp->Parameters.DeviceIoControl.InputBufferLength );
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: {
FCB->LocalAddress =
TaCopyTransportAddress( &ConnectReq->RemoteAddress );
if( FCB->LocalAddress ) {
RtlZeroMemory( FCB->LocalAddress,
TaLengthOfTransportAddress
( &ConnectReq->RemoteAddress ) );
FCB->LocalAddress->TAAddressCount = 1;
FCB->LocalAddress->Address[0].AddressType =
ConnectReq->RemoteAddress.Address[0].AddressType;
FCB->LocalAddress->Address[0].AddressLength =
ConnectReq->RemoteAddress.Address[0].AddressLength;
Status = WarmSocketForBind( FCB );
if( NT_SUCCESS(Status) )
FCB->State = SOCKET_STATE_BOUND;
else
return UnlockAndMaybeComplete( FCB, Status, Irp, 0, NULL,
TRUE );
} else
return UnlockAndMaybeComplete
( FCB, STATUS_NO_MEMORY, Irp, 0, NULL, TRUE );
} /* Drop through to SOCKET_STATE_BOUND */
case SOCKET_STATE_BOUND:
FCB->RemoteAddress =
TaCopyTransportAddress( &ConnectReq->RemoteAddress );
Status = WarmSocketForConnection( FCB );
FCB->State = SOCKET_STATE_CONNECTING;
if( NT_SUCCESS(Status) ) {
Status = TdiConnect( &FCB->PendingTdiIrp,
FCB->Connection.Object,
FCB->RemoteAddress,
StreamSocketConnectComplete,
FCB );
}
break;
default:
AFD_DbgPrint(MID_TRACE,("Inappropriate socket state %d for connect\n",
FCB->State));
break;
}
return UnlockAndMaybeComplete( FCB, Status, Irp, 0, NULL, TRUE );
}

View file

@ -0,0 +1,68 @@
/* $Id: context.c,v 1.2 2004/07/18 22:49:17 arty Exp $
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel
* FILE: drivers/net/afd/afd/context.c
* PURPOSE: Ancillary functions driver
* PROGRAMMER: Art Yerkes (ayerkes@speakeasy.net)
* UPDATE HISTORY:
* 20040708 Created
*/
#include "afd.h"
#include "tdi_proto.h"
#include "tdiconn.h"
#include "debug.h"
NTSTATUS STDCALL
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;
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, 0, NULL, FALSE );
}
NTSTATUS STDCALL
AfdSetContext( PDEVICE_OBJECT DeviceObject, PIRP Irp,
PIO_STACK_LOCATION IrpSp ) {
NTSTATUS Status = STATUS_NO_MEMORY;
PFILE_OBJECT FileObject = IrpSp->FileObject;
PAFD_FCB FCB = FileObject->FsContext;
if( !SocketAcquireStateLock( FCB ) ) return LostSocket( Irp );
if( FCB->ContextSize <
IrpSp->Parameters.DeviceIoControl.InputBufferLength ) {
if( FCB->Context )
ExFreePool( FCB->Context );
FCB->Context =
ExAllocatePool
( PagedPool,
IrpSp->Parameters.DeviceIoControl.InputBufferLength );
}
if( FCB->Context ) {
Status = STATUS_SUCCESS;
RtlCopyMemory( FCB->Context,
IrpSp->Parameters.DeviceIoControl.Type3InputBuffer,
IrpSp->Parameters.DeviceIoControl.InputBufferLength );
}
AFD_DbgPrint(MID_TRACE,("Returning %x\n", Status));
return UnlockAndMaybeComplete( FCB, Status, Irp, 0, NULL, FALSE );
}

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,52 @@
/* $Id: info.c,v 1.2 2004/07/18 22:49:17 arty Exp $
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel
* FILE: drivers/net/afd/afd/info.c
* PURPOSE: Ancillary functions driver
* PROGRAMMER: Art Yerkes (ayerkes@speakeasy.net)
* UPDATE HISTORY:
* 20040708 Created
*/
#include "afd.h"
#include "tdi_proto.h"
#include "tdiconn.h"
#include "debug.h"
NTSTATUS STDCALL
AfdGetInfo( PDEVICE_OBJECT DeviceObject, PIRP Irp,
PIO_STACK_LOCATION IrpSp ) {
NTSTATUS Status = STATUS_SUCCESS;
PAFD_INFO InfoReq = IrpSp->Parameters.DeviceIoControl.Type3InputBuffer;
PFILE_OBJECT FileObject = IrpSp->FileObject;
PAFD_FCB FCB = FileObject->FsContext;
AFD_DbgPrint(MID_TRACE,("Called %x %x\n", InfoReq,
InfoReq ? InfoReq->InformationClass : 0));
if( !SocketAcquireStateLock( FCB ) ) return LostSocket( Irp );
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 %d\n", FCB->Send.Size));
break;
case AFD_INFO_GROUP_ID_TYPE:
InfoReq->Information.Ulong = 0; /* What is group id */
break;
default:
AFD_DbgPrint(MID_TRACE,("Unknown info id %x\n",
InfoReq->InformationClass));
Status = STATUS_INVALID_PARAMETER;
break;
}
AFD_DbgPrint(MID_TRACE,("Returning %x\n", Status));
return UnlockAndMaybeComplete( FCB, Status, Irp, 0, NULL, FALSE );
}

View file

@ -0,0 +1,61 @@
/* $Id: listen.c,v 1.2 2004/07/18 22:49:17 arty Exp $
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel
* FILE: drivers/net/afd/afd/listen.c
* PURPOSE: Ancillary functions driver
* PROGRAMMER: Art Yerkes (ayerkes@speakeasy.net)
* UPDATE HISTORY:
* 20040708 Created
*/
#include "afd.h"
#include "tdi_proto.h"
#include "tdiconn.h"
#include "debug.h"
NTSTATUS DDKAPI ListenComplete
( PDEVICE_OBJECT DeviceObject,
PIRP Irp,
PVOID Context ) {
PAFD_FCB FCB = (PAFD_FCB)Context;
AFD_DbgPrint(MID_TRACE,("Completing listen request.\n"));
AFD_DbgPrint(MID_TRACE,("IoStatus was %x\n", FCB->ListenIrp.Iosb.Status));
AFD_DbgPrint(MID_TRACE,("Doing nothing as yet.\n"));
return STATUS_SUCCESS;
}
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;
AFD_DbgPrint(MID_TRACE,("Called\n"));
if( !SocketAcquireStateLock( FCB ) ) return LostSocket( Irp );
if( !(ListenReq = LockRequest( Irp, IrpSp )) )
return UnlockAndMaybeComplete( FCB, STATUS_NO_MEMORY, Irp,
0, NULL, FALSE );
if( FCB->State != SOCKET_STATE_BOUND ) {
Status = STATUS_UNSUCCESSFUL;
AFD_DbgPrint(MID_TRACE,("Could not listen an unbound socket\n"));
return UnlockAndMaybeComplete( FCB, Status, Irp, 0, NULL, TRUE );
}
FCB->DelayedAccept = ListenReq->UseDelayedAcceptance;
Status = WarmSocketForConnection( FCB );
FCB->State = SOCKET_STATE_LISTENING;
Status = TdiListen( &FCB->ListenIrp.InFlightRequest,
FCB->Connection.Object,
&FCB->ListenIrp.ConnectionInfo,
&FCB->ListenIrp.Iosb,
ListenComplete,
FCB );
AFD_DbgPrint(MID_TRACE,("Returning %x\n", Status));
return UnlockAndMaybeComplete( FCB, Status, Irp, 0, NULL, TRUE );
}

View file

@ -0,0 +1,212 @@
/* $Id: lock.c,v 1.2 2004/07/18 22:49:17 arty Exp $
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel
* FILE: drivers/net/afd/afd/lock.c
* PURPOSE: Ancillary functions driver
* PROGRAMMER: Art Yerkes (ayerkes@speakeasy.net)
* UPDATE HISTORY:
* 20040708 Created
*/
#include "afd.h"
#include "tdi_proto.h"
#include "tdiconn.h"
#include "debug.h"
/* Lock a method_neither request so it'll be available from DISPATCH_LEVEL */
PVOID LockRequest( PIRP Irp, PIO_STACK_LOCATION IrpSp ) {
Irp->MdlAddress =
IoAllocateMdl( IrpSp->Parameters.DeviceIoControl.Type3InputBuffer,
IrpSp->Parameters.DeviceIoControl.InputBufferLength,
FALSE,
FALSE,
NULL );
if( Irp->MdlAddress ) {
MmProbeAndLockPages( Irp->MdlAddress, KernelMode, IoModifyAccess );
IrpSp->Parameters.DeviceIoControl.Type3InputBuffer =
MmMapLockedPages( Irp->MdlAddress, KernelMode );
return IrpSp->Parameters.DeviceIoControl.Type3InputBuffer;
} else return NULL;
}
VOID UnlockRequest( PIRP Irp, PIO_STACK_LOCATION IrpSp ) {
MmUnmapLockedPages( IrpSp->Parameters.DeviceIoControl.Type3InputBuffer,
Irp->MdlAddress );
MmUnlockPages( Irp->MdlAddress );
IoFreeMdl( Irp->MdlAddress );
Irp->MdlAddress = NULL;
}
PAFD_WSABUF LockBuffers( PAFD_WSABUF Buf, UINT Count, BOOLEAN Write ) {
UINT i;
/* Copy the buffer array so we don't lose it */
UINT Size = sizeof(AFD_WSABUF) * Count;
PAFD_WSABUF NewBuf = ExAllocatePool( PagedPool, Size * 2 );
PMDL NewMdl;
AFD_DbgPrint(MID_TRACE,("Called\n"));
if( NewBuf ) {
PAFD_MAPBUF MapBuf = (PAFD_MAPBUF)(NewBuf + Count);
RtlCopyMemory( NewBuf, Buf, Size );
for( i = 0; i < Count; i++ ) {
AFD_DbgPrint(MID_TRACE,("Locking buffer %d (%x:%d)\n",
i, NewBuf[i].buf, NewBuf[i].len));
if( NewBuf[i].len ) {
NewMdl = IoAllocateMdl( NewBuf[i].buf,
NewBuf[i].len,
FALSE,
FALSE,
NULL );
} else {
MapBuf[i].Mdl = NULL;
continue;
}
AFD_DbgPrint(MID_TRACE,("NewMdl @ %x\n", NewMdl));
MapBuf[i].Mdl = NewMdl;
if( MapBuf[i].Mdl ) {
AFD_DbgPrint(MID_TRACE,("Probe and lock pages\n"));
MmProbeAndLockPages( MapBuf[i].Mdl, KernelMode,
Write ? IoModifyAccess : IoReadAccess );
AFD_DbgPrint(MID_TRACE,("MmProbeAndLock finished\n"));
}
}
}
AFD_DbgPrint(MID_TRACE,("Leaving %x\n", NewBuf));
return NewBuf;
}
VOID UnlockBuffers( PAFD_WSABUF Buf, UINT Count ) {
PAFD_MAPBUF Map = (PAFD_MAPBUF)(Buf + Count);
UINT i;
for( i = 0; i < Count; i++ ) {
if( Map[i].Mdl ) {
MmUnlockPages( Map[i].Mdl );
IoFreeMdl( Map[i].Mdl );
}
}
ExFreePool( Buf );
}
/* Returns transitioned state or SOCKET_STATE_INVALID_TRANSITION */
UINT SocketAcquireStateLock( PAFD_FCB FCB ) {
NTSTATUS Status = STATUS_SUCCESS;
PVOID CurrentThread = KeGetCurrentThread();
AFD_DbgPrint(MAX_TRACE,("Called on %x, attempting to lock\n", FCB));
/* Wait for the previous user to unlock the FCB state. There might be
* multiple waiters waiting to change the state. We need to check each
* time we get the event whether somebody still has the state locked */
if( !FCB ) return FALSE;
if( CurrentThread == FCB->CurrentThread ) {
FCB->LockCount++;
AFD_DbgPrint(MID_TRACE,
("Same thread, lock count %d\n", FCB->LockCount));
return TRUE;
} else {
AFD_DbgPrint(MID_TRACE,
("Thread %x opposes lock thread %x\n",
CurrentThread, FCB->CurrentThread));
}
if( KeGetCurrentIrql() == PASSIVE_LEVEL ) {
ExAcquireFastMutex( &FCB->Mutex );
while( FCB->Locked ) {
AFD_DbgPrint
(MID_TRACE,("FCB %x is locked, waiting for notification\n",
FCB));
ExReleaseFastMutex( &FCB->Mutex );
Status = KeWaitForSingleObject( &FCB->StateLockedEvent,
UserRequest,
KernelMode,
FALSE,
NULL );
ExAcquireFastMutex( &FCB->Mutex );
if( Status == STATUS_SUCCESS ) break;
}
FCB->Locked = TRUE;
FCB->CurrentThread = CurrentThread;
FCB->LockCount++;
ExReleaseFastMutex( &FCB->Mutex );
} else {
KeAcquireSpinLock( &FCB->SpinLock, &FCB->OldIrql );
FCB->Locked = TRUE;
FCB->CurrentThread = CurrentThread;
FCB->LockCount++;
}
AFD_DbgPrint(MAX_TRACE,("Got lock (%d).\n", FCB->LockCount));
return TRUE;
}
VOID SocketStateUnlock( PAFD_FCB FCB ) {
ASSERT(FCB->LockCount > 0);
FCB->LockCount--;
if( !FCB->LockCount ) {
FCB->CurrentThread = NULL;
if( KeGetCurrentIrql() == PASSIVE_LEVEL ) {
ExAcquireFastMutex( &FCB->Mutex );
FCB->Locked = FALSE;
ExReleaseFastMutex( &FCB->Mutex );
} else {
FCB->Locked = FALSE;
KeReleaseSpinLock( &FCB->SpinLock, FCB->OldIrql );
}
AFD_DbgPrint(MAX_TRACE,("Unlocked.\n"));
KePulseEvent( &FCB->StateLockedEvent, IO_NETWORK_INCREMENT, FALSE );
} else {
AFD_DbgPrint(MID_TRACE,("Lock count %d\n", FCB->LockCount));
}
}
NTSTATUS DDKAPI UnlockAndMaybeComplete
( PAFD_FCB FCB, NTSTATUS Status, PIRP Irp,
UINT Information,
PIO_COMPLETION_ROUTINE Completion,
BOOL ShouldUnlock ) {
SocketStateUnlock( FCB );
if( Status == STATUS_PENDING ) {
IoMarkIrpPending( Irp );
} else {
Irp->IoStatus.Status = Status;
Irp->IoStatus.Information = Information;
if( Completion )
Completion( FCB->DeviceExt->DeviceObject, Irp, FCB );
if( ShouldUnlock )
UnlockRequest( Irp, IoGetCurrentIrpStackLocation( Irp ) );
IoCompleteRequest( Irp, IO_NETWORK_INCREMENT );
}
return Status;
}
NTSTATUS LostSocket( PIRP Irp, BOOL ShouldUnlockIrp ) {
NTSTATUS Status = STATUS_INVALID_PARAMETER;
AFD_DbgPrint(MIN_TRACE,("Called.\n"));
Irp->IoStatus.Information = 0;
Irp->IoStatus.Status = Status;
if( ShouldUnlockIrp )
UnlockRequest( Irp, IoGetCurrentIrpStackLocation( Irp ) );
IoCompleteRequest( Irp, IO_NO_INCREMENT );
return Status;
}
NTSTATUS LeaveIrpUntilLater( PAFD_FCB FCB, PIRP Irp, UINT Function ) {
InsertTailList( &FCB->PendingIrpList[Function],
&Irp->Tail.Overlay.ListEntry );
return UnlockAndMaybeComplete( FCB, STATUS_PENDING, Irp, 0, NULL, FALSE );
}

View file

@ -0,0 +1,344 @@
/* $Id: main.c,v 1.2 2004/07/18 22:49:17 arty Exp $
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel
* FILE: drivers/net/afd/afd/main.c
* PURPOSE: Ancillary functions driver
* PROGRAMMER: Art Yerkes (ayerkes@speakeasy.net)
* UPDATE HISTORY:
* 20040630 Created
*
* Suggestions: Uniform naming (AfdXxx)
*/
/* INCLUDES */
#include "afd.h"
#include "tdi_proto.h"
#include "tdiconn.h"
#include "debug.h"
#ifdef DBG
extern NTSTATUS DDKAPI MmCopyFromCaller( PVOID Dst, PVOID Src, UINT Size );
/* See debug.h for debug/trace constants */
DWORD DebugTraceLevel = DEBUG_ULTRA;
#endif /* DBG */
void OskitDumpBuffer( PCHAR Data, UINT Len ) {
unsigned int i;
for( i = 0; i < Len; i++ ) {
if( i && !(i & 0xf) ) DbgPrint( "\n" );
if( !(i & 0xf) ) DbgPrint( "%08x: ", (UINT)(Data + i) );
DbgPrint( " %02x", Data[i] & 0xff );
}
DbgPrint("\n");
}
/* FUNCTIONS */
NTSTATUS STDCALL
AfdCreateSocket(PDEVICE_OBJECT DeviceObject, PIRP Irp,
PIO_STACK_LOCATION IrpSp) {
PAFD_FCB FCB;
PFILE_OBJECT FileObject;
PAFD_DEVICE_EXTENSION DeviceExt;
PFILE_FULL_EA_INFORMATION EaInfo;
PAFD_CREATE_PACKET ConnectInfo;
ULONG EaLength;
PWCHAR EaInfoValue;
UINT Disposition, i;
AFD_DbgPrint(MID_TRACE,
("AfdCreate(DeviceObject %p Irp %p)\n", DeviceObject, Irp));
DeviceExt = DeviceObject->DeviceExtension;
FileObject = IrpSp->FileObject;
Disposition = (IrpSp->Parameters.Create.Options >> 24) & 0xff;
Irp->IoStatus.Information = 0;
EaInfo = Irp->AssociatedIrp.SystemBuffer;
ConnectInfo = (PAFD_CREATE_PACKET)(EaInfo->EaName + EaInfo->EaNameLength + 1);
EaInfoValue = (PWCHAR)(((PCHAR)ConnectInfo) + sizeof(AFD_CREATE_PACKET));
if(!EaInfo) {
AFD_DbgPrint(MIN_TRACE, ("No EA Info in IRP.\n"));
Irp->IoStatus.Status = STATUS_INVALID_PARAMETER;
IoCompleteRequest( Irp, IO_NO_INCREMENT );
return STATUS_INVALID_PARAMETER;
}
EaLength = sizeof(FILE_FULL_EA_INFORMATION) +
EaInfo->EaNameLength +
EaInfo->EaValueLength;
AFD_DbgPrint(MID_TRACE,("EaInfo: %x, EaInfoValue: %x\n",
EaInfo, EaInfoValue));
AFD_DbgPrint(MID_TRACE,("About to allocate the new FCB\n"));
FCB = ExAllocatePool(NonPagedPool, sizeof(PAFD_FCB));
if( FCB == NULL ) {
Irp->IoStatus.Status = STATUS_NO_MEMORY;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return STATUS_NO_MEMORY;
}
AFD_DbgPrint(MID_TRACE,("Initializing the new FCB @ %x (FileObject %x)\n", FCB, FileObject));
RtlZeroMemory( FCB, sizeof( *FCB ) );
FCB->Flags = ConnectInfo->EndpointFlags;
FCB->State = SOCKET_STATE_CREATED;
FCB->FileObject = FileObject;
FCB->DeviceExt = DeviceExt;
FCB->Recv.Size = DEFAULT_RECEIVE_WINDOW_SIZE;
FCB->Send.Size = DEFAULT_SEND_WINDOW_SIZE;
KeInitializeSpinLock( &FCB->SpinLock );
ExInitializeFastMutex( &FCB->Mutex );
KeInitializeEvent( &FCB->StateLockedEvent, NotificationEvent, FALSE );
for( i = 0; i < MAX_FUNCTIONS; i++ ) {
InitializeListHead( &FCB->PendingIrpList[i] );
}
AFD_DbgPrint(MID_TRACE,("%x: Checking command channel\n", FCB));
FCB->TdiDeviceName.Length = ConnectInfo->SizeOfTransportName;
FCB->TdiDeviceName.MaximumLength = FCB->TdiDeviceName.Length;
FCB->TdiDeviceName.Buffer =
ExAllocatePool( NonPagedPool, FCB->TdiDeviceName.Length );
RtlCopyMemory( FCB->TdiDeviceName.Buffer,
ConnectInfo->TransportName,
FCB->TdiDeviceName.Length );
if( !FCB->TdiDeviceName.Buffer ) {
ExFreePool(FCB);
AFD_DbgPrint(MID_TRACE,("Could not copy target string\n"));
Irp->IoStatus.Status = STATUS_NO_MEMORY;
IoCompleteRequest( Irp, IO_NETWORK_INCREMENT );
return STATUS_NO_MEMORY;
}
AFD_DbgPrint(MID_TRACE,("Success: %s %wZ\n",
EaInfo->EaName, &FCB->TdiDeviceName));
FileObject->FsContext = FCB;
Irp->IoStatus.Status = STATUS_SUCCESS;
IoCompleteRequest( Irp, IO_NETWORK_INCREMENT );
return STATUS_SUCCESS;
}
NTSTATUS STDCALL
AfdCloseSocket(PDEVICE_OBJECT DeviceObject, PIRP Irp,
PIO_STACK_LOCATION IrpSp)
{
PFILE_OBJECT FileObject = IrpSp->FileObject;
PAFD_FCB FCB = FileObject->FsContext;
UINT i;
PAFD_IN_FLIGHT_REQUEST InFlightRequest[IN_FLIGHT_REQUESTS];
if( !SocketAcquireStateLock( FCB ) ) return LostSocket( Irp, FALSE );
InFlightRequest[0] = &FCB->ListenIrp;
InFlightRequest[1] = &FCB->ReceiveIrp;
InFlightRequest[2] = &FCB->SendIrp;
AFD_DbgPrint(MID_TRACE,
("AfdClose(DeviceObject %p Irp %p)\n", DeviceObject, Irp));
AFD_DbgPrint(MID_TRACE,("FCB %x\n", FCB));
FileObject->FsContext = NULL;
FCB->PollState |= AFD_EVENT_CLOSE;
PollReeval( FCB->DeviceExt, FCB->FileObject );
/* After PoolReeval, this FCB should not be involved in any outstanding
* poll requests */
/* Cancel our pending requests */
for( i = 0; i < IN_FLIGHT_REQUESTS; i++ ) {
NTSTATUS Status = STATUS_NO_SUCH_FILE;
if( InFlightRequest[i]->InFlightRequest ) {
InFlightRequest[i]->InFlightRequest->IoStatus.Status = Status;
InFlightRequest[i]->InFlightRequest->IoStatus.Information = 0;
IoCancelIrp( InFlightRequest[i]->InFlightRequest );
}
}
SocketStateUnlock( FCB );
if( FCB->Recv.Window )
ExFreePool( FCB->Recv.Window );
if( FCB->Send.Window )
ExFreePool( FCB->Send.Window );
if( FCB->AddressFrom )
ExFreePool( FCB->AddressFrom );
if( FCB->LocalAddress )
ExFreePool( FCB->LocalAddress );
ExFreePool(FCB->TdiDeviceName.Buffer);
ExFreePool(FCB);
Irp->IoStatus.Status = STATUS_SUCCESS;
Irp->IoStatus.Information = 0;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
AFD_DbgPrint(MID_TRACE, ("Returning success.\n"));
return STATUS_SUCCESS;
}
NTSTATUS STDCALL
AfdDispatch(PDEVICE_OBJECT DeviceObject, PIRP Irp)
{
PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation(Irp);
NTSTATUS Status = STATUS_SUCCESS;
PFILE_OBJECT FileObject = IrpSp->FileObject;
AFD_DbgPrint(MID_TRACE,("AfdDispatch: %d\n", IrpSp->MajorFunction));
if( IrpSp->MajorFunction != IRP_MJ_CREATE) {
AFD_DbgPrint(MID_TRACE,("FO %x, IrpSp->FO %x\n",
FileObject, IrpSp->FileObject));
ASSERT(FileObject == IrpSp->FileObject);
}
switch(IrpSp->MajorFunction)
{
/* opening and closing handles to the device */
case IRP_MJ_CREATE:
/* Mostly borrowed from the named pipe file system */
return AfdCreateSocket(DeviceObject, Irp, IrpSp);
case IRP_MJ_CLOSE:
/* Ditto the borrowing */
return AfdCloseSocket(DeviceObject, Irp, IrpSp);
/* write data */
case IRP_MJ_WRITE:
return AfdConnectedSocketWriteData( DeviceObject, Irp, IrpSp, TRUE );
/* read data */
case IRP_MJ_READ:
return AfdConnectedSocketReadData( DeviceObject, Irp, IrpSp, TRUE );
case IRP_MJ_DEVICE_CONTROL:
{
switch( IrpSp->Parameters.DeviceIoControl.IoControlCode ) {
case IOCTL_AFD_BIND:
return AfdBindSocket( DeviceObject, Irp, IrpSp );
case IOCTL_AFD_CONNECT:
return AfdStreamSocketConnect( DeviceObject, Irp, IrpSp );
case IOCTL_AFD_START_LISTEN:
return AfdListenSocket( DeviceObject, Irp, IrpSp );
case IOCTL_AFD_RECV:
return AfdConnectedSocketReadData( DeviceObject, Irp, IrpSp,
FALSE );
case IOCTL_AFD_SELECT:
return AfdSelect( DeviceObject, Irp, IrpSp );
case IOCTL_AFD_RECV_DATAGRAM:
return AfdPacketSocketReadData( DeviceObject, Irp, IrpSp );
case IOCTL_AFD_SEND:
return AfdConnectedSocketWriteData( DeviceObject, Irp, IrpSp,
FALSE );
case IOCTL_AFD_SEND_DATAGRAM:
return AfdPacketSocketWriteData( DeviceObject, Irp, IrpSp );
case IOCTL_AFD_GET_INFO:
return AfdGetInfo( DeviceObject, Irp, IrpSp );
case IOCTL_AFD_GET_CONTEXT:
return AfdGetContext( DeviceObject, Irp, IrpSp );
case IOCTL_AFD_SET_CONTEXT:
return AfdSetContext( DeviceObject, Irp, IrpSp );
default:
Status = STATUS_NOT_IMPLEMENTED;
Irp->IoStatus.Information = 0;
AFD_DbgPrint(MIN_TRACE, ("Unknown IOCTL (0x%x)\n",
IrpSp->Parameters.DeviceIoControl.
IoControlCode));
break;
}
break;
}
/* unsupported operations */
default:
{
Status = STATUS_NOT_IMPLEMENTED;
AFD_DbgPrint(MIN_TRACE,
("Irp: Unknown Major code was %x\n",
IrpSp->MajorFunction));
break;
}
}
AFD_DbgPrint(MID_TRACE, ("Returning %x\n", Status));
Irp->IoStatus.Status = Status;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return (Status);
}
VOID STDCALL
AfdUnload(PDRIVER_OBJECT DriverObject)
{
}
NTSTATUS STDCALL
DriverEntry(PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPath)
{
PDEVICE_OBJECT DeviceObject;
UNICODE_STRING wstrDeviceName;
PAFD_DEVICE_EXTENSION DeviceExt;
NTSTATUS Status;
/* register driver routines */
DriverObject->MajorFunction[IRP_MJ_CLOSE] = AfdDispatch;
DriverObject->MajorFunction[IRP_MJ_CREATE] = AfdDispatch;
DriverObject->MajorFunction[IRP_MJ_WRITE] = AfdDispatch;
DriverObject->MajorFunction[IRP_MJ_READ] = AfdDispatch;
DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = AfdDispatch;
DriverObject->DriverUnload = AfdUnload;
/* create afd device */
RtlRosInitUnicodeStringFromLiteral(&wstrDeviceName, L"\\Device\\Afd");
Status = IoCreateDevice
( DriverObject,
sizeof(AFD_DEVICE_EXTENSION),
&wstrDeviceName,
FILE_DEVICE_NAMED_PIPE,
0,
FALSE,
&DeviceObject );
/* failure */
if(!NT_SUCCESS(Status))
{
return (Status);
}
DeviceExt = DeviceObject->DeviceExtension;
KeInitializeSpinLock( &DeviceExt->Lock );
InitializeListHead( &DeviceExt->Polls );
AFD_DbgPrint(MID_TRACE,("Device created: object %x ext %x\n",
DeviceObject, DeviceExt));
return (Status);
}
/* EOF */

View file

@ -1,285 +0,0 @@
/*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS Ancillary Function Driver
* FILE: afd/opnclose.c
* PURPOSE: File object creation and destruction
* PROGRAMMERS: Casper S. Hornstrup (chorns@users.sourceforge.net)
* REVISIONS:
* CSH 01/09-2000 Created
*/
#include <afd.h>
PAFDFCB AfdInitializeFCB(
PDEVICE_EXTENSION DeviceExt,
PFILE_OBJECT FileObject OPTIONAL)
/*
* FUNCTION: Allocates and initializes a File Control Block structure
*/
{
PAFDFCB NewFCB;
NewFCB = ExAllocatePool(NonPagedPool, sizeof(AFDFCB));
if (!NewFCB)
return NULL;
RtlZeroMemory(NewFCB, sizeof(AFDFCB));
ExInitializeResourceLite(&NewFCB->NTRequiredFCB.MainResource);
ExInitializeResourceLite(&NewFCB->NTRequiredFCB.PagingIoResource);
NewFCB->DeviceExt = DeviceExt;
NewFCB->ReferenceCount = 1;
NewFCB->OpenHandleCount = 1;
NewFCB->TdiAddressObjectHandle = INVALID_HANDLE_VALUE;
NewFCB->TdiConnectionObjectHandle = INVALID_HANDLE_VALUE;
InitializeListHead(&NewFCB->CCBListHead);
InsertTailList(&DeviceExt->FCBListHead, &NewFCB->ListEntry);
InitializeListHead(&NewFCB->ReceiveQueue);
KeInitializeSpinLock(&NewFCB->ReceiveQueueLock);
InitializeListHead(&NewFCB->ReadRequestQueue);
InitializeListHead(&NewFCB->ListenRequestQueue);
if (FileObject)
FileObject->FsContext = (PVOID)NewFCB;
AFD_DbgPrint(MAX_TRACE, ("FCB created for file object (0x%X) at (0x%X).\n", FileObject, NewFCB));
return NewFCB;
}
PAFDCCB AfdInitializeCCB(
PAFDFCB FCB,
PFILE_OBJECT FileObject)
/*
* FUNCTION: Allocates and initializes a Context Control Block structure
*/
{
PAFDCCB NewCCB;
NewCCB = ExAllocatePool(NonPagedPool, sizeof(AFDCCB));
if (!NewCCB)
return NULL;
RtlZeroMemory(NewCCB, sizeof(AFDCCB));
NewCCB->FileObject = FileObject;
FileObject->FsContext2 = (PVOID)NewCCB;
InsertTailList(&FCB->CCBListHead, &NewCCB->ListEntry);
AFD_DbgPrint(MAX_TRACE, ("CCB created for file object (0x%X) at (0x%X).\n", FileObject, NewCCB));
return NewCCB;
}
NTSTATUS
STDCALL
AfdCreate(
PDEVICE_OBJECT DeviceObject,
PIRP Irp)
{
PAFD_SOCKET_INFORMATION SocketInfo;
PFILE_FULL_EA_INFORMATION EaInfo;
PDEVICE_EXTENSION DeviceExt;
NTSTATUS Status;
ULONG EaLength;
PAFDFCB FCB;
PAFDCCB CCB;
PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation(Irp);
PFILE_OBJECT FileObject = IrpSp->FileObject;
AFD_DbgPrint(MAX_TRACE, ("Called.\n"));
assert(DeviceObject);
DeviceExt = DeviceObject->DeviceExtension;
EaInfo = Irp->AssociatedIrp.SystemBuffer;
/* Parameter check */
if (!EaInfo) {
AFD_DbgPrint(MIN_TRACE, ("No EA information in IRP.\n"));
return STATUS_INVALID_PARAMETER;
}
SocketInfo = (PAFD_SOCKET_INFORMATION)(EaInfo->EaName + EaInfo->EaNameLength);
EaLength = sizeof(FILE_FULL_EA_INFORMATION) +
EaInfo->EaNameLength +
EaInfo->EaValueLength;
if (EaLength < sizeof(FILE_FULL_EA_INFORMATION) +
AFD_SOCKET_LENGTH + sizeof(AFD_SOCKET_INFORMATION)) {
AFD_DbgPrint(MIN_TRACE, ("EA information has invalid length.\n"));
return STATUS_INVALID_PARAMETER;
}
AFD_DbgPrint(MAX_TRACE, ("EaInfo at (0x%X) length is (%d).\n", EaInfo, EaLength));
/* FIXME: File/socket could already be open, do a search for it */
FCB = AfdInitializeFCB(DeviceExt, FileObject);
CCB = AfdInitializeCCB(FCB, FileObject);
if (CCB && FCB) {
FCB->CommandChannel = SocketInfo->CommandChannel;
if (!FCB->CommandChannel) {
FCB->AddressFamily = SocketInfo->AddressFamily;
FCB->SocketType = SocketInfo->SocketType;
FCB->Protocol = SocketInfo->Protocol;
FCB->SocketName = SocketInfo->Name;
FCB->HelperContext = SocketInfo->HelperContext;
FCB->NotificationEvents = SocketInfo->NotificationEvents;
FCB->TdiDeviceName.Length = 0;
FCB->TdiDeviceName.MaximumLength = SocketInfo->TdiDeviceName.MaximumLength;
FCB->TdiDeviceName.Buffer = ExAllocatePool(
NonPagedPool,
FCB->TdiDeviceName.MaximumLength);
if (FCB->TdiDeviceName.Buffer) {
RtlCopyUnicodeString(&FCB->TdiDeviceName, &SocketInfo->TdiDeviceName);
AFD_DbgPrint(MAX_TRACE, ("TDI device name is (%wZ).\n", &FCB->TdiDeviceName));
/* Open address file now for raw sockets */
if (FCB->SocketType == SOCK_RAW) {
AFD_DbgPrint(MAX_TRACE, ("Opening raw socket.\n"));
Status = TdiOpenAddressFile(
&FCB->TdiDeviceName,
&SocketInfo->Name,
&FCB->TdiAddressObjectHandle,
&FCB->TdiAddressObject);
if (NT_SUCCESS(Status)) {
Status = AfdRegisterEventHandlers(FCB);
if (NT_SUCCESS(Status)) {
FCB->State = SOCKET_STATE_BOUND;
} else {
AFD_DbgPrint(MAX_TRACE, ("AfdRegisterEventHandlers() failed (0x%X).\n", Status));
}
} else {
AFD_DbgPrint(MAX_TRACE, ("TdiOpenAddressFile() failed (0x%X).\n", Status));
}
} else
Status = STATUS_SUCCESS;
} else
Status = STATUS_INSUFFICIENT_RESOURCES;
} else
Status = STATUS_SUCCESS;
} else
Status = STATUS_INSUFFICIENT_RESOURCES;
if (!NT_SUCCESS(Status)) {
/* FIXME: Cleanup */
AFD_DbgPrint(MAX_TRACE, ("FIXME: Cleanup.\n"));
}
Irp->IoStatus.Status = Status;
Irp->IoStatus.Information = 0;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
AFD_DbgPrint(MAX_TRACE, ("Leaving. Status (0x%X).\n", Status));
return Status;
}
VOID
AfdKillListenRequests(PAFDFCB FCB)
{
/* FIXME: Implement */
AFD_DbgPrint(MIN_TRACE, ("Unimplemented.\n"));
/*ExFreeToNPagedLookasideList(&ListenRequestLookasideList,
(PVOID)ListenRequest);*/
}
NTSTATUS
STDCALL
AfdClose(
PDEVICE_OBJECT DeviceObject,
PIRP Irp)
{
PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation(Irp);
PFILE_OBJECT FileObject = IrpSp->FileObject;
NTSTATUS Status;
PAFDFCB FCB;
PAFDCCB CCB;
AFD_DbgPrint(MAX_TRACE, ("Called.\n"));
assert(DeviceObject);
assert(FileObject);
FCB = FileObject->FsContext;
CCB = FileObject->FsContext2;
switch (IrpSp->MajorFunction) {
/* Close a file object */
case IRP_MJ_CLOSE:
FCB->ReferenceCount--;
if (FCB->ReferenceCount < 1) {
if (!FCB->CommandChannel) {
/* Kill outstanding listen requests */
AfdKillListenRequests(FCB);
/* Close TDI connection file object */
if (FCB->TdiConnectionObjectHandle != INVALID_HANDLE_VALUE) {
TdiCloseDevice(FCB->TdiConnectionObjectHandle, FCB->TdiConnectionObject);
FCB->TdiConnectionObjectHandle = INVALID_HANDLE_VALUE;
}
/* Close TDI address file object */
if (FCB->TdiAddressObjectHandle != INVALID_HANDLE_VALUE) {
AfdDeregisterEventHandlers(FCB);
TdiCloseDevice(FCB->TdiAddressObjectHandle, FCB->TdiAddressObject);
FCB->TdiAddressObjectHandle = INVALID_HANDLE_VALUE;
}
}
ExFreePool(FCB);
}
Status = STATUS_SUCCESS;
break;
/* Release resources bound to a file object */
case IRP_MJ_CLEANUP:
FCB->OpenHandleCount--;
Status = STATUS_SUCCESS;
ExFreePool(CCB);
break;
default:
Status = STATUS_INVALID_DEVICE_REQUEST;
}
// ExFreePool(CCB);
Irp->IoStatus.Status = Status;
Irp->IoStatus.Information = 0;
AFD_DbgPrint(MAX_TRACE, ("Completing IRP at (0x%X).\n", Irp));
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return Status;
}
/* EOF */

View file

@ -1,118 +0,0 @@
/*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS Ancillary Function Driver
* FILE: afd/rdwr.c
* PURPOSE: File object read/write functions
* PROGRAMMERS: Casper S. Hornstrup (chorns@users.sourceforge.net)
* REVISIONS:
* CSH 01/09-2000 Created
*/
#include <afd.h>
NTSTATUS AfdReadFile(
PDEVICE_EXTENSION DeviceExt,
PFILE_OBJECT FileObject,
PVOID Buffer,
ULONG Length,
ULONG Offset)
/*
* FUNCTION: Reads data from a file
*/
{
UNIMPLEMENTED
return STATUS_UNSUCCESSFUL;
}
NTSTATUS
STDCALL
AfdRead(
PDEVICE_OBJECT DeviceObject,
PIRP Irp)
{
#if 1
UNIMPLEMENTED
Irp->IoStatus.Status = STATUS_UNSUCCESSFUL;
Irp->IoStatus.Information = 0;
return STATUS_UNSUCCESSFUL;
#else
PDEVICE_EXTENSION DeviceExt = DeviceObject->DeviceExtension;
PIO_STACK_LOCATION IoSp = IoGetCurrentIrpStackLocation(Irp);
PFILE_OBJECT FileObject = IoSp->FileObject;
NTSTATUS Status;
ULONG Length;
PVOID Buffer;
ULONG Offset;
Length = IoSp->Parameters.Read.Length;
Buffer = MmGetSystemAddressForMdl(Irp->MdlAddress);
Offset = IoSp->Parameters.Read.ByteOffset.u.LowPart;
Status = AfdReadFile(DeviceExt, FileObject, Buffer, Length, Offset);
Irp->IoStatus.Status = Status;
Irp->IoStatus.Information = Length;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return Status;
#endif
}
NTSTATUS
STDCALL
AfdWrite(
PDEVICE_OBJECT DeviceObject,
PIRP Irp)
{
PIO_STACK_LOCATION IoSp = IoGetCurrentIrpStackLocation(Irp);
PFILE_OBJECT FileObject = IoSp->FileObject;
NTSTATUS Status = STATUS_NOT_IMPLEMENTED;
ULONG Length;
PVOID Buffer;
ULONG Offset;
PAFDFCB FCB;
PAFDCCB CCB;
FCB = FileObject->FsContext;
CCB = FileObject->FsContext2;
assert(FCB);
assert(CCB);
Length = IoSp->Parameters.Write.Length;
Buffer = MmGetSystemAddressForMdl(Irp->MdlAddress);
Offset = IoSp->Parameters.Write.ByteOffset.u.LowPart;
AFD_DbgPrint(MAX_TRACE, ("Called. Length (%d) Buffer (0x%X) Offset (0x%X)\n",
Length, Buffer, Offset));
assert((FCB->SocketType == SOCK_STREAM) || (FCB->SocketType == SOCK_DGRAM));
switch (FCB->SocketType) {
case SOCK_STREAM:
/* FIXME: Support connectionful communication */
break;
case SOCK_DGRAM:
/* Connectionless communication */
//Status = TdiSendDatagram(FCB->TdiAddressObject, WH2N(2000), 0x7F000001, Buffer, Length);
//if (!NT_SUCCESS(Status)) {
Length = 0;
//}
break;
case SOCK_RAW:
/* FIXME: Support raw communication */
break;
}
Irp->IoStatus.Status = Status;
Irp->IoStatus.Information = Length;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
AFD_DbgPrint(MAX_TRACE, ("Leaving.\n"));
return Status;
}
/* EOF */

View file

@ -0,0 +1,338 @@
/* $Id: read.c,v 1.2 2004/07/18 22:49:17 arty Exp $
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel
* FILE: drivers/net/afd/afd/read.c
* PURPOSE: Ancillary functions driver
* PROGRAMMER: Art Yerkes (ayerkes@speakeasy.net)
* UPDATE HISTORY:
* 20040708 Created
*
* Improve buffering code
*/
#include "afd.h"
#include "tdi_proto.h"
#include "tdiconn.h"
#include "debug.h"
NTSTATUS TryToSatisfyRecvRequestFromBuffer( PAFD_FCB FCB,
PAFD_RECV_INFO RecvReq,
PUINT TotalBytesCopied ) {
UINT i, BytesToCopy = 0,
BytesAvailable =
FCB->Recv.Content - FCB->Recv.BytesUsed;
*TotalBytesCopied = 0;
PAFD_MAPBUF Map;
if( !BytesAvailable ) return STATUS_PENDING;
Map = (PAFD_MAPBUF)(RecvReq->BufferArray + RecvReq->BufferCount);
AFD_DbgPrint(MID_TRACE,("Buffer Count: %d @ %x\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 %d: %x:%d\n",
i,
Map[i].BufferAddress,
BytesToCopy));
RtlCopyMemory( Map[i].BufferAddress,
FCB->Recv.Window + FCB->Recv.BytesUsed,
BytesToCopy );
MmUnmapLockedPages( Map[i].BufferAddress, Map[i].Mdl );
FCB->Recv.BytesUsed += BytesToCopy;
*TotalBytesCopied += BytesToCopy;
BytesAvailable -= BytesToCopy;
}
}
return STATUS_SUCCESS;
}
NTSTATUS DDKAPI ReceiveComplete
( PDEVICE_OBJECT DeviceObject,
PIRP Irp,
PVOID Context ) {
NTSTATUS Status = Irp->IoStatus.Status;
PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation(Irp);
PAFD_FCB FCB = (PAFD_FCB)Context;
PLIST_ENTRY NextIrpEntry;
PIRP NextIrp;
PIO_STACK_LOCATION NextIrpSp;
PAFD_RECV_INFO RecvReq;
UINT TotalBytesCopied = 0;
AFD_DbgPrint(MID_TRACE,("Called\n"));
if( !SocketAcquireStateLock( FCB ) ) return Status;
if( NT_SUCCESS(Irp->IoStatus.Status) ) {
/* Update the receive window */
FCB->Recv.Content = Irp->IoStatus.Information;
FCB->Recv.BytesUsed = 0;
/* Kick the user that receive would be possible now */
/* XXX Not implemented yet */
AFD_DbgPrint(MID_TRACE,("FCB %x Receive data waiting %d\n",
FCB, FCB->Recv.Content));
OskitDumpBuffer( FCB->Recv.Window, FCB->Recv.Content );
Status = STATUS_SUCCESS;
/* Try to clear some requests */
while( !IsListEmpty( &FCB->PendingIrpList[FUNCTION_RECV] ) &&
NT_SUCCESS(Status) ) {
NextIrpEntry =
RemoveHeadList(&FCB->PendingIrpList[FUNCTION_RECV]);
NextIrp =
CONTAINING_RECORD(NextIrpEntry, IRP, Tail.Overlay.ListEntry);
NextIrpSp = IoGetCurrentIrpStackLocation( NextIrp );
RecvReq = NextIrpSp->Parameters.DeviceIoControl.Type3InputBuffer;
AFD_DbgPrint(MID_TRACE,("RecvReq @ %x\n", RecvReq));
Status = TryToSatisfyRecvRequestFromBuffer
( FCB, RecvReq, &TotalBytesCopied );
if( Status == STATUS_PENDING ) {
AFD_DbgPrint(MID_TRACE,("Ran out of data for %x\n", NextIrp));
InsertHeadList(&FCB->PendingIrpList[FUNCTION_RECV],
&NextIrp->Tail.Overlay.ListEntry);
break;
} else {
AFD_DbgPrint(MID_TRACE,("Completing recv %x\n", NextIrp));
UnlockBuffers( RecvReq->BufferArray, RecvReq->BufferCount );
NextIrp->IoStatus.Status = Status;
NextIrp->IoStatus.Information = TotalBytesCopied;
IoCompleteRequest( NextIrp, IO_NETWORK_INCREMENT );
}
}
if( FCB->Recv.Window && !FCB->Recv.Content ) {
AFD_DbgPrint(MID_TRACE,
("Exhausted our buffer. Requesting new: %x\n", FCB));
Status = TdiReceive( &FCB->ReceiveIrp.InFlightRequest,
IrpSp->FileObject,
TDI_RECEIVE_NORMAL,
FCB->Recv.Window,
FCB->Recv.Size,
&FCB->ReceiveIrp.Iosb,
ReceiveComplete,
FCB );
}
} else {
while( !IsListEmpty( &FCB->PendingIrpList[FUNCTION_RECV] ) ) {
NextIrpEntry =
RemoveHeadList(&FCB->PendingIrpList[FUNCTION_RECV]);
NextIrp =
CONTAINING_RECORD(NextIrpEntry, IRP, Tail.Overlay.ListEntry);
AFD_DbgPrint(MID_TRACE,("Completing recv %x (%x)\n",
NextIrp, Status));
Irp->IoStatus.Status = Status;
Irp->IoStatus.Information = 0;
IoCompleteRequest( Irp, IO_NETWORK_INCREMENT );
}
}
if( FCB->Recv.Content ) {
FCB->PollState |= AFD_EVENT_RECEIVE;
PollReeval( FCB->DeviceExt, FCB->FileObject );
} else
FCB->PollState &= ~AFD_EVENT_RECEIVE;
SocketStateUnlock( FCB );
AFD_DbgPrint(MID_TRACE,("Returned %x\n", Status));
return Status;
}
NTSTATUS STDCALL
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;
AFD_DbgPrint(MID_TRACE,("Called on %x\n", FCB));
if( !SocketAcquireStateLock( FCB ) ) return LostSocket( Irp, FALSE );
if( !(RecvReq = LockRequest( Irp, IrpSp )) )
return UnlockAndMaybeComplete( FCB, STATUS_NO_MEMORY,
Irp, 0, NULL, FALSE );
RecvReq->BufferArray = LockBuffers( RecvReq->BufferArray,
RecvReq->BufferCount,
TRUE );
Status = TryToSatisfyRecvRequestFromBuffer
( FCB, RecvReq, &TotalBytesCopied );
if( Status != STATUS_PENDING ) {
UnlockBuffers( RecvReq->BufferArray, RecvReq->BufferCount );
return UnlockAndMaybeComplete( FCB, Status, Irp,
TotalBytesCopied, NULL, TRUE );
} else {
return LeaveIrpUntilLater( FCB, Irp, FUNCTION_RECV );
}
}
NTSTATUS STDCALL
SatisfyPacketRecvRequest( PAFD_FCB FCB, PIRP Irp,
PAFD_STORED_DATAGRAM DatagramRecv ) {
NTSTATUS Status = STATUS_SUCCESS;
PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation( Irp );
PAFD_RECV_INFO RecvReq =
IrpSp->Parameters.DeviceIoControl.Type3InputBuffer;
UINT CopyLen = 0;
CopyLen = MIN(DatagramRecv->Len, RecvReq->BufferArray[0].len);
RtlCopyMemory( RecvReq->BufferArray[0].buf, DatagramRecv->Buffer,
CopyLen );
Status = Irp->IoStatus.Status = STATUS_SUCCESS;
Irp->IoStatus.Information = CopyLen;
ExFreePool( DatagramRecv );
return Status;
}
NTSTATUS DDKAPI
PacketSocketRecvComplete(
PDEVICE_OBJECT DeviceObject,
PIRP Irp,
PVOID Context ) {
NTSTATUS Status = STATUS_SUCCESS;
PAFD_FCB FCB = Context;
PIRP NextIrp;
PLIST_ENTRY ListEntry;
PAFD_RECV_INFO RecvReq;
PAFD_STORED_DATAGRAM DatagramRecv;
UINT DGSize = Irp->IoStatus.Information + sizeof( AFD_STORED_DATAGRAM );
AFD_DbgPrint(MID_TRACE,("Called on %x\n", FCB));
if( !SocketAcquireStateLock( FCB ) ) {
SocketStateUnlock( FCB );
return STATUS_UNSUCCESSFUL;
}
DatagramRecv = ExAllocatePool( NonPagedPool, DGSize );
if( DatagramRecv ) {
DatagramRecv->Len = Irp->IoStatus.Information;
RtlCopyMemory( DatagramRecv->Buffer, FCB->Recv.Window,
DatagramRecv->Len );
InsertTailList( &FCB->DatagramList, &DatagramRecv->ListEntry );
} else Status = STATUS_NO_MEMORY;
/* Satisfy as many requests as we can */
while( NT_SUCCESS(Status) &&
!IsListEmpty( &FCB->DatagramList ) &&
!IsListEmpty( &FCB->PendingIrpList[FUNCTION_RECV_DATAGRAM] ) ) {
ListEntry = RemoveHeadList( &FCB->DatagramList );
DatagramRecv = CONTAINING_RECORD( ListEntry, AFD_STORED_DATAGRAM,
ListEntry );
ListEntry = RemoveHeadList
( &FCB->PendingIrpList[FUNCTION_RECV_DATAGRAM] );
NextIrp = CONTAINING_RECORD( ListEntry, IRP, Tail.Overlay.ListEntry );
RecvReq = NextIrp->AssociatedIrp.SystemBuffer;
if( DatagramRecv->Len > RecvReq->BufferArray[0].len &&
!(RecvReq->TdiFlags & TDI_RECEIVE_PARTIAL) ) {
InsertHeadList( &FCB->DatagramList,
&DatagramRecv->ListEntry );
Status = NextIrp->IoStatus.Status = STATUS_BUFFER_TOO_SMALL;
NextIrp->IoStatus.Information = DatagramRecv->Len;
UnlockBuffers( RecvReq->BufferArray, RecvReq->BufferCount );
IoCompleteRequest( NextIrp, IO_NETWORK_INCREMENT );
} else {
Status = SatisfyPacketRecvRequest( FCB, NextIrp, DatagramRecv );
UnlockBuffers( RecvReq->BufferArray, RecvReq->BufferCount );
IoCompleteRequest( NextIrp, IO_NETWORK_INCREMENT );
}
}
if( !IsListEmpty( &FCB->DatagramList ) ) {
FCB->PollState |= AFD_EVENT_RECEIVE;
PollReeval( FCB->DeviceExt, FCB->FileObject );
}
/* Now relaunch the datagram request */
Status = TdiReceiveDatagram
( &FCB->ReceiveIrp.InFlightRequest,
FCB->AddressFile.Object,
0,
FCB->Recv.Window,
FCB->Recv.Size,
FCB->AddressFrom,
&FCB->ReceiveIrp.Iosb,
PacketSocketRecvComplete,
FCB );
SocketStateUnlock( FCB );
return STATUS_SUCCESS;
}
NTSTATUS STDCALL
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 RecvReq;
PLIST_ENTRY ListEntry;
PAFD_STORED_DATAGRAM DatagramRecv;
AFD_DbgPrint(MID_TRACE,("Called on %x\n", FCB));
if( !SocketAcquireStateLock( FCB ) ) return LostSocket( Irp, FALSE );
if( !(RecvReq = LockRequest( Irp, IrpSp )) )
return UnlockAndMaybeComplete( FCB, STATUS_NO_MEMORY,
Irp, 0, NULL, FALSE );
if( !IsListEmpty( &FCB->DatagramList ) ) {
ListEntry = RemoveHeadList( &FCB->DatagramList );
DatagramRecv = CONTAINING_RECORD( ListEntry, AFD_STORED_DATAGRAM,
ListEntry );
if( DatagramRecv->Len > RecvReq->BufferArray[0].len &&
!(RecvReq->TdiFlags & TDI_RECEIVE_PARTIAL) ) {
InsertHeadList( &FCB->DatagramList,
&DatagramRecv->ListEntry );
Status = Irp->IoStatus.Status = STATUS_BUFFER_TOO_SMALL;
Irp->IoStatus.Information = DatagramRecv->Len;
return UnlockAndMaybeComplete
( FCB, Status, Irp, RecvReq->BufferArray[0].len, NULL, TRUE );
} else {
if( IsListEmpty( &FCB->DatagramList ) )
FCB->PollState &= ~AFD_EVENT_RECEIVE;
Status = SatisfyPacketRecvRequest( FCB, Irp, DatagramRecv );
return UnlockAndMaybeComplete
( FCB, Status, Irp, Irp->IoStatus.Information, NULL, TRUE );
}
} else {
RecvReq->BufferArray = LockBuffers( RecvReq->BufferArray,
RecvReq->BufferCount,
TRUE );
return LeaveIrpUntilLater( FCB, Irp, FUNCTION_RECV_DATAGRAM );
}
}

View file

@ -1,316 +0,0 @@
/*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS Ancillary Function Driver
* FILE: afd/routines.c
* PURPOSE: Support routines
* PROGRAMMERS: Casper S. Hornstrup (chorns@users.sourceforge.net)
* REVISIONS:
* CSH 01/02-2001 Created
*/
#include <afd.h>
#include <debug.h>
#ifndef DONT_USE_ME_THIS_WAY_IM_LIFTED_FROM_NTOSKRNL_XXX_DO_THIS_THE_RIGHT_WAY
LONG FASTCALL
XxInterlockedExchange(PLONG Target,
LONG Value);
__asm__("\n\t.global @XxInterlockedExchange@8\n\t"
"@XxInterlockedExchange@8:\n\t"
"xchgl %edx,(%ecx)\n\t"
"movl %edx,%eax\n\t"
"ret\n\t");
#define InterlockedExchange XxInterlockedExchange
#endif
VOID DumpName(
LPSOCKADDR Name)
{
AFD_DbgPrint(MIN_TRACE, ("DumpName:\n"));
AFD_DbgPrint(MIN_TRACE, (" sa_family: %d\n", Name->sa_family));
AFD_DbgPrint(MIN_TRACE, (" sin_port: %d\n", WN2H(((LPSOCKADDR_IN)Name)->sin_port)));
AFD_DbgPrint(MIN_TRACE, (" in_addr: 0x%x\n", WN2H(((LPSOCKADDR_IN)Name)->sin_addr.S_un.S_addr)));
}
ULONG WSABufferSize(
LPWSABUF Buffers,
DWORD BufferCount)
{
ULONG i;
LPWSABUF p;
ULONG Count = 0;
p = Buffers;
for (i = 0; i < BufferCount; i++) {
Count += p->len;
p++;
}
AFD_DbgPrint(MAX_TRACE, ("Buffer is %d bytes.\n", Count));
return Count;
}
NTSTATUS MergeWSABuffers(
LPWSABUF Buffers,
DWORD BufferCount,
PVOID Destination,
ULONG MaxLength,
PULONG BytesCopied)
{
ULONG Length;
LPWSABUF p;
ULONG i;
*BytesCopied = 0;
if (BufferCount == 0)
return STATUS_SUCCESS;
p = Buffers;
AFD_DbgPrint(MAX_TRACE, ("Destination is 0x%X\n", Destination));
AFD_DbgPrint(MAX_TRACE, ("p is 0x%X\n", p));
for (i = 0; i < BufferCount; i++) {
Length = p->len;
if (Length > MaxLength)
/* Don't copy out of bounds */
Length = MaxLength;
RtlCopyMemory(Destination, p->buf, Length);
Destination += Length;
AFD_DbgPrint(MAX_TRACE, ("Destination is 0x%X\n", Destination));
p++;
AFD_DbgPrint(MAX_TRACE, ("p is 0x%X\n", p));
*BytesCopied += Length;
MaxLength -= Length;
if (MaxLength == 0)
/* Destination buffer is full */
break;
}
return STATUS_SUCCESS;
}
VOID TryToSatisfyRecvRequest( PAFDFCB FCB, BOOL Continuous ) {
PAFD_READ_REQUEST ReadRequest;
PLIST_ENTRY Entry;
NTSTATUS Status;
ULONG Count = 0;
AFD_DbgPrint(MAX_TRACE, ("Satisfying read request.\n"));
while (!IsListEmpty(&FCB->ReadRequestQueue) &&
!IsListEmpty(&FCB->ReceiveQueue)) {
AFD_DbgPrint(MAX_TRACE, ("Satisfying read request.\n"));
Entry = RemoveHeadList(&FCB->ReadRequestQueue);
ReadRequest = CONTAINING_RECORD(Entry, AFD_READ_REQUEST, ListEntry);
AFD_DbgPrint(MAX_TRACE,("ReadRequest: (li) %x %x %x\n",
ReadRequest->Irp,
ReadRequest->RecvFromRequest,
ReadRequest->RecvFromReply));
Status = FillWSABuffers(
FCB,
ReadRequest->RecvFromRequest->Buffers,
ReadRequest->RecvFromRequest->BufferCount,
&Count,
Continuous );
ReadRequest->RecvFromReply->NumberOfBytesRecvd = Count;
ReadRequest->RecvFromReply->Status = NO_ERROR;
ReadRequest->Irp->IoStatus.Information =
sizeof(*ReadRequest->RecvFromReply);
ReadRequest->Irp->IoStatus.Status = Status;
AFD_DbgPrint(MAX_TRACE, ("Completing IRP at (0x%X).\n", ReadRequest->Irp));
IoSetCancelRoutine(ReadRequest->Irp, NULL);
IoCompleteRequest(ReadRequest->Irp, IO_NETWORK_INCREMENT);
}
AFD_DbgPrint(MAX_TRACE, ("Bytes received (0x%X).\n", Count));
}
/*
* NOTES: ReceiveQueueLock must be acquired for the FCB when called
*/
NTSTATUS FillWSABuffers(
PAFDFCB FCB,
LPWSABUF Buffers,
DWORD BufferCount,
PULONG BytesCopied,
BOOL Continuous)
{
PUCHAR DstData, SrcData;
UINT DstSize, SrcSize;
UINT Count, Total;
PAFD_BUFFER SrcBuffer;
PMDL Mdl;
PLIST_ENTRY Entry;
*BytesCopied = 0;
if (BufferCount == 0)
return STATUS_SUCCESS;
if (IsListEmpty(&FCB->ReceiveQueue))
return STATUS_SUCCESS;
Entry = RemoveHeadList(&FCB->ReceiveQueue);
SrcBuffer = CONTAINING_RECORD(Entry, AFD_BUFFER, ListEntry);
SrcData = SrcBuffer->Buffer.buf + SrcBuffer->Offset;
SrcSize = SrcBuffer->Buffer.len - SrcBuffer->Offset;
/* First buffer: map the pages so we can access them */
Mdl = (PMDL)Buffers->buf;
DstData = MmMapLockedPages( Mdl, KernelMode );
DstSize = Buffers->len;
/* Copy the data */
for (Total = 0;;) {
/* Find out how many bytes we can copy at one time */
if (DstSize < SrcSize)
Count = DstSize;
else
Count = SrcSize;
AFD_DbgPrint(MAX_TRACE, ("DstData (0x%X) SrcData (0x%X) Count (0x%X).\n",
DstData, SrcData, Count));
RtlCopyMemory((PVOID)DstData, (PVOID)SrcData, Count);
Total += Count;
SrcSize -= Count;
if (SrcSize == 0) {
ExFreePool(SrcBuffer->Buffer.buf);
ExFreePool(SrcBuffer);
/* No more bytes in source buffer. Proceed to the next buffer
in the source buffer chain if there is one */
if (IsListEmpty(&FCB->ReceiveQueue)) {
SrcBuffer = NULL;
SrcData = 0;
SrcSize = 0;
break;
}
Entry = RemoveHeadList(&FCB->ReceiveQueue);
SrcBuffer = CONTAINING_RECORD(Entry, AFD_BUFFER, ListEntry);
SrcData = SrcBuffer->Buffer.buf;
SrcSize = SrcBuffer->Buffer.len;
}
DstSize -= Count;
if (DstSize == 0) {
/* No more bytes in destination buffer. Proceed to
the next buffer in the destination buffer chain */
BufferCount--;
if (BufferCount < 1)
break;
/* And cleanup the pages. */
MmUnmapLockedPages( DstData, Mdl );
MmUnlockPages( Mdl );
IoFreeMdl( Mdl );
Buffers++;
Mdl = (PMDL)Buffers->buf;
DstData = MmMapLockedPages( Mdl, KernelMode );
DstSize = Buffers->len;
}
}
if (SrcSize > 0) {
SrcBuffer->Offset += Total;
InsertHeadList(&FCB->ReceiveQueue, Entry);
} else if (SrcBuffer != NULL) {
ExFreePool(SrcBuffer->Buffer.buf);
ExFreePool(SrcBuffer);
}
*BytesCopied = Total;
return STATUS_SUCCESS;
}
ULONG ChecksumCompute(
PVOID Data,
UINT Count,
ULONG Seed)
/*
* FUNCTION: Calculate checksum of a buffer
* ARGUMENTS:
* Data = Pointer to buffer with data
* Count = Number of bytes in buffer
* Seed = Previously calculated checksum (if any)
* RETURNS:
* Checksum of buffer
*/
{
/* FIXME: This should be done in assembler */
register ULONG Sum = Seed;
while (Count > 1) {
Sum += *(PUSHORT)Data;
Count -= 2;
Data = (PVOID) ((ULONG_PTR) Data + 2);
}
/* Add left-over byte, if any */
if (Count > 0)
Sum += *(PUCHAR)Data;
/* Fold 32-bit sum to 16 bits */
while (Sum >> 16)
Sum = (Sum & 0xFFFF) + (Sum >> 16);
return ~Sum;
}
VOID BuildIPv4Header(
PIPv4_HEADER IPHeader,
ULONG TotalSize,
ULONG Protocol,
PSOCKADDR SourceAddress,
PSOCKADDR DestinationAddress)
{
PSOCKADDR_IN SrcNameIn = (PSOCKADDR_IN)SourceAddress;
PSOCKADDR_IN DstNameIn = (PSOCKADDR_IN)DestinationAddress;
/* Version = 4, Length = 5 DWORDs */
IPHeader->VerIHL = 0x45;
/* Normal Type-of-Service */
IPHeader->Tos = 0;
/* Length of header and data */
IPHeader->TotalLength = WH2N((USHORT)TotalSize);
/* Identification */
IPHeader->Id = 0;
/* One fragment at offset 0 */
IPHeader->FlagsFragOfs = 0;
/* Time-to-Live is 128 */
IPHeader->Ttl = 128;
/* Protocol number */
IPHeader->Protocol = Protocol;
/* Checksum is 0 (calculated later) */
IPHeader->Checksum = 0;
/* Source address */
IPHeader->SrcAddr = SrcNameIn->sin_addr.S_un.S_addr;
/* Destination address */
IPHeader->DstAddr = DstNameIn->sin_addr.S_un.S_addr;
/* Calculate checksum of IP header */
IPHeader->Checksum = (USHORT)
ChecksumCompute(IPHeader, sizeof(IPv4_HEADER), 0);
}
/* EOF */

View file

@ -0,0 +1,237 @@
/* $Id: select.c,v 1.2 2004/07/18 22:49:17 arty Exp $
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel
* FILE: drivers/net/afd/afd/select.c
* PURPOSE: Ancillary functions driver
* PROGRAMMER: Art Yerkes (ayerkes@speakeasy.net)
* UPDATE HISTORY:
* 20040708 Created
*/
#include "afd.h"
#include "tdi_proto.h"
#include "tdiconn.h"
#include "debug.h"
VOID CopyBackStatus( PAFD_HANDLE HandleArray,
UINT HandleCount ) {
UINT i;
for( i = 0; i < HandleCount; i++ ) {
HandleArray[i].Events = HandleArray[i].Status;
HandleArray[i].Status = 0;
}
}
VOID ZeroEvents( PAFD_HANDLE HandleArray,
UINT HandleCount ) {
UINT i;
for( i = 0; i < HandleCount; i++ ) {
HandleArray[i].Events = 0;
HandleArray[i].Status = 0;
}
}
NTSTATUS STDCALL
ScanForImmediateTrigger( PAFD_HANDLE HandleArray,
UINT HandleCount,
PUINT HandlesSet ) {
NTSTATUS Status = STATUS_SUCCESS;
PFILE_OBJECT FileObject;
PAFD_FCB FCB;
UINT i;
BOOLEAN ShouldReturnNow = FALSE;
for( i = 0; i < HandleCount && NT_SUCCESS(Status); i++ ) {
HandleArray[i].Status = 0;
Status =
ObReferenceObjectByHandle
( (PVOID)HandleArray[i].Handle,
FILE_ALL_ACCESS,
NULL,
KernelMode,
(PVOID*)&FileObject,
NULL );
if( NT_SUCCESS(Status) ) {
FCB = FileObject->FsContext;
/* Check select bits */
if( !SocketAcquireStateLock( FCB ) )
Status = STATUS_UNSUCCESSFUL;
if( NT_SUCCESS(Status) )
HandleArray[i].Status =
FCB->PollState & HandleArray[i].Events;
if( HandleArray[i].Status ) ShouldReturnNow = TRUE;
ObDereferenceObject( (PVOID)HandleArray[i].Handle );
}
}
if( !NT_SUCCESS(Status) || ShouldReturnNow ) return Status;
else return STATUS_PENDING;
}
VOID SelectTimeout( PKDPC Dpc,
PVOID DeferredContext,
PVOID SystemArgument1,
PVOID SystemArgument2 ) {
PAFD_ACTIVE_POLL Poll = DeferredContext;
PAFD_POLL_INFO PollReq;
PAFD_DEVICE_EXTENSION DeviceExt;
PIRP Irp;
KIRQL OldIrql;
Irp = Poll->Irp;
DeviceExt = Poll->DeviceExt;
PollReq = Irp->AssociatedIrp.SystemBuffer;
KeAcquireSpinLock( &DeviceExt->Lock, &OldIrql );
RemoveEntryList( &Poll->ListEntry );
KeReleaseSpinLock( &DeviceExt->Lock, OldIrql );
ExFreePool( Poll );
ZeroEvents( PollReq->Handles, PollReq->HandleCount );
Irp->IoStatus.Status = STATUS_TIMEOUT;
Irp->IoStatus.Information = -1;
IoCompleteRequest( Irp, IO_NO_INCREMENT );
}
NTSTATUS STDCALL
AfdSelect( PDEVICE_OBJECT DeviceObject, PIRP Irp,
PIO_STACK_LOCATION IrpSp ) {
NTSTATUS Status = STATUS_NO_MEMORY;
PAFD_POLL_INFO PollReq = Irp->AssociatedIrp.SystemBuffer;
PAFD_DEVICE_EXTENSION DeviceExt = DeviceObject->DeviceExtension;
PAFD_ACTIVE_POLL Poll = NULL;
UINT CopySize = IrpSp->Parameters.DeviceIoControl.InputBufferLength;
UINT AllocSize =
CopySize + sizeof(AFD_ACTIVE_POLL) - sizeof(AFD_POLL_INFO);
KIRQL OldIrql;
UINT HandlesSignalled;
AFD_DbgPrint(MID_TRACE,("Called\n"));
Status = ScanForImmediateTrigger( PollReq->Handles,
PollReq->HandleCount,
&HandlesSignalled );
if( Status == STATUS_PENDING ) {
Poll = ExAllocatePool( NonPagedPool, AllocSize );
if( Poll ) {
KeAcquireSpinLock( &DeviceExt->Lock, &OldIrql );
KeInitializeDpc( (PRKDPC)&Poll->TimeoutDpc,
(PKDEFERRED_ROUTINE)SelectTimeout,
Poll );
PollReq->Timeout.QuadPart *= -1;
/* Negative values are relative */
KeInitializeTimerEx( &Poll->Timer, NotificationTimer );
KeSetTimer( &Poll->Timer, PollReq->Timeout, &Poll->TimeoutDpc );
Poll->Irp = Irp;
Poll->DeviceExt = DeviceExt;
InsertTailList( &DeviceExt->Polls, &Poll->ListEntry );
Status = STATUS_PENDING;
KeReleaseSpinLock( &DeviceExt->Lock, OldIrql );
} else Status = STATUS_NO_MEMORY;
} else if( Status == STATUS_SUCCESS ) {
CopyBackStatus( PollReq->Handles,
PollReq->HandleCount );
} else {
ZeroEvents( PollReq->Handles,
PollReq->HandleCount );
}
AFD_DbgPrint(MID_TRACE,("Returning %x\n", Status));
if( Status == STATUS_PENDING )
IoMarkIrpPending( Irp );
else {
Irp->IoStatus.Status = Status;
Irp->IoStatus.Information = HandlesSignalled;
IoCompleteRequest( Irp, IO_NETWORK_INCREMENT );
}
return Status;
}
VOID SignalSocket( PAFD_ACTIVE_POLL Poll, PAFD_POLL_INFO PollReq, UINT i ) {
/* One of the files was destroyed. We return now with error. */
Poll->Irp->IoStatus.Status = STATUS_SUCCESS; /* XXX REVISIT */
Poll->Irp->IoStatus.Information = 1;
CopyBackStatus( PollReq->Handles,
PollReq->HandleCount );
IoCompleteRequest( Poll->Irp, IO_NETWORK_INCREMENT );
}
BOOLEAN UpdatePollWithFCB( PAFD_ACTIVE_POLL Poll, PFILE_OBJECT FileObject ) {
UINT i;
NTSTATUS Status;
PFILE_OBJECT TargetFile;
PAFD_FCB FCB;
PAFD_POLL_INFO PollReq = Poll->Irp->AssociatedIrp.SystemBuffer;
for( i = 0; i < PollReq->HandleCount; i++ ) {
Status =
ObReferenceObjectByHandle
( (PVOID)PollReq->Handles[i].Handle,
FILE_ALL_ACCESS,
NULL,
KernelMode,
(PVOID*)&TargetFile,
NULL );
if( !NT_SUCCESS(Status) ) {
PollReq->Handles[i].Status = AFD_EVENT_CLOSE;
SignalSocket( Poll, PollReq, i );
return TRUE;
} else {
FCB = FileObject->FsContext;
if( !SocketAcquireStateLock( FCB ) ) {
PollReq->Handles[i].Status = AFD_EVENT_CLOSE;
SignalSocket( Poll, PollReq, i );
} else {
PollReq->Handles[i].Status =
PollReq->Handles[i].Events & FCB->PollState;
if( PollReq->Handles[i].Status )
SignalSocket( Poll, PollReq, i );
}
return TRUE;
}
}
return FALSE;
}
VOID PollReeval( PAFD_DEVICE_EXTENSION DeviceExt, PFILE_OBJECT FileObject ) {
PAFD_ACTIVE_POLL Poll = NULL;
PLIST_ENTRY ThePollEnt = NULL;
KIRQL OldIrql;
AFD_DbgPrint(MID_TRACE,("Called: DeviceExt %x FileObject %x\n",
DeviceExt, FileObject));
KeAcquireSpinLock( &DeviceExt->Lock, &OldIrql );
ThePollEnt = DeviceExt->Polls.Flink;
while( ThePollEnt != &DeviceExt->Polls ) {
Poll = CONTAINING_RECORD( ThePollEnt, AFD_ACTIVE_POLL, ListEntry );
if( UpdatePollWithFCB( Poll, FileObject ) ) {
ThePollEnt = ThePollEnt->Flink;
RemoveEntryList( &Poll->ListEntry );
} else
ThePollEnt = ThePollEnt->Flink;
}
KeReleaseSpinLock( &DeviceExt->Lock, OldIrql );
AFD_DbgPrint(MID_TRACE,("Leaving"));
}

View file

@ -8,6 +8,7 @@
* CSH 01/09-2000 Created
*/
#include <afd.h>
#include "debug.h"
#include "tdiconn.h"
#ifdef DBG
@ -57,10 +58,12 @@ NTSTATUS TdiCall(
{
NTSTATUS Status;
AFD_DbgPrint(MAX_TRACE, ("Called\n"));
AFD_DbgPrint(MID_TRACE, ("Called\n"));
AFD_DbgPrint(MID_TRACE, ("Irp->UserEvent = %x\n", Irp->UserEvent));
Status = IoCallDriver(DeviceObject, Irp);
AFD_DbgPrint(MAX_TRACE, ("IoCallDriver: %08x\n", Status));
AFD_DbgPrint(MID_TRACE, ("IoCallDriver: %08x\n", Status));
if ((Status == STATUS_PENDING) && (Event != NULL)) {
AFD_DbgPrint(MAX_TRACE, ("Waiting on transport.\n"));
@ -110,7 +113,7 @@ NTSTATUS TdiOpenDevice(
NULL); /* Security descriptor */
Status = ZwCreateFile(Handle, /* Return file handle */
GENERIC_READ | GENERIC_WRITE, /* Desired access */
GENERIC_READ | GENERIC_WRITE | SYNCHRONIZE, /* Desired access */
&Attr, /* Object attributes */
&Iosb, /* IO status */
0, /* Initial allocation size */
@ -122,7 +125,7 @@ NTSTATUS TdiOpenDevice(
EaLength); /* EA length */
if (NT_SUCCESS(Status)) {
Status = ObReferenceObjectByHandle(*Handle, /* Handle to open file */
GENERIC_READ | GENERIC_WRITE, /* Access mode */
GENERIC_READ | GENERIC_WRITE | SYNCHRONIZE, /* Access mode */
NULL, /* Object type */
KernelMode, /* Access mode */
(PVOID*)Object, /* Pointer to object */
@ -158,9 +161,9 @@ NTSTATUS TdiCloseDevice(
}
NTSTATUS TdiOpenAddressFileIPv4(
NTSTATUS TdiOpenAddressFile(
PUNICODE_STRING DeviceName,
LPSOCKADDR Name,
PTRANSPORT_ADDRESS Name,
PHANDLE AddressHandle,
PFILE_OBJECT *AddressObject)
/*
@ -175,21 +178,21 @@ NTSTATUS TdiOpenAddressFileIPv4(
*/
{
PFILE_FULL_EA_INFORMATION EaInfo;
PTA_IP_ADDRESS Address;
NTSTATUS Status;
ULONG EaLength;
PTRANSPORT_ADDRESS Address;
AFD_DbgPrint(MAX_TRACE, ("Called. DeviceName (%wZ) Name (0x%X)\n",
DeviceName, Name));
/* EaName must be 0-terminated, even though TDI_TRANSPORT_ADDRESS_LENGTH does *not* include the 0 */
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 +
sizeof(TA_IP_ADDRESS) + 1;
TDI_TRANSPORT_ADDRESS_LENGTH +
TaLengthOfTransportAddress( Name ) + 1;
EaInfo = (PFILE_FULL_EA_INFORMATION)ExAllocatePool(NonPagedPool, EaLength);
if (!EaInfo)
return STATUS_INSUFFICIENT_RESOURCES;
return STATUS_INSUFFICIENT_RESOURCES;
RtlZeroMemory(EaInfo, EaLength);
EaInfo->EaNameLength = TDI_TRANSPORT_ADDRESS_LENGTH;
/* Don't copy the terminating 0; we have already zeroed it */
@ -197,9 +200,9 @@ NTSTATUS TdiOpenAddressFileIPv4(
TdiTransportAddress,
TDI_TRANSPORT_ADDRESS_LENGTH);
EaInfo->EaValueLength = sizeof(TA_IP_ADDRESS);
Address = (PTA_IP_ADDRESS)(EaInfo->EaName + TDI_TRANSPORT_ADDRESS_LENGTH + 1); /* 0-terminated */
TdiBuildAddressIPv4(Address, Name);
Address =
(PTRANSPORT_ADDRESS)(EaInfo->EaName + TDI_TRANSPORT_ADDRESS_LENGTH + 1); /* 0-terminated */
TaCopyTransportAddressInPlace( Address, Name );
Status = TdiOpenDevice(DeviceName,
EaLength,
EaInfo,
@ -210,43 +213,6 @@ NTSTATUS TdiOpenAddressFileIPv4(
}
NTSTATUS TdiOpenAddressFile(
PUNICODE_STRING DeviceName,
LPSOCKADDR Name,
PHANDLE AddressHandle,
PFILE_OBJECT *AddressObject)
/*
* FUNCTION: Opens an address file object
* ARGUMENTS:
* DeviceName = Pointer to counted string with name of device
* Name = Pointer to socket name
* AddressHandle = Address of buffer to place address file handle
* AddressObject = Address of buffer to place address file object
* RETURNS:
* Status of operation
*/
{
NTSTATUS Status;
switch (Name->sa_family) {
case AF_INET:
Status = TdiOpenAddressFileIPv4(
DeviceName,
Name,
AddressHandle,
AddressObject);
break;
default:
AFD_DbgPrint(MAX_TRACE, ("Unknown socket address family (0x%X)\n",
Name->sa_family));
Status = STATUS_INVALID_PARAMETER;
}
return Status;
}
NTSTATUS TdiOpenConnectionEndpointFile(
PUNICODE_STRING DeviceName,
PHANDLE ConnectionHandle,
@ -298,8 +264,11 @@ NTSTATUS TdiOpenConnectionEndpointFile(
NTSTATUS TdiConnect(
PFILE_OBJECT ConnectionObject,
LPSOCKADDR RemoteAddress)
PIRP *Irp,
PFILE_OBJECT ConnectionObject,
PTRANSPORT_ADDRESS RemoteAddress,
PIO_COMPLETION_ROUTINE CompletionRoutine,
PVOID CompletionContext)
/*
* FUNCTION: Connect a connection endpoint to a remote peer
* ARGUMENTS:
@ -315,7 +284,6 @@ NTSTATUS TdiConnect(
IO_STATUS_BLOCK Iosb;
NTSTATUS Status;
KEVENT Event;
PIRP Irp;
AFD_DbgPrint(MAX_TRACE, ("Called\n"));
@ -323,12 +291,17 @@ NTSTATUS TdiConnect(
DeviceObject = IoGetRelatedDeviceObject(ConnectionObject);
Status = TdiBuildConnectionInfo(&RequestConnectionInfo, RemoteAddress);
if (!NT_SUCCESS(Status))
/* Use same TDI address type for return connection information */
Status = TdiBuildConnectionInfo(&RequestConnectionInfo,
&RemoteAddress->Address[0]);
if (!NT_SUCCESS(Status)) {
ExFreePool(RequestConnectionInfo);
return Status;
}
/* Use same TDI address type for return connection information */
Status = TdiBuildConnectionInfo(&ReturnConnectionInfo, RemoteAddress);
Status = TdiBuildConnectionInfo(&ReturnConnectionInfo,
&RemoteAddress->Address[0]);
if (!NT_SUCCESS(Status)) {
ExFreePool(RequestConnectionInfo);
ExFreePool(ReturnConnectionInfo);
@ -337,29 +310,27 @@ NTSTATUS TdiConnect(
KeInitializeEvent(&Event, NotificationEvent, FALSE);
Irp = TdiBuildInternalDeviceControlIrp(TDI_CONNECT, /* Sub function */
DeviceObject, /* Device object */
ConnectionObject, /* File object */
&Event, /* Event */
&Iosb); /* Status */
if (!Irp) {
ExFreePool(RequestConnectionInfo);
*Irp = TdiBuildInternalDeviceControlIrp(TDI_CONNECT, /* Sub function */
DeviceObject, /* Device object */
ConnectionObject, /* File object */
&Event, /* Event */
&Iosb); /* Status */
if (!*Irp) {
ExFreePool(ReturnConnectionInfo);
return STATUS_INSUFFICIENT_RESOURCES;
}
TdiBuildConnect(Irp, /* IRP */
TdiBuildConnect(*Irp, /* IRP */
DeviceObject, /* Device object */
ConnectionObject, /* File object */
NULL, /* Completion routine */
NULL, /* Completion routine context */
CompletionRoutine, /* Completion routine */
CompletionContext, /* Completion routine context */
NULL, /* Time */
RequestConnectionInfo, /* Request connection information */
ReturnConnectionInfo); /* Return connection information */
Status = TdiCall(Irp, DeviceObject, &Event, &Iosb);
Status = TdiCall(*Irp, DeviceObject, &Event, &Iosb);
ExFreePool(RequestConnectionInfo);
ExFreePool(ReturnConnectionInfo);
return Status;
@ -414,14 +385,16 @@ NTSTATUS TdiAssociateAddressFile(
}
NTSTATUS TdiListen(
PAFD_LISTEN_REQUEST ListenRequest,
NTSTATUS TdiListen
( PIRP *Irp,
PFILE_OBJECT ConnectionObject,
PTDI_CONNECTION_INFORMATION *RequestConnectionInfo,
PIO_STATUS_BLOCK Iosb,
PIO_COMPLETION_ROUTINE CompletionRoutine,
PVOID CompletionContext)
/*
* FUNCTION: Listen on a connection endpoint for a connection request from a remote peer
* ARGUMENTS:
* ListenRequest = Pointer to listen request object
* CompletionRoutine = Routine to be called when IRP is completed
* CompletionContext = Context for CompletionRoutine
* RETURNS:
@ -429,46 +402,40 @@ NTSTATUS TdiListen(
* May return STATUS_PENDING
*/
{
PFILE_OBJECT ConnectionObject;
PDEVICE_OBJECT DeviceObject;
NTSTATUS Status;
PIRP Irp;
AFD_DbgPrint(MAX_TRACE, ("Called\n"));
ConnectionObject = ListenRequest->Fcb->TdiConnectionObject;
assert(ConnectionObject);
DeviceObject = IoGetRelatedDeviceObject(ConnectionObject);
Status = TdiBuildNullConnectionInfo(&ListenRequest->RequestConnectionInfo,
TDI_ADDRESS_TYPE_IP);
Status = TdiBuildNullConnectionInfo(RequestConnectionInfo,
TDI_ADDRESS_TYPE_IP);
if (!NT_SUCCESS(Status))
return Status;
Irp = TdiBuildInternalDeviceControlIrp(TDI_LISTEN, /* Sub function */
DeviceObject, /* Device object */
ConnectionObject, /* File object */
NULL, /* Event */
&ListenRequest->Iosb); /* Status */
if (Irp == NULL)
*Irp = TdiBuildInternalDeviceControlIrp(TDI_LISTEN, /* Sub function */
DeviceObject, /* Device object */
ConnectionObject, /* File object */
NULL, /* Event */
Iosb); /* Status */
if (*Irp == NULL)
{
ExFreePool(ListenRequest->RequestConnectionInfo);
ListenRequest->RequestConnectionInfo = NULL;
return STATUS_INSUFFICIENT_RESOURCES;
ExFreePool(*RequestConnectionInfo);
return STATUS_INSUFFICIENT_RESOURCES;
}
TdiBuildListen(Irp, /* IRP */
TdiBuildListen(*Irp, /* IRP */
DeviceObject, /* Device object */
ConnectionObject, /* File object */
CompletionRoutine, /* Completion routine */
CompletionContext, /* Completion routine context */
0, /* Flags */
ListenRequest->RequestConnectionInfo, /* Request connection information */
*RequestConnectionInfo, /* Request connection information */
NULL /* ReturnConnectionInfo */); /* Return connection information */
Status = TdiCall(Irp, DeviceObject, NULL /* Don't wait for completion */, &ListenRequest->Iosb);
Status = TdiCall(*Irp, DeviceObject, NULL /* Don't wait for completion */, Iosb);
return Status;
}
@ -629,7 +596,7 @@ NTSTATUS TdiQueryInformation(
return Status;
}
#if 0
NTSTATUS TdiQueryInformationEx(
PFILE_OBJECT FileObject,
ULONG Entity,
@ -672,7 +639,6 @@ NTSTATUS TdiQueryInformationEx(
OutputLength); /* Return information */
}
NTSTATUS TdiQueryAddress(
PFILE_OBJECT FileObject,
PULONG Address)
@ -806,31 +772,20 @@ NTSTATUS TdiQueryAddress(
return Status;
}
#endif
NTSTATUS TdiSend(
PFILE_OBJECT TransportObject,
PVOID Buffer,
ULONG BufferSize)
/*
* FUNCTION: Sends a block of data
* ARGUMENTS:
* TransportObject = Pointer to transport object
* Buffer = Pointer to buffer with data to send
* BufferSize = Length of Buffer
* RETURNS:
* Status of operation
*/
NTSTATUS TdiSend
( PIRP *Irp,
PFILE_OBJECT TransportObject,
USHORT Flags,
PCHAR Buffer,
UINT BufferLength,
PIO_STATUS_BLOCK Iosb,
PIO_COMPLETION_ROUTINE CompletionRoutine,
PVOID CompletionContext )
{
#if 0
PTDI_CONNECTION_INFORMATION ConnectInfo;
PDEVICE_OBJECT DeviceObject;
IO_STATUS_BLOCK Iosb;
DWORD TdiAddressSize;
PVOID BaseAddress;
NTSTATUS Status;
KEVENT Event;
PIRP Irp;
PMDL Mdl;
DeviceObject = IoGetRelatedDeviceObject(TransportObject);
@ -839,38 +794,28 @@ NTSTATUS TdiSend(
return STATUS_INVALID_PARAMETER;
}
Status = TdiBuildConnectionInfo( &ConnectInfo, Address );
if (!NT_SUCCESS(Status))
return STATUS_INSUFFICIENT_RESOURCES;
*Irp = TdiBuildInternalDeviceControlIrp
( TDI_SEND, /* Sub function */
DeviceObject, /* Device object */
TransportObject, /* File object */
NULL, /* Event */
Iosb ); /* Status */
KeInitializeEvent(&Event, NotificationEvent, FALSE);
Irp = TdiBuildInternalDeviceControlIrp(TDI_SEND_DATAGRAM, /* Sub function */
DeviceObject, /* Device object */
TransportObject, /* File object */
&Event, /* Event */
&Iosb); /* Status */
if (!Irp) {
AFD_DbgPrint(MIN_TRACE, ("TdiBuildInternalDeviceControlIrp() failed.\n"));
ExFreePool(ConnectInfo);
if (!*Irp) {
AFD_DbgPrint(MIN_TRACE, ("Insufficient resources.\n"));
return STATUS_INSUFFICIENT_RESOURCES;
}
DisplayBuffer(Request->Buffers->buf, Request->Buffers->len);
AFD_DbgPrint(MID_TRACE, ("Allocating irp for %x:%d\n", Buffer,BufferLength));
/* FIXME: There may be more than one buffer */
BufferSize = Request->Buffers->len;
Mdl = IoAllocateMdl(
Request->Buffers->buf, /* Virtual address of buffer */
Request->Buffers->len, /* Length of buffer */
FALSE, /* Not secondary */
FALSE, /* Don't charge quota */
NULL); /* Don't use IRP */
Mdl = IoAllocateMdl(Buffer, /* Virtual address */
BufferLength, /* Length of buffer */
FALSE, /* Not secondary */
FALSE, /* Don't charge quota */
*Irp); /* use IRP */
if (!Mdl) {
AFD_DbgPrint(MIN_TRACE, ("IoAllocateMdl() failed.\n"));
IoFreeIrp(Irp);
ExFreePool(ConnectInfo);
AFD_DbgPrint(MIN_TRACE, ("Insufficient resources.\n"));
IoFreeIrp(*Irp);
return STATUS_INSUFFICIENT_RESOURCES;
}
@ -879,68 +824,44 @@ DisplayBuffer(Request->Buffers->buf, Request->Buffers->len);
#endif
MmProbeAndLockPages(Mdl, KernelMode, IoModifyAccess);
#ifdef _MSC_VER
} except(EXCEPTION_EXECUTE_HANDLER) {
} except (EXCEPTION_EXECUTE_HANDLER) {
AFD_DbgPrint(MIN_TRACE, ("MmProbeAndLockPages() failed.\n"));
IoFreeMdl(Mdl);
IoFreeIrp(Irp);
ExFreePool(ConnectInfo);
return STATUS_UNSUCCESSFUL;
IoFreeIrp(*Irp);
return STATUS_INSUFFICIENT_RESOURCES;
}
#endif
BaseAddress = MmMapLockedPages(Mdl, KernelMode);
AFD_DbgPrint(MID_TRACE,("AFD>>> Got an MDL: %x\n", Mdl));
AFD_DbgPrint(MAX_TRACE, ("Mapped user mode buffer at 0x%X.\n", BaseAddress));
TdiBuildSend(*Irp, /* I/O Request Packet */
DeviceObject, /* Device object */
TransportObject, /* File object */
CompletionRoutine, /* Completion routine */
CompletionContext, /* Completion context */
Mdl, /* Data buffer */
Flags, /* Flags */
BufferLength); /* Length of data */
TdiBuildSendDatagram(Irp, /* I/O Request Packet */
DeviceObject, /* Device object */
TransportObject, /* File object */
NULL, /* Completion routine */
NULL, /* Completion context */
Mdl, /* Descriptor for data buffer */
BufferSize, /* Size of data to send */
ConnectInfo); /* Connection information */
Status = TdiCall(Irp, DeviceObject, &Event, &Iosb);
MmUnmapLockedPages(BaseAddress, Mdl);
MmUnlockPages(Mdl);
IoFreeMdl(Mdl);
ExFreePool(ConnectInfo);
Status = TdiCall(*Irp, DeviceObject, NULL, Iosb);
/* Does not block... The MDL is deleted in the receive completion
routine. */
return Status;
#endif
return STATUS_SUCCESS;
}
NTSTATUS TdiSendDatagram(
NTSTATUS TdiReceive(
PIRP *Irp,
PFILE_OBJECT TransportObject,
LPSOCKADDR Address,
PMDL Mdl,
ULONG BufferSize)
/*
* FUNCTION: Sends a datagram
* ARGUMENTS:
* TransportObject = Pointer to transport object
* Address = Remote address to send data to
* Mdl = MDL of buffer to send
* BufferSize = Length of buffer
* RETURNS:
* Status of operation
*/
USHORT Flags,
PCHAR Buffer,
UINT BufferLength,
PIO_STATUS_BLOCK Iosb,
PIO_COMPLETION_ROUTINE CompletionRoutine,
PVOID CompletionContext)
{
PTDI_CONNECTION_INFORMATION ConnectInfo;
PDEVICE_OBJECT DeviceObject;
IO_STATUS_BLOCK Iosb;
NTSTATUS Status;
KEVENT Event;
PIRP Irp;
AFD_DbgPrint(MAX_TRACE, ("Called.\n"));
PMDL Mdl;
DeviceObject = IoGetRelatedDeviceObject(TransportObject);
if (!DeviceObject) {
@ -948,89 +869,73 @@ NTSTATUS TdiSendDatagram(
return STATUS_INVALID_PARAMETER;
}
AFD_DbgPrint(MAX_TRACE,
("TdiSendDatagram: TansportObject = %08x\n", TransportObject));
*Irp = TdiBuildInternalDeviceControlIrp
( TDI_RECEIVE, /* Sub function */
DeviceObject, /* Device object */
TransportObject, /* File object */
NULL, /* Event */
Iosb ); /* Status */
TdiBuildConnectionInfo( &ConnectInfo, Address );
AFD_DbgPrint(MAX_TRACE, ("Point B\n"));
KeInitializeEvent(&Event, NotificationEvent, FALSE);
AFD_DbgPrint(MAX_TRACE, ("Point 0\n"));
Irp = TdiBuildInternalDeviceControlIrp(TDI_SEND_DATAGRAM, /* Sub function */
DeviceObject, /* Device object */
TransportObject, /* File object */
&Event, /* Event */
&Iosb); /* Status */
if (!Irp) {
AFD_DbgPrint(MIN_TRACE, ("TdiBuildInternalDeviceControlIrp() failed.\n"));
ExFreePool(ConnectInfo);
if (!*Irp) {
AFD_DbgPrint(MIN_TRACE, ("Insufficient resources.\n"));
return STATUS_INSUFFICIENT_RESOURCES;
}
AFD_DbgPrint(MAX_TRACE, ("Point 1\n"));
AFD_DbgPrint(MID_TRACE, ("Allocating irp for %x:%d\n", Buffer,BufferLength));
#if 0
Mdl = IoAllocateMdl(Buffer, /* Virtual address of buffer */
BufferSize, /* Length of buffer */
FALSE, /* Not secondary */
FALSE, /* Don't charge quota */
NULL); /* Don't use IRP */
Mdl = IoAllocateMdl(Buffer, /* Virtual address */
BufferLength, /* Length of buffer */
FALSE, /* Not secondary */
FALSE, /* Don't charge quota */
*Irp); /* Don't use IRP */
if (!Mdl) {
AFD_DbgPrint(MIN_TRACE, ("IoAllocateMdl() failed.\n"));
IoFreeIrp(Irp);
ExFreePool(ConnectInfo);
AFD_DbgPrint(MIN_TRACE, ("Insufficient resources.\n"));
IoFreeIrp(*Irp);
return STATUS_INSUFFICIENT_RESOURCES;
}
#ifdef _MSC_VER
try {
#endif
MmProbeAndLockPages(Mdl, KernelMode, IoModifyAccess);
#ifdef _MSC_VER
} except(EXCEPTION_EXECUTE_HANDLER) {
} except (EXCEPTION_EXECUTE_HANDLER) {
AFD_DbgPrint(MIN_TRACE, ("MmProbeAndLockPages() failed.\n"));
IoFreeIrp(Irp);
ExFreePool(ConnectInfo);
return STATUS_UNSUCCESSFUL;
IoFreeMdl(Mdl);
IoFreeIrp(*Irp);
return STATUS_INSUFFICIENT_RESOURCES;
}
#endif
#endif
AFD_DbgPrint(MAX_TRACE, ("TdiBuildSendDatagram()\n"));
TdiBuildSendDatagram(Irp, /* I/O Request Packet */
DeviceObject, /* Device object */
TransportObject, /* File object */
NULL, /* Completion routine */
NULL, /* Completion context */
Mdl, /* Descriptor for data buffer */
BufferSize, /* Size of data to send */
ConnectInfo); /* Connection information */
AFD_DbgPrint(MAX_TRACE, ("Returned from TdiBuildSendDatagram\n"));
AFD_DbgPrint(MID_TRACE,("AFD>>> Got an MDL: %x\n", Mdl));
Status = TdiCall(Irp, DeviceObject, &Event, &Iosb);
AFD_DbgPrint(MAX_TRACE, ("Returned from TdiCall\n"));
TdiBuildReceive(*Irp, /* I/O Request Packet */
DeviceObject, /* Device object */
TransportObject, /* File object */
CompletionRoutine, /* Completion routine */
CompletionContext, /* Completion context */
Mdl, /* Data buffer */
Flags, /* Flags */
BufferLength); /* Length of data */
#if 0
MmUnlockPages(Mdl);
IoFreeMdl(Mdl);
#endif
ExFreePool(ConnectInfo);
AFD_DbgPrint(MAX_TRACE, ("Leaving %08x.\n", Status));
Status = TdiCall(*Irp, DeviceObject, NULL, Iosb);
/* Does not block... The MDL is deleted in the receive completion
routine. */
return Status;
}
NTSTATUS TdiReceiveDatagram(
PIRP *Irp,
PFILE_OBJECT TransportObject,
LPSOCKADDR From,
LPSOCKADDR Address,
PUCHAR Buffer,
PULONG BufferSize)
USHORT Flags,
PCHAR Buffer,
UINT BufferLength,
PTDI_CONNECTION_INFORMATION Addr,
PIO_STATUS_BLOCK Iosb,
PIO_COMPLETION_ROUTINE CompletionRoutine,
PVOID CompletionContext)
/*
* FUNCTION: Receives a datagram
* ARGUMENTS:
@ -1043,49 +948,38 @@ NTSTATUS TdiReceiveDatagram(
* Status of operation
*/
{
PTDI_CONNECTION_INFORMATION ReceiveInfo;
TDI_CONNECTION_INFORMATION ReturnInfo;
PDEVICE_OBJECT DeviceObject;
IO_STATUS_BLOCK Iosb;
NTSTATUS Status;
KEVENT Event;
PIRP Irp;
PMDL Mdl;
if (From != NULL) {
/* FIXME: Check that the socket type match the socket */
}
DeviceObject = IoGetRelatedDeviceObject(TransportObject);
if (!DeviceObject) {
AFD_DbgPrint(MIN_TRACE, ("Bad device object.\n"));
return STATUS_INVALID_PARAMETER;
}
TdiBuildConnectionInfoPair( &ReceiveInfo, From, Address );
KeInitializeEvent(&Event, NotificationEvent, FALSE);
*Irp = TdiBuildInternalDeviceControlIrp
( TDI_RECEIVE_DATAGRAM, /* Sub function */
DeviceObject, /* Device object */
TransportObject, /* File object */
NULL, /* Event */
Iosb ); /* Status */
Irp = TdiBuildInternalDeviceControlIrp(TDI_RECEIVE_DATAGRAM, /* Sub function */
DeviceObject, /* Device object */
TransportObject, /* File object */
&Event, /* Event */
&Iosb); /* Status */
if (!Irp) {
if (!*Irp) {
AFD_DbgPrint(MIN_TRACE, ("Insufficient resources.\n"));
ExFreePool(ReceiveInfo);
return STATUS_INSUFFICIENT_RESOURCES;
}
AFD_DbgPrint(MID_TRACE, ("Allocating irp for %x:%d\n", Buffer,BufferLength));
Mdl = IoAllocateMdl(Buffer, /* Virtual address */
*BufferSize, /* Length of buffer */
BufferLength, /* Length of buffer */
FALSE, /* Not secondary */
FALSE, /* Don't charge quota */
NULL); /* Don't use IRP */
*Irp); /* Don't use IRP */
if (!Mdl) {
AFD_DbgPrint(MIN_TRACE, ("Insufficient resources.\n"));
IoFreeIrp(Irp);
ExFreePool(ReceiveInfo);
IoFreeIrp(*Irp);
return STATUS_INSUFFICIENT_RESOURCES;
}
@ -1097,33 +991,117 @@ NTSTATUS TdiReceiveDatagram(
} except (EXCEPTION_EXECUTE_HANDLER) {
AFD_DbgPrint(MIN_TRACE, ("MmProbeAndLockPages() failed.\n"));
IoFreeMdl(Mdl);
IoFreeIrp(Irp);
ExFreePool(ReceiveInfo);
IoFreeIrp(*Irp);
return STATUS_INSUFFICIENT_RESOURCES;
}
#endif
TdiBuildReceiveDatagram(Irp, /* I/O Request Packet */
DeviceObject, /* Device object */
TransportObject, /* File object */
NULL, /* Completion routine */
NULL, /* Completion context */
Mdl, /* Data buffer */
*BufferSize, /* Size of data buffer */
ReceiveInfo, /* Connection information */
&ReturnInfo, /* Connection information */
TDI_RECEIVE_NORMAL); /* Flags */
Status = TdiCall(Irp, DeviceObject, &Event, &Iosb);
if (NT_SUCCESS(Status)) {
*BufferSize = Iosb.Information;
TdiBuildName(Address, TdiGetRemoteAddress(&ReturnInfo));
AFD_DbgPrint(MID_TRACE,("AFD>>> Got an MDL: %x\n", Mdl));
TdiBuildReceiveDatagram
(*Irp, /* I/O Request Packet */
DeviceObject, /* Device object */
TransportObject, /* File object */
CompletionRoutine, /* Completion routine */
CompletionContext, /* Completion context */
Mdl, /* Data buffer */
BufferLength,
Addr,
Addr,
Flags); /* Length of data */
Status = TdiCall(*Irp, DeviceObject, NULL, Iosb);
/* Does not block... The MDL is deleted in the receive completion
routine. */
return Status;
}
NTSTATUS TdiSendDatagram(
PIRP *Irp,
PFILE_OBJECT TransportObject,
PCHAR Buffer,
UINT BufferLength,
PTDI_CONNECTION_INFORMATION Addr,
PIO_STATUS_BLOCK Iosb,
PIO_COMPLETION_ROUTINE CompletionRoutine,
PVOID CompletionContext)
/*
* FUNCTION: Sends a datagram
* ARGUMENTS:
* TransportObject = Pointer to transport object
* From = Send filter (NULL if none)
* Address = Address of buffer to place remote address
* Buffer = Address of buffer to place sendd data
* BufferSize = Address of buffer with length of Buffer (updated)
* RETURNS:
* Status of operation
*/
{
PDEVICE_OBJECT DeviceObject;
NTSTATUS Status;
PMDL Mdl;
DeviceObject = IoGetRelatedDeviceObject(TransportObject);
if (!DeviceObject) {
AFD_DbgPrint(MIN_TRACE, ("Bad device object.\n"));
return STATUS_INVALID_PARAMETER;
}
MmUnlockPages(Mdl);
*Irp = TdiBuildInternalDeviceControlIrp
( TDI_SEND_DATAGRAM, /* Sub function */
DeviceObject, /* Device object */
TransportObject, /* File object */
NULL, /* Event */
Iosb ); /* Status */
IoFreeMdl(Mdl);
if (!*Irp) {
AFD_DbgPrint(MIN_TRACE, ("Insufficient resources.\n"));
return STATUS_INSUFFICIENT_RESOURCES;
}
ExFreePool(ReceiveInfo);
AFD_DbgPrint(MID_TRACE, ("Allocating irp for %x:%d\n", Buffer,BufferLength));
Mdl = IoAllocateMdl(Buffer, /* Virtual address */
BufferLength, /* Length of buffer */
FALSE, /* Not secondary */
FALSE, /* Don't charge quota */
*Irp); /* Don't use IRP */
if (!Mdl) {
AFD_DbgPrint(MIN_TRACE, ("Insufficient resources.\n"));
IoFreeIrp(*Irp);
return STATUS_INSUFFICIENT_RESOURCES;
}
#ifdef _MSC_VER
try {
#endif
MmProbeAndLockPages(Mdl, KernelMode, IoModifyAccess);
#ifdef _MSC_VER
} except (EXCEPTION_EXECUTE_HANDLER) {
AFD_DbgPrint(MIN_TRACE, ("MmProbeAndLockPages() failed.\n"));
IoFreeMdl(Mdl);
IoFreeIrp(*Irp);
return STATUS_INSUFFICIENT_RESOURCES;
}
#endif
AFD_DbgPrint(MID_TRACE,("AFD>>> Got an MDL: %x\n", Mdl));
TdiBuildSendDatagram
(*Irp, /* I/O Request Packet */
DeviceObject, /* Device object */
TransportObject, /* File object */
CompletionRoutine, /* Completion routine */
CompletionContext, /* Completion context */
Mdl, /* Data buffer */
BufferLength, /* Bytes to send */
Addr); /* Address */
Status = TdiCall(*Irp, DeviceObject, NULL, Iosb);
/* Does not block... The MDL is deleted in the send completion
routine. */
return Status;
}

View file

@ -1,191 +1,63 @@
/* $Id: tdiconn.c,v 1.2 2004/07/18 22:49:17 arty Exp $
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel
* FILE: drivers/net/afd/afd/tdiconn.c
* PURPOSE: Ancillary functions driver
* PROGRAMMER: Art Yerkes (ayerkes@speakeasy.net)
* UPDATE HISTORY:
* 20040708 Created
*/
#include <afd.h>
#include "debug.h"
#include "tdiconn.h"
DWORD TdiAddressSizeFromType(
ULONG Type)
/*
* FUNCTION: Returns the size of a TDI style address of given address type
* ARGUMENTS:
* Type = TDI style address type
* RETURNS:
* Size of TDI style address, 0 if Type is not valid
*/
{
switch (Type) {
case TDI_ADDRESS_TYPE_IP:
return sizeof(TA_IP_ADDRESS);
/* FIXME: More to come */
}
AFD_DbgPrint(MIN_TRACE, ("Unknown TDI address type (%d).\n", Type));
return 0;
UINT TdiAddressSizeFromType( UINT AddressType ) {
switch( AddressType ) {
case TDI_ADDRESS_TYPE_IP:
return sizeof(TA_IP_ADDRESS);
default:
KeBugCheck( 0 );
}
return 0;
}
DWORD TdiAddressSizeFromName(
LPSOCKADDR Name)
/*
* FUNCTION: Returns the size of a TDI style address equivalent to a
* WinSock style name
* ARGUMENTS:
* Name = WinSock style name
* RETURNS:
* Size of TDI style address, 0 if Name is not valid
*/
{
switch (Name->sa_family) {
case AF_INET:
return sizeof(TA_IP_ADDRESS);
/* FIXME: More to come */
}
AFD_DbgPrint(MIN_TRACE, ("Unknown address family (%d).\n", Name->sa_family));
return 0;
UINT TaLengthOfAddress( PTA_ADDRESS Addr ) {
UINT AddrLen = 2 * sizeof( USHORT ) + Addr->AddressLength;
AFD_DbgPrint(MID_TRACE,("AddrLen %x\n", AddrLen));
return AddrLen;
}
VOID TdiBuildAddressIPv4(
PTA_IP_ADDRESS Address,
LPSOCKADDR Name)
/*
* FUNCTION: Builds an IPv4 TDI style address
* ARGUMENTS:
* Address = Address of buffer to place TDI style IPv4 address
* Name = Pointer to WinSock style IPv4 name
*/
{
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 = ((LPSOCKADDR_IN)Name)->sin_port;
Address->Address[0].Address[0].in_addr = ((LPSOCKADDR_IN)Name)->sin_addr.S_un.S_addr;
UINT TaLengthOfTransportAddress( PTRANSPORT_ADDRESS Addr ) {
UINT AddrLen = 2 * sizeof( ULONG ) + Addr->Address[0].AddressLength;
AFD_DbgPrint(MID_TRACE,("AddrLen %x\n", AddrLen));
return AddrLen;
}
NTSTATUS TdiBuildAddress(
PTA_ADDRESS Address,
LPSOCKADDR Name)
/*
* FUNCTION: Builds a TDI style address
* ARGUMENTS:
* Address = Address of buffer to place TDI style address
* Name = Pointer to WinSock style name
* RETURNS:
* Status of operation
*/
{
NTSTATUS Status = STATUS_SUCCESS;
switch (Name->sa_family) {
case AF_INET:
TdiBuildAddressIPv4((PTA_IP_ADDRESS)Address,Name);
break;
/* FIXME: More to come */
default:
AFD_DbgPrint(MID_TRACE, ("Unknown address family (%d).\n", Name->sa_family));
Status = STATUS_INVALID_PARAMETER;
}
return Status;
VOID TaCopyAddressInPlace( PTA_ADDRESS Target,
PTA_ADDRESS Source ) {
UINT AddrLen = TaLengthOfAddress( Source );
RtlCopyMemory( Target, Source, AddrLen );
}
NTSTATUS TdiBuildName(
LPSOCKADDR Name,
PTA_ADDRESS Address)
/*
* FUNCTION: Builds a WinSock style address
* ARGUMENTS:
* Name = Address of buffer to place WinSock style name
* Address = Pointer to TDI style address
* RETURNS:
* Status of operation
*/
{
NTSTATUS Status = STATUS_SUCCESS;
switch (Address->AddressType) {
case TDI_ADDRESS_TYPE_IP:
Name->sa_family = AF_INET;
((LPSOCKADDR_IN)Name)->sin_port =
((PTDI_ADDRESS_IP)&Address->Address[0])->sin_port;
((LPSOCKADDR_IN)Name)->sin_addr.S_un.S_addr =
((PTDI_ADDRESS_IP)&Address->Address[0])->in_addr;
break;
/* FIXME: More to come */
default:
AFD_DbgPrint(MID_TRACE, ("Unknown TDI address type (%d).\n", Address->AddressType));
Status = STATUS_INVALID_PARAMETER;
}
return Status;
VOID TaCopyTransportAddressInPlace( PTRANSPORT_ADDRESS Target,
PTRANSPORT_ADDRESS Source ) {
UINT AddrLen = TaLengthOfTransportAddress( Source );
RtlCopyMemory( Target, Source, AddrLen );
}
NTSTATUS TdiBuildConnectionInfoInPlace
( PTDI_CONNECTION_INFORMATION ConnInfo,
LPSOCKADDR Name )
/*
* FUNCTION: Builds a TDI connection information structure
* ARGUMENTS:
* ConnectionInfo = Address of buffer to place connection information
* Name = Pointer to WinSock style name
* RETURNS:
* Status of operation
*/
{
ULONG TdiAddressSize;
PTRANSPORT_ADDRESS TaCopyTransportAddress( PTRANSPORT_ADDRESS OtherAddress ) {
UINT AddrLen;
PTRANSPORT_ADDRESS A;
TdiAddressSize = TdiAddressSizeFromName(Name);
ASSERT(OtherAddress->TAAddressCount == 1);
AddrLen = TaLengthOfTransportAddress( OtherAddress );
A = ExAllocatePool( NonPagedPool, AddrLen );
RtlZeroMemory(ConnInfo,
sizeof(TDI_CONNECTION_INFORMATION) +
TdiAddressSize);
if( A )
TaCopyTransportAddressInPlace( A, OtherAddress );
ConnInfo->OptionsLength = sizeof(ULONG);
ConnInfo->RemoteAddressLength = TdiAddressSize;
ConnInfo->RemoteAddress = (PVOID)
(((PCHAR)ConnInfo) + sizeof(TDI_CONNECTION_INFORMATION));
TdiBuildAddress(ConnInfo->RemoteAddress, Name);
return STATUS_SUCCESS;
return A;
}
NTSTATUS TdiBuildConnectionInfo(
PTDI_CONNECTION_INFORMATION *ConnectionInfo,
LPSOCKADDR Name)
/*
* FUNCTION: Builds a TDI connection information structure
* ARGUMENTS:
* ConnectionInfo = Address of buffer pointer to allocate connection
* information on
* Name = Pointer to WinSock style name
* RETURNS:
* Status of operation
*/
{
PTDI_CONNECTION_INFORMATION ConnInfo;
ULONG TdiAddressSize;
NTSTATUS Status;
TdiAddressSize = TdiAddressSizeFromName(Name);
ConnInfo = (PTDI_CONNECTION_INFORMATION)
ExAllocatePool(NonPagedPool,
sizeof(TDI_CONNECTION_INFORMATION) +
TdiAddressSize);
if (!ConnInfo)
return STATUS_INSUFFICIENT_RESOURCES;
Status = TdiBuildConnectionInfoInPlace( ConnInfo, Name );
if( !NT_SUCCESS(Status) )
ExFreePool( ConnInfo );
else
*ConnectionInfo = ConnInfo;
return Status;
}
NTSTATUS TdiBuildNullConnectionInfoInPlace
( PTDI_CONNECTION_INFORMATION ConnInfo,
@ -204,8 +76,8 @@ NTSTATUS TdiBuildNullConnectionInfoInPlace
TdiAddressSize = TdiAddressSizeFromType(Type);
RtlZeroMemory(ConnInfo,
sizeof(TDI_CONNECTION_INFORMATION) +
TdiAddressSize);
sizeof(TDI_CONNECTION_INFORMATION) +
TdiAddressSize);
ConnInfo->OptionsLength = sizeof(ULONG);
ConnInfo->RemoteAddressLength = 0;
@ -235,8 +107,8 @@ NTSTATUS TdiBuildNullConnectionInfo
ConnInfo = (PTDI_CONNECTION_INFORMATION)
ExAllocatePool(NonPagedPool,
sizeof(TDI_CONNECTION_INFORMATION) +
TdiAddressSize);
sizeof(TDI_CONNECTION_INFORMATION) +
TdiAddressSize);
if (!ConnInfo)
return STATUS_INSUFFICIENT_RESOURCES;
@ -247,13 +119,44 @@ NTSTATUS TdiBuildNullConnectionInfo
else
*ConnectionInfo = ConnInfo;
ConnInfo->RemoteAddress = (PTA_ADDRESS)&ConnInfo[1];
ConnInfo->RemoteAddressLength = TdiAddressSize;
return Status;
}
NTSTATUS
TdiBuildConnectionInfoInPlace
( PTDI_CONNECTION_INFORMATION ConnectionInfo,
PTA_ADDRESS Address ) {
NTSTATUS Status = STATUS_SUCCESS;
RtlCopyMemory( ConnectionInfo->RemoteAddress,
Address,
ConnectionInfo->RemoteAddressLength );
return Status;
}
NTSTATUS
TdiBuildConnectionInfo
( PTDI_CONNECTION_INFORMATION *ConnectionInfo,
PTA_ADDRESS Address ) {
NTSTATUS Status = TdiBuildNullConnectionInfo( ConnectionInfo,
Address->AddressType );
if( NT_SUCCESS(Status) )
TdiBuildConnectionInfoInPlace( *ConnectionInfo, Address );
return Status;
}
NTSTATUS
TdiBuildConnectionInfoPair
( PTDI_CONNECTION_INFO_PAIR ConnectionInfo,
LPSOCKADDR From, LPSOCKADDR To )
PTA_ADDRESS From, PTA_ADDRESS To )
/*
* FUNCTION: Fill a TDI_CONNECTION_INFO_PAIR struct will the two addresses
* given.
@ -266,11 +169,11 @@ TdiBuildConnectionInfoPair
*/
{
PCHAR LayoutFrame;
DWORD SizeOfEntry;
UINT SizeOfEntry;
ULONG TdiAddressSize;
/* FIXME: Get from socket information */
TdiAddressSize = TdiAddressSizeFromName(From);
TdiAddressSize = TdiAddressSizeFromType(From->AddressType);
SizeOfEntry = TdiAddressSize + sizeof(TDI_CONNECTION_INFORMATION);
LayoutFrame = (PCHAR)ExAllocatePool(NonPagedPool, 2 * SizeOfEntry);
@ -282,18 +185,20 @@ TdiBuildConnectionInfoPair
RtlZeroMemory( LayoutFrame, 2 * SizeOfEntry );
PTDI_CONNECTION_INFORMATION
{
PTDI_CONNECTION_INFORMATION
FromTdiConn = (PTDI_CONNECTION_INFORMATION)LayoutFrame,
ToTdiConn = (PTDI_CONNECTION_INFORMATION)LayoutFrame + SizeOfEntry;
if (From != NULL) {
if (From != NULL) {
TdiBuildConnectionInfoInPlace( FromTdiConn, From );
} else {
} else {
TdiBuildNullConnectionInfoInPlace( FromTdiConn,
From->sa_family );
}
From->AddressType );
}
TdiBuildConnectionInfoInPlace( ToTdiConn, To );
TdiBuildConnectionInfoInPlace( ToTdiConn, To );
}
return STATUS_SUCCESS;
}

View file

@ -0,0 +1,269 @@
/* $Id: write.c,v 1.2 2004/07/18 22:49:17 arty Exp $
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel
* FILE: drivers/net/afd/afd/write.c
* PURPOSE: Ancillary functions driver
* PROGRAMMER: Art Yerkes (ayerkes@speakeasy.net)
* UPDATE HISTORY:
* 20040708 Created
*/
#include "afd.h"
#include "tdi_proto.h"
#include "tdiconn.h"
#include "debug.h"
NTSTATUS DDKAPI SendComplete
( PDEVICE_OBJECT DeviceObject,
PIRP Irp,
PVOID Context ) {
NTSTATUS Status = Irp->IoStatus.Status;
PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation(Irp);
PAFD_FCB FCB = (PAFD_FCB)Context;
PLIST_ENTRY NextIrpEntry;
PIRP NextIrp = NULL;
PIO_STACK_LOCATION NextIrpSp;
PAFD_SEND_INFO SendReq;
PAFD_MAPBUF Map;
UINT TotalBytesCopied = 0, SpaceAvail, i, CopySize = 0;
AFD_DbgPrint(MID_TRACE,("Called, status %x, %d bytes used\n",
Irp->IoStatus.Status,
Irp->IoStatus.Information));
if( !SocketAcquireStateLock( FCB ) ) return Status;
if( !NT_SUCCESS(Status) ) {
/* Complete all following send IRPs with error */
while( !IsListEmpty( &FCB->PendingIrpList[FUNCTION_SEND] ) ) {
NextIrpEntry =
RemoveHeadList(&FCB->PendingIrpList[FUNCTION_SEND]);
NextIrp =
CONTAINING_RECORD(NextIrpEntry, IRP, Tail.Overlay.ListEntry);
NextIrpSp = IoGetCurrentIrpStackLocation( NextIrp );
SendReq = NextIrpSp->Parameters.DeviceIoControl.Type3InputBuffer;
UnlockBuffers( SendReq->BufferArray,
SendReq->BufferCount );
NextIrp->IoStatus.Status = Status;
NextIrp->IoStatus.Information = 0;
IoCompleteRequest( NextIrp, IO_NETWORK_INCREMENT );
}
SocketStateUnlock( FCB );
return STATUS_SUCCESS;
}
RtlMoveMemory( FCB->Send.Window,
FCB->Send.Window + FCB->Send.BytesUsed,
FCB->Send.BytesUsed - Irp->IoStatus.Information );
FCB->Send.BytesUsed -= Irp->IoStatus.Information;
if( !FCB->Send.BytesUsed &&
!IsListEmpty( &FCB->PendingIrpList[FUNCTION_SEND] ) &&
NT_SUCCESS(Status) ) {
NextIrpEntry =
RemoveHeadList(&FCB->PendingIrpList[FUNCTION_RECV]);
NextIrp =
CONTAINING_RECORD(NextIrpEntry, IRP, Tail.Overlay.ListEntry);
NextIrpSp = IoGetCurrentIrpStackLocation( NextIrp );
SendReq = NextIrpSp->Parameters.DeviceIoControl.Type3InputBuffer;
Map = (PAFD_MAPBUF)(SendReq->BufferArray + SendReq->BufferCount);
AFD_DbgPrint(MID_TRACE,("SendReq @ %x\n", SendReq));
SpaceAvail = FCB->Send.Size - FCB->Send.BytesUsed;
for( i = 0; FCB->Send.BytesUsed < FCB->Send.Content &&
i < SendReq->BufferCount; i++ ) {
Map[i].BufferAddress =
MmMapLockedPages( Map[i].Mdl, KernelMode );
CopySize = MIN( SpaceAvail,
SendReq->BufferArray[i].len );
RtlCopyMemory( FCB->Send.Window + FCB->Send.BytesUsed,
Map[i].BufferAddress,
CopySize );
MmUnmapLockedPages( Map[i].Mdl, KernelMode );
FCB->Send.BytesUsed += CopySize;
TotalBytesCopied += CopySize;
SpaceAvail -= CopySize;
}
}
/* Some data is still waiting */
if( FCB->Send.BytesUsed ) {
FCB->PollState &= ~AFD_EVENT_SEND;
Status = TdiSend( &FCB->SendIrp.InFlightRequest,
IrpSp->FileObject,
0,
FCB->Send.Window,
FCB->Send.BytesUsed,
&FCB->SendIrp.Iosb,
SendComplete,
FCB );
} else {
FCB->PollState |= AFD_EVENT_SEND;
PollReeval( FCB->DeviceExt, FCB->FileObject );
}
if( TotalBytesCopied > 0 ) {
UnlockBuffers( SendReq->BufferArray, SendReq->BufferCount );
if( Status == STATUS_PENDING )
Status = STATUS_SUCCESS;
AFD_DbgPrint(MID_TRACE,("Dismissing request: %x\n", Status));
return UnlockAndMaybeComplete( FCB, Status, Irp, TotalBytesCopied,
NULL, TRUE );
} else if( NextIrp ) {
AFD_DbgPrint(MID_TRACE,("Could not do any more with Irp %x\n",
NextIrp));
InsertHeadList( &FCB->PendingIrpList[FUNCTION_SEND],
&Irp->Tail.Overlay.ListEntry );
SocketStateUnlock( FCB );
}
return STATUS_SUCCESS;
}
NTSTATUS STDCALL
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, CopySize = 0,
SpaceAvail = 0, TotalBytesEncountered = 0;
AFD_DbgPrint(MID_TRACE,("Called on %x\n", FCB));
if( !SocketAcquireStateLock( FCB ) ) return LostSocket( Irp, FALSE );
if( !(SendReq = LockRequest( Irp, IrpSp )) )
return UnlockAndMaybeComplete
( FCB, STATUS_NO_MEMORY, Irp, TotalBytesCopied, NULL, FALSE );
AFD_DbgPrint(MID_TRACE,("Socket state %d\n", FCB->State));
if( FCB->State != SOCKET_STATE_CONNECTED ) {
AFD_DbgPrint(MID_TRACE,("Queuing request\n"));
return LeaveIrpUntilLater( FCB, Irp, FUNCTION_SEND );
}
AFD_DbgPrint(MID_TRACE,("We already have %d bytes waiting.\n",
FCB->Send.BytesUsed));
SendReq->BufferArray = LockBuffers( SendReq->BufferArray,
SendReq->BufferCount,
FALSE );
AFD_DbgPrint(MID_TRACE,("FCB->Send.BytesUsed = %d\n",
FCB->Send.BytesUsed));
if( !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++ ) {
CopySize = MIN( SpaceAvail,
SendReq->BufferArray[i].len );
TotalBytesEncountered += SendReq->BufferArray[i].len;
AFD_DbgPrint(MID_TRACE,("Copying Buffer %d, %x:%d to %x\n",
i,
SendReq->BufferArray[i].buf,
CopySize,
FCB->Send.Window + FCB->Send.BytesUsed));
RtlCopyMemory( FCB->Send.Window + FCB->Send.BytesUsed,
SendReq->BufferArray[i].buf,
CopySize );
FCB->Send.BytesUsed += CopySize;
TotalBytesCopied += CopySize;
SpaceAvail -= CopySize;
}
if( TotalBytesEncountered == 0 ) {
UnlockBuffers( SendReq->BufferArray, SendReq->BufferCount );
AFD_DbgPrint(MID_TRACE,("Empty send\n"));
return UnlockAndMaybeComplete
( FCB, Status, Irp, TotalBytesCopied, NULL, TRUE );
}
AFD_DbgPrint(MID_TRACE,("Completed %d bytes\n", TotalBytesCopied));
if( TotalBytesCopied > 0 ) {
UnlockBuffers( SendReq->BufferArray, SendReq->BufferCount );
Status = TdiSend( &FCB->SendIrp.InFlightRequest,
FCB->Connection.Object,
0,
FCB->Send.Window,
FCB->Send.BytesUsed,
&FCB->SendIrp.Iosb,
SendComplete,
FCB );
if( Status == STATUS_PENDING )
Status = STATUS_SUCCESS;
AFD_DbgPrint(MID_TRACE,("Dismissing request: %x\n", Status));
return UnlockAndMaybeComplete
( FCB, Status, Irp, TotalBytesCopied, NULL, TRUE );
}
}
AFD_DbgPrint(MID_TRACE,("Queuing request\n"));
return LeaveIrpUntilLater( FCB, Irp, FUNCTION_SEND );
}
NTSTATUS STDCALL
AfdPacketSocketWriteData(PDEVICE_OBJECT DeviceObject, PIRP Irp,
PIO_STACK_LOCATION IrpSp) {
NTSTATUS Status = STATUS_SUCCESS;
PFILE_OBJECT FileObject = IrpSp->FileObject;
PAFD_FCB FCB = FileObject->FsContext;
PAFD_SEND_INFO_UDP SendReq;
AFD_DbgPrint(MID_TRACE,("Called on %x\n", FCB));
if( !SocketAcquireStateLock( FCB ) ) return LostSocket( Irp, FALSE );
if( !(SendReq = LockRequest( Irp, IrpSp )) )
return UnlockAndMaybeComplete
( FCB, STATUS_NO_MEMORY, Irp, 0, NULL, FALSE );
/* Check the size of the Address given ... */
Status = TdiSendDatagram
( &FCB->SendIrp.InFlightRequest,
FCB->AddressFile.Object,
SendReq->BufferArray[0].buf,
SendReq->BufferArray[0].len,
SendReq->RemoteAddress,
&FCB->SendIrp.Iosb,
NULL,
NULL );
if( Status == STATUS_PENDING ) Status = STATUS_SUCCESS;
AFD_DbgPrint(MID_TRACE,("Dismissing request: %x\n", Status));
return UnlockAndMaybeComplete
( FCB, Status, Irp, SendReq->BufferArray[0].len, NULL, TRUE );
}

View file

@ -0,0 +1,47 @@
ActivePoll -> Timer, Dpc, Handles
FCB -> Polls Involved In ...
What poll needs to do:
Accumulate:
for each fcb
If error is set, check error condition on fcb on entry
If writable is set, check fcb on entry for zero send content
If readable is set, check fcb has nonzero read content
If any handle was not valid, complete fail
If any of the above checks were true, complete success
Otherwise:
make an active poll object
for each fcb, make a poll entry
chain the poll entry to the fcb
set summary bits in fcb state for polling (what must be polled)
chain the active poll object to the device ext
set timer and dpc
pending
complete select:
for each fcb
find the poll entry in the fcb and unchain it
rescan poll bits for this fcb
get irp from poll object, and deallocate poll object
complete irp
select timeout:
Find the poll object in the device ext chain and unchain it
complete select with timeout
fcb send complete and connect complete:
if no more send irps and send bit set in summary
find each poll entry with send bit set and complete select with (1) on it
fcb recv complete:
if fcb has recv data and recv bit set in summary
find each poll entry with recv bit set and complete select with (1) on it

View file

@ -1,423 +1,287 @@
/*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS Ancillary Function Driver
* FILE: include/afd.h
* PURPOSE: Main driver header
/* $Id: afd.h,v 1.19 2004/07/18 22:49:17 arty Exp $
*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel
* FILE: drivers/net/afd/include/afd.h
* PURPOSE: Ancillary functions driver -- constants and structures
* PROGRAMMER: Art Yerkes (ayerkes@speakeasy.net)
* UPDATE HISTORY:
* 20040630 Created
*/
#ifndef __AFD_H
#define __AFD_H
#ifndef _AFD_H
#define _AFD_H
#include <ntddk.h>
#include <tdi.h>
#include <tdikrnl.h>
#include <tdiinfo.h>
#include <string.h>
#include <ndis.h>
#include <shared.h>
#ifndef _MSC_VER
#include <rosrtl/string.h>
#include <winsock2.h>
#include <ddk/ntddk.h>
#include <ddk/ntifs.h>
#include <ddk/tdiinfo.h>
#include <ddk/tdikrnl.h>
#include <afd/shared.h>
#include <debug.h>
#include <ddk/tdi.h>
#include <ddk/ndis.h>
#include <tcpmisc.h>
#include <tcpioctl.h>
#else
#include <ntdef.h>
#define STDCALL
#endif
#define IP_MIB_STATS_ID 1
#define IP_MIB_ADDRTABLE_ENTRY_ID 0x102
#ifndef MIN
#define MIN(x,y) (((x)<(y))?(x):(y))
#endif
/* Forward declarations */
struct _AFDFCB;
#define SOCKET_STATE_INVALID_TRANSITION ((DWORD)-1)
#define SOCKET_STATE_CREATED 0
#define SOCKET_STATE_BOUND 1
#define SOCKET_STATE_CONNECTING 2
#define SOCKET_STATE_CONNECTED 3
#define SOCKET_STATE_LISTENING 4
#define SOCKET_STATE_MASK 0x0000ffff
#define SOCKET_STATE_LOCKED 0x40000000
#define SOCKET_STATE_NEW 0x80000000
#define SOCKET_STATE_CLOSED 0x00000100
typedef struct _DEVICE_EXTENSION {
PDEVICE_OBJECT StorageDevice;
KSPIN_LOCK FCBListLock;
LIST_ENTRY FCBListHead;
} DEVICE_EXTENSION, *PDEVICE_EXTENSION;
#define FUNCTION_CONNECT 0
#define FUNCTION_RECV 1
#define FUNCTION_RECV_DATAGRAM 2
#define FUNCTION_SEND 3
#define FUNCTION_CLOSE 4
#define MAX_FUNCTIONS 5
/* Context Control Block structure */
typedef struct _AFDCCB {
struct _AFDFCB *FCB;
LIST_ENTRY ListEntry;
PFILE_OBJECT FileObject;
ULONG Flags;
LARGE_INTEGER CurrentByteOffset;
} AFDCCB, *PAFDCCB;
#define IN_FLIGHT_REQUESTS 3
/* Flags for CCB structure */
#define CCB_CLEANED 0x00000001
#define DEFAULT_SEND_WINDOW_SIZE 16384
#define DEFAULT_RECEIVE_WINDOW_SIZE 16384
typedef struct _FsdNTRequiredFCB {
FSRTL_COMMON_FCB_HEADER CommonFCBHeader;
SECTION_OBJECT_POINTERS SectionObject;
ERESOURCE MainResource;
ERESOURCE PagingIoResource;
} FsdNTRequiredFCB, *PFsdNTRequiredFCB;
#define SGID_CONNECTIONLESS 1 /* XXX Find this flag */
typedef struct _AFDFCB {
FsdNTRequiredFCB NTRequiredFCB;
LIST_ENTRY ListEntry;
BOOL CommandChannel;
PDEVICE_EXTENSION DeviceExt;
SHARE_ACCESS ShareAccess;
ULONG ReferenceCount;
ULONG OpenHandleCount;
HANDLE TdiAddressObjectHandle;
PFILE_OBJECT TdiAddressObject;
HANDLE TdiConnectionObjectHandle;
PFILE_OBJECT TdiConnectionObject;
LIST_ENTRY CCBListHead;
INT AddressFamily;
INT SocketType;
INT Protocol;
SOCKADDR SocketName;
PVOID HelperContext;
DWORD NotificationEvents;
UNICODE_STRING TdiDeviceName;
DWORD State;
PVOID SendBuffer;
LIST_ENTRY ReceiveQueue;
KSPIN_LOCK ReceiveQueueLock;
LIST_ENTRY ReadRequestQueue;
LIST_ENTRY ListenRequestQueue;
/* For WSAEventSelect() */
WSANETWORKEVENTS NetworkEvents;
PKEVENT EventObject;
} AFDFCB, *PAFDFCB;
typedef struct _AFD_MAPBUF {
PVOID BufferAddress;
PMDL Mdl;
} AFD_MAPBUF, *PAFD_MAPBUF;
/* Socket states */
#define SOCKET_STATE_CREATED 0
#define SOCKET_STATE_BOUND 1
#define SOCKET_STATE_LISTENING 2
#define SOCKET_STATE_CONNECTED 3
typedef struct _AFD_DEVICE_EXTENSION {
PDEVICE_OBJECT DeviceObject;
LIST_ENTRY Polls;
KSPIN_LOCK Lock;
} AFD_DEVICE_EXTENSION, *PAFD_DEVICE_EXTENSION;
typedef struct _AFD_BUFFER {
LIST_ENTRY ListEntry;
WSABUF Buffer;
UINT Offset;
} AFD_BUFFER, *PAFD_BUFFER;
typedef struct _AFD_ACTIVE_POLL {
LIST_ENTRY ListEntry;
PIRP Irp;
PAFD_DEVICE_EXTENSION DeviceExt;
KDPC TimeoutDpc;
KTIMER Timer;
} AFD_ACTIVE_POLL, *PAFD_ACTIVE_POLL;
typedef struct _AFD_READ_REQUEST {
LIST_ENTRY ListEntry;
PIRP Irp;
PFILE_REQUEST_RECVFROM RecvFromRequest;
PFILE_REPLY_RECVFROM RecvFromReply;
} AFD_READ_REQUEST, *PAFD_READ_REQUEST;
typedef struct _IRP_LIST {
LIST_ENTRY ListEntry;
PIRP Irp;
} IRP_LIST, *PIRP_LIST;
typedef struct _AFD_LISTEN_REQUEST {
LIST_ENTRY ListEntry;
PAFDFCB Fcb;
PTDI_CONNECTION_INFORMATION RequestConnectionInfo;
IO_STATUS_BLOCK Iosb;
} AFD_LISTEN_REQUEST, *PAFD_LISTEN_REQUEST;
typedef struct _AFD_TDI_OBJECT {
PFILE_OBJECT Object;
HANDLE Handle;
} AFD_TDI_OBJECT, *PAFD_TDI_OBJECT;
typedef struct IPSNMP_INFO {
ULONG Forwarding;
ULONG DefaultTTL;
ULONG InReceives;
ULONG InHdrErrors;
ULONG InAddrErrors;
ULONG ForwDatagrams;
ULONG InUnknownProtos;
ULONG InDiscards;
ULONG InDelivers;
ULONG OutRequests;
ULONG RoutingDiscards;
ULONG OutDiscards;
ULONG OutNoRoutes;
ULONG ReasmTimeout;
ULONG ReasmReqds;
ULONG ReasmOks;
ULONG ReasmFails;
ULONG FragOks;
ULONG FragFails;
ULONG FragCreates;
ULONG NumIf;
ULONG NumAddr;
ULONG NumRoutes;
} IPSNMP_INFO, *PIPSNMP_INFO;
typedef struct _AFD_IN_FLIGHT_REQUEST {
PIRP InFlightRequest;
IO_STATUS_BLOCK Iosb;
PTDI_CONNECTION_INFORMATION ConnectionInfo;
} AFD_IN_FLIGHT_REQUEST, *PAFD_IN_FLIGHT_REQUEST;
typedef struct IPADDR_ENTRY {
ULONG Addr;
ULONG Index;
ULONG Mask;
ULONG BcastAddr;
ULONG ReasmSize;
USHORT Context;
USHORT Pad;
} IPADDR_ENTRY, *PIPADDR_ENTRY;
typedef struct _AFD_DATA_WINDOW {
PCHAR Window;
UINT BytesUsed, Size, Content;
} AFD_DATA_WINDOW, *PAFD_DATA_WINDOW;
typedef struct _AFD_STORED_DATAGRAM {
LIST_ENTRY ListEntry;
UINT Len;
PTA_ADDRESS Address;
CHAR Buffer[1];
} AFD_STORED_DATAGRAM, *PAFD_STORED_DATAGRAM;
#define TL_INSTANCE 0
typedef struct _AFD_FCB {
BOOLEAN Locked;
UINT State, Flags;
KIRQL OldIrql;
UINT LockCount;
PVOID CurrentThread;
KSPIN_LOCK SpinLock;
PFILE_OBJECT FileObject;
PAFD_DEVICE_EXTENSION DeviceExt;
BOOLEAN DelayedAccept;
PTRANSPORT_ADDRESS LocalAddress, RemoteAddress;
PTDI_CONNECTION_INFORMATION AddressFrom;
AFD_TDI_OBJECT AddressFile, Connection;
AFD_IN_FLIGHT_REQUEST ListenIrp, ReceiveIrp, SendIrp;
AFD_DATA_WINDOW Send, Recv;
FAST_MUTEX Mutex;
KEVENT StateLockedEvent;
UNICODE_STRING TdiDeviceName;
PVOID Context;
DWORD PollState;
UINT ContextSize;
PIRP PendingTdiIrp;
LIST_ENTRY PendingIrpList[MAX_FUNCTIONS];
LIST_ENTRY DatagramList;
} AFD_FCB, *PAFD_FCB;
/* IPv4 header format */
typedef struct IPv4_HEADER {
UCHAR VerIHL; /* 4-bit version, 4-bit Internet Header Length */
UCHAR Tos; /* Type of Service */
USHORT TotalLength; /* Total Length */
USHORT Id; /* Identification */
USHORT FlagsFragOfs; /* 3-bit Flags, 13-bit Fragment Offset */
UCHAR Ttl; /* Time to Live */
UCHAR Protocol; /* Protocol */
USHORT Checksum; /* Header Checksum */
ULONG SrcAddr; /* Source Address */
ULONG DstAddr; /* Destination Address */
} IPv4_HEADER, *PIPv4_HEADER;
/* bind.c */
NTSTATUS WarmSocketForBind( PAFD_FCB FCB );
NTSTATUS STDCALL
AfdBindSocket(PDEVICE_OBJECT DeviceObject, PIRP Irp,
PIO_STACK_LOCATION IrpSp);
/* IOCTL codes */
/* connect.c */
#define IOCTL_TCP_QUERY_INFORMATION_EX \
CTL_CODE(FILE_DEVICE_NETWORK, 0, METHOD_NEITHER, FILE_ANY_ACCESS)
NTSTATUS WarmSocketForConnection( PAFD_FCB FCB );
NTSTATUS STDCALL
AfdStreamSocketConnect(PDEVICE_OBJECT DeviceObject, PIRP Irp,
PIO_STACK_LOCATION IrpSp);
#define IOCTL_TCP_SET_INFORMATION_EX \
CTL_CODE(FILE_DEVICE_NETWORK, 1, METHOD_BUFFERED, FILE_WRITE_ACCESS)
/* context.c */
NTSTATUS STDCALL
AfdGetContext( PDEVICE_OBJECT DeviceObject, PIRP Irp,
PIO_STACK_LOCATION IrpSp );
NTSTATUS STDCALL
AfdSetContext( PDEVICE_OBJECT DeviceObject, PIRP Irp,
PIO_STACK_LOCATION IrpSp );
#ifdef i386
/* info.c */
/* DWORD network to host byte order conversion for i386 */
#define DN2H(dw) \
((((dw) & 0xFF000000L) >> 24) | \
(((dw) & 0x00FF0000L) >> 8) | \
(((dw) & 0x0000FF00L) << 8) | \
(((dw) & 0x000000FFL) << 24))
NTSTATUS STDCALL
AfdGetInfo( PDEVICE_OBJECT DeviceObject, PIRP Irp,
PIO_STACK_LOCATION IrpSp );
/* DWORD host to network byte order conversion for i386 */
#define DH2N(dw) \
((((dw) & 0xFF000000L) >> 24) | \
(((dw) & 0x00FF0000L) >> 8) | \
(((dw) & 0x0000FF00L) << 8) | \
(((dw) & 0x000000FFL) << 24))
/* listen.c */
/* WORD network to host order conversion for i386 */
#define WN2H(w) \
((((w) & 0xFF00) >> 8) | \
(((w) & 0x00FF) << 8))
NTSTATUS AfdListenSocket(PDEVICE_OBJECT DeviceObject, PIRP Irp,
PIO_STACK_LOCATION IrpSp);
/* WORD host to network byte order conversion for i386 */
#define WH2N(w) \
((((w) & 0xFF00) >> 8) | \
(((w) & 0x00FF) << 8))
/* lock.c */
#else /* i386 */
PAFD_WSABUF LockBuffers( PAFD_WSABUF Buf, UINT Count, BOOLEAN Write );
VOID UnlockBuffers( PAFD_WSABUF Buf, UINT Count );
UINT SocketAcquireStateLock( PAFD_FCB FCB );
NTSTATUS DDKAPI UnlockAndMaybeComplete
( PAFD_FCB FCB, NTSTATUS Status, PIRP Irp,
UINT Information,
PIO_COMPLETION_ROUTINE Completion,
BOOL ShouldUnlockIrp );
VOID SocketStateUnlock( PAFD_FCB FCB );
NTSTATUS LostSocket( PIRP Irp, BOOL ShouldUnlockIrp );
PVOID LockRequest( PIRP Irp, PIO_STACK_LOCATION IrpSp );
VOID UnlockRequest( PIRP Irp, PIO_STACK_LOCATION IrpSp );
/* DWORD network to host byte order conversion for other architectures */
#define DN2H(dw) \
(dw)
/* main.c */
/* DWORD host to network byte order conversion for other architectures */
#define DH2N(dw) \
(dw)
VOID OskitDumpBuffer( PCHAR Buffer, UINT Len );
NTSTATUS LeaveIrpUntilLater( PAFD_FCB FCB, PIRP Irp, UINT Function );
/* WORD network to host order conversion for other architectures */
#define WN2H(w) \
(w)
/* read.c */
/* WORD host to network byte order conversion for other architectures */
#define WH2N(w) \
(w)
#endif /* i386 */
extern NPAGED_LOOKASIDE_LIST BufferLookasideList;
extern NPAGED_LOOKASIDE_LIST ReadRequestLookasideList;
extern NPAGED_LOOKASIDE_LIST ListenRequestLookasideList;
/* Prototypes from dispatch.c */
NTSTATUS AfdDispBind(
PIRP Irp,
PIO_STACK_LOCATION IrpSp);
NTSTATUS AfdDispListen(
PIRP Irp,
PIO_STACK_LOCATION IrpSp);
NTSTATUS AfdDispSendTo(
PIRP Irp,
PIO_STACK_LOCATION IrpSp);
NTSTATUS AfdDispRecvFrom(
PIRP Irp,
PIO_STACK_LOCATION IrpSp);
NTSTATUS AfdDispSelect(
PIRP Irp,
PIO_STACK_LOCATION IrpSp);
NTSTATUS AfdDispEventSelect(
NTSTATUS DDKAPI ReceiveComplete
( PDEVICE_OBJECT DeviceObject,
PIRP Irp,
PIO_STACK_LOCATION IrpSp);
PVOID Context );
NTSTATUS AfdDispEnumNetworkEvents(
PIRP Irp,
PIO_STACK_LOCATION IrpSp);
NTSTATUS AfdDispRecv(
PIRP Irp,
PIO_STACK_LOCATION IrpSp);
NTSTATUS AfdDispSend(
PIRP Irp,
PIO_STACK_LOCATION IrpSp);
NTSTATUS AfdDispConnect(
NTSTATUS DDKAPI PacketSocketRecvComplete
( PDEVICE_OBJECT DeviceObject,
PIRP Irp,
PIO_STACK_LOCATION IrpSp);
PVOID Context );
NTSTATUS AfdDispGetName(
PIRP Irp,
PIO_STACK_LOCATION IrpSp);
NTSTATUS STDCALL
AfdConnectedSocketReadData(PDEVICE_OBJECT DeviceObject, PIRP Irp,
PIO_STACK_LOCATION IrpSp, BOOLEAN Short);
NTSTATUS STDCALL
AfdPacketSocketReadData(PDEVICE_OBJECT DeviceObject, PIRP Irp,
PIO_STACK_LOCATION IrpSp );
/* Prototypes from event.c */
/* select.c */
NTSTATUS AfdRegisterEventHandlers(
PAFDFCB FCB);
NTSTATUS STDCALL
AfdSelect( PDEVICE_OBJECT DeviceObject, PIRP Irp,
PIO_STACK_LOCATION IrpSp );
VOID PollReeval( PAFD_DEVICE_EXTENSION DeviceObject, PFILE_OBJECT FileObject );
NTSTATUS AfdDeregisterEventHandlers(
PAFDFCB FCB);
/* Prototypes from opnclose.c */
NTSTATUS STDCALL AfdCreate(
PDEVICE_OBJECT DeviceObject,
PIRP Irp);
NTSTATUS STDCALL AfdClose(
PDEVICE_OBJECT DeviceObject,
PIRP Irp);
/* Prototypes from rdwr.c */
NTSTATUS AfdEventReceiveDatagramHandler(
IN PVOID TdiEventContext,
IN LONG SourceAddressLength,
IN PVOID SourceAddress,
IN LONG OptionsLength,
IN PVOID Options,
IN ULONG ReceiveDatagramFlags,
IN ULONG BytesIndicated,
IN ULONG BytesAvailable,
OUT ULONG * BytesTaken,
IN PVOID Tsdu,
OUT PIRP * IoRequestPacket);
NTSTATUS STDCALL AfdRead(
PDEVICE_OBJECT DeviceObject,
PIRP Irp);
NTSTATUS STDCALL AfdWrite(
PDEVICE_OBJECT DeviceObject,
PIRP Irp);
/* Prototypes from routines.c */
VOID DumpName(
LPSOCKADDR Name);
/* Requires caller to hold the recv queue lock */
VOID TryToSatisfyRecvRequest( PAFDFCB FCB, BOOL Continuous );
ULONG WSABufferSize(
LPWSABUF Buffers,
DWORD BufferCount);
NTSTATUS MergeWSABuffers(
LPWSABUF Buffers,
DWORD BufferCount,
PVOID Destination,
ULONG MaxLength,
PULONG BytesCopied);
NTSTATUS FillWSABuffers(
PAFDFCB FCB,
LPWSABUF Buffers,
DWORD BufferCount,
PULONG BytesCopied,
BOOL Continuous);
VOID BuildIPv4Header(
PIPv4_HEADER IPHeader,
ULONG TotalSize,
ULONG Protocol,
PSOCKADDR SourceAddress,
PSOCKADDR DestinationAddress);
/* Prototypes from tdi.c */
NTSTATUS TdiCloseDevice(
HANDLE Handle,
PFILE_OBJECT FileObject);
NTSTATUS TdiOpenAddressFileIPv4(
PUNICODE_STRING DeviceName,
LPSOCKADDR Name,
PHANDLE AddressHandle,
PFILE_OBJECT *AddressObject);
/* tdi.c */
NTSTATUS TdiOpenAddressFile(
PUNICODE_STRING DeviceName,
LPSOCKADDR Name,
PHANDLE AddressHandle,
PFILE_OBJECT *AddressObject);
NTSTATUS TdiOpenConnectionEndpointFile(
PUNICODE_STRING DeviceName,
PHANDLE ConnectionHandle,
PFILE_OBJECT *ConnectionObject);
NTSTATUS TdiConnect(
PFILE_OBJECT ConnectionObject,
LPSOCKADDR RemoteAddress);
PUNICODE_STRING DeviceName,
PTRANSPORT_ADDRESS Name,
PHANDLE AddressHandle,
PFILE_OBJECT *AddressObject);
NTSTATUS TdiAssociateAddressFile(
HANDLE AddressHandle,
PFILE_OBJECT ConnectionObject);
NTSTATUS TdiListen(
PAFD_LISTEN_REQUEST Request,
NTSTATUS TdiListen
( PIRP *Irp,
PFILE_OBJECT ConnectionObject,
PTDI_CONNECTION_INFORMATION *RequestConnectionInfo,
PIO_STATUS_BLOCK Iosb,
PIO_COMPLETION_ROUTINE CompletionRoutine,
PVOID CompletionContext);
NTSTATUS TdiSetEventHandler(
PFILE_OBJECT FileObject,
LONG EventType,
PVOID Handler,
PVOID Context);
NTSTATUS TdiReceive
( PIRP *Irp,
PFILE_OBJECT ConnectionObject,
USHORT Flags,
PCHAR Buffer,
UINT BufferLength,
PIO_STATUS_BLOCK Iosb,
PIO_COMPLETION_ROUTINE CompletionRoutine,
PVOID CompletionContext);
NTSTATUS TdiQueryInformation(
PFILE_OBJECT FileObject,
LONG QueryType,
PMDL MdlBuffer);
NTSTATUS TdiSend
( PIRP *Irp,
PFILE_OBJECT ConnectionObject,
USHORT Flags,
PCHAR Buffer,
UINT BufferLength,
PIO_STATUS_BLOCK Iosb,
PIO_COMPLETION_ROUTINE CompletionRoutine,
PVOID CompletionContext);
NTSTATUS TdiQueryDeviceControl(
PFILE_OBJECT FileObject,
ULONG IoControlCode,
PVOID InputBuffer,
ULONG InputBufferLength,
PVOID OutputBuffer,
ULONG OutputBufferLength,
PULONG Return);
NTSTATUS TdiQueryInformationEx(
PFILE_OBJECT FileObject,
ULONG Entity,
ULONG Instance,
ULONG Class,
ULONG Type,
ULONG Id,
PVOID OutputBuffer,
PULONG OutputLength);
NTSTATUS TdiQueryAddress(
PFILE_OBJECT FileObject,
PULONG Address);
NTSTATUS TdiSend(
PFILE_OBJECT TransportObject,
PVOID Buffer,
ULONG BufferSize);
NTSTATUS TdiReceiveDatagram(
PIRP *Irp,
PFILE_OBJECT TransportObject,
USHORT Flags,
PCHAR Buffer,
UINT BufferLength,
PTDI_CONNECTION_INFORMATION From,
PIO_STATUS_BLOCK Iosb,
PIO_COMPLETION_ROUTINE CompletionRoutine,
PVOID CompletionContext);
NTSTATUS TdiSendDatagram(
PFILE_OBJECT TransportObject,
LPSOCKADDR Address,
PMDL Mdl,
ULONG BufferSize);
PIRP *Irp,
PFILE_OBJECT TransportObject,
PCHAR Buffer,
UINT BufferLength,
PTDI_CONNECTION_INFORMATION To,
PIO_STATUS_BLOCK Iosb,
PIO_COMPLETION_ROUTINE CompletionRoutine,
PVOID CompletionContext);
#endif /*__AFD_H */
/* write.c */
/* EOF */
NTSTATUS STDCALL
AfdConnectedSocketWriteData(PDEVICE_OBJECT DeviceObject, PIRP Irp,
PIO_STACK_LOCATION IrpSp, BOOLEAN Short);
NTSTATUS STDCALL
AfdPacketSocketWriteData(PDEVICE_OBJECT DeviceObject, PIRP Irp,
PIO_STACK_LOCATION IrpSp);
#endif/*_AFD_H*/

View file

@ -0,0 +1,17 @@
#ifndef _TDI_PROTO_H
#define _TDI_PROTO_H
NTSTATUS TdiConnect( PIRP *PendingIrp,
PFILE_OBJECT ConnectionObject,
PTRANSPORT_ADDRESS RemoteAddress,
PIO_COMPLETION_ROUTINE CompletionRoutine,
PVOID CompletionContext );
NTSTATUS TdiOpenConnectionEndpointFile(PUNICODE_STRING DeviceName,
PHANDLE ConnectionHandle,
PFILE_OBJECT *ConnectionObject);
NTSTATUS TdiCloseDevice(HANDLE Handle,
PFILE_OBJECT FileObject);
#endif/*_TDI_PROTO_H*/

View file

@ -2,27 +2,30 @@
#define _TDICONN_H
#include <afd.h>
#ifdef _MSC_VER
#include <ntddtdi.h>
#endif
typedef VOID *PTDI_CONNECTION_INFO_PAIR;
DWORD TdiAddressSizeFromType( ULONG Type );
DWORD TdiAddressSizeFromName( LPSOCKADDR Name );
VOID TdiBuildAddressIPv4( PTA_IP_ADDRESS Address,
LPSOCKADDR Name );
NTSTATUS TdiBuildAddress( PTA_ADDRESS Address,
LPSOCKADDR Name );
NTSTATUS TdiBuildName( LPSOCKADDR Name,
PTA_ADDRESS Address );
PTRANSPORT_ADDRESS TaCopyTransportAddress( PTRANSPORT_ADDRESS OtherAddress );
UINT TaLengthOfAddress( PTA_ADDRESS Addr );
UINT TaLengthOfTransportAddress( PTRANSPORT_ADDRESS Addr );
VOID TaCopyAddressInPlace( PTA_ADDRESS Target, PTA_ADDRESS Source );
VOID TaCopyTransportAddressInPlace( PTRANSPORT_ADDRESS Target,
PTRANSPORT_ADDRESS Source );
UINT TdiAddressSizeFromType( UINT Type );
UINT TdiAddressSizeFromName( PTRANSPORT_ADDRESS Name );
NTSTATUS TdiBuildConnectionInfoInPlace
( PTDI_CONNECTION_INFORMATION ConnInfo, LPSOCKADDR Name );
( PTDI_CONNECTION_INFORMATION ConnInfo, PTA_ADDRESS Name );
NTSTATUS TdiBuildConnectionInfo
( PTDI_CONNECTION_INFORMATION *ConnectionInfo, LPSOCKADDR Name );
( PTDI_CONNECTION_INFORMATION *ConnectionInfo, PTA_ADDRESS Name );
NTSTATUS TdiBuildNullConnectionInfoToPlace
( PTDI_CONNECTION_INFORMATION ConnInfo, ULONG Type );
NTSTATUS TdiBuildNullConnectionInfo
( PTDI_CONNECTION_INFORMATION *ConnectionInfo, ULONG Type );
NTSTATUS TdiBuildConnectionInfoPair
( PTDI_CONNECTION_INFO_PAIR ConnectionInfo, LPSOCKADDR From, LPSOCKADDR To );
( PTDI_CONNECTION_INFO_PAIR ConnectionInfo, PTA_ADDRESS From, PTA_ADDRESS To );
PTA_ADDRESS TdiGetRemoteAddress( PTDI_CONNECTION_INFORMATION TdiConn );
#endif/*_TDICONN_H*/

View file

@ -1,4 +1,4 @@
# $Id: makefile,v 1.10 2004/03/02 18:18:13 navaraf Exp $
# $Id: makefile,v 1.11 2004/07/18 22:49:16 arty Exp $
PATH_TO_TOP = ../../..
@ -6,17 +6,21 @@ TARGET_TYPE = driver
TARGET_NAME = afd
TARGET_CFLAGS = -I./include -DDBG -D__USE_W32API -Werror -Wall
TARGET_CFLAGS = -I./include -I$(PATH_TO_TOP)/w32api/include/ddk -I$(PATH_TO_TOP)/include/afd -DDBG -D__USE_W32API -Werror -Wall
TARGET_OBJECTS = \
afd/afd.o \
afd/dispatch.o \
afd/event.o \
afd/opnclose.o \
afd/rdwr.o \
afd/routines.o \
afd/tdi.o \
afd/tdiconn.o
afd/bind.o \
afd/connect.o \
afd/context.o \
afd/info.o \
afd/listen.o \
afd/lock.o \
afd/main.o \
afd/read.o \
afd/select.o \
afd/tdi.o \
afd/tdiconn.o \
afd/write.o
include $(PATH_TO_TOP)/rules.mak

View file

@ -20,7 +20,7 @@
#include <info.h>
#include <memtrack.h>
//#define NDEBUG
#define NDEBUG
#ifndef NDEBUG
DWORD DebugTraceLevel = 0x7fffffff;

View file

@ -9,53 +9,64 @@
#include <msafd.h>
typedef struct _WSHELPER_DLL_ENTRIES {
PWSH_ADDRESS_TO_STRING lpWSHAddressToString;
PWSH_ENUM_PROTOCOLS lpWSHEnumProtocols;
PWSH_GET_BROADCAST_SOCKADDR lpWSHGetBroadcastSockaddr;
PWSH_GET_PROVIDER_GUID lpWSHGetProviderGuid;
PWSH_GET_SOCKADDR_TYPE lpWSHGetSockaddrType;
PWSH_GET_SOCKET_INFORMATION lpWSHGetSocketInformation;
PWSH_GET_WILDCARD_SOCKEADDR lpWSHGetWildcardSockaddr;
PWSH_GET_WINSOCK_MAPPING lpWSHGetWinsockMapping;
PWSH_GET_WSAPROTOCOL_INFO lpWSHGetWSAProtocolInfo;
PWSH_IOCTL lpWSHIoctl;
PWSH_JOIN_LEAF lpWSHJoinLeaf;
PWSH_NOTIFY lpWSHNotify;
PWSH_OPEN_SOCKET lpWSHOpenSocket;
PWSH_OPEN_SOCKET2 lpWSHOpenSocket2;
PWSH_SET_SOCKET_INFORMATION lpWSHSetSocketInformation;
PWSH_STRING_TO_ADDRESS lpWSHStringToAddress;
} WSHELPER_DLL_ENTRIES, *PWSHELPER_DLL_ENTRIES;
typedef struct _HELPER_DATA {
LIST_ENTRY Helpers;
LONG RefCount;
HANDLE hInstance;
INT MinWSAddressLength;
INT MaxWSAddressLength;
INT MinTDIAddressLength;
INT MaxTDIAddressLength;
BOOLEAN UseDelayedAcceptance;
PWINSOCK_MAPPING Mapping;
PWSH_OPEN_SOCKET WSHOpenSocket;
PWSH_OPEN_SOCKET2 WSHOpenSocket2;
PWSH_JOIN_LEAF WSHJoinLeaf;
PWSH_NOTIFY WSHNotify;
PWSH_GET_SOCKET_INFORMATION WSHGetSocketInformation;
PWSH_SET_SOCKET_INFORMATION WSHSetSocketInformation;
PWSH_GET_SOCKADDR_TYPE WSHGetSockaddrType;
PWSH_GET_WILDCARD_SOCKEADDR WSHGetWildcardSockaddr;
PWSH_GET_BROADCAST_SOCKADDR WSHGetBroadcastSockaddr;
PWSH_ADDRESS_TO_STRING WSHAddressToString;
PWSH_STRING_TO_ADDRESS WSHStringToAddress;
PWSH_IOCTL WSHIoctl;
WCHAR TransportName[1];
} HELPER_DATA, *PHELPER_DATA;
typedef struct _WSHELPER_DLL {
LIST_ENTRY ListEntry;
CRITICAL_SECTION Lock;
WCHAR LibraryName[MAX_PATH];
HMODULE hModule;
WSHELPER_DLL_ENTRIES EntryTable;
PWINSOCK_MAPPING Mapping;
} WSHELPER_DLL, *PWSHELPER_DLL;
int SockLoadHelperDll(
PWSTR TransportName,
PWINSOCK_MAPPING Mapping,
PHELPER_DATA *HelperDllData
);
int SockLoadTransportMapping(
PWSTR TransportName,
PWINSOCK_MAPPING *Mapping
);
PWSHELPER_DLL CreateHelperDLL(
LPWSTR LibraryName);
int SockLoadTransportList(
PWSTR *TransportList
);
INT DestroyHelperDLL(
PWSHELPER_DLL HelperDLL);
BOOL SockIsTripleInMapping(
PWINSOCK_MAPPING Mapping,
INT AddressFamily,
INT SocketType,
INT Protocol
);
PWSHELPER_DLL LocateHelperDLL(
LPWSAPROTOCOL_INFOW lpProtocolInfo);
INT LoadHelperDLL(
PWSHELPER_DLL HelperDLL);
INT UnloadHelperDLL(
PWSHELPER_DLL HelperDLL);
VOID CreateHelperDLLDatabase(VOID);
VOID DestroyHelperDLLDatabase(VOID);
int SockGetTdiName(
PINT AddressFamily,
PINT SocketType,
PINT Protocol,
GROUP Group,
DWORD Flags,
PUNICODE_STRING TransportName,
PVOID *HelperDllContext,
PHELPER_DATA *HelperDllData,
PDWORD Events
);
#endif /* __HELPERS_H */

View file

@ -11,23 +11,102 @@
#include <windows.h>
#include <ddk/ntddk.h>
#include <ddk/ntifs.h>
#include <wsahelp.h>
#include <wsahelp.h> /* comment for msvc */
//#include "C:\Programming\ReactOS\reactos\w32api\include\wsahelp.h" uncomment for MSVC
#include <winsock2.h>
#include <ws2spi.h>
#include <ddk/tdi.h>
//#include "C:\Programming\ReactOS\reactos\w32api\include\ddk\tdi.h" uncomment for MSVC
#include <ddk/tdi.h> /* comment for msvc */
#include <afd/shared.h>
#include <helpers.h>
#include <debug.h>
/*typedef _MSAFD_LISTEN_REQUEST
{
LIST_ENTRY ListEntry;
HANDLE Socket;
} MSAFD_LISTEN_REQUEST, *PMSAFD_LISTEN_REQUEST;*/
extern HANDLE GlobalHeap;
extern WSPUPCALLTABLE Upcalls;
extern LPWPUCOMPLETEOVERLAPPEDREQUEST lpWPUCompleteOverlappedRequest;
extern LIST_ENTRY SockHelpersListHead;
extern HANDLE SockEvent;
typedef enum _SOCKET_STATE {
SocketOpen,
SocketBound,
SocketBoundUdp,
SocketConnected,
SocketClosed
} SOCKET_STATE, *PSOCKET_STATE;
typedef struct _SOCK_SHARED_INFO {
SOCKET_STATE State;
INT AddressFamily;
INT SocketType;
INT Protocol;
INT SizeOfLocalAddress;
INT SizeOfRemoteAddress;
ULONG LingerData;
ULONG SendTimeout;
ULONG RecvTimeout;
ULONG SizeOfRecvBuffer;
ULONG SizeOfSendBuffer;
struct {
BOOLEAN Listening:1;
BOOLEAN Broadcast:1;
BOOLEAN Debug:1;
BOOLEAN OobInline:1;
BOOLEAN ReuseAddresses:1;
BOOLEAN ExclusiveAddressUse:1;
BOOLEAN NonBlocking:1;
BOOLEAN DontUseWildcard:1;
BOOLEAN ReceiveShutdown:1;
BOOLEAN SendShutdown:1;
BOOLEAN UseDelayedAcceptance:1;
BOOLEAN UseSAN:1;
}; // Flags
DWORD CreateFlags;
DWORD CatalogEntryId;
DWORD ServiceFlags1;
DWORD ProviderFlags;
GROUP GroupID;
DWORD GroupType;
INT GroupPriority;
INT SocketLastError;
HWND hWnd;
LONG Unknown;
DWORD SequenceNumber;
UINT wMsg;
LONG Event;
LONG DisabledEvents;
} SOCK_SHARED_INFO, *PSOCK_SHARED_INFO;
typedef struct _SOCKET_INFORMATION {
ULONG RefCount;
SOCKET Handle;
SOCK_SHARED_INFO SharedData;
DWORD HelperEvents;
PHELPER_DATA HelperData;
PVOID HelperContext;
PSOCKADDR LocalAddress;
PSOCKADDR RemoteAddress;
HANDLE TdiAddressHandle;
HANDLE TdiConnectionHandle;
PVOID AsyncData;
HANDLE EventObject;
LONG NetworkEvents;
CRITICAL_SECTION Lock;
PVOID SanData;
BOOL TrySAN;
SOCKADDR WSLocalAddress;
SOCKADDR WSRemoteAddress;
} SOCKET_INFORMATION, *PSOCKET_INFORMATION;
typedef struct _SOCKET_CONTEXT {
SOCK_SHARED_INFO SharedData;
ULONG SizeOfHelperData;
ULONG Padding;
SOCKADDR LocalAddress;
SOCKADDR RemoteAddress;
/* Plus Helper Data */
} SOCKET_CONTEXT, *PSOCKET_CONTEXT;
SOCKET
WSPAPI
@ -314,6 +393,28 @@ WSPStringToAddress(
IN OUT LPINT lpAddressLength,
OUT LPINT lpErrno);
PSOCKET_INFORMATION GetSocketStructure(
SOCKET Handle
);
int GetSocketInformation(
PSOCKET_INFORMATION Socket,
ULONG AfdInformationClass,
PULONG Ulong OPTIONAL,
PLARGE_INTEGER LargeInteger OPTIONAL
);
int SetSocketInformation(
PSOCKET_INFORMATION Socket,
ULONG AfdInformationClass,
PULONG Ulong OPTIONAL,
PLARGE_INTEGER LargeInteger OPTIONAL
);
int CreateContext(
PSOCKET_INFORMATION Socket
);
#endif /* __MSAFD_H */
/* EOF */

View file

@ -1,4 +1,4 @@
# $Id: makefile,v 1.14 2004/06/09 18:11:39 arty Exp $
# $Id: makefile,v 1.15 2004/07/18 22:49:17 arty Exp $
PATH_TO_TOP = ../..
@ -8,7 +8,7 @@ TARGET_NAME = msafd
TARGET_BASE = $(TARGET_BASE_LIB_MSAFD)
TARGET_SDKLIBS = ntdll.a kernel32.a
TARGET_SDKLIBS = ntdll.a kernel32.a advapi32.a
TARGET_CFLAGS = \
-I./include \

File diff suppressed because it is too large Load diff

View file

@ -4,58 +4,103 @@
* FILE: misc/event.c
* PURPOSE: Event handling
* PROGRAMMERS: Casper S. Hornstrup (chorns@users.sourceforge.net)
* Alex Ionescu (alex@relsoft.net)
* REVISIONS:
* CSH 15/06-2001 Created
* Alex 16/07/2004 - Complete Rewrite
*/
#include <msafd.h>
INT
WSPAPI
int
WSPAPI
WSPEventSelect(
IN SOCKET s,
IN WSAEVENT hEventObject,
IN LONG lNetworkEvents,
OUT LPINT lpErrno)
SOCKET Handle,
WSAEVENT hEventObject,
long lNetworkEvents,
LPINT lpErrno)
{
FILE_REQUEST_EVENTSELECT Request;
FILE_REPLY_EVENTSELECT Reply;
IO_STATUS_BLOCK Iosb;
NTSTATUS Status;
IO_STATUS_BLOCK IOSB;
AFD_EVENT_SELECT_INFO EventSelectInfo;
PSOCKET_INFORMATION Socket = NULL;
NTSTATUS Status;
ULONG BlockMode;
Request.hEventObject = hEventObject;
Request.lNetworkEvents = lNetworkEvents;
/* Get the Socket Structure associate to this Socket*/
Socket = GetSocketStructure(Handle);
Status = NtDeviceIoControlFile(
(HANDLE)s,
NULL,
NULL,
NULL,
&Iosb,
IOCTL_AFD_EVENTSELECT,
&Request,
sizeof(FILE_REQUEST_EVENTSELECT),
&Reply,
sizeof(FILE_REPLY_EVENTSELECT));
if (Status == STATUS_PENDING) {
AFD_DbgPrint(MAX_TRACE, ("Waiting on transport.\n"));
/* FIXME: Wait only for blocking sockets */
Status = NtWaitForSingleObject((HANDLE)s, FALSE, NULL);
}
/* Set Socket to Non-Blocking */
BlockMode = 1;
SetSocketInformation(Socket, AFD_INFO_BLOCKING_MODE, &BlockMode, NULL);
Socket->SharedData.NonBlocking = TRUE;
if (!NT_SUCCESS(Status)) {
AFD_DbgPrint(MAX_TRACE, ("Status (0x%X).\n", Status));
*lpErrno = WSAENOBUFS;
return SOCKET_ERROR;
/* Deactivate Async Select if there is one */
if (Socket->EventObject) {
//SockAsyncSelect(Socket, NULL, 0, 0);
}
AFD_DbgPrint(MAX_TRACE, ("Event select successful. Status (0x%X).\n",
Reply.Status));
/* Set Structure Info */
EventSelectInfo.EventObject = hEventObject;
EventSelectInfo.Events = 0;
*lpErrno = Reply.Status;
/* Set Events to wait for */
if (lNetworkEvents & FD_READ) {
EventSelectInfo.Events |= AFD_EVENT_RECEIVE;
}
return 0;
if (lNetworkEvents & FD_WRITE) {
EventSelectInfo.Events |= AFD_EVENT_SEND;
}
if (lNetworkEvents & FD_OOB) {
EventSelectInfo.Events |= AFD_EVENT_OOB_RECEIVE;
}
if (lNetworkEvents & FD_ACCEPT) {
EventSelectInfo.Events |= AFD_EVENT_ACCEPT;
}
if (lNetworkEvents & FD_CONNECT) {
EventSelectInfo.Events |= AFD_EVENT_CONNECT | AFD_EVENT_CONNECT_FAIL;
}
if (lNetworkEvents & FD_CLOSE) {
EventSelectInfo.Events |= AFD_EVENT_DISCONNECT | AFD_EVENT_ABORT;
}
if (lNetworkEvents & FD_QOS) {
EventSelectInfo.Events |= AFD_EVENT_QOS;
}
if (lNetworkEvents & FD_GROUP_QOS) {
EventSelectInfo.Events |= AFD_EVENT_GROUP_QOS;
}
/* Send IOCTL */
Status = NtDeviceIoControlFile((HANDLE)Handle,
SockEvent,
NULL,
NULL,
&IOSB,
IOCTL_AFD_EVENT_SELECT,
&EventSelectInfo,
sizeof(EventSelectInfo),
NULL,
0);
/* Wait for return */
if (Status == STATUS_PENDING) {
WaitForSingleObject(SockEvent, 0);
}
/* Set Socket Data*/
Socket->EventObject = hEventObject;
Socket->NetworkEvents = lNetworkEvents;
return 0;
}
INT
WSPAPI
WSPEnumNetworkEvents(
@ -64,42 +109,7 @@ WSPEnumNetworkEvents(
OUT LPWSANETWORKEVENTS lpNetworkEvents,
OUT LPINT lpErrno)
{
FILE_REQUEST_ENUMNETWORKEVENTS Request;
FILE_REPLY_ENUMNETWORKEVENTS Reply;
IO_STATUS_BLOCK Iosb;
NTSTATUS Status;
Request.hEventObject = hEventObject;
Status = NtDeviceIoControlFile(
(HANDLE)s,
NULL,
NULL,
NULL,
&Iosb,
IOCTL_AFD_ENUMNETWORKEVENTS,
&Request,
sizeof(FILE_REQUEST_ENUMNETWORKEVENTS),
&Reply,
sizeof(FILE_REPLY_ENUMNETWORKEVENTS));
if (Status == STATUS_PENDING) {
AFD_DbgPrint(MAX_TRACE, ("Waiting on transport.\n"));
/* FIXME: Wait only for blocking sockets */
Status = NtWaitForSingleObject((HANDLE)s, FALSE, NULL);
}
if (!NT_SUCCESS(Status)) {
AFD_DbgPrint(MAX_TRACE, ("Status (0x%X).\n", Status));
*lpErrno = WSAENOBUFS;
return SOCKET_ERROR;
}
AFD_DbgPrint(MAX_TRACE, ("EnumNetworkEvents successful. Status (0x%X).\n",
Reply.Status));
*lpErrno = Reply.Status;
return 0;
return 0;
}
/* EOF */

View file

@ -4,8 +4,10 @@
* FILE: misc/helpers.c
* PURPOSE: Helper DLL management
* PROGRAMMERS: Casper S. Hornstrup (chorns@users.sourceforge.net)
* Alex Ionescu (alex@relsoft.net)
* REVISIONS:
* CSH 01/09-2000 Created
* Alex 16/07/2004 - Complete Rewrite
*/
#include <msafd.h>
#include <helpers.h>
@ -13,275 +15,503 @@
CRITICAL_SECTION HelperDLLDatabaseLock;
LIST_ENTRY HelperDLLDatabaseListHead;
PWSHELPER_DLL CreateHelperDLL(
LPWSTR LibraryName)
INT
SockGetTdiName(
PINT AddressFamily,
PINT SocketType,
PINT Protocol,
GROUP Group,
DWORD Flags,
PUNICODE_STRING TransportName,
PVOID *HelperDllContext,
PHELPER_DATA *HelperDllData,
PDWORD Events)
{
PWSHELPER_DLL HelperDLL;
PHELPER_DATA HelperData;
PWSTR Transports;
PWSTR Transport;
PWINSOCK_MAPPING Mapping;
PLIST_ENTRY Helpers;
INT Status;
HelperDLL = HeapAlloc(GlobalHeap, 0, sizeof(WSHELPER_DLL));
if (!HelperDLL)
return NULL;
AFD_DbgPrint(MID_TRACE,("Called\n"));
InitializeCriticalSection(&HelperDLL->Lock);
HelperDLL->hModule = NULL;
lstrcpyW(HelperDLL->LibraryName, LibraryName);
HelperDLL->Mapping = NULL;
/* Check in our Current Loaded Helpers */
for (Helpers = SockHelpersListHead.Flink;
Helpers != &SockHelpersListHead;
Helpers = Helpers->Flink ) {
EnterCriticalSection(&HelperDLLDatabaseLock);
InsertTailList(&HelperDLLDatabaseListHead, &HelperDLL->ListEntry);
LeaveCriticalSection(&HelperDLLDatabaseLock);
HelperData = CONTAINING_RECORD(Helpers, HELPER_DATA, Helpers);
AFD_DbgPrint(MAX_TRACE, ("Returning helper at (0x%X).\n", HelperDLL));
/* See if this Mapping works for us */
if (SockIsTripleInMapping (HelperData->Mapping,
*AddressFamily,
*SocketType,
*Protocol)) {
return HelperDLL;
}
/* Call the Helper Dll function get the Transport Name */
if (HelperData->WSHOpenSocket2 == NULL ) {
INT DestroyHelperDLL(
PWSHELPER_DLL HelperDLL)
{
INT Status;
AFD_DbgPrint(MAX_TRACE, ("HelperDLL (0x%X).\n", HelperDLL));
EnterCriticalSection(&HelperDLLDatabaseLock);
RemoveEntryList(&HelperDLL->ListEntry);
LeaveCriticalSection(&HelperDLLDatabaseLock);
if (HelperDLL->hModule) {
Status = UnloadHelperDLL(HelperDLL);
} else {
Status = NO_ERROR;
}
if (HelperDLL->Mapping)
HeapFree(GlobalHeap, 0, HelperDLL->Mapping);
DeleteCriticalSection(&HelperDLL->Lock);
HeapFree(GlobalHeap, 0, HelperDLL);
return Status;
}
PWSHELPER_DLL LocateHelperDLL(
LPWSAPROTOCOL_INFOW lpProtocolInfo)
{
PLIST_ENTRY CurrentEntry;
PWSHELPER_DLL HelperDLL;
UINT i;
EnterCriticalSection(&HelperDLLDatabaseLock);
CurrentEntry = HelperDLLDatabaseListHead.Flink;
while (CurrentEntry != &HelperDLLDatabaseListHead) {
HelperDLL = CONTAINING_RECORD(CurrentEntry,
WSHELPER_DLL,
ListEntry);
for (i = 0; i < HelperDLL->Mapping->Rows; i++) {
if ((lpProtocolInfo->iAddressFamily == (INT) HelperDLL->Mapping->Mapping[i].AddressFamily) &&
(lpProtocolInfo->iSocketType == (INT) HelperDLL->Mapping->Mapping[i].SocketType) &&
((lpProtocolInfo->iProtocol == (INT) HelperDLL->Mapping->Mapping[i].Protocol) ||
(lpProtocolInfo->iSocketType == SOCK_RAW))) {
LeaveCriticalSection(&HelperDLLDatabaseLock);
AFD_DbgPrint(MAX_TRACE, ("Returning helper DLL at (0x%X).\n", HelperDLL));
return HelperDLL;
/* DLL Doesn't support WSHOpenSocket2, call the old one */
HelperData->WSHOpenSocket(AddressFamily,
SocketType,
Protocol,
TransportName,
HelperDllContext,
Events
);
} else {
HelperData->WSHOpenSocket2(AddressFamily,
SocketType,
Protocol,
Group,
Flags,
TransportName,
HelperDllContext,
Events
);
}
/* Return the Helper Pointers */
*HelperDllData = HelperData;
return NO_ERROR;
}
CurrentEntry = CurrentEntry->Flink;
}
LeaveCriticalSection(&HelperDLLDatabaseLock);
AFD_DbgPrint(MAX_TRACE, ("Could not locate helper DLL.\n"));
/* Get the Transports available */
Status = SockLoadTransportList(&Transports);
return NULL;
}
INT GetHelperDLLEntries(
PWSHELPER_DLL HelperDLL)
{
PVOID e;
/* Check for error */
if (Status) {
AFD_DbgPrint(MIN_TRACE, ("Can't get transport list\n"));
return Status;
}
/* The following functions MUST be supported */
e = GetProcAddress(HelperDLL->hModule, "WSHEnumProtocols");
if (!e) return ERROR_BAD_PROVIDER;
HelperDLL->EntryTable.lpWSHEnumProtocols = e;
/* Loop through each transport until we find one that can satisfy us */
for (Transport = Transports;
*Transports != 0;
Transport += wcslen(Transport) + 1) {
e = GetProcAddress(HelperDLL->hModule, "WSHGetSockaddrType");
if (!e) return ERROR_BAD_PROVIDER;
HelperDLL->EntryTable.lpWSHGetSockaddrType = e;
e = GetProcAddress(HelperDLL->hModule, "WSHGetSocketInformation");
if (!e) return ERROR_BAD_PROVIDER;
HelperDLL->EntryTable.lpWSHGetSocketInformation = e;
e = GetProcAddress(HelperDLL->hModule, "WSHGetWildcardSockaddr");
if (!e) return ERROR_BAD_PROVIDER;
HelperDLL->EntryTable.lpWSHGetWildcardSockaddr = e;
e = GetProcAddress(HelperDLL->hModule, "WSHGetWinsockMapping");
if (!e) return ERROR_BAD_PROVIDER;
HelperDLL->EntryTable.lpWSHGetWinsockMapping = e;
e = GetProcAddress(HelperDLL->hModule, "WSHNotify");
if (!e) return ERROR_BAD_PROVIDER;
HelperDLL->EntryTable.lpWSHNotify = e;
e = GetProcAddress(HelperDLL->hModule, "WSHOpenSocket");
if (!e) return ERROR_BAD_PROVIDER;
HelperDLL->EntryTable.lpWSHOpenSocket = e;
e = GetProcAddress(HelperDLL->hModule, "WSHSetSocketInformation");
if (!e) return ERROR_BAD_PROVIDER;
HelperDLL->EntryTable.lpWSHSetSocketInformation = e;
/*
The following functions are OPTIONAL.
Whoever wants to call them, must check that the pointer is not NULL.
*/
e = GetProcAddress(HelperDLL->hModule, "WSHAddressToString");
HelperDLL->EntryTable.lpWSHAddressToString = e;
e = GetProcAddress(HelperDLL->hModule, "WSHGetBroadcastSockaddr");
HelperDLL->EntryTable.lpWSHGetBroadcastSockaddr = e;
e = GetProcAddress(HelperDLL->hModule, "WSHGetProviderGuid");
HelperDLL->EntryTable.lpWSHGetProviderGuid = e;
e = GetProcAddress(HelperDLL->hModule, "WSHGetWSAProtocolInfo");
HelperDLL->EntryTable.lpWSHGetWSAProtocolInfo = e;
e = GetProcAddress(HelperDLL->hModule, "WSHIoctl");
HelperDLL->EntryTable.lpWSHIoctl = e;
e = GetProcAddress(HelperDLL->hModule, "WSHJoinLeaf");
HelperDLL->EntryTable.lpWSHJoinLeaf = e;
e = GetProcAddress(HelperDLL->hModule, "WSHOpenSocket2");
HelperDLL->EntryTable.lpWSHOpenSocket2 = e;
e = GetProcAddress(HelperDLL->hModule, "WSHStringToAddress");
HelperDLL->EntryTable.lpWSHStringToAddress = e;
return NO_ERROR;
}
INT LoadHelperDLL(
PWSHELPER_DLL HelperDLL)
{
INT Status = NO_ERROR;
AFD_DbgPrint(MAX_TRACE, ("Loading helper dll at (0x%X).\n", HelperDLL));
if (!HelperDLL->hModule) {
/* DLL is not loaded so load it now */
HelperDLL->hModule = LoadLibrary(HelperDLL->LibraryName);
AFD_DbgPrint(MAX_TRACE, ("hModule is (0x%X).\n", HelperDLL->hModule));
if (HelperDLL->hModule) {
Status = GetHelperDLLEntries(HelperDLL);
} else
Status = ERROR_DLL_NOT_FOUND;
} else
Status = NO_ERROR;
AFD_DbgPrint(MAX_TRACE, ("Status (%d).\n", Status));
return Status;
}
INT UnloadHelperDLL(
PWSHELPER_DLL HelperDLL)
{
INT Status = NO_ERROR;
AFD_DbgPrint(MAX_TRACE, ("HelperDLL (0x%X) hModule (0x%X).\n", HelperDLL, HelperDLL->hModule));
if (HelperDLL->hModule) {
if (!FreeLibrary(HelperDLL->hModule)) {
Status = GetLastError();
/* See what mapping this Transport supports */
Status = SockLoadTransportMapping(Transport, &Mapping);
/* Check for error */
if (Status) {
AFD_DbgPrint(MIN_TRACE, ("Can't get mapping\n"));
HeapFree(GlobalHeap, 0, Transports);
return Status;
}
HelperDLL->hModule = NULL;
}
return Status;
/* See if this Mapping works for us */
if (SockIsTripleInMapping(Mapping, *AddressFamily, *SocketType, *Protocol)) {
/* It does, so load the DLL associated with it */
Status = SockLoadHelperDll(Transport, Mapping, &HelperData);
/* Check for error */
if (Status) {
AFD_DbgPrint(MIN_TRACE, ("Can't load helper DLL\n"));
HeapFree(GlobalHeap, 0, Transports);
HeapFree(GlobalHeap, 0, Mapping);
return Status;
}
/* Call the Helper Dll function get the Transport Name */
if (HelperData->WSHOpenSocket2 == NULL) {
/* DLL Doesn't support WSHOpenSocket2, call the old one */
HelperData->WSHOpenSocket(AddressFamily,
SocketType,
Protocol,
TransportName,
HelperDllContext,
Events
);
} else {
HelperData->WSHOpenSocket2(AddressFamily,
SocketType,
Protocol,
Group,
Flags,
TransportName,
HelperDllContext,
Events
);
}
/* Return the Helper Pointers */
*HelperDllData = HelperData;
HeapFree(GlobalHeap, 0, Transports);
HeapFree(GlobalHeap, 0, Mapping);
return NO_ERROR;
}
HeapFree(GlobalHeap, 0, Mapping);
}
HeapFree(GlobalHeap, 0, Transports);
return WSAEINVAL;
}
VOID CreateHelperDLLDatabase(VOID)
INT
SockLoadTransportMapping(
PWSTR TransportName,
PWINSOCK_MAPPING *Mapping)
{
PWSHELPER_DLL HelperDLL;
PWSTR TransportKey;
HKEY KeyHandle;
ULONG MappingSize;
LONG Status;
InitializeCriticalSection(&HelperDLLDatabaseLock);
AFD_DbgPrint(MID_TRACE,("Called: TransportName %ws\n", TransportName));
InitializeListHead(&HelperDLLDatabaseListHead);
/* Allocate a Buffer */
TransportKey = HeapAlloc(GlobalHeap, 0, (54 + wcslen(TransportName)) * sizeof(WCHAR));
/* FIXME: Read helper DLL configuration from registry */
HelperDLL = CreateHelperDLL(L"wshtcpip.dll");
if (!HelperDLL)
return;
HelperDLL->Mapping = HeapAlloc(
GlobalHeap,
0,
5 * sizeof(WINSOCK_MAPPING) + 3 * sizeof(DWORD));
if (!HelperDLL->Mapping)
return;
HelperDLL->Mapping->Rows = 5;
HelperDLL->Mapping->Columns = 3;
HelperDLL->Mapping->Mapping[0].AddressFamily = AF_INET;
HelperDLL->Mapping->Mapping[0].SocketType = SOCK_STREAM;
HelperDLL->Mapping->Mapping[0].Protocol = 0;
HelperDLL->Mapping->Mapping[1].AddressFamily = AF_INET;
HelperDLL->Mapping->Mapping[1].SocketType = SOCK_STREAM;
HelperDLL->Mapping->Mapping[1].Protocol = IPPROTO_TCP;
HelperDLL->Mapping->Mapping[2].AddressFamily = AF_INET;
HelperDLL->Mapping->Mapping[2].SocketType = SOCK_DGRAM;
HelperDLL->Mapping->Mapping[2].Protocol = 0;
HelperDLL->Mapping->Mapping[3].AddressFamily = AF_INET;
HelperDLL->Mapping->Mapping[3].SocketType = SOCK_DGRAM;
HelperDLL->Mapping->Mapping[3].Protocol = IPPROTO_UDP;
HelperDLL->Mapping->Mapping[4].AddressFamily = AF_INET;
HelperDLL->Mapping->Mapping[4].SocketType = SOCK_RAW;
HelperDLL->Mapping->Mapping[4].Protocol = 0;
LoadHelperDLL(HelperDLL);
}
VOID DestroyHelperDLLDatabase(VOID)
{
PLIST_ENTRY CurrentEntry;
PLIST_ENTRY NextEntry;
PWSHELPER_DLL HelperDLL;
CurrentEntry = HelperDLLDatabaseListHead.Flink;
while (CurrentEntry != &HelperDLLDatabaseListHead) {
NextEntry = CurrentEntry->Flink;
HelperDLL = CONTAINING_RECORD(CurrentEntry,
WSHELPER_DLL,
ListEntry);
DestroyHelperDLL(HelperDLL);
CurrentEntry = NextEntry;
/* Check for error */
if (TransportKey == NULL) {
AFD_DbgPrint(MIN_TRACE, ("Buffer allocation failed\n"));
return WSAEINVAL;
}
DeleteCriticalSection(&HelperDLLDatabaseLock);
/* Generate the right key name */
wcscpy(TransportKey, L"System\\CurrentControlSet\\Services\\");
wcscat(TransportKey, TransportName);
wcscat(TransportKey, L"\\Parameters\\Winsock");
/* Open the Key */
Status = RegOpenKeyExW(HKEY_LOCAL_MACHINE, TransportKey, 0, KEY_READ, &KeyHandle);
/* We don't need the Transport Key anymore */
HeapFree(GlobalHeap, 0, TransportKey);
/* Check for error */
if (Status) {
AFD_DbgPrint(MIN_TRACE, ("Error reading transport mapping registry\n"));
return WSAEINVAL;
}
/* Find out how much space we need for the Mapping */
Status = RegQueryValueExW(KeyHandle, L"Mapping", NULL, NULL, NULL, &MappingSize);
/* Check for error */
if (Status) {
AFD_DbgPrint(MIN_TRACE, ("Error reading transport mapping registry\n"));
return WSAEINVAL;
}
/* Allocate Memory for the Mapping */
*Mapping = HeapAlloc(GlobalHeap, 0, MappingSize);
/* Check for error */
if (*Mapping == NULL) {
AFD_DbgPrint(MIN_TRACE, ("Buffer allocation failed\n"));
return WSAEINVAL;
}
/* Read the Mapping */
Status = RegQueryValueExW(KeyHandle, L"Mapping", NULL, NULL, (LPBYTE)*Mapping, &MappingSize);
/* Check for error */
if (Status) {
AFD_DbgPrint(MIN_TRACE, ("Error reading transport mapping registry\n"));
HeapFree(GlobalHeap, 0, *Mapping);
return WSAEINVAL;
}
/* Close key and return */
RegCloseKey(KeyHandle);
return 0;
}
INT
SockLoadTransportList(
PWSTR *TransportList)
{
ULONG TransportListSize;
HKEY KeyHandle;
LONG Status;
AFD_DbgPrint(MID_TRACE,("Called\n"));
/* Open the Transports Key */
Status = RegOpenKeyExW (HKEY_LOCAL_MACHINE,
L"SYSTEM\\CurrentControlSet\\Services\\Winsock\\Parameters",
0,
KEY_READ,
&KeyHandle);
/* Check for error */
if (Status) {
AFD_DbgPrint(MIN_TRACE, ("Error reading transport list registry\n"));
return WSAEINVAL;
}
/* Get the Transport List Size */
Status = RegQueryValueExW(KeyHandle,
L"Transports",
NULL,
NULL,
NULL,
&TransportListSize);
/* Check for error */
if (Status) {
AFD_DbgPrint(MIN_TRACE, ("Error reading transport list registry\n"));
return WSAEINVAL;
}
/* Allocate Memory for the Transport List */
*TransportList = HeapAlloc(GlobalHeap, 0, TransportListSize);
/* Check for error */
if (*TransportList == NULL) {
AFD_DbgPrint(MIN_TRACE, ("Buffer allocation failed\n"));
return WSAEINVAL;
}
/* Get the Transports */
Status = RegQueryValueExW (KeyHandle,
L"Transports",
NULL,
NULL,
(LPBYTE)*TransportList,
&TransportListSize);
/* Check for error */
if (Status) {
AFD_DbgPrint(MIN_TRACE, ("Error reading transport list registry\n"));
HeapFree(GlobalHeap, 0, *TransportList);
return WSAEINVAL;
}
/* Close key and return */
RegCloseKey(KeyHandle);
return 0;
}
INT
SockLoadHelperDll(
PWSTR TransportName,
PWINSOCK_MAPPING Mapping,
PHELPER_DATA *HelperDllData)
{
PHELPER_DATA HelperData;
PWSTR HelperDllName;
PWSTR FullHelperDllName;
ULONG HelperDllNameSize;
PWSTR HelperKey;
HKEY KeyHandle;
ULONG DataSize;
LONG Status;
/* Allocate space for the Helper Structure and TransportName */
HelperData = HeapAlloc(GlobalHeap, 0, sizeof(*HelperData) + (wcslen(TransportName) + 1) * sizeof(WCHAR));
/* Check for error */
if (HelperData == NULL) {
AFD_DbgPrint(MIN_TRACE, ("Buffer allocation failed\n"));
return WSAEINVAL;
}
/* Allocate Space for the Helper DLL Key */
HelperKey = HeapAlloc(GlobalHeap, 0, (54 + wcslen(TransportName)) * sizeof(WCHAR));
/* Check for error */
if (HelperKey == NULL) {
AFD_DbgPrint(MIN_TRACE, ("Buffer allocation failed\n"));
HeapFree(GlobalHeap, 0, HelperData);
return WSAEINVAL;
}
/* Generate the right key name */
wcscpy(HelperKey, L"System\\CurrentControlSet\\Services\\");
wcscat(HelperKey, TransportName);
wcscat(HelperKey, L"\\Parameters\\Winsock");
/* Open the Key */
Status = RegOpenKeyExW(HKEY_LOCAL_MACHINE, HelperKey, 0, KEY_READ, &KeyHandle);
HeapFree(GlobalHeap, 0, HelperKey);
/* Check for error */
if (Status) {
AFD_DbgPrint(MIN_TRACE, ("Error reading helper DLL parameters\n"));
HeapFree(GlobalHeap, 0, HelperData);
return WSAEINVAL;
}
/* Read Size of SockAddr Structures */
DataSize = sizeof(HelperData->MinWSAddressLength);
HelperData->MinWSAddressLength = 16;
RegQueryValueExW (KeyHandle,
L"MinSockaddrLength",
NULL,
NULL,
(LPBYTE)&HelperData->MinWSAddressLength,
&DataSize);
DataSize = sizeof(HelperData->MinWSAddressLength);
HelperData->MaxWSAddressLength = 16;
RegQueryValueExW (KeyHandle,
L"MaxSockaddrLength",
NULL,
NULL,
(LPBYTE)&HelperData->MaxWSAddressLength,
&DataSize);
/* Size of TDI Structures */
HelperData->MinTDIAddressLength = HelperData->MinWSAddressLength + 6;
HelperData->MaxTDIAddressLength = HelperData->MaxWSAddressLength + 6;
/* Read Delayed Acceptance Setting */
DataSize = sizeof(DWORD);
HelperData->UseDelayedAcceptance = FALSE;
RegQueryValueExW (KeyHandle,
L"UseDelayedAcceptance",
NULL,
NULL,
(LPBYTE)&HelperData->UseDelayedAcceptance,
&DataSize);
/* Allocate Space for the Helper DLL Names */
HelperDllName = HeapAlloc(GlobalHeap, 0, 512);
/* Check for error */
if (HelperDllName == NULL) {
AFD_DbgPrint(MIN_TRACE, ("Buffer allocation failed\n"));
HeapFree(GlobalHeap, 0, HelperData);
return WSAEINVAL;
}
FullHelperDllName = HeapAlloc(GlobalHeap, 0, 512);
/* Check for error */
if (FullHelperDllName == NULL) {
AFD_DbgPrint(MIN_TRACE, ("Buffer allocation failed\n"));
HeapFree(GlobalHeap, 0, HelperDllName);
HeapFree(GlobalHeap, 0, HelperData);
return WSAEINVAL;
}
/* Get the name of the Helper DLL*/
DataSize = 512;
Status = RegQueryValueExW (KeyHandle,
L"HelperDllName",
NULL,
NULL,
(LPBYTE)HelperDllName,
&DataSize);
/* Check for error */
if (Status) {
AFD_DbgPrint(MIN_TRACE, ("Error reading helper DLL parameters\n"));
HeapFree(GlobalHeap, 0, FullHelperDllName);
HeapFree(GlobalHeap, 0, HelperDllName);
HeapFree(GlobalHeap, 0, HelperData);
return WSAEINVAL;
}
/* Get the Full name, expanding Environment Strings */
HelperDllNameSize = ExpandEnvironmentStringsW (HelperDllName,
FullHelperDllName,
256);
/* Load the DLL */
HelperData->hInstance = LoadLibraryW(FullHelperDllName);
HeapFree(GlobalHeap, 0, HelperDllName);
HeapFree(GlobalHeap, 0, FullHelperDllName);
if (HelperData->hInstance == NULL) {
AFD_DbgPrint(MIN_TRACE, ("Error loading helper DLL\n"));
HeapFree(GlobalHeap, 0, HelperData);
return WSAEINVAL;
}
/* Close Key */
RegCloseKey(KeyHandle);
/* Get the Pointers to the Helper Routines */
HelperData->WSHOpenSocket = (PWSH_OPEN_SOCKET)
GetProcAddress(HelperData->hInstance,
"WSHOpenSocket");
HelperData->WSHOpenSocket2 = (PWSH_OPEN_SOCKET2)
GetProcAddress(HelperData->hInstance,
"WSHOpenSocket2");
HelperData->WSHJoinLeaf = (PWSH_JOIN_LEAF)
GetProcAddress(HelperData->hInstance,
"WSHJoinLeaf");
HelperData->WSHNotify = (PWSH_NOTIFY)
GetProcAddress(HelperData->hInstance, "WSHNotify");
HelperData->WSHGetSocketInformation = (PWSH_GET_SOCKET_INFORMATION)
GetProcAddress(HelperData->hInstance,
"WSHGetSocketInformation");
HelperData->WSHSetSocketInformation = (PWSH_SET_SOCKET_INFORMATION)
GetProcAddress(HelperData->hInstance,
"WSHSetSocketInformation");
HelperData->WSHGetSockaddrType = (PWSH_GET_SOCKADDR_TYPE)
GetProcAddress(HelperData->hInstance,
"WSHGetSockaddrType");
HelperData->WSHGetWildcardSockaddr = (PWSH_GET_WILDCARD_SOCKEADDR)
GetProcAddress(HelperData->hInstance,
"WSHGetWildcardSockaddr");
HelperData->WSHGetBroadcastSockaddr = (PWSH_GET_BROADCAST_SOCKADDR)
GetProcAddress(HelperData->hInstance,
"WSHGetBroadcastSockaddr");
HelperData->WSHAddressToString = (PWSH_ADDRESS_TO_STRING)
GetProcAddress(HelperData->hInstance,
"WSHAddressToString");
HelperData->WSHStringToAddress = (PWSH_STRING_TO_ADDRESS)
GetProcAddress(HelperData->hInstance,
"WSHStringToAddress");
HelperData->WSHIoctl = (PWSH_IOCTL)
GetProcAddress(HelperData->hInstance,
"WSHIoctl");
/* Save the Mapping Structure and transport name */
HelperData->Mapping = Mapping;
wcscpy(HelperData->TransportName, TransportName);
/* Increment Reference Count */
HelperData->RefCount = 1;
/* Add it to our list */
InsertHeadList(&SockHelpersListHead, &HelperData->Helpers);
/* Return Pointers */
*HelperDllData = HelperData;
return 0;
}
BOOL
SockIsTripleInMapping(
PWINSOCK_MAPPING Mapping,
INT AddressFamily,
INT SocketType,
INT Protocol)
{
/* The Windows version returns more detailed information on which of the 3 parameters failed...we should do this later */
ULONG Row;
AFD_DbgPrint(MID_TRACE,("Called, Mapping rows = %d\n", Mapping->Rows));
/* Loop through Mapping to Find a matching one */
for (Row = 0; Row < Mapping->Rows; Row++) {
AFD_DbgPrint(MID_TRACE,("Examining: row %d: AF %d type %d proto %d\n",
Row,
(INT)Mapping->Mapping[Row].AddressFamily,
(INT)Mapping->Mapping[Row].SocketType,
(INT)Mapping->Mapping[Row].Protocol));
/* Check of all three values Match */
if (((INT)Mapping->Mapping[Row].AddressFamily == AddressFamily) &&
((INT)Mapping->Mapping[Row].SocketType == SocketType) &&
((INT)Mapping->Mapping[Row].Protocol == Protocol)) {
AFD_DbgPrint(MID_TRACE,("Found\n"));
return TRUE;
}
}
AFD_DbgPrint(MID_TRACE,("Not found\n"));
return FALSE;
}
/* EOF */

View file

@ -4,8 +4,10 @@
* FILE: misc/sndrcv.c
* PURPOSE: Send/receive routines
* PROGRAMMERS: Casper S. Hornstrup (chorns@users.sourceforge.net)
* Alex Ionescu (alex@relsoft.net)
* REVISIONS:
* CSH 01/09-2000 Created
* Alex 16/07/2004 - Complete Rewrite
*/
#include <string.h>
#include <msafd.h>
@ -25,80 +27,489 @@ WSPAsyncSelect(
}
INT
int
WSPAPI
WSPRecv(
IN SOCKET s,
IN OUT LPWSABUF lpBuffers,
IN DWORD dwBufferCount,
OUT LPDWORD lpNumberOfBytesRecvd,
IN OUT LPDWORD lpFlags,
IN LPWSAOVERLAPPED lpOverlapped,
IN LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine,
IN LPWSATHREADID lpThreadId,
OUT LPINT lpErrno)
SOCKET Handle,
LPWSABUF lpBuffers,
DWORD dwBufferCount,
LPDWORD lpNumberOfBytesRead,
LPDWORD ReceiveFlags,
LPWSAOVERLAPPED lpOverlapped,
LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine,
LPWSATHREADID lpThreadId,
LPINT lpErrno)
{
PFILE_REQUEST_RECVFROM Request;
FILE_REPLY_RECVFROM Reply;
IO_STATUS_BLOCK Iosb;
NTSTATUS Status;
DWORD Size;
PIO_STATUS_BLOCK IOSB;
IO_STATUS_BLOCK DummyIOSB;
AFD_RECV_INFO RecvInfo;
NTSTATUS Status;
PVOID APCContext;
PVOID APCFunction;
HANDLE Event;
AFD_DbgPrint(MAX_TRACE, ("Called.\n"));
/* Set up the Receive Structure */
RecvInfo.BufferArray = (PAFD_WSABUF)lpBuffers;
RecvInfo.BufferCount = dwBufferCount;
RecvInfo.TdiFlags = 0;
RecvInfo.AfdFlags = 0;
Size = dwBufferCount * sizeof(WSABUF);
/* Set the TDI Flags */
if (*ReceiveFlags == 0) {
RecvInfo.TdiFlags |= TDI_RECEIVE_NORMAL;
} else {
if (*ReceiveFlags & MSG_OOB) {
RecvInfo.TdiFlags |= TDI_RECEIVE_EXPEDITED;
} else {
RecvInfo.TdiFlags |= TDI_RECEIVE_NORMAL;
}
Request = (PFILE_REQUEST_RECVFROM)HeapAlloc(
GlobalHeap, 0, sizeof(FILE_REQUEST_RECVFROM) + Size);
if (!Request) {
AFD_DbgPrint(MIN_TRACE, ("Insufficient resources.\n"));
*lpErrno = WSAENOBUFS;
return SOCKET_ERROR;
}
if (*ReceiveFlags & MSG_PEEK) {
RecvInfo.TdiFlags |= TDI_RECEIVE_PEEK;
}
/* Put buffer pointers after request structure */
Request->Buffers = (LPWSABUF)(Request + 1);
Request->BufferCount = dwBufferCount;
Request->Flags = lpFlags;
RtlCopyMemory(Request->Buffers, lpBuffers, Size);
Status = NtDeviceIoControlFile(
(HANDLE)s,
NULL,
NULL,
NULL,
&Iosb,
IOCTL_AFD_RECV,
Request,
sizeof(FILE_REQUEST_RECVFROM) + Size,
&Reply,
sizeof(FILE_REPLY_RECVFROM));
HeapFree(GlobalHeap, 0, Request);
if (Status == STATUS_PENDING) {
AFD_DbgPrint(MAX_TRACE, ("Waiting on transport.\n"));
/* FIXME: Wait only for blocking sockets */
Status = NtWaitForSingleObject((HANDLE)s, FALSE, NULL);
}
if (!NT_SUCCESS(Status)) {
AFD_DbgPrint(MAX_TRACE, ("Status (0x%X).\n", Status));
*lpErrno = WSAENOBUFS;
return SOCKET_ERROR;
if (*ReceiveFlags & MSG_PARTIAL) {
RecvInfo.TdiFlags |= TDI_RECEIVE_NORMAL;
}
}
AFD_DbgPrint(MAX_TRACE, ("Receive successful (0x%X).\n",
Reply.NumberOfBytesRecvd));
/* Verifiy if we should use APC */
*lpNumberOfBytesRecvd = Reply.NumberOfBytesRecvd;
//*lpFlags = 0;
if (lpOverlapped == NULL) {
return 0;
/* Not using Overlapped structure, so use normal blocking on event */
APCContext = NULL;
APCFunction = NULL;
Event = SockEvent;
IOSB = &DummyIOSB;
} else {
if (lpCompletionRoutine == NULL) {
/* Using Overlapped Structure, but no Completition Routine, so no need for APC */
APCContext = lpOverlapped;
APCFunction = NULL;
Event = lpOverlapped->hEvent;
} else {
/* Using Overlapped Structure and a Completition Routine, so use an APC */
APCFunction = NULL; // should be a private io completition function inside us
APCContext = lpCompletionRoutine;
RecvInfo.AfdFlags = AFD_SKIP_FIO;
}
IOSB = (PIO_STATUS_BLOCK)&lpOverlapped->Internal;
RecvInfo.AfdFlags |= AFD_OVERLAPPED;
}
IOSB->Status = STATUS_PENDING;
/* Send IOCTL */
Status = NtDeviceIoControlFile((HANDLE)Handle,
SockEvent,
APCFunction,
APCContext,
IOSB,
IOCTL_AFD_RECV,
&RecvInfo,
sizeof(RecvInfo),
NULL,
0);
/* Wait for completition of not overlapped */
if (Status == STATUS_PENDING && lpOverlapped == NULL) {
WaitForSingleObject(SockEvent, 0); // BUGBUG, shouldn wait infintely for receive...
Status = IOSB->Status;
}
/* Return the Flags */
*ReceiveFlags = 0;
switch (Status) {
case STATUS_SUCCESS:
break;
case STATUS_PENDING :
return WSA_IO_PENDING;
case STATUS_BUFFER_OVERFLOW:
return WSAEMSGSIZE;
case STATUS_RECEIVE_EXPEDITED:
*ReceiveFlags = MSG_OOB;
break;
case STATUS_RECEIVE_PARTIAL_EXPEDITED :
*ReceiveFlags = MSG_PARTIAL | MSG_OOB;
break;
case STATUS_RECEIVE_PARTIAL :
*ReceiveFlags = MSG_PARTIAL;
break;
}
/* Return Number of bytes Read */
*lpNumberOfBytesRead = (DWORD)IOSB->Information;
/* Success */
return STATUS_SUCCESS;
}
int
WSPAPI
WSPRecvFrom(
SOCKET Handle,
LPWSABUF lpBuffers,
DWORD dwBufferCount,
LPDWORD lpNumberOfBytesRead,
LPDWORD ReceiveFlags,
struct sockaddr *SocketAddress,
int *SocketAddressLength,
LPWSAOVERLAPPED lpOverlapped,
LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine,
LPWSATHREADID lpThreadId,
LPINT lpErrno)
{
PIO_STATUS_BLOCK IOSB;
IO_STATUS_BLOCK DummyIOSB;
AFD_RECV_INFO_UDP RecvInfo;
NTSTATUS Status;
PVOID APCContext;
PVOID APCFunction;
HANDLE Event;
/* Set up the Receive Structure */
RecvInfo.BufferArray = (PAFD_WSABUF)lpBuffers;
RecvInfo.BufferCount = dwBufferCount;
RecvInfo.TdiFlags = 0;
RecvInfo.AfdFlags = 0;
RecvInfo.AddressLength = SocketAddressLength;
RecvInfo.Address = SocketAddress;
/* Set the TDI Flags */
if (*ReceiveFlags == 0) {
RecvInfo.TdiFlags |= TDI_RECEIVE_NORMAL;
} else {
if (*ReceiveFlags & MSG_OOB) {
RecvInfo.TdiFlags |= TDI_RECEIVE_EXPEDITED;
} else {
RecvInfo.TdiFlags |= TDI_RECEIVE_NORMAL;
}
if (*ReceiveFlags & MSG_PEEK) {
RecvInfo.TdiFlags |= TDI_RECEIVE_PEEK;
}
if (*ReceiveFlags & MSG_PARTIAL) {
RecvInfo.TdiFlags |= TDI_RECEIVE_NORMAL;
}
}
/* Verifiy if we should use APC */
if (lpOverlapped == NULL) {
/* Not using Overlapped structure, so use normal blocking on event */
APCContext = NULL;
APCFunction = NULL;
Event = SockEvent;
IOSB = &DummyIOSB;
} else {
if (lpCompletionRoutine == NULL) {
/* Using Overlapped Structure, but no Completition Routine, so no need for APC */
APCContext = lpOverlapped;
APCFunction = NULL;
Event = lpOverlapped->hEvent;
} else {
/* Using Overlapped Structure and a Completition Routine, so use an APC */
APCFunction = NULL; // should be a private io completition function inside us
APCContext = lpCompletionRoutine;
RecvInfo.AfdFlags = AFD_SKIP_FIO;
}
IOSB = (PIO_STATUS_BLOCK)&lpOverlapped->Internal;
RecvInfo.AfdFlags |= AFD_OVERLAPPED;
}
IOSB->Status = STATUS_PENDING;
/* Send IOCTL */
Status = NtDeviceIoControlFile((HANDLE)Handle,
SockEvent,
APCFunction,
APCContext,
IOSB,
IOCTL_AFD_RECV_DATAGRAM,
&RecvInfo,
sizeof(RecvInfo),
NULL,
0);
/* Wait for completition of not overlapped */
if (Status == STATUS_PENDING && lpOverlapped == NULL) {
WaitForSingleObject(SockEvent, 0); // BUGBUG, shouldn wait infintely for receive...
Status = IOSB->Status;
}
/* Return the Flags */
*ReceiveFlags = 0;
switch (Status) {
case STATUS_SUCCESS:
break;
case STATUS_PENDING :
return WSA_IO_PENDING;
case STATUS_BUFFER_OVERFLOW:
return WSAEMSGSIZE;
case STATUS_RECEIVE_EXPEDITED:
*ReceiveFlags = MSG_OOB;
break;
case STATUS_RECEIVE_PARTIAL_EXPEDITED :
*ReceiveFlags = MSG_PARTIAL | MSG_OOB;
break;
case STATUS_RECEIVE_PARTIAL :
*ReceiveFlags = MSG_PARTIAL;
break;
}
/* Return Number of bytes Read */
*lpNumberOfBytesRead = (DWORD)IOSB->Information;
/* Success */
return STATUS_SUCCESS;
}
int
WSPAPI
WSPSend(
SOCKET Handle,
LPWSABUF lpBuffers,
DWORD dwBufferCount,
LPDWORD lpNumberOfBytesSent,
DWORD iFlags,
LPWSAOVERLAPPED lpOverlapped,
LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine,
LPWSATHREADID lpThreadId,
LPINT lpErrno)
{
PIO_STATUS_BLOCK IOSB;
IO_STATUS_BLOCK DummyIOSB;
AFD_SEND_INFO SendInfo;
NTSTATUS Status;
PVOID APCContext;
PVOID APCFunction;
HANDLE Event;
/* Set up the Send Structure */
SendInfo.BufferArray = (PAFD_WSABUF)lpBuffers;
SendInfo.BufferCount = dwBufferCount;
SendInfo.TdiFlags = 0;
SendInfo.AfdFlags = 0;
/* Set the TDI Flags */
if (iFlags) {
if (iFlags & MSG_OOB) {
SendInfo.TdiFlags |= TDI_SEND_EXPEDITED;
}
if (iFlags & MSG_PARTIAL) {
SendInfo.TdiFlags |= TDI_SEND_PARTIAL;
}
}
/* Verifiy if we should use APC */
if (lpOverlapped == NULL) {
/* Not using Overlapped structure, so use normal blocking on event */
APCContext = NULL;
APCFunction = NULL;
Event = SockEvent;
IOSB = &DummyIOSB;
} else {
if (lpCompletionRoutine == NULL) {
/* Using Overlapped Structure, but no Completition Routine, so no need for APC */
APCContext = lpOverlapped;
APCFunction = NULL;
Event = lpOverlapped->hEvent;
} else {
/* Using Overlapped Structure and a Completition Routine, so use an APC */
APCFunction = NULL; // should be a private io completition function inside us
APCContext = lpCompletionRoutine;
SendInfo.AfdFlags = AFD_SKIP_FIO;
}
IOSB = (PIO_STATUS_BLOCK)&lpOverlapped->Internal;
SendInfo.AfdFlags |= AFD_OVERLAPPED;
}
IOSB->Status = STATUS_PENDING;
/* Send IOCTL */
Status = NtDeviceIoControlFile((HANDLE)Handle,
SockEvent,
APCFunction,
APCContext,
IOSB,
IOCTL_AFD_SEND,
&SendInfo,
sizeof(SendInfo),
NULL,
0);
/* Wait for completition of not overlapped */
if (Status == STATUS_PENDING && lpOverlapped == NULL) {
WaitForSingleObject(SockEvent, 0); // BUGBUG, shouldn wait infintely for send...
Status = IOSB->Status;
}
if (Status == STATUS_PENDING) {
return WSA_IO_PENDING;
}
/* Return Number of bytes Sent */
*lpNumberOfBytesSent = (DWORD)IOSB->Information;
/* Success */
return STATUS_SUCCESS;
}
int
WSPAPI
WSPSendTo(
SOCKET Handle,
LPWSABUF lpBuffers,
DWORD dwBufferCount,
LPDWORD lpNumberOfBytesSent,
DWORD iFlags,
struct sockaddr *SocketAddress,
int SocketAddressLength,
LPWSAOVERLAPPED lpOverlapped,
LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine,
LPWSATHREADID lpThreadId,
LPINT lpErrno)
{
PIO_STATUS_BLOCK IOSB;
IO_STATUS_BLOCK DummyIOSB;
AFD_SEND_INFO_UDP SendInfo;
PSOCKET_INFORMATION Socket;
NTSTATUS Status;
PVOID APCContext;
PVOID APCFunction;
HANDLE Event;
PTRANSPORT_ADDRESS RemoteAddress;
UCHAR TdiBuffer[0x16];
PSOCKADDR BindAddress;
INT BindAddressLength;
/* Get the Socket Structure associate to this Socket*/
Socket = GetSocketStructure(Handle);
/* Bind us First */
if (Socket->SharedData.State == SocketOpen) {
/* Get the Wildcard Address */
BindAddressLength = Socket->HelperData->MaxWSAddressLength;
BindAddress = HeapAlloc(GlobalHeap, 0, BindAddressLength);
Socket->HelperData->WSHGetWildcardSockaddr (Socket->HelperContext,
BindAddress,
&BindAddressLength);
/* Bind it */
WSPBind(Handle, BindAddress, BindAddressLength, NULL);
}
/* Set up Address in TDI Format */
RemoteAddress = (PTRANSPORT_ADDRESS)TdiBuffer;
RemoteAddress->TAAddressCount = 1;
RemoteAddress->Address[0].AddressLength = SocketAddressLength - sizeof(SocketAddress->sa_family);
RtlCopyMemory(&RemoteAddress->Address[0].AddressType, SocketAddress, SocketAddressLength);
/* Set up Structure */
SendInfo.BufferArray = (PAFD_WSABUF)lpBuffers;
SendInfo.AfdFlags = 0;
SendInfo.BufferCount = dwBufferCount;
SendInfo.RemoteAddress = RemoteAddress;
SendInfo.SizeOfRemoteAddress = Socket->HelperData->MaxTDIAddressLength;
/* Verifiy if we should use APC */
if (lpOverlapped == NULL) {
/* Not using Overlapped structure, so use normal blocking on event */
APCContext = NULL;
APCFunction = NULL;
Event = SockEvent;
IOSB = &DummyIOSB;
} else {
if (lpCompletionRoutine == NULL) {
/* Using Overlapped Structure, but no Completition Routine, so no need for APC */
APCContext = lpOverlapped;
APCFunction = NULL;
Event = lpOverlapped->hEvent;
} else {
/* Using Overlapped Structure and a Completition Routine, so use an APC */
APCFunction = NULL; // should be a private io completition function inside us
APCContext = lpCompletionRoutine;
SendInfo.AfdFlags = AFD_SKIP_FIO;
}
IOSB = (PIO_STATUS_BLOCK)&lpOverlapped->Internal;
SendInfo.AfdFlags |= AFD_OVERLAPPED;
}
/* Send IOCTL */
Status = NtDeviceIoControlFile((HANDLE)Handle,
SockEvent,
APCFunction,
APCContext,
IOSB,
IOCTL_AFD_SEND_DATAGRAM,
&SendInfo,
sizeof(SendInfo),
NULL,
0);
/* Wait for completition of not overlapped */
if (Status == STATUS_PENDING && lpOverlapped == NULL) {
WaitForSingleObject(SockEvent, 0); // BUGBUG, shouldn wait infintely for send...
Status = IOSB->Status;
}
if (Status == STATUS_PENDING) {
return WSA_IO_PENDING;
}
/* Return Number of bytes Sent */
*lpNumberOfBytesSent = (DWORD)IOSB->Information;
/* Success */
return STATUS_SUCCESS;
}
INT
WSPAPI
WSPRecvDisconnect(
@ -111,160 +522,6 @@ WSPRecvDisconnect(
return 0;
}
INT
WSPAPI
WSPRecvFrom(
IN SOCKET s,
IN OUT LPWSABUF lpBuffers,
IN DWORD dwBufferCount,
OUT LPDWORD lpNumberOfBytesRecvd,
IN OUT LPDWORD lpFlags,
OUT LPSOCKADDR lpFrom,
IN OUT LPINT lpFromLen,
IN LPWSAOVERLAPPED lpOverlapped,
IN LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine,
IN LPWSATHREADID lpThreadId,
OUT LPINT lpErrno)
{
PFILE_REQUEST_RECVFROM Request;
FILE_REPLY_RECVFROM Reply;
IO_STATUS_BLOCK Iosb;
NTSTATUS Status;
DWORD Size;
AFD_DbgPrint(MAX_TRACE, ("Called.\n"));
Size = dwBufferCount * sizeof(WSABUF);
Request = (PFILE_REQUEST_RECVFROM)HeapAlloc(
GlobalHeap, 0, sizeof(FILE_REQUEST_RECVFROM) + Size);
if (!Request) {
AFD_DbgPrint(MIN_TRACE, ("Insufficient resources.\n"));
*lpErrno = WSAENOBUFS;
return SOCKET_ERROR;
}
/* Put buffer pointers after request structure */
Request->Buffers = (LPWSABUF)(Request + 1);
Request->BufferCount = dwBufferCount;
Request->Flags = lpFlags;
Request->From = lpFrom;
Request->FromLen = lpFromLen;
RtlCopyMemory(Request->Buffers, lpBuffers, Size);
Status = NtDeviceIoControlFile(
(HANDLE)s,
NULL,
NULL,
NULL,
&Iosb,
IOCTL_AFD_RECVFROM,
Request,
sizeof(FILE_REQUEST_RECVFROM) + Size,
&Reply,
sizeof(FILE_REPLY_RECVFROM));
HeapFree(GlobalHeap, 0, Request);
if (Status == STATUS_PENDING) {
AFD_DbgPrint(MAX_TRACE, ("Waiting on transport.\n"));
/* FIXME: Wait only for blocking sockets */
Status = NtWaitForSingleObject((HANDLE)s, FALSE, NULL);
}
if (!NT_SUCCESS(Status)) {
AFD_DbgPrint(MAX_TRACE, ("Status (0x%X).\n", Status));
*lpErrno = WSAENOBUFS;
return SOCKET_ERROR;
}
AFD_DbgPrint(MAX_TRACE, ("Receive successful (0x%X).\n",
Reply.NumberOfBytesRecvd));
*lpNumberOfBytesRecvd = Reply.NumberOfBytesRecvd;
//*lpFlags = 0;
((PSOCKADDR_IN)lpFrom)->sin_family = AF_INET;
((PSOCKADDR_IN)lpFrom)->sin_port = 0;
((PSOCKADDR_IN)lpFrom)->sin_addr.S_un.S_addr = 0x0100007F;
*lpFromLen = sizeof(SOCKADDR_IN);
return 0;
}
INT
WSPAPI
WSPSend(
IN SOCKET s,
IN LPWSABUF lpBuffers,
IN DWORD dwBufferCount,
OUT LPDWORD lpNumberOfBytesSent,
IN DWORD dwFlags,
IN LPWSAOVERLAPPED lpOverlapped,
IN LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine,
IN LPWSATHREADID lpThreadId,
OUT LPINT lpErrno)
{
PFILE_REQUEST_SENDTO Request;
FILE_REPLY_SENDTO Reply;
IO_STATUS_BLOCK Iosb;
NTSTATUS Status;
DWORD Size;
AFD_DbgPrint(MAX_TRACE, ("Called.\n"));
Size = dwBufferCount * sizeof(WSABUF);
CP
Request = (PFILE_REQUEST_SENDTO)HeapAlloc(
GlobalHeap, 0, sizeof(FILE_REQUEST_SENDTO) + Size);
if (!Request) {
*lpErrno = WSAENOBUFS;
return SOCKET_ERROR;
}
CP
/* Put buffer pointers after request structure */
Request->Buffers = (LPWSABUF)(Request + 1);
Request->BufferCount = dwBufferCount;
Request->Flags = dwFlags;
CP
RtlCopyMemory(Request->Buffers, lpBuffers, Size);
CP
Status = NtDeviceIoControlFile
( (HANDLE)s,
NULL,
NULL,
NULL,
&Iosb,
IOCTL_AFD_SEND,
Request,
sizeof(FILE_REQUEST_SENDTO) + Size,
&Reply,
sizeof(FILE_REPLY_SENDTO));
CP
/* HeapFree(GlobalHeap, 0, Request); */
CP
if (Status == STATUS_PENDING) {
AFD_DbgPrint(MAX_TRACE, ("Waiting on transport.\n"));
/* FIXME: Wait only for blocking sockets */
Status = NtWaitForSingleObject((HANDLE)s, FALSE, NULL);
}
CP
if (!NT_SUCCESS(Status)) {
AFD_DbgPrint(MAX_TRACE, ("Status (0x%X).\n", Status));
*lpErrno = WSAENOBUFS;
return SOCKET_ERROR;
}
AFD_DbgPrint(MAX_TRACE, ("Send successful.\n"));
return 0;
}
INT
@ -279,78 +536,4 @@ WSPSendDisconnect(
return 0;
}
INT
WSPAPI
WSPSendTo(
IN SOCKET s,
IN LPWSABUF lpBuffers,
IN DWORD dwBufferCount,
OUT LPDWORD lpNumberOfBytesSent,
IN DWORD dwFlags,
IN CONST LPSOCKADDR lpTo,
IN INT iToLen,
IN LPWSAOVERLAPPED lpOverlapped,
IN LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine,
IN LPWSATHREADID lpThreadId,
OUT LPINT lpErrno)
{
PFILE_REQUEST_SENDTO Request;
FILE_REPLY_SENDTO Reply;
IO_STATUS_BLOCK Iosb;
NTSTATUS Status;
DWORD Size;
AFD_DbgPrint(MAX_TRACE, ("Called.\n"));
Size = dwBufferCount * sizeof(WSABUF);
Request = (PFILE_REQUEST_SENDTO)HeapAlloc(
GlobalHeap, 0, sizeof(FILE_REQUEST_SENDTO) + Size);
if (!Request) {
*lpErrno = WSAENOBUFS;
return SOCKET_ERROR;
}
/* Put buffer pointers after request structure */
Request->Buffers = (LPWSABUF)(Request + 1);
Request->BufferCount = dwBufferCount;
Request->Flags = dwFlags;
Request->ToLen = iToLen;
RtlCopyMemory(&Request->To, lpTo, sizeof(SOCKADDR));
RtlCopyMemory(Request->Buffers, lpBuffers, Size);
Status = NtDeviceIoControlFile(
(HANDLE)s,
NULL,
NULL,
NULL,
&Iosb,
IOCTL_AFD_SENDTO,
Request,
sizeof(FILE_REQUEST_SENDTO) + Size,
&Reply,
sizeof(FILE_REPLY_SENDTO));
HeapFree(GlobalHeap, 0, Request);
if (Status == STATUS_PENDING) {
AFD_DbgPrint(MAX_TRACE, ("Waiting on transport.\n"));
/* FIXME: Wait only for blocking sockets */
Status = NtWaitForSingleObject((HANDLE)s, FALSE, NULL);
}
if (!NT_SUCCESS(Status)) {
AFD_DbgPrint(MAX_TRACE, ("Status (0x%X).\n", Status));
*lpErrno = WSAENOBUFS;
return SOCKET_ERROR;
}
AFD_DbgPrint(MAX_TRACE, ("Send successful.\n"));
return 0;
}
/* EOF */

View file

@ -152,20 +152,6 @@ WSPSetSockOpt(
return 0;
}
INT
WSPAPI
WSPShutdown(
IN SOCKET s,
IN INT how,
OUT LPINT lpErrno)
{
UNIMPLEMENTED
return 0;
}
INT
WSPAPI
WSPStringToAddress(

View file

@ -3,6 +3,6 @@
LIBRARY msafd.dll
EXPORTS
WSPStartup@76
WSPStartup=_WSPStartup@76
; EOF