2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS kernel
4 * FILE: drivers/net/afd/afd/select.c
5 * PURPOSE: Ancillary functions driver
6 * PROGRAMMER: Art Yerkes (ayerkes@speakeasy.net)
11 #include "tdi_proto.h"
15 VOID
PrintEvents( ULONG Events
) {
16 char *events_list
[] = { "AFD_EVENT_RECEIVE",
17 "AFD_EVENT_OOB_RECEIVE",
19 "AFD_EVENT_DISCONNECT",
24 "AFD_EVENT_CONNECT_FAIL",
26 "AFD_EVENT_GROUP_QOS",
30 for( i
= 0; events_list
[i
]; i
++ )
31 if( Events
& (1 << i
) ) DbgPrint("%s ", events_list
[i
] );
34 VOID
CopyBackStatus( PAFD_HANDLE HandleArray
,
38 for( i
= 0; i
< HandleCount
; i
++ ) {
39 HandleArray
[i
].Events
= HandleArray
[i
].Status
;
40 HandleArray
[i
].Status
= 0;
44 VOID
ZeroEvents( PAFD_HANDLE HandleArray
,
48 for( i
= 0; i
< HandleCount
; i
++ )
49 HandleArray
[i
].Status
= 0;
52 VOID
RemoveSelect( PAFD_ACTIVE_POLL Poll
) {
53 AFD_DbgPrint(MID_TRACE
,("Called\n"));
55 RemoveEntryList( &Poll
->ListEntry
);
56 KeCancelTimer( &Poll
->Timer
);
60 AFD_DbgPrint(MID_TRACE
,("Done\n"));
63 VOID
SignalSocket( PAFD_ACTIVE_POLL Poll
, PAFD_POLL_INFO PollReq
,
67 AFD_DbgPrint(MID_TRACE
,("Called (Status %x)\n", Status
));
68 KeCancelTimer( &Poll
->Timer
);
69 Poll
->Irp
->IoStatus
.Status
= Status
;
70 Poll
->Irp
->IoStatus
.Information
=
71 FIELD_OFFSET(AFD_POLL_INFO
, Handles
) + sizeof(AFD_HANDLE
) * PollReq
->HandleCount
;
72 CopyBackStatus( PollReq
->Handles
,
73 PollReq
->HandleCount
);
74 for( i
= 0; i
< PollReq
->HandleCount
; i
++ ) {
77 ("Handle(%x): Got %x,%x\n",
78 PollReq
->Handles
[i
].Handle
,
79 PollReq
->Handles
[i
].Events
,
80 PollReq
->Handles
[i
].Status
));
82 UnlockHandles( AFD_HANDLES(PollReq
), PollReq
->HandleCount
);
83 AFD_DbgPrint(MID_TRACE
,("Completing\n"));
84 IoCompleteRequest( Irp
, IO_NETWORK_INCREMENT
);
85 RemoveEntryList( &Poll
->ListEntry
);
87 AFD_DbgPrint(MID_TRACE
,("Done\n"));
90 VOID
SelectTimeout( PKDPC Dpc
,
91 PVOID DeferredContext
,
92 PVOID SystemArgument1
,
93 PVOID SystemArgument2
) {
94 PAFD_ACTIVE_POLL Poll
= DeferredContext
;
95 PAFD_POLL_INFO PollReq
;
98 PAFD_DEVICE_EXTENSION DeviceExt
;
100 AFD_DbgPrint(MID_TRACE
,("Called\n"));
103 DeviceExt
= Poll
->DeviceExt
;
104 PollReq
= Irp
->AssociatedIrp
.SystemBuffer
;
106 ZeroEvents( PollReq
->Handles
, PollReq
->HandleCount
);
108 KeAcquireSpinLock( &DeviceExt
->Lock
, &OldIrql
);
109 SignalSocket( Poll
, PollReq
, STATUS_TIMEOUT
);
110 KeReleaseSpinLock( &DeviceExt
->Lock
, OldIrql
);
112 AFD_DbgPrint(MID_TRACE
,("Timeout\n"));
115 VOID
KillSelectsForFCB( PAFD_DEVICE_EXTENSION DeviceExt
,
116 PFILE_OBJECT FileObject
,
117 BOOLEAN OnlyExclusive
) {
119 PLIST_ENTRY ListEntry
;
120 PAFD_ACTIVE_POLL Poll
;
122 PAFD_POLL_INFO PollReq
;
123 PAFD_HANDLE HandleArray
;
126 AFD_DbgPrint(MID_TRACE
,("Killing selects that refer to %x\n", FileObject
));
128 KeAcquireSpinLock( &DeviceExt
->Lock
, &OldIrql
);
130 ListEntry
= DeviceExt
->Polls
.Flink
;
131 while ( ListEntry
!= &DeviceExt
->Polls
) {
132 Poll
= CONTAINING_RECORD(ListEntry
, AFD_ACTIVE_POLL
, ListEntry
);
133 ListEntry
= ListEntry
->Flink
;
135 PollReq
= Irp
->AssociatedIrp
.SystemBuffer
;
136 HandleArray
= AFD_HANDLES(PollReq
);
138 for( i
= 0; i
< PollReq
->HandleCount
; i
++ ) {
139 AFD_DbgPrint(MAX_TRACE
,("Req: %x, This %x\n",
140 HandleArray
[i
].Handle
, FileObject
));
141 if( (PVOID
)HandleArray
[i
].Handle
== FileObject
&&
142 (!OnlyExclusive
|| (OnlyExclusive
&& Poll
->Exclusive
)) ) {
143 ZeroEvents( PollReq
->Handles
, PollReq
->HandleCount
);
144 SignalSocket( Poll
, PollReq
, STATUS_SUCCESS
);
149 KeReleaseSpinLock( &DeviceExt
->Lock
, OldIrql
);
151 AFD_DbgPrint(MID_TRACE
,("Done\n"));
155 AfdSelect( PDEVICE_OBJECT DeviceObject
, PIRP Irp
,
156 PIO_STACK_LOCATION IrpSp
) {
157 NTSTATUS Status
= STATUS_NO_MEMORY
;
159 PFILE_OBJECT FileObject
;
160 PAFD_POLL_INFO PollReq
= Irp
->AssociatedIrp
.SystemBuffer
;
161 PAFD_DEVICE_EXTENSION DeviceExt
= DeviceObject
->DeviceExtension
;
162 PAFD_ACTIVE_POLL Poll
= NULL
;
163 UINT CopySize
= IrpSp
->Parameters
.DeviceIoControl
.InputBufferLength
;
165 CopySize
+ sizeof(AFD_ACTIVE_POLL
) - sizeof(AFD_POLL_INFO
);
167 UINT i
, Signalled
= 0;
168 ULONG Exclusive
= PollReq
->Exclusive
;
170 AFD_DbgPrint(MID_TRACE
,("Called (HandleCount %d Timeout %d)\n",
171 PollReq
->HandleCount
,
172 (INT
)(PollReq
->Timeout
.QuadPart
)));
174 SET_AFD_HANDLES(PollReq
,
175 LockHandles( PollReq
->Handles
, PollReq
->HandleCount
));
177 if( !AFD_HANDLES(PollReq
) ) {
178 Irp
->IoStatus
.Status
= STATUS_NO_MEMORY
;
179 Irp
->IoStatus
.Information
= 0;
180 IoCompleteRequest( Irp
, IO_NETWORK_INCREMENT
);
181 return Irp
->IoStatus
.Status
;
185 for( i
= 0; i
< PollReq
->HandleCount
; i
++ ) {
186 if( !AFD_HANDLES(PollReq
)[i
].Handle
) continue;
188 KillSelectsForFCB( DeviceExt
,
189 (PFILE_OBJECT
)AFD_HANDLES(PollReq
)[i
].Handle
,
194 ZeroEvents( PollReq
->Handles
,
195 PollReq
->HandleCount
);
197 Poll
= ExAllocatePool( NonPagedPool
, AllocSize
);
201 Poll
->DeviceExt
= DeviceExt
;
202 Poll
->Exclusive
= Exclusive
;
204 KeInitializeTimerEx( &Poll
->Timer
, NotificationTimer
);
205 KeSetTimer( &Poll
->Timer
, PollReq
->Timeout
, &Poll
->TimeoutDpc
);
207 KeInitializeDpc( (PRKDPC
)&Poll
->TimeoutDpc
,
208 (PKDEFERRED_ROUTINE
)SelectTimeout
,
211 KeAcquireSpinLock( &DeviceExt
->Lock
, &OldIrql
);
212 InsertTailList( &DeviceExt
->Polls
, &Poll
->ListEntry
);
214 for( i
= 0; i
< PollReq
->HandleCount
; i
++ ) {
215 if( !AFD_HANDLES(PollReq
)[i
].Handle
) continue;
217 FileObject
= (PFILE_OBJECT
)AFD_HANDLES(PollReq
)[i
].Handle
;
218 FCB
= FileObject
->FsContext
;
220 if( (FCB
->PollState
& AFD_EVENT_CLOSE
) ||
221 (PollReq
->Handles
[i
].Status
& AFD_EVENT_CLOSE
) ) {
222 AFD_HANDLES(PollReq
)[i
].Handle
= 0;
223 PollReq
->Handles
[i
].Events
= 0;
224 PollReq
->Handles
[i
].Status
= AFD_EVENT_CLOSE
;
228 DbgPrint("AFD: Select Events: ");
229 PrintEvents( PollReq
->Handles
[i
].Events
);
233 PollReq
->Handles
[i
].Status
=
234 PollReq
->Handles
[i
].Events
& FCB
->PollState
;
235 if( PollReq
->Handles
[i
].Status
) {
236 AFD_DbgPrint(MID_TRACE
,("Signalling %x with %x\n",
237 FCB
, FCB
->PollState
));
244 Status
= STATUS_SUCCESS
;
245 Irp
->IoStatus
.Status
= Status
;
246 SignalSocket( Poll
, PollReq
, Status
);
248 Status
= STATUS_PENDING
;
249 IoMarkIrpPending( Irp
);
252 KeReleaseSpinLock( &DeviceExt
->Lock
, OldIrql
);
253 } else Status
= STATUS_NO_MEMORY
;
255 AFD_DbgPrint(MID_TRACE
,("Returning %x\n", Status
));
261 AfdEventSelect( PDEVICE_OBJECT DeviceObject
, PIRP Irp
,
262 PIO_STACK_LOCATION IrpSp
) {
263 PFILE_OBJECT FileObject
= IrpSp
->FileObject
;
264 NTSTATUS Status
= STATUS_NO_MEMORY
;
265 PAFD_EVENT_SELECT_INFO EventSelectInfo
=
266 (PAFD_EVENT_SELECT_INFO
)LockRequest( Irp
, IrpSp
);
267 PAFD_FCB FCB
= FileObject
->FsContext
;
269 AFD_DbgPrint(MID_TRACE
,("Called (Event %x Triggers %x)\n",
270 EventSelectInfo
->EventObject
,
271 EventSelectInfo
->Events
));
273 if( !SocketAcquireStateLock( FCB
) ) {
274 UnlockRequest( Irp
, IrpSp
);
275 return LostSocket( Irp
, FALSE
);
278 FCB
->EventSelectTriggers
= FCB
->EventsFired
= 0;
279 if( FCB
->EventSelect
) ObDereferenceObject( FCB
->EventSelect
);
280 FCB
->EventSelect
= NULL
;
282 if( EventSelectInfo
->EventObject
&& EventSelectInfo
->Events
) {
283 Status
= ObReferenceObjectByHandle( (PVOID
)EventSelectInfo
->
288 (PVOID
*)&FCB
->EventSelect
,
291 if( !NT_SUCCESS(Status
) )
292 FCB
->EventSelect
= NULL
;
294 FCB
->EventSelectTriggers
= EventSelectInfo
->Events
;
295 } else /* Work done, cancelling select */
296 Status
= STATUS_SUCCESS
;
298 AFD_DbgPrint(MID_TRACE
,("Returning %x\n", Status
));
300 return UnlockAndMaybeComplete( FCB
, STATUS_SUCCESS
, Irp
,
305 AfdEnumEvents( PDEVICE_OBJECT DeviceObject
, PIRP Irp
,
306 PIO_STACK_LOCATION IrpSp
) {
307 PFILE_OBJECT FileObject
= IrpSp
->FileObject
;
308 PAFD_ENUM_NETWORK_EVENTS_INFO EnumReq
=
309 (PAFD_ENUM_NETWORK_EVENTS_INFO
)LockRequest( Irp
, IrpSp
);
310 PAFD_FCB FCB
= FileObject
->FsContext
;
312 AFD_DbgPrint(MID_TRACE
,("Called (FCB %x)\n", FCB
));
314 if( !SocketAcquireStateLock( FCB
) ) {
315 UnlockRequest( Irp
, IrpSp
);
316 return LostSocket( Irp
, FALSE
);
319 EnumReq
->PollEvents
= FCB
->PollState
;
320 RtlZeroMemory( EnumReq
->EventStatus
, sizeof(EnumReq
->EventStatus
) );
322 return UnlockAndMaybeComplete( FCB
, STATUS_SUCCESS
, Irp
,
326 /* * * NOTE ALWAYS CALLED AT DISPATCH_LEVEL * * */
327 BOOLEAN
UpdatePollWithFCB( PAFD_ACTIVE_POLL Poll
, PFILE_OBJECT FileObject
) {
331 PAFD_POLL_INFO PollReq
= Poll
->Irp
->AssociatedIrp
.SystemBuffer
;
333 ASSERT( KeGetCurrentIrql() == DISPATCH_LEVEL
);
335 for( i
= 0; i
< PollReq
->HandleCount
; i
++ ) {
336 if( !AFD_HANDLES(PollReq
)[i
].Handle
) continue;
338 FileObject
= (PFILE_OBJECT
)AFD_HANDLES(PollReq
)[i
].Handle
;
339 FCB
= FileObject
->FsContext
;
341 if( (FCB
->PollState
& AFD_EVENT_CLOSE
) ||
342 (PollReq
->Handles
[i
].Status
& AFD_EVENT_CLOSE
) ) {
343 AFD_HANDLES(PollReq
)[i
].Handle
= 0;
344 PollReq
->Handles
[i
].Events
= 0;
345 PollReq
->Handles
[i
].Status
= AFD_EVENT_CLOSE
;
348 PollReq
->Handles
[i
].Status
=
349 PollReq
->Handles
[i
].Events
& FCB
->PollState
;
350 if( PollReq
->Handles
[i
].Status
) {
351 AFD_DbgPrint(MID_TRACE
,("Signalling %x with %x\n",
352 FCB
, FCB
->PollState
));
358 return Signalled
? 1 : 0;
361 VOID
PollReeval( PAFD_DEVICE_EXTENSION DeviceExt
, PFILE_OBJECT FileObject
) {
362 PAFD_ACTIVE_POLL Poll
= NULL
;
363 PLIST_ENTRY ThePollEnt
= NULL
;
366 PAFD_POLL_INFO PollReq
;
367 PKEVENT EventSelect
= NULL
;
369 AFD_DbgPrint(MID_TRACE
,("Called: DeviceExt %x FileObject %x\n",
370 DeviceExt
, FileObject
));
372 KeAcquireSpinLock( &DeviceExt
->Lock
, &OldIrql
);
374 /* Take care of any event select signalling */
375 FCB
= (PAFD_FCB
)FileObject
->FsContext
;
377 /* Not sure if i can do this at DISPATCH_LEVEL ... try it at passive */
378 AFD_DbgPrint(MID_TRACE
,("Current State: %x, Events Fired: %x, "
379 "Select Triggers %x\n",
380 FCB
->PollState
, FCB
->EventsFired
,
381 FCB
->EventSelectTriggers
));
382 if( FCB
->PollState
& ~FCB
->EventsFired
& FCB
->EventSelectTriggers
) {
383 FCB
->EventsFired
|= FCB
->PollState
;
384 EventSelect
= FCB
->EventSelect
;
388 KeReleaseSpinLock( &DeviceExt
->Lock
, OldIrql
);
392 /* Now signal normal select irps */
393 ThePollEnt
= DeviceExt
->Polls
.Flink
;
395 while( ThePollEnt
!= &DeviceExt
->Polls
) {
396 Poll
= CONTAINING_RECORD( ThePollEnt
, AFD_ACTIVE_POLL
, ListEntry
);
397 PollReq
= Poll
->Irp
->AssociatedIrp
.SystemBuffer
;
398 AFD_DbgPrint(MID_TRACE
,("Checking poll %x\n", Poll
));
400 if( UpdatePollWithFCB( Poll
, FileObject
) ) {
401 ThePollEnt
= ThePollEnt
->Flink
;
402 AFD_DbgPrint(MID_TRACE
,("Signalling socket\n"));
403 SignalSocket( Poll
, PollReq
, STATUS_SUCCESS
);
405 ThePollEnt
= ThePollEnt
->Flink
;
408 KeReleaseSpinLock( &DeviceExt
->Lock
, OldIrql
);
410 AFD_DbgPrint(MID_TRACE
,("Setting event %x\n", EventSelect
));
411 if( EventSelect
) KeSetEvent( EventSelect
, IO_NETWORK_INCREMENT
, FALSE
);
413 AFD_DbgPrint(MID_TRACE
,("Leaving\n"));