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)
13 static VOID
PrintEvents( ULONG Events
) {
15 char *events_list
[] = { "AFD_EVENT_RECEIVE",
16 "AFD_EVENT_OOB_RECEIVE",
18 "AFD_EVENT_DISCONNECT",
23 "AFD_EVENT_CONNECT_FAIL",
25 "AFD_EVENT_GROUP_QOS",
29 for( i
= 0; events_list
[i
]; i
++ )
30 if( Events
& (1 << i
) ) AFD_DbgPrint(MID_TRACE
,("%s ", events_list
[i
] ));
34 static 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;
50 HandleArray
[i
].Events
= 0;
55 /* you must pass either Poll OR Irp */
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
);
71 ExFreePoolWithTag(Poll
, TAG_AFD_ACTIVE_POLL
);
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 if( Irp
->MdlAddress
) UnlockRequest( Irp
, IoGetCurrentIrpStackLocation( Irp
) );
89 AFD_DbgPrint(MID_TRACE
,("Completing\n"));
90 (void)IoSetCancelRoutine(Irp
, NULL
);
91 IoCompleteRequest( Irp
, IO_NETWORK_INCREMENT
);
92 AFD_DbgPrint(MID_TRACE
,("Done\n"));
95 static KDEFERRED_ROUTINE SelectTimeout
;
96 static VOID NTAPI
SelectTimeout( PKDPC Dpc
,
97 PVOID DeferredContext
,
98 PVOID SystemArgument1
,
99 PVOID SystemArgument2
) {
100 PAFD_ACTIVE_POLL Poll
= DeferredContext
;
101 PAFD_POLL_INFO PollReq
;
104 PAFD_DEVICE_EXTENSION DeviceExt
;
106 UNREFERENCED_PARAMETER(Dpc
);
107 UNREFERENCED_PARAMETER(SystemArgument1
);
108 UNREFERENCED_PARAMETER(SystemArgument2
);
110 AFD_DbgPrint(MID_TRACE
,("Called\n"));
113 DeviceExt
= Poll
->DeviceExt
;
114 PollReq
= Irp
->AssociatedIrp
.SystemBuffer
;
116 ZeroEvents( PollReq
->Handles
, PollReq
->HandleCount
);
118 KeAcquireSpinLock( &DeviceExt
->Lock
, &OldIrql
);
119 SignalSocket( Poll
, NULL
, PollReq
, STATUS_TIMEOUT
);
120 KeReleaseSpinLock( &DeviceExt
->Lock
, OldIrql
);
122 AFD_DbgPrint(MID_TRACE
,("Timeout\n"));
125 VOID
KillSelectsForFCB( PAFD_DEVICE_EXTENSION DeviceExt
,
126 PFILE_OBJECT FileObject
,
127 BOOLEAN OnlyExclusive
) {
129 PLIST_ENTRY ListEntry
;
130 PAFD_ACTIVE_POLL Poll
;
132 PAFD_POLL_INFO PollReq
;
133 PAFD_HANDLE HandleArray
;
136 AFD_DbgPrint(MID_TRACE
,("Killing selects that refer to %p\n", FileObject
));
138 KeAcquireSpinLock( &DeviceExt
->Lock
, &OldIrql
);
140 ListEntry
= DeviceExt
->Polls
.Flink
;
141 while ( ListEntry
!= &DeviceExt
->Polls
) {
142 Poll
= CONTAINING_RECORD(ListEntry
, AFD_ACTIVE_POLL
, ListEntry
);
143 ListEntry
= ListEntry
->Flink
;
145 PollReq
= Irp
->AssociatedIrp
.SystemBuffer
;
146 HandleArray
= AFD_HANDLES(PollReq
);
148 for( i
= 0; i
< PollReq
->HandleCount
; i
++ ) {
149 AFD_DbgPrint(MAX_TRACE
,("Req: %u, This %p\n",
150 HandleArray
[i
].Handle
, FileObject
));
151 if( (PVOID
)HandleArray
[i
].Handle
== FileObject
&&
152 (!OnlyExclusive
|| (OnlyExclusive
&& Poll
->Exclusive
)) ) {
153 ZeroEvents( PollReq
->Handles
, PollReq
->HandleCount
);
154 SignalSocket( Poll
, NULL
, PollReq
, STATUS_CANCELLED
);
159 KeReleaseSpinLock( &DeviceExt
->Lock
, OldIrql
);
161 AFD_DbgPrint(MID_TRACE
,("Done\n"));
165 AfdSelect( PDEVICE_OBJECT DeviceObject
, PIRP Irp
,
166 PIO_STACK_LOCATION IrpSp
) {
167 NTSTATUS Status
= STATUS_NO_MEMORY
;
169 PFILE_OBJECT FileObject
;
170 PAFD_POLL_INFO PollReq
= Irp
->AssociatedIrp
.SystemBuffer
;
171 PAFD_DEVICE_EXTENSION DeviceExt
= DeviceObject
->DeviceExtension
;
173 UINT i
, Signalled
= 0;
174 ULONG Exclusive
= PollReq
->Exclusive
;
176 UNREFERENCED_PARAMETER(IrpSp
);
178 AFD_DbgPrint(MID_TRACE
,("Called (HandleCount %u Timeout %d)\n",
179 PollReq
->HandleCount
,
180 (INT
)(PollReq
->Timeout
.QuadPart
)));
182 SET_AFD_HANDLES(PollReq
,
183 LockHandles( PollReq
->Handles
, PollReq
->HandleCount
));
185 if( !AFD_HANDLES(PollReq
) ) {
186 Irp
->IoStatus
.Status
= STATUS_NO_MEMORY
;
187 Irp
->IoStatus
.Information
= 0;
188 IoCompleteRequest( Irp
, IO_NETWORK_INCREMENT
);
189 return STATUS_NO_MEMORY
;
193 for( i
= 0; i
< PollReq
->HandleCount
; i
++ ) {
194 if( !AFD_HANDLES(PollReq
)[i
].Handle
) continue;
196 KillSelectsForFCB( DeviceExt
,
197 (PFILE_OBJECT
)AFD_HANDLES(PollReq
)[i
].Handle
,
202 KeAcquireSpinLock( &DeviceExt
->Lock
, &OldIrql
);
204 for( i
= 0; i
< PollReq
->HandleCount
; i
++ ) {
205 if( !AFD_HANDLES(PollReq
)[i
].Handle
) continue;
207 FileObject
= (PFILE_OBJECT
)AFD_HANDLES(PollReq
)[i
].Handle
;
208 FCB
= FileObject
->FsContext
;
210 AFD_DbgPrint(MID_TRACE
, ("AFD: Select Events: "));
211 PrintEvents( PollReq
->Handles
[i
].Events
);
212 AFD_DbgPrint(MID_TRACE
,("\n"));
214 PollReq
->Handles
[i
].Status
=
215 PollReq
->Handles
[i
].Events
& FCB
->PollState
;
216 if( PollReq
->Handles
[i
].Status
) {
217 AFD_DbgPrint(MID_TRACE
,("Signalling %p with %x\n",
218 FCB
, FCB
->PollState
));
224 Status
= STATUS_SUCCESS
;
225 Irp
->IoStatus
.Status
= Status
;
226 SignalSocket( NULL
, Irp
, PollReq
, Status
);
229 PAFD_ACTIVE_POLL Poll
= NULL
;
231 Poll
= ExAllocatePoolWithTag(NonPagedPool
,
232 sizeof(AFD_ACTIVE_POLL
),
233 TAG_AFD_ACTIVE_POLL
);
237 Poll
->DeviceExt
= DeviceExt
;
238 Poll
->Exclusive
= Exclusive
;
240 KeInitializeTimerEx( &Poll
->Timer
, NotificationTimer
);
242 KeInitializeDpc( (PRKDPC
)&Poll
->TimeoutDpc
, SelectTimeout
, Poll
);
244 InsertTailList( &DeviceExt
->Polls
, &Poll
->ListEntry
);
246 KeSetTimer( &Poll
->Timer
, PollReq
->Timeout
, &Poll
->TimeoutDpc
);
248 Status
= STATUS_PENDING
;
249 IoMarkIrpPending( Irp
);
250 (void)IoSetCancelRoutine(Irp
, AfdCancelHandler
);
252 AFD_DbgPrint(MAX_TRACE
, ("FIXME: do something with the IRP!\n"));
253 Status
= STATUS_NO_MEMORY
;
257 KeReleaseSpinLock( &DeviceExt
->Lock
, OldIrql
);
259 AFD_DbgPrint(MID_TRACE
,("Returning %x\n", Status
));
265 AfdEventSelect( PDEVICE_OBJECT DeviceObject
, PIRP Irp
,
266 PIO_STACK_LOCATION IrpSp
) {
267 PFILE_OBJECT FileObject
= IrpSp
->FileObject
;
268 NTSTATUS Status
= STATUS_NO_MEMORY
;
269 PAFD_EVENT_SELECT_INFO EventSelectInfo
=
270 (PAFD_EVENT_SELECT_INFO
)LockRequest( Irp
, IrpSp
, FALSE
, NULL
);
271 PAFD_FCB FCB
= FileObject
->FsContext
;
273 UNREFERENCED_PARAMETER(DeviceObject
);
275 if( !SocketAcquireStateLock( FCB
) ) {
276 return LostSocket( Irp
);
279 if ( !EventSelectInfo
) {
280 return UnlockAndMaybeComplete( FCB
, STATUS_NO_MEMORY
, Irp
,
283 AFD_DbgPrint(MID_TRACE
,("Called (Event %p Triggers %u)\n",
284 EventSelectInfo
->EventObject
,
285 EventSelectInfo
->Events
));
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
) )
301 AFD_DbgPrint(MIN_TRACE
,("Failed reference event (0x%x)\n", Status
));
302 FCB
->EventSelect
= NULL
;
305 FCB
->EventSelectTriggers
= EventSelectInfo
->Events
;
307 FCB
->EventSelect
= NULL
;
308 FCB
->EventSelectTriggers
= 0;
309 Status
= STATUS_SUCCESS
;
312 if((FCB
->EventSelect
) &&
313 (FCB
->PollState
& (FCB
->EventSelectTriggers
& ~FCB
->EventSelectDisabled
)))
315 AFD_DbgPrint(MID_TRACE
,("Setting event %p\n", FCB
->EventSelect
));
317 /* Set the application's event */
318 KeSetEvent( FCB
->EventSelect
, IO_NETWORK_INCREMENT
, FALSE
);
321 AFD_DbgPrint(MID_TRACE
,("Returning %x\n", Status
));
323 return UnlockAndMaybeComplete( FCB
, Status
, Irp
,
328 AfdEnumEvents( PDEVICE_OBJECT DeviceObject
, PIRP Irp
,
329 PIO_STACK_LOCATION IrpSp
) {
330 PFILE_OBJECT FileObject
= IrpSp
->FileObject
;
331 PAFD_ENUM_NETWORK_EVENTS_INFO EnumReq
=
332 (PAFD_ENUM_NETWORK_EVENTS_INFO
)LockRequest( Irp
, IrpSp
, TRUE
, NULL
);
333 PAFD_FCB FCB
= FileObject
->FsContext
;
337 UNREFERENCED_PARAMETER(DeviceObject
);
339 AFD_DbgPrint(MID_TRACE
,("Called (FCB %p)\n", FCB
));
341 if( !SocketAcquireStateLock( FCB
) ) {
342 return LostSocket( Irp
);
346 return UnlockAndMaybeComplete( FCB
, STATUS_NO_MEMORY
, Irp
, 0 );
349 /* An event may optionally be provided for us to clear */
350 if (EnumReq
->Event
!= NULL
)
352 Status
= ObReferenceObjectByHandle(EnumReq
->Event
,
358 if (!NT_SUCCESS(Status
))
360 AFD_DbgPrint(MIN_TRACE
,("Unable to reference event %x\n", Status
));
361 return UnlockAndMaybeComplete(FCB
, Status
, Irp
, 0);
364 /* Clear the event */
365 KeClearEvent(UserEvent
);
366 ObDereferenceObject(UserEvent
);
369 /* Copy the poll state, masking out disabled events */
370 EnumReq
->PollEvents
= (FCB
->PollState
& ~FCB
->EventSelectDisabled
);
371 RtlCopyMemory( EnumReq
->EventStatus
,
373 sizeof(EnumReq
->EventStatus
) );
375 /* Disable the events that triggered the select until the reenabling function is called */
376 FCB
->EventSelectDisabled
|= (FCB
->PollState
& FCB
->EventSelectTriggers
);
378 return UnlockAndMaybeComplete( FCB
, STATUS_SUCCESS
, Irp
, 0 );
381 /* * * NOTE ALWAYS CALLED AT DISPATCH_LEVEL * * */
382 static BOOLEAN
UpdatePollWithFCB( PAFD_ACTIVE_POLL Poll
, PFILE_OBJECT FileObject
) {
386 PAFD_POLL_INFO PollReq
= Poll
->Irp
->AssociatedIrp
.SystemBuffer
;
388 ASSERT( KeGetCurrentIrql() == DISPATCH_LEVEL
);
390 for( i
= 0; i
< PollReq
->HandleCount
; i
++ ) {
391 if( !AFD_HANDLES(PollReq
)[i
].Handle
) continue;
393 FileObject
= (PFILE_OBJECT
)AFD_HANDLES(PollReq
)[i
].Handle
;
394 FCB
= FileObject
->FsContext
;
396 PollReq
->Handles
[i
].Status
= PollReq
->Handles
[i
].Events
& FCB
->PollState
;
397 if( PollReq
->Handles
[i
].Status
) {
398 AFD_DbgPrint(MID_TRACE
,("Signalling %p with %x\n",
399 FCB
, FCB
->PollState
));
404 return Signalled
? 1 : 0;
407 VOID
PollReeval( PAFD_DEVICE_EXTENSION DeviceExt
, PFILE_OBJECT FileObject
) {
408 PAFD_ACTIVE_POLL Poll
= NULL
;
409 PLIST_ENTRY ThePollEnt
= NULL
;
412 PAFD_POLL_INFO PollReq
;
414 AFD_DbgPrint(MID_TRACE
,("Called: DeviceExt %p FileObject %p\n",
415 DeviceExt
, FileObject
));
417 KeAcquireSpinLock( &DeviceExt
->Lock
, &OldIrql
);
419 /* Take care of any event select signalling */
420 FCB
= (PAFD_FCB
)FileObject
->FsContext
;
423 KeReleaseSpinLock( &DeviceExt
->Lock
, OldIrql
);
427 /* Now signal normal select irps */
428 ThePollEnt
= DeviceExt
->Polls
.Flink
;
430 while( ThePollEnt
!= &DeviceExt
->Polls
) {
431 Poll
= CONTAINING_RECORD( ThePollEnt
, AFD_ACTIVE_POLL
, ListEntry
);
432 PollReq
= Poll
->Irp
->AssociatedIrp
.SystemBuffer
;
433 AFD_DbgPrint(MID_TRACE
,("Checking poll %p\n", Poll
));
435 if( UpdatePollWithFCB( Poll
, FileObject
) ) {
436 ThePollEnt
= ThePollEnt
->Flink
;
437 AFD_DbgPrint(MID_TRACE
,("Signalling socket\n"));
438 SignalSocket( Poll
, NULL
, PollReq
, STATUS_SUCCESS
);
440 ThePollEnt
= ThePollEnt
->Flink
;
443 KeReleaseSpinLock( &DeviceExt
->Lock
, OldIrql
);
445 if((FCB
->EventSelect
) &&
446 (FCB
->PollState
& (FCB
->EventSelectTriggers
& ~FCB
->EventSelectDisabled
)))
448 AFD_DbgPrint(MID_TRACE
,("Setting event %p\n", FCB
->EventSelect
));
450 /* Set the application's event */
451 KeSetEvent( FCB
->EventSelect
, IO_NETWORK_INCREMENT
, FALSE
);
454 AFD_DbgPrint(MID_TRACE
,("Leaving\n"));