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)
19 /* See debug.h for debug/trace constants */
20 //DWORD DebugTraceLevel = DEBUG_ULTRA;
21 DWORD DebugTraceLevel
= MIN_TRACE
;
25 void OskitDumpBuffer( PCHAR Data
, UINT Len
) {
28 for( i
= 0; i
< Len
; i
++ ) {
29 if( i
&& !(i
& 0xf) ) DbgPrint( "\n" );
30 if( !(i
& 0xf) ) DbgPrint( "%p: ", (Data
+ i
) );
31 DbgPrint( " %02x", Data
[i
] & 0xff );
39 DriverEntry(PDRIVER_OBJECT DriverObject
, PUNICODE_STRING RegistryPath
);
42 AfdGetDisconnectOptions(PDEVICE_OBJECT DeviceObject
, PIRP Irp
,
43 PIO_STACK_LOCATION IrpSp
)
45 PFILE_OBJECT FileObject
= IrpSp
->FileObject
;
46 PAFD_FCB FCB
= FileObject
->FsContext
;
47 UINT BufferSize
= IrpSp
->Parameters
.DeviceIoControl
.OutputBufferLength
;
49 UNREFERENCED_PARAMETER(DeviceObject
);
51 if (!SocketAcquireStateLock(FCB
)) return LostSocket(Irp
);
53 if (FCB
->DisconnectOptionsSize
== 0)
55 AFD_DbgPrint(MIN_TRACE
,("Invalid parameter\n"));
56 return UnlockAndMaybeComplete(FCB
, STATUS_INVALID_PARAMETER
, Irp
, 0);
59 ASSERT(FCB
->DisconnectOptions
);
61 if (FCB
->FilledDisconnectOptions
< BufferSize
) BufferSize
= FCB
->FilledDisconnectOptions
;
63 RtlCopyMemory(Irp
->UserBuffer
,
64 FCB
->DisconnectOptions
,
67 return UnlockAndMaybeComplete(FCB
, STATUS_SUCCESS
, Irp
, BufferSize
);
72 AfdSetDisconnectOptions(PDEVICE_OBJECT DeviceObject
, PIRP Irp
,
73 PIO_STACK_LOCATION IrpSp
)
75 PFILE_OBJECT FileObject
= IrpSp
->FileObject
;
76 PAFD_FCB FCB
= FileObject
->FsContext
;
77 PVOID DisconnectOptions
= LockRequest(Irp
, IrpSp
, FALSE
, NULL
);
78 UINT DisconnectOptionsSize
= IrpSp
->Parameters
.DeviceIoControl
.InputBufferLength
;
80 UNREFERENCED_PARAMETER(DeviceObject
);
82 if (!SocketAcquireStateLock(FCB
)) return LostSocket(Irp
);
84 if (!DisconnectOptions
)
85 return UnlockAndMaybeComplete(FCB
, STATUS_NO_MEMORY
, Irp
, 0);
87 if (FCB
->DisconnectOptions
)
89 ExFreePoolWithTag(FCB
->DisconnectOptions
, TAG_AFD_DISCONNECT_OPTIONS
);
90 FCB
->DisconnectOptions
= NULL
;
91 FCB
->DisconnectOptionsSize
= 0;
92 FCB
->FilledDisconnectOptions
= 0;
95 FCB
->DisconnectOptions
= ExAllocatePoolWithTag(PagedPool
,
96 DisconnectOptionsSize
,
97 TAG_AFD_DISCONNECT_OPTIONS
);
99 if (!FCB
->DisconnectOptions
)
100 return UnlockAndMaybeComplete(FCB
, STATUS_NO_MEMORY
, Irp
, 0);
102 RtlCopyMemory(FCB
->DisconnectOptions
,
104 DisconnectOptionsSize
);
106 FCB
->DisconnectOptionsSize
= DisconnectOptionsSize
;
108 return UnlockAndMaybeComplete(FCB
, STATUS_SUCCESS
, Irp
, 0);
113 AfdSetDisconnectOptionsSize(PDEVICE_OBJECT DeviceObject
, PIRP Irp
,
114 PIO_STACK_LOCATION IrpSp
)
116 PFILE_OBJECT FileObject
= IrpSp
->FileObject
;
117 PAFD_FCB FCB
= FileObject
->FsContext
;
118 PUINT DisconnectOptionsSize
= LockRequest(Irp
, IrpSp
, FALSE
, NULL
);
119 UINT BufferSize
= IrpSp
->Parameters
.DeviceIoControl
.InputBufferLength
;
121 UNREFERENCED_PARAMETER(DeviceObject
);
123 if (!SocketAcquireStateLock(FCB
)) return LostSocket(Irp
);
125 if (!DisconnectOptionsSize
)
126 return UnlockAndMaybeComplete(FCB
, STATUS_NO_MEMORY
, Irp
, 0);
128 if (BufferSize
< sizeof(UINT
))
130 AFD_DbgPrint(MIN_TRACE
,("Buffer too small\n"));
131 return UnlockAndMaybeComplete(FCB
, STATUS_BUFFER_TOO_SMALL
, Irp
, 0);
134 if (FCB
->DisconnectOptions
)
136 ExFreePoolWithTag(FCB
->DisconnectOptions
, TAG_AFD_DISCONNECT_OPTIONS
);
137 FCB
->DisconnectOptionsSize
= 0;
138 FCB
->FilledDisconnectOptions
= 0;
141 FCB
->DisconnectOptions
= ExAllocatePoolWithTag(PagedPool
,
142 *DisconnectOptionsSize
,
143 TAG_AFD_DISCONNECT_OPTIONS
);
145 if (!FCB
->DisconnectOptions
) return UnlockAndMaybeComplete(FCB
, STATUS_NO_MEMORY
, Irp
, 0);
147 FCB
->DisconnectOptionsSize
= *DisconnectOptionsSize
;
149 return UnlockAndMaybeComplete(FCB
, STATUS_SUCCESS
, Irp
, 0);
153 AfdGetDisconnectData(PDEVICE_OBJECT DeviceObject
, PIRP Irp
,
154 PIO_STACK_LOCATION IrpSp
)
156 PFILE_OBJECT FileObject
= IrpSp
->FileObject
;
157 PAFD_FCB FCB
= FileObject
->FsContext
;
158 UINT BufferSize
= IrpSp
->Parameters
.DeviceIoControl
.OutputBufferLength
;
160 UNREFERENCED_PARAMETER(DeviceObject
);
162 if (!SocketAcquireStateLock(FCB
)) return LostSocket(Irp
);
164 if (FCB
->DisconnectDataSize
== 0)
166 AFD_DbgPrint(MIN_TRACE
,("Invalid parameter\n"));
167 return UnlockAndMaybeComplete(FCB
, STATUS_INVALID_PARAMETER
, Irp
, 0);
170 ASSERT(FCB
->DisconnectData
);
172 if (FCB
->FilledDisconnectData
< BufferSize
)
173 BufferSize
= FCB
->FilledDisconnectData
;
175 RtlCopyMemory(Irp
->UserBuffer
,
179 return UnlockAndMaybeComplete(FCB
, STATUS_SUCCESS
, Irp
, BufferSize
);
184 AfdSetDisconnectData(PDEVICE_OBJECT DeviceObject
, PIRP Irp
,
185 PIO_STACK_LOCATION IrpSp
)
187 PFILE_OBJECT FileObject
= IrpSp
->FileObject
;
188 PAFD_FCB FCB
= FileObject
->FsContext
;
189 PVOID DisconnectData
= LockRequest(Irp
, IrpSp
, FALSE
, NULL
);
190 UINT DisconnectDataSize
= IrpSp
->Parameters
.DeviceIoControl
.InputBufferLength
;
192 UNREFERENCED_PARAMETER(DeviceObject
);
194 if (!SocketAcquireStateLock(FCB
)) return LostSocket(Irp
);
197 return UnlockAndMaybeComplete(FCB
, STATUS_NO_MEMORY
, Irp
, 0);
199 if (FCB
->DisconnectData
)
201 ExFreePoolWithTag(FCB
->DisconnectData
, TAG_AFD_DISCONNECT_DATA
);
202 FCB
->DisconnectData
= NULL
;
203 FCB
->DisconnectDataSize
= 0;
204 FCB
->FilledDisconnectData
= 0;
207 FCB
->DisconnectData
= ExAllocatePoolWithTag(PagedPool
,
209 TAG_AFD_DISCONNECT_DATA
);
211 if (!FCB
->DisconnectData
)
212 return UnlockAndMaybeComplete(FCB
, STATUS_NO_MEMORY
, Irp
, 0);
214 RtlCopyMemory(FCB
->DisconnectData
,
218 FCB
->DisconnectDataSize
= DisconnectDataSize
;
220 return UnlockAndMaybeComplete(FCB
, STATUS_SUCCESS
, Irp
, 0);
225 AfdSetDisconnectDataSize(PDEVICE_OBJECT DeviceObject
, PIRP Irp
,
226 PIO_STACK_LOCATION IrpSp
)
228 PFILE_OBJECT FileObject
= IrpSp
->FileObject
;
229 PAFD_FCB FCB
= FileObject
->FsContext
;
230 PUINT DisconnectDataSize
= LockRequest(Irp
, IrpSp
, FALSE
, NULL
);
231 UINT BufferSize
= IrpSp
->Parameters
.DeviceIoControl
.InputBufferLength
;
233 UNREFERENCED_PARAMETER(DeviceObject
);
235 if (!SocketAcquireStateLock(FCB
)) return LostSocket(Irp
);
237 if (!DisconnectDataSize
)
238 return UnlockAndMaybeComplete(FCB
, STATUS_NO_MEMORY
, Irp
, 0);
240 if (BufferSize
< sizeof(UINT
))
242 AFD_DbgPrint(MIN_TRACE
,("Buffer too small\n"));
243 return UnlockAndMaybeComplete(FCB
, STATUS_BUFFER_TOO_SMALL
, Irp
, 0);
246 if (FCB
->DisconnectData
)
248 ExFreePoolWithTag(FCB
->DisconnectData
, TAG_AFD_DISCONNECT_DATA
);
249 FCB
->DisconnectDataSize
= 0;
250 FCB
->FilledDisconnectData
= 0;
253 FCB
->DisconnectData
= ExAllocatePoolWithTag(PagedPool
,
255 TAG_AFD_DISCONNECT_DATA
);
257 if (!FCB
->DisconnectData
)
258 return UnlockAndMaybeComplete(FCB
, STATUS_NO_MEMORY
, Irp
, 0);
260 FCB
->DisconnectDataSize
= *DisconnectDataSize
;
262 return UnlockAndMaybeComplete(FCB
, STATUS_SUCCESS
, Irp
, 0);
265 static NTSTATUS NTAPI
266 AfdGetTdiHandles(PDEVICE_OBJECT DeviceObject
, PIRP Irp
,
267 PIO_STACK_LOCATION IrpSp
)
269 PFILE_OBJECT FileObject
= IrpSp
->FileObject
;
270 PAFD_FCB FCB
= FileObject
->FsContext
;
271 PULONG HandleFlags
= LockRequest(Irp
, IrpSp
, TRUE
, NULL
);
272 PAFD_TDI_HANDLE_DATA HandleData
= Irp
->UserBuffer
;
274 UNREFERENCED_PARAMETER(DeviceObject
);
276 if (!SocketAcquireStateLock(FCB
)) return LostSocket(Irp
);
279 return UnlockAndMaybeComplete(FCB
, STATUS_NO_MEMORY
, Irp
, 0);
281 if (IrpSp
->Parameters
.DeviceIoControl
.InputBufferLength
< sizeof(ULONG
) ||
282 IrpSp
->Parameters
.DeviceIoControl
.OutputBufferLength
< sizeof(*HandleData
))
284 AFD_DbgPrint(MIN_TRACE
,("Buffer too small\n"));
285 return UnlockAndMaybeComplete(FCB
, STATUS_BUFFER_TOO_SMALL
, Irp
, 0);
288 if ((*HandleFlags
) & AFD_ADDRESS_HANDLE
)
289 HandleData
->TdiAddressHandle
= FCB
->AddressFile
.Handle
;
291 if ((*HandleFlags
) & AFD_CONNECTION_HANDLE
)
292 HandleData
->TdiConnectionHandle
= FCB
->Connection
.Handle
;
294 return UnlockAndMaybeComplete(FCB
, STATUS_SUCCESS
, Irp
, 0);
297 static NTSTATUS NTAPI
298 AfdCreateSocket(PDEVICE_OBJECT DeviceObject
, PIRP Irp
,
299 PIO_STACK_LOCATION IrpSp
) {
301 PFILE_OBJECT FileObject
;
302 PAFD_DEVICE_EXTENSION DeviceExt
;
303 PFILE_FULL_EA_INFORMATION EaInfo
;
304 PAFD_CREATE_PACKET ConnectInfo
= NULL
;
306 PWCHAR EaInfoValue
= NULL
;
309 NTSTATUS Status
= STATUS_SUCCESS
;
311 AFD_DbgPrint(MID_TRACE
,("AfdCreate(DeviceObject %p Irp %p)\n",
314 DeviceExt
= DeviceObject
->DeviceExtension
;
315 FileObject
= IrpSp
->FileObject
;
316 //Disposition = (IrpSp->Parameters.Create.Options >> 24) & 0xff;
318 Irp
->IoStatus
.Information
= 0;
320 EaInfo
= Irp
->AssociatedIrp
.SystemBuffer
;
323 ConnectInfo
= (PAFD_CREATE_PACKET
)(EaInfo
->EaName
+ EaInfo
->EaNameLength
+ 1);
324 EaInfoValue
= (PWCHAR
)(((PCHAR
)ConnectInfo
) + sizeof(AFD_CREATE_PACKET
));
326 //EaLength = sizeof(FILE_FULL_EA_INFORMATION) + EaInfo->EaNameLength + EaInfo->EaValueLength;
328 AFD_DbgPrint(MID_TRACE
,("EaInfo: %p, EaInfoValue: %p\n",
329 EaInfo
, EaInfoValue
));
332 AFD_DbgPrint(MID_TRACE
,("About to allocate the new FCB\n"));
334 FCB
= ExAllocatePoolWithTag(NonPagedPool
, sizeof(AFD_FCB
), TAG_AFD_FCB
);
336 Irp
->IoStatus
.Status
= STATUS_NO_MEMORY
;
337 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
338 return STATUS_NO_MEMORY
;
341 AFD_DbgPrint(MID_TRACE
,("Initializing the new FCB @ %p (FileObject %p Flags %x)\n",
342 FCB
, FileObject
, ConnectInfo
? ConnectInfo
->EndpointFlags
: 0));
344 RtlZeroMemory( FCB
, sizeof( *FCB
) );
346 FCB
->Flags
= ConnectInfo
? ConnectInfo
->EndpointFlags
: 0;
347 FCB
->GroupID
= ConnectInfo
? ConnectInfo
->GroupID
: 0;
348 FCB
->GroupType
= 0; /* FIXME */
349 FCB
->State
= SOCKET_STATE_CREATED
;
350 FCB
->FileObject
= FileObject
;
351 FCB
->DeviceExt
= DeviceExt
;
352 FCB
->AddressFile
.Handle
= INVALID_HANDLE_VALUE
;
353 FCB
->Connection
.Handle
= INVALID_HANDLE_VALUE
;
355 KeInitializeMutex( &FCB
->Mutex
, 0 );
357 for( i
= 0; i
< MAX_FUNCTIONS
; i
++ ) {
358 InitializeListHead( &FCB
->PendingIrpList
[i
] );
361 InitializeListHead( &FCB
->DatagramList
);
362 InitializeListHead( &FCB
->PendingConnections
);
364 AFD_DbgPrint(MID_TRACE
,("%p: Checking command channel\n", FCB
));
367 FCB
->TdiDeviceName
.Length
= ConnectInfo
->SizeOfTransportName
;
368 FCB
->TdiDeviceName
.MaximumLength
= FCB
->TdiDeviceName
.Length
;
369 FCB
->TdiDeviceName
.Buffer
= ExAllocatePoolWithTag(NonPagedPool
,
370 FCB
->TdiDeviceName
.Length
,
371 TAG_AFD_TRANSPORT_ADDRESS
);
373 if( !FCB
->TdiDeviceName
.Buffer
) {
374 ExFreePoolWithTag(FCB
, TAG_AFD_FCB
);
375 AFD_DbgPrint(MID_TRACE
,("Could not copy target string\n"));
376 Irp
->IoStatus
.Status
= STATUS_NO_MEMORY
;
377 IoCompleteRequest( Irp
, IO_NETWORK_INCREMENT
);
378 return STATUS_NO_MEMORY
;
381 RtlCopyMemory( FCB
->TdiDeviceName
.Buffer
,
382 ConnectInfo
->TransportName
,
383 FCB
->TdiDeviceName
.Length
);
385 AFD_DbgPrint(MID_TRACE
,("Success: %s %wZ\n",
386 EaInfo
->EaName
, &FCB
->TdiDeviceName
));
388 AFD_DbgPrint(MID_TRACE
,("Success: Control connection\n"));
391 FileObject
->FsContext
= FCB
;
393 /* It seems that UDP sockets are writable from inception */
394 if( FCB
->Flags
& AFD_ENDPOINT_CONNECTIONLESS
) {
395 AFD_DbgPrint(MID_TRACE
,("Packet oriented socket\n"));
397 /* A datagram socket is always sendable */
398 FCB
->PollState
|= AFD_EVENT_SEND
;
399 FCB
->PollStatus
[FD_WRITE_BIT
] = STATUS_SUCCESS
;
400 PollReeval( FCB
->DeviceExt
, FCB
->FileObject
);
403 if( !NT_SUCCESS(Status
) ) {
404 if (FCB
->TdiDeviceName
.Buffer
)
406 ExFreePoolWithTag(FCB
->TdiDeviceName
.Buffer
, TAG_AFD_TRANSPORT_ADDRESS
);
408 ExFreePoolWithTag(FCB
, TAG_AFD_FCB
);
409 FileObject
->FsContext
= NULL
;
412 Irp
->IoStatus
.Status
= Status
;
413 IoCompleteRequest( Irp
, IO_NETWORK_INCREMENT
);
418 static NTSTATUS NTAPI
419 AfdCleanupSocket(PDEVICE_OBJECT DeviceObject
, PIRP Irp
,
420 PIO_STACK_LOCATION IrpSp
)
422 PFILE_OBJECT FileObject
= IrpSp
->FileObject
;
423 PAFD_FCB FCB
= FileObject
->FsContext
;
424 PLIST_ENTRY CurrentEntry
, NextEntry
;
428 UNREFERENCED_PARAMETER(DeviceObject
);
430 if( !SocketAcquireStateLock( FCB
) ) return LostSocket(Irp
);
432 for (Function
= 0; Function
< MAX_FUNCTIONS
; Function
++)
434 CurrentEntry
= FCB
->PendingIrpList
[Function
].Flink
;
435 while (CurrentEntry
!= &FCB
->PendingIrpList
[Function
])
437 NextEntry
= CurrentEntry
->Flink
;
438 CurrentIrp
= CONTAINING_RECORD(CurrentEntry
, IRP
, Tail
.Overlay
.ListEntry
);
440 /* The cancel routine will remove the IRP from the list */
441 IoCancelIrp(CurrentIrp
);
443 CurrentEntry
= NextEntry
;
447 KillSelectsForFCB( FCB
->DeviceExt
, FileObject
, FALSE
);
449 return UnlockAndMaybeComplete(FCB
, STATUS_SUCCESS
, Irp
, 0);
452 static NTSTATUS NTAPI
453 AfdCloseSocket(PDEVICE_OBJECT DeviceObject
, PIRP Irp
,
454 PIO_STACK_LOCATION IrpSp
)
456 PFILE_OBJECT FileObject
= IrpSp
->FileObject
;
457 PAFD_FCB FCB
= FileObject
->FsContext
;
459 PAFD_IN_FLIGHT_REQUEST InFlightRequest
[IN_FLIGHT_REQUESTS
];
460 PAFD_TDI_OBJECT_QELT Qelt
;
461 PLIST_ENTRY QeltEntry
;
464 AFD_DbgPrint(MID_TRACE
,("AfdClose(DeviceObject %p Irp %p)\n",
467 if( !SocketAcquireStateLock( FCB
) ) return STATUS_FILE_CLOSED
;
469 FCB
->State
= SOCKET_STATE_CLOSED
;
471 InFlightRequest
[0] = &FCB
->ListenIrp
;
472 InFlightRequest
[1] = &FCB
->ReceiveIrp
;
473 InFlightRequest
[2] = &FCB
->SendIrp
;
474 InFlightRequest
[3] = &FCB
->ConnectIrp
;
475 InFlightRequest
[4] = &FCB
->DisconnectIrp
;
477 /* Cancel our pending requests */
478 for( i
= 0; i
< IN_FLIGHT_REQUESTS
; i
++ ) {
479 if( InFlightRequest
[i
]->InFlightRequest
) {
480 AFD_DbgPrint(MID_TRACE
,("Cancelling in flight irp %u (%p)\n",
481 i
, InFlightRequest
[i
]->InFlightRequest
));
482 IoCancelIrp(InFlightRequest
[i
]->InFlightRequest
);
486 KillSelectsForFCB( FCB
->DeviceExt
, FileObject
, FALSE
);
488 ASSERT(IsListEmpty(&FCB
->PendingIrpList
[FUNCTION_CONNECT
]));
489 ASSERT(IsListEmpty(&FCB
->PendingIrpList
[FUNCTION_SEND
]));
490 ASSERT(IsListEmpty(&FCB
->PendingIrpList
[FUNCTION_RECV
]));
491 ASSERT(IsListEmpty(&FCB
->PendingIrpList
[FUNCTION_PREACCEPT
]));
492 ASSERT(IsListEmpty(&FCB
->PendingIrpList
[FUNCTION_DISCONNECT
]));
494 while (!IsListEmpty(&FCB
->PendingConnections
))
496 QeltEntry
= RemoveHeadList(&FCB
->PendingConnections
);
497 Qelt
= CONTAINING_RECORD(QeltEntry
, AFD_TDI_OBJECT_QELT
, ListEntry
);
499 /* We have to close all pending connections or the listen won't get closed */
500 TdiDisassociateAddressFile(Qelt
->Object
.Object
);
501 ObDereferenceObject(Qelt
->Object
.Object
);
502 ZwClose(Qelt
->Object
.Handle
);
504 ExFreePoolWithTag(Qelt
, TAG_AFD_ACCEPT_QUEUE
);
507 SocketStateUnlock( FCB
);
509 if( FCB
->EventSelect
)
510 ObDereferenceObject( FCB
->EventSelect
);
513 ExFreePoolWithTag(FCB
->Context
, TAG_AFD_SOCKET_CONTEXT
);
515 if (FCB
->Recv
.Window
)
516 ExFreePoolWithTag(FCB
->Recv
.Window
, TAG_AFD_DATA_BUFFER
);
518 if (FCB
->Send
.Window
)
519 ExFreePoolWithTag(FCB
->Send
.Window
, TAG_AFD_DATA_BUFFER
);
521 if (FCB
->AddressFrom
)
522 ExFreePoolWithTag(FCB
->AddressFrom
, TAG_AFD_TDI_CONNECTION_INFORMATION
);
524 if (FCB
->ConnectCallInfo
)
525 ExFreePoolWithTag(FCB
->ConnectCallInfo
, TAG_AFD_TDI_CONNECTION_INFORMATION
);
527 if (FCB
->ConnectReturnInfo
)
528 ExFreePoolWithTag(FCB
->ConnectReturnInfo
, TAG_AFD_TDI_CONNECTION_INFORMATION
);
530 if (FCB
->ConnectData
)
531 ExFreePoolWithTag(FCB
->ConnectData
, TAG_AFD_CONNECT_DATA
);
533 if (FCB
->DisconnectData
)
534 ExFreePoolWithTag(FCB
->DisconnectData
, TAG_AFD_DISCONNECT_DATA
);
536 if (FCB
->ConnectOptions
)
537 ExFreePoolWithTag(FCB
->ConnectOptions
, TAG_AFD_CONNECT_OPTIONS
);
539 if (FCB
->DisconnectOptions
)
540 ExFreePoolWithTag(FCB
->DisconnectOptions
, TAG_AFD_DISCONNECT_OPTIONS
);
542 if (FCB
->LocalAddress
)
543 ExFreePoolWithTag(FCB
->LocalAddress
, TAG_AFD_TRANSPORT_ADDRESS
);
545 if (FCB
->RemoteAddress
)
546 ExFreePoolWithTag(FCB
->RemoteAddress
, TAG_AFD_TRANSPORT_ADDRESS
);
548 if( FCB
->Connection
.Object
)
550 TdiDisassociateAddressFile(FCB
->Connection
.Object
);
551 ObDereferenceObject(FCB
->Connection
.Object
);
554 if( FCB
->AddressFile
.Object
)
555 ObDereferenceObject(FCB
->AddressFile
.Object
);
557 if( FCB
->AddressFile
.Handle
!= INVALID_HANDLE_VALUE
)
559 if (ZwClose(FCB
->AddressFile
.Handle
) == STATUS_INVALID_HANDLE
)
561 DbgPrint("INVALID ADDRESS FILE HANDLE VALUE: %p %p\n", FCB
->AddressFile
.Handle
, FCB
->AddressFile
.Object
);
565 if( FCB
->Connection
.Handle
!= INVALID_HANDLE_VALUE
)
567 if (ZwClose(FCB
->Connection
.Handle
) == STATUS_INVALID_HANDLE
)
569 DbgPrint("INVALID CONNECTION HANDLE VALUE: %p %p\n", FCB
->Connection
.Handle
, FCB
->Connection
.Object
);
573 if (FCB
->TdiDeviceName
.Buffer
)
575 ExFreePoolWithTag(FCB
->TdiDeviceName
.Buffer
, TAG_AFD_TRANSPORT_ADDRESS
);
578 ExFreePoolWithTag(FCB
, TAG_AFD_FCB
);
580 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
581 Irp
->IoStatus
.Information
= 0;
582 IoCompleteRequest(Irp
, IO_NETWORK_INCREMENT
);
584 AFD_DbgPrint(MID_TRACE
, ("Returning success.\n"));
586 return STATUS_SUCCESS
;
589 static IO_COMPLETION_ROUTINE DisconnectComplete
;
593 DisconnectComplete(PDEVICE_OBJECT DeviceObject
,
597 PAFD_FCB FCB
= Context
;
599 PLIST_ENTRY CurrentEntry
;
601 UNREFERENCED_PARAMETER(DeviceObject
);
603 if (!SocketAcquireStateLock(FCB
))
604 return STATUS_FILE_CLOSED
;
606 ASSERT(FCB
->DisconnectIrp
.InFlightRequest
== Irp
);
607 FCB
->DisconnectIrp
.InFlightRequest
= NULL
;
609 ASSERT(FCB
->DisconnectPending
);
610 ASSERT((IsListEmpty(&FCB
->PendingIrpList
[FUNCTION_SEND
]) && !FCB
->SendIrp
.InFlightRequest
) ||
611 (FCB
->DisconnectFlags
& TDI_DISCONNECT_ABORT
));
613 if (NT_SUCCESS(Irp
->IoStatus
.Status
) && (FCB
->DisconnectFlags
& TDI_DISCONNECT_RELEASE
))
615 FCB
->FilledDisconnectData
= MIN(FCB
->DisconnectDataSize
, FCB
->ConnectReturnInfo
->UserDataLength
);
616 if (FCB
->FilledDisconnectData
)
618 RtlCopyMemory(FCB
->DisconnectData
,
619 FCB
->ConnectReturnInfo
->UserData
,
620 FCB
->FilledDisconnectData
);
623 FCB
->FilledDisconnectOptions
= MIN(FCB
->DisconnectOptionsSize
, FCB
->ConnectReturnInfo
->OptionsLength
);
624 if (FCB
->FilledDisconnectOptions
)
626 RtlCopyMemory(FCB
->DisconnectOptions
,
627 FCB
->ConnectReturnInfo
->Options
,
628 FCB
->FilledDisconnectOptions
);
632 FCB
->DisconnectPending
= FALSE
;
634 while (!IsListEmpty(&FCB
->PendingIrpList
[FUNCTION_DISCONNECT
]))
636 CurrentEntry
= RemoveHeadList(&FCB
->PendingIrpList
[FUNCTION_DISCONNECT
]);
637 CurrentIrp
= CONTAINING_RECORD(CurrentEntry
, IRP
, Tail
.Overlay
.ListEntry
);
638 CurrentIrp
->IoStatus
.Status
= Irp
->IoStatus
.Status
;
639 CurrentIrp
->IoStatus
.Information
= 0;
640 UnlockRequest(CurrentIrp
, IoGetCurrentIrpStackLocation(CurrentIrp
));
641 (void)IoSetCancelRoutine(CurrentIrp
, NULL
);
642 IoCompleteRequest(CurrentIrp
, IO_NETWORK_INCREMENT
);
645 if (!(FCB
->DisconnectFlags
& TDI_DISCONNECT_RELEASE
))
647 /* Signal complete connection closure immediately */
648 FCB
->PollState
|= AFD_EVENT_ABORT
;
649 FCB
->PollStatus
[FD_CLOSE_BIT
] = Irp
->IoStatus
.Status
;
650 FCB
->LastReceiveStatus
= STATUS_FILE_CLOSED
;
651 PollReeval(FCB
->DeviceExt
, FCB
->FileObject
);
654 SocketStateUnlock(FCB
);
656 return Irp
->IoStatus
.Status
;
661 DoDisconnect(PAFD_FCB FCB
)
665 ASSERT(FCB
->DisconnectPending
);
666 ASSERT((IsListEmpty(&FCB
->PendingIrpList
[FUNCTION_SEND
]) && !FCB
->SendIrp
.InFlightRequest
) ||
667 (FCB
->DisconnectFlags
& TDI_DISCONNECT_ABORT
));
669 if (FCB
->DisconnectIrp
.InFlightRequest
)
671 return STATUS_PENDING
;
674 FCB
->ConnectCallInfo
->UserData
= FCB
->DisconnectData
;
675 FCB
->ConnectCallInfo
->UserDataLength
= FCB
->DisconnectDataSize
;
676 FCB
->ConnectCallInfo
->Options
= FCB
->DisconnectOptions
;
677 FCB
->ConnectCallInfo
->OptionsLength
= FCB
->DisconnectOptionsSize
;
679 Status
= TdiDisconnect(&FCB
->DisconnectIrp
.InFlightRequest
,
680 FCB
->Connection
.Object
,
681 &FCB
->DisconnectTimeout
,
682 FCB
->DisconnectFlags
,
685 FCB
->ConnectCallInfo
,
686 FCB
->ConnectReturnInfo
);
687 if (Status
!= STATUS_PENDING
)
689 FCB
->DisconnectPending
= FALSE
;
696 RetryDisconnectCompletion(PAFD_FCB FCB
)
698 ASSERT(FCB
->RemoteAddress
);
700 if (IsListEmpty(&FCB
->PendingIrpList
[FUNCTION_SEND
]) && !FCB
->SendIrp
.InFlightRequest
&& FCB
->DisconnectPending
)
702 /* Sends are done; fire off a TDI_DISCONNECT request */
707 static NTSTATUS NTAPI
708 AfdDisconnect(PDEVICE_OBJECT DeviceObject
, PIRP Irp
,
709 PIO_STACK_LOCATION IrpSp
) {
710 PFILE_OBJECT FileObject
= IrpSp
->FileObject
;
711 PAFD_FCB FCB
= FileObject
->FsContext
;
712 PAFD_DISCONNECT_INFO DisReq
;
713 NTSTATUS Status
= STATUS_SUCCESS
;
715 PLIST_ENTRY CurrentEntry
;
718 UNREFERENCED_PARAMETER(DeviceObject
);
720 if (!SocketAcquireStateLock(FCB
)) return LostSocket(Irp
);
722 if (!(DisReq
= LockRequest(Irp
, IrpSp
, FALSE
, NULL
)))
723 return UnlockAndMaybeComplete( FCB
, STATUS_NO_MEMORY
,
726 /* Send direction only */
727 if ((DisReq
->DisconnectType
& AFD_DISCONNECT_SEND
) &&
728 !(DisReq
->DisconnectType
& AFD_DISCONNECT_RECV
))
730 /* Perform a controlled disconnect */
731 Flags
= TDI_DISCONNECT_RELEASE
;
733 /* Receive direction or both */
736 /* Mark that we can't issue another receive request */
737 FCB
->TdiReceiveClosed
= TRUE
;
739 /* Try to cancel a pending TDI receive IRP if there was one in progress */
740 if (FCB
->ReceiveIrp
.InFlightRequest
)
741 IoCancelIrp(FCB
->ReceiveIrp
.InFlightRequest
);
743 /* Discard any pending data */
744 FCB
->Recv
.Content
= 0;
745 FCB
->Recv
.BytesUsed
= 0;
747 /* Mark us as overread to complete future reads with an error */
748 FCB
->Overread
= TRUE
;
750 /* Set a successful receive status to indicate a shutdown on overread */
751 FCB
->LastReceiveStatus
= STATUS_SUCCESS
;
753 /* Clear the receive event */
754 FCB
->PollState
&= ~AFD_EVENT_RECEIVE
;
756 /* Receive direction only */
757 if ((DisReq
->DisconnectType
& AFD_DISCONNECT_RECV
) &&
758 !(DisReq
->DisconnectType
& AFD_DISCONNECT_SEND
))
760 /* No need to tell the transport driver for receive direction only */
761 return UnlockAndMaybeComplete( FCB
, STATUS_SUCCESS
, Irp
, 0 );
765 /* Perform an abortive disconnect */
766 Flags
= TDI_DISCONNECT_ABORT
;
770 if (!(FCB
->Flags
& AFD_ENDPOINT_CONNECTIONLESS
))
772 if (!FCB
->ConnectCallInfo
)
774 AFD_DbgPrint(MIN_TRACE
,("Invalid parameter\n"));
775 return UnlockAndMaybeComplete( FCB
, STATUS_INVALID_PARAMETER
,
779 if (FCB
->DisconnectPending
)
781 if (FCB
->DisconnectIrp
.InFlightRequest
)
783 IoCancelIrp(FCB
->DisconnectIrp
.InFlightRequest
);
784 ASSERT(!FCB
->DisconnectIrp
.InFlightRequest
);
788 while (!IsListEmpty(&FCB
->PendingIrpList
[FUNCTION_DISCONNECT
]))
790 CurrentEntry
= RemoveHeadList(&FCB
->PendingIrpList
[FUNCTION_DISCONNECT
]);
791 CurrentIrp
= CONTAINING_RECORD(CurrentEntry
, IRP
, Tail
.Overlay
.ListEntry
);
792 CurrentIrp
->IoStatus
.Status
= STATUS_CANCELLED
;
793 CurrentIrp
->IoStatus
.Information
= 0;
794 UnlockRequest(CurrentIrp
, IoGetCurrentIrpStackLocation(CurrentIrp
));
795 (void)IoSetCancelRoutine(CurrentIrp
, NULL
);
796 IoCompleteRequest(CurrentIrp
, IO_NETWORK_INCREMENT
);
801 FCB
->DisconnectFlags
= Flags
;
802 FCB
->DisconnectTimeout
= DisReq
->Timeout
;
803 FCB
->DisconnectPending
= TRUE
;
804 FCB
->SendClosed
= TRUE
;
805 FCB
->PollState
&= ~AFD_EVENT_SEND
;
807 Status
= QueueUserModeIrp(FCB
, Irp
, FUNCTION_DISCONNECT
);
808 if (Status
== STATUS_PENDING
)
810 if ((IsListEmpty(&FCB
->PendingIrpList
[FUNCTION_SEND
]) && !FCB
->SendIrp
.InFlightRequest
) ||
811 (FCB
->DisconnectFlags
& TDI_DISCONNECT_ABORT
))
813 /* Go ahead and execute the disconnect because we're ready for it */
814 Status
= DoDisconnect(FCB
);
817 if (Status
!= STATUS_PENDING
)
818 RemoveEntryList(&Irp
->Tail
.Overlay
.ListEntry
);
821 if (Status
== STATUS_PENDING
)
823 SocketStateUnlock(FCB
);
830 if (!(Flags
& TDI_DISCONNECT_RELEASE
))
832 if (!FCB
->RemoteAddress
)
834 AFD_DbgPrint(MIN_TRACE
,("Invalid parameter\n"));
835 return UnlockAndMaybeComplete(FCB
, STATUS_INVALID_PARAMETER
, Irp
, 0);
838 ExFreePoolWithTag(FCB
->RemoteAddress
, TAG_AFD_TRANSPORT_ADDRESS
);
840 FCB
->RemoteAddress
= NULL
;
843 FCB
->PollState
&= ~AFD_EVENT_SEND
;
844 FCB
->SendClosed
= TRUE
;
847 return UnlockAndMaybeComplete( FCB
, Status
, Irp
, 0 );
851 AfdQueryFsDeviceInfo(PDEVICE_OBJECT DeviceObject
, PFILE_FS_DEVICE_INFORMATION Buffer
, PULONG Length
)
853 if (*Length
>= sizeof(FILE_FS_DEVICE_INFORMATION
))
855 Buffer
->Characteristics
= 0;
856 Buffer
->DeviceType
= FILE_DEVICE_NAMED_PIPE
;
858 *Length
-= sizeof(FILE_FS_DEVICE_INFORMATION
);
860 return STATUS_SUCCESS
;
864 ASSERT(*Length
>= sizeof(FILE_FS_DEVICE_INFORMATION
));
865 return STATUS_INFO_LENGTH_MISMATCH
;
869 static NTSTATUS NTAPI
870 AfdQueryVolumeInformation(PDEVICE_OBJECT DeviceObject
, PIRP Irp
, PIO_STACK_LOCATION IrpSp
)
872 FS_INFORMATION_CLASS InfoClass
;
875 NTSTATUS Status
= STATUS_INVALID_INFO_CLASS
;
877 Buffer
= Irp
->AssociatedIrp
.SystemBuffer
;
878 Length
= IrpSp
->Parameters
.QueryVolume
.Length
;
879 InfoClass
= IrpSp
->Parameters
.QueryVolume
.FsInformationClass
;
883 case FileFsDeviceInformation
:
884 Status
= AfdQueryFsDeviceInfo(DeviceObject
, Buffer
, &Length
);
890 Irp
->IoStatus
.Status
= Status
;
891 Irp
->IoStatus
.Information
= IrpSp
->Parameters
.QueryVolume
.Length
- Length
;
892 IoCompleteRequest(Irp
, IO_NETWORK_INCREMENT
);
897 static DRIVER_DISPATCH AfdDispatch
;
898 static NTSTATUS NTAPI
899 AfdDispatch(PDEVICE_OBJECT DeviceObject
, PIRP Irp
)
901 PIO_STACK_LOCATION IrpSp
= IoGetCurrentIrpStackLocation(Irp
);
902 NTSTATUS Status
= STATUS_NOT_IMPLEMENTED
;
904 PFILE_OBJECT FileObject
= IrpSp
->FileObject
;
907 AFD_DbgPrint(MID_TRACE
,("AfdDispatch: %u\n", IrpSp
->MajorFunction
));
908 if( IrpSp
->MajorFunction
!= IRP_MJ_CREATE
) {
909 AFD_DbgPrint(MID_TRACE
,("FO %p, IrpSp->FO %p\n",
910 FileObject
, IrpSp
->FileObject
));
911 ASSERT(FileObject
== IrpSp
->FileObject
);
914 Irp
->IoStatus
.Information
= 0;
916 switch(IrpSp
->MajorFunction
)
918 /* opening and closing handles to the device */
920 /* Mostly borrowed from the named pipe file system */
921 return AfdCreateSocket(DeviceObject
, Irp
, IrpSp
);
924 /* Ditto the borrowing */
925 return AfdCloseSocket(DeviceObject
, Irp
, IrpSp
);
928 return AfdCleanupSocket(DeviceObject
, Irp
, IrpSp
);
932 return AfdConnectedSocketWriteData( DeviceObject
, Irp
, IrpSp
, TRUE
);
936 return AfdConnectedSocketReadData( DeviceObject
, Irp
, IrpSp
, TRUE
);
938 /* query volume info */
939 case IRP_MJ_QUERY_VOLUME_INFORMATION
:
940 return AfdQueryVolumeInformation(DeviceObject
, Irp
, IrpSp
);
942 case IRP_MJ_DEVICE_CONTROL
:
944 switch( IrpSp
->Parameters
.DeviceIoControl
.IoControlCode
) {
946 return AfdBindSocket( DeviceObject
, Irp
, IrpSp
);
948 case IOCTL_AFD_CONNECT
:
949 return AfdStreamSocketConnect( DeviceObject
, Irp
, IrpSp
);
951 case IOCTL_AFD_START_LISTEN
:
952 return AfdListenSocket( DeviceObject
, Irp
, IrpSp
);
955 return AfdConnectedSocketReadData( DeviceObject
, Irp
, IrpSp
,
958 case IOCTL_AFD_SELECT
:
959 return AfdSelect( DeviceObject
, Irp
, IrpSp
);
961 case IOCTL_AFD_EVENT_SELECT
:
962 return AfdEventSelect( DeviceObject
, Irp
, IrpSp
);
964 case IOCTL_AFD_ENUM_NETWORK_EVENTS
:
965 return AfdEnumEvents( DeviceObject
, Irp
, IrpSp
);
967 case IOCTL_AFD_RECV_DATAGRAM
:
968 return AfdPacketSocketReadData( DeviceObject
, Irp
, IrpSp
);
971 return AfdConnectedSocketWriteData( DeviceObject
, Irp
, IrpSp
,
974 case IOCTL_AFD_SEND_DATAGRAM
:
975 return AfdPacketSocketWriteData( DeviceObject
, Irp
, IrpSp
);
977 case IOCTL_AFD_GET_INFO
:
978 return AfdGetInfo( DeviceObject
, Irp
, IrpSp
);
980 case IOCTL_AFD_SET_INFO
:
981 return AfdSetInfo( DeviceObject
, Irp
, IrpSp
);
983 case IOCTL_AFD_GET_CONTEXT_SIZE
:
984 return AfdGetContextSize( DeviceObject
, Irp
, IrpSp
);
986 case IOCTL_AFD_GET_CONTEXT
:
987 return AfdGetContext( DeviceObject
, Irp
, IrpSp
);
989 case IOCTL_AFD_SET_CONTEXT
:
990 return AfdSetContext( DeviceObject
, Irp
, IrpSp
);
992 case IOCTL_AFD_WAIT_FOR_LISTEN
:
993 return AfdWaitForListen( DeviceObject
, Irp
, IrpSp
);
995 case IOCTL_AFD_ACCEPT
:
996 return AfdAccept( DeviceObject
, Irp
, IrpSp
);
998 case IOCTL_AFD_DISCONNECT
:
999 return AfdDisconnect( DeviceObject
, Irp
, IrpSp
);
1001 case IOCTL_AFD_GET_SOCK_NAME
:
1002 return AfdGetSockName( DeviceObject
, Irp
, IrpSp
);
1004 case IOCTL_AFD_GET_PEER_NAME
:
1005 return AfdGetPeerName( DeviceObject
, Irp
, IrpSp
);
1007 case IOCTL_AFD_GET_CONNECT_DATA
:
1008 return AfdGetConnectData(DeviceObject
, Irp
, IrpSp
);
1010 case IOCTL_AFD_SET_CONNECT_DATA
:
1011 return AfdSetConnectData(DeviceObject
, Irp
, IrpSp
);
1013 case IOCTL_AFD_SET_DISCONNECT_DATA
:
1014 return AfdSetDisconnectData(DeviceObject
, Irp
, IrpSp
);
1016 case IOCTL_AFD_GET_DISCONNECT_DATA
:
1017 return AfdGetDisconnectData(DeviceObject
, Irp
, IrpSp
);
1019 case IOCTL_AFD_SET_CONNECT_DATA_SIZE
:
1020 return AfdSetConnectDataSize(DeviceObject
, Irp
, IrpSp
);
1022 case IOCTL_AFD_SET_DISCONNECT_DATA_SIZE
:
1023 return AfdSetDisconnectDataSize(DeviceObject
, Irp
, IrpSp
);
1025 case IOCTL_AFD_SET_CONNECT_OPTIONS
:
1026 return AfdSetConnectOptions(DeviceObject
, Irp
, IrpSp
);
1028 case IOCTL_AFD_SET_DISCONNECT_OPTIONS
:
1029 return AfdSetDisconnectOptions(DeviceObject
, Irp
, IrpSp
);
1031 case IOCTL_AFD_GET_CONNECT_OPTIONS
:
1032 return AfdGetConnectOptions(DeviceObject
, Irp
, IrpSp
);
1034 case IOCTL_AFD_GET_DISCONNECT_OPTIONS
:
1035 return AfdGetDisconnectOptions(DeviceObject
, Irp
, IrpSp
);
1037 case IOCTL_AFD_SET_CONNECT_OPTIONS_SIZE
:
1038 return AfdSetConnectOptionsSize(DeviceObject
, Irp
, IrpSp
);
1040 case IOCTL_AFD_SET_DISCONNECT_OPTIONS_SIZE
:
1041 return AfdSetDisconnectOptionsSize(DeviceObject
, Irp
, IrpSp
);
1043 case IOCTL_AFD_GET_TDI_HANDLES
:
1044 return AfdGetTdiHandles(DeviceObject
, Irp
, IrpSp
);
1046 case IOCTL_AFD_DEFER_ACCEPT
:
1047 DbgPrint("IOCTL_AFD_DEFER_ACCEPT is UNIMPLEMENTED!\n");
1050 case IOCTL_AFD_GET_PENDING_CONNECT_DATA
:
1051 DbgPrint("IOCTL_AFD_GET_PENDING_CONNECT_DATA is UNIMPLEMENTED!\n");
1054 case IOCTL_AFD_VALIDATE_GROUP
:
1055 DbgPrint("IOCTL_AFD_VALIDATE_GROUP is UNIMPLEMENTED!\n");
1059 Status
= STATUS_NOT_SUPPORTED
;
1060 DbgPrint("Unknown IOCTL (0x%x)\n",
1061 IrpSp
->Parameters
.DeviceIoControl
.IoControlCode
);
1067 /* unsupported operations */
1070 Status
= STATUS_NOT_IMPLEMENTED
;
1071 AFD_DbgPrint(MIN_TRACE
,
1072 ("Irp: Unknown Major code was %x\n",
1073 IrpSp
->MajorFunction
));
1078 AFD_DbgPrint(MID_TRACE
, ("Returning %x\n", Status
));
1079 Irp
->IoStatus
.Status
= Status
;
1080 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
1085 BOOLEAN
CheckUnlockExtraBuffers(PAFD_FCB FCB
, PIO_STACK_LOCATION IrpSp
)
1087 if (FCB
->Flags
& AFD_ENDPOINT_CONNECTIONLESS
)
1089 if (IrpSp
->MajorFunction
== IRP_MJ_READ
|| IrpSp
->MajorFunction
== IRP_MJ_WRITE
)
1091 /* read()/write() call - no extra buffers */
1094 else if (IrpSp
->MajorFunction
== IRP_MJ_DEVICE_CONTROL
)
1096 if (IrpSp
->Parameters
.DeviceIoControl
.IoControlCode
== IOCTL_AFD_RECV_DATAGRAM
)
1098 /* recvfrom() call - extra buffers */
1101 else if (IrpSp
->Parameters
.DeviceIoControl
.IoControlCode
== IOCTL_AFD_RECV
)
1103 /* recv() call - no extra buffers */
1106 else if (IrpSp
->Parameters
.DeviceIoControl
.IoControlCode
== IOCTL_AFD_SEND
||
1107 IrpSp
->Parameters
.DeviceIoControl
.IoControlCode
== IOCTL_AFD_SEND_DATAGRAM
)
1109 /* send()/sendto() call - no extra buffers */
1121 /* Unknown IRP_MJ code */
1128 /* Connection-oriented never has extra buffers */
1134 CleanupPendingIrp(PAFD_FCB FCB
, PIRP Irp
, PIO_STACK_LOCATION IrpSp
, PAFD_ACTIVE_POLL Poll
)
1136 PAFD_RECV_INFO RecvReq
;
1137 PAFD_SEND_INFO SendReq
;
1138 PAFD_POLL_INFO PollReq
;
1140 if (IrpSp
->MajorFunction
== IRP_MJ_READ
)
1142 RecvReq
= GetLockedData(Irp
, IrpSp
);
1143 UnlockBuffers(RecvReq
->BufferArray
, RecvReq
->BufferCount
, CheckUnlockExtraBuffers(FCB
, IrpSp
));
1145 else if (IrpSp
->MajorFunction
== IRP_MJ_WRITE
)
1147 SendReq
= GetLockedData(Irp
, IrpSp
);
1148 UnlockBuffers(SendReq
->BufferArray
, SendReq
->BufferCount
, CheckUnlockExtraBuffers(FCB
, IrpSp
));
1152 ASSERT(IrpSp
->MajorFunction
== IRP_MJ_DEVICE_CONTROL
);
1154 if (IrpSp
->Parameters
.DeviceIoControl
.IoControlCode
== IOCTL_AFD_RECV
)
1156 RecvReq
= GetLockedData(Irp
, IrpSp
);
1157 UnlockBuffers(RecvReq
->BufferArray
, RecvReq
->BufferCount
, CheckUnlockExtraBuffers(FCB
, IrpSp
));
1159 else if (IrpSp
->Parameters
.DeviceIoControl
.IoControlCode
== IOCTL_AFD_SEND
)
1161 SendReq
= GetLockedData(Irp
, IrpSp
);
1162 UnlockBuffers(SendReq
->BufferArray
, SendReq
->BufferCount
, CheckUnlockExtraBuffers(FCB
, IrpSp
));
1164 else if (IrpSp
->Parameters
.DeviceIoControl
.IoControlCode
== IOCTL_AFD_SELECT
)
1168 PollReq
= Irp
->AssociatedIrp
.SystemBuffer
;
1169 ZeroEvents(PollReq
->Handles
, PollReq
->HandleCount
);
1170 SignalSocket(Poll
, NULL
, PollReq
, STATUS_CANCELLED
);
1177 AfdCancelHandler(PDEVICE_OBJECT DeviceObject
,
1180 PIO_STACK_LOCATION IrpSp
= IoGetCurrentIrpStackLocation(Irp
);
1181 PFILE_OBJECT FileObject
= IrpSp
->FileObject
;
1182 PAFD_FCB FCB
= FileObject
->FsContext
;
1183 ULONG Function
, IoctlCode
;
1185 PLIST_ENTRY CurrentEntry
;
1186 PAFD_DEVICE_EXTENSION DeviceExt
= DeviceObject
->DeviceExtension
;
1188 PAFD_ACTIVE_POLL Poll
;
1190 IoReleaseCancelSpinLock(Irp
->CancelIrql
);
1192 if (!SocketAcquireStateLock(FCB
))
1195 switch (IrpSp
->MajorFunction
)
1197 case IRP_MJ_DEVICE_CONTROL
:
1198 IoctlCode
= IrpSp
->Parameters
.DeviceIoControl
.IoControlCode
;
1202 IoctlCode
= IOCTL_AFD_RECV
;
1206 IoctlCode
= IOCTL_AFD_SEND
;
1211 SocketStateUnlock(FCB
);
1217 case IOCTL_AFD_RECV
:
1218 case IOCTL_AFD_RECV_DATAGRAM
:
1219 Function
= FUNCTION_RECV
;
1222 case IOCTL_AFD_SEND
:
1223 case IOCTL_AFD_SEND_DATAGRAM
:
1224 Function
= FUNCTION_SEND
;
1227 case IOCTL_AFD_CONNECT
:
1228 Function
= FUNCTION_CONNECT
;
1231 case IOCTL_AFD_WAIT_FOR_LISTEN
:
1232 Function
= FUNCTION_PREACCEPT
;
1235 case IOCTL_AFD_SELECT
:
1236 KeAcquireSpinLock(&DeviceExt
->Lock
, &OldIrql
);
1238 CurrentEntry
= DeviceExt
->Polls
.Flink
;
1239 while (CurrentEntry
!= &DeviceExt
->Polls
)
1241 Poll
= CONTAINING_RECORD(CurrentEntry
, AFD_ACTIVE_POLL
, ListEntry
);
1243 if (Irp
== Poll
->Irp
)
1245 CleanupPendingIrp(FCB
, Irp
, IrpSp
, Poll
);
1246 KeReleaseSpinLock(&DeviceExt
->Lock
, OldIrql
);
1247 SocketStateUnlock(FCB
);
1252 CurrentEntry
= CurrentEntry
->Flink
;
1256 KeReleaseSpinLock(&DeviceExt
->Lock
, OldIrql
);
1258 SocketStateUnlock(FCB
);
1260 DbgPrint("WARNING!!! IRP cancellation race could lead to a process hang! (IOCTL_AFD_SELECT)\n");
1263 case IOCTL_AFD_DISCONNECT
:
1264 Function
= FUNCTION_DISCONNECT
;
1269 UnlockAndMaybeComplete(FCB
, STATUS_CANCELLED
, Irp
, 0);
1273 CurrentEntry
= FCB
->PendingIrpList
[Function
].Flink
;
1274 while (CurrentEntry
!= &FCB
->PendingIrpList
[Function
])
1276 CurrentIrp
= CONTAINING_RECORD(CurrentEntry
, IRP
, Tail
.Overlay
.ListEntry
);
1278 if (CurrentIrp
== Irp
)
1280 RemoveEntryList(CurrentEntry
);
1281 CleanupPendingIrp(FCB
, Irp
, IrpSp
, NULL
);
1282 UnlockAndMaybeComplete(FCB
, STATUS_CANCELLED
, Irp
, 0);
1287 CurrentEntry
= CurrentEntry
->Flink
;
1291 SocketStateUnlock(FCB
);
1293 DbgPrint("WARNING!!! IRP cancellation race could lead to a process hang! (Function: %u)\n", Function
);
1296 static DRIVER_UNLOAD AfdUnload
;
1298 AfdUnload(PDRIVER_OBJECT DriverObject
)
1300 UNREFERENCED_PARAMETER(DriverObject
);
1304 DriverEntry(PDRIVER_OBJECT DriverObject
, PUNICODE_STRING RegistryPath
)
1306 PDEVICE_OBJECT DeviceObject
;
1307 UNICODE_STRING wstrDeviceName
= RTL_CONSTANT_STRING(L
"\\Device\\Afd");
1308 PAFD_DEVICE_EXTENSION DeviceExt
;
1311 UNREFERENCED_PARAMETER(RegistryPath
);
1312 /* register driver routines */
1313 DriverObject
->MajorFunction
[IRP_MJ_CLOSE
] = AfdDispatch
;
1314 DriverObject
->MajorFunction
[IRP_MJ_CREATE
] = AfdDispatch
;
1315 DriverObject
->MajorFunction
[IRP_MJ_CLEANUP
] = AfdDispatch
;
1316 DriverObject
->MajorFunction
[IRP_MJ_WRITE
] = AfdDispatch
;
1317 DriverObject
->MajorFunction
[IRP_MJ_READ
] = AfdDispatch
;
1318 DriverObject
->MajorFunction
[IRP_MJ_DEVICE_CONTROL
] = AfdDispatch
;
1319 DriverObject
->MajorFunction
[IRP_MJ_QUERY_VOLUME_INFORMATION
] = AfdDispatch
;
1320 DriverObject
->DriverUnload
= AfdUnload
;
1322 Status
= IoCreateDevice(DriverObject
,
1323 sizeof(AFD_DEVICE_EXTENSION
),
1325 FILE_DEVICE_NAMED_PIPE
,
1331 if (!NT_SUCCESS(Status
))
1336 DeviceExt
= DeviceObject
->DeviceExtension
;
1337 KeInitializeSpinLock( &DeviceExt
->Lock
);
1338 InitializeListHead( &DeviceExt
->Polls
);
1340 AFD_DbgPrint(MID_TRACE
,("Device created: object %p ext %p\n",
1341 DeviceObject
, DeviceExt
));