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 static VOID
PrintEvents( ULONG Events
) {
17 char *events_list
[] = { "AFD_EVENT_RECEIVE",
18 "AFD_EVENT_OOB_RECEIVE",
20 "AFD_EVENT_DISCONNECT",
25 "AFD_EVENT_CONNECT_FAIL",
27 "AFD_EVENT_GROUP_QOS",
31 for( i
= 0; events_list
[i
]; i
++ )
32 if( Events
& (1 << i
) ) AFD_DbgPrint(MID_TRACE
,("%s ", events_list
[i
] ));
36 static VOID
CopyBackStatus( PAFD_HANDLE HandleArray
,
40 for( i
= 0; i
< HandleCount
; i
++ ) {
41 HandleArray
[i
].Events
= HandleArray
[i
].Status
;
42 HandleArray
[i
].Status
= 0;
46 static VOID
ZeroEvents( PAFD_HANDLE HandleArray
,
50 for( i
= 0; i
< HandleCount
; i
++ )
51 HandleArray
[i
].Status
= 0;
55 /* you must pass either Poll OR Irp */
56 static VOID
SignalSocket(
57 PAFD_ACTIVE_POLL Poll OPTIONAL
,
59 PAFD_POLL_INFO PollReq
,
64 PIRP Irp
= _Irp
? _Irp
: Poll
->Irp
;
65 AFD_DbgPrint(MID_TRACE
,("Called (Status %x)\n", Status
));
69 KeCancelTimer( &Poll
->Timer
);
70 RemoveEntryList( &Poll
->ListEntry
);
74 Irp
->IoStatus
.Status
= Status
;
75 Irp
->IoStatus
.Information
=
76 FIELD_OFFSET(AFD_POLL_INFO
, Handles
) + sizeof(AFD_HANDLE
) * PollReq
->HandleCount
;
77 CopyBackStatus( PollReq
->Handles
,
78 PollReq
->HandleCount
);
79 for( i
= 0; i
< PollReq
->HandleCount
; i
++ ) {
82 ("Handle(%x): Got %x,%x\n",
83 PollReq
->Handles
[i
].Handle
,
84 PollReq
->Handles
[i
].Events
,
85 PollReq
->Handles
[i
].Status
));
87 UnlockHandles( AFD_HANDLES(PollReq
), PollReq
->HandleCount
);
88 AFD_DbgPrint(MID_TRACE
,("Completing\n"));
89 IoCompleteRequest( Irp
, IO_NETWORK_INCREMENT
);
90 AFD_DbgPrint(MID_TRACE
,("Done\n"));
93 static VOID
SelectTimeout( PKDPC Dpc
,
94 PVOID DeferredContext
,
95 PVOID SystemArgument1
,
96 PVOID SystemArgument2
) {
97 PAFD_ACTIVE_POLL Poll
= DeferredContext
;
98 PAFD_POLL_INFO PollReq
;
101 PAFD_DEVICE_EXTENSION DeviceExt
;
103 AFD_DbgPrint(MID_TRACE
,("Called\n"));
106 DeviceExt
= Poll
->DeviceExt
;
107 PollReq
= Irp
->AssociatedIrp
.SystemBuffer
;
109 ZeroEvents( PollReq
->Handles
, PollReq
->HandleCount
);
111 KeAcquireSpinLock( &DeviceExt
->Lock
, &OldIrql
);
112 SignalSocket( Poll
, NULL
, PollReq
, STATUS_TIMEOUT
);
113 KeReleaseSpinLock( &DeviceExt
->Lock
, OldIrql
);
115 AFD_DbgPrint(MID_TRACE
,("Timeout\n"));
118 VOID
KillSelectsForFCB( PAFD_DEVICE_EXTENSION DeviceExt
,
119 PFILE_OBJECT FileObject
,
120 BOOLEAN OnlyExclusive
) {
122 PLIST_ENTRY ListEntry
;
123 PAFD_ACTIVE_POLL Poll
;
125 PAFD_POLL_INFO PollReq
;
126 PAFD_HANDLE HandleArray
;
129 AFD_DbgPrint(MID_TRACE
,("Killing selects that refer to %x\n", FileObject
));
131 KeAcquireSpinLock( &DeviceExt
->Lock
, &OldIrql
);
133 ListEntry
= DeviceExt
->Polls
.Flink
;
134 while ( ListEntry
!= &DeviceExt
->Polls
) {
135 Poll
= CONTAINING_RECORD(ListEntry
, AFD_ACTIVE_POLL
, ListEntry
);
136 ListEntry
= ListEntry
->Flink
;
138 PollReq
= Irp
->AssociatedIrp
.SystemBuffer
;
139 HandleArray
= AFD_HANDLES(PollReq
);
141 for( i
= 0; i
< PollReq
->HandleCount
; i
++ ) {
142 AFD_DbgPrint(MAX_TRACE
,("Req: %x, This %x\n",
143 HandleArray
[i
].Handle
, FileObject
));
144 if( (PVOID
)HandleArray
[i
].Handle
== FileObject
&&
145 (!OnlyExclusive
|| (OnlyExclusive
&& Poll
->Exclusive
)) ) {
146 ZeroEvents( PollReq
->Handles
, PollReq
->HandleCount
);
147 SignalSocket( Poll
, NULL
, PollReq
, STATUS_SUCCESS
);
152 KeReleaseSpinLock( &DeviceExt
->Lock
, OldIrql
);
154 AFD_DbgPrint(MID_TRACE
,("Done\n"));
158 AfdSelect( PDEVICE_OBJECT DeviceObject
, PIRP Irp
,
159 PIO_STACK_LOCATION IrpSp
) {
160 NTSTATUS Status
= STATUS_NO_MEMORY
;
162 PFILE_OBJECT FileObject
;
163 PAFD_POLL_INFO PollReq
= Irp
->AssociatedIrp
.SystemBuffer
;
164 PAFD_DEVICE_EXTENSION DeviceExt
= DeviceObject
->DeviceExtension
;
165 UINT CopySize
= IrpSp
->Parameters
.DeviceIoControl
.InputBufferLength
;
167 CopySize
+ sizeof(AFD_ACTIVE_POLL
) - sizeof(AFD_POLL_INFO
);
169 UINT i
, Signalled
= 0;
170 ULONG Exclusive
= PollReq
->Exclusive
;
172 AFD_DbgPrint(MID_TRACE
,("Called (HandleCount %d Timeout %d)\n",
173 PollReq
->HandleCount
,
174 (INT
)(PollReq
->Timeout
.QuadPart
)));
176 SET_AFD_HANDLES(PollReq
,
177 LockHandles( PollReq
->Handles
, PollReq
->HandleCount
));
179 if( !AFD_HANDLES(PollReq
) ) {
180 Irp
->IoStatus
.Status
= STATUS_NO_MEMORY
;
181 Irp
->IoStatus
.Information
= 0;
182 IoCompleteRequest( Irp
, IO_NETWORK_INCREMENT
);
183 return Irp
->IoStatus
.Status
;
187 for( i
= 0; i
< PollReq
->HandleCount
; i
++ ) {
188 if( !AFD_HANDLES(PollReq
)[i
].Handle
) continue;
190 KillSelectsForFCB( DeviceExt
,
191 (PFILE_OBJECT
)AFD_HANDLES(PollReq
)[i
].Handle
,
196 ZeroEvents( PollReq
->Handles
,
197 PollReq
->HandleCount
);
199 KeAcquireSpinLock( &DeviceExt
->Lock
, &OldIrql
);
201 for( i
= 0; i
< PollReq
->HandleCount
; i
++ ) {
202 if( !AFD_HANDLES(PollReq
)[i
].Handle
) continue;
204 FileObject
= (PFILE_OBJECT
)AFD_HANDLES(PollReq
)[i
].Handle
;
205 FCB
= FileObject
->FsContext
;
207 if( (FCB
->PollState
& AFD_EVENT_CLOSE
) ||
208 (PollReq
->Handles
[i
].Status
& AFD_EVENT_CLOSE
) ) {
209 AFD_HANDLES(PollReq
)[i
].Handle
= 0;
210 PollReq
->Handles
[i
].Events
= 0;
211 PollReq
->Handles
[i
].Status
= AFD_EVENT_CLOSE
;
214 AFD_DbgPrint(MID_TRACE
, ("AFD: Select Events: "));
215 PrintEvents( PollReq
->Handles
[i
].Events
);
216 AFD_DbgPrint(MID_TRACE
,("\n"));
218 PollReq
->Handles
[i
].Status
=
219 PollReq
->Handles
[i
].Events
& FCB
->PollState
;
220 if( PollReq
->Handles
[i
].Status
) {
221 AFD_DbgPrint(MID_TRACE
,("Signalling %x with %x\n",
222 FCB
, FCB
->PollState
));
229 Status
= STATUS_SUCCESS
;
230 Irp
->IoStatus
.Status
= Status
;
231 SignalSocket( NULL
, Irp
, PollReq
, Status
);
234 PAFD_ACTIVE_POLL Poll
= NULL
;
236 Poll
= ExAllocatePool( NonPagedPool
, AllocSize
);
240 Poll
->DeviceExt
= DeviceExt
;
241 Poll
->Exclusive
= Exclusive
;
243 KeInitializeTimerEx( &Poll
->Timer
, NotificationTimer
);
245 KeInitializeDpc( (PRKDPC
)&Poll
->TimeoutDpc
,
246 (PKDEFERRED_ROUTINE
)SelectTimeout
,
249 InsertTailList( &DeviceExt
->Polls
, &Poll
->ListEntry
);
251 KeSetTimer( &Poll
->Timer
, PollReq
->Timeout
, &Poll
->TimeoutDpc
);
253 Status
= STATUS_PENDING
;
254 IoMarkIrpPending( Irp
);
256 AFD_DbgPrint(MAX_TRACE
, ("FIXME: do something with the IRP!\n"));
257 Status
= STATUS_NO_MEMORY
;
261 KeReleaseSpinLock( &DeviceExt
->Lock
, OldIrql
);
263 AFD_DbgPrint(MID_TRACE
,("Returning %x\n", Status
));
269 AfdEventSelect( PDEVICE_OBJECT DeviceObject
, PIRP Irp
,
270 PIO_STACK_LOCATION IrpSp
) {
271 PFILE_OBJECT FileObject
= IrpSp
->FileObject
;
272 NTSTATUS Status
= STATUS_NO_MEMORY
;
273 PAFD_EVENT_SELECT_INFO EventSelectInfo
=
274 (PAFD_EVENT_SELECT_INFO
)LockRequest( Irp
, IrpSp
);
275 PAFD_FCB FCB
= FileObject
->FsContext
;
277 AFD_DbgPrint(MID_TRACE
,("Called (Event %x Triggers %x)\n",
278 EventSelectInfo
->EventObject
,
279 EventSelectInfo
->Events
));
281 if( !SocketAcquireStateLock( FCB
) ) {
282 UnlockRequest( Irp
, IrpSp
);
283 return LostSocket( Irp
, FALSE
);
286 FCB
->EventSelectTriggers
= FCB
->EventsFired
= 0;
287 if( FCB
->EventSelect
) ObDereferenceObject( FCB
->EventSelect
);
288 FCB
->EventSelect
= NULL
;
290 if( EventSelectInfo
->EventObject
&& EventSelectInfo
->Events
) {
291 Status
= ObReferenceObjectByHandle( (PVOID
)EventSelectInfo
->
296 (PVOID
*)&FCB
->EventSelect
,
299 if( !NT_SUCCESS(Status
) )
300 FCB
->EventSelect
= NULL
;
302 FCB
->EventSelectTriggers
= EventSelectInfo
->Events
;
303 } else /* Work done, cancelling select */
304 Status
= STATUS_SUCCESS
;
306 AFD_DbgPrint(MID_TRACE
,("Returning %x\n", Status
));
308 return UnlockAndMaybeComplete( FCB
, STATUS_SUCCESS
, Irp
,
313 AfdEnumEvents( PDEVICE_OBJECT DeviceObject
, PIRP Irp
,
314 PIO_STACK_LOCATION IrpSp
) {
315 PFILE_OBJECT FileObject
= IrpSp
->FileObject
;
316 PAFD_ENUM_NETWORK_EVENTS_INFO EnumReq
=
317 (PAFD_ENUM_NETWORK_EVENTS_INFO
)LockRequest( Irp
, IrpSp
);
318 PAFD_FCB FCB
= FileObject
->FsContext
;
320 AFD_DbgPrint(MID_TRACE
,("Called (FCB %x)\n", FCB
));
322 if( !SocketAcquireStateLock( FCB
) ) {
323 UnlockRequest( Irp
, IrpSp
);
324 return LostSocket( Irp
, FALSE
);
327 EnumReq
->PollEvents
= FCB
->PollState
;
328 RtlZeroMemory( EnumReq
->EventStatus
, sizeof(EnumReq
->EventStatus
) );
330 return UnlockAndMaybeComplete( FCB
, STATUS_SUCCESS
, Irp
,
334 /* * * NOTE ALWAYS CALLED AT DISPATCH_LEVEL * * */
335 static BOOLEAN
UpdatePollWithFCB( PAFD_ACTIVE_POLL Poll
, PFILE_OBJECT FileObject
) {
339 PAFD_POLL_INFO PollReq
= Poll
->Irp
->AssociatedIrp
.SystemBuffer
;
341 ASSERT( KeGetCurrentIrql() == DISPATCH_LEVEL
);
343 for( i
= 0; i
< PollReq
->HandleCount
; i
++ ) {
344 if( !AFD_HANDLES(PollReq
)[i
].Handle
) continue;
346 FileObject
= (PFILE_OBJECT
)AFD_HANDLES(PollReq
)[i
].Handle
;
347 FCB
= FileObject
->FsContext
;
349 if( (FCB
->PollState
& AFD_EVENT_CLOSE
) ||
350 (PollReq
->Handles
[i
].Status
& AFD_EVENT_CLOSE
) ) {
351 AFD_HANDLES(PollReq
)[i
].Handle
= 0;
352 PollReq
->Handles
[i
].Events
= 0;
353 PollReq
->Handles
[i
].Status
= AFD_EVENT_CLOSE
;
356 PollReq
->Handles
[i
].Status
=
357 PollReq
->Handles
[i
].Events
& FCB
->PollState
;
358 if( PollReq
->Handles
[i
].Status
) {
359 AFD_DbgPrint(MID_TRACE
,("Signalling %x with %x\n",
360 FCB
, FCB
->PollState
));
366 return Signalled
? 1 : 0;
369 VOID
PollReeval( PAFD_DEVICE_EXTENSION DeviceExt
, PFILE_OBJECT FileObject
) {
370 PAFD_ACTIVE_POLL Poll
= NULL
;
371 PLIST_ENTRY ThePollEnt
= NULL
;
374 PAFD_POLL_INFO PollReq
;
375 PKEVENT EventSelect
= NULL
;
377 AFD_DbgPrint(MID_TRACE
,("Called: DeviceExt %x FileObject %x\n",
378 DeviceExt
, FileObject
));
380 KeAcquireSpinLock( &DeviceExt
->Lock
, &OldIrql
);
382 /* Take care of any event select signalling */
383 FCB
= (PAFD_FCB
)FileObject
->FsContext
;
385 /* Not sure if i can do this at DISPATCH_LEVEL ... try it at passive */
386 AFD_DbgPrint(MID_TRACE
,("Current State: %x, Events Fired: %x, "
387 "Select Triggers %x\n",
388 FCB
->PollState
, FCB
->EventsFired
,
389 FCB
->EventSelectTriggers
));
390 if( FCB
->PollState
& ~FCB
->EventsFired
& FCB
->EventSelectTriggers
) {
391 FCB
->EventsFired
|= FCB
->PollState
;
392 EventSelect
= FCB
->EventSelect
;
396 KeReleaseSpinLock( &DeviceExt
->Lock
, OldIrql
);
400 /* Now signal normal select irps */
401 ThePollEnt
= DeviceExt
->Polls
.Flink
;
403 while( ThePollEnt
!= &DeviceExt
->Polls
) {
404 Poll
= CONTAINING_RECORD( ThePollEnt
, AFD_ACTIVE_POLL
, ListEntry
);
405 PollReq
= Poll
->Irp
->AssociatedIrp
.SystemBuffer
;
406 AFD_DbgPrint(MID_TRACE
,("Checking poll %x\n", Poll
));
408 if( UpdatePollWithFCB( Poll
, FileObject
) ) {
409 ThePollEnt
= ThePollEnt
->Flink
;
410 AFD_DbgPrint(MID_TRACE
,("Signalling socket\n"));
411 SignalSocket( Poll
, NULL
, PollReq
, STATUS_SUCCESS
);
413 ThePollEnt
= ThePollEnt
->Flink
;
416 KeReleaseSpinLock( &DeviceExt
->Lock
, OldIrql
);
418 AFD_DbgPrint(MID_TRACE
,("Setting event %x\n", EventSelect
));
419 if( EventSelect
) KeSetEvent( EventSelect
, IO_NETWORK_INCREMENT
, FALSE
);
421 AFD_DbgPrint(MID_TRACE
,("Leaving\n"));