1 /* $Id: select.c,v 1.3 2004/09/05 04:26:29 arty Exp $
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
CopyBackStatus( PAFD_HANDLE HandleArray
,
19 for( i
= 0; i
< HandleCount
; i
++ ) {
20 HandleArray
[i
].Events
= HandleArray
[i
].Status
;
21 HandleArray
[i
].Status
= 0;
25 VOID
ZeroEvents( PAFD_HANDLE HandleArray
,
29 for( i
= 0; i
< HandleCount
; i
++ ) {
30 HandleArray
[i
].Events
= 0;
31 HandleArray
[i
].Status
= 0;
36 ScanForImmediateTrigger( PAFD_HANDLE HandleArray
,
39 NTSTATUS Status
= STATUS_SUCCESS
;
40 PFILE_OBJECT FileObject
;
43 BOOLEAN ShouldReturnNow
= FALSE
;
45 for( i
= 0; i
< HandleCount
&& NT_SUCCESS(Status
); i
++ ) {
46 HandleArray
[i
].Status
= 0;
48 ObReferenceObjectByHandle
49 ( (PVOID
)HandleArray
[i
].Handle
,
56 if( NT_SUCCESS(Status
) ) {
57 FCB
= FileObject
->FsContext
;
58 /* Check select bits */
59 if( !SocketAcquireStateLock( FCB
) )
60 Status
= STATUS_UNSUCCESSFUL
;
61 if( NT_SUCCESS(Status
) )
62 HandleArray
[i
].Status
=
63 FCB
->PollState
& HandleArray
[i
].Events
;
64 if( HandleArray
[i
].Status
) ShouldReturnNow
= TRUE
;
65 ObDereferenceObject( (PVOID
)HandleArray
[i
].Handle
);
69 if( !NT_SUCCESS(Status
) || ShouldReturnNow
) return Status
;
70 else return STATUS_PENDING
;
73 VOID
SelectTimeout( PKDPC Dpc
,
74 PVOID DeferredContext
,
75 PVOID SystemArgument1
,
76 PVOID SystemArgument2
) {
77 PAFD_ACTIVE_POLL Poll
= DeferredContext
;
78 PAFD_POLL_INFO PollReq
;
79 PAFD_DEVICE_EXTENSION DeviceExt
;
84 DeviceExt
= Poll
->DeviceExt
;
86 PollReq
= Irp
->AssociatedIrp
.SystemBuffer
;
88 KeAcquireSpinLock( &DeviceExt
->Lock
, &OldIrql
);
89 RemoveEntryList( &Poll
->ListEntry
);
90 KeReleaseSpinLock( &DeviceExt
->Lock
, OldIrql
);
94 ZeroEvents( PollReq
->Handles
, PollReq
->HandleCount
);
96 Irp
->IoStatus
.Status
= STATUS_TIMEOUT
;
97 Irp
->IoStatus
.Information
= -1;
99 IoCompleteRequest( Irp
, IO_NO_INCREMENT
);
103 AfdSelect( PDEVICE_OBJECT DeviceObject
, PIRP Irp
,
104 PIO_STACK_LOCATION IrpSp
) {
105 NTSTATUS Status
= STATUS_NO_MEMORY
;
106 PAFD_POLL_INFO PollReq
= Irp
->AssociatedIrp
.SystemBuffer
;
107 PAFD_DEVICE_EXTENSION DeviceExt
= DeviceObject
->DeviceExtension
;
108 PAFD_ACTIVE_POLL Poll
= NULL
;
109 UINT CopySize
= IrpSp
->Parameters
.DeviceIoControl
.InputBufferLength
;
111 CopySize
+ sizeof(AFD_ACTIVE_POLL
) - sizeof(AFD_POLL_INFO
);
113 UINT HandlesSignalled
;
115 AFD_DbgPrint(MID_TRACE
,("Called\n"));
117 Status
= ScanForImmediateTrigger( PollReq
->Handles
,
118 PollReq
->HandleCount
,
121 if( Status
== STATUS_PENDING
) {
122 Poll
= ExAllocatePool( NonPagedPool
, AllocSize
);
125 KeAcquireSpinLock( &DeviceExt
->Lock
, &OldIrql
);
127 KeInitializeDpc( (PRKDPC
)&Poll
->TimeoutDpc
,
128 (PKDEFERRED_ROUTINE
)SelectTimeout
,
130 PollReq
->Timeout
.QuadPart
*= -1;
131 /* Negative values are relative */
132 KeInitializeTimerEx( &Poll
->Timer
, NotificationTimer
);
133 KeSetTimer( &Poll
->Timer
, PollReq
->Timeout
, &Poll
->TimeoutDpc
);
136 Poll
->DeviceExt
= DeviceExt
;
138 InsertTailList( &DeviceExt
->Polls
, &Poll
->ListEntry
);
139 Status
= STATUS_PENDING
;
141 KeReleaseSpinLock( &DeviceExt
->Lock
, OldIrql
);
142 } else Status
= STATUS_NO_MEMORY
;
143 } else if( Status
== STATUS_SUCCESS
) {
144 CopyBackStatus( PollReq
->Handles
,
145 PollReq
->HandleCount
);
147 ZeroEvents( PollReq
->Handles
,
148 PollReq
->HandleCount
);
151 AFD_DbgPrint(MID_TRACE
,("Returning %x\n", Status
));
153 if( Status
== STATUS_PENDING
)
154 IoMarkIrpPending( Irp
);
156 Irp
->IoStatus
.Status
= Status
;
157 Irp
->IoStatus
.Information
= HandlesSignalled
;
158 IoCompleteRequest( Irp
, IO_NETWORK_INCREMENT
);
164 VOID
SignalSocket( PAFD_ACTIVE_POLL Poll
, PAFD_POLL_INFO PollReq
, UINT i
) {
165 /* One of the files was destroyed. We return now with error. */
166 Poll
->Irp
->IoStatus
.Status
= STATUS_SUCCESS
; /* XXX REVISIT */
167 Poll
->Irp
->IoStatus
.Information
= 1;
168 CopyBackStatus( PollReq
->Handles
,
169 PollReq
->HandleCount
);
170 IoCompleteRequest( Poll
->Irp
, IO_NETWORK_INCREMENT
);
173 BOOLEAN
UpdatePollWithFCB( PAFD_ACTIVE_POLL Poll
, PFILE_OBJECT FileObject
) {
176 PFILE_OBJECT TargetFile
;
178 PAFD_POLL_INFO PollReq
= Poll
->Irp
->AssociatedIrp
.SystemBuffer
;
180 for( i
= 0; i
< PollReq
->HandleCount
; i
++ ) {
182 ObReferenceObjectByHandle
183 ( (PVOID
)PollReq
->Handles
[i
].Handle
,
190 if( !NT_SUCCESS(Status
) ) {
191 PollReq
->Handles
[i
].Status
= AFD_EVENT_CLOSE
;
192 SignalSocket( Poll
, PollReq
, i
);
195 FCB
= FileObject
->FsContext
;
197 if( !SocketAcquireStateLock( FCB
) ) {
198 PollReq
->Handles
[i
].Status
= AFD_EVENT_CLOSE
;
199 SignalSocket( Poll
, PollReq
, i
);
201 PollReq
->Handles
[i
].Status
=
202 PollReq
->Handles
[i
].Events
& FCB
->PollState
;
203 if( PollReq
->Handles
[i
].Status
)
204 SignalSocket( Poll
, PollReq
, i
);
213 VOID
PollReeval( PAFD_DEVICE_EXTENSION DeviceExt
, PFILE_OBJECT FileObject
) {
214 PAFD_ACTIVE_POLL Poll
= NULL
;
215 PLIST_ENTRY ThePollEnt
= NULL
;
218 AFD_DbgPrint(MID_TRACE
,("Called: DeviceExt %x FileObject %x\n",
219 DeviceExt
, FileObject
));
221 KeAcquireSpinLock( &DeviceExt
->Lock
, &OldIrql
);
223 ThePollEnt
= DeviceExt
->Polls
.Flink
;
225 while( ThePollEnt
!= &DeviceExt
->Polls
) {
226 Poll
= CONTAINING_RECORD( ThePollEnt
, AFD_ACTIVE_POLL
, ListEntry
);
227 if( UpdatePollWithFCB( Poll
, FileObject
) ) {
228 ThePollEnt
= ThePollEnt
->Flink
;
229 RemoveEntryList( &Poll
->ListEntry
);
231 ThePollEnt
= ThePollEnt
->Flink
;
234 KeReleaseSpinLock( &DeviceExt
->Lock
, OldIrql
);
236 AFD_DbgPrint(MID_TRACE
,("Leaving\n"));