2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS kernel
4 * FILE: drivers/net/afd/afd/lock.c
5 * PURPOSE: Ancillary functions driver
6 * PROGRAMMER: Art Yerkes (ayerkes@speakeasy.net)
13 PVOID
GetLockedData(PIRP Irp
, PIO_STACK_LOCATION IrpSp
)
15 ASSERT(Irp
->MdlAddress
);
16 ASSERT(Irp
->Tail
.Overlay
.DriverContext
[0]);
18 UNREFERENCED_PARAMETER(IrpSp
);
20 return Irp
->Tail
.Overlay
.DriverContext
[0];
23 /* Lock a method_neither request so it'll be available from DISPATCH_LEVEL */
24 PVOID
LockRequest( PIRP Irp
,
25 PIO_STACK_LOCATION IrpSp
,
27 KPROCESSOR_MODE
*LockMode
) {
28 BOOLEAN LockFailed
= FALSE
;
30 ASSERT(!Irp
->MdlAddress
);
32 switch (IrpSp
->MajorFunction
)
34 case IRP_MJ_DEVICE_CONTROL
:
35 case IRP_MJ_INTERNAL_DEVICE_CONTROL
:
36 ASSERT(IrpSp
->Parameters
.DeviceIoControl
.Type3InputBuffer
);
37 ASSERT(IrpSp
->Parameters
.DeviceIoControl
.InputBufferLength
);
41 IoAllocateMdl( IrpSp
->Parameters
.DeviceIoControl
.Type3InputBuffer
,
42 IrpSp
->Parameters
.DeviceIoControl
.InputBufferLength
,
46 if( Irp
->MdlAddress
) {
48 MmProbeAndLockPages( Irp
->MdlAddress
, Irp
->RequestorMode
, IoModifyAccess
);
49 } _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
) {
54 AFD_DbgPrint(MIN_TRACE
,("Failed to lock pages\n"));
55 IoFreeMdl( Irp
->MdlAddress
);
56 Irp
->MdlAddress
= NULL
;
60 /* The mapped address goes in index 1 */
61 Irp
->Tail
.Overlay
.DriverContext
[1] = MmGetSystemAddressForMdlSafe(Irp
->MdlAddress
, NormalPagePriority
);
62 if (!Irp
->Tail
.Overlay
.DriverContext
[1])
64 AFD_DbgPrint(MIN_TRACE
,("Failed to get mapped address\n"));
65 MmUnlockPages(Irp
->MdlAddress
);
66 IoFreeMdl( Irp
->MdlAddress
);
67 Irp
->MdlAddress
= NULL
;
71 /* The allocated address goes in index 0 */
72 Irp
->Tail
.Overlay
.DriverContext
[0] = ExAllocatePoolWithTag(NonPagedPool
,
73 MmGetMdlByteCount(Irp
->MdlAddress
),
76 if (!Irp
->Tail
.Overlay
.DriverContext
[0])
78 AFD_DbgPrint(MIN_TRACE
,("Failed to allocate memory\n"));
79 MmUnlockPages(Irp
->MdlAddress
);
80 IoFreeMdl( Irp
->MdlAddress
);
81 Irp
->MdlAddress
= NULL
;
85 RtlCopyMemory(Irp
->Tail
.Overlay
.DriverContext
[0],
86 Irp
->Tail
.Overlay
.DriverContext
[1],
87 MmGetMdlByteCount(Irp
->MdlAddress
));
89 /* If we don't want a copy back, we zero the mapped address pointer */
92 Irp
->Tail
.Overlay
.DriverContext
[1] = NULL
;
95 /* We're using a user-mode buffer directly */
106 ASSERT(Irp
->UserBuffer
);
109 IoAllocateMdl(Irp
->UserBuffer
,
110 (IrpSp
->MajorFunction
== IRP_MJ_READ
) ?
111 IrpSp
->Parameters
.Read
.Length
: IrpSp
->Parameters
.Write
.Length
,
115 if( Irp
->MdlAddress
) {
116 PAFD_RECV_INFO AfdInfo
;
119 MmProbeAndLockPages( Irp
->MdlAddress
, Irp
->RequestorMode
, IoModifyAccess
);
120 } _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
) {
125 AFD_DbgPrint(MIN_TRACE
,("Failed to lock pages\n"));
126 IoFreeMdl( Irp
->MdlAddress
);
127 Irp
->MdlAddress
= NULL
;
131 /* We need to create the info struct that AFD expects for all send/recv requests */
132 AfdInfo
= ExAllocatePoolWithTag(NonPagedPool
,
133 sizeof(AFD_RECV_INFO
) + sizeof(AFD_WSABUF
),
134 TAG_AFD_DATA_BUFFER
);
138 AFD_DbgPrint(MIN_TRACE
,("Failed to allocate memory\n"));
139 MmUnlockPages(Irp
->MdlAddress
);
140 IoFreeMdl( Irp
->MdlAddress
);
141 Irp
->MdlAddress
= NULL
;
145 /* We'll append the buffer array to this struct */
146 AfdInfo
->BufferArray
= (PAFD_WSABUF
)(AfdInfo
+ 1);
147 AfdInfo
->BufferCount
= 1;
149 /* Setup the default flags values */
150 AfdInfo
->AfdFlags
= 0;
151 AfdInfo
->TdiFlags
= 0;
153 /* Now build the buffer array */
154 AfdInfo
->BufferArray
[0].buf
= MmGetSystemAddressForMdl(Irp
->MdlAddress
);
155 AfdInfo
->BufferArray
[0].len
= MmGetMdlByteCount(Irp
->MdlAddress
);
157 /* Store the struct where AFD expects */
158 Irp
->Tail
.Overlay
.DriverContext
[0] = AfdInfo
;
160 /* Don't copy anything out */
161 Irp
->Tail
.Overlay
.DriverContext
[1] = NULL
;
163 /* We're using a placeholder buffer that we allocated */
164 if (LockMode
!= NULL
)
166 *LockMode
= KernelMode
;
177 return GetLockedData(Irp
, IrpSp
);
180 VOID
UnlockRequest( PIRP Irp
, PIO_STACK_LOCATION IrpSp
)
182 ASSERT(Irp
->MdlAddress
);
183 ASSERT(Irp
->Tail
.Overlay
.DriverContext
[0]);
185 UNREFERENCED_PARAMETER(IrpSp
);
187 /* Check if we need to copy stuff back */
188 if (Irp
->Tail
.Overlay
.DriverContext
[1] != NULL
)
190 RtlCopyMemory(Irp
->Tail
.Overlay
.DriverContext
[1],
191 Irp
->Tail
.Overlay
.DriverContext
[0],
192 MmGetMdlByteCount(Irp
->MdlAddress
));
195 ExFreePoolWithTag(Irp
->Tail
.Overlay
.DriverContext
[0], TAG_AFD_DATA_BUFFER
);
196 MmUnlockPages( Irp
->MdlAddress
);
197 IoFreeMdl( Irp
->MdlAddress
);
198 Irp
->MdlAddress
= NULL
;
201 /* Note: We add an extra buffer if LockAddress is true. This allows us to
202 * treat the address buffer as an ordinary client buffer. It's only used
205 PAFD_WSABUF
LockBuffers( PAFD_WSABUF Buf
, UINT Count
,
206 PVOID AddressBuf
, PINT AddressLen
,
207 BOOLEAN Write
, BOOLEAN LockAddress
,
208 KPROCESSOR_MODE LockMode
) {
210 /* Copy the buffer array so we don't lose it */
211 UINT Lock
= LockAddress
? 2 : 0;
212 UINT Size
= (sizeof(AFD_WSABUF
) + sizeof(AFD_MAPBUF
)) * (Count
+ Lock
);
213 PAFD_WSABUF NewBuf
= ExAllocatePoolWithTag(PagedPool
, Size
, TAG_AFD_WSA_BUFFER
);
214 BOOLEAN LockFailed
= FALSE
;
217 AFD_DbgPrint(MID_TRACE
,("Called(%p)\n", NewBuf
));
220 RtlZeroMemory(NewBuf
, Size
);
222 MapBuf
= (PAFD_MAPBUF
)(NewBuf
+ Count
+ Lock
);
225 RtlCopyMemory( NewBuf
, Buf
, sizeof(AFD_WSABUF
) * Count
);
227 if (AddressBuf
&& AddressLen
) {
228 NewBuf
[Count
].buf
= AddressBuf
;
229 NewBuf
[Count
].len
= *AddressLen
;
230 NewBuf
[Count
+ 1].buf
= (PVOID
)AddressLen
;
231 NewBuf
[Count
+ 1].len
= sizeof(*AddressLen
);
235 } _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
) {
236 AFD_DbgPrint(MIN_TRACE
,("Access violation copying buffer info "
237 "from userland (%p %p)\n",
239 ExFreePoolWithTag(NewBuf
, TAG_AFD_WSA_BUFFER
);
240 _SEH2_YIELD(return NULL
);
243 for( i
= 0; i
< Count
; i
++ ) {
244 AFD_DbgPrint(MID_TRACE
,("Locking buffer %u (%p:%u)\n",
245 i
, NewBuf
[i
].buf
, NewBuf
[i
].len
));
247 if( NewBuf
[i
].buf
&& NewBuf
[i
].len
) {
248 MapBuf
[i
].Mdl
= IoAllocateMdl( NewBuf
[i
].buf
,
254 MapBuf
[i
].Mdl
= NULL
;
258 AFD_DbgPrint(MID_TRACE
,("NewMdl @ %p\n", MapBuf
[i
].Mdl
));
260 if( MapBuf
[i
].Mdl
) {
261 AFD_DbgPrint(MID_TRACE
,("Probe and lock pages\n"));
263 MmProbeAndLockPages( MapBuf
[i
].Mdl
, LockMode
,
264 Write
? IoModifyAccess
: IoReadAccess
);
265 } _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
) {
268 AFD_DbgPrint(MID_TRACE
,("MmProbeAndLock finished\n"));
271 AFD_DbgPrint(MIN_TRACE
,("Failed to lock pages\n"));
272 IoFreeMdl( MapBuf
[i
].Mdl
);
273 MapBuf
[i
].Mdl
= NULL
;
274 ExFreePoolWithTag(NewBuf
, TAG_AFD_WSA_BUFFER
);
278 ExFreePoolWithTag(NewBuf
, TAG_AFD_WSA_BUFFER
);
284 AFD_DbgPrint(MID_TRACE
,("Leaving %p\n", NewBuf
));
289 VOID
UnlockBuffers( PAFD_WSABUF Buf
, UINT Count
, BOOL Address
) {
290 UINT Lock
= Address
? 2 : 0;
291 PAFD_MAPBUF Map
= (PAFD_MAPBUF
)(Buf
+ Count
+ Lock
);
296 for( i
= 0; i
< Count
+ Lock
; i
++ ) {
298 MmUnlockPages( Map
[i
].Mdl
);
299 IoFreeMdl( Map
[i
].Mdl
);
304 ExFreePoolWithTag(Buf
, TAG_AFD_WSA_BUFFER
);
308 /* Produce a kernel-land handle array with handles replaced by object
309 * pointers. This will allow the system to do proper alerting */
310 PAFD_HANDLE
LockHandles( PAFD_HANDLE HandleArray
, UINT HandleCount
) {
312 NTSTATUS Status
= STATUS_SUCCESS
;
314 PAFD_HANDLE FileObjects
= ExAllocatePoolWithTag(NonPagedPool
,
315 HandleCount
* sizeof(AFD_HANDLE
),
316 TAG_AFD_POLL_HANDLE
);
318 for( i
= 0; FileObjects
&& i
< HandleCount
; i
++ ) {
319 FileObjects
[i
].Status
= 0;
320 FileObjects
[i
].Events
= HandleArray
[i
].Events
;
321 FileObjects
[i
].Handle
= 0;
322 if( !HandleArray
[i
].Handle
) continue;
323 if( NT_SUCCESS(Status
) ) {
324 Status
= ObReferenceObjectByHandle
325 ( (PVOID
)HandleArray
[i
].Handle
,
329 (PVOID
*)&FileObjects
[i
].Handle
,
333 if( !NT_SUCCESS(Status
) )
335 AFD_DbgPrint(MIN_TRACE
,("Failed to reference handles (0x%x)\n", Status
));
336 FileObjects
[i
].Handle
= 0;
340 if( !NT_SUCCESS(Status
) ) {
341 UnlockHandles( FileObjects
, HandleCount
);
348 VOID
UnlockHandles( PAFD_HANDLE HandleArray
, UINT HandleCount
) {
351 for( i
= 0; i
< HandleCount
; i
++ ) {
352 if( HandleArray
[i
].Handle
)
353 ObDereferenceObject( (PVOID
)HandleArray
[i
].Handle
);
356 ExFreePoolWithTag(HandleArray
, TAG_AFD_POLL_HANDLE
);
360 BOOLEAN
SocketAcquireStateLock( PAFD_FCB FCB
) {
361 if( !FCB
) return FALSE
;
363 return !KeWaitForMutexObject(&FCB
->Mutex
,
370 VOID
SocketStateUnlock( PAFD_FCB FCB
) {
371 KeReleaseMutex(&FCB
->Mutex
, FALSE
);
374 NTSTATUS NTAPI UnlockAndMaybeComplete
375 ( PAFD_FCB FCB
, NTSTATUS Status
, PIRP Irp
,
377 Irp
->IoStatus
.Status
= Status
;
378 Irp
->IoStatus
.Information
= Information
;
379 if ( Irp
->MdlAddress
) UnlockRequest( Irp
, IoGetCurrentIrpStackLocation( Irp
) );
380 (void)IoSetCancelRoutine(Irp
, NULL
);
381 SocketStateUnlock( FCB
);
382 IoCompleteRequest( Irp
, IO_NETWORK_INCREMENT
);
387 NTSTATUS
LostSocket( PIRP Irp
) {
388 NTSTATUS Status
= STATUS_FILE_CLOSED
;
389 AFD_DbgPrint(MIN_TRACE
,("Called.\n"));
390 Irp
->IoStatus
.Information
= 0;
391 Irp
->IoStatus
.Status
= Status
;
392 if ( Irp
->MdlAddress
) UnlockRequest( Irp
, IoGetCurrentIrpStackLocation( Irp
) );
393 IoCompleteRequest( Irp
, IO_NO_INCREMENT
);
397 NTSTATUS
QueueUserModeIrp(PAFD_FCB FCB
, PIRP Irp
, UINT Function
)
401 /* Add the IRP to the queue in all cases (so AfdCancelHandler will work properly) */
402 InsertTailList( &FCB
->PendingIrpList
[Function
],
403 &Irp
->Tail
.Overlay
.ListEntry
);
405 /* Acquire the cancel spin lock and check the cancel bit */
406 IoAcquireCancelSpinLock(&Irp
->CancelIrql
);
409 /* We are not cancelled; we're good to go so
410 * set the cancel routine, release the cancel spin lock,
411 * mark the IRP as pending, and
412 * return STATUS_PENDING to the caller
414 (void)IoSetCancelRoutine(Irp
, AfdCancelHandler
);
415 IoReleaseCancelSpinLock(Irp
->CancelIrql
);
416 IoMarkIrpPending(Irp
);
417 Status
= STATUS_PENDING
;
421 /* We were already cancelled before we were able to register our cancel routine
422 * so we are to call the cancel routine ourselves right here to cancel the IRP
423 * (which handles all the stuff we do above) and return STATUS_CANCELLED to the caller
425 AfdCancelHandler(IoGetCurrentIrpStackLocation(Irp
)->DeviceObject
,
427 Status
= STATUS_CANCELLED
;
433 NTSTATUS
LeaveIrpUntilLater( PAFD_FCB FCB
, PIRP Irp
, UINT Function
) {
436 Status
= QueueUserModeIrp(FCB
, Irp
, Function
);
438 SocketStateUnlock( FCB
);