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/pseh.h"
16 /* Lock a method_neither request so it'll be available from DISPATCH_LEVEL */
17 PVOID
LockRequest( PIRP Irp
, PIO_STACK_LOCATION IrpSp
) {
19 IoAllocateMdl( IrpSp
->Parameters
.DeviceIoControl
.Type3InputBuffer
,
20 IrpSp
->Parameters
.DeviceIoControl
.InputBufferLength
,
24 if( Irp
->MdlAddress
) {
25 MmProbeAndLockPages( Irp
->MdlAddress
, KernelMode
, IoModifyAccess
);
26 IrpSp
->Parameters
.DeviceIoControl
.Type3InputBuffer
=
27 MmMapLockedPages( Irp
->MdlAddress
, KernelMode
);
28 return IrpSp
->Parameters
.DeviceIoControl
.Type3InputBuffer
;
32 VOID
UnlockRequest( PIRP Irp
, PIO_STACK_LOCATION IrpSp
) {
33 MmUnmapLockedPages( IrpSp
->Parameters
.DeviceIoControl
.Type3InputBuffer
,
35 MmUnlockPages( Irp
->MdlAddress
);
36 IoFreeMdl( Irp
->MdlAddress
);
37 Irp
->MdlAddress
= NULL
;
40 /* Note: We add an extra buffer if LockAddress is true. This allows us to
41 * treat the address buffer as an ordinary client buffer. It's only used
44 PAFD_WSABUF
LockBuffers( PAFD_WSABUF Buf
, UINT Count
,
45 PVOID AddressBuf
, PINT AddressLen
,
46 BOOLEAN Write
, BOOLEAN LockAddress
) {
48 /* Copy the buffer array so we don't lose it */
49 UINT Lock
= LockAddress
? 2 : 0;
50 UINT Size
= sizeof(AFD_WSABUF
) * (Count
+ Lock
);
51 PAFD_WSABUF NewBuf
= ExAllocatePool( PagedPool
, Size
* 2 );
54 AFD_DbgPrint(MID_TRACE
,("Called\n"));
57 PAFD_MAPBUF MapBuf
= (PAFD_MAPBUF
)(NewBuf
+ Count
+ Lock
);
60 RtlCopyMemory( NewBuf
, Buf
, sizeof(AFD_WSABUF
) * Count
);
62 NewBuf
[Count
].buf
= AddressBuf
;
63 NewBuf
[Count
].len
= *AddressLen
;
65 NewBuf
[Count
].buf
= (PVOID
)AddressLen
;
66 NewBuf
[Count
].len
= sizeof(*AddressLen
);
70 AFD_DbgPrint(MIN_TRACE
,("Access violation copying buffer info "
71 "from userland (%x %x)\n",
77 for( i
= 0; i
< Count
; i
++ ) {
78 AFD_DbgPrint(MID_TRACE
,("Locking buffer %d (%x:%d)\n",
79 i
, NewBuf
[i
].buf
, NewBuf
[i
].len
));
82 NewMdl
= IoAllocateMdl( NewBuf
[i
].buf
,
92 AFD_DbgPrint(MID_TRACE
,("NewMdl @ %x\n", NewMdl
));
94 MapBuf
[i
].Mdl
= NewMdl
;
97 AFD_DbgPrint(MID_TRACE
,("Probe and lock pages\n"));
98 MmProbeAndLockPages( MapBuf
[i
].Mdl
, KernelMode
,
99 Write
? IoModifyAccess
: IoReadAccess
);
100 AFD_DbgPrint(MID_TRACE
,("MmProbeAndLock finished\n"));
105 AFD_DbgPrint(MID_TRACE
,("Leaving %x\n", NewBuf
));
110 VOID
UnlockBuffers( PAFD_WSABUF Buf
, UINT Count
, BOOL Address
) {
111 UINT Lock
= Address
? 2 : 0;
112 PAFD_MAPBUF Map
= (PAFD_MAPBUF
)(Buf
+ Count
+ Lock
);
115 for( i
= 0; i
< Count
+ Lock
; i
++ ) {
117 MmUnlockPages( Map
[i
].Mdl
);
118 IoFreeMdl( Map
[i
].Mdl
);
125 /* Produce a kernel-land handle array with handles replaced by object
126 * pointers. This will allow the system to do proper alerting */
127 PAFD_HANDLE
LockHandles( PAFD_HANDLE HandleArray
, UINT HandleCount
) {
131 PAFD_HANDLE FileObjects
= ExAllocatePool
132 ( NonPagedPool
, HandleCount
* sizeof(AFD_HANDLE
) );
134 for( i
= 0; FileObjects
&& i
< HandleCount
; i
++ ) {
135 HandleArray
[i
].Status
= 0;
136 HandleArray
[i
].Events
= HandleArray
[i
].Events
;
137 FileObjects
[i
].Handle
= 0;
138 Status
= ObReferenceObjectByHandle
139 ( (PVOID
)HandleArray
[i
].Handle
,
143 (PVOID
*)&FileObjects
[i
].Handle
,
150 VOID
UnlockHandles( PAFD_HANDLE HandleArray
, UINT HandleCount
) {
153 for( i
= 0; i
< HandleCount
; i
++ ) {
154 if( HandleArray
[i
].Handle
)
155 ObDereferenceObject( (PVOID
)HandleArray
[i
].Handle
);
158 ExFreePool( HandleArray
);
161 /* Returns transitioned state or SOCKET_STATE_INVALID_TRANSITION */
162 UINT
SocketAcquireStateLock( PAFD_FCB FCB
) {
163 NTSTATUS Status
= STATUS_SUCCESS
;
164 PVOID CurrentThread
= KeGetCurrentThread();
166 ASSERT(KeGetCurrentIrql() == PASSIVE_LEVEL
);
168 AFD_DbgPrint(MAX_TRACE
,("Called on %x, attempting to lock\n", FCB
));
170 /* Wait for the previous user to unlock the FCB state. There might be
171 * multiple waiters waiting to change the state. We need to check each
172 * time we get the event whether somebody still has the state locked */
174 if( !FCB
) return FALSE
;
176 if( CurrentThread
== FCB
->CurrentThread
) {
178 AFD_DbgPrint(MID_TRACE
,
179 ("Same thread, lock count %d\n", FCB
->LockCount
));
182 AFD_DbgPrint(MID_TRACE
,
183 ("Thread %x opposes lock thread %x\n",
184 CurrentThread
, FCB
->CurrentThread
));
188 ExAcquireFastMutex( &FCB
->Mutex
);
190 while( FCB
->Locked
) {
192 (MID_TRACE
,("FCB %x is locked, waiting for notification\n",
194 ExReleaseFastMutex( &FCB
->Mutex
);
195 Status
= KeWaitForSingleObject( &FCB
->StateLockedEvent
,
200 ExAcquireFastMutex( &FCB
->Mutex
);
203 FCB
->CurrentThread
= CurrentThread
;
205 ExReleaseFastMutex( &FCB
->Mutex
);
207 AFD_DbgPrint(MAX_TRACE
,("Got lock (%d).\n", FCB
->LockCount
));
212 VOID
SocketStateUnlock( PAFD_FCB FCB
) {
214 PVOID CurrentThread
= KeGetCurrentThread();
216 ASSERT(FCB
->LockCount
> 0);
217 ASSERT(KeGetCurrentIrql() == PASSIVE_LEVEL
);
219 ExAcquireFastMutex( &FCB
->Mutex
);
222 if( !FCB
->LockCount
) {
223 FCB
->CurrentThread
= NULL
;
226 AFD_DbgPrint(MAX_TRACE
,("Unlocked.\n"));
227 KePulseEvent( &FCB
->StateLockedEvent
, IO_NETWORK_INCREMENT
, FALSE
);
229 AFD_DbgPrint(MAX_TRACE
,("New lock count: %d (Thr: %x)\n",
230 FCB
->LockCount
, CurrentThread
));
232 ExReleaseFastMutex( &FCB
->Mutex
);
235 NTSTATUS NTAPI UnlockAndMaybeComplete
236 ( PAFD_FCB FCB
, NTSTATUS Status
, PIRP Irp
,
238 PIO_COMPLETION_ROUTINE Completion
,
239 BOOL ShouldUnlock
) {
240 SocketStateUnlock( FCB
);
241 if( Status
== STATUS_PENDING
) {
242 IoMarkIrpPending( Irp
);
244 Irp
->IoStatus
.Status
= Status
;
245 Irp
->IoStatus
.Information
= Information
;
247 Completion( FCB
->DeviceExt
->DeviceObject
, Irp
, FCB
);
249 UnlockRequest( Irp
, IoGetCurrentIrpStackLocation( Irp
) );
250 IoCompleteRequest( Irp
, IO_NETWORK_INCREMENT
);
256 NTSTATUS
LostSocket( PIRP Irp
, BOOL ShouldUnlockIrp
) {
257 NTSTATUS Status
= STATUS_INVALID_PARAMETER
;
258 AFD_DbgPrint(MIN_TRACE
,("Called.\n"));
259 Irp
->IoStatus
.Information
= 0;
260 Irp
->IoStatus
.Status
= Status
;
261 if( ShouldUnlockIrp
)
262 UnlockRequest( Irp
, IoGetCurrentIrpStackLocation( Irp
) );
263 IoCompleteRequest( Irp
, IO_NO_INCREMENT
);
267 NTSTATUS
LeaveIrpUntilLater( PAFD_FCB FCB
, PIRP Irp
, UINT Function
) {
268 InsertTailList( &FCB
->PendingIrpList
[Function
],
269 &Irp
->Tail
.Overlay
.ListEntry
);
270 return UnlockAndMaybeComplete( FCB
, STATUS_PENDING
, Irp
, 0, NULL
, FALSE
);
273 VOID
SocketCalloutEnter( PAFD_FCB FCB
) {
275 FCB
->Critical
= TRUE
;
276 SocketStateUnlock( FCB
);
279 VOID
SocketCalloutLeave( PAFD_FCB FCB
) {
280 FCB
->Critical
= FALSE
;
281 SocketAcquireStateLock( FCB
);