2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS kernel
4 * FILE: drivers/net/afd/afd/main.c
5 * PURPOSE: Ancillary functions driver
6 * PROGRAMMER: Art Yerkes (ayerkes@speakeasy.net)
10 * Suggestions: Uniform naming (AfdXxx)
16 #include "tdi_proto.h"
22 /* See debug.h for debug/trace constants */
23 //DWORD DebugTraceLevel = DEBUG_ULTRA;
24 DWORD DebugTraceLevel
= 0;
28 void OskitDumpBuffer( PCHAR Data
, UINT Len
) {
31 for( i
= 0; i
< Len
; i
++ ) {
32 if( i
&& !(i
& 0xf) ) DbgPrint( "\n" );
33 if( !(i
& 0xf) ) DbgPrint( "%08x: ", (UINT
)(Data
+ i
) );
34 DbgPrint( " %02x", Data
[i
] & 0xff );
42 AfdCreateSocket(PDEVICE_OBJECT DeviceObject
, PIRP Irp
,
43 PIO_STACK_LOCATION IrpSp
) {
45 PFILE_OBJECT FileObject
;
46 PAFD_DEVICE_EXTENSION DeviceExt
;
47 PFILE_FULL_EA_INFORMATION EaInfo
;
48 PAFD_CREATE_PACKET ConnectInfo
= NULL
;
50 PWCHAR EaInfoValue
= NULL
;
53 AFD_DbgPrint(MID_TRACE
,
54 ("AfdCreate(DeviceObject %p Irp %p)\n", DeviceObject
, Irp
));
56 DeviceExt
= DeviceObject
->DeviceExtension
;
57 FileObject
= IrpSp
->FileObject
;
58 Disposition
= (IrpSp
->Parameters
.Create
.Options
>> 24) & 0xff;
60 Irp
->IoStatus
.Information
= 0;
62 EaInfo
= Irp
->AssociatedIrp
.SystemBuffer
;
65 ConnectInfo
= (PAFD_CREATE_PACKET
)(EaInfo
->EaName
+ EaInfo
->EaNameLength
+ 1);
66 EaInfoValue
= (PWCHAR
)(((PCHAR
)ConnectInfo
) + sizeof(AFD_CREATE_PACKET
));
68 EaLength
= sizeof(FILE_FULL_EA_INFORMATION
) +
69 EaInfo
->EaNameLength
+
70 EaInfo
->EaValueLength
;
72 AFD_DbgPrint(MID_TRACE
,("EaInfo: %x, EaInfoValue: %x\n",
73 EaInfo
, EaInfoValue
));
76 AFD_DbgPrint(MID_TRACE
,("About to allocate the new FCB\n"));
78 FCB
= ExAllocatePool(NonPagedPool
, sizeof(AFD_FCB
));
80 Irp
->IoStatus
.Status
= STATUS_NO_MEMORY
;
81 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
82 return STATUS_NO_MEMORY
;
85 AFD_DbgPrint(MID_TRACE
,("Initializing the new FCB @ %x (FileObject %x Flags %x)\n", FCB
, FileObject
, ConnectInfo
? ConnectInfo
->EndpointFlags
: 0));
87 RtlZeroMemory( FCB
, sizeof( *FCB
) );
89 FCB
->Flags
= ConnectInfo
? ConnectInfo
->EndpointFlags
: 0;
90 FCB
->State
= SOCKET_STATE_CREATED
;
91 FCB
->FileObject
= FileObject
;
92 FCB
->DeviceExt
= DeviceExt
;
93 FCB
->Recv
.Size
= DEFAULT_RECEIVE_WINDOW_SIZE
;
94 FCB
->Send
.Size
= DEFAULT_SEND_WINDOW_SIZE
;
96 KeInitializeSpinLock( &FCB
->SpinLock
);
97 ExInitializeFastMutex( &FCB
->Mutex
);
98 KeInitializeEvent( &FCB
->StateLockedEvent
, NotificationEvent
, FALSE
);
100 for( i
= 0; i
< MAX_FUNCTIONS
; i
++ ) {
101 InitializeListHead( &FCB
->PendingIrpList
[i
] );
104 InitializeListHead( &FCB
->DatagramList
);
105 InitializeListHead( &FCB
->PendingConnections
);
107 AFD_DbgPrint(MID_TRACE
,("%x: Checking command channel\n", FCB
));
110 FCB
->TdiDeviceName
.Length
= ConnectInfo
->SizeOfTransportName
;
111 FCB
->TdiDeviceName
.MaximumLength
= FCB
->TdiDeviceName
.Length
;
112 FCB
->TdiDeviceName
.Buffer
=
113 ExAllocatePool( NonPagedPool
, FCB
->TdiDeviceName
.Length
);
114 RtlCopyMemory( FCB
->TdiDeviceName
.Buffer
,
115 ConnectInfo
->TransportName
,
116 FCB
->TdiDeviceName
.Length
);
118 if( !FCB
->TdiDeviceName
.Buffer
) {
120 AFD_DbgPrint(MID_TRACE
,("Could not copy target string\n"));
121 Irp
->IoStatus
.Status
= STATUS_NO_MEMORY
;
122 IoCompleteRequest( Irp
, IO_NETWORK_INCREMENT
);
123 return STATUS_NO_MEMORY
;
126 AFD_DbgPrint(MID_TRACE
,("Success: %s %wZ\n",
127 EaInfo
->EaName
, &FCB
->TdiDeviceName
));
129 AFD_DbgPrint(MID_TRACE
,("Success: Control connection\n"));
132 FileObject
->FsContext
= FCB
;
134 /* It seems that UDP sockets are writable from inception */
135 if( FCB
->Flags
& SGID_CONNECTIONLESS
) {
136 AFD_DbgPrint(MID_TRACE
,("Packet oriented socket\n"));
137 /* Allocate our backup buffer */
138 FCB
->Recv
.Window
= ExAllocatePool( NonPagedPool
, FCB
->Recv
.Size
);
139 FCB
->Send
.Window
= ExAllocatePool( NonPagedPool
, FCB
->Send
.Size
);
140 /* A datagram socket is always sendable */
141 FCB
->PollState
|= AFD_EVENT_SEND
;
142 PollReeval( FCB
->DeviceExt
, FCB
->FileObject
);
145 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
146 IoCompleteRequest( Irp
, IO_NETWORK_INCREMENT
);
148 return STATUS_SUCCESS
;
151 VOID
DestroySocket( PAFD_FCB FCB
) {
153 BOOLEAN ReturnEarly
= FALSE
;
154 PAFD_IN_FLIGHT_REQUEST InFlightRequest
[IN_FLIGHT_REQUESTS
];
156 AFD_DbgPrint(MIN_TRACE
,("Called (%x)\n", FCB
));
158 if( !SocketAcquireStateLock( FCB
) ) return;
160 FCB
->State
= SOCKET_STATE_CLOSED
;
162 InFlightRequest
[0] = &FCB
->ListenIrp
;
163 InFlightRequest
[1] = &FCB
->ReceiveIrp
;
164 InFlightRequest
[2] = &FCB
->SendIrp
;
166 /* Return early here because we might be called in the mean time. */
168 FCB
->ListenIrp
.InFlightRequest
||
169 FCB
->ReceiveIrp
.InFlightRequest
||
170 FCB
->SendIrp
.InFlightRequest
) {
171 AFD_DbgPrint(MIN_TRACE
,("Leaving socket alive (%x %x %x)\n",
172 FCB
->ListenIrp
.InFlightRequest
,
173 FCB
->ReceiveIrp
.InFlightRequest
,
174 FCB
->SendIrp
.InFlightRequest
));
178 /* After PoolReeval, this FCB should not be involved in any outstanding
181 /* Cancel our pending requests */
182 for( i
= 0; i
< IN_FLIGHT_REQUESTS
; i
++ ) {
183 NTSTATUS Status
= STATUS_NO_SUCH_FILE
;
184 if( InFlightRequest
[i
]->InFlightRequest
) {
185 AFD_DbgPrint(MID_TRACE
,("Cancelling in flight irp %d (%x)\n",
186 i
, InFlightRequest
[i
]->InFlightRequest
));
187 InFlightRequest
[i
]->InFlightRequest
->IoStatus
.Status
= Status
;
188 InFlightRequest
[i
]->InFlightRequest
->IoStatus
.Information
= 0;
189 IoCancelIrp( InFlightRequest
[i
]->InFlightRequest
);
193 SocketStateUnlock( FCB
);
195 if( ReturnEarly
) return;
197 if( FCB
->Recv
.Window
)
198 ExFreePool( FCB
->Recv
.Window
);
199 if( FCB
->Send
.Window
)
200 ExFreePool( FCB
->Send
.Window
);
201 if( FCB
->AddressFrom
)
202 ExFreePool( FCB
->AddressFrom
);
203 if( FCB
->LocalAddress
)
204 ExFreePool( FCB
->LocalAddress
);
206 ExFreePool(FCB
->TdiDeviceName
.Buffer
);
209 AFD_DbgPrint(MIN_TRACE
,("Deleted (%x)\n", FCB
));
211 AFD_DbgPrint(MIN_TRACE
,("Leaving\n"));
215 AfdCloseSocket(PDEVICE_OBJECT DeviceObject
, PIRP Irp
,
216 PIO_STACK_LOCATION IrpSp
)
218 PFILE_OBJECT FileObject
= IrpSp
->FileObject
;
219 PAFD_FCB FCB
= FileObject
->FsContext
;
221 AFD_DbgPrint(MID_TRACE
,
222 ("AfdClose(DeviceObject %p Irp %p)\n", DeviceObject
, Irp
));
224 AFD_DbgPrint(MID_TRACE
,("FCB %x\n", FCB
));
226 FCB
->PollState
|= AFD_EVENT_CLOSE
;
227 PollReeval( FCB
->DeviceExt
, FileObject
);
228 KillSelectsForFCB( FCB
->DeviceExt
, FileObject
, FALSE
);
230 if( FCB
->EventSelect
) ObDereferenceObject( FCB
->EventSelect
);
232 FileObject
->FsContext
= NULL
;
233 DestroySocket( FCB
);
235 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
236 Irp
->IoStatus
.Information
= 0;
237 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
239 AFD_DbgPrint(MID_TRACE
, ("Returning success.\n"));
241 return STATUS_SUCCESS
;
245 AfdDisconnect(PDEVICE_OBJECT DeviceObject
, PIRP Irp
,
246 PIO_STACK_LOCATION IrpSp
) {
247 PFILE_OBJECT FileObject
= IrpSp
->FileObject
;
248 PAFD_FCB FCB
= FileObject
->FsContext
;
249 PAFD_DISCONNECT_INFO DisReq
;
250 IO_STATUS_BLOCK Iosb
;
251 PTDI_CONNECTION_INFORMATION ConnInfo
;
255 if( !SocketAcquireStateLock( FCB
) ) return LostSocket( Irp
, FALSE
);
257 if( !(DisReq
= LockRequest( Irp
, IrpSp
)) )
258 return UnlockAndMaybeComplete( FCB
, STATUS_NO_MEMORY
,
259 Irp
, 0, NULL
, FALSE
);
261 if (NULL
== FCB
->RemoteAddress
)
267 Status
= TdiBuildNullConnectionInfo
268 ( &ConnInfo
, FCB
->RemoteAddress
->Address
[0].AddressType
);
270 if( !NT_SUCCESS(Status
) || !ConnInfo
)
271 return UnlockAndMaybeComplete( FCB
, STATUS_NO_MEMORY
,
272 Irp
, 0, NULL
, TRUE
);
275 if( DisReq
->DisconnectType
& AFD_DISCONNECT_SEND
)
276 Flags
|= TDI_DISCONNECT_RELEASE
;
277 if( DisReq
->DisconnectType
& AFD_DISCONNECT_RECV
||
278 DisReq
->DisconnectType
& AFD_DISCONNECT_ABORT
)
279 Flags
|= TDI_DISCONNECT_ABORT
;
281 Status
= TdiDisconnect( FCB
->Connection
.Object
,
290 ExFreePool( ConnInfo
);
292 return UnlockAndMaybeComplete( FCB
, Status
, Irp
, 0, NULL
, TRUE
);
296 AfdDispatch(PDEVICE_OBJECT DeviceObject
, PIRP Irp
)
298 PIO_STACK_LOCATION IrpSp
= IoGetCurrentIrpStackLocation(Irp
);
299 NTSTATUS Status
= STATUS_SUCCESS
;
301 PFILE_OBJECT FileObject
= IrpSp
->FileObject
;
304 AFD_DbgPrint(MID_TRACE
,("AfdDispatch: %d\n", IrpSp
->MajorFunction
));
305 if( IrpSp
->MajorFunction
!= IRP_MJ_CREATE
) {
306 AFD_DbgPrint(MID_TRACE
,("FO %x, IrpSp->FO %x\n",
307 FileObject
, IrpSp
->FileObject
));
308 ASSERT(FileObject
== IrpSp
->FileObject
);
311 switch(IrpSp
->MajorFunction
)
313 /* opening and closing handles to the device */
315 /* Mostly borrowed from the named pipe file system */
316 return AfdCreateSocket(DeviceObject
, Irp
, IrpSp
);
319 /* Ditto the borrowing */
320 return AfdCloseSocket(DeviceObject
, Irp
, IrpSp
);
324 return AfdConnectedSocketWriteData( DeviceObject
, Irp
, IrpSp
, TRUE
);
328 return AfdConnectedSocketReadData( DeviceObject
, Irp
, IrpSp
, TRUE
);
330 case IRP_MJ_DEVICE_CONTROL
:
332 switch( IrpSp
->Parameters
.DeviceIoControl
.IoControlCode
) {
334 return AfdBindSocket( DeviceObject
, Irp
, IrpSp
);
336 case IOCTL_AFD_CONNECT
:
337 return AfdStreamSocketConnect( DeviceObject
, Irp
, IrpSp
);
339 case IOCTL_AFD_START_LISTEN
:
340 return AfdListenSocket( DeviceObject
, Irp
, IrpSp
);
343 return AfdConnectedSocketReadData( DeviceObject
, Irp
, IrpSp
,
346 case IOCTL_AFD_SELECT
:
347 return AfdSelect( DeviceObject
, Irp
, IrpSp
);
349 case IOCTL_AFD_EVENT_SELECT
:
350 return AfdEventSelect( DeviceObject
, Irp
, IrpSp
);
352 case IOCTL_AFD_ENUM_NETWORK_EVENTS
:
353 return AfdEnumEvents( DeviceObject
, Irp
, IrpSp
);
355 case IOCTL_AFD_RECV_DATAGRAM
:
356 return AfdPacketSocketReadData( DeviceObject
, Irp
, IrpSp
);
359 return AfdConnectedSocketWriteData( DeviceObject
, Irp
, IrpSp
,
362 case IOCTL_AFD_SEND_DATAGRAM
:
363 return AfdPacketSocketWriteData( DeviceObject
, Irp
, IrpSp
);
365 case IOCTL_AFD_GET_INFO
:
366 return AfdGetInfo( DeviceObject
, Irp
, IrpSp
);
368 case IOCTL_AFD_GET_CONTEXT
:
369 return AfdGetContext( DeviceObject
, Irp
, IrpSp
);
371 case IOCTL_AFD_SET_CONTEXT
:
372 return AfdSetContext( DeviceObject
, Irp
, IrpSp
);
374 case IOCTL_AFD_WAIT_FOR_LISTEN
:
375 return AfdWaitForListen( DeviceObject
, Irp
, IrpSp
);
377 case IOCTL_AFD_ACCEPT
:
378 return AfdAccept( DeviceObject
, Irp
, IrpSp
);
380 case IOCTL_AFD_DISCONNECT
:
381 return AfdDisconnect( DeviceObject
, Irp
, IrpSp
);
383 case IOCTL_AFD_GET_SOCK_NAME
:
384 return AfdGetSockOrPeerName( DeviceObject
, Irp
, IrpSp
, TRUE
);
386 case IOCTL_AFD_GET_PEER_NAME
:
387 return AfdGetSockOrPeerName( DeviceObject
, Irp
, IrpSp
, FALSE
);
389 case IOCTL_AFD_GET_TDI_HANDLES
:
390 AFD_DbgPrint(MIN_TRACE
, ("IOCTL_AFD_GET_TDI_HANDLES\n"));
393 case IOCTL_AFD_SET_INFO
:
394 AFD_DbgPrint(MIN_TRACE
, ("IOCTL_AFD_SET_INFO\n"));
397 case IOCTL_AFD_SET_CONNECT_DATA
:
398 AFD_DbgPrint(MIN_TRACE
, ("IOCTL_AFD_SET_CONNECT_DATA\n"));
401 case IOCTL_AFD_SET_CONNECT_OPTIONS
:
402 AFD_DbgPrint(MIN_TRACE
, ("IOCTL_AFD_SET_CONNECT_OPTIONS\n"));
405 case IOCTL_AFD_SET_DISCONNECT_DATA
:
406 AFD_DbgPrint(MIN_TRACE
, ("IOCTL_AFD_SET_DISCONNECT_DATA\n"));
409 case IOCTL_AFD_SET_DISCONNECT_OPTIONS
:
410 AFD_DbgPrint(MIN_TRACE
, ("IOCTL_AFD_SET_DISCONNECT_OPTIONS\n"));
413 case IOCTL_AFD_GET_CONNECT_DATA
:
414 AFD_DbgPrint(MIN_TRACE
, ("IOCTL_AFD_GET_CONNECT_DATA\n"));
417 case IOCTL_AFD_GET_CONNECT_OPTIONS
:
418 AFD_DbgPrint(MIN_TRACE
, ("IOCTL_AFD_GET_CONNECT_OPTIONS\n"));
421 case IOCTL_AFD_GET_DISCONNECT_DATA
:
422 AFD_DbgPrint(MIN_TRACE
, ("IOCTL_AFD_GET_DISCONNECT_DATA\n"));
425 case IOCTL_AFD_GET_DISCONNECT_OPTIONS
:
426 AFD_DbgPrint(MIN_TRACE
, ("IOCTL_AFD_GET_DISCONNECT_OPTIONS\n"));
429 case IOCTL_AFD_SET_CONNECT_DATA_SIZE
:
430 AFD_DbgPrint(MIN_TRACE
, ("IOCTL_AFD_SET_CONNECT_DATA_SIZE\n"));
433 case IOCTL_AFD_SET_CONNECT_OPTIONS_SIZE
:
434 AFD_DbgPrint(MIN_TRACE
, ("IOCTL_AFD_SET_CONNECT_OPTIONS_SIZE\n"));
437 case IOCTL_AFD_SET_DISCONNECT_DATA_SIZE
:
438 AFD_DbgPrint(MIN_TRACE
, ("IOCTL_AFD_SET_DISCONNECT_DATA_SIZE\n"));
441 case IOCTL_AFD_SET_DISCONNECT_OPTIONS_SIZE
:
442 AFD_DbgPrint(MIN_TRACE
, ("IOCTL_AFD_SET_DISCONNECT_OPTIONS_SIZE\n"));
445 case IOCTL_AFD_DEFER_ACCEPT
:
446 AFD_DbgPrint(MIN_TRACE
, ("IOCTL_AFD_DEFER_ACCEPT\n"));
449 case IOCTL_AFD_GET_PENDING_CONNECT_DATA
:
450 AFD_DbgPrint(MIN_TRACE
, ("IOCTL_AFD_GET_PENDING_CONNECT_DATA\n"));
454 Status
= STATUS_NOT_IMPLEMENTED
;
455 Irp
->IoStatus
.Information
= 0;
456 AFD_DbgPrint(MIN_TRACE
, ("Unknown IOCTL (0x%x)\n",
457 IrpSp
->Parameters
.DeviceIoControl
.
464 /* unsupported operations */
467 Status
= STATUS_NOT_IMPLEMENTED
;
468 AFD_DbgPrint(MIN_TRACE
,
469 ("Irp: Unknown Major code was %x\n",
470 IrpSp
->MajorFunction
));
475 AFD_DbgPrint(MID_TRACE
, ("Returning %x\n", Status
));
476 Irp
->IoStatus
.Status
= Status
;
477 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
483 AfdUnload(PDRIVER_OBJECT DriverObject
)
488 DriverEntry(PDRIVER_OBJECT DriverObject
, PUNICODE_STRING RegistryPath
)
490 PDEVICE_OBJECT DeviceObject
;
491 UNICODE_STRING wstrDeviceName
= RTL_CONSTANT_STRING(L
"\\Device\\Afd");
492 PAFD_DEVICE_EXTENSION DeviceExt
;
495 /* register driver routines */
496 DriverObject
->MajorFunction
[IRP_MJ_CLOSE
] = AfdDispatch
;
497 DriverObject
->MajorFunction
[IRP_MJ_CREATE
] = AfdDispatch
;
498 DriverObject
->MajorFunction
[IRP_MJ_WRITE
] = AfdDispatch
;
499 DriverObject
->MajorFunction
[IRP_MJ_READ
] = AfdDispatch
;
500 DriverObject
->MajorFunction
[IRP_MJ_DEVICE_CONTROL
] = AfdDispatch
;
501 DriverObject
->DriverUnload
= AfdUnload
;
503 Status
= IoCreateDevice
505 sizeof(AFD_DEVICE_EXTENSION
),
507 FILE_DEVICE_NAMED_PIPE
,
513 if(!NT_SUCCESS(Status
))
518 DeviceExt
= DeviceObject
->DeviceExtension
;
519 KeInitializeSpinLock( &DeviceExt
->Lock
);
520 InitializeListHead( &DeviceExt
->Polls
);
522 AFD_DbgPrint(MID_TRACE
,("Device created: object %x ext %x\n",
523 DeviceObject
, DeviceExt
));