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 VOID
SelectTimeout( PKDPC Dpc
,
95 PVOID DeferredContext
,
96 PVOID SystemArgument1
,
97 PVOID SystemArgument2
) {
98 PAFD_ACTIVE_POLL Poll
= DeferredContext
;
99 PAFD_POLL_INFO PollReq
;
102 PAFD_DEVICE_EXTENSION DeviceExt
;
104 AFD_DbgPrint(MID_TRACE
,("Called\n"));
107 DeviceExt
= Poll
->DeviceExt
;
108 PollReq
= Irp
->AssociatedIrp
.SystemBuffer
;
110 ZeroEvents( PollReq
->Handles
, PollReq
->HandleCount
);
112 KeAcquireSpinLock( &DeviceExt
->Lock
, &OldIrql
);
113 SignalSocket( Poll
, NULL
, PollReq
, STATUS_TIMEOUT
);
114 KeReleaseSpinLock( &DeviceExt
->Lock
, OldIrql
);
116 AFD_DbgPrint(MID_TRACE
,("Timeout\n"));
119 VOID
KillSelectsForFCB( PAFD_DEVICE_EXTENSION DeviceExt
,
120 PFILE_OBJECT FileObject
,
121 BOOLEAN OnlyExclusive
) {
123 PLIST_ENTRY ListEntry
;
124 PAFD_ACTIVE_POLL Poll
;
126 PAFD_POLL_INFO PollReq
;
127 PAFD_HANDLE HandleArray
;
130 AFD_DbgPrint(MID_TRACE
,("Killing selects that refer to %x\n", FileObject
));
132 KeAcquireSpinLock( &DeviceExt
->Lock
, &OldIrql
);
134 ListEntry
= DeviceExt
->Polls
.Flink
;
135 while ( ListEntry
!= &DeviceExt
->Polls
) {
136 Poll
= CONTAINING_RECORD(ListEntry
, AFD_ACTIVE_POLL
, ListEntry
);
137 ListEntry
= ListEntry
->Flink
;
139 PollReq
= Irp
->AssociatedIrp
.SystemBuffer
;
140 HandleArray
= AFD_HANDLES(PollReq
);
142 for( i
= 0; i
< PollReq
->HandleCount
; i
++ ) {
143 AFD_DbgPrint(MAX_TRACE
,("Req: %x, This %x\n",
144 HandleArray
[i
].Handle
, FileObject
));
145 if( (PVOID
)HandleArray
[i
].Handle
== FileObject
&&
146 (!OnlyExclusive
|| (OnlyExclusive
&& Poll
->Exclusive
)) ) {
147 ZeroEvents( PollReq
->Handles
, PollReq
->HandleCount
);
148 SignalSocket( Poll
, NULL
, PollReq
, STATUS_CANCELLED
);
153 KeReleaseSpinLock( &DeviceExt
->Lock
, OldIrql
);
155 AFD_DbgPrint(MID_TRACE
,("Done\n"));
159 AfdSelect( PDEVICE_OBJECT DeviceObject
, PIRP Irp
,
160 PIO_STACK_LOCATION IrpSp
) {
161 NTSTATUS Status
= STATUS_NO_MEMORY
;
163 PFILE_OBJECT FileObject
;
164 PAFD_POLL_INFO PollReq
= Irp
->AssociatedIrp
.SystemBuffer
;
165 PAFD_DEVICE_EXTENSION DeviceExt
= DeviceObject
->DeviceExtension
;
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 STATUS_NO_MEMORY
;
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 KeAcquireSpinLock( &DeviceExt
->Lock
, &OldIrql
);
196 for( i
= 0; i
< PollReq
->HandleCount
; i
++ ) {
197 if( !AFD_HANDLES(PollReq
)[i
].Handle
) continue;
199 FileObject
= (PFILE_OBJECT
)AFD_HANDLES(PollReq
)[i
].Handle
;
200 FCB
= FileObject
->FsContext
;
202 AFD_DbgPrint(MID_TRACE
, ("AFD: Select Events: "));
203 PrintEvents( PollReq
->Handles
[i
].Events
);
204 AFD_DbgPrint(MID_TRACE
,("\n"));
206 PollReq
->Handles
[i
].Status
=
207 PollReq
->Handles
[i
].Events
& FCB
->PollState
;
208 if( PollReq
->Handles
[i
].Status
) {
209 AFD_DbgPrint(MID_TRACE
,("Signalling %x with %x\n",
210 FCB
, FCB
->PollState
));
216 Status
= STATUS_SUCCESS
;
217 Irp
->IoStatus
.Status
= Status
;
218 SignalSocket( NULL
, Irp
, PollReq
, Status
);
221 PAFD_ACTIVE_POLL Poll
= NULL
;
223 Poll
= ExAllocatePool( NonPagedPool
, sizeof(AFD_ACTIVE_POLL
) );
227 Poll
->DeviceExt
= DeviceExt
;
228 Poll
->Exclusive
= Exclusive
;
230 KeInitializeTimerEx( &Poll
->Timer
, NotificationTimer
);
232 KeInitializeDpc( (PRKDPC
)&Poll
->TimeoutDpc
,
233 (PKDEFERRED_ROUTINE
)SelectTimeout
,
236 InsertTailList( &DeviceExt
->Polls
, &Poll
->ListEntry
);
238 KeSetTimer( &Poll
->Timer
, PollReq
->Timeout
, &Poll
->TimeoutDpc
);
240 Status
= STATUS_PENDING
;
241 IoMarkIrpPending( Irp
);
242 (void)IoSetCancelRoutine(Irp
, AfdCancelHandler
);
244 AFD_DbgPrint(MAX_TRACE
, ("FIXME: do something with the IRP!\n"));
245 Status
= STATUS_NO_MEMORY
;
249 KeReleaseSpinLock( &DeviceExt
->Lock
, OldIrql
);
251 AFD_DbgPrint(MID_TRACE
,("Returning %x\n", Status
));
257 AfdEventSelect( PDEVICE_OBJECT DeviceObject
, PIRP Irp
,
258 PIO_STACK_LOCATION IrpSp
) {
259 PFILE_OBJECT FileObject
= IrpSp
->FileObject
;
260 NTSTATUS Status
= STATUS_NO_MEMORY
;
261 PAFD_EVENT_SELECT_INFO EventSelectInfo
=
262 (PAFD_EVENT_SELECT_INFO
)LockRequest( Irp
, IrpSp
);
263 PAFD_FCB FCB
= FileObject
->FsContext
;
265 if( !SocketAcquireStateLock( FCB
) ) {
266 return LostSocket( Irp
);
269 if ( !EventSelectInfo
) {
270 return UnlockAndMaybeComplete( FCB
, STATUS_NO_MEMORY
, Irp
,
273 AFD_DbgPrint(MID_TRACE
,("Called (Event %x Triggers %x)\n",
274 EventSelectInfo
->EventObject
,
275 EventSelectInfo
->Events
));
277 if( FCB
->EventSelect
) ObDereferenceObject( FCB
->EventSelect
);
278 FCB
->EventSelect
= NULL
;
280 if( EventSelectInfo
->EventObject
&& EventSelectInfo
->Events
) {
281 Status
= ObReferenceObjectByHandle( (PVOID
)EventSelectInfo
->
286 (PVOID
*)&FCB
->EventSelect
,
289 if( !NT_SUCCESS(Status
) )
291 AFD_DbgPrint(MIN_TRACE
,("Failed reference event (0x%x)\n", Status
));
292 FCB
->EventSelect
= NULL
;
295 FCB
->EventSelectTriggers
= EventSelectInfo
->Events
;
297 FCB
->EventSelect
= NULL
;
298 FCB
->EventSelectTriggers
= 0;
299 Status
= STATUS_SUCCESS
;
302 if((FCB
->EventSelect
) &&
303 (FCB
->PollState
& (FCB
->EventSelectTriggers
& ~FCB
->EventSelectDisabled
)))
305 AFD_DbgPrint(MID_TRACE
,("Setting event %x\n", FCB
->EventSelect
));
307 /* Disable the events that triggered the select until the reenabling function is called */
308 FCB
->EventSelectDisabled
|= (FCB
->PollState
& (FCB
->EventSelectTriggers
& ~FCB
->EventSelectDisabled
));
310 /* Set the application's event */
311 KeSetEvent( FCB
->EventSelect
, IO_NETWORK_INCREMENT
, FALSE
);
314 AFD_DbgPrint(MID_TRACE
,("Returning %x\n", Status
));
316 return UnlockAndMaybeComplete( FCB
, Status
, Irp
,
321 AfdEnumEvents( PDEVICE_OBJECT DeviceObject
, PIRP Irp
,
322 PIO_STACK_LOCATION IrpSp
) {
323 PFILE_OBJECT FileObject
= IrpSp
->FileObject
;
324 PAFD_ENUM_NETWORK_EVENTS_INFO EnumReq
=
325 (PAFD_ENUM_NETWORK_EVENTS_INFO
)LockRequest( Irp
, IrpSp
);
326 PAFD_FCB FCB
= FileObject
->FsContext
;
328 AFD_DbgPrint(MID_TRACE
,("Called (FCB %x)\n", FCB
));
330 if( !SocketAcquireStateLock( FCB
) ) {
331 return LostSocket( Irp
);
335 return UnlockAndMaybeComplete( FCB
, STATUS_NO_MEMORY
, Irp
,
339 EnumReq
->PollEvents
= FCB
->PollState
;
340 RtlCopyMemory( EnumReq
->EventStatus
,
342 sizeof(EnumReq
->EventStatus
) );
344 return UnlockAndMaybeComplete( FCB
, STATUS_SUCCESS
, Irp
,
348 /* * * NOTE ALWAYS CALLED AT DISPATCH_LEVEL * * */
349 static BOOLEAN
UpdatePollWithFCB( PAFD_ACTIVE_POLL Poll
, PFILE_OBJECT FileObject
) {
353 PAFD_POLL_INFO PollReq
= Poll
->Irp
->AssociatedIrp
.SystemBuffer
;
355 ASSERT( KeGetCurrentIrql() == DISPATCH_LEVEL
);
357 for( i
= 0; i
< PollReq
->HandleCount
; i
++ ) {
358 if( !AFD_HANDLES(PollReq
)[i
].Handle
) continue;
360 FileObject
= (PFILE_OBJECT
)AFD_HANDLES(PollReq
)[i
].Handle
;
361 FCB
= FileObject
->FsContext
;
363 PollReq
->Handles
[i
].Status
= PollReq
->Handles
[i
].Events
& FCB
->PollState
;
364 if( PollReq
->Handles
[i
].Status
) {
365 AFD_DbgPrint(MID_TRACE
,("Signalling %x with %x\n",
366 FCB
, FCB
->PollState
));
371 return Signalled
? 1 : 0;
374 VOID
PollReeval( PAFD_DEVICE_EXTENSION DeviceExt
, PFILE_OBJECT FileObject
) {
375 PAFD_ACTIVE_POLL Poll
= NULL
;
376 PLIST_ENTRY ThePollEnt
= NULL
;
379 PAFD_POLL_INFO PollReq
;
381 AFD_DbgPrint(MID_TRACE
,("Called: DeviceExt %x FileObject %x\n",
382 DeviceExt
, FileObject
));
384 KeAcquireSpinLock( &DeviceExt
->Lock
, &OldIrql
);
386 /* Take care of any event select signalling */
387 FCB
= (PAFD_FCB
)FileObject
->FsContext
;
390 KeReleaseSpinLock( &DeviceExt
->Lock
, OldIrql
);
394 /* Now signal normal select irps */
395 ThePollEnt
= DeviceExt
->Polls
.Flink
;
397 while( ThePollEnt
!= &DeviceExt
->Polls
) {
398 Poll
= CONTAINING_RECORD( ThePollEnt
, AFD_ACTIVE_POLL
, ListEntry
);
399 PollReq
= Poll
->Irp
->AssociatedIrp
.SystemBuffer
;
400 AFD_DbgPrint(MID_TRACE
,("Checking poll %x\n", Poll
));
402 if( UpdatePollWithFCB( Poll
, FileObject
) ) {
403 ThePollEnt
= ThePollEnt
->Flink
;
404 AFD_DbgPrint(MID_TRACE
,("Signalling socket\n"));
405 SignalSocket( Poll
, NULL
, PollReq
, STATUS_SUCCESS
);
407 ThePollEnt
= ThePollEnt
->Flink
;
410 KeReleaseSpinLock( &DeviceExt
->Lock
, OldIrql
);
412 if((FCB
->EventSelect
) &&
413 (FCB
->PollState
& (FCB
->EventSelectTriggers
& ~FCB
->EventSelectDisabled
)))
415 AFD_DbgPrint(MID_TRACE
,("Setting event %x\n", FCB
->EventSelect
));
417 /* Disable the events that triggered the select until the reenabling function is called */
418 FCB
->EventSelectDisabled
|= (FCB
->PollState
& (FCB
->EventSelectTriggers
& ~FCB
->EventSelectDisabled
));
420 /* Set the application's event */
421 KeSetEvent( FCB
->EventSelect
, IO_NETWORK_INCREMENT
, FALSE
);
424 AFD_DbgPrint(MID_TRACE
,("Leaving\n"));