Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygenlock.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
1.7.6.1
|