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)
11 #include "tdi_proto.h"
14 #include "pseh/pseh2.h"
16 /* Lock a method_neither request so it'll be available from DISPATCH_LEVEL */
17 PVOID
LockRequest( PIRP Irp
, PIO_STACK_LOCATION IrpSp
) {
18 BOOLEAN LockFailed
= FALSE
;
20 ASSERT(IrpSp
->Parameters
.DeviceIoControl
.Type3InputBuffer
);
21 ASSERT(IrpSp
->Parameters
.DeviceIoControl
.InputBufferLength
);
22 ASSERT(!Irp
->MdlAddress
);
25 IoAllocateMdl( IrpSp
->Parameters
.DeviceIoControl
.Type3InputBuffer
,
26 IrpSp
->Parameters
.DeviceIoControl
.InputBufferLength
,
30 if( Irp
->MdlAddress
) {
32 MmProbeAndLockPages( Irp
->MdlAddress
, Irp
->RequestorMode
, IoModifyAccess
);
33 } _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
) {
38 IoFreeMdl( Irp
->MdlAddress
);
39 Irp
->MdlAddress
= NULL
;
43 IrpSp
->Parameters
.DeviceIoControl
.Type3InputBuffer
=
44 MmGetSystemAddressForMdlSafe( Irp
->MdlAddress
, NormalPagePriority
);
46 if( !IrpSp
->Parameters
.DeviceIoControl
.Type3InputBuffer
) {
47 MmUnlockPages( Irp
->MdlAddress
);
48 IoFreeMdl( Irp
->MdlAddress
);
49 Irp
->MdlAddress
= NULL
;
53 return IrpSp
->Parameters
.DeviceIoControl
.Type3InputBuffer
;
57 VOID
UnlockRequest( PIRP Irp
, PIO_STACK_LOCATION IrpSp
)
59 MmUnlockPages( Irp
->MdlAddress
);
60 IoFreeMdl( Irp
->MdlAddress
);
61 Irp
->MdlAddress
= NULL
;
64 /* Note: We add an extra buffer if LockAddress is true. This allows us to
65 * treat the address buffer as an ordinary client buffer. It's only used
68 PAFD_WSABUF
LockBuffers( PAFD_WSABUF Buf
, UINT Count
,
69 PVOID AddressBuf
, PINT AddressLen
,
70 BOOLEAN Write
, BOOLEAN LockAddress
) {
72 /* Copy the buffer array so we don't lose it */
73 UINT Lock
= LockAddress
? 2 : 0;
74 UINT Size
= sizeof(AFD_WSABUF
) * (Count
+ Lock
);
75 PAFD_WSABUF NewBuf
= ExAllocatePool( PagedPool
, Size
* 2 );
76 BOOLEAN LockFailed
= FALSE
;
79 AFD_DbgPrint(MID_TRACE
,("Called(%08x)\n", NewBuf
));
82 RtlZeroMemory(NewBuf
, Size
* 2);
84 MapBuf
= (PAFD_MAPBUF
)(NewBuf
+ Count
+ Lock
);
87 RtlCopyMemory( NewBuf
, Buf
, sizeof(AFD_WSABUF
) * Count
);
89 if (AddressBuf
&& AddressLen
) {
90 NewBuf
[Count
].buf
= AddressBuf
;
91 NewBuf
[Count
].len
= *AddressLen
;
92 NewBuf
[Count
+ 1].buf
= (PVOID
)AddressLen
;
93 NewBuf
[Count
+ 1].len
= sizeof(*AddressLen
);
97 } _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
) {
98 AFD_DbgPrint(MIN_TRACE
,("Access violation copying buffer info "
99 "from userland (%x %x)\n",
101 ExFreePool( NewBuf
);
102 _SEH2_YIELD(return NULL
);
105 for( i
= 0; i
< Count
; i
++ ) {
106 AFD_DbgPrint(MID_TRACE
,("Locking buffer %d (%x:%d)\n",
107 i
, NewBuf
[i
].buf
, NewBuf
[i
].len
));
109 if( NewBuf
[i
].buf
&& NewBuf
[i
].len
) {
110 MapBuf
[i
].Mdl
= IoAllocateMdl( NewBuf
[i
].buf
,
116 MapBuf
[i
].Mdl
= NULL
;
120 AFD_DbgPrint(MID_TRACE
,("NewMdl @ %x\n", MapBuf
[i
].Mdl
));
122 if( MapBuf
[i
].Mdl
) {
123 AFD_DbgPrint(MID_TRACE
,("Probe and lock pages\n"));
125 MmProbeAndLockPages( MapBuf
[i
].Mdl
, KernelMode
,
126 Write
? IoModifyAccess
: IoReadAccess
);
127 } _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
) {
130 AFD_DbgPrint(MID_TRACE
,("MmProbeAndLock finished\n"));
133 IoFreeMdl( MapBuf
[i
].Mdl
);
134 MapBuf
[i
].Mdl
= NULL
;
135 ExFreePool( NewBuf
);
139 ExFreePool( NewBuf
);
145 AFD_DbgPrint(MID_TRACE
,("Leaving %x\n", NewBuf
));
150 VOID
UnlockBuffers( PAFD_WSABUF Buf
, UINT Count
, BOOL Address
) {
151 UINT Lock
= Address
? 2 : 0;
152 PAFD_MAPBUF Map
= (PAFD_MAPBUF
)(Buf
+ Count
+ Lock
);
157 for( i
= 0; i
< Count
+ Lock
; i
++ ) {
159 MmUnlockPages( Map
[i
].Mdl
);
160 IoFreeMdl( Map
[i
].Mdl
);
169 /* Produce a kernel-land handle array with handles replaced by object
170 * pointers. This will allow the system to do proper alerting */
171 PAFD_HANDLE
LockHandles( PAFD_HANDLE HandleArray
, UINT HandleCount
) {
173 NTSTATUS Status
= STATUS_SUCCESS
;
175 PAFD_HANDLE FileObjects
= ExAllocatePool
176 ( NonPagedPool
, HandleCount
* sizeof(AFD_HANDLE
) );
178 for( i
= 0; FileObjects
&& i
< HandleCount
; i
++ ) {
179 FileObjects
[i
].Status
= 0;
180 FileObjects
[i
].Events
= HandleArray
[i
].Events
;
181 FileObjects
[i
].Handle
= 0;
182 if( !HandleArray
[i
].Handle
) continue;
183 if( NT_SUCCESS(Status
) ) {
184 Status
= ObReferenceObjectByHandle
185 ( (PVOID
)HandleArray
[i
].Handle
,
189 (PVOID
*)&FileObjects
[i
].Handle
,
193 if( !NT_SUCCESS(Status
) )
194 FileObjects
[i
].Handle
= 0;
197 if( !NT_SUCCESS(Status
) ) {
198 UnlockHandles( FileObjects
, HandleCount
);
205 VOID
UnlockHandles( PAFD_HANDLE HandleArray
, UINT HandleCount
) {
208 for( i
= 0; i
< HandleCount
; i
++ ) {
209 if( HandleArray
[i
].Handle
)
210 ObDereferenceObject( (PVOID
)HandleArray
[i
].Handle
);
213 ExFreePool( HandleArray
);
217 BOOLEAN
SocketAcquireStateLock( PAFD_FCB FCB
) {
218 if( !FCB
) return FALSE
;
220 return !KeWaitForMutexObject(&FCB
->Mutex
,
227 VOID
SocketStateUnlock( PAFD_FCB FCB
) {
228 KeReleaseMutex(&FCB
->Mutex
, FALSE
);
231 NTSTATUS NTAPI UnlockAndMaybeComplete
232 ( PAFD_FCB FCB
, NTSTATUS Status
, PIRP Irp
,
234 Irp
->IoStatus
.Status
= Status
;
235 Irp
->IoStatus
.Information
= Information
;
236 if ( Irp
->MdlAddress
) UnlockRequest( Irp
, IoGetCurrentIrpStackLocation( Irp
) );
237 (void)IoSetCancelRoutine(Irp
, NULL
);
238 SocketStateUnlock( FCB
);
239 IoCompleteRequest( Irp
, IO_NETWORK_INCREMENT
);
244 NTSTATUS
LostSocket( PIRP Irp
) {
245 NTSTATUS Status
= STATUS_FILE_CLOSED
;
246 AFD_DbgPrint(MIN_TRACE
,("Called.\n"));
247 Irp
->IoStatus
.Information
= 0;
248 Irp
->IoStatus
.Status
= Status
;
249 if ( Irp
->MdlAddress
) UnlockRequest( Irp
, IoGetCurrentIrpStackLocation( Irp
) );
250 IoCompleteRequest( Irp
, IO_NO_INCREMENT
);
254 NTSTATUS
LeaveIrpUntilLater( PAFD_FCB FCB
, PIRP Irp
, UINT Function
) {
255 InsertTailList( &FCB
->PendingIrpList
[Function
],
256 &Irp
->Tail
.Overlay
.ListEntry
);
257 IoMarkIrpPending(Irp
);
258 (void)IoSetCancelRoutine(Irp
, AfdCancelHandler
);
259 SocketStateUnlock( FCB
);
260 return STATUS_PENDING
;