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 DriverEntry(PDRIVER_OBJECT DriverObject
, PUNICODE_STRING RegistryPath
);
45 AfdCreateSocket(PDEVICE_OBJECT DeviceObject
, PIRP Irp
,
46 PIO_STACK_LOCATION IrpSp
) {
48 PFILE_OBJECT FileObject
;
49 PAFD_DEVICE_EXTENSION DeviceExt
;
50 PFILE_FULL_EA_INFORMATION EaInfo
;
51 PAFD_CREATE_PACKET ConnectInfo
= NULL
;
53 PWCHAR EaInfoValue
= NULL
;
55 NTSTATUS Status
= STATUS_SUCCESS
;
57 AFD_DbgPrint(MID_TRACE
,
58 ("AfdCreate(DeviceObject %p Irp %p)\n", DeviceObject
, Irp
));
60 DeviceExt
= DeviceObject
->DeviceExtension
;
61 FileObject
= IrpSp
->FileObject
;
62 Disposition
= (IrpSp
->Parameters
.Create
.Options
>> 24) & 0xff;
64 Irp
->IoStatus
.Information
= 0;
66 EaInfo
= Irp
->AssociatedIrp
.SystemBuffer
;
69 ConnectInfo
= (PAFD_CREATE_PACKET
)(EaInfo
->EaName
+ EaInfo
->EaNameLength
+ 1);
70 EaInfoValue
= (PWCHAR
)(((PCHAR
)ConnectInfo
) + sizeof(AFD_CREATE_PACKET
));
72 EaLength
= sizeof(FILE_FULL_EA_INFORMATION
) +
73 EaInfo
->EaNameLength
+
74 EaInfo
->EaValueLength
;
76 AFD_DbgPrint(MID_TRACE
,("EaInfo: %x, EaInfoValue: %x\n",
77 EaInfo
, EaInfoValue
));
80 AFD_DbgPrint(MID_TRACE
,("About to allocate the new FCB\n"));
82 FCB
= ExAllocatePool(NonPagedPool
, sizeof(AFD_FCB
));
84 Irp
->IoStatus
.Status
= STATUS_NO_MEMORY
;
85 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
86 return STATUS_NO_MEMORY
;
89 AFD_DbgPrint(MID_TRACE
,("Initializing the new FCB @ %x (FileObject %x Flags %x)\n", FCB
, FileObject
, ConnectInfo
? ConnectInfo
->EndpointFlags
: 0));
91 RtlZeroMemory( FCB
, sizeof( *FCB
) );
93 FCB
->Flags
= ConnectInfo
? ConnectInfo
->EndpointFlags
: 0;
94 FCB
->State
= SOCKET_STATE_CREATED
;
95 FCB
->FileObject
= FileObject
;
96 FCB
->DeviceExt
= DeviceExt
;
97 FCB
->Recv
.Size
= DEFAULT_RECEIVE_WINDOW_SIZE
;
98 FCB
->Send
.Size
= DEFAULT_SEND_WINDOW_SIZE
;
100 KeInitializeSpinLock( &FCB
->SpinLock
);
101 ExInitializeFastMutex( &FCB
->Mutex
);
102 KeInitializeEvent( &FCB
->StateLockedEvent
, NotificationEvent
, FALSE
);
104 for( i
= 0; i
< MAX_FUNCTIONS
; i
++ ) {
105 InitializeListHead( &FCB
->PendingIrpList
[i
] );
108 InitializeListHead( &FCB
->DatagramList
);
109 InitializeListHead( &FCB
->PendingConnections
);
111 AFD_DbgPrint(MID_TRACE
,("%x: Checking command channel\n", FCB
));
114 FCB
->TdiDeviceName
.Length
= ConnectInfo
->SizeOfTransportName
;
115 FCB
->TdiDeviceName
.MaximumLength
= FCB
->TdiDeviceName
.Length
;
116 FCB
->TdiDeviceName
.Buffer
=
117 ExAllocatePool( NonPagedPool
, FCB
->TdiDeviceName
.Length
);
119 if( !FCB
->TdiDeviceName
.Buffer
) {
121 AFD_DbgPrint(MID_TRACE
,("Could not copy target string\n"));
122 Irp
->IoStatus
.Status
= STATUS_NO_MEMORY
;
123 IoCompleteRequest( Irp
, IO_NETWORK_INCREMENT
);
124 return STATUS_NO_MEMORY
;
127 RtlCopyMemory( FCB
->TdiDeviceName
.Buffer
,
128 ConnectInfo
->TransportName
,
129 FCB
->TdiDeviceName
.Length
);
131 AFD_DbgPrint(MID_TRACE
,("Success: %s %wZ\n",
132 EaInfo
->EaName
, &FCB
->TdiDeviceName
));
134 AFD_DbgPrint(MID_TRACE
,("Success: Control connection\n"));
137 FileObject
->FsContext
= FCB
;
139 /* It seems that UDP sockets are writable from inception */
140 if( FCB
->Flags
& SGID_CONNECTIONLESS
) {
141 AFD_DbgPrint(MID_TRACE
,("Packet oriented socket\n"));
142 /* Allocate our backup buffer */
143 FCB
->Recv
.Window
= ExAllocatePool( NonPagedPool
, FCB
->Recv
.Size
);
144 if( !FCB
->Recv
.Window
) Status
= STATUS_NO_MEMORY
;
145 if( NT_SUCCESS(Status
) )
147 FCB
->Send
.Window
= ExAllocatePool( NonPagedPool
, FCB
->Send
.Size
);
148 if( !FCB
->Send
.Window
) {
149 if( FCB
->Recv
.Window
) ExFreePool( FCB
->Recv
.Window
);
150 Status
= STATUS_NO_MEMORY
;
153 /* A datagram socket is always sendable */
154 FCB
->PollState
|= AFD_EVENT_SEND
;
155 PollReeval( FCB
->DeviceExt
, FCB
->FileObject
);
158 if( !NT_SUCCESS(Status
) ) {
159 if( FCB
->TdiDeviceName
.Buffer
) ExFreePool( FCB
->TdiDeviceName
.Buffer
);
161 FileObject
->FsContext
= NULL
;
164 Irp
->IoStatus
.Status
= Status
;
165 IoCompleteRequest( Irp
, IO_NETWORK_INCREMENT
);
170 VOID
CleanupSocket( PAFD_FCB FCB
) {
172 PAFD_IN_FLIGHT_REQUEST InFlightRequest
[IN_FLIGHT_REQUESTS
];
174 AFD_DbgPrint(MIN_TRACE
,("Called (%x)\n", FCB
));
176 if( !SocketAcquireStateLock( FCB
) ) return;
178 FCB
->State
= SOCKET_STATE_CLOSED
;
180 InFlightRequest
[0] = &FCB
->ListenIrp
;
181 InFlightRequest
[1] = &FCB
->ReceiveIrp
;
182 InFlightRequest
[2] = &FCB
->SendIrp
;
183 InFlightRequest
[3] = &FCB
->ConnectIrp
;
185 /* Cancel our pending requests */
186 for( i
= 0; i
< IN_FLIGHT_REQUESTS
; i
++ ) {
187 if( InFlightRequest
[i
]->InFlightRequest
) {
188 AFD_DbgPrint(MID_TRACE
,("Cancelling in flight irp %d (%x)\n",
189 i
, InFlightRequest
[i
]->InFlightRequest
));
190 IoCancelIrp(InFlightRequest
[i
]->InFlightRequest
);
194 FCB
->State
= SOCKET_STATE_CREATED
;
196 if( FCB
->EventSelect
) {
197 ObDereferenceObject( FCB
->EventSelect
);
198 FCB
->EventSelect
= NULL
;
201 ExFreePool( FCB
->Context
);
204 if( FCB
->Recv
.Window
) {
205 ExFreePool( FCB
->Recv
.Window
);
206 FCB
->Recv
.Window
= NULL
;
208 if( FCB
->Send
.Window
) {
209 ExFreePool( FCB
->Send
.Window
);
210 FCB
->Send
.Window
= NULL
;
212 if( FCB
->AddressFrom
) {
213 ExFreePool( FCB
->AddressFrom
);
214 FCB
->AddressFrom
= NULL
;
216 if( FCB
->LocalAddress
) {
217 ExFreePool( FCB
->LocalAddress
);
218 FCB
->LocalAddress
= NULL
;
220 if( FCB
->RemoteAddress
) {
221 ExFreePool( FCB
->RemoteAddress
);
222 FCB
->RemoteAddress
= NULL
;
224 if( FCB
->Connection
.Object
) {
225 NtClose(FCB
->Connection
.Handle
);
226 ObDereferenceObject(FCB
->Connection
.Object
);
227 FCB
->Connection
.Object
= NULL
;
229 if( FCB
->AddressFile
.Object
) {
230 NtClose(FCB
->AddressFile
.Handle
);
231 ObDereferenceObject(FCB
->AddressFile
.Object
);
232 FCB
->AddressFile
.Object
= NULL
;
235 SocketStateUnlock( FCB
);
238 VOID
DestroySocket( PAFD_FCB FCB
) {
239 if( FCB
->TdiDeviceName
.Buffer
)
240 ExFreePool(FCB
->TdiDeviceName
.Buffer
);
243 AFD_DbgPrint(MIN_TRACE
,("Deleted (%x)\n", FCB
));
246 static NTSTATUS NTAPI
247 AfdCloseSocket(PDEVICE_OBJECT DeviceObject
, PIRP Irp
,
248 PIO_STACK_LOCATION IrpSp
)
250 PFILE_OBJECT FileObject
= IrpSp
->FileObject
;
251 PAFD_FCB FCB
= FileObject
->FsContext
;
253 AFD_DbgPrint(MID_TRACE
,
254 ("AfdClose(DeviceObject %p Irp %p)\n", DeviceObject
, Irp
));
256 if( !SocketAcquireStateLock( FCB
) ) return LostSocket( Irp
);
258 AFD_DbgPrint(MID_TRACE
,("FCB %x\n", FCB
));
260 FileObject
->FsContext
= NULL
;
261 SocketStateUnlock( FCB
);
263 DestroySocket( FCB
);
265 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
266 Irp
->IoStatus
.Information
= 0;
267 IoCompleteRequest(Irp
, IO_NETWORK_INCREMENT
);
269 AFD_DbgPrint(MID_TRACE
, ("Returning success.\n"));
271 return STATUS_SUCCESS
;
274 static NTSTATUS NTAPI
275 AfdCleanupSocket(PDEVICE_OBJECT DeviceObject
, PIRP Irp
,
276 PIO_STACK_LOCATION IrpSp
)
278 PFILE_OBJECT FileObject
= IrpSp
->FileObject
;
279 PAFD_FCB FCB
= FileObject
->FsContext
;
281 if( !SocketAcquireStateLock( FCB
) ) return LostSocket( Irp
);
283 CleanupSocket( FCB
);
285 KillSelectsForFCB( FCB
->DeviceExt
, FileObject
, FALSE
);
287 SocketStateUnlock( FCB
);
289 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
290 Irp
->IoStatus
.Information
= 0;
291 IoCompleteRequest(Irp
, IO_NETWORK_INCREMENT
);
293 return STATUS_SUCCESS
;
296 static NTSTATUS NTAPI
297 AfdDisconnect(PDEVICE_OBJECT DeviceObject
, PIRP Irp
,
298 PIO_STACK_LOCATION IrpSp
) {
299 PFILE_OBJECT FileObject
= IrpSp
->FileObject
;
300 PAFD_FCB FCB
= FileObject
->FsContext
;
301 PAFD_DISCONNECT_INFO DisReq
;
302 IO_STATUS_BLOCK Iosb
;
303 PTDI_CONNECTION_INFORMATION ConnInfo
;
307 if( !SocketAcquireStateLock( FCB
) ) return LostSocket( Irp
);
309 if( !(DisReq
= LockRequest( Irp
, IrpSp
)) )
310 return UnlockAndMaybeComplete( FCB
, STATUS_NO_MEMORY
,
313 if (NULL
== FCB
->RemoteAddress
)
319 Status
= TdiBuildNullConnectionInfo
320 ( &ConnInfo
, FCB
->RemoteAddress
->Address
[0].AddressType
);
322 if( !NT_SUCCESS(Status
) || !ConnInfo
)
323 return UnlockAndMaybeComplete( FCB
, STATUS_NO_MEMORY
,
327 if( DisReq
->DisconnectType
& AFD_DISCONNECT_SEND
)
328 Flags
|= TDI_DISCONNECT_RELEASE
;
329 if( DisReq
->DisconnectType
& AFD_DISCONNECT_RECV
||
330 DisReq
->DisconnectType
& AFD_DISCONNECT_ABORT
)
331 Flags
|= TDI_DISCONNECT_ABORT
;
333 Status
= TdiDisconnect( FCB
->Connection
.Object
,
342 if (ConnInfo
) ExFreePool( ConnInfo
);
344 return UnlockAndMaybeComplete( FCB
, Status
, Irp
, 0 );
347 static NTSTATUS NTAPI
348 AfdDispatch(PDEVICE_OBJECT DeviceObject
, PIRP Irp
)
350 PIO_STACK_LOCATION IrpSp
= IoGetCurrentIrpStackLocation(Irp
);
351 NTSTATUS Status
= STATUS_SUCCESS
;
353 PFILE_OBJECT FileObject
= IrpSp
->FileObject
;
356 AFD_DbgPrint(MID_TRACE
,("AfdDispatch: %d\n", IrpSp
->MajorFunction
));
357 if( IrpSp
->MajorFunction
!= IRP_MJ_CREATE
) {
358 AFD_DbgPrint(MID_TRACE
,("FO %x, IrpSp->FO %x\n",
359 FileObject
, IrpSp
->FileObject
));
360 ASSERT(FileObject
== IrpSp
->FileObject
);
363 Irp
->IoStatus
.Information
= 0;
365 switch(IrpSp
->MajorFunction
)
367 /* opening and closing handles to the device */
369 /* Mostly borrowed from the named pipe file system */
370 return AfdCreateSocket(DeviceObject
, Irp
, IrpSp
);
373 /* Ditto the borrowing */
374 return AfdCloseSocket(DeviceObject
, Irp
, IrpSp
);
377 return AfdCleanupSocket(DeviceObject
, Irp
, IrpSp
);
381 return AfdConnectedSocketWriteData( DeviceObject
, Irp
, IrpSp
, TRUE
);
385 return AfdConnectedSocketReadData( DeviceObject
, Irp
, IrpSp
, TRUE
);
387 case IRP_MJ_DEVICE_CONTROL
:
389 switch( IrpSp
->Parameters
.DeviceIoControl
.IoControlCode
) {
391 return AfdBindSocket( DeviceObject
, Irp
, IrpSp
);
393 case IOCTL_AFD_CONNECT
:
394 return AfdStreamSocketConnect( DeviceObject
, Irp
, IrpSp
);
396 case IOCTL_AFD_START_LISTEN
:
397 return AfdListenSocket( DeviceObject
, Irp
, IrpSp
);
400 return AfdConnectedSocketReadData( DeviceObject
, Irp
, IrpSp
,
403 case IOCTL_AFD_SELECT
:
404 return AfdSelect( DeviceObject
, Irp
, IrpSp
);
406 case IOCTL_AFD_EVENT_SELECT
:
407 return AfdEventSelect( DeviceObject
, Irp
, IrpSp
);
409 case IOCTL_AFD_ENUM_NETWORK_EVENTS
:
410 return AfdEnumEvents( DeviceObject
, Irp
, IrpSp
);
412 case IOCTL_AFD_RECV_DATAGRAM
:
413 return AfdPacketSocketReadData( DeviceObject
, Irp
, IrpSp
);
416 return AfdConnectedSocketWriteData( DeviceObject
, Irp
, IrpSp
,
419 case IOCTL_AFD_SEND_DATAGRAM
:
420 return AfdPacketSocketWriteData( DeviceObject
, Irp
, IrpSp
);
422 case IOCTL_AFD_GET_INFO
:
423 return AfdGetInfo( DeviceObject
, Irp
, IrpSp
);
425 case IOCTL_AFD_GET_CONTEXT
:
426 return AfdGetContext( DeviceObject
, Irp
, IrpSp
);
428 case IOCTL_AFD_SET_CONTEXT
:
429 return AfdSetContext( DeviceObject
, Irp
, IrpSp
);
431 case IOCTL_AFD_WAIT_FOR_LISTEN
:
432 return AfdWaitForListen( DeviceObject
, Irp
, IrpSp
);
434 case IOCTL_AFD_ACCEPT
:
435 return AfdAccept( DeviceObject
, Irp
, IrpSp
);
437 case IOCTL_AFD_DISCONNECT
:
438 return AfdDisconnect( DeviceObject
, Irp
, IrpSp
);
440 case IOCTL_AFD_GET_SOCK_NAME
:
441 return AfdGetSockName( DeviceObject
, Irp
, IrpSp
);
443 case IOCTL_AFD_GET_PEER_NAME
:
444 return AfdGetPeerName( DeviceObject
, Irp
, IrpSp
);
446 case IOCTL_AFD_GET_TDI_HANDLES
:
447 AFD_DbgPrint(MIN_TRACE
, ("IOCTL_AFD_GET_TDI_HANDLES\n"));
450 case IOCTL_AFD_SET_INFO
:
451 AFD_DbgPrint(MIN_TRACE
, ("IOCTL_AFD_SET_INFO\n"));
454 case IOCTL_AFD_SET_CONNECT_DATA
:
455 AFD_DbgPrint(MIN_TRACE
, ("IOCTL_AFD_SET_CONNECT_DATA\n"));
458 case IOCTL_AFD_SET_CONNECT_OPTIONS
:
459 AFD_DbgPrint(MIN_TRACE
, ("IOCTL_AFD_SET_CONNECT_OPTIONS\n"));
462 case IOCTL_AFD_SET_DISCONNECT_DATA
:
463 AFD_DbgPrint(MIN_TRACE
, ("IOCTL_AFD_SET_DISCONNECT_DATA\n"));
466 case IOCTL_AFD_SET_DISCONNECT_OPTIONS
:
467 AFD_DbgPrint(MIN_TRACE
, ("IOCTL_AFD_SET_DISCONNECT_OPTIONS\n"));
470 case IOCTL_AFD_GET_CONNECT_DATA
:
471 AFD_DbgPrint(MIN_TRACE
, ("IOCTL_AFD_GET_CONNECT_DATA\n"));
474 case IOCTL_AFD_GET_CONNECT_OPTIONS
:
475 AFD_DbgPrint(MIN_TRACE
, ("IOCTL_AFD_GET_CONNECT_OPTIONS\n"));
478 case IOCTL_AFD_GET_DISCONNECT_DATA
:
479 AFD_DbgPrint(MIN_TRACE
, ("IOCTL_AFD_GET_DISCONNECT_DATA\n"));
482 case IOCTL_AFD_GET_DISCONNECT_OPTIONS
:
483 AFD_DbgPrint(MIN_TRACE
, ("IOCTL_AFD_GET_DISCONNECT_OPTIONS\n"));
486 case IOCTL_AFD_SET_CONNECT_DATA_SIZE
:
487 AFD_DbgPrint(MIN_TRACE
, ("IOCTL_AFD_SET_CONNECT_DATA_SIZE\n"));
490 case IOCTL_AFD_SET_CONNECT_OPTIONS_SIZE
:
491 AFD_DbgPrint(MIN_TRACE
, ("IOCTL_AFD_SET_CONNECT_OPTIONS_SIZE\n"));
494 case IOCTL_AFD_SET_DISCONNECT_DATA_SIZE
:
495 AFD_DbgPrint(MIN_TRACE
, ("IOCTL_AFD_SET_DISCONNECT_DATA_SIZE\n"));
498 case IOCTL_AFD_SET_DISCONNECT_OPTIONS_SIZE
:
499 AFD_DbgPrint(MIN_TRACE
, ("IOCTL_AFD_SET_DISCONNECT_OPTIONS_SIZE\n"));
502 case IOCTL_AFD_DEFER_ACCEPT
:
503 AFD_DbgPrint(MIN_TRACE
, ("IOCTL_AFD_DEFER_ACCEPT\n"));
506 case IOCTL_AFD_GET_PENDING_CONNECT_DATA
:
507 AFD_DbgPrint(MIN_TRACE
, ("IOCTL_AFD_GET_PENDING_CONNECT_DATA\n"));
511 Status
= STATUS_NOT_IMPLEMENTED
;
512 AFD_DbgPrint(MIN_TRACE
, ("Unknown IOCTL (0x%x)\n",
513 IrpSp
->Parameters
.DeviceIoControl
.
520 /* unsupported operations */
523 Status
= STATUS_NOT_IMPLEMENTED
;
524 AFD_DbgPrint(MIN_TRACE
,
525 ("Irp: Unknown Major code was %x\n",
526 IrpSp
->MajorFunction
));
531 AFD_DbgPrint(MID_TRACE
, ("Returning %x\n", Status
));
532 Irp
->IoStatus
.Status
= Status
;
533 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
539 AfdUnload(PDRIVER_OBJECT DriverObject
)
544 DriverEntry(PDRIVER_OBJECT DriverObject
, PUNICODE_STRING RegistryPath
)
546 PDEVICE_OBJECT DeviceObject
;
547 UNICODE_STRING wstrDeviceName
= RTL_CONSTANT_STRING(L
"\\Device\\Afd");
548 PAFD_DEVICE_EXTENSION DeviceExt
;
551 /* register driver routines */
552 DriverObject
->MajorFunction
[IRP_MJ_CLOSE
] = AfdDispatch
;
553 DriverObject
->MajorFunction
[IRP_MJ_CREATE
] = AfdDispatch
;
554 DriverObject
->MajorFunction
[IRP_MJ_CLEANUP
] = AfdDispatch
;
555 DriverObject
->MajorFunction
[IRP_MJ_WRITE
] = AfdDispatch
;
556 DriverObject
->MajorFunction
[IRP_MJ_READ
] = AfdDispatch
;
557 DriverObject
->MajorFunction
[IRP_MJ_DEVICE_CONTROL
] = AfdDispatch
;
558 DriverObject
->DriverUnload
= AfdUnload
;
560 Status
= IoCreateDevice
562 sizeof(AFD_DEVICE_EXTENSION
),
564 FILE_DEVICE_NAMED_PIPE
,
570 if(!NT_SUCCESS(Status
))
575 DeviceExt
= DeviceObject
->DeviceExtension
;
576 KeInitializeSpinLock( &DeviceExt
->Lock
);
577 InitializeListHead( &DeviceExt
->Polls
);
579 AFD_DbgPrint(MID_TRACE
,("Device created: object %x ext %x\n",
580 DeviceObject
, DeviceExt
));