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

lock.c
Go to the documentation of this file.
00001 /* $Id: lock.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/lock.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 PVOID GetLockedData(PIRP Irp, PIO_STACK_LOCATION IrpSp)
00013 {
00014     ASSERT(Irp->MdlAddress);
00015 
00016     return MmGetSystemAddressForMdlSafe(Irp->MdlAddress, NormalPagePriority);
00017 }
00018 
00019 /* Lock a method_neither request so it'll be available from DISPATCH_LEVEL */
00020 PVOID LockRequest( PIRP Irp, PIO_STACK_LOCATION IrpSp ) {
00021     BOOLEAN LockFailed = FALSE;
00022 
00023     ASSERT(!Irp->MdlAddress);
00024 
00025     switch (IrpSp->MajorFunction)
00026     {
00027         case IRP_MJ_DEVICE_CONTROL:
00028         case IRP_MJ_INTERNAL_DEVICE_CONTROL:
00029             ASSERT(IrpSp->Parameters.DeviceIoControl.Type3InputBuffer);
00030             ASSERT(IrpSp->Parameters.DeviceIoControl.InputBufferLength);
00031 
00032 
00033             Irp->MdlAddress =
00034             IoAllocateMdl( IrpSp->Parameters.DeviceIoControl.Type3InputBuffer,
00035                           IrpSp->Parameters.DeviceIoControl.InputBufferLength,
00036                           FALSE,
00037                           FALSE,
00038                           NULL );
00039             if( Irp->MdlAddress ) {
00040                 _SEH2_TRY {
00041                     MmProbeAndLockPages( Irp->MdlAddress, Irp->RequestorMode, IoModifyAccess );
00042                 } _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) {
00043                     LockFailed = TRUE;
00044                 } _SEH2_END;
00045 
00046                 if( LockFailed ) {
00047                     AFD_DbgPrint(MIN_TRACE,("Failed to lock pages\n"));
00048                     IoFreeMdl( Irp->MdlAddress );
00049                     Irp->MdlAddress = NULL;
00050                     return NULL;
00051                 }
00052             } else return NULL;
00053             break;
00054 
00055         case IRP_MJ_READ:
00056         case IRP_MJ_WRITE:
00057             ASSERT(Irp->UserBuffer);
00058 
00059             Irp->MdlAddress =
00060             IoAllocateMdl(Irp->UserBuffer,
00061                           (IrpSp->MajorFunction == IRP_MJ_READ) ?
00062                                 IrpSp->Parameters.Read.Length : IrpSp->Parameters.Write.Length,
00063                           FALSE,
00064                           FALSE,
00065                           NULL );
00066             if( Irp->MdlAddress ) {
00067                 _SEH2_TRY {
00068                     MmProbeAndLockPages( Irp->MdlAddress, Irp->RequestorMode, IoModifyAccess );
00069                 } _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) {
00070                     LockFailed = TRUE;
00071                 } _SEH2_END;
00072 
00073                 if( LockFailed ) {
00074                     AFD_DbgPrint(MIN_TRACE,("Failed to lock pages\n"));
00075                     IoFreeMdl( Irp->MdlAddress );
00076                     Irp->MdlAddress = NULL;
00077                     return NULL;
00078                 }
00079             } else return NULL;
00080             break;
00081 
00082         default:
00083             ASSERT(FALSE);
00084             return NULL;
00085     }
00086 
00087     return GetLockedData(Irp, IrpSp);
00088 }
00089 
00090 VOID UnlockRequest( PIRP Irp, PIO_STACK_LOCATION IrpSp )
00091 {
00092     ASSERT(Irp->MdlAddress);
00093     MmUnlockPages( Irp->MdlAddress );
00094     IoFreeMdl( Irp->MdlAddress );
00095     Irp->MdlAddress = NULL;
00096 }
00097 
00098 /* Note: We add an extra buffer if LockAddress is true.  This allows us to
00099  * treat the address buffer as an ordinary client buffer.  It's only used
00100  * for datagrams. */
00101 
00102 PAFD_WSABUF LockBuffers( PAFD_WSABUF Buf, UINT Count,
00103                          PVOID AddressBuf, PINT AddressLen,
00104                          BOOLEAN Write, BOOLEAN LockAddress ) {
00105     UINT i;
00106     /* Copy the buffer array so we don't lose it */
00107     UINT Lock = LockAddress ? 2 : 0;
00108     UINT Size = sizeof(AFD_WSABUF) * (Count + Lock);
00109     PAFD_WSABUF NewBuf = ExAllocatePool( PagedPool, Size * 2 );
00110     BOOLEAN LockFailed = FALSE;
00111     PAFD_MAPBUF MapBuf;
00112 
00113     AFD_DbgPrint(MID_TRACE,("Called(%08x)\n", NewBuf));
00114 
00115     if( NewBuf ) {
00116         RtlZeroMemory(NewBuf, Size * 2);
00117 
00118         MapBuf = (PAFD_MAPBUF)(NewBuf + Count + Lock);
00119 
00120         _SEH2_TRY {
00121             RtlCopyMemory( NewBuf, Buf, sizeof(AFD_WSABUF) * Count );
00122             if( LockAddress ) {
00123                 if (AddressBuf && AddressLen) {
00124                     NewBuf[Count].buf = AddressBuf;
00125                     NewBuf[Count].len = *AddressLen;
00126                     NewBuf[Count + 1].buf = (PVOID)AddressLen;
00127                     NewBuf[Count + 1].len = sizeof(*AddressLen);
00128                 }
00129                 Count += 2;
00130             }
00131         } _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) {
00132             AFD_DbgPrint(MIN_TRACE,("Access violation copying buffer info "
00133                                     "from userland (%x %x)\n",
00134                                     Buf, AddressLen));
00135             ExFreePool( NewBuf );
00136             _SEH2_YIELD(return NULL);
00137         } _SEH2_END;
00138 
00139         for( i = 0; i < Count; i++ ) {
00140             AFD_DbgPrint(MID_TRACE,("Locking buffer %d (%x:%d)\n",
00141                                     i, NewBuf[i].buf, NewBuf[i].len));
00142 
00143             if( NewBuf[i].buf && NewBuf[i].len ) {
00144                 MapBuf[i].Mdl = IoAllocateMdl( NewBuf[i].buf,
00145                                                NewBuf[i].len,
00146                                                FALSE,
00147                                                FALSE,
00148                                                NULL );
00149             } else {
00150                 MapBuf[i].Mdl = NULL;
00151                 continue;
00152             }
00153 
00154             AFD_DbgPrint(MID_TRACE,("NewMdl @ %x\n", MapBuf[i].Mdl));
00155 
00156             if( MapBuf[i].Mdl ) {
00157                 AFD_DbgPrint(MID_TRACE,("Probe and lock pages\n"));
00158                 _SEH2_TRY {
00159                     MmProbeAndLockPages( MapBuf[i].Mdl, UserMode,
00160                                          Write ? IoModifyAccess : IoReadAccess );
00161                 } _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) {
00162                     LockFailed = TRUE;
00163                 } _SEH2_END;
00164                 AFD_DbgPrint(MID_TRACE,("MmProbeAndLock finished\n"));
00165 
00166                 if( LockFailed ) {
00167             AFD_DbgPrint(MIN_TRACE,("Failed to lock pages\n"));
00168                     IoFreeMdl( MapBuf[i].Mdl );
00169                     MapBuf[i].Mdl = NULL;
00170                     ExFreePool( NewBuf );
00171                     return NULL;
00172                 }
00173             } else {
00174                 ExFreePool( NewBuf );
00175                 return NULL;
00176             }
00177         }
00178     }
00179 
00180     AFD_DbgPrint(MID_TRACE,("Leaving %x\n", NewBuf));
00181 
00182     return NewBuf;
00183 }
00184 
00185 VOID UnlockBuffers( PAFD_WSABUF Buf, UINT Count, BOOL Address ) {
00186     UINT Lock = Address ? 2 : 0;
00187     PAFD_MAPBUF Map = (PAFD_MAPBUF)(Buf + Count + Lock);
00188     UINT i;
00189 
00190     if( !Buf ) return;
00191 
00192     for( i = 0; i < Count + Lock; i++ ) {
00193         if( Map[i].Mdl ) {
00194             MmUnlockPages( Map[i].Mdl );
00195             IoFreeMdl( Map[i].Mdl );
00196             Map[i].Mdl = NULL;
00197         }
00198     }
00199 
00200     ExFreePool( Buf );
00201     Buf = NULL;
00202 }
00203 
00204 /* Produce a kernel-land handle array with handles replaced by object
00205  * pointers.  This will allow the system to do proper alerting */
00206 PAFD_HANDLE LockHandles( PAFD_HANDLE HandleArray, UINT HandleCount ) {
00207     UINT i;
00208     NTSTATUS Status = STATUS_SUCCESS;
00209 
00210     PAFD_HANDLE FileObjects = ExAllocatePool
00211         ( NonPagedPool, HandleCount * sizeof(AFD_HANDLE) );
00212 
00213     for( i = 0; FileObjects && i < HandleCount; i++ ) {
00214         FileObjects[i].Status = 0;
00215         FileObjects[i].Events = HandleArray[i].Events;
00216         FileObjects[i].Handle = 0;
00217         if( !HandleArray[i].Handle ) continue;
00218         if( NT_SUCCESS(Status) ) {
00219                 Status = ObReferenceObjectByHandle
00220                     ( (PVOID)HandleArray[i].Handle,
00221                       FILE_ALL_ACCESS,
00222                       NULL,
00223                        KernelMode,
00224                        (PVOID*)&FileObjects[i].Handle,
00225                        NULL );
00226         }
00227 
00228         if( !NT_SUCCESS(Status) )
00229         {
00230             AFD_DbgPrint(MIN_TRACE,("Failed to reference handles (0x%x)\n", Status));
00231             FileObjects[i].Handle = 0;
00232         }
00233     }
00234 
00235     if( !NT_SUCCESS(Status) ) {
00236         UnlockHandles( FileObjects, HandleCount );
00237         return NULL;
00238     }
00239 
00240     return FileObjects;
00241 }
00242 
00243 VOID UnlockHandles( PAFD_HANDLE HandleArray, UINT HandleCount ) {
00244     UINT i;
00245 
00246     for( i = 0; i < HandleCount; i++ ) {
00247         if( HandleArray[i].Handle )
00248             ObDereferenceObject( (PVOID)HandleArray[i].Handle );
00249     }
00250 
00251     ExFreePool( HandleArray );
00252     HandleArray = NULL;
00253 }
00254 
00255 BOOLEAN SocketAcquireStateLock( PAFD_FCB FCB ) {
00256     if( !FCB ) return FALSE;
00257 
00258     return !KeWaitForMutexObject(&FCB->Mutex,
00259                                  Executive,
00260                                  KernelMode,
00261                                  FALSE,
00262                                  NULL);
00263 }
00264 
00265 VOID SocketStateUnlock( PAFD_FCB FCB ) {
00266     KeReleaseMutex(&FCB->Mutex, FALSE);
00267 }
00268 
00269 NTSTATUS NTAPI UnlockAndMaybeComplete
00270 ( PAFD_FCB FCB, NTSTATUS Status, PIRP Irp,
00271   UINT Information ) {
00272     Irp->IoStatus.Status = Status;
00273     Irp->IoStatus.Information = Information;
00274     if ( Irp->MdlAddress ) UnlockRequest( Irp, IoGetCurrentIrpStackLocation( Irp ) );
00275     (void)IoSetCancelRoutine(Irp, NULL);
00276     SocketStateUnlock( FCB );
00277     IoCompleteRequest( Irp, IO_NETWORK_INCREMENT );
00278     return Status;
00279 }
00280 
00281 
00282 NTSTATUS LostSocket( PIRP Irp ) {
00283     NTSTATUS Status = STATUS_FILE_CLOSED;
00284     AFD_DbgPrint(MIN_TRACE,("Called.\n"));
00285     Irp->IoStatus.Information = 0;
00286     Irp->IoStatus.Status = Status;
00287     if ( Irp->MdlAddress ) UnlockRequest( Irp, IoGetCurrentIrpStackLocation( Irp ) );
00288     IoCompleteRequest( Irp, IO_NO_INCREMENT );
00289     return Status;
00290 }
00291 
00292 NTSTATUS QueueUserModeIrp(PAFD_FCB FCB, PIRP Irp, UINT Function)
00293 {
00294     NTSTATUS Status;
00295 
00296     /* Add the IRP to the queue in all cases (so AfdCancelHandler will work properly) */
00297     InsertTailList( &FCB->PendingIrpList[Function],
00298                    &Irp->Tail.Overlay.ListEntry );
00299 
00300     /* Acquire the cancel spin lock and check the cancel bit */
00301     IoAcquireCancelSpinLock(&Irp->CancelIrql);
00302     if (!Irp->Cancel)
00303     {
00304         /* We are not cancelled; we're good to go so
00305          * set the cancel routine, release the cancel spin lock,
00306          * mark the IRP as pending, and
00307          * return STATUS_PENDING to the caller
00308          */
00309         (void)IoSetCancelRoutine(Irp, AfdCancelHandler);
00310         IoReleaseCancelSpinLock(Irp->CancelIrql);
00311         IoMarkIrpPending(Irp);
00312         Status = STATUS_PENDING;
00313     }
00314     else
00315     {
00316         /* We were already cancelled before we were able to register our cancel routine
00317          * so we are to call the cancel routine ourselves right here to cancel the IRP
00318          * (which handles all the stuff we do above) and return STATUS_CANCELLED to the caller
00319          */
00320         AfdCancelHandler(IoGetCurrentIrpStackLocation(Irp)->DeviceObject,
00321                          Irp);
00322         Status = STATUS_CANCELLED;
00323     }
00324 
00325     return Status;
00326 }
00327 
00328 NTSTATUS LeaveIrpUntilLater( PAFD_FCB FCB, PIRP Irp, UINT Function ) {
00329     NTSTATUS Status;
00330 
00331     Status = QueueUserModeIrp(FCB, Irp, Function);
00332 
00333     SocketStateUnlock( FCB );
00334 
00335     return Status;
00336 }

Generated on Fri May 25 2012 04:22:19 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.