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)
12 static VOID
PrintEvents( ULONG Events
) {
14 char *events_list
[] = { "AFD_EVENT_RECEIVE",
15 "AFD_EVENT_OOB_RECEIVE",
17 "AFD_EVENT_DISCONNECT",
22 "AFD_EVENT_CONNECT_FAIL",
24 "AFD_EVENT_GROUP_QOS",
28 for( i
= 0; events_list
[i
]; i
++ )
29 if( Events
& (1 << i
) ) AFD_DbgPrint(MID_TRACE
,("%s ", events_list
[i
] ));
33 static VOID
CopyBackStatus( PAFD_HANDLE HandleArray
,
37 for( i
= 0; i
< HandleCount
; i
++ ) {
38 HandleArray
[i
].Events
= HandleArray
[i
].Status
;
39 HandleArray
[i
].Status
= 0;
43 VOID
ZeroEvents( PAFD_HANDLE HandleArray
,
47 for( i
= 0; i
< HandleCount
; i
++ ) {
48 HandleArray
[i
].Status
= 0;
49 HandleArray
[i
].Events
= 0;
54 /* you must pass either Poll OR Irp */
56 PAFD_ACTIVE_POLL Poll OPTIONAL
,
58 PAFD_POLL_INFO PollReq
,
63 PIRP Irp
= _Irp
? _Irp
: Poll
->Irp
;
64 AFD_DbgPrint(MID_TRACE
,("Called (Status %x)\n", Status
));
68 KeCancelTimer( &Poll
->Timer
);
69 RemoveEntryList( &Poll
->ListEntry
);
73 Irp
->IoStatus
.Status
= Status
;
74 Irp
->IoStatus
.Information
=
75 FIELD_OFFSET(AFD_POLL_INFO
, Handles
) + sizeof(AFD_HANDLE
) * PollReq
->HandleCount
;
76 CopyBackStatus( PollReq
->Handles
,
77 PollReq
->HandleCount
);
78 for( i
= 0; i
< PollReq
->HandleCount
; i
++ ) {
81 ("Handle(%x): Got %x,%x\n",
82 PollReq
->Handles
[i
].Handle
,
83 PollReq
->Handles
[i
].Events
,
84 PollReq
->Handles
[i
].Status
));
86 UnlockHandles( AFD_HANDLES(PollReq
), PollReq
->HandleCount
);
87 if( Irp
->MdlAddress
) UnlockRequest( Irp
, IoGetCurrentIrpStackLocation( Irp
) );
88 AFD_DbgPrint(MID_TRACE
,("Completing\n"));
89 (void)IoSetCancelRoutine(Irp
, NULL
);
90 IoCompleteRequest( Irp
, IO_NETWORK_INCREMENT
);
91 AFD_DbgPrint(MID_TRACE
,("Done\n"));
94 static KDEFERRED_ROUTINE SelectTimeout
;
95 static VOID NTAPI
SelectTimeout( PKDPC Dpc
,
96 PVOID DeferredContext
,
97 PVOID SystemArgument1
,
98 PVOID SystemArgument2
) {
99 PAFD_ACTIVE_POLL Poll
= DeferredContext
;
100 PAFD_POLL_INFO PollReq
;
103 PAFD_DEVICE_EXTENSION DeviceExt
;
105 UNREFERENCED_PARAMETER(Dpc
);
106 UNREFERENCED_PARAMETER(SystemArgument1
);
107 UNREFERENCED_PARAMETER(SystemArgument2
);
109 AFD_DbgPrint(MID_TRACE
,("Called\n"));
112 DeviceExt
= Poll
->DeviceExt
;
113 PollReq
= Irp
->AssociatedIrp
.SystemBuffer
;
115 ZeroEvents( PollReq
->Handles
, PollReq
->HandleCount
);
117 KeAcquireSpinLock( &DeviceExt
->Lock
, &OldIrql
);
118 SignalSocket( Poll
, NULL
, PollReq
, STATUS_TIMEOUT
);
119 KeReleaseSpinLock( &DeviceExt
->Lock
, OldIrql
);
121 AFD_DbgPrint(MID_TRACE
,("Timeout\n"));
124 VOID
KillSelectsForFCB( PAFD_DEVICE_EXTENSION DeviceExt
,
125 PFILE_OBJECT FileObject
,
126 BOOLEAN OnlyExclusive
) {
128 PLIST_ENTRY ListEntry
;
129 PAFD_ACTIVE_POLL Poll
;
131 PAFD_POLL_INFO PollReq
;
132 PAFD_HANDLE HandleArray
;
135 AFD_DbgPrint(MID_TRACE
,("Killing selects that refer to %p\n", FileObject
));
137 KeAcquireSpinLock( &DeviceExt
->Lock
, &OldIrql
);
139 ListEntry
= DeviceExt
->Polls
.Flink
;
140 while ( ListEntry
!= &DeviceExt
->Polls
) {
141 Poll
= CONTAINING_RECORD(ListEntry
, AFD_ACTIVE_POLL
, ListEntry
);
142 ListEntry
= ListEntry
->Flink
;
144 PollReq
= Irp
->AssociatedIrp
.SystemBuffer
;
145 HandleArray
= AFD_HANDLES(PollReq
);
147 for( i
= 0; i
< PollReq
->HandleCount
; i
++ ) {
148 AFD_DbgPrint(MAX_TRACE
,("Req: %u, This %p\n",
149 HandleArray
[i
].Handle
, FileObject
));
150 if( (PVOID
)HandleArray
[i
].Handle
== FileObject
&&
151 (!OnlyExclusive
|| (OnlyExclusive
&& Poll
->Exclusive
)) ) {
152 ZeroEvents( PollReq
->Handles
, PollReq
->HandleCount
);
153 SignalSocket( Poll
, NULL
, PollReq
, STATUS_CANCELLED
);
158 KeReleaseSpinLock( &DeviceExt
->Lock
, OldIrql
);
160 AFD_DbgPrint(MID_TRACE
,("Done\n"));
164 AfdSelect( PDEVICE_OBJECT DeviceObject
, PIRP Irp
,
165 PIO_STACK_LOCATION IrpSp
) {
166 NTSTATUS Status
= STATUS_NO_MEMORY
;
168 PFILE_OBJECT FileObject
;
169 PAFD_POLL_INFO PollReq
= Irp
->AssociatedIrp
.SystemBuffer
;
170 PAFD_DEVICE_EXTENSION DeviceExt
= DeviceObject
->DeviceExtension
;
172 UINT i
, Signalled
= 0;
173 ULONG Exclusive
= PollReq
->Exclusive
;
175 UNREFERENCED_PARAMETER(IrpSp
);
177 AFD_DbgPrint(MID_TRACE
,("Called (HandleCount %u Timeout %d)\n",
178 PollReq
->HandleCount
,
179 (INT
)(PollReq
->Timeout
.QuadPart
)));
181 SET_AFD_HANDLES(PollReq
,
182 LockHandles( PollReq
->Handles
, PollReq
->HandleCount
));
184 if( !AFD_HANDLES(PollReq
) ) {
185 Irp
->IoStatus
.Status
= STATUS_NO_MEMORY
;
186 Irp
->IoStatus
.Information
= 0;
187 IoCompleteRequest( Irp
, IO_NETWORK_INCREMENT
);
188 return STATUS_NO_MEMORY
;
192 for( i
= 0; i
< PollReq
->HandleCount
; i
++ ) {
193 if( !AFD_HANDLES(PollReq
)[i
].Handle
) continue;
195 KillSelectsForFCB( DeviceExt
,
196 (PFILE_OBJECT
)AFD_HANDLES(PollReq
)[i
].Handle
,
201 KeAcquireSpinLock( &DeviceExt
->Lock
, &OldIrql
);
203 for( i
= 0; i
< PollReq
->HandleCount
; i
++ ) {
204 if( !AFD_HANDLES(PollReq
)[i
].Handle
) continue;
206 FileObject
= (PFILE_OBJECT
)AFD_HANDLES(PollReq
)[i
].Handle
;
207 FCB
= FileObject
->FsContext
;
209 AFD_DbgPrint(MID_TRACE
, ("AFD: Select Events: "));
210 PrintEvents( PollReq
->Handles
[i
].Events
);
211 AFD_DbgPrint(MID_TRACE
,("\n"));
213 PollReq
->Handles
[i
].Status
=
214 PollReq
->Handles
[i
].Events
& FCB
->PollState
;
215 if( PollReq
->Handles
[i
].Status
) {
216 AFD_DbgPrint(MID_TRACE
,("Signalling %p with %x\n",
217 FCB
, FCB
->PollState
));
223 Status
= STATUS_SUCCESS
;
224 Irp
->IoStatus
.Status
= Status
;
225 SignalSocket( NULL
, Irp
, PollReq
, Status
);
228 PAFD_ACTIVE_POLL Poll
= NULL
;
230 Poll
= ExAllocatePool( NonPagedPool
, sizeof(AFD_ACTIVE_POLL
) );
234 Poll
->DeviceExt
= DeviceExt
;
235 Poll
->Exclusive
= Exclusive
;
237 KeInitializeTimerEx( &Poll
->Timer
, NotificationTimer
);
239 KeInitializeDpc( (PRKDPC
)&Poll
->TimeoutDpc
, SelectTimeout
, Poll
);
241 InsertTailList( &DeviceExt
->Polls
, &Poll
->ListEntry
);
243 KeSetTimer( &Poll
->Timer
, PollReq
->Timeout
, &Poll
->TimeoutDpc
);
245 Status
= STATUS_PENDING
;
246 IoMarkIrpPending( Irp
);
247 (void)IoSetCancelRoutine(Irp
, AfdCancelHandler
);
249 AFD_DbgPrint(MAX_TRACE
, ("FIXME: do something with the IRP!\n"));
250 Status
= STATUS_NO_MEMORY
;
254 KeReleaseSpinLock( &DeviceExt
->Lock
, OldIrql
);
256 AFD_DbgPrint(MID_TRACE
,("Returning %x\n", Status
));
262 AfdEventSelect( PDEVICE_OBJECT DeviceObject
, PIRP Irp
,
263 PIO_STACK_LOCATION IrpSp
) {
264 PFILE_OBJECT FileObject
= IrpSp
->FileObject
;
265 NTSTATUS Status
= STATUS_NO_MEMORY
;
266 PAFD_EVENT_SELECT_INFO EventSelectInfo
=
267 (PAFD_EVENT_SELECT_INFO
)LockRequest( Irp
, IrpSp
, FALSE
, NULL
);
268 PAFD_FCB FCB
= FileObject
->FsContext
;
270 UNREFERENCED_PARAMETER(DeviceObject
);
272 if( !SocketAcquireStateLock( FCB
) ) {
273 return LostSocket( Irp
);
276 if ( !EventSelectInfo
) {
277 return UnlockAndMaybeComplete( FCB
, STATUS_NO_MEMORY
, Irp
,
280 AFD_DbgPrint(MID_TRACE
,("Called (Event %p Triggers %u)\n",
281 EventSelectInfo
->EventObject
,
282 EventSelectInfo
->Events
));
284 if( FCB
->EventSelect
) ObDereferenceObject( FCB
->EventSelect
);
285 FCB
->EventSelect
= NULL
;
287 if( EventSelectInfo
->EventObject
&& EventSelectInfo
->Events
) {
288 Status
= ObReferenceObjectByHandle( (PVOID
)EventSelectInfo
->
293 (PVOID
*)&FCB
->EventSelect
,
296 if( !NT_SUCCESS(Status
) )
298 AFD_DbgPrint(MIN_TRACE
,("Failed reference event (0x%x)\n", Status
));
299 FCB
->EventSelect
= NULL
;
302 FCB
->EventSelectTriggers
= EventSelectInfo
->Events
;
304 FCB
->EventSelect
= NULL
;
305 FCB
->EventSelectTriggers
= 0;
306 Status
= STATUS_SUCCESS
;
309 if((FCB
->EventSelect
) &&
310 (FCB
->PollState
& (FCB
->EventSelectTriggers
& ~FCB
->EventSelectDisabled
)))
312 AFD_DbgPrint(MID_TRACE
,("Setting event %p\n", FCB
->EventSelect
));
314 /* Set the application's event */
315 KeSetEvent( FCB
->EventSelect
, IO_NETWORK_INCREMENT
, FALSE
);
318 AFD_DbgPrint(MID_TRACE
,("Returning %x\n", Status
));
320 return UnlockAndMaybeComplete( FCB
, Status
, Irp
,
325 AfdEnumEvents( PDEVICE_OBJECT DeviceObject
, PIRP Irp
,
326 PIO_STACK_LOCATION IrpSp
) {
327 PFILE_OBJECT FileObject
= IrpSp
->FileObject
;
328 PAFD_ENUM_NETWORK_EVENTS_INFO EnumReq
=
329 (PAFD_ENUM_NETWORK_EVENTS_INFO
)LockRequest( Irp
, IrpSp
, TRUE
, NULL
);
330 PAFD_FCB FCB
= FileObject
->FsContext
;
334 UNREFERENCED_PARAMETER(DeviceObject
);
336 AFD_DbgPrint(MID_TRACE
,("Called (FCB %p)\n", FCB
));
338 if( !SocketAcquireStateLock( FCB
) ) {
339 return LostSocket( Irp
);
343 return UnlockAndMaybeComplete( FCB
, STATUS_NO_MEMORY
, Irp
, 0 );
346 Status
= ObReferenceObjectByHandle(EnumReq
->Event
,
352 if (!NT_SUCCESS(Status
))
354 AFD_DbgPrint(MIN_TRACE
,("Unable to reference event %x\n", Status
));
355 return UnlockAndMaybeComplete(FCB
, Status
, Irp
, 0);
358 /* Clear the event */
359 KeClearEvent(UserEvent
);
360 ObDereferenceObject(UserEvent
);
362 /* Copy the poll state, masking out disabled events */
363 EnumReq
->PollEvents
= (FCB
->PollState
& ~FCB
->EventSelectDisabled
);
364 RtlCopyMemory( EnumReq
->EventStatus
,
366 sizeof(EnumReq
->EventStatus
) );
368 /* Disable the events that triggered the select until the reenabling function is called */
369 FCB
->EventSelectDisabled
|= (FCB
->PollState
& FCB
->EventSelectTriggers
);
371 return UnlockAndMaybeComplete( FCB
, STATUS_SUCCESS
, Irp
, 0 );
374 /* * * NOTE ALWAYS CALLED AT DISPATCH_LEVEL * * */
375 static BOOLEAN
UpdatePollWithFCB( PAFD_ACTIVE_POLL Poll
, PFILE_OBJECT FileObject
) {
379 PAFD_POLL_INFO PollReq
= Poll
->Irp
->AssociatedIrp
.SystemBuffer
;
381 ASSERT( KeGetCurrentIrql() == DISPATCH_LEVEL
);
383 for( i
= 0; i
< PollReq
->HandleCount
; i
++ ) {
384 if( !AFD_HANDLES(PollReq
)[i
].Handle
) continue;
386 FileObject
= (PFILE_OBJECT
)AFD_HANDLES(PollReq
)[i
].Handle
;
387 FCB
= FileObject
->FsContext
;
389 PollReq
->Handles
[i
].Status
= PollReq
->Handles
[i
].Events
& FCB
->PollState
;
390 if( PollReq
->Handles
[i
].Status
) {
391 AFD_DbgPrint(MID_TRACE
,("Signalling %p with %x\n",
392 FCB
, FCB
->PollState
));
397 return Signalled
? 1 : 0;
400 VOID
PollReeval( PAFD_DEVICE_EXTENSION DeviceExt
, PFILE_OBJECT FileObject
) {
401 PAFD_ACTIVE_POLL Poll
= NULL
;
402 PLIST_ENTRY ThePollEnt
= NULL
;
405 PAFD_POLL_INFO PollReq
;
407 AFD_DbgPrint(MID_TRACE
,("Called: DeviceExt %p FileObject %p\n",
408 DeviceExt
, FileObject
));
410 KeAcquireSpinLock( &DeviceExt
->Lock
, &OldIrql
);
412 /* Take care of any event select signalling */
413 FCB
= (PAFD_FCB
)FileObject
->FsContext
;
416 KeReleaseSpinLock( &DeviceExt
->Lock
, OldIrql
);
420 /* Now signal normal select irps */
421 ThePollEnt
= DeviceExt
->Polls
.Flink
;
423 while( ThePollEnt
!= &DeviceExt
->Polls
) {
424 Poll
= CONTAINING_RECORD( ThePollEnt
, AFD_ACTIVE_POLL
, ListEntry
);
425 PollReq
= Poll
->Irp
->AssociatedIrp
.SystemBuffer
;
426 AFD_DbgPrint(MID_TRACE
,("Checking poll %p\n", Poll
));
428 if( UpdatePollWithFCB( Poll
, FileObject
) ) {
429 ThePollEnt
= ThePollEnt
->Flink
;
430 AFD_DbgPrint(MID_TRACE
,("Signalling socket\n"));
431 SignalSocket( Poll
, NULL
, PollReq
, STATUS_SUCCESS
);
433 ThePollEnt
= ThePollEnt
->Flink
;
436 KeReleaseSpinLock( &DeviceExt
->Lock
, OldIrql
);
438 if((FCB
->EventSelect
) &&
439 (FCB
->PollState
& (FCB
->EventSelectTriggers
& ~FCB
->EventSelectDisabled
)))
441 AFD_DbgPrint(MID_TRACE
,("Setting event %p\n", FCB
->EventSelect
));
443 /* Set the application's event */
444 KeSetEvent( FCB
->EventSelect
, IO_NETWORK_INCREMENT
, FALSE
);
447 AFD_DbgPrint(MID_TRACE
,("Leaving\n"));