Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygenselect.c
Go to the documentation of this file.
00001 /* $Id: select.c 56389 2012-04-22 13:11:54Z tfaber $ 00002 * COPYRIGHT: See COPYING in the top level directory 00003 * PROJECT: ReactOS kernel 00004 * FILE: drivers/net/afd/afd/select.c 00005 * PURPOSE: Ancillary functions driver 00006 * PROGRAMMER: Art Yerkes (ayerkes@speakeasy.net) 00007 * UPDATE HISTORY: 00008 * 20040708 Created 00009 */ 00010 #include "afd.h" 00011 00012 static VOID PrintEvents( ULONG Events ) { 00013 #if DBG 00014 char *events_list[] = { "AFD_EVENT_RECEIVE", 00015 "AFD_EVENT_OOB_RECEIVE", 00016 "AFD_EVENT_SEND", 00017 "AFD_EVENT_DISCONNECT", 00018 "AFD_EVENT_ABORT", 00019 "AFD_EVENT_CLOSE", 00020 "AFD_EVENT_CONNECT", 00021 "AFD_EVENT_ACCEPT", 00022 "AFD_EVENT_CONNECT_FAIL", 00023 "AFD_EVENT_QOS", 00024 "AFD_EVENT_GROUP_QOS", 00025 NULL }; 00026 int i; 00027 00028 for( i = 0; events_list[i]; i++ ) 00029 if( Events & (1 << i) ) AFD_DbgPrint(MID_TRACE,("%s ", events_list[i] )); 00030 #endif 00031 } 00032 00033 static VOID CopyBackStatus( PAFD_HANDLE HandleArray, 00034 UINT HandleCount ) { 00035 UINT i; 00036 00037 for( i = 0; i < HandleCount; i++ ) { 00038 HandleArray[i].Events = HandleArray[i].Status; 00039 HandleArray[i].Status = 0; 00040 } 00041 } 00042 00043 VOID ZeroEvents( PAFD_HANDLE HandleArray, 00044 UINT HandleCount ) { 00045 UINT i; 00046 00047 for( i = 0; i < HandleCount; i++ ) { 00048 HandleArray[i].Status = 0; 00049 HandleArray[i].Events = 0; 00050 } 00051 } 00052 00053 00054 /* you must pass either Poll OR Irp */ 00055 VOID SignalSocket( 00056 PAFD_ACTIVE_POLL Poll OPTIONAL, 00057 PIRP _Irp OPTIONAL, 00058 PAFD_POLL_INFO PollReq, 00059 NTSTATUS Status 00060 ) 00061 { 00062 UINT i; 00063 PIRP Irp = _Irp ? _Irp : Poll->Irp; 00064 AFD_DbgPrint(MID_TRACE,("Called (Status %x)\n", Status)); 00065 00066 if (Poll) 00067 { 00068 KeCancelTimer( &Poll->Timer ); 00069 RemoveEntryList( &Poll->ListEntry ); 00070 ExFreePool( Poll ); 00071 } 00072 00073 Irp->IoStatus.Status = Status; 00074 Irp->IoStatus.Information = 00075 FIELD_OFFSET(AFD_POLL_INFO, Handles) + sizeof(AFD_HANDLE) * PollReq->HandleCount; 00076 CopyBackStatus( PollReq->Handles, 00077 PollReq->HandleCount ); 00078 for( i = 0; i < PollReq->HandleCount; i++ ) { 00079 AFD_DbgPrint 00080 (MAX_TRACE, 00081 ("Handle(%x): Got %x,%x\n", 00082 PollReq->Handles[i].Handle, 00083 PollReq->Handles[i].Events, 00084 PollReq->Handles[i].Status)); 00085 } 00086 UnlockHandles( AFD_HANDLES(PollReq), PollReq->HandleCount ); 00087 if( Irp->MdlAddress ) UnlockRequest( Irp, IoGetCurrentIrpStackLocation( Irp ) ); 00088 AFD_DbgPrint(MID_TRACE,("Completing\n")); 00089 (void)IoSetCancelRoutine(Irp, NULL); 00090 IoCompleteRequest( Irp, IO_NETWORK_INCREMENT ); 00091 AFD_DbgPrint(MID_TRACE,("Done\n")); 00092 } 00093 00094 static VOID SelectTimeout( PKDPC Dpc, 00095 PVOID DeferredContext, 00096 PVOID SystemArgument1, 00097 PVOID SystemArgument2 ) { 00098 PAFD_ACTIVE_POLL Poll = DeferredContext; 00099 PAFD_POLL_INFO PollReq; 00100 PIRP Irp; 00101 KIRQL OldIrql; 00102 PAFD_DEVICE_EXTENSION DeviceExt; 00103 00104 AFD_DbgPrint(MID_TRACE,("Called\n")); 00105 00106 Irp = Poll->Irp; 00107 DeviceExt = Poll->DeviceExt; 00108 PollReq = Irp->AssociatedIrp.SystemBuffer; 00109 00110 ZeroEvents( PollReq->Handles, PollReq->HandleCount ); 00111 00112 KeAcquireSpinLock( &DeviceExt->Lock, &OldIrql ); 00113 SignalSocket( Poll, NULL, PollReq, STATUS_TIMEOUT ); 00114 KeReleaseSpinLock( &DeviceExt->Lock, OldIrql ); 00115 00116 AFD_DbgPrint(MID_TRACE,("Timeout\n")); 00117 } 00118 00119 VOID KillSelectsForFCB( PAFD_DEVICE_EXTENSION DeviceExt, 00120 PFILE_OBJECT FileObject, 00121 BOOLEAN OnlyExclusive ) { 00122 KIRQL OldIrql; 00123 PLIST_ENTRY ListEntry; 00124 PAFD_ACTIVE_POLL Poll; 00125 PIRP Irp; 00126 PAFD_POLL_INFO PollReq; 00127 PAFD_HANDLE HandleArray; 00128 UINT i; 00129 00130 AFD_DbgPrint(MID_TRACE,("Killing selects that refer to %x\n", FileObject)); 00131 00132 KeAcquireSpinLock( &DeviceExt->Lock, &OldIrql ); 00133 00134 ListEntry = DeviceExt->Polls.Flink; 00135 while ( ListEntry != &DeviceExt->Polls ) { 00136 Poll = CONTAINING_RECORD(ListEntry, AFD_ACTIVE_POLL, ListEntry); 00137 ListEntry = ListEntry->Flink; 00138 Irp = Poll->Irp; 00139 PollReq = Irp->AssociatedIrp.SystemBuffer; 00140 HandleArray = AFD_HANDLES(PollReq); 00141 00142 for( i = 0; i < PollReq->HandleCount; i++ ) { 00143 AFD_DbgPrint(MAX_TRACE,("Req: %x, This %x\n", 00144 HandleArray[i].Handle, FileObject)); 00145 if( (PVOID)HandleArray[i].Handle == FileObject && 00146 (!OnlyExclusive || (OnlyExclusive && Poll->Exclusive)) ) { 00147 ZeroEvents( PollReq->Handles, PollReq->HandleCount ); 00148 SignalSocket( Poll, NULL, PollReq, STATUS_CANCELLED ); 00149 } 00150 } 00151 } 00152 00153 KeReleaseSpinLock( &DeviceExt->Lock, OldIrql ); 00154 00155 AFD_DbgPrint(MID_TRACE,("Done\n")); 00156 } 00157 00158 NTSTATUS NTAPI 00159 AfdSelect( PDEVICE_OBJECT DeviceObject, PIRP Irp, 00160 PIO_STACK_LOCATION IrpSp ) { 00161 NTSTATUS Status = STATUS_NO_MEMORY; 00162 PAFD_FCB FCB; 00163 PFILE_OBJECT FileObject; 00164 PAFD_POLL_INFO PollReq = Irp->AssociatedIrp.SystemBuffer; 00165 PAFD_DEVICE_EXTENSION DeviceExt = DeviceObject->DeviceExtension; 00166 KIRQL OldIrql; 00167 UINT i, Signalled = 0; 00168 ULONG Exclusive = PollReq->Exclusive; 00169 00170 AFD_DbgPrint(MID_TRACE,("Called (HandleCount %d Timeout %d)\n", 00171 PollReq->HandleCount, 00172 (INT)(PollReq->Timeout.QuadPart))); 00173 00174 SET_AFD_HANDLES(PollReq, 00175 LockHandles( PollReq->Handles, PollReq->HandleCount )); 00176 00177 if( !AFD_HANDLES(PollReq) ) { 00178 Irp->IoStatus.Status = STATUS_NO_MEMORY; 00179 Irp->IoStatus.Information = 0; 00180 IoCompleteRequest( Irp, IO_NETWORK_INCREMENT ); 00181 return STATUS_NO_MEMORY; 00182 } 00183 00184 if( Exclusive ) { 00185 for( i = 0; i < PollReq->HandleCount; i++ ) { 00186 if( !AFD_HANDLES(PollReq)[i].Handle ) continue; 00187 00188 KillSelectsForFCB( DeviceExt, 00189 (PFILE_OBJECT)AFD_HANDLES(PollReq)[i].Handle, 00190 TRUE ); 00191 } 00192 } 00193 00194 KeAcquireSpinLock( &DeviceExt->Lock, &OldIrql ); 00195 00196 for( i = 0; i < PollReq->HandleCount; i++ ) { 00197 if( !AFD_HANDLES(PollReq)[i].Handle ) continue; 00198 00199 FileObject = (PFILE_OBJECT)AFD_HANDLES(PollReq)[i].Handle; 00200 FCB = FileObject->FsContext; 00201 00202 AFD_DbgPrint(MID_TRACE, ("AFD: Select Events: ")); 00203 PrintEvents( PollReq->Handles[i].Events ); 00204 AFD_DbgPrint(MID_TRACE,("\n")); 00205 00206 PollReq->Handles[i].Status = 00207 PollReq->Handles[i].Events & FCB->PollState; 00208 if( PollReq->Handles[i].Status ) { 00209 AFD_DbgPrint(MID_TRACE,("Signalling %x with %x\n", 00210 FCB, FCB->PollState)); 00211 Signalled++; 00212 } 00213 } 00214 00215 if( Signalled ) { 00216 Status = STATUS_SUCCESS; 00217 Irp->IoStatus.Status = Status; 00218 SignalSocket( NULL, Irp, PollReq, Status ); 00219 } else { 00220 00221 PAFD_ACTIVE_POLL Poll = NULL; 00222 00223 Poll = ExAllocatePool( NonPagedPool, sizeof(AFD_ACTIVE_POLL) ); 00224 00225 if (Poll){ 00226 Poll->Irp = Irp; 00227 Poll->DeviceExt = DeviceExt; 00228 Poll->Exclusive = Exclusive; 00229 00230 KeInitializeTimerEx( &Poll->Timer, NotificationTimer ); 00231 00232 KeInitializeDpc( (PRKDPC)&Poll->TimeoutDpc, 00233 (PKDEFERRED_ROUTINE)SelectTimeout, 00234 Poll ); 00235 00236 InsertTailList( &DeviceExt->Polls, &Poll->ListEntry ); 00237 00238 KeSetTimer( &Poll->Timer, PollReq->Timeout, &Poll->TimeoutDpc ); 00239 00240 Status = STATUS_PENDING; 00241 IoMarkIrpPending( Irp ); 00242 (void)IoSetCancelRoutine(Irp, AfdCancelHandler); 00243 } else { 00244 AFD_DbgPrint(MAX_TRACE, ("FIXME: do something with the IRP!\n")); 00245 Status = STATUS_NO_MEMORY; 00246 } 00247 } 00248 00249 KeReleaseSpinLock( &DeviceExt->Lock, OldIrql ); 00250 00251 AFD_DbgPrint(MID_TRACE,("Returning %x\n", Status)); 00252 00253 return Status; 00254 } 00255 00256 NTSTATUS NTAPI 00257 AfdEventSelect( PDEVICE_OBJECT DeviceObject, PIRP Irp, 00258 PIO_STACK_LOCATION IrpSp ) { 00259 PFILE_OBJECT FileObject = IrpSp->FileObject; 00260 NTSTATUS Status = STATUS_NO_MEMORY; 00261 PAFD_EVENT_SELECT_INFO EventSelectInfo = 00262 (PAFD_EVENT_SELECT_INFO)LockRequest( Irp, IrpSp ); 00263 PAFD_FCB FCB = FileObject->FsContext; 00264 00265 if( !SocketAcquireStateLock( FCB ) ) { 00266 return LostSocket( Irp ); 00267 } 00268 00269 if ( !EventSelectInfo ) { 00270 return UnlockAndMaybeComplete( FCB, STATUS_NO_MEMORY, Irp, 00271 0 ); 00272 } 00273 AFD_DbgPrint(MID_TRACE,("Called (Event %x Triggers %x)\n", 00274 EventSelectInfo->EventObject, 00275 EventSelectInfo->Events)); 00276 00277 if( FCB->EventSelect ) ObDereferenceObject( FCB->EventSelect ); 00278 FCB->EventSelect = NULL; 00279 00280 if( EventSelectInfo->EventObject && EventSelectInfo->Events ) { 00281 Status = ObReferenceObjectByHandle( (PVOID)EventSelectInfo-> 00282 EventObject, 00283 EVENT_ALL_ACCESS, 00284 ExEventObjectType, 00285 UserMode, 00286 (PVOID *)&FCB->EventSelect, 00287 NULL ); 00288 00289 if( !NT_SUCCESS(Status) ) 00290 { 00291 AFD_DbgPrint(MIN_TRACE,("Failed reference event (0x%x)\n", Status)); 00292 FCB->EventSelect = NULL; 00293 } 00294 else 00295 FCB->EventSelectTriggers = EventSelectInfo->Events; 00296 } else { 00297 FCB->EventSelect = NULL; 00298 FCB->EventSelectTriggers = 0; 00299 Status = STATUS_SUCCESS; 00300 } 00301 00302 if((FCB->EventSelect) && 00303 (FCB->PollState & (FCB->EventSelectTriggers & ~FCB->EventSelectDisabled))) 00304 { 00305 AFD_DbgPrint(MID_TRACE,("Setting event %x\n", FCB->EventSelect)); 00306 00307 /* Disable the events that triggered the select until the reenabling function is called */ 00308 FCB->EventSelectDisabled |= (FCB->PollState & (FCB->EventSelectTriggers & ~FCB->EventSelectDisabled)); 00309 00310 /* Set the application's event */ 00311 KeSetEvent( FCB->EventSelect, IO_NETWORK_INCREMENT, FALSE ); 00312 } 00313 00314 AFD_DbgPrint(MID_TRACE,("Returning %x\n", Status)); 00315 00316 return UnlockAndMaybeComplete( FCB, Status, Irp, 00317 0 ); 00318 } 00319 00320 NTSTATUS NTAPI 00321 AfdEnumEvents( PDEVICE_OBJECT DeviceObject, PIRP Irp, 00322 PIO_STACK_LOCATION IrpSp ) { 00323 PFILE_OBJECT FileObject = IrpSp->FileObject; 00324 PAFD_ENUM_NETWORK_EVENTS_INFO EnumReq = 00325 (PAFD_ENUM_NETWORK_EVENTS_INFO)LockRequest( Irp, IrpSp ); 00326 PAFD_FCB FCB = FileObject->FsContext; 00327 00328 AFD_DbgPrint(MID_TRACE,("Called (FCB %x)\n", FCB)); 00329 00330 if( !SocketAcquireStateLock( FCB ) ) { 00331 return LostSocket( Irp ); 00332 } 00333 00334 if ( !EnumReq ) { 00335 return UnlockAndMaybeComplete( FCB, STATUS_NO_MEMORY, Irp, 0 ); 00336 } 00337 00338 EnumReq->PollEvents = FCB->PollState; 00339 RtlCopyMemory( EnumReq->EventStatus, 00340 FCB->PollStatus, 00341 sizeof(EnumReq->EventStatus) ); 00342 00343 return UnlockAndMaybeComplete( FCB, STATUS_SUCCESS, Irp, 0 ); 00344 } 00345 00346 /* * * NOTE ALWAYS CALLED AT DISPATCH_LEVEL * * */ 00347 static BOOLEAN UpdatePollWithFCB( PAFD_ACTIVE_POLL Poll, PFILE_OBJECT FileObject ) { 00348 UINT i; 00349 PAFD_FCB FCB; 00350 UINT Signalled = 0; 00351 PAFD_POLL_INFO PollReq = Poll->Irp->AssociatedIrp.SystemBuffer; 00352 00353 ASSERT( KeGetCurrentIrql() == DISPATCH_LEVEL ); 00354 00355 for( i = 0; i < PollReq->HandleCount; i++ ) { 00356 if( !AFD_HANDLES(PollReq)[i].Handle ) continue; 00357 00358 FileObject = (PFILE_OBJECT)AFD_HANDLES(PollReq)[i].Handle; 00359 FCB = FileObject->FsContext; 00360 00361 PollReq->Handles[i].Status = PollReq->Handles[i].Events & FCB->PollState; 00362 if( PollReq->Handles[i].Status ) { 00363 AFD_DbgPrint(MID_TRACE,("Signalling %x with %x\n", 00364 FCB, FCB->PollState)); 00365 Signalled++; 00366 } 00367 } 00368 00369 return Signalled ? 1 : 0; 00370 } 00371 00372 VOID PollReeval( PAFD_DEVICE_EXTENSION DeviceExt, PFILE_OBJECT FileObject ) { 00373 PAFD_ACTIVE_POLL Poll = NULL; 00374 PLIST_ENTRY ThePollEnt = NULL; 00375 PAFD_FCB FCB; 00376 KIRQL OldIrql; 00377 PAFD_POLL_INFO PollReq; 00378 00379 AFD_DbgPrint(MID_TRACE,("Called: DeviceExt %x FileObject %x\n", 00380 DeviceExt, FileObject)); 00381 00382 KeAcquireSpinLock( &DeviceExt->Lock, &OldIrql ); 00383 00384 /* Take care of any event select signalling */ 00385 FCB = (PAFD_FCB)FileObject->FsContext; 00386 00387 if( !FCB ) { 00388 KeReleaseSpinLock( &DeviceExt->Lock, OldIrql ); 00389 return; 00390 } 00391 00392 /* Now signal normal select irps */ 00393 ThePollEnt = DeviceExt->Polls.Flink; 00394 00395 while( ThePollEnt != &DeviceExt->Polls ) { 00396 Poll = CONTAINING_RECORD( ThePollEnt, AFD_ACTIVE_POLL, ListEntry ); 00397 PollReq = Poll->Irp->AssociatedIrp.SystemBuffer; 00398 AFD_DbgPrint(MID_TRACE,("Checking poll %x\n", Poll)); 00399 00400 if( UpdatePollWithFCB( Poll, FileObject ) ) { 00401 ThePollEnt = ThePollEnt->Flink; 00402 AFD_DbgPrint(MID_TRACE,("Signalling socket\n")); 00403 SignalSocket( Poll, NULL, PollReq, STATUS_SUCCESS ); 00404 } else 00405 ThePollEnt = ThePollEnt->Flink; 00406 } 00407 00408 KeReleaseSpinLock( &DeviceExt->Lock, OldIrql ); 00409 00410 if((FCB->EventSelect) && 00411 (FCB->PollState & (FCB->EventSelectTriggers & ~FCB->EventSelectDisabled))) 00412 { 00413 AFD_DbgPrint(MID_TRACE,("Setting event %x\n", FCB->EventSelect)); 00414 00415 /* Disable the events that triggered the select until the reenabling function is called */ 00416 FCB->EventSelectDisabled |= (FCB->PollState & (FCB->EventSelectTriggers & ~FCB->EventSelectDisabled)); 00417 00418 /* Set the application's event */ 00419 KeSetEvent( FCB->EventSelect, IO_NETWORK_INCREMENT, FALSE ); 00420 } 00421 00422 AFD_DbgPrint(MID_TRACE,("Leaving\n")); 00423 } Generated on Sun May 27 2012 04:18:48 for ReactOS by
1.7.6.1
|