ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

select.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 doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.