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 /* FIXME: should depend on SystemSize */
26 ULONG AfdReceiveWindowSize
= 0x2000;
27 ULONG AfdSendWindowSize
= 0x2000;
29 void OskitDumpBuffer( PCHAR Data
, UINT Len
) {
32 for( i
= 0; i
< Len
; i
++ ) {
33 if( i
&& !(i
& 0xf) ) DbgPrint( "\n" );
34 if( !(i
& 0xf) ) DbgPrint( "%p: ", (Data
+ i
) );
35 DbgPrint( " %02x", Data
[i
] & 0xff );
43 DriverEntry(PDRIVER_OBJECT DriverObject
, PUNICODE_STRING RegistryPath
);
46 AfdGetDisconnectOptions(PDEVICE_OBJECT DeviceObject
, PIRP Irp
,
47 PIO_STACK_LOCATION IrpSp
)
49 PFILE_OBJECT FileObject
= IrpSp
->FileObject
;
50 PAFD_FCB FCB
= FileObject
->FsContext
;
51 UINT BufferSize
= IrpSp
->Parameters
.DeviceIoControl
.OutputBufferLength
;
53 UNREFERENCED_PARAMETER(DeviceObject
);
55 if (!SocketAcquireStateLock(FCB
)) return LostSocket(Irp
);
57 if (FCB
->DisconnectOptionsSize
== 0)
59 AFD_DbgPrint(MIN_TRACE
,("Invalid parameter\n"));
60 return UnlockAndMaybeComplete(FCB
, STATUS_INVALID_PARAMETER
, Irp
, 0);
63 ASSERT(FCB
->DisconnectOptions
);
65 if (FCB
->FilledDisconnectOptions
< BufferSize
) BufferSize
= FCB
->FilledDisconnectOptions
;
67 RtlCopyMemory(Irp
->UserBuffer
,
68 FCB
->DisconnectOptions
,
71 return UnlockAndMaybeComplete(FCB
, STATUS_SUCCESS
, Irp
, BufferSize
);
76 AfdSetDisconnectOptions(PDEVICE_OBJECT DeviceObject
, PIRP Irp
,
77 PIO_STACK_LOCATION IrpSp
)
79 PFILE_OBJECT FileObject
= IrpSp
->FileObject
;
80 PAFD_FCB FCB
= FileObject
->FsContext
;
81 PVOID DisconnectOptions
= LockRequest(Irp
, IrpSp
, FALSE
, NULL
);
82 UINT DisconnectOptionsSize
= IrpSp
->Parameters
.DeviceIoControl
.InputBufferLength
;
84 UNREFERENCED_PARAMETER(DeviceObject
);
86 if (!SocketAcquireStateLock(FCB
)) return LostSocket(Irp
);
88 if (!DisconnectOptions
)
89 return UnlockAndMaybeComplete(FCB
, STATUS_NO_MEMORY
, Irp
, 0);
91 if (FCB
->DisconnectOptions
)
93 ExFreePoolWithTag(FCB
->DisconnectOptions
, TAG_AFD_DISCONNECT_OPTIONS
);
94 FCB
->DisconnectOptions
= NULL
;
95 FCB
->DisconnectOptionsSize
= 0;
96 FCB
->FilledDisconnectOptions
= 0;
99 FCB
->DisconnectOptions
= ExAllocatePoolWithTag(PagedPool
,
100 DisconnectOptionsSize
,
101 TAG_AFD_DISCONNECT_OPTIONS
);
103 if (!FCB
->DisconnectOptions
)
104 return UnlockAndMaybeComplete(FCB
, STATUS_NO_MEMORY
, Irp
, 0);
106 RtlCopyMemory(FCB
->DisconnectOptions
,
108 DisconnectOptionsSize
);
110 FCB
->DisconnectOptionsSize
= DisconnectOptionsSize
;
112 return UnlockAndMaybeComplete(FCB
, STATUS_SUCCESS
, Irp
, 0);
117 AfdSetDisconnectOptionsSize(PDEVICE_OBJECT DeviceObject
, PIRP Irp
,
118 PIO_STACK_LOCATION IrpSp
)
120 PFILE_OBJECT FileObject
= IrpSp
->FileObject
;
121 PAFD_FCB FCB
= FileObject
->FsContext
;
122 PUINT DisconnectOptionsSize
= LockRequest(Irp
, IrpSp
, FALSE
, NULL
);
123 UINT BufferSize
= IrpSp
->Parameters
.DeviceIoControl
.InputBufferLength
;
125 UNREFERENCED_PARAMETER(DeviceObject
);
127 if (!SocketAcquireStateLock(FCB
)) return LostSocket(Irp
);
129 if (!DisconnectOptionsSize
)
130 return UnlockAndMaybeComplete(FCB
, STATUS_NO_MEMORY
, Irp
, 0);
132 if (BufferSize
< sizeof(UINT
))
134 AFD_DbgPrint(MIN_TRACE
,("Buffer too small\n"));
135 return UnlockAndMaybeComplete(FCB
, STATUS_BUFFER_TOO_SMALL
, Irp
, 0);
138 if (FCB
->DisconnectOptions
)
140 ExFreePoolWithTag(FCB
->DisconnectOptions
, TAG_AFD_DISCONNECT_OPTIONS
);
141 FCB
->DisconnectOptionsSize
= 0;
142 FCB
->FilledDisconnectOptions
= 0;
145 FCB
->DisconnectOptions
= ExAllocatePoolWithTag(PagedPool
,
146 *DisconnectOptionsSize
,
147 TAG_AFD_DISCONNECT_OPTIONS
);
149 if (!FCB
->DisconnectOptions
) return UnlockAndMaybeComplete(FCB
, STATUS_NO_MEMORY
, Irp
, 0);
151 FCB
->DisconnectOptionsSize
= *DisconnectOptionsSize
;
153 return UnlockAndMaybeComplete(FCB
, STATUS_SUCCESS
, Irp
, 0);
157 AfdGetDisconnectData(PDEVICE_OBJECT DeviceObject
, PIRP Irp
,
158 PIO_STACK_LOCATION IrpSp
)
160 PFILE_OBJECT FileObject
= IrpSp
->FileObject
;
161 PAFD_FCB FCB
= FileObject
->FsContext
;
162 UINT BufferSize
= IrpSp
->Parameters
.DeviceIoControl
.OutputBufferLength
;
164 UNREFERENCED_PARAMETER(DeviceObject
);
166 if (!SocketAcquireStateLock(FCB
)) return LostSocket(Irp
);
168 if (FCB
->DisconnectDataSize
== 0)
170 AFD_DbgPrint(MIN_TRACE
,("Invalid parameter\n"));
171 return UnlockAndMaybeComplete(FCB
, STATUS_INVALID_PARAMETER
, Irp
, 0);
174 ASSERT(FCB
->DisconnectData
);
176 if (FCB
->FilledDisconnectData
< BufferSize
)
177 BufferSize
= FCB
->FilledDisconnectData
;
179 RtlCopyMemory(Irp
->UserBuffer
,
183 return UnlockAndMaybeComplete(FCB
, STATUS_SUCCESS
, Irp
, BufferSize
);
188 AfdSetDisconnectData(PDEVICE_OBJECT DeviceObject
, PIRP Irp
,
189 PIO_STACK_LOCATION IrpSp
)
191 PFILE_OBJECT FileObject
= IrpSp
->FileObject
;
192 PAFD_FCB FCB
= FileObject
->FsContext
;
193 PVOID DisconnectData
= LockRequest(Irp
, IrpSp
, FALSE
, NULL
);
194 UINT DisconnectDataSize
= IrpSp
->Parameters
.DeviceIoControl
.InputBufferLength
;
196 UNREFERENCED_PARAMETER(DeviceObject
);
198 if (!SocketAcquireStateLock(FCB
)) return LostSocket(Irp
);
201 return UnlockAndMaybeComplete(FCB
, STATUS_NO_MEMORY
, Irp
, 0);
203 if (FCB
->DisconnectData
)
205 ExFreePoolWithTag(FCB
->DisconnectData
, TAG_AFD_DISCONNECT_DATA
);
206 FCB
->DisconnectData
= NULL
;
207 FCB
->DisconnectDataSize
= 0;
208 FCB
->FilledDisconnectData
= 0;
211 FCB
->DisconnectData
= ExAllocatePoolWithTag(PagedPool
,
213 TAG_AFD_DISCONNECT_DATA
);
215 if (!FCB
->DisconnectData
)
216 return UnlockAndMaybeComplete(FCB
, STATUS_NO_MEMORY
, Irp
, 0);
218 RtlCopyMemory(FCB
->DisconnectData
,
222 FCB
->DisconnectDataSize
= DisconnectDataSize
;
224 return UnlockAndMaybeComplete(FCB
, STATUS_SUCCESS
, Irp
, 0);
229 AfdSetDisconnectDataSize(PDEVICE_OBJECT DeviceObject
, PIRP Irp
,
230 PIO_STACK_LOCATION IrpSp
)
232 PFILE_OBJECT FileObject
= IrpSp
->FileObject
;
233 PAFD_FCB FCB
= FileObject
->FsContext
;
234 PUINT DisconnectDataSize
= LockRequest(Irp
, IrpSp
, FALSE
, NULL
);
235 UINT BufferSize
= IrpSp
->Parameters
.DeviceIoControl
.InputBufferLength
;
237 UNREFERENCED_PARAMETER(DeviceObject
);
239 if (!SocketAcquireStateLock(FCB
)) return LostSocket(Irp
);
241 if (!DisconnectDataSize
)
242 return UnlockAndMaybeComplete(FCB
, STATUS_NO_MEMORY
, Irp
, 0);
244 if (BufferSize
< sizeof(UINT
))
246 AFD_DbgPrint(MIN_TRACE
,("Buffer too small\n"));
247 return UnlockAndMaybeComplete(FCB
, STATUS_BUFFER_TOO_SMALL
, Irp
, 0);
250 if (FCB
->DisconnectData
)
252 ExFreePoolWithTag(FCB
->DisconnectData
, TAG_AFD_DISCONNECT_DATA
);
253 FCB
->DisconnectDataSize
= 0;
254 FCB
->FilledDisconnectData
= 0;
257 FCB
->DisconnectData
= ExAllocatePoolWithTag(PagedPool
,
259 TAG_AFD_DISCONNECT_DATA
);
261 if (!FCB
->DisconnectData
)
262 return UnlockAndMaybeComplete(FCB
, STATUS_NO_MEMORY
, Irp
, 0);
264 FCB
->DisconnectDataSize
= *DisconnectDataSize
;
266 return UnlockAndMaybeComplete(FCB
, STATUS_SUCCESS
, Irp
, 0);
269 static NTSTATUS NTAPI
270 AfdGetTdiHandles(PDEVICE_OBJECT DeviceObject
, PIRP Irp
,
271 PIO_STACK_LOCATION IrpSp
)
273 PFILE_OBJECT FileObject
= IrpSp
->FileObject
;
274 PAFD_FCB FCB
= FileObject
->FsContext
;
275 PULONG HandleFlags
= LockRequest(Irp
, IrpSp
, TRUE
, NULL
);
276 PAFD_TDI_HANDLE_DATA HandleData
= Irp
->UserBuffer
;
278 UNREFERENCED_PARAMETER(DeviceObject
);
280 if (!SocketAcquireStateLock(FCB
)) return LostSocket(Irp
);
283 return UnlockAndMaybeComplete(FCB
, STATUS_NO_MEMORY
, Irp
, 0);
285 if (IrpSp
->Parameters
.DeviceIoControl
.InputBufferLength
< sizeof(ULONG
) ||
286 IrpSp
->Parameters
.DeviceIoControl
.OutputBufferLength
< sizeof(*HandleData
))
288 AFD_DbgPrint(MIN_TRACE
,("Buffer too small\n"));
289 return UnlockAndMaybeComplete(FCB
, STATUS_BUFFER_TOO_SMALL
, Irp
, 0);
292 if ((*HandleFlags
) & AFD_ADDRESS_HANDLE
)
293 HandleData
->TdiAddressHandle
= FCB
->AddressFile
.Handle
;
295 if ((*HandleFlags
) & AFD_CONNECTION_HANDLE
)
296 HandleData
->TdiConnectionHandle
= FCB
->Connection
.Handle
;
298 return UnlockAndMaybeComplete(FCB
, STATUS_SUCCESS
, Irp
, 0);
301 static NTSTATUS NTAPI
302 AfdCreateSocket(PDEVICE_OBJECT DeviceObject
, PIRP Irp
,
303 PIO_STACK_LOCATION IrpSp
) {
305 PFILE_OBJECT FileObject
;
306 PAFD_DEVICE_EXTENSION DeviceExt
;
307 PFILE_FULL_EA_INFORMATION EaInfo
;
308 PAFD_CREATE_PACKET ConnectInfo
= NULL
;
310 PWCHAR EaInfoValue
= NULL
;
313 NTSTATUS Status
= STATUS_SUCCESS
;
315 AFD_DbgPrint(MID_TRACE
,("AfdCreate(DeviceObject %p Irp %p)\n",
318 DeviceExt
= DeviceObject
->DeviceExtension
;
319 FileObject
= IrpSp
->FileObject
;
320 FileObject
->Flags
|= FO_NAMED_PIPE
;
321 //Disposition = (IrpSp->Parameters.Create.Options >> 24) & 0xff;
323 Irp
->IoStatus
.Information
= 0;
325 EaInfo
= Irp
->AssociatedIrp
.SystemBuffer
;
328 ConnectInfo
= (PAFD_CREATE_PACKET
)(EaInfo
->EaName
+ EaInfo
->EaNameLength
+ 1);
329 EaInfoValue
= (PWCHAR
)(((PCHAR
)ConnectInfo
) + sizeof(AFD_CREATE_PACKET
));
331 //EaLength = sizeof(FILE_FULL_EA_INFORMATION) + EaInfo->EaNameLength + EaInfo->EaValueLength;
333 AFD_DbgPrint(MID_TRACE
,("EaInfo: %p, EaInfoValue: %p\n",
334 EaInfo
, EaInfoValue
));
337 AFD_DbgPrint(MID_TRACE
,("About to allocate the new FCB\n"));
339 FCB
= ExAllocatePoolWithTag(NonPagedPool
, sizeof(AFD_FCB
), TAG_AFD_FCB
);
341 Irp
->IoStatus
.Status
= STATUS_NO_MEMORY
;
342 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
343 return STATUS_NO_MEMORY
;
346 AFD_DbgPrint(MID_TRACE
,("Initializing the new FCB @ %p (FileObject %p Flags %x)\n",
347 FCB
, FileObject
, ConnectInfo
? ConnectInfo
->EndpointFlags
: 0));
349 RtlZeroMemory( FCB
, sizeof( *FCB
) );
351 FCB
->Flags
= ConnectInfo
? ConnectInfo
->EndpointFlags
: 0;
352 FCB
->GroupID
= ConnectInfo
? ConnectInfo
->GroupID
: 0;
353 FCB
->GroupType
= 0; /* FIXME */
354 FCB
->State
= SOCKET_STATE_CREATED
;
355 FCB
->FileObject
= FileObject
;
356 FCB
->DeviceExt
= DeviceExt
;
357 FCB
->AddressFile
.Handle
= INVALID_HANDLE_VALUE
;
358 FCB
->Connection
.Handle
= INVALID_HANDLE_VALUE
;
359 FCB
->Recv
.Size
= AfdReceiveWindowSize
;
360 FCB
->Send
.Size
= AfdSendWindowSize
;
362 KeInitializeMutex( &FCB
->Mutex
, 0 );
364 for( i
= 0; i
< MAX_FUNCTIONS
; i
++ ) {
365 InitializeListHead( &FCB
->PendingIrpList
[i
] );
368 InitializeListHead( &FCB
->DatagramList
);
369 InitializeListHead( &FCB
->PendingConnections
);
371 AFD_DbgPrint(MID_TRACE
,("%p: Checking command channel\n", FCB
));
374 FCB
->TdiDeviceName
.Length
= ConnectInfo
->SizeOfTransportName
;
375 FCB
->TdiDeviceName
.MaximumLength
= FCB
->TdiDeviceName
.Length
;
376 FCB
->TdiDeviceName
.Buffer
= ExAllocatePoolWithTag(NonPagedPool
,
377 FCB
->TdiDeviceName
.Length
,
378 TAG_AFD_TRANSPORT_ADDRESS
);
380 if( !FCB
->TdiDeviceName
.Buffer
) {
381 ExFreePoolWithTag(FCB
, TAG_AFD_FCB
);
382 AFD_DbgPrint(MID_TRACE
,("Could not copy target string\n"));
383 Irp
->IoStatus
.Status
= STATUS_NO_MEMORY
;
384 IoCompleteRequest( Irp
, IO_NETWORK_INCREMENT
);
385 return STATUS_NO_MEMORY
;
388 RtlCopyMemory( FCB
->TdiDeviceName
.Buffer
,
389 ConnectInfo
->TransportName
,
390 FCB
->TdiDeviceName
.Length
);
392 AFD_DbgPrint(MID_TRACE
,("Success: %s %wZ\n",
393 EaInfo
->EaName
, &FCB
->TdiDeviceName
));
395 AFD_DbgPrint(MID_TRACE
,("Success: Control connection\n"));
398 FileObject
->FsContext
= FCB
;
400 /* It seems that UDP sockets are writable from inception */
401 if( FCB
->Flags
& AFD_ENDPOINT_CONNECTIONLESS
) {
402 AFD_DbgPrint(MID_TRACE
,("Packet oriented socket\n"));
404 /* A datagram socket is always sendable */
405 FCB
->PollState
|= AFD_EVENT_SEND
;
406 FCB
->PollStatus
[FD_WRITE_BIT
] = STATUS_SUCCESS
;
407 PollReeval( FCB
->DeviceExt
, FCB
->FileObject
);
410 if( !NT_SUCCESS(Status
) ) {
411 if (FCB
->TdiDeviceName
.Buffer
)
413 ExFreePoolWithTag(FCB
->TdiDeviceName
.Buffer
, TAG_AFD_TRANSPORT_ADDRESS
);
415 ExFreePoolWithTag(FCB
, TAG_AFD_FCB
);
416 FileObject
->FsContext
= NULL
;
419 Irp
->IoStatus
.Status
= Status
;
420 IoCompleteRequest( Irp
, IO_NETWORK_INCREMENT
);
425 static NTSTATUS NTAPI
426 AfdCleanupSocket(PDEVICE_OBJECT DeviceObject
, PIRP Irp
,
427 PIO_STACK_LOCATION IrpSp
)
429 PFILE_OBJECT FileObject
= IrpSp
->FileObject
;
430 PAFD_FCB FCB
= FileObject
->FsContext
;
431 PLIST_ENTRY CurrentEntry
, NextEntry
;
435 UNREFERENCED_PARAMETER(DeviceObject
);
437 if( !SocketAcquireStateLock( FCB
) ) return LostSocket(Irp
);
439 for (Function
= 0; Function
< MAX_FUNCTIONS
; Function
++)
441 CurrentEntry
= FCB
->PendingIrpList
[Function
].Flink
;
442 while (CurrentEntry
!= &FCB
->PendingIrpList
[Function
])
444 NextEntry
= CurrentEntry
->Flink
;
445 CurrentIrp
= CONTAINING_RECORD(CurrentEntry
, IRP
, Tail
.Overlay
.ListEntry
);
447 /* The cancel routine will remove the IRP from the list */
448 IoCancelIrp(CurrentIrp
);
450 CurrentEntry
= NextEntry
;
454 KillSelectsForFCB( FCB
->DeviceExt
, FileObject
, FALSE
);
456 return UnlockAndMaybeComplete(FCB
, STATUS_SUCCESS
, Irp
, 0);
459 static NTSTATUS NTAPI
460 AfdCloseSocket(PDEVICE_OBJECT DeviceObject
, PIRP Irp
,
461 PIO_STACK_LOCATION IrpSp
)
463 PFILE_OBJECT FileObject
= IrpSp
->FileObject
;
464 PAFD_FCB FCB
= FileObject
->FsContext
;
466 PAFD_IN_FLIGHT_REQUEST InFlightRequest
[IN_FLIGHT_REQUESTS
];
467 PAFD_TDI_OBJECT_QELT Qelt
;
468 PLIST_ENTRY QeltEntry
;
471 AFD_DbgPrint(MID_TRACE
,("AfdClose(DeviceObject %p Irp %p)\n",
474 if( !SocketAcquireStateLock( FCB
) ) return STATUS_FILE_CLOSED
;
476 FCB
->State
= SOCKET_STATE_CLOSED
;
478 InFlightRequest
[0] = &FCB
->ListenIrp
;
479 InFlightRequest
[1] = &FCB
->ReceiveIrp
;
480 InFlightRequest
[2] = &FCB
->SendIrp
;
481 InFlightRequest
[3] = &FCB
->ConnectIrp
;
482 InFlightRequest
[4] = &FCB
->DisconnectIrp
;
484 /* Cancel our pending requests */
485 for( i
= 0; i
< IN_FLIGHT_REQUESTS
; i
++ ) {
486 if( InFlightRequest
[i
]->InFlightRequest
) {
487 AFD_DbgPrint(MID_TRACE
,("Cancelling in flight irp %u (%p)\n",
488 i
, InFlightRequest
[i
]->InFlightRequest
));
489 IoCancelIrp(InFlightRequest
[i
]->InFlightRequest
);
493 KillSelectsForFCB( FCB
->DeviceExt
, FileObject
, FALSE
);
495 ASSERT(IsListEmpty(&FCB
->PendingIrpList
[FUNCTION_CONNECT
]));
496 ASSERT(IsListEmpty(&FCB
->PendingIrpList
[FUNCTION_SEND
]));
497 ASSERT(IsListEmpty(&FCB
->PendingIrpList
[FUNCTION_RECV
]));
498 ASSERT(IsListEmpty(&FCB
->PendingIrpList
[FUNCTION_PREACCEPT
]));
499 ASSERT(IsListEmpty(&FCB
->PendingIrpList
[FUNCTION_DISCONNECT
]));
501 while (!IsListEmpty(&FCB
->PendingConnections
))
503 QeltEntry
= RemoveHeadList(&FCB
->PendingConnections
);
504 Qelt
= CONTAINING_RECORD(QeltEntry
, AFD_TDI_OBJECT_QELT
, ListEntry
);
506 /* We have to close all pending connections or the listen won't get closed */
507 TdiDisassociateAddressFile(Qelt
->Object
.Object
);
508 ObDereferenceObject(Qelt
->Object
.Object
);
509 ZwClose(Qelt
->Object
.Handle
);
511 ExFreePoolWithTag(Qelt
, TAG_AFD_ACCEPT_QUEUE
);
514 SocketStateUnlock( FCB
);
516 if( FCB
->EventSelect
)
517 ObDereferenceObject( FCB
->EventSelect
);
520 ExFreePoolWithTag(FCB
->Context
, TAG_AFD_SOCKET_CONTEXT
);
522 if (FCB
->Recv
.Window
)
523 ExFreePoolWithTag(FCB
->Recv
.Window
, TAG_AFD_DATA_BUFFER
);
525 if (FCB
->Send
.Window
)
526 ExFreePoolWithTag(FCB
->Send
.Window
, TAG_AFD_DATA_BUFFER
);
528 if (FCB
->AddressFrom
)
529 ExFreePoolWithTag(FCB
->AddressFrom
, TAG_AFD_TDI_CONNECTION_INFORMATION
);
531 if (FCB
->ConnectCallInfo
)
532 ExFreePoolWithTag(FCB
->ConnectCallInfo
, TAG_AFD_TDI_CONNECTION_INFORMATION
);
534 if (FCB
->ConnectReturnInfo
)
535 ExFreePoolWithTag(FCB
->ConnectReturnInfo
, TAG_AFD_TDI_CONNECTION_INFORMATION
);
537 if (FCB
->ConnectData
)
538 ExFreePoolWithTag(FCB
->ConnectData
, TAG_AFD_CONNECT_DATA
);
540 if (FCB
->DisconnectData
)
541 ExFreePoolWithTag(FCB
->DisconnectData
, TAG_AFD_DISCONNECT_DATA
);
543 if (FCB
->ConnectOptions
)
544 ExFreePoolWithTag(FCB
->ConnectOptions
, TAG_AFD_CONNECT_OPTIONS
);
546 if (FCB
->DisconnectOptions
)
547 ExFreePoolWithTag(FCB
->DisconnectOptions
, TAG_AFD_DISCONNECT_OPTIONS
);
549 if (FCB
->LocalAddress
)
550 ExFreePoolWithTag(FCB
->LocalAddress
, TAG_AFD_TRANSPORT_ADDRESS
);
552 if (FCB
->RemoteAddress
)
553 ExFreePoolWithTag(FCB
->RemoteAddress
, TAG_AFD_TRANSPORT_ADDRESS
);
555 if( FCB
->Connection
.Object
)
557 TdiDisassociateAddressFile(FCB
->Connection
.Object
);
558 ObDereferenceObject(FCB
->Connection
.Object
);
561 if( FCB
->AddressFile
.Object
)
562 ObDereferenceObject(FCB
->AddressFile
.Object
);
564 if( FCB
->AddressFile
.Handle
!= INVALID_HANDLE_VALUE
)
566 if (ZwClose(FCB
->AddressFile
.Handle
) == STATUS_INVALID_HANDLE
)
568 DbgPrint("INVALID ADDRESS FILE HANDLE VALUE: %p %p\n", FCB
->AddressFile
.Handle
, FCB
->AddressFile
.Object
);
572 if( FCB
->Connection
.Handle
!= INVALID_HANDLE_VALUE
)
574 if (ZwClose(FCB
->Connection
.Handle
) == STATUS_INVALID_HANDLE
)
576 DbgPrint("INVALID CONNECTION HANDLE VALUE: %p %p\n", FCB
->Connection
.Handle
, FCB
->Connection
.Object
);
580 if (FCB
->TdiDeviceName
.Buffer
)
582 ExFreePoolWithTag(FCB
->TdiDeviceName
.Buffer
, TAG_AFD_TRANSPORT_ADDRESS
);
585 ExFreePoolWithTag(FCB
, TAG_AFD_FCB
);
587 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
588 Irp
->IoStatus
.Information
= 0;
589 IoCompleteRequest(Irp
, IO_NETWORK_INCREMENT
);
591 AFD_DbgPrint(MID_TRACE
, ("Returning success.\n"));
593 return STATUS_SUCCESS
;
596 static IO_COMPLETION_ROUTINE DisconnectComplete
;
600 DisconnectComplete(PDEVICE_OBJECT DeviceObject
,
604 PAFD_FCB FCB
= Context
;
606 PLIST_ENTRY CurrentEntry
;
608 UNREFERENCED_PARAMETER(DeviceObject
);
610 if (!SocketAcquireStateLock(FCB
))
611 return STATUS_FILE_CLOSED
;
613 ASSERT(FCB
->DisconnectIrp
.InFlightRequest
== Irp
);
614 FCB
->DisconnectIrp
.InFlightRequest
= NULL
;
616 ASSERT(FCB
->DisconnectPending
);
617 ASSERT((IsListEmpty(&FCB
->PendingIrpList
[FUNCTION_SEND
]) && !FCB
->SendIrp
.InFlightRequest
) ||
618 (FCB
->DisconnectFlags
& TDI_DISCONNECT_ABORT
));
620 if (NT_SUCCESS(Irp
->IoStatus
.Status
) && (FCB
->DisconnectFlags
& TDI_DISCONNECT_RELEASE
))
622 FCB
->FilledDisconnectData
= MIN(FCB
->DisconnectDataSize
, FCB
->ConnectReturnInfo
->UserDataLength
);
623 if (FCB
->FilledDisconnectData
)
625 RtlCopyMemory(FCB
->DisconnectData
,
626 FCB
->ConnectReturnInfo
->UserData
,
627 FCB
->FilledDisconnectData
);
630 FCB
->FilledDisconnectOptions
= MIN(FCB
->DisconnectOptionsSize
, FCB
->ConnectReturnInfo
->OptionsLength
);
631 if (FCB
->FilledDisconnectOptions
)
633 RtlCopyMemory(FCB
->DisconnectOptions
,
634 FCB
->ConnectReturnInfo
->Options
,
635 FCB
->FilledDisconnectOptions
);
639 FCB
->DisconnectPending
= FALSE
;
641 while (!IsListEmpty(&FCB
->PendingIrpList
[FUNCTION_DISCONNECT
]))
643 CurrentEntry
= RemoveHeadList(&FCB
->PendingIrpList
[FUNCTION_DISCONNECT
]);
644 CurrentIrp
= CONTAINING_RECORD(CurrentEntry
, IRP
, Tail
.Overlay
.ListEntry
);
645 CurrentIrp
->IoStatus
.Status
= Irp
->IoStatus
.Status
;
646 CurrentIrp
->IoStatus
.Information
= 0;
647 UnlockRequest(CurrentIrp
, IoGetCurrentIrpStackLocation(CurrentIrp
));
648 (void)IoSetCancelRoutine(CurrentIrp
, NULL
);
649 IoCompleteRequest(CurrentIrp
, IO_NETWORK_INCREMENT
);
652 if (!(FCB
->DisconnectFlags
& TDI_DISCONNECT_RELEASE
))
654 /* Signal complete connection closure immediately */
655 FCB
->PollState
|= AFD_EVENT_ABORT
;
656 FCB
->PollStatus
[FD_CLOSE_BIT
] = Irp
->IoStatus
.Status
;
657 FCB
->LastReceiveStatus
= STATUS_FILE_CLOSED
;
658 PollReeval(FCB
->DeviceExt
, FCB
->FileObject
);
661 SocketStateUnlock(FCB
);
663 return Irp
->IoStatus
.Status
;
668 DoDisconnect(PAFD_FCB FCB
)
672 ASSERT(FCB
->DisconnectPending
);
673 ASSERT((IsListEmpty(&FCB
->PendingIrpList
[FUNCTION_SEND
]) && !FCB
->SendIrp
.InFlightRequest
) ||
674 (FCB
->DisconnectFlags
& TDI_DISCONNECT_ABORT
));
676 if (FCB
->DisconnectIrp
.InFlightRequest
)
678 return STATUS_PENDING
;
681 FCB
->ConnectCallInfo
->UserData
= FCB
->DisconnectData
;
682 FCB
->ConnectCallInfo
->UserDataLength
= FCB
->DisconnectDataSize
;
683 FCB
->ConnectCallInfo
->Options
= FCB
->DisconnectOptions
;
684 FCB
->ConnectCallInfo
->OptionsLength
= FCB
->DisconnectOptionsSize
;
686 Status
= TdiDisconnect(&FCB
->DisconnectIrp
.InFlightRequest
,
687 FCB
->Connection
.Object
,
688 &FCB
->DisconnectTimeout
,
689 FCB
->DisconnectFlags
,
692 FCB
->ConnectCallInfo
,
693 FCB
->ConnectReturnInfo
);
694 if (Status
!= STATUS_PENDING
)
696 FCB
->DisconnectPending
= FALSE
;
703 RetryDisconnectCompletion(PAFD_FCB FCB
)
705 ASSERT(FCB
->RemoteAddress
);
707 if (IsListEmpty(&FCB
->PendingIrpList
[FUNCTION_SEND
]) && !FCB
->SendIrp
.InFlightRequest
&& FCB
->DisconnectPending
)
709 /* Sends are done; fire off a TDI_DISCONNECT request */
714 static NTSTATUS NTAPI
715 AfdDisconnect(PDEVICE_OBJECT DeviceObject
, PIRP Irp
,
716 PIO_STACK_LOCATION IrpSp
) {
717 PFILE_OBJECT FileObject
= IrpSp
->FileObject
;
718 PAFD_FCB FCB
= FileObject
->FsContext
;
719 PAFD_DISCONNECT_INFO DisReq
;
720 NTSTATUS Status
= STATUS_SUCCESS
;
722 PLIST_ENTRY CurrentEntry
;
725 UNREFERENCED_PARAMETER(DeviceObject
);
727 if (!SocketAcquireStateLock(FCB
)) return LostSocket(Irp
);
729 if (!(DisReq
= LockRequest(Irp
, IrpSp
, FALSE
, NULL
)))
730 return UnlockAndMaybeComplete( FCB
, STATUS_NO_MEMORY
,
733 /* Send direction only */
734 if ((DisReq
->DisconnectType
& AFD_DISCONNECT_SEND
) &&
735 !(DisReq
->DisconnectType
& AFD_DISCONNECT_RECV
))
737 /* Perform a controlled disconnect */
738 Flags
= TDI_DISCONNECT_RELEASE
;
740 /* Receive direction or both */
743 /* Mark that we can't issue another receive request */
744 FCB
->TdiReceiveClosed
= TRUE
;
746 /* Try to cancel a pending TDI receive IRP if there was one in progress */
747 if (FCB
->ReceiveIrp
.InFlightRequest
)
748 IoCancelIrp(FCB
->ReceiveIrp
.InFlightRequest
);
750 /* Discard any pending data */
751 FCB
->Recv
.Content
= 0;
752 FCB
->Recv
.BytesUsed
= 0;
754 /* Mark us as overread to complete future reads with an error */
755 FCB
->Overread
= TRUE
;
757 /* Set a successful receive status to indicate a shutdown on overread */
758 FCB
->LastReceiveStatus
= STATUS_SUCCESS
;
760 /* Clear the receive event */
761 FCB
->PollState
&= ~AFD_EVENT_RECEIVE
;
763 /* Receive direction only */
764 if ((DisReq
->DisconnectType
& AFD_DISCONNECT_RECV
) &&
765 !(DisReq
->DisconnectType
& AFD_DISCONNECT_SEND
))
767 /* No need to tell the transport driver for receive direction only */
768 return UnlockAndMaybeComplete( FCB
, STATUS_SUCCESS
, Irp
, 0 );
772 /* Perform an abortive disconnect */
773 Flags
= TDI_DISCONNECT_ABORT
;
777 if (!(FCB
->Flags
& AFD_ENDPOINT_CONNECTIONLESS
))
779 if (!FCB
->ConnectCallInfo
)
781 AFD_DbgPrint(MIN_TRACE
,("Invalid parameter\n"));
782 return UnlockAndMaybeComplete( FCB
, STATUS_INVALID_PARAMETER
,
786 if (FCB
->DisconnectPending
)
788 if (FCB
->DisconnectIrp
.InFlightRequest
)
790 IoCancelIrp(FCB
->DisconnectIrp
.InFlightRequest
);
791 ASSERT(!FCB
->DisconnectIrp
.InFlightRequest
);
795 while (!IsListEmpty(&FCB
->PendingIrpList
[FUNCTION_DISCONNECT
]))
797 CurrentEntry
= RemoveHeadList(&FCB
->PendingIrpList
[FUNCTION_DISCONNECT
]);
798 CurrentIrp
= CONTAINING_RECORD(CurrentEntry
, IRP
, Tail
.Overlay
.ListEntry
);
799 CurrentIrp
->IoStatus
.Status
= STATUS_CANCELLED
;
800 CurrentIrp
->IoStatus
.Information
= 0;
801 UnlockRequest(CurrentIrp
, IoGetCurrentIrpStackLocation(CurrentIrp
));
802 (void)IoSetCancelRoutine(CurrentIrp
, NULL
);
803 IoCompleteRequest(CurrentIrp
, IO_NETWORK_INCREMENT
);
808 FCB
->DisconnectFlags
= Flags
;
809 FCB
->DisconnectTimeout
= DisReq
->Timeout
;
810 FCB
->DisconnectPending
= TRUE
;
811 FCB
->SendClosed
= TRUE
;
812 FCB
->PollState
&= ~AFD_EVENT_SEND
;
814 Status
= QueueUserModeIrp(FCB
, Irp
, FUNCTION_DISCONNECT
);
815 if (Status
== STATUS_PENDING
)
817 if ((IsListEmpty(&FCB
->PendingIrpList
[FUNCTION_SEND
]) && !FCB
->SendIrp
.InFlightRequest
) ||
818 (FCB
->DisconnectFlags
& TDI_DISCONNECT_ABORT
))
820 /* Go ahead and execute the disconnect because we're ready for it */
821 Status
= DoDisconnect(FCB
);
824 if (Status
!= STATUS_PENDING
)
825 RemoveEntryList(&Irp
->Tail
.Overlay
.ListEntry
);
828 if (Status
== STATUS_PENDING
)
830 SocketStateUnlock(FCB
);
837 if (!(Flags
& TDI_DISCONNECT_RELEASE
))
839 if (!FCB
->RemoteAddress
)
841 AFD_DbgPrint(MIN_TRACE
,("Invalid parameter\n"));
842 return UnlockAndMaybeComplete(FCB
, STATUS_INVALID_PARAMETER
, Irp
, 0);
845 ExFreePoolWithTag(FCB
->RemoteAddress
, TAG_AFD_TRANSPORT_ADDRESS
);
847 FCB
->RemoteAddress
= NULL
;
850 FCB
->PollState
&= ~AFD_EVENT_SEND
;
851 FCB
->SendClosed
= TRUE
;
854 return UnlockAndMaybeComplete( FCB
, Status
, Irp
, 0 );
858 AfdQueryFsDeviceInfo(PDEVICE_OBJECT DeviceObject
, PFILE_FS_DEVICE_INFORMATION Buffer
, PULONG Length
)
860 if (*Length
>= sizeof(FILE_FS_DEVICE_INFORMATION
))
862 Buffer
->Characteristics
= 0;
863 Buffer
->DeviceType
= FILE_DEVICE_NAMED_PIPE
;
865 *Length
-= sizeof(FILE_FS_DEVICE_INFORMATION
);
867 return STATUS_SUCCESS
;
871 ASSERT(*Length
>= sizeof(FILE_FS_DEVICE_INFORMATION
));
872 return STATUS_INFO_LENGTH_MISMATCH
;
876 static NTSTATUS NTAPI
877 AfdQueryVolumeInformation(PDEVICE_OBJECT DeviceObject
, PIRP Irp
, PIO_STACK_LOCATION IrpSp
)
879 FS_INFORMATION_CLASS InfoClass
;
882 NTSTATUS Status
= STATUS_INVALID_INFO_CLASS
;
884 Buffer
= Irp
->AssociatedIrp
.SystemBuffer
;
885 Length
= IrpSp
->Parameters
.QueryVolume
.Length
;
886 InfoClass
= IrpSp
->Parameters
.QueryVolume
.FsInformationClass
;
890 case FileFsDeviceInformation
:
891 Status
= AfdQueryFsDeviceInfo(DeviceObject
, Buffer
, &Length
);
897 Irp
->IoStatus
.Status
= Status
;
898 Irp
->IoStatus
.Information
= IrpSp
->Parameters
.QueryVolume
.Length
- Length
;
899 IoCompleteRequest(Irp
, IO_NETWORK_INCREMENT
);
904 static DRIVER_DISPATCH AfdDispatch
;
905 static NTSTATUS NTAPI
906 AfdDispatch(PDEVICE_OBJECT DeviceObject
, PIRP Irp
)
908 PIO_STACK_LOCATION IrpSp
= IoGetCurrentIrpStackLocation(Irp
);
909 NTSTATUS Status
= STATUS_NOT_IMPLEMENTED
;
911 PFILE_OBJECT FileObject
= IrpSp
->FileObject
;
914 AFD_DbgPrint(MID_TRACE
,("AfdDispatch: %u\n", IrpSp
->MajorFunction
));
915 if( IrpSp
->MajorFunction
!= IRP_MJ_CREATE
) {
916 AFD_DbgPrint(MID_TRACE
,("FO %p, IrpSp->FO %p\n",
917 FileObject
, IrpSp
->FileObject
));
918 ASSERT(FileObject
== IrpSp
->FileObject
);
921 Irp
->IoStatus
.Information
= 0;
923 switch(IrpSp
->MajorFunction
)
925 /* opening and closing handles to the device */
927 /* Mostly borrowed from the named pipe file system */
928 return AfdCreateSocket(DeviceObject
, Irp
, IrpSp
);
931 /* Ditto the borrowing */
932 return AfdCloseSocket(DeviceObject
, Irp
, IrpSp
);
935 return AfdCleanupSocket(DeviceObject
, Irp
, IrpSp
);
939 return AfdConnectedSocketWriteData( DeviceObject
, Irp
, IrpSp
, TRUE
);
943 return AfdConnectedSocketReadData( DeviceObject
, Irp
, IrpSp
, TRUE
);
945 /* query volume info */
946 case IRP_MJ_QUERY_VOLUME_INFORMATION
:
947 return AfdQueryVolumeInformation(DeviceObject
, Irp
, IrpSp
);
949 case IRP_MJ_DEVICE_CONTROL
:
951 switch( IrpSp
->Parameters
.DeviceIoControl
.IoControlCode
) {
953 return AfdBindSocket( DeviceObject
, Irp
, IrpSp
);
955 case IOCTL_AFD_CONNECT
:
956 return AfdStreamSocketConnect( DeviceObject
, Irp
, IrpSp
);
958 case IOCTL_AFD_START_LISTEN
:
959 return AfdListenSocket( DeviceObject
, Irp
, IrpSp
);
962 return AfdConnectedSocketReadData( DeviceObject
, Irp
, IrpSp
,
965 case IOCTL_AFD_SELECT
:
966 return AfdSelect( DeviceObject
, Irp
, IrpSp
);
968 case IOCTL_AFD_EVENT_SELECT
:
969 return AfdEventSelect( DeviceObject
, Irp
, IrpSp
);
971 case IOCTL_AFD_ENUM_NETWORK_EVENTS
:
972 return AfdEnumEvents( DeviceObject
, Irp
, IrpSp
);
974 case IOCTL_AFD_RECV_DATAGRAM
:
975 return AfdPacketSocketReadData( DeviceObject
, Irp
, IrpSp
);
978 return AfdConnectedSocketWriteData( DeviceObject
, Irp
, IrpSp
,
981 case IOCTL_AFD_SEND_DATAGRAM
:
982 return AfdPacketSocketWriteData( DeviceObject
, Irp
, IrpSp
);
984 case IOCTL_AFD_GET_INFO
:
985 return AfdGetInfo( DeviceObject
, Irp
, IrpSp
);
987 case IOCTL_AFD_SET_INFO
:
988 return AfdSetInfo( DeviceObject
, Irp
, IrpSp
);
990 case IOCTL_AFD_GET_CONTEXT_SIZE
:
991 return AfdGetContextSize( DeviceObject
, Irp
, IrpSp
);
993 case IOCTL_AFD_GET_CONTEXT
:
994 return AfdGetContext( DeviceObject
, Irp
, IrpSp
);
996 case IOCTL_AFD_SET_CONTEXT
:
997 return AfdSetContext( DeviceObject
, Irp
, IrpSp
);
999 case IOCTL_AFD_WAIT_FOR_LISTEN
:
1000 return AfdWaitForListen( DeviceObject
, Irp
, IrpSp
);
1002 case IOCTL_AFD_ACCEPT
:
1003 return AfdAccept( DeviceObject
, Irp
, IrpSp
);
1005 case IOCTL_AFD_DISCONNECT
:
1006 return AfdDisconnect( DeviceObject
, Irp
, IrpSp
);
1008 case IOCTL_AFD_GET_SOCK_NAME
:
1009 return AfdGetSockName( DeviceObject
, Irp
, IrpSp
);
1011 case IOCTL_AFD_GET_PEER_NAME
:
1012 return AfdGetPeerName( DeviceObject
, Irp
, IrpSp
);
1014 case IOCTL_AFD_GET_CONNECT_DATA
:
1015 return AfdGetConnectData(DeviceObject
, Irp
, IrpSp
);
1017 case IOCTL_AFD_SET_CONNECT_DATA
:
1018 return AfdSetConnectData(DeviceObject
, Irp
, IrpSp
);
1020 case IOCTL_AFD_SET_DISCONNECT_DATA
:
1021 return AfdSetDisconnectData(DeviceObject
, Irp
, IrpSp
);
1023 case IOCTL_AFD_GET_DISCONNECT_DATA
:
1024 return AfdGetDisconnectData(DeviceObject
, Irp
, IrpSp
);
1026 case IOCTL_AFD_SET_CONNECT_DATA_SIZE
:
1027 return AfdSetConnectDataSize(DeviceObject
, Irp
, IrpSp
);
1029 case IOCTL_AFD_SET_DISCONNECT_DATA_SIZE
:
1030 return AfdSetDisconnectDataSize(DeviceObject
, Irp
, IrpSp
);
1032 case IOCTL_AFD_SET_CONNECT_OPTIONS
:
1033 return AfdSetConnectOptions(DeviceObject
, Irp
, IrpSp
);
1035 case IOCTL_AFD_SET_DISCONNECT_OPTIONS
:
1036 return AfdSetDisconnectOptions(DeviceObject
, Irp
, IrpSp
);
1038 case IOCTL_AFD_GET_CONNECT_OPTIONS
:
1039 return AfdGetConnectOptions(DeviceObject
, Irp
, IrpSp
);
1041 case IOCTL_AFD_GET_DISCONNECT_OPTIONS
:
1042 return AfdGetDisconnectOptions(DeviceObject
, Irp
, IrpSp
);
1044 case IOCTL_AFD_SET_CONNECT_OPTIONS_SIZE
:
1045 return AfdSetConnectOptionsSize(DeviceObject
, Irp
, IrpSp
);
1047 case IOCTL_AFD_SET_DISCONNECT_OPTIONS_SIZE
:
1048 return AfdSetDisconnectOptionsSize(DeviceObject
, Irp
, IrpSp
);
1050 case IOCTL_AFD_GET_TDI_HANDLES
:
1051 return AfdGetTdiHandles(DeviceObject
, Irp
, IrpSp
);
1053 case IOCTL_AFD_DEFER_ACCEPT
:
1054 DbgPrint("IOCTL_AFD_DEFER_ACCEPT is UNIMPLEMENTED!\n");
1057 case IOCTL_AFD_GET_PENDING_CONNECT_DATA
:
1058 DbgPrint("IOCTL_AFD_GET_PENDING_CONNECT_DATA is UNIMPLEMENTED!\n");
1061 case IOCTL_AFD_VALIDATE_GROUP
:
1062 DbgPrint("IOCTL_AFD_VALIDATE_GROUP is UNIMPLEMENTED!\n");
1066 Status
= STATUS_NOT_SUPPORTED
;
1067 DbgPrint("Unknown IOCTL (0x%x)\n",
1068 IrpSp
->Parameters
.DeviceIoControl
.IoControlCode
);
1074 /* unsupported operations */
1077 Status
= STATUS_NOT_IMPLEMENTED
;
1078 AFD_DbgPrint(MIN_TRACE
,
1079 ("Irp: Unknown Major code was %x\n",
1080 IrpSp
->MajorFunction
));
1085 AFD_DbgPrint(MID_TRACE
, ("Returning %x\n", Status
));
1086 Irp
->IoStatus
.Status
= Status
;
1087 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
1092 BOOLEAN
CheckUnlockExtraBuffers(PAFD_FCB FCB
, PIO_STACK_LOCATION IrpSp
)
1094 if (FCB
->Flags
& AFD_ENDPOINT_CONNECTIONLESS
)
1096 if (IrpSp
->MajorFunction
== IRP_MJ_READ
|| IrpSp
->MajorFunction
== IRP_MJ_WRITE
)
1098 /* read()/write() call - no extra buffers */
1101 else if (IrpSp
->MajorFunction
== IRP_MJ_DEVICE_CONTROL
)
1103 if (IrpSp
->Parameters
.DeviceIoControl
.IoControlCode
== IOCTL_AFD_RECV_DATAGRAM
)
1105 /* recvfrom() call - extra buffers */
1108 else if (IrpSp
->Parameters
.DeviceIoControl
.IoControlCode
== IOCTL_AFD_RECV
)
1110 /* recv() call - no extra buffers */
1113 else if (IrpSp
->Parameters
.DeviceIoControl
.IoControlCode
== IOCTL_AFD_SEND
||
1114 IrpSp
->Parameters
.DeviceIoControl
.IoControlCode
== IOCTL_AFD_SEND_DATAGRAM
)
1116 /* send()/sendto() call - no extra buffers */
1128 /* Unknown IRP_MJ code */
1135 /* Connection-oriented never has extra buffers */
1141 CleanupPendingIrp(PAFD_FCB FCB
, PIRP Irp
, PIO_STACK_LOCATION IrpSp
, PAFD_ACTIVE_POLL Poll
)
1143 PAFD_RECV_INFO RecvReq
;
1144 PAFD_SEND_INFO SendReq
;
1145 PAFD_POLL_INFO PollReq
;
1147 if (IrpSp
->MajorFunction
== IRP_MJ_READ
)
1149 RecvReq
= GetLockedData(Irp
, IrpSp
);
1150 UnlockBuffers(RecvReq
->BufferArray
, RecvReq
->BufferCount
, CheckUnlockExtraBuffers(FCB
, IrpSp
));
1152 else if (IrpSp
->MajorFunction
== IRP_MJ_WRITE
)
1154 SendReq
= GetLockedData(Irp
, IrpSp
);
1155 UnlockBuffers(SendReq
->BufferArray
, SendReq
->BufferCount
, CheckUnlockExtraBuffers(FCB
, IrpSp
));
1159 ASSERT(IrpSp
->MajorFunction
== IRP_MJ_DEVICE_CONTROL
);
1161 if (IrpSp
->Parameters
.DeviceIoControl
.IoControlCode
== IOCTL_AFD_RECV
)
1163 RecvReq
= GetLockedData(Irp
, IrpSp
);
1164 UnlockBuffers(RecvReq
->BufferArray
, RecvReq
->BufferCount
, CheckUnlockExtraBuffers(FCB
, IrpSp
));
1166 else if (IrpSp
->Parameters
.DeviceIoControl
.IoControlCode
== IOCTL_AFD_SEND
)
1168 SendReq
= GetLockedData(Irp
, IrpSp
);
1169 UnlockBuffers(SendReq
->BufferArray
, SendReq
->BufferCount
, CheckUnlockExtraBuffers(FCB
, IrpSp
));
1171 else if (IrpSp
->Parameters
.DeviceIoControl
.IoControlCode
== IOCTL_AFD_SELECT
)
1175 PollReq
= Irp
->AssociatedIrp
.SystemBuffer
;
1176 ZeroEvents(PollReq
->Handles
, PollReq
->HandleCount
);
1177 SignalSocket(Poll
, NULL
, PollReq
, STATUS_CANCELLED
);
1184 AfdCancelHandler(PDEVICE_OBJECT DeviceObject
,
1187 PIO_STACK_LOCATION IrpSp
= IoGetCurrentIrpStackLocation(Irp
);
1188 PFILE_OBJECT FileObject
= IrpSp
->FileObject
;
1189 PAFD_FCB FCB
= FileObject
->FsContext
;
1190 ULONG Function
, IoctlCode
;
1192 PLIST_ENTRY CurrentEntry
;
1193 PAFD_DEVICE_EXTENSION DeviceExt
= DeviceObject
->DeviceExtension
;
1195 PAFD_ACTIVE_POLL Poll
;
1197 IoReleaseCancelSpinLock(Irp
->CancelIrql
);
1199 if (!SocketAcquireStateLock(FCB
))
1202 switch (IrpSp
->MajorFunction
)
1204 case IRP_MJ_DEVICE_CONTROL
:
1205 IoctlCode
= IrpSp
->Parameters
.DeviceIoControl
.IoControlCode
;
1209 IoctlCode
= IOCTL_AFD_RECV
;
1213 IoctlCode
= IOCTL_AFD_SEND
;
1218 SocketStateUnlock(FCB
);
1224 case IOCTL_AFD_RECV
:
1225 case IOCTL_AFD_RECV_DATAGRAM
:
1226 Function
= FUNCTION_RECV
;
1229 case IOCTL_AFD_SEND
:
1230 case IOCTL_AFD_SEND_DATAGRAM
:
1231 Function
= FUNCTION_SEND
;
1234 case IOCTL_AFD_CONNECT
:
1235 Function
= FUNCTION_CONNECT
;
1238 case IOCTL_AFD_WAIT_FOR_LISTEN
:
1239 Function
= FUNCTION_PREACCEPT
;
1242 case IOCTL_AFD_SELECT
:
1243 KeAcquireSpinLock(&DeviceExt
->Lock
, &OldIrql
);
1245 CurrentEntry
= DeviceExt
->Polls
.Flink
;
1246 while (CurrentEntry
!= &DeviceExt
->Polls
)
1248 Poll
= CONTAINING_RECORD(CurrentEntry
, AFD_ACTIVE_POLL
, ListEntry
);
1250 if (Irp
== Poll
->Irp
)
1252 CleanupPendingIrp(FCB
, Irp
, IrpSp
, Poll
);
1253 KeReleaseSpinLock(&DeviceExt
->Lock
, OldIrql
);
1254 SocketStateUnlock(FCB
);
1259 CurrentEntry
= CurrentEntry
->Flink
;
1263 KeReleaseSpinLock(&DeviceExt
->Lock
, OldIrql
);
1265 SocketStateUnlock(FCB
);
1267 DbgPrint("WARNING!!! IRP cancellation race could lead to a process hang! (IOCTL_AFD_SELECT)\n");
1270 case IOCTL_AFD_DISCONNECT
:
1271 Function
= FUNCTION_DISCONNECT
;
1276 UnlockAndMaybeComplete(FCB
, STATUS_CANCELLED
, Irp
, 0);
1280 CurrentEntry
= FCB
->PendingIrpList
[Function
].Flink
;
1281 while (CurrentEntry
!= &FCB
->PendingIrpList
[Function
])
1283 CurrentIrp
= CONTAINING_RECORD(CurrentEntry
, IRP
, Tail
.Overlay
.ListEntry
);
1285 if (CurrentIrp
== Irp
)
1287 RemoveEntryList(CurrentEntry
);
1288 CleanupPendingIrp(FCB
, Irp
, IrpSp
, NULL
);
1289 UnlockAndMaybeComplete(FCB
, STATUS_CANCELLED
, Irp
, 0);
1294 CurrentEntry
= CurrentEntry
->Flink
;
1298 SocketStateUnlock(FCB
);
1300 DbgPrint("WARNING!!! IRP cancellation race could lead to a process hang! (Function: %u)\n", Function
);
1303 static DRIVER_UNLOAD AfdUnload
;
1305 AfdUnload(PDRIVER_OBJECT DriverObject
)
1307 UNREFERENCED_PARAMETER(DriverObject
);
1311 DriverEntry(PDRIVER_OBJECT DriverObject
, PUNICODE_STRING RegistryPath
)
1313 PDEVICE_OBJECT DeviceObject
;
1314 UNICODE_STRING wstrDeviceName
= RTL_CONSTANT_STRING(L
"\\Device\\Afd");
1315 PAFD_DEVICE_EXTENSION DeviceExt
;
1318 UNREFERENCED_PARAMETER(RegistryPath
);
1319 /* register driver routines */
1320 DriverObject
->MajorFunction
[IRP_MJ_CLOSE
] = AfdDispatch
;
1321 DriverObject
->MajorFunction
[IRP_MJ_CREATE
] = AfdDispatch
;
1322 DriverObject
->MajorFunction
[IRP_MJ_CLEANUP
] = AfdDispatch
;
1323 DriverObject
->MajorFunction
[IRP_MJ_WRITE
] = AfdDispatch
;
1324 DriverObject
->MajorFunction
[IRP_MJ_READ
] = AfdDispatch
;
1325 DriverObject
->MajorFunction
[IRP_MJ_DEVICE_CONTROL
] = AfdDispatch
;
1326 DriverObject
->MajorFunction
[IRP_MJ_QUERY_VOLUME_INFORMATION
] = AfdDispatch
;
1327 DriverObject
->DriverUnload
= AfdUnload
;
1329 Status
= IoCreateDevice(DriverObject
,
1330 sizeof(AFD_DEVICE_EXTENSION
),
1332 FILE_DEVICE_NAMED_PIPE
,
1338 if (!NT_SUCCESS(Status
))
1343 DeviceExt
= DeviceObject
->DeviceExtension
;
1344 KeInitializeSpinLock( &DeviceExt
->Lock
);
1345 InitializeListHead( &DeviceExt
->Polls
);
1347 AFD_DbgPrint(MID_TRACE
,("Device created: object %p ext %p\n",
1348 DeviceObject
, DeviceExt
));