Main Page | Class Hierarchy | Class List | File List | Class Members | File Members

filelock.c File Reference

#include "FsRtlP.h"

Go to the source code of this file.

Classes

struct  _LOCKTREE_NODE
struct  _SH_LOCK
struct  _EX_LOCK
struct  _WAITING_LOCK
struct  _LOCK_QUEUE
struct  _LOCK_INFO

Defines

#define Dbg   (0x20000000)
#define INLINE   __inline
#define TAG_EXCLUSIVE_LOCK   'xeLF'
#define TAG_FILE_LOCK   'lfLF'
#define TAG_LOCK_INFO   'ilLF'
#define TAG_LOCKTREE_NODE   'nlLF'
#define TAG_SHARED_LOCK   'hsLF'
#define TAG_WAITING_LOCK   'lwLF'
#define FsRtlAcquireLockQueue(a, b)   ExAcquireSpinLock(&(a)->QueueSpinLock, b);
#define FsRtlReacquireLockQueue(a, b, c)   ExAcquireSpinLock(&(b)->QueueSpinLock, c);
#define FsRtlReleaseLockQueue(a, b)   ExReleaseSpinLock(&(a)->QueueSpinLock, b);
#define FsRtlCompleteLockIrp(A, B, C, D, E, F)

Typedefs

typedef _LOCKTREE_NODE LOCKTREE_NODE
typedef _LOCKTREE_NODEPLOCKTREE_NODE
typedef _SH_LOCK SH_LOCK
typedef _SH_LOCKPSH_LOCK
typedef _EX_LOCK EX_LOCK
typedef _EX_LOCKPEX_LOCK
typedef _WAITING_LOCK WAITING_LOCK
typedef _WAITING_LOCKPWAITING_LOCK
typedef _LOCK_QUEUE LOCK_QUEUE
typedef _LOCK_QUEUEPLOCK_QUEUE
typedef _LOCK_INFO LOCK_INFO
typedef _LOCK_INFOPLOCK_INFO

Functions

INLINE PSH_LOCK FsRtlAllocateSharedLock (VOID)
INLINE PEX_LOCK FsRtlAllocateExclusiveLock (VOID)
INLINE PWAITING_LOCK FsRtlAllocateWaitingLock (VOID)
INLINE PLOCKTREE_NODE FsRtlAllocateLockTreeNode (VOID)
INLINE PLOCK_INFO FsRtlAllocateLockInfo (VOID)
INLINE VOID FsRtlFreeSharedLock (IN PSH_LOCK C)
INLINE VOID FsRtlFreeExclusiveLock (IN PEX_LOCK C)
INLINE VOID FsRtlFreeWaitingLock (IN PWAITING_LOCK C)
INLINE VOID FsRtlFreeLockTreeNode (IN PLOCKTREE_NODE C)
INLINE VOID FsRtlFreeLockInfo (IN PLOCK_INFO C)
INLINE VOID FsRtlCompleteLockIrpReal (IN PCOMPLETE_LOCK_IRP_ROUTINE CompleteLockIrpRoutine, IN PVOID Context, IN PIRP Irp, IN NTSTATUS Status, IN PNTSTATUS NewStatus, IN PFILE_OBJECT FileObject)
VOID FsRtlSplitLocks (IN PLOCKTREE_NODE ParentNode, IN PSINGLE_LIST_ENTRY *pStartLink, IN PLARGE_INTEGER LastShadowedByte, IN PLARGE_INTEGER GlueOffset)
PRTL_SPLAY_LINKS FsRtlFindFirstOverlappingSharedNode (IN PRTL_SPLAY_LINKS Tree, IN PLARGE_INTEGER StartingByte, IN PLARGE_INTEGER EndingByte, IN OUT PRTL_SPLAY_LINKS *LastEdgeNode, IN OUT PBOOLEAN GreaterThan)
PRTL_SPLAY_LINKS FsRtlFindFirstOverlappingExclusiveNode (IN PRTL_SPLAY_LINKS Tree, IN PLARGE_INTEGER StartingByte, IN PLARGE_INTEGER EndingByte, IN OUT PRTL_SPLAY_LINKS *LastEdgeNode, IN OUT PBOOLEAN GreaterThan)
PSH_LOCK FsRtlFindFirstOverlapInNode (IN PLOCKTREE_NODE Node, IN PLARGE_INTEGER StartingByte, IN PLARGE_INTEGER EndingByte)
BOOLEAN FsRtlPrivateInsertLock (IN PLOCK_INFO LockInfo, IN PFILE_OBJECT FileObject, IN PFILE_LOCK_INFO FileLockInfo)
BOOLEAN FsRtlPrivateInsertSharedLock (IN PLOCK_QUEUE LockQueue, IN PSH_LOCK NewLock)
VOID FsRtlPrivateInsertExclusiveLock (IN PLOCK_QUEUE LockQueue, IN PEX_LOCK NewLock)
VOID FsRtlPrivateCheckWaitingLocks (IN PLOCK_INFO LockInfo, IN PLOCK_QUEUE LockQueue, IN KIRQL OldIrql)
VOID FsRtlPrivateCancelFileLockIrp (IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
BOOLEAN FsRtlPrivateCheckForExclusiveLockAccess (IN PLOCK_QUEUE LockInfo, IN PFILE_LOCK_INFO FileLockInfo)
BOOLEAN FsRtlPrivateCheckForSharedLockAccess (IN PLOCK_QUEUE LockInfo, IN PFILE_LOCK_INFO FileLockInfo)
NTSTATUS FsRtlPrivateFastUnlockAll (IN PFILE_LOCK FileLock, IN PFILE_OBJECT FileObject, IN PEPROCESS ProcessId, IN ULONG Key, IN BOOLEAN MatchKey, IN PVOID Context OPTIONAL)
BOOLEAN FsRtlPrivateInitializeFileLock (IN PFILE_LOCK FileLock, IN BOOLEAN ViaFastCall)
VOID FsRtlPrivateRemoveLock (IN PLOCK_INFO LockInfo, IN PFILE_LOCK_INFO, IN BOOLEAN CheckForWaiters)
BOOLEAN FsRtlCheckNoSharedConflict (IN PLOCK_QUEUE LockQueue, IN PLARGE_INTEGER Starting, IN PLARGE_INTEGER Ending)
BOOLEAN FsRtlCheckNoExclusiveConflict (IN PLOCK_QUEUE LockQueue, IN PLARGE_INTEGER Starting, IN PLARGE_INTEGER Ending, IN ULONG Key, IN PFILE_OBJECT FileObject, IN PVOID ProcessId)
VOID FsRtlPrivateResetLowestLockOffset (PLOCK_INFO LockInfo)
NTSTATUS FsRtlFastUnlockSingleShared (IN PLOCK_INFO LockInfo, IN PFILE_OBJECT FileObject, IN LARGE_INTEGER UNALIGNED *FileOffset, IN PLARGE_INTEGER Length, IN PEPROCESS ProcessId, IN ULONG Key, IN PVOID Context OPTIONAL, IN BOOLEAN IgnoreUnlockRoutine, IN BOOLEAN CheckForWaiters)
NTSTATUS FsRtlFastUnlockSingleExclusive (IN PLOCK_INFO LockInfo, IN PFILE_OBJECT FileObject, IN LARGE_INTEGER UNALIGNED *FileOffset, IN PLARGE_INTEGER Length, IN PEPROCESS ProcessId, IN ULONG Key, IN PVOID Context OPTIONAL, IN BOOLEAN IgnoreUnlockRoutine, IN BOOLEAN CheckForWaiters)
VOID FsRtlInitializeFileLocks (VOID)
VOID FsRtlInitializeFileLock (IN PFILE_LOCK FileLock, IN PCOMPLETE_LOCK_IRP_ROUTINE CompleteLockIrpRoutine OPTIONAL, IN PUNLOCK_ROUTINE UnlockRoutine OPTIONAL)
VOID FsRtlUninitializeFileLock (IN PFILE_LOCK FileLock)
PFILE_LOCK FsRtlAllocateFileLock (IN PCOMPLETE_LOCK_IRP_ROUTINE CompleteLockIrpRoutine OPTIONAL, IN PUNLOCK_ROUTINE UnlockRoutine OPTIONAL)
VOID FsRtlFreeFileLock (IN PFILE_LOCK FileLock)
NTSTATUS FsRtlProcessFileLock (IN PFILE_LOCK FileLock, IN PIRP Irp, IN PVOID Context OPTIONAL)
BOOLEAN FsRtlCheckLockForReadAccess (IN PFILE_LOCK FileLock, IN PIRP Irp)
BOOLEAN FsRtlCheckLockForWriteAccess (IN PFILE_LOCK FileLock, IN PIRP Irp)
PFILE_LOCK_INFO FsRtlGetNextFileLock (IN PFILE_LOCK FileLock, IN BOOLEAN Restart)
BOOLEAN FsRtlFastCheckLockForRead (IN PFILE_LOCK FileLock, IN PLARGE_INTEGER StartingByte, IN PLARGE_INTEGER Length, IN ULONG Key, IN PFILE_OBJECT FileObject, IN PVOID ProcessId)
BOOLEAN FsRtlFastCheckLockForWrite (IN PFILE_LOCK FileLock, IN PLARGE_INTEGER StartingByte, IN PLARGE_INTEGER Length, IN ULONG Key, IN PVOID FileObject, IN PVOID ProcessId)
VOID FsRtlSplitLocks (IN PLOCKTREE_NODE ParentNode, IN PSINGLE_LIST_ENTRY *pStartLink OPTIONAL, IN PLARGE_INTEGER LastShadowedByte OPTIONAL, IN PLARGE_INTEGER GlueOffset OPTIONAL)
NTSTATUS FsRtlFastUnlockSingle (IN PFILE_LOCK FileLock, IN PFILE_OBJECT FileObject, IN LARGE_INTEGER UNALIGNED *FileOffset, IN PLARGE_INTEGER Length, IN PEPROCESS ProcessId, IN ULONG Key, IN PVOID Context OPTIONAL, IN BOOLEAN AlreadySynchronized)
NTSTATUS FsRtlFastUnlockAll (IN PFILE_LOCK FileLock, IN PFILE_OBJECT FileObject, IN PEPROCESS ProcessId, IN PVOID Context OPTIONAL)
NTSTATUS FsRtlFastUnlockAllByKey (IN PFILE_LOCK FileLock, IN PFILE_OBJECT FileObject, IN PEPROCESS ProcessId, IN ULONG Key, IN PVOID Context OPTIONAL)
BOOLEAN FsRtlPrivateLock (IN PFILE_LOCK FileLock, IN PFILE_OBJECT FileObject, IN PLARGE_INTEGER FileOffset, IN PLARGE_INTEGER Length, IN PEPROCESS ProcessId, IN ULONG Key, IN BOOLEAN FailImmediately, IN BOOLEAN ExclusiveLock, OUT PIO_STATUS_BLOCK Iosb, IN PIRP Irp OPTIONAL, IN PVOID Context, IN BOOLEAN AlreadySynchronized)

Variables

FAST_MUTEX FsRtlCreateLockInfo
NPAGED_LOOKASIDE_LIST FsRtlSharedLockLookasideList
NPAGED_LOOKASIDE_LIST FsRtlExclusiveLockLookasideList
NPAGED_LOOKASIDE_LIST FsRtlWaitingLockLookasideList
NPAGED_LOOKASIDE_LIST FsRtlLockTreeNodeLookasideList
NPAGED_LOOKASIDE_LIST FsRtlLockInfoLookasideList
PAGED_LOOKASIDE_LIST FsRtlFileLockLookasideList


Define Documentation

#define Dbg   (0x20000000)
 

Definition at line 94 of file filelock.c.

#define FsRtlAcquireLockQueue a,
 )     ExAcquireSpinLock(&(a)->QueueSpinLock, b);
 

Definition at line 481 of file filelock.c.

Referenced by FsRtlFastUnlockSingleExclusive(), FsRtlFastUnlockSingleShared(), FsRtlGetNextFileLock(), FsRtlPrivateLock(), and FsRtlUninitializeFileLock().

#define FsRtlCompleteLockIrp A,
B,
C,
D,
E,
 ) 
 

Value:

FsRtlCompleteLockIrpReal( (A)->CompleteLockIrpRoutine, \ B, \ C, \ D, \ E, \ F )

Definition at line 497 of file filelock.c.

Referenced by FsRtlPrivateCancelFileLockIrp(), FsRtlPrivateCheckWaitingLocks(), FsRtlPrivateFastUnlockAll(), FsRtlPrivateLock(), FsRtlProcessFileLock(), and FsRtlUninitializeFileLock().

#define FsRtlReacquireLockQueue a,
b,
c   )     ExAcquireSpinLock(&(b)->QueueSpinLock, c);
 

Definition at line 484 of file filelock.c.

Referenced by FsRtlFastCheckLockForRead(), FsRtlFastCheckLockForWrite(), FsRtlFastUnlockSingleExclusive(), FsRtlFastUnlockSingleShared(), FsRtlPrivateCancelFileLockIrp(), FsRtlPrivateCheckWaitingLocks(), and FsRtlPrivateFastUnlockAll().

#define FsRtlReleaseLockQueue a,
 )     ExReleaseSpinLock(&(a)->QueueSpinLock, b);
 

Definition at line 487 of file filelock.c.

Referenced by FsRtlFastCheckLockForRead(), FsRtlFastCheckLockForWrite(), FsRtlFastUnlockSingleExclusive(), FsRtlFastUnlockSingleShared(), FsRtlGetNextFileLock(), FsRtlPrivateCancelFileLockIrp(), FsRtlPrivateCheckWaitingLocks(), FsRtlPrivateFastUnlockAll(), FsRtlPrivateLock(), and FsRtlUninitializeFileLock().

#define INLINE   __inline
 

Definition at line 101 of file filelock.c.

#define TAG_EXCLUSIVE_LOCK   'xeLF'
 

Definition at line 104 of file filelock.c.

Referenced by FsRtlInitializeFileLocks().

#define TAG_FILE_LOCK   'lfLF'
 

Definition at line 105 of file filelock.c.

Referenced by FsRtlInitializeFileLocks().

#define TAG_LOCK_INFO   'ilLF'
 

Definition at line 106 of file filelock.c.

Referenced by FsRtlInitializeFileLocks().

#define TAG_LOCKTREE_NODE   'nlLF'
 

Definition at line 107 of file filelock.c.

Referenced by FsRtlInitializeFileLocks().

#define TAG_SHARED_LOCK   'hsLF'
 

Definition at line 108 of file filelock.c.

Referenced by FsRtlInitializeFileLocks().

#define TAG_WAITING_LOCK   'lwLF'
 

Definition at line 109 of file filelock.c.

Referenced by FsRtlInitializeFileLocks().


Typedef Documentation

typedef struct _EX_LOCK EX_LOCK
 

typedef struct _LOCK_INFO LOCK_INFO
 

typedef struct _LOCK_QUEUE LOCK_QUEUE
 

typedef struct _LOCKTREE_NODE LOCKTREE_NODE
 

typedef struct _EX_LOCK * PEX_LOCK
 

Referenced by FsRtlAllocateExclusiveLock(), FsRtlCheckNoExclusiveConflict(), FsRtlFastUnlockSingleExclusive(), FsRtlFindFirstOverlappingExclusiveNode(), FsRtlGetNextFileLock(), FsRtlPrivateCheckForExclusiveLockAccess(), FsRtlPrivateCheckForSharedLockAccess(), FsRtlPrivateFastUnlockAll(), FsRtlPrivateInsertLock(), FsRtlPrivateResetLowestLockOffset(), and FsRtlUninitializeFileLock().

typedef struct _LOCK_INFO * PLOCK_INFO
 

Referenced by FsRtlAllocateLockInfo(), FsRtlCheckLockForReadAccess(), FsRtlCheckLockForWriteAccess(), FsRtlFastCheckLockForRead(), FsRtlFastCheckLockForWrite(), FsRtlGetNextFileLock(), FsRtlPrivateCancelFileLockIrp(), FsRtlPrivateFastUnlockAll(), FsRtlPrivateInitializeFileLock(), FsRtlPrivateLock(), and FsRtlUninitializeFileLock().

typedef struct _LOCK_QUEUE * PLOCK_QUEUE
 

Referenced by FsRtlFastCheckLockForRead(), FsRtlFastCheckLockForWrite(), FsRtlFastUnlockSingleExclusive(), FsRtlFastUnlockSingleShared(), FsRtlPrivateCancelFileLockIrp(), FsRtlPrivateFastUnlockAll(), and FsRtlPrivateLock().

typedef struct _LOCKTREE_NODE * PLOCKTREE_NODE
 

Referenced by FsRtlAllocateLockTreeNode(), FsRtlCheckNoSharedConflict(), FsRtlFastUnlockSingleShared(), FsRtlFindFirstOverlappingSharedNode(), FsRtlGetNextFileLock(), FsRtlPrivateCheckForExclusiveLockAccess(), FsRtlPrivateFastUnlockAll(), FsRtlPrivateInsertSharedLock(), FsRtlPrivateResetLowestLockOffset(), FsRtlSplitLocks(), and FsRtlUninitializeFileLock().

typedef struct _SH_LOCK * PSH_LOCK
 

Referenced by FsRtlAllocateSharedLock(), FsRtlFastUnlockSingleShared(), FsRtlFindFirstOverlapInNode(), FsRtlFindFirstOverlappingSharedNode(), FsRtlGetNextFileLock(), FsRtlPrivateCheckForExclusiveLockAccess(), FsRtlPrivateFastUnlockAll(), FsRtlPrivateInsertLock(), FsRtlPrivateInsertSharedLock(), FsRtlPrivateResetLowestLockOffset(), FsRtlSplitLocks(), and FsRtlUninitializeFileLock().

typedef struct _WAITING_LOCK * PWAITING_LOCK
 

Referenced by FsRtlAllocateWaitingLock(), FsRtlPrivateCancelFileLockIrp(), FsRtlPrivateCheckWaitingLocks(), FsRtlPrivateFastUnlockAll(), FsRtlPrivateLock(), and FsRtlUninitializeFileLock().

typedef struct _SH_LOCK SH_LOCK
 

typedef struct _WAITING_LOCK WAITING_LOCK
 


Function Documentation

INLINE PEX_LOCK FsRtlAllocateExclusiveLock VOID   ) 
 

Definition at line 400 of file filelock.c.

References ExAllocateFromNPagedLookasideList(), FsRtlExclusiveLockLookasideList, and PEX_LOCK.

Referenced by FsRtlPrivateInsertLock().

00403 { 00404 return (PEX_LOCK) ExAllocateFromNPagedLookasideList( &FsRtlExclusiveLockLookasideList ); 00405 }

PFILE_LOCK FsRtlAllocateFileLock IN PCOMPLETE_LOCK_IRP_ROUTINE CompleteLockIrpRoutine  OPTIONAL,
IN PUNLOCK_ROUTINE UnlockRoutine  OPTIONAL
 

Definition at line 1141 of file filelock.c.

References ExAllocateFromPagedLookasideList(), FsRtlFileLockLookasideList, FsRtlInitializeFileLock(), and NULL.

Referenced by UdfCreateFileLock().

01146 { 01147 PFILE_LOCK FileLock; 01148 01149 FileLock = ExAllocateFromPagedLookasideList( &FsRtlFileLockLookasideList ); 01150 01151 if (FileLock != NULL) { 01152 01153 FsRtlInitializeFileLock( FileLock, 01154 CompleteLockIrpRoutine, 01155 UnlockRoutine ); 01156 } 01157 01158 return FileLock; 01159 }

INLINE PLOCK_INFO FsRtlAllocateLockInfo VOID   ) 
 

Definition at line 427 of file filelock.c.

References ExAllocateFromNPagedLookasideList(), FsRtlLockInfoLookasideList, and PLOCK_INFO.

Referenced by FsRtlPrivateInitializeFileLock().

00430 { 00431 return (PLOCK_INFO) ExAllocateFromNPagedLookasideList( &FsRtlLockInfoLookasideList ); 00432 }

INLINE PLOCKTREE_NODE FsRtlAllocateLockTreeNode VOID   ) 
 

Definition at line 418 of file filelock.c.

References ExAllocateFromNPagedLookasideList(), FsRtlLockTreeNodeLookasideList, and PLOCKTREE_NODE.

Referenced by FsRtlPrivateInsertSharedLock(), and FsRtlSplitLocks().

00421 { 00422 return (PLOCKTREE_NODE) ExAllocateFromNPagedLookasideList( &FsRtlLockTreeNodeLookasideList ); 00423 }

INLINE PSH_LOCK FsRtlAllocateSharedLock VOID   ) 
 

Definition at line 391 of file filelock.c.

References ExAllocateFromNPagedLookasideList(), FsRtlSharedLockLookasideList, and PSH_LOCK.

Referenced by FsRtlPrivateInsertLock().

00394 { 00395 return (PSH_LOCK) ExAllocateFromNPagedLookasideList( &FsRtlSharedLockLookasideList ); 00396 }

INLINE PWAITING_LOCK FsRtlAllocateWaitingLock VOID   ) 
 

Definition at line 409 of file filelock.c.

References ExAllocateFromNPagedLookasideList(), FsRtlWaitingLockLookasideList, and PWAITING_LOCK.

Referenced by FsRtlPrivateLock().

00412 { 00413 return (PWAITING_LOCK) ExAllocateFromNPagedLookasideList( &FsRtlWaitingLockLookasideList ); 00414 }

BOOLEAN FsRtlCheckLockForReadAccess IN PFILE_LOCK  FileLock,
IN PIRP  Irp
 

Definition at line 1315 of file filelock.c.

References Dbg, DebugTrace, _LOCK_QUEUE::ExclusiveLockTree, _IO_STACK_LOCATION::FileObject, FsRtlFastCheckLockForRead(), IoGetCurrentIrpStackLocation, IoGetRequestorProcess(), Irp, Key, _LOCK_INFO::LockQueue, _LOCK_INFO::LowestLockOffset, NULL, _IO_STACK_LOCATION::Parameters, PLOCK_INFO, and TRUE.

Referenced by UdfCommonRead().

01322 : 01323 01324 This routine checks to see if the caller has read access to the 01325 range indicated in the IRP due to file locks. This call does not 01326 complete the Irp it only uses it to get the lock information and read 01327 information. The IRP must be for a read operation. 01328 01329 Arguments: 01330 01331 FileLock - Supplies the File Lock to check. 01332 01333 Irp - Supplies the Irp being processed. 01334 01335 Return Value: 01336 01337 BOOLEAN - TRUE if the indicated user/request has read access to the 01338 entire specified byte range, and FALSE otherwise 01339 01340 --*/ 01341 01342 { 01343 BOOLEAN Result; 01344 01345 PIO_STACK_LOCATION IrpSp; 01346 01347 PLOCK_INFO LockInfo; 01348 LARGE_INTEGER StartingByte; 01349 LARGE_INTEGER Length; 01350 ULONG Key; 01351 PFILE_OBJECT FileObject; 01352 PVOID ProcessId; 01353 LARGE_INTEGER BeyondLastByte; 01354 01355 DebugTrace(+1, Dbg, "FsRtlCheckLockForReadAccess, FileLock = %08lx\n", FileLock); 01356 01357 if ((LockInfo = (PLOCK_INFO) FileLock->LockInformation) == NULL) { 01358 DebugTrace(-1, Dbg, "FsRtlCheckLockForReadAccess (No current lock info) -> TRUE\n", 0); 01359 return TRUE; 01360 } 01361 01362 // 01363 // Do a really fast test to see if there are any exclusive locks to start with 01364 // 01365 01366 if (LockInfo->LockQueue.ExclusiveLockTree == NULL) { 01367 DebugTrace(-1, Dbg, "FsRtlCheckLockForReadAccess (No current locks) -> TRUE\n", 0); 01368 return TRUE; 01369 } 01370 01371 // 01372 // Get the read offset and compare it to the lowest existing lock. 01373 // 01374 01375 IrpSp = IoGetCurrentIrpStackLocation( Irp ); 01376 01377 StartingByte = IrpSp->Parameters.Read.ByteOffset; 01378 (ULONGLONG)Length.QuadPart = (ULONGLONG)IrpSp->Parameters.Read.Length; 01379 01380 (ULONGLONG)BeyondLastByte.QuadPart = (ULONGLONG)StartingByte.QuadPart + Length.LowPart; 01381 if ( (ULONGLONG)BeyondLastByte.QuadPart <= (ULONGLONG)LockInfo->LowestLockOffset ) { 01382 DebugTrace(-1, Dbg, "FsRtlCheckLockForReadAccess (Below lowest lock) -> TRUE\n", 0); 01383 return TRUE; 01384 } 01385 01386 // 01387 // Get remaining parameters. 01388 // 01389 01390 Key = IrpSp->Parameters.Read.Key; 01391 FileObject = IrpSp->FileObject; 01392 ProcessId = IoGetRequestorProcess( Irp ); 01393 01394 // 01395 // Call our private work routine to do the real check 01396 // 01397 01398 Result = FsRtlFastCheckLockForRead( FileLock, 01399 &StartingByte, 01400 &Length, 01401 Key, 01402 FileObject, 01403 ProcessId ); 01404 01405 // 01406 // And return to our caller 01407 // 01408 01409 DebugTrace(-1, Dbg, "FsRtlCheckLockForReadAccess -> %08lx\n", Result); 01410 01411 return Result; 01412 }

BOOLEAN FsRtlCheckLockForWriteAccess IN PFILE_LOCK  FileLock,
IN PIRP  Irp
 

Definition at line 1416 of file filelock.c.

References Dbg, DebugTrace, _LOCK_QUEUE::ExclusiveLockTree, _IO_STACK_LOCATION::FileObject, FsRtlFastCheckLockForWrite(), IoGetCurrentIrpStackLocation, IoGetRequestorProcess(), Irp, Key, _LOCK_INFO::LockQueue, _LOCK_INFO::LowestLockOffset, NULL, _IO_STACK_LOCATION::Parameters, PLOCK_INFO, _LOCK_QUEUE::SharedLockTree, and TRUE.

01423 : 01424 01425 This routine checks to see if the caller has write access to the 01426 indicated range due to file locks. This call does not complete the 01427 Irp it only uses it to get the lock information and write information. 01428 The IRP must be for a write operation. 01429 01430 Arguments: 01431 01432 FileLock - Supplies the File Lock to check. 01433 01434 Irp - Supplies the Irp being processed. 01435 01436 Return Value: 01437 01438 BOOLEAN - TRUE if the indicated user/request has write access to the 01439 entire specified byte range, and FALSE otherwise 01440 01441 --*/ 01442 01443 { 01444 BOOLEAN Result; 01445 01446 PIO_STACK_LOCATION IrpSp; 01447 01448 PLOCK_INFO LockInfo; 01449 LARGE_INTEGER StartingByte; 01450 LARGE_INTEGER Length; 01451 ULONG Key; 01452 PFILE_OBJECT FileObject; 01453 PVOID ProcessId; 01454 LARGE_INTEGER BeyondLastByte; 01455 01456 DebugTrace(+1, Dbg, "FsRtlCheckLockForWriteAccess, FileLock = %08lx\n", FileLock); 01457 01458 if ((LockInfo = (PLOCK_INFO) FileLock->LockInformation) == NULL) { 01459 DebugTrace(-1, Dbg, "FsRtlCheckLockForWriteAccess (No current lock info) -> TRUE\n", 0); 01460 return TRUE; 01461 } 01462 01463 // 01464 // Do a really fast test to see if there are any locks to start with 01465 // 01466 01467 if (LockInfo->LockQueue.ExclusiveLockTree == NULL && LockInfo->LockQueue.SharedLockTree == NULL) { 01468 DebugTrace(-1, Dbg, "FsRtlCheckLockForWriteAccess (No current locks) -> TRUE\n", 0); 01469 return TRUE; 01470 } 01471 01472 // 01473 // Get the write offset and compare it to the lowest existing lock. 01474 // 01475 01476 IrpSp = IoGetCurrentIrpStackLocation( Irp ); 01477 01478 StartingByte = IrpSp->Parameters.Write.ByteOffset; 01479 (ULONGLONG)Length.QuadPart = (ULONGLONG)IrpSp->Parameters.Write.Length; 01480 01481 (ULONGLONG)BeyondLastByte.QuadPart = (ULONGLONG)StartingByte.QuadPart + Length.LowPart; 01482 if ( (ULONGLONG)BeyondLastByte.QuadPart <= (ULONGLONG)LockInfo->LowestLockOffset ) { 01483 DebugTrace(-1, Dbg, "FsRtlCheckLockForWriteAccess (Below lowest lock) -> TRUE\n", 0); 01484 return TRUE; 01485 } 01486 01487 // 01488 // Get remaining parameters. 01489 // 01490 01491 Key = IrpSp->Parameters.Write.Key; 01492 FileObject = IrpSp->FileObject; 01493 ProcessId = IoGetRequestorProcess( Irp ); 01494 01495 // 01496 // Call our private work routine to do the real work 01497 // 01498 01499 Result = FsRtlFastCheckLockForWrite( FileLock, 01500 &StartingByte, 01501 &Length, 01502 Key, 01503 FileObject, 01504 ProcessId ); 01505 01506 // 01507 // And return to our caller 01508 // 01509 01510 DebugTrace(-1, Dbg, "FsRtlCheckLockForWriteAccess -> %08lx\n", Result); 01511 01512 return Result; 01513 }

BOOLEAN FsRtlCheckNoExclusiveConflict IN PLOCK_QUEUE  LockQueue,
IN PLARGE_INTEGER  Starting,
IN PLARGE_INTEGER  Ending,
IN ULONG  Key,
IN PFILE_OBJECT  FileObject,
IN PVOID  ProcessId
 

Definition at line 2469 of file filelock.c.

References Dbg, DebugTrace, FALSE, FsRtlFindFirstOverlappingExclusiveNode(), Key, Lock, NULL, PEX_LOCK, RtlRealSuccessor(), RtlSplay(), Status, and TRUE.

Referenced by FsRtlFastCheckLockForRead(), and FsRtlFastCheckLockForWrite().

02479 : 02480 02481 This routine checks to see if there is conflict in the exclusive locks with 02482 a given range and identifying tuple of key, fileobject and process. This is 02483 for part of the read access path. 02484 02485 Arguments: 02486 02487 FileLock - Supplies the File Lock to check 02488 02489 StartingByte - Supplies the first byte (zero based) to check 02490 02491 Length - Supplies the length, in bytes, to check 02492 02493 Key - Supplies the key to use in the check 02494 02495 FileObject - Supplies the file object to use in the check 02496 02497 ProcessId - Supplies the Process Id to use in the check 02498 02499 Return Value: 02500 02501 BOOLEAN - TRUE if the indicated user/request doesn't conflict in 02502 entire specified byte range, and FALSE otherwise 02503 02504 --*/ 02505 { 02506 PRTL_SPLAY_LINKS SplayLinks, BeginLinks; 02507 PEX_LOCK Lock; 02508 BOOLEAN Status = TRUE; 02509 02510 // 02511 // Find the node to begin the search at and go 02512 // 02513 02514 for (SplayLinks = FsRtlFindFirstOverlappingExclusiveNode( LockQueue->ExclusiveLockTree, 02515 Starting, 02516 Ending, 02517 &BeginLinks, 02518 NULL); 02519 SplayLinks; 02520 SplayLinks = RtlRealSuccessor(SplayLinks)) { 02521 02522 Lock = CONTAINING_RECORD( SplayLinks, EX_LOCK, Links ); 02523 02524 // 02525 // If the current lock is greater than the end of the range we're 02526 // looking for then the the user doesn't conflict 02527 // 02528 // if (Ending < Lock->StartingByte) ... 02529 // 02530 02531 if ((ULONGLONG)Ending->QuadPart < (ULONGLONG)Lock->LockInfo.StartingByte.QuadPart) { 02532 02533 DebugTrace(0, Dbg, "FsRtlCheckForExclusiveConflict, Ending < Lock->StartingByte\n", 0); 02534 02535 break; 02536 } 02537 02538 // 02539 // Check for any overlap with the request. The test for 02540 // overlap is that starting byte is less than or equal to the locks 02541 // ending byte, and the ending byte is greater than or equal to the 02542 // locks starting byte. We already tested for this latter case in 02543 // the preceding statement. 02544 // 02545 // if (Starting <= Lock->StartingByte + Lock->Length - 1) ... 02546 // 02547 02548 if ((ULONGLONG)Starting->QuadPart <= (ULONGLONG)Lock->LockInfo.EndingByte.QuadPart) { 02549 02550 // 02551 // This request overlaps the lock. We cannot grant the request 02552 // if the file object, process id, and key do not match. Otherwise 02553 // we'll continue looping looking at locks 02554 // 02555 02556 if ((Lock->LockInfo.FileObject != FileObject) || 02557 (Lock->LockInfo.ProcessId != ProcessId) || 02558 (Lock->LockInfo.Key != Key)) { 02559 02560 DebugTrace(0, Dbg, "FsRtlCheckForExclusiveConflict, Range locked already\n", 0); 02561 02562 Status = FALSE; 02563 break; 02564 } 02565 } 02566 } 02567 02568 if (BeginLinks) { 02569 02570 LockQueue->ExclusiveLockTree = RtlSplay(BeginLinks); 02571 } 02572 02573 // 02574 // We searched the entire range without a conflict so we'll note no conflict 02575 // 02576 02577 return Status; 02578 }

BOOLEAN FsRtlCheckNoSharedConflict IN PLOCK_QUEUE  LockQueue,
IN PLARGE_INTEGER  Starting,
IN PLARGE_INTEGER  Ending
 

Definition at line 2392 of file filelock.c.

References FALSE, FsRtlFindFirstOverlapInNode(), FsRtlFindFirstOverlappingSharedNode(), _LOCKTREE_NODE::HoleyNode, NULL, PLOCKTREE_NODE, RtlSplay(), and TRUE.

Referenced by FsRtlFastCheckLockForWrite().

02399 : 02400 02401 This routine checks to see if there is overlap in the shared locks with 02402 the given range. It is intended for use in the write access check path 02403 so that a rebalance will occur. 02404 02405 Arguments: 02406 02407 FileLock - Supplies the File Lock to check 02408 02409 StartingByte - Supplies the first byte (zero based) to check 02410 02411 Length - Supplies the length, in bytes, to check 02412 02413 Key - Supplies the key to use in the check 02414 02415 FileObject - Supplies the file object to use in the check 02416 02417 ProcessId - Supplies the Process Id to use in the check 02418 02419 Return Value: 02420 02421 BOOLEAN - TRUE if the indicated user/request doesn't conflict in 02422 entire specified byte range, and FALSE otherwise 02423 02424 --*/ 02425 { 02426 PRTL_SPLAY_LINKS SplayLinks, BeginLinks; 02427 PLOCKTREE_NODE Node; 02428 02429 SplayLinks = FsRtlFindFirstOverlappingSharedNode( LockQueue->SharedLockTree, 02430 Starting, 02431 Ending, 02432 &BeginLinks, 02433 NULL); 02434 02435 if (BeginLinks) { 02436 02437 LockQueue->SharedLockTree = RtlSplay(BeginLinks); 02438 } 02439 02440 // 02441 // If this node is holey, we'll have to walk the whole thing. 02442 // 02443 02444 if (SplayLinks) { 02445 02446 Node = CONTAINING_RECORD( SplayLinks, LOCKTREE_NODE, Links ); 02447 02448 if (Node->HoleyNode) { 02449 02450 return (BOOLEAN)(FsRtlFindFirstOverlapInNode( Node, Starting, Ending ) == NULL); 02451 } 02452 02453 // 02454 // Overlapping non-holey node, so we do have shared lock conflict. 02455 // 02456 02457 return FALSE; 02458 } 02459 02460 // 02461 // No node overlaps. 02462 // 02463 02464 return TRUE; 02465 }

INLINE VOID FsRtlCompleteLockIrpReal IN PCOMPLETE_LOCK_IRP_ROUTINE  CompleteLockIrpRoutine,
IN PVOID  Context,
IN PIRP  Irp,
IN NTSTATUS  Status,
IN PNTSTATUS  NewStatus,
IN PFILE_OBJECT  FileObject
 

Definition at line 507 of file filelock.c.

References FsRtlCompleteRequest, _IRP::IoStatus, Irp, NTSTATUS(), NULL, PCOMPLETE_LOCK_IRP_ROUTINE, and Status.

00515 { 00516 // 00517 // This fools the compiler into generating the Status only once 00518 // if it is calculated from an expression. 00519 // 00520 00521 NTSTATUS LocalStatus = Status; 00522 00523 if (CompleteLockIrpRoutine != NULL) { 00524 00525 if (FileObject != NULL) { 00526 00527 FileObject->LastLock = NULL; 00528 } 00529 00530 Irp->IoStatus.Status = LocalStatus; 00531 *NewStatus = CompleteLockIrpRoutine( Context, Irp ); 00532 00533 } else { 00534 00535 FsRtlCompleteRequest( Irp, LocalStatus ); 00536 *NewStatus = LocalStatus; 00537 } 00538 }

BOOLEAN FsRtlFastCheckLockForRead IN PFILE_LOCK  FileLock,
IN PLARGE_INTEGER  StartingByte,
IN PLARGE_INTEGER  Length,
IN ULONG  Key,
IN PFILE_OBJECT  FileObject,
IN PVOID  ProcessId
 

Definition at line 2582 of file filelock.c.

References Dbg, DebugTrace, _FILE_LOCK_INFO::EndingByte, _LOCK_QUEUE::ExclusiveLockTree, FsRtlCheckNoExclusiveConflict(), FsRtlReacquireLockQueue, FsRtlReleaseLockQueue, _FILE_LOCK_INFO::Key, Key, _LOCK_INFO::LockQueue, _LOCK_INFO::LowestLockOffset, NULL, PLOCK_INFO, PLOCK_QUEUE, _FILE_LOCK_INFO::ProcessId, _FILE_LOCK_INFO::StartingByte, Status, and TRUE.

Referenced by FsRtlCheckLockForReadAccess().

02593 : 02594 02595 This routine checks to see if the caller has read access to the 02596 indicated range due to file locks. 02597 02598 Arguments: 02599 02600 FileLock - Supplies the File Lock to check 02601 02602 StartingByte - Supplies the first byte (zero based) to check 02603 02604 Length - Supplies the length, in bytes, to check 02605 02606 Key - Supplies the to use in the check 02607 02608 FileObject - Supplies the file object to use in the check 02609 02610 ProcessId - Supplies the Process Id to use in the check 02611 02612 Return Value: 02613 02614 BOOLEAN - TRUE if the indicated user/request has read access to the 02615 entire specified byte range, and FALSE otherwise 02616 02617 --*/ 02618 02619 { 02620 LARGE_INTEGER Starting; 02621 LARGE_INTEGER Ending; 02622 02623 PLOCK_INFO LockInfo; 02624 PLOCK_QUEUE LockQueue; 02625 KIRQL OldIrql; 02626 PFILE_LOCK_INFO LastLock; 02627 BOOLEAN Status; 02628 02629 if ((LockInfo = (PLOCK_INFO) FileLock->LockInformation) == NULL) { 02630 02631 // 02632 // No lock information on this FileLock 02633 // 02634 02635 DebugTrace(0, Dbg, "FsRtlFastCheckLockForRead, No lock info\n", 0); 02636 return TRUE; 02637 } 02638 02639 // 02640 // If there isn't an exclusive lock then we can immediately grant access 02641 // 02642 02643 if (LockInfo->LockQueue.ExclusiveLockTree == NULL) { 02644 DebugTrace(0, Dbg, "FsRtlFastCheckLockForRead, No exlocks present\n", 0); 02645 return TRUE; 02646 } 02647 02648 // 02649 // If length is zero then automatically give grant access 02650 // 02651 02652 if ((ULONGLONG)Length->QuadPart == 0) { 02653 02654 DebugTrace(0, Dbg, "FsRtlFastCheckLockForRead, Length == 0\n", 0); 02655 return TRUE; 02656 } 02657 02658 // 02659 // Get our starting and ending byte position 02660 // 02661 02662 Starting = *StartingByte; 02663 (ULONGLONG)Ending.QuadPart = (ULONGLONG)Starting.QuadPart + (ULONGLONG)Length->QuadPart - 1; 02664 02665 // 02666 // Now check lock queue 02667 // 02668 02669 LockQueue = &LockInfo->LockQueue; 02670 02671 // 02672 // Grab the waiting lock queue spinlock to exclude anyone from messing 02673 // with the queue while we're using it 02674 // 02675 02676 FsRtlReacquireLockQueue(LockInfo, LockQueue, &OldIrql); 02677 02678 // 02679 // If the range ends below the lowest existing lock, this read is OK. 02680 // 02681 02682 if ( ((ULONGLONG)Ending.QuadPart < (ULONGLONG)LockInfo->LowestLockOffset) ) { 02683 DebugTrace(0, Dbg, "FsRtlFastCheckLockForRead (below lowest lock)\n", 0); 02684 02685 FsRtlReleaseLockQueue(LockQueue, OldIrql); 02686 return TRUE; 02687 } 02688 02689 // 02690 // If the caller just locked this range, he can read it. 02691 // 02692 02693 LastLock = (PFILE_LOCK_INFO)FileObject->LastLock; 02694 if ((LastLock != NULL) && 02695 ((ULONGLONG)Starting.QuadPart >= (ULONGLONG)LastLock->StartingByte.QuadPart) && 02696 ((ULONGLONG)Ending.QuadPart <= (ULONGLONG)LastLock->EndingByte.QuadPart) && 02697 (LastLock->Key == Key) && 02698 (LastLock->ProcessId == ProcessId)) { 02699 02700 FsRtlReleaseLockQueue(LockQueue, OldIrql); 02701 return TRUE; 02702 } 02703 02704 // 02705 // Check the exclusive locks for a conflict. It is impossible to have 02706 // a read conflict with any shared lock. 02707 // 02708 02709 Status = FsRtlCheckNoExclusiveConflict(LockQueue, &Starting, &Ending, Key, FileObject, ProcessId); 02710 02711 FsRtlReleaseLockQueue(LockQueue, OldIrql); 02712 02713 return Status; 02714 }

BOOLEAN FsRtlFastCheckLockForWrite IN PFILE_LOCK  FileLock,
IN PLARGE_INTEGER  StartingByte,
IN PLARGE_INTEGER  Length,
IN ULONG  Key,
IN PVOID  FileObject,
IN PVOID  ProcessId
 

Definition at line 2718 of file filelock.c.

References Dbg, DebugTrace, _FILE_LOCK_INFO::EndingByte, _FILE_LOCK_INFO::ExclusiveLock, _LOCK_QUEUE::ExclusiveLockTree, FsRtlCheckNoExclusiveConflict(), FsRtlCheckNoSharedConflict(), FsRtlReacquireLockQueue, FsRtlReleaseLockQueue, _FILE_LOCK_INFO::Key, Key, _LOCK_INFO::LockQueue, _LOCK_INFO::LowestLockOffset, NULL, PLOCK_INFO, PLOCK_QUEUE, _FILE_LOCK_INFO::ProcessId, _LOCK_QUEUE::SharedLockTree, _FILE_LOCK_INFO::StartingByte, Status, and TRUE.

Referenced by FsRtlCheckLockForWriteAccess().

02729 : 02730 02731 This routine checks to see if the caller has write access to the 02732 indicated range due to file locks 02733 02734 Arguments: 02735 02736 FileLock - Supplies the File Lock to check 02737 02738 StartingByte - Supplies the first byte (zero based) to check 02739 02740 Length - Supplies the length, in bytes, to check 02741 02742 Key - Supplies the to use in the check 02743 02744 FileObject - Supplies the file object to use in the check 02745 02746 ProcessId - Supplies the Process Id to use in the check 02747 02748 Return Value: 02749 02750 BOOLEAN - TRUE if the indicated user/request has write access to the 02751 entire specified byte range, and FALSE otherwise 02752 02753 --*/ 02754 02755 { 02756 LARGE_INTEGER Starting; 02757 LARGE_INTEGER Ending; 02758 02759 PLOCK_INFO LockInfo; 02760 PLOCK_QUEUE LockQueue; 02761 KIRQL OldIrql; 02762 PFILE_LOCK_INFO LastLock; 02763 BOOLEAN Status; 02764 02765 if ((LockInfo = (PLOCK_INFO) FileLock->LockInformation) == NULL) { 02766 02767 // 02768 // No lock information on this FileLock 02769 // 02770 02771 DebugTrace(0, Dbg, "FsRtlFastCheckLockForRead, No lock info\n", 0); 02772 return TRUE; 02773 } 02774 02775 // 02776 // If there isn't a lock then we can immediately grant access 02777 // 02778 02779 if (LockInfo->LockQueue.SharedLockTree == NULL && LockInfo->LockQueue.ExclusiveLockTree == NULL) { 02780 02781 DebugTrace(0, Dbg, "FsRtlFastCheckLockForWrite, No locks present\n", 0); 02782 return TRUE; 02783 } 02784 02785 // 02786 // If length is zero then automatically grant access 02787 // 02788 02789 if ((ULONGLONG)Length->QuadPart == 0) { 02790 02791 DebugTrace(0, Dbg, "FsRtlFastCheckLockForWrite, Length == 0\n", 0); 02792 return TRUE; 02793 } 02794 02795 // 02796 // Get our starting and ending byte position 02797 // 02798 02799 Starting = *StartingByte; 02800 (ULONGLONG)Ending.QuadPart = (ULONGLONG)Starting.QuadPart + (ULONGLONG)Length->QuadPart - 1; 02801 02802 // 02803 // Now check lock queue 02804 // 02805 02806 LockQueue = &LockInfo->LockQueue; 02807 02808 // 02809 // Grab the waiting lock queue spinlock to exclude anyone from messing 02810 // with the queue while we're using it 02811 // 02812 02813 FsRtlReacquireLockQueue(LockInfo, LockQueue, &OldIrql); 02814 02815 // 02816 // If the range ends below the lowest existing lock, this write is OK. 02817 // 02818 02819 if ( ((ULONGLONG)Ending.QuadPart < (ULONGLONG)LockInfo->LowestLockOffset) ) { 02820 02821 DebugTrace(0, Dbg, "FsRtlFastCheckLockForWrite (below lowest lock)\n", 0); 02822 02823 FsRtlReleaseLockQueue(LockQueue, OldIrql); 02824 return TRUE; 02825 } 02826 02827 // 02828 // If the caller just locked this range exclusively, he can write it. 02829 // 02830 02831 LastLock = (PFILE_LOCK_INFO)((PFILE_OBJECT)FileObject)->LastLock; 02832 if ((LastLock != NULL) && 02833 ((ULONGLONG)Starting.QuadPart >= (ULONGLONG)LastLock->StartingByte.QuadPart) && 02834 ((ULONGLONG)Ending.QuadPart <= (ULONGLONG)LastLock->EndingByte.QuadPart) && 02835 (LastLock->Key == Key) && 02836 (LastLock->ProcessId == ProcessId) && 02837 LastLock->ExclusiveLock) { 02838 02839 FsRtlReleaseLockQueue(LockQueue, OldIrql); 02840 return TRUE; 02841 } 02842 02843 // 02844 // Check the shared locks for overlap. Any overlap in the shared locks is fatal. 02845 // 02846 02847 Status = FsRtlCheckNoSharedConflict(LockQueue, &Starting, &Ending); 02848 02849 if (Status == TRUE) { 02850 02851 // 02852 // No overlap in the shared locks, so check the exclusive locks for overlap. 02853 // 02854 02855 Status = FsRtlCheckNoExclusiveConflict(LockQueue, &Starting, &Ending, Key, FileObject, ProcessId); 02856 } 02857 02858 FsRtlReleaseLockQueue(LockQueue, OldIrql); 02859 02860 return Status; 02861 }

NTSTATUS FsRtlFastUnlockAll IN PFILE_LOCK  FileLock,
IN PFILE_OBJECT  FileObject,
IN PEPROCESS  ProcessId,
IN PVOID Context  OPTIONAL
 

Definition at line 3770 of file filelock.c.

References FALSE, and FsRtlPrivateFastUnlockAll().

Referenced by FsRtlProcessFileLock(), UdfCommonCleanup(), and UdfFastUnlockAll().

03779 : 03780 03781 This routine performs an Unlock all operation on the current locks 03782 associated with the specified file lock. Only those locks with 03783 a matching file object and process id are freed. 03784 03785 Arguments: 03786 03787 FileLock - Supplies the file lock being freed. 03788 03789 FileObject - Supplies the file object associated with the file lock 03790 03791 ProcessId - Supplies the Process Id assoicated with the locks to be 03792 freed 03793 03794 Context - Supplies an optional context to use when completing waiting 03795 lock irps. 03796 03797 Return Value: 03798 03799 None 03800 03801 --*/ 03802 03803 { 03804 return FsRtlPrivateFastUnlockAll( 03805 FileLock, 03806 FileObject, 03807 ProcessId, 03808 0, FALSE, // No Key 03809 Context ); 03810 }

NTSTATUS FsRtlFastUnlockAllByKey IN PFILE_LOCK  FileLock,
IN PFILE_OBJECT  FileObject,
IN PEPROCESS  ProcessId,
IN ULONG  Key,
IN PVOID Context  OPTIONAL
 

Definition at line 3814 of file filelock.c.

References FsRtlPrivateFastUnlockAll(), Key, and TRUE.

Referenced by FsRtlProcessFileLock(), and UdfFastUnlockAllByKey().

03824 : 03825 03826 This routine performs an Unlock All by Key operation on the current locks 03827 associated with the specified file lock. Only those locks with 03828 a matching file object, process id, and key are freed. The input Irp 03829 is completed by this procedure 03830 03831 Arguments: 03832 03833 FileLock - Supplies the file lock being freed. 03834 03835 FileObject - Supplies the file object associated with the file lock 03836 03837 ProcessId - Supplies the Process Id assoicated with the locks to be 03838 freed 03839 03840 Key - Supplies the Key to use in this operation 03841 03842 Context - Supplies an optional context to use when completing waiting 03843 lock irps. 03844 03845 Return Value: 03846 03847 NTSTATUS - The return status for the operation. 03848 03849 --*/ 03850 03851 { 03852 return FsRtlPrivateFastUnlockAll( 03853 FileLock, 03854 FileObject, 03855 ProcessId, 03856 Key, TRUE, 03857 Context ); 03858 03859 }

NTSTATUS FsRtlFastUnlockSingle IN PFILE_LOCK  FileLock,
IN PFILE_OBJECT  FileObject,
IN LARGE_INTEGER UNALIGNED *  FileOffset,
IN PLARGE_INTEGER  Length,
IN PEPROCESS  ProcessId,
IN ULONG  Key,
IN PVOID Context  OPTIONAL,
IN BOOLEAN  AlreadySynchronized
 

Definition at line 3241 of file filelock.c.

References FALSE, FsRtlFastUnlockSingleExclusive(), FsRtlFastUnlockSingleShared(), Key, NTSTATUS(), NULL, Status, and TRUE.

Referenced by FsRtlProcessFileLock(), and UdfFastUnlockSingle().

03254 : 03255 03256 This routine performs an Unlock Single operation on the current locks 03257 associated with the specified file lock. Only the lock with a matching 03258 file object, process id, key, and range is freed. 03259 03260 Arguments: 03261 03262 FileLock - Supplies the file lock being freed. 03263 03264 FileObject - Supplies the file object holding the locks 03265 03266 FileOffset - Supplies the offset to be unlocked 03267 03268 Length - Supplies the length in bytes to be unlocked 03269 03270 ProcessId - Supplies the process Id to use in this operation 03271 03272 Key - Supplies the key to use in this operation 03273 03274 Context - Optionally supplies context to use when completing Irps 03275 03276 AlreadySynchronized - Indicates that the caller has already synchronized 03277 access to the file lock so the fields in the file lock and 03278 be updated without further locking, but not the queues. 03279 03280 Return Value: 03281 03282 NTSTATUS - The completion status for this operation 03283 03284 --*/ 03285 03286 { 03287 NTSTATUS Status; 03288 03289 // 03290 // XXX AlreadySynchronized is obsolete. It was apparently added for the dead 03291 // XXX SoloLock code. 03292 // 03293 03294 if (FileLock->LockInformation == NULL) { 03295 03296 // 03297 // Fast exit - no locks are applied 03298 // 03299 03300 return STATUS_RANGE_NOT_LOCKED; 03301 } 03302 03303 Status = FsRtlFastUnlockSingleExclusive( FileLock->LockInformation, 03304 FileObject, 03305 FileOffset, 03306 Length, 03307 ProcessId, 03308 Key, 03309 Context, 03310 FALSE, 03311 TRUE ); 03312 03313 if (Status == STATUS_SUCCESS) { 03314 03315 // 03316 // Found and unlocked in the exclusive tree, so we're done 03317 // 03318 03319 return Status; 03320 } 03321 03322 Status = FsRtlFastUnlockSingleShared( FileLock->LockInformation, 03323 FileObject, 03324 FileOffset, 03325 Length, 03326 ProcessId, 03327 Key, 03328 Context, 03329 FALSE, 03330 TRUE ); 03331 03332 return Status; 03333 }

NTSTATUS FsRtlFastUnlockSingleExclusive IN PLOCK_INFO  LockInfo,
IN PFILE_OBJECT  FileObject,
IN LARGE_INTEGER UNALIGNED *  FileOffset,
IN PLARGE_INTEGER  Length,
IN PEPROCESS  ProcessId,
IN ULONG  Key,
IN PVOID Context  OPTIONAL,
IN BOOLEAN  IgnoreUnlockRoutine,
IN BOOLEAN  CheckForWaiters
 

Definition at line 3589 of file filelock.c.

References Dbg, DebugTrace, _LOCK_QUEUE::ExclusiveLockTree, FsRtlAcquireLockQueue, FsRtlFindFirstOverlappingExclusiveNode(), FsRtlFreeExclusiveLock(), FsRtlPrivateCheckWaitingLocks(), FsRtlPrivateResetLowestLockOffset(), FsRtlReacquireLockQueue, FsRtlReleaseLockQueue, Key, Lock, NULL, PEX_LOCK, PLOCK_QUEUE, RtlDelete(), RtlRealSuccessor(), and _LOCK_QUEUE::WaitingLocks.

Referenced by FsRtlFastUnlockSingle(), and FsRtlPrivateRemoveLock().

03603 : 03604 03605 This routine performs an Unlock Single operation on the exclusive locks 03606 associated with the specified lock data. Only the lock with a matching 03607 file object, process id, key, and range is freed. 03608 03609 Arguments: 03610 03611 LockInfo - Supplies the lock data being operated on 03612 03613 FileObject - Supplies the file object holding the locks 03614 03615 FileOffset - Supplies the offset to be unlocked 03616 03617 Length - Supplies the length in bytes to be unlocked 03618 03619 ProcessId - Supplies the process Id to use in this operation 03620 03621 Key - Supplies the key to use in this operation 03622 03623 Context - Optionally supplies context to use when completing Irps 03624 03625 IgnoreUnlockRoutine - inidicates that the filelock's unlock routine 03626 should not be called on lock removal (for removal of aborted 03627 locks) 03628 03629 CheckForWaiters - If true check for possible waiting locks, caused 03630 by freeing the locked range 03631 03632 Return Value: 03633 03634 NTSTATUS - The completion status for this operation 03635 03636 --*/ 03637 03638 { 03639 KIRQL OldIrql; 03640 PLOCK_QUEUE LockQueue; 03641 PRTL_SPLAY_LINKS SplayLinks; 03642 LARGE_INTEGER EndingOffset; 03643 PEX_LOCK Lock; 03644 LARGE_INTEGER AlignedFileOffset; 03645 03646 // 03647 // General case - search the outstanding lock queue for this lock 03648 // 03649 03650 AlignedFileOffset = *FileOffset; 03651 03652 LockQueue = &LockInfo->LockQueue; 03653 03654 FsRtlAcquireLockQueue(LockQueue, &OldIrql); 03655 03656 // 03657 // Check for the no locks currently held 03658 // 03659 03660 if (LockQueue->ExclusiveLockTree == NULL) { 03661 03662 FsRtlReleaseLockQueue( LockQueue, OldIrql ); 03663 03664 return STATUS_RANGE_NOT_LOCKED; 03665 } 03666 03667 // 03668 // Find the overlapping lock, if it exists. Note that this is usually 03669 // the only lock we need to check since we are assuming this is an 03670 // existing lock. However, if the lock is a zero length lock we will 03671 // have a run of locks to check. 03672 // 03673 03674 EndingOffset.QuadPart = (ULONGLONG)AlignedFileOffset.QuadPart + (ULONGLONG)Length->QuadPart - 1; 03675 03676 for (SplayLinks = FsRtlFindFirstOverlappingExclusiveNode( LockQueue->ExclusiveLockTree, 03677 &AlignedFileOffset, 03678 &EndingOffset, 03679 NULL, 03680 NULL ); 03681 SplayLinks; 03682 SplayLinks = RtlRealSuccessor(SplayLinks)) { 03683 03684 Lock = CONTAINING_RECORD( SplayLinks, EX_LOCK, Links ); 03685 03686 if ((Lock->LockInfo.FileObject == FileObject) && 03687 (Lock->LockInfo.ProcessId == ProcessId) && 03688 (Lock->LockInfo.Key == Key) && 03689 ((ULONGLONG)Lock->LockInfo.StartingByte.QuadPart == (ULONGLONG)AlignedFileOffset.QuadPart) && 03690 ((ULONGLONG)Lock->LockInfo.Length.QuadPart == (ULONGLONG)Length->QuadPart)) { 03691 03692 DebugTrace(0, Dbg, "Ex Found one to unlock\n", 0); 03693 03694 // 03695 // We have an exact match so now is the time to delete this 03696 // lock. Remove the lock from the list, then call the 03697 // optional unlock routine, then delete the lock. 03698 // 03699 03700 if (FileObject->LastLock == &Lock->LockInfo) { 03701 03702 FileObject->LastLock = NULL; 03703 } 03704 03705 // 03706 // Snip the deleted lock 03707 // 03708 03709 LockQueue->ExclusiveLockTree = RtlDelete(&Lock->Links); 03710 03711 if (LockInfo->LowestLockOffset != 0xffffffff && 03712 LockInfo->LowestLockOffset == Lock->LockInfo.StartingByte.LowPart) { 03713 03714 // 03715 // This was the lowest lock in the tree, so reset the lowest lock 03716 // offset 03717 // 03718 03719 FsRtlPrivateResetLowestLockOffset(LockInfo); 03720 } 03721 03722 if (!IgnoreUnlockRoutine && LockInfo->UnlockRoutine != NULL) { 03723 03724 FsRtlReleaseLockQueue( LockQueue, OldIrql ); 03725 03726 LockInfo->UnlockRoutine( Context, &Lock->LockInfo ); 03727 03728 FsRtlReacquireLockQueue( LockInfo, LockQueue, &OldIrql ); 03729 03730 } 03731 03732 FsRtlFreeExclusiveLock( Lock ); 03733 03734 // 03735 // See if there are additional waiting locks that we can 03736 // now release. 03737 // 03738 03739 if (CheckForWaiters && LockQueue->WaitingLocks.Next) { 03740 03741 FsRtlPrivateCheckWaitingLocks( LockInfo, LockQueue, OldIrql ); 03742 } 03743 03744 FsRtlReleaseLockQueue( LockQueue, OldIrql ); 03745 03746 return STATUS_SUCCESS; 03747 } 03748 03749 if ((ULONGLONG)Lock->LockInfo.StartingByte.QuadPart > (ULONGLONG)AlignedFileOffset.QuadPart) { 03750 03751 // 03752 // The current lock begins at a byte offset greater than the range we are seeking 03753 // to unlock. This range must therefore not be locked. 03754 // 03755 03756 break; 03757 } 03758 } 03759 03760 // 03761 // Lock was not found, return to our caller 03762 // 03763 03764 FsRtlReleaseLockQueue(LockQueue, OldIrql); 03765 return STATUS_RANGE_NOT_LOCKED; 03766 }

NTSTATUS FsRtlFastUnlockSingleShared IN PLOCK_INFO  LockInfo,
IN PFILE_OBJECT  FileObject,
IN LARGE_INTEGER UNALIGNED *  FileOffset,
IN PLARGE_INTEGER  Length,
IN PEPROCESS  ProcessId,
IN ULONG  Key,
IN PVOID Context  OPTIONAL,
IN BOOLEAN  IgnoreUnlockRoutine,
IN BOOLEAN  CheckForWaiters
 

Definition at line 3337 of file filelock.c.

References Dbg, DebugTrace, FsRtlAcquireLockQueue, FsRtlFindFirstOverlappingSharedNode(), FsRtlFreeLockTreeNode(), FsRtlFreeSharedLock(), FsRtlPrivateCheckWaitingLocks(), FsRtlPrivateResetLowestLockOffset(), FsRtlReacquireLockQueue, FsRtlReleaseLockQueue, FsRtlSplitLocks(), Key, Lock, _LOCKTREE_NODE::Locks, NULL, PLOCK_QUEUE, PLOCKTREE_NODE, PSH_LOCK, RtlDelete(), _LOCK_QUEUE::SharedLockTree, _LOCKTREE_NODE::Tail, and _LOCK_QUEUE::WaitingLocks.

Referenced by FsRtlFastUnlockSingle(), and FsRtlPrivateRemoveLock().

03351 : 03352 03353 This routine performs an Unlock Single operation on the current locks 03354 associated with the specified file lock. Only the lock with a matching 03355 file object, process id, key, and range is freed. 03356 03357 Arguments: 03358 03359 LockInfo - Supplies the lock data being operated on 03360 03361 FileObject - Supplies the file object holding the locks 03362 03363 FileOffset - Supplies the offset to be unlocked 03364 03365 Length - Supplies the length in bytes to be unlocked 03366 03367 ProcessId - Supplies the process Id to use in this operation 03368 03369 Key - Supplies the key to use in this operation 03370 03371 Context - Optionally supplies context to use when completing Irps 03372 03373 IgnoreUnlockRoutine - inidicates that the filelock's unlock routine 03374 should not be called on lock removal (for removal of aborted 03375 locks) 03376 03377 CheckForWaiters - If true check for possible waiting locks, caused 03378 by freeing the locked range 03379 03380 Return Value: 03381 03382 NTSTATUS - The completion status for this operation 03383 03384 --*/ 03385 03386 { 03387 PSINGLE_LIST_ENTRY *pLink, Link; 03388 KIRQL OldIrql; 03389 03390 PLOCK_QUEUE LockQueue; 03391 PRTL_SPLAY_LINKS SplayLinks; 03392 LARGE_INTEGER EndingOffset, MaxOffset; 03393 PLOCKTREE_NODE Node; 03394 LARGE_INTEGER AlignedFileOffset; 03395 03396 // 03397 // General case - search the outstanding lock queue for this lock 03398 // 03399 03400 AlignedFileOffset = *FileOffset; 03401 03402 LockQueue = &LockInfo->LockQueue; 03403 03404 FsRtlAcquireLockQueue(LockQueue, &OldIrql); 03405 03406 // 03407 // Check for the no locks currently held 03408 // 03409 03410 if (LockQueue->SharedLockTree == NULL) { 03411 03412 FsRtlReleaseLockQueue( LockQueue, OldIrql ); 03413 03414 return STATUS_RANGE_NOT_LOCKED; 03415 } 03416 03417 // 03418 // Find the overlapping node, if it exists, to search. Note that 03419 // we don't have to go through more than one node in the tree 03420 // since we are assuming this is an existing lock. 03421 // 03422 03423 EndingOffset.QuadPart = (ULONGLONG)AlignedFileOffset.QuadPart + (ULONGLONG)Length->QuadPart - 1; 03424 03425 SplayLinks = FsRtlFindFirstOverlappingSharedNode( LockQueue->SharedLockTree, 03426 &AlignedFileOffset, 03427 &EndingOffset, 03428 NULL, 03429 NULL ); 03430 03431 if (SplayLinks == NULL) { 03432 03433 // 03434 // No node in the tree overlaps this range, so we're done 03435 // 03436 03437 FsRtlReleaseLockQueue(LockQueue, OldIrql); 03438 03439 return STATUS_RANGE_NOT_LOCKED; 03440 } 03441 03442 Node = CONTAINING_RECORD( SplayLinks, LOCKTREE_NODE, Links ); 03443 MaxOffset.QuadPart = 0; 03444 03445 for (pLink = &Node->Locks.Next; 03446 (Link = *pLink) != NULL; 03447 pLink = &Link->Next) { 03448 03449 PSH_LOCK Lock; 03450 03451 Lock = CONTAINING_RECORD( Link, SH_LOCK, Link ); 03452 03453 DebugTrace(0, Dbg, "Sh Top of Loop, Lock = %08lx\n", Lock ); 03454 03455 if ((Lock->LockInfo.FileObject == FileObject) && 03456 (Lock->LockInfo.ProcessId == ProcessId) && 03457 (Lock->LockInfo.Key == Key) && 03458 ((ULONGLONG)Lock->LockInfo.StartingByte.QuadPart == (ULONGLONG)AlignedFileOffset.QuadPart) && 03459 ((ULONGLONG)Lock->LockInfo.Length.QuadPart == (ULONGLONG)Length->QuadPart)) { 03460 03461 DebugTrace(0, Dbg, "Sh Found one to unlock\n", 0); 03462 03463 // 03464 // We have an exact match so now is the time to delete this 03465 // lock. Remove the lock from the list, then call the 03466 // optional unlock routine, then delete the lock. 03467 // 03468 03469 if (FileObject->LastLock == &Lock->LockInfo) { 03470 03471 FileObject->LastLock = NULL; 03472 } 03473 03474 if (*pLink == Node->Tail.Next) { 03475 03476 // 03477 // Deleting the tail node of the list. Safe even if deleting the 03478 // first node since this implies we're also deleting the last node 03479 // in the node which means we'll delete the node ... 03480 // 03481 03482 Node->Tail.Next = CONTAINING_RECORD( pLink, SINGLE_LIST_ENTRY, Next ); 03483 } 03484 03485 // 03486 // Snip the deleted lock 03487 // 03488 03489 *pLink = Link->Next; 03490 03491 if (pLink == &Node->Locks.Next) { 03492 03493 // 03494 // Deleted first lock in node 03495 // 03496 03497 if (Node->Locks.Next == NULL) { 03498 03499 // 03500 // Just deleted last lock on this node, so free it 03501 // 03502 03503 LockQueue->SharedLockTree = RtlDelete(SplayLinks); 03504 03505 FsRtlFreeLockTreeNode(Node); 03506 03507 Node = NULL; 03508 } 03509 03510 if (LockInfo->LowestLockOffset != 0xffffffff && 03511 LockInfo->LowestLockOffset == Lock->LockInfo.StartingByte.LowPart) { 03512 03513 // 03514 // This was the lowest lock in the trees, reset the lowest lock offset 03515 // 03516 03517 FsRtlPrivateResetLowestLockOffset(LockInfo); 03518 } 03519 } 03520 03521 // 03522 // Now the fun begins. It may be the case that the lock just snipped from 03523 // the chain was gluing locks at this node together, so we need to 03524 // inspect the chain. 03525 // 03526 03527 if (Node) { 03528 03529 FsRtlSplitLocks(Node, pLink, &Lock->LockInfo.EndingByte, &MaxOffset); 03530 } 03531 03532 if (!IgnoreUnlockRoutine && LockInfo->UnlockRoutine != NULL) { 03533 03534 FsRtlReleaseLockQueue( LockQueue, OldIrql ); 03535 03536 LockInfo->UnlockRoutine( Context, &Lock->LockInfo ); 03537 03538 FsRtlReacquireLockQueue( LockInfo, LockQueue, &OldIrql ); 03539 03540 } 03541 03542 FsRtlFreeSharedLock( Lock ); 03543 03544 // 03545 // See if there are additional waiting locks that we can 03546 // now release. 03547 // 03548 03549 if (CheckForWaiters && LockQueue->WaitingLocks.Next) { 03550 03551 FsRtlPrivateCheckWaitingLocks( LockInfo, LockQueue, OldIrql ); 03552 } 03553 03554 FsRtlReleaseLockQueue( LockQueue, OldIrql ); 03555 03556 return STATUS_SUCCESS; 03557 } 03558 03559 if ((ULONGLONG)Lock->LockInfo.StartingByte.QuadPart > (ULONGLONG)AlignedFileOffset.QuadPart) { 03560 03561 // 03562 // The current lock begins at a byte offset greater than the range we are seeking 03563 // to unlock. This range must therefore not be locked. 03564 // 03565 03566 break; 03567 } 03568 03569 if ((ULONGLONG)MaxOffset.QuadPart < (ULONGLONG)Lock->LockInfo.EndingByte.QuadPart) { 03570 03571 // 03572 // Maintain the maximum offset affected by locks up to this point. 03573 // 03574 03575 MaxOffset.QuadPart = Lock->LockInfo.EndingByte.QuadPart; 03576 } 03577 } 03578 03579 // 03580 // Lock was not found, return to our caller 03581 // 03582 03583 FsRtlReleaseLockQueue(LockQueue, OldIrql); 03584 return STATUS_RANGE_NOT_LOCKED; 03585 }

PSH_LOCK FsRtlFindFirstOverlapInNode IN PLOCKTREE_NODE  Node,
IN PLARGE_INTEGER  StartingByte,
IN PLARGE_INTEGER  EndingByte
 

Definition at line 1856 of file filelock.c.

References ASSERT, FALSE, Lock, NULL, and PSH_LOCK.

Referenced by FsRtlCheckNoSharedConflict(), and FsRtlPrivateCheckForExclusiveLockAccess().

01864 : 01865 01866 This routine examines a shared lock node, usually a node which is known to be composed 01867 of several non-overlapping lock segments (holey), for true overlap with the indicated 01868 range. This is not handled in the normal overlap check (..FindFirstOverlappingSharedLock) 01869 since the needs for holey checks are rather different than the full node check. 01870 01871 Arguments: 01872 01873 Node - the lock tree node to be examined for overlap 01874 01875 StartingByte - supplies the first byte offset of the range to check 01876 01877 EndingByte - supplies the last byte offset of the range to check 01878 01879 Return Value: 01880 01881 PSH_LOCK - the first lock which overlaps with the specified range. 01882 01883 --*/ 01884 { 01885 PSH_LOCK Lock; 01886 PSINGLE_LIST_ENTRY Link; 01887 01888 for (Link = Node->Locks.Next; 01889 Link; 01890 Link = Link->Next) { 01891 01892 Lock = CONTAINING_RECORD( Link, SH_LOCK, Link ); 01893 01894 // 01895 // Logic is the same as above checkers. If the ending byte of the lock is less than the 01896 // starting byte of the range, OR we have the weird [0, 0) case, then the lock is almost 01897 // certainly less than the range. 01898 // 01899 01900 if ((ULONGLONG)Lock->LockInfo.EndingByte.QuadPart < (ULONGLONG)StartingByte->QuadPart || 01901 (Lock->LockInfo.StartingByte.QuadPart == 0 && Lock->LockInfo.Length.QuadPart == 0)) { 01902 01903 // 01904 // ... except if the lock and range are equivalent, in which case we have discovered 01905 // zero lock/range overlap. 01906 // 01907 01908 if ((ULONGLONG)Lock->LockInfo.EndingByte.QuadPart == (ULONGLONG)EndingByte->QuadPart && 01909 (ULONGLONG)Lock->LockInfo.StartingByte.QuadPart == (ULONGLONG)StartingByte->QuadPart) { 01910 01911 return Lock; 01912 } 01913 01914 // 01915 // Look forward in the node. 01916 // 01917 01918 continue; 01919 } 01920 01921 // 01922 // No overlap at all if the lock begins at a higher byte than the last of the range. 01923 // We already covered zero length locks (where this is true, and overlap could still 01924 // occur). 01925 // 01926 01927 if ((ULONGLONG)Lock->LockInfo.StartingByte.QuadPart > (ULONGLONG)EndingByte->QuadPart) { 01928 01929 return NULL; 01930 } 01931 01932 // 01933 // Regular overlap has occured. Return this lock. 01934 // 01935 01936 return Lock; 01937 } 01938 01939 // 01940 // If we invoke this check and wander off the end of the node without determining what is 01941 // going on, something is terribly wrong. 01942 // 01943 01944 ASSERT( FALSE ); 01945 01946 return NULL; 01947 }

PRTL_SPLAY_LINKS FsRtlFindFirstOverlappingExclusiveNode IN PRTL_SPLAY_LINKS  Tree,
IN PLARGE_INTEGER  StartingByte,
IN PLARGE_INTEGER  EndingByte,
IN OUT PRTL_SPLAY_LINKS *  LastEdgeNode,
IN OUT PBOOLEAN  GreaterThan
 

Definition at line 1687 of file filelock.c.

References FALSE, GreaterThan, Lock, NULL, PEX_LOCK, and TRUE.

Referenced by FsRtlCheckNoExclusiveConflict(), FsRtlFastUnlockSingleExclusive(), FsRtlGetNextFileLock(), FsRtlPrivateCheckForExclusiveLockAccess(), FsRtlPrivateCheckForSharedLockAccess(), and FsRtlPrivateInsertExclusiveLock().

01696 : 01697 01698 This routine returns the first node in the exclusive lock tree which 01699 overlaps with the range given. No nodes given by RtlRealPredecessor() 01700 on the result overlap the range. 01701 01702 Arguments: 01703 01704 Tree - supplies the splay links of the root node of the exclusive tree 01705 to search 01706 01707 StartingByte - supplies the first byte offset of the range to check 01708 01709 EndingByte - supplies the last byte offset of the range to check 01710 01711 LastEdgeNode - optional, will be set to the last node searched 01712 not including returned node (presumeably where a new node will 01713 be inserted if return is NULL). 01714 01715 GreaterThan - optional, set according to whether LastEdgeNode is covering 01716 a range greater than the queried range. !GreaterThan == LessThan, since 01717 we would have returned this node in the "Equals" (overlap) case. 01718 01719 Return Value: 01720 01721 The splay links of the node, if such a node exists, NULL otherwise 01722 01723 --*/ 01724 { 01725 PRTL_SPLAY_LINKS SplayLinks; 01726 PEX_LOCK Lock, LastOverlapNode; 01727 01728 if (LastEdgeNode) *LastEdgeNode = NULL; 01729 if (GreaterThan) *GreaterThan = FALSE; 01730 01731 LastOverlapNode = NULL; 01732 SplayLinks = Tree; 01733 01734 while (SplayLinks) { 01735 01736 Lock = CONTAINING_RECORD( SplayLinks, EX_LOCK, Links ); 01737 01738 // 01739 // We may have to go right in the tree if this lock covers a range before the start of this 01740 // range we are looking for overlap on or this lock is [0, 0). This is important since a lock 01741 // on [0, 0) will look like the extent is from [0, ~0], which is the only case where the zero 01742 // length lock relation of End < Start does not hold. 01743 // 01744 01745 if ((ULONGLONG)Lock->LockInfo.EndingByte.QuadPart < (ULONGLONG)StartingByte->QuadPart || 01746 (Lock->LockInfo.StartingByte.QuadPart == 0 && Lock->LockInfo.Length.QuadPart == 0)) { 01747 01748 if ((ULONGLONG)Lock->LockInfo.EndingByte.QuadPart == (ULONGLONG)EndingByte->QuadPart && 01749 (ULONGLONG)Lock->LockInfo.StartingByte.QuadPart == (ULONGLONG)StartingByte->QuadPart) { 01750 01751 // 01752 // The extent of the lock is less than the starting position of the 01753 // range we are checking and the lock is equal to the range, which 01754 // implies that the range and the lock are zero length. 01755 // 01756 // This is a zero length lock node and we are searching for zero 01757 // length overlap. Since the exclusive tree is one lock per node, 01758 // we are in the potential middle of a run of zero length locks in 01759 // the tree. Go left to find the first zero length lock. 01760 // 01761 // This is actually the same logic we'd use for equivalent locks, 01762 // but the only time that can happen in this tree is for zero length 01763 // locks. 01764 // 01765 01766 LastOverlapNode = Lock; 01767 01768 if (LastEdgeNode) *LastEdgeNode = SplayLinks; 01769 if (GreaterThan) *GreaterThan = FALSE; 01770 01771 SplayLinks = RtlLeftChild(SplayLinks); 01772 continue; 01773 } 01774 01775 // 01776 // This lock is strictly less than this byterange, so go 01777 // right in the tree. 01778 // 01779 01780 if (LastEdgeNode) *LastEdgeNode = SplayLinks; 01781 if (GreaterThan) *GreaterThan = FALSE; 01782 01783 SplayLinks = RtlRightChild(SplayLinks); 01784 continue; 01785 } 01786 01787 if ((ULONGLONG)Lock->LockInfo.StartingByte.QuadPart <= (ULONGLONG)EndingByte->QuadPart) { 01788 01789 // 01790 // We have an overlap, but we need to see if the byterange starts 01791 // before this node so that there is the guarantee that we start 01792 // the search at the correct point. There may be still be predecessor 01793 // nodes covering the byterange. 01794 // 01795 01796 if ((ULONGLONG)Lock->LockInfo.StartingByte.QuadPart <= (ULONGLONG)StartingByte->QuadPart) { 01797 01798 // 01799 // This node begins at a byte offset prior to the byterange we 01800 // are checking, so it must be the correct starting position. 01801 // 01802 01803 break; 01804 } 01805 01806 // 01807 // Drop a marker at this node so that we can come back if it turns out 01808 // that the left subtree does not cover the range of bytes before this 01809 // node in the byterange. 01810 // 01811 01812 LastOverlapNode = Lock; 01813 } 01814 01815 // 01816 // It must now be the case this lock is strictly greater than the byterange, 01817 // or we have the candidate overlap case above, so go left in the tree. 01818 // 01819 01820 if (LastEdgeNode) *LastEdgeNode = SplayLinks; 01821 if (GreaterThan) *GreaterThan = TRUE; 01822 01823 SplayLinks = RtlLeftChild(SplayLinks); 01824 } 01825 01826 if (SplayLinks == NULL) { 01827 01828 // 01829 // We hit the edge of the tree. If the LastOverlapNode is set, it means that 01830 // we had kept searching left in the tree for a node that covered the starting 01831 // byte of the byterange, but didn't find it. If it isn't set, we'll do the 01832 // right thing anyway since Node <- NULL. 01833 // 01834 01835 Lock = LastOverlapNode; 01836 } 01837 01838 if (Lock == NULL) { 01839 01840 // 01841 // No overlapping lock existed 01842 // 01843 01844 return NULL; 01845 } 01846 01847 // 01848 // Return the splay links of the first overlapping lock 01849 // 01850 01851 return &Lock->Links; 01852 }

PRTL_SPLAY_LINKS FsRtlFindFirstOverlappingSharedNode IN PRTL_SPLAY_LINKS  Tree,
IN PLARGE_INTEGER  StartingByte,
IN PLARGE_INTEGER  EndingByte,
IN OUT PRTL_SPLAY_LINKS *  LastEdgeNode,
IN OUT PBOOLEAN  GreaterThan
 

Definition at line 1517 of file filelock.c.

References _LOCKTREE_NODE::Extent, FALSE, GreaterThan, _LOCKTREE_NODE::Links, Lock, _LOCKTREE_NODE::Locks, NULL, PLOCKTREE_NODE, PSH_LOCK, and TRUE.

Referenced by FsRtlCheckNoSharedConflict(), FsRtlFastUnlockSingleShared(), FsRtlGetNextFileLock(), FsRtlPrivateCheckForExclusiveLockAccess(), and FsRtlPrivateInsertSharedLock().

01526 : 01527 01528 This routine returns the first node in the shared lock tree which 01529 overlaps with the range given. No nodes given by RtlRealPredecessor() 01530 on the result overlap the range. 01531 01532 Arguments: 01533 01534 Tree - supplies the splay links of the root node of the shared tree 01535 to search 01536 01537 StartingByte - supplies the first byte offset of the range to check 01538 01539 EndingByte - supplies the last byte offset of the range to check 01540 01541 LastEdgeNode - optional, will be set to the last node searched in the 01542 not including returned node (presumeably where a new node will 01543 be inserted if return is NULL). 01544 01545 GreaterThan - optional, set according to whether LastEdgeNode is covering 01546 a range greater than the queried range. !GreaterThan == LessThan, since 01547 we would have returned this node in the "Equals" (overlap) case. 01548 01549 Return Value: 01550 01551 The splay links of the node, if such a node exists, NULL otherwise 01552 01553 --*/ 01554 { 01555 PLOCKTREE_NODE Node, LastOverlapNode; 01556 PRTL_SPLAY_LINKS SplayLinks; 01557 PSH_LOCK Lock; 01558 01559 if (LastEdgeNode) *LastEdgeNode = NULL; 01560 if (GreaterThan) *GreaterThan = FALSE; 01561 01562 LastOverlapNode = NULL; 01563 SplayLinks = Tree; 01564 01565 while (SplayLinks) { 01566 01567 Node = CONTAINING_RECORD( SplayLinks, LOCKTREE_NODE, Links ); 01568 01569 // 01570 // Pull up the first lock on the chain at this node to check 01571 // the starting byte offset of locks at this node 01572 // 01573 01574 Lock = CONTAINING_RECORD( Node->Locks.Next, SH_LOCK, Link ); 01575 01576 // 01577 // We may have to go right in the tree if this lock covers a range before the start of this 01578 // range we are looking for overlap on or this lock is [0, 0). This is important since a lock 01579 // on [0, 0) will look like the extent is from [0, ~0], which is the only case where the zero 01580 // length lock relation of End < Start does not hold. 01581 // 01582 01583 if (Node->Extent < (ULONGLONG)StartingByte->QuadPart || 01584 (Lock->LockInfo.StartingByte.QuadPart == 0 && Lock->LockInfo.Length.QuadPart == 0)) { 01585 01586 if ((ULONGLONG)Lock->LockInfo.EndingByte.QuadPart == (ULONGLONG)EndingByte->QuadPart && 01587 (ULONGLONG)Lock->LockInfo.StartingByte.QuadPart == (ULONGLONG)StartingByte->QuadPart) { 01588 01589 // 01590 // The extent of the node is less than the starting position of the 01591 // range we are checking and the first lock on this node is equal to 01592 // the range, which implies that the range and the lock are zero 01593 // length. 01594 // 01595 // This is a zero length lock node and we are searching for zero 01596 // length overlap. This makes multiple zero length shared locks 01597 // occupy the same node, which is a win, but makes application of 01598 // zero length exclusive locks check the length of the overlapping 01599 // lock to see if they really conflict. 01600 // 01601 01602 break; 01603 } 01604 01605 // 01606 // All locks at this node are strictly less than this 01607 // byterange, so go right in the tree. 01608 // 01609 01610 if (LastEdgeNode) *LastEdgeNode = SplayLinks; 01611 if (GreaterThan) *GreaterThan = FALSE; 01612 01613 SplayLinks = RtlRightChild(SplayLinks); 01614 continue; 01615 } 01616 01617 if ((ULONGLONG)Lock->LockInfo.StartingByte.QuadPart <= (ULONGLONG)EndingByte->QuadPart) { 01618 01619 // 01620 // We have an overlap, but we need to see if the byterange starts 01621 // before this node so that there is the guarantee that we start 01622 // the search at the correct point. There may be still be predecessor 01623 // nodes covering the byterange. 01624 // 01625 01626 if ((ULONGLONG)Lock->LockInfo.StartingByte.QuadPart <= (ULONGLONG)StartingByte->QuadPart) { 01627 01628 // 01629 // This node begins at a byte offset prior to the byterange we 01630 // are checking, so it must be the correct starting position. 01631 // 01632 01633 break; 01634 } 01635 01636 // 01637 // Drop a marker at this node so that we can come back if it turns out 01638 // that the left subtree does not cover the range of bytes before this 01639 // node in the byterange. 01640 // 01641 01642 LastOverlapNode = Node; 01643 } 01644 01645 // 01646 // It must now be the case that all locks at this node are strictly greater 01647 // than the byterange, or we have the candidate overlap case above, 01648 // so go left in the tree. 01649 // 01650 01651 if (LastEdgeNode) *LastEdgeNode = SplayLinks; 01652 if (GreaterThan) *GreaterThan = TRUE; 01653 01654 SplayLinks = RtlLeftChild(SplayLinks); 01655 } 01656 01657 if (SplayLinks == NULL) { 01658 01659 // 01660 // We hit the edge of the tree. If the LastOverlapNode is set, it means that 01661 // we had kept searching left in the tree for a node that covered the starting 01662 // byte of the byterange, but didn't find it. If it isn't set, we'll do the 01663 // right thing anyway since Node <- NULL. 01664 // 01665 01666 Node = LastOverlapNode; 01667 } 01668 01669 if (Node == NULL) { 01670 01671 // 01672 // No overlapping node existed 01673 // 01674 01675 return NULL; 01676 } 01677 01678 // 01679 // Return the splay links of the first overlapping node 01680 // 01681 01682 return &Node->Links; 01683 }

INLINE VOID FsRtlFreeExclusiveLock IN PEX_LOCK  C  ) 
 

Definition at line 446 of file filelock.c.

References ExFreeToNPagedLookasideList(), and FsRtlExclusiveLockLookasideList.

Referenced by FsRtlFastUnlockSingleExclusive(), FsRtlPrivateFastUnlockAll(), and FsRtlUninitializeFileLock().

00449 { 00450 ExFreeToNPagedLookasideList( &FsRtlExclusiveLockLookasideList, (PVOID)C ); 00451 }

VOID FsRtlFreeFileLock IN PFILE_LOCK  FileLock  ) 
 

Definition at line 1162 of file filelock.c.

References ExFreeToPagedLookasideList(), FsRtlFileLockLookasideList, and FsRtlUninitializeFileLock().

Referenced by UdfDeleteFcb().

01165 { 01166 FsRtlUninitializeFileLock( FileLock ); 01167 01168 ExFreeToPagedLookasideList( &FsRtlFileLockLookasideList, FileLock ); 01169 }

INLINE VOID FsRtlFreeLockInfo IN PLOCK_INFO  C  ) 
 

Definition at line 473 of file filelock.c.

References ExFreeToNPagedLookasideList(), and FsRtlLockInfoLookasideList.

Referenced by FsRtlUninitializeFileLock().

00476 { 00477 ExFreeToNPagedLookasideList( &FsRtlLockInfoLookasideList, (PVOID)C ); 00478 }

INLINE VOID FsRtlFreeLockTreeNode IN PLOCKTREE_NODE  C  ) 
 

Definition at line 464 of file filelock.c.

References ExFreeToNPagedLookasideList(), and FsRtlLockTreeNodeLookasideList.

Referenced by FsRtlFastUnlockSingleShared(), FsRtlPrivateFastUnlockAll(), FsRtlPrivateInsertSharedLock(), and FsRtlUninitializeFileLock().

00467 { 00468 ExFreeToNPagedLookasideList( &FsRtlLockTreeNodeLookasideList, (PVOID)C ); 00469 }

INLINE VOID FsRtlFreeSharedLock IN PSH_LOCK  C  ) 
 

Definition at line 437 of file filelock.c.

References ExFreeToNPagedLookasideList(), and FsRtlSharedLockLookasideList.

Referenced by FsRtlFastUnlockSingleShared(), FsRtlPrivateFastUnlockAll(), and FsRtlUninitializeFileLock().

00440 { 00441 ExFreeToNPagedLookasideList( &FsRtlSharedLockLookasideList, (PVOID)C ); 00442 }

INLINE VOID FsRtlFreeWaitingLock IN PWAITING_LOCK  C  ) 
 

Definition at line 455 of file filelock.c.

References ExFreeToNPagedLookasideList(), and FsRtlWaitingLockLookasideList.

Referenced by FsRtlPrivateCancelFileLockIrp(), FsRtlPrivateCheckWaitingLocks(), FsRtlPrivateFastUnlockAll(), and FsRtlUninitializeFileLock().

00458 { 00459 ExFreeToNPagedLookasideList( &FsRtlWaitingLockLookasideList, (PVOID)C ); 00460 }

PFILE_LOCK_INFO FsRtlGetNextFileLock IN PFILE_LOCK  FileLock,
IN BOOLEAN  Restart
 

Definition at line 1951 of file filelock.c.

References Dbg, DebugTrace, _FILE_LOCK_INFO::EndingByte, _FILE_LOCK_INFO::ExclusiveLock, _LOCK_QUEUE::ExclusiveLockTree, FALSE, _FILE_LOCK_INFO::FileObject, FsRtlAcquireLockQueue, FsRtlFindFirstOverlappingExclusiveNode(), FsRtlFindFirstOverlappingSharedNode(), FsRtlReleaseLockQueue, GreaterThan, _FILE_LOCK_INFO::Key, _FILE_LOCK_INFO::Length, _EX_LOCK::LockInfo, _SH_LOCK::LockInfo, _LOCK_INFO::LockQueue, _LOCKTREE_NODE::Locks, NULL, PEX_LOCK, PLOCK_INFO, PLOCKTREE_NODE, _FILE_LOCK_INFO::ProcessId, PSH_LOCK, RtlRealSuccessor(), _LOCK_QUEUE::SharedLockTree, _FILE_LOCK_INFO::StartingByte, and TRUE.

01958 : 01959 01960 This routine enumerates the individual file locks denoted by the input file lock 01961 variable. It returns a pointer to the file lock information stored for each lock. 01962 The caller is responsible for synchronizing call to this procedure and for not 01963 altering any of the data returned by this procedure. If the caller does not 01964 synchronize the enumeration will not be reliably complete. 01965 01966 The way a programmer will use this procedure to enumerate all of the locks 01967 is as follows: 01968 01969 for (p = FsRtlGetNextFileLock( FileLock, TRUE ); 01970 p != NULL; 01971 p = FsRtlGetNextFileLock( FileLock, FALSE )) { 01972 01973 // Process the lock information referenced by p 01974 } 01975 01976 Order is *not* guaranteed. 01977 01978 Arguments: 01979 01980 FileLock - Supplies the File Lock to enumerate. The current 01981 enumeration state is stored in the file lock variable so if multiple 01982 threads are enumerating the lock at the same time the results will 01983 be unpredictable. 01984 01985 Restart - Indicates if the enumeration is to start at the beginning of the 01986 file lock tree or if we are continuing from a previous call. 01987 01988 Return Value: 01989 01990 PFILE_LOCK_INFO - Either it returns a pointer to the next file lock 01991 record for the input file lock or it returns NULL if there 01992 are not more locks. 01993 01994 --*/ 01995 01996 { 01997 FILE_LOCK_INFO FileLockInfo; 01998 PVOID ContinuationPointer; 01999 PLOCK_INFO LockInfo; 02000 PLOCKTREE_NODE Node; 02001 PSINGLE_LIST_ENTRY Link; 02002 PRTL_SPLAY_LINKS SplayLinks, LastSplayLinks; 02003 PSH_LOCK ShLock; 02004 PEX_LOCK ExLock; 02005 BOOLEAN FoundReturnable, GreaterThan; 02006 KIRQL OldIrql; 02007 02008 DebugTrace(+1, Dbg, "FsRtlGetNextFileLock, FileLock = %08lx\n", FileLock); 02009 02010 if ((LockInfo = (PLOCK_INFO) FileLock->LockInformation) == NULL) { 02011 // 02012 // No lock information on this FileLock 02013 // 02014 02015 return NULL; 02016 } 02017 02018 FoundReturnable = FALSE; 02019 02020 // 02021 // Before getting the spinlock, copy pagable info onto stack 02022 // 02023 02024 FileLockInfo = FileLock->LastReturnedLockInfo; 02025 ContinuationPointer = FileLock->LastReturnedLock; 02026 02027 FsRtlAcquireLockQueue (&LockInfo->LockQueue, &OldIrql); 02028 02029 if (!Restart) { 02030 // 02031 // Given the last returned lock, find its current successor in the tree. 02032 // Previous implementations would reset the enumeration if the last returned 02033 // lock had been removed from the tree but I think we can be better in that 02034 // case since every other structure modifying event (add new locks, delete 02035 // other locks) would *not* have caused the reset. Possible minor performance 02036 // enhancement. 02037 // 02038 02039 // 02040 // Find the node which could contain the last returned lock. We enumerate the 02041 // exclusive lock tree, then the shared lock tree. Find the one we're enumerating. 02042 // 02043 02044 if (FileLockInfo.ExclusiveLock) { 02045 02046 // 02047 // Continue enumeration in the exclusive lock tree 02048 // 02049 02050 ExLock = NULL; 02051 02052 SplayLinks = FsRtlFindFirstOverlappingExclusiveNode( LockInfo->LockQueue.ExclusiveLockTree, 02053 &FileLockInfo.StartingByte, 02054 &FileLockInfo.EndingByte, 02055 &LastSplayLinks, 02056 &GreaterThan ); 02057 02058 if (SplayLinks == NULL) { 02059 02060 // 02061 // No overlapping nodes were found, try to find successor 02062 // 02063 02064 if (GreaterThan) { 02065 02066 // 02067 // Last node looked at was greater than the lock so it is 02068 // the place to pick up the enumeration 02069 // 02070 02071 SplayLinks = LastSplayLinks; 02072 02073 } else { 02074 02075 // 02076 // Last node looked at was less than the lock so grab its successor 02077 // 02078 02079 if (LastSplayLinks) { 02080 02081 SplayLinks = RtlRealSuccessor(LastSplayLinks); 02082 } 02083 } 02084 02085 } else { 02086 02087 // 02088 // Found an overlapping lock, see if it is the last returned 02089 // 02090 02091 for (; 02092 SplayLinks; 02093 SplayLinks = RtlRealSuccessor(SplayLinks)) { 02094 02095 ExLock = CONTAINING_RECORD( SplayLinks, EX_LOCK, Links ); 02096 02097 if (ContinuationPointer == ExLock && 02098 (ULONGLONG)FileLockInfo.StartingByte.QuadPart == (ULONGLONG)ExLock->LockInfo.StartingByte.QuadPart && 02099 (ULONGLONG)FileLockInfo.Length.QuadPart == (ULONGLONG)ExLock->LockInfo.Length.QuadPart && 02100 FileLockInfo.Key == ExLock->LockInfo.Key && 02101 FileLockInfo.FileObject == ExLock->LockInfo.FileObject && 02102 FileLockInfo.ProcessId == ExLock->LockInfo.ProcessId) { 02103 02104 // 02105 // Found last returned, dig up its successor 02106 // 02107 02108 SplayLinks = RtlRealSuccessor(SplayLinks); 02109 02110 // 02111 // Got the node cold, so we're done 02112 // 02113 02114 break; 02115 } 02116 02117 // 02118 // This lock overlapped and was not the last returned. In fact, since this lock would 02119 // have conflicted with the last returned we know it could not have been returned 02120 // before, so this should be returned to the caller. 02121 // 02122 // However, if it is a zero length lock we are looking for and a zero length lock we hit, 02123 // we are at the beginning of a run we need to inspect. If we cannot find the last lock 02124 // we returned, resume the enumeration at the beginning of the run. 02125 // 02126 02127 if (ExLock->LockInfo.Length.QuadPart != 0 || FileLockInfo.Length.QuadPart != 0) { 02128 02129 break; 02130 } 02131 02132 // 02133 // Keep wandering down the run 02134 // 02135 } 02136 } 02137 02138 // 02139 // Were we able to find a lock to return? 02140 // 02141 02142 if (SplayLinks == NULL) { 02143 02144 // 02145 // There aren't any more exclusive locks, fall over to the shared tree 02146 // 02147 02148 SplayLinks = LockInfo->LockQueue.SharedLockTree; 02149 02150 if (SplayLinks) { 02151 02152 while (RtlLeftChild(SplayLinks)) { 02153 02154 SplayLinks = RtlLeftChild(SplayLinks); 02155 } 02156 02157 Node = CONTAINING_RECORD(SplayLinks, LOCKTREE_NODE, Links); 02158 ShLock = CONTAINING_RECORD(Node->Locks.Next, SH_LOCK, Link); 02159 02160 FileLockInfo = ShLock->LockInfo; 02161 ContinuationPointer = ShLock; 02162 FoundReturnable = TRUE; 02163 } 02164 02165 } else { 02166 02167 // 02168 // This is the lock to return 02169 // 02170 02171 ExLock = CONTAINING_RECORD( SplayLinks, EX_LOCK, Links ); 02172 02173 FileLockInfo = ExLock->LockInfo; 02174 ContinuationPointer = ExLock; 02175 FoundReturnable = TRUE; 02176 } 02177 02178 } else { 02179 02180 // 02181 // Continue enumeration in the shared lock tree 02182 // 02183 02184 Node = NULL; 02185 02186 SplayLinks = FsRtlFindFirstOverlappingSharedNode( LockInfo->LockQueue.SharedLockTree, 02187 &FileLockInfo.StartingByte, 02188 &FileLockInfo.EndingByte, 02189 &LastSplayLinks, 02190 &GreaterThan ); 02191 02192 if (SplayLinks == NULL) { 02193 02194 // 02195 // No overlapping nodes were found 02196 // 02197 02198 if (GreaterThan) { 02199 02200 // 02201 // Last node looked at was greater than the lock so it is 02202 // the place to pick up the enumeration 02203 // 02204 02205 if (LastSplayLinks) { 02206 02207 SplayLinks = LastSplayLinks; 02208 Node = CONTAINING_RECORD( LastSplayLinks, LOCKTREE_NODE, Links ); 02209 } 02210 02211 } else { 02212 02213 // 02214 // Last node looked at was less than the lock so grab its successor 02215 // 02216 02217 if (LastSplayLinks) { 02218 02219 SplayLinks = RtlRealSuccessor(LastSplayLinks); 02220 02221 if (SplayLinks) { 02222 02223 Node = CONTAINING_RECORD( SplayLinks, LOCKTREE_NODE, Links ); 02224 } 02225 } 02226 } 02227 02228 } else { 02229 02230 // 02231 // Grab the node we found 02232 // 02233 02234 Node = CONTAINING_RECORD( SplayLinks, LOCKTREE_NODE, Links ); 02235 } 02236 02237 // 02238 // If we have a node to look at, it may still not contain the the last returned lock 02239 // if this isn't synchronized. 02240 // 02241 02242 if (Node != NULL) { 02243 02244 // 02245 // Walk down the locks at this node looking for the last returned lock 02246 // 02247 02248 for (Link = Node->Locks.Next; 02249 Link; 02250 Link = Link->Next) { 02251 02252 // 02253 // Get a pointer to the current lock record 02254 // 02255 02256 ShLock = CONTAINING_RECORD( Link, SH_LOCK, Link ); 02257 02258 // 02259 // See if it's a match 02260 // 02261 02262 if (ContinuationPointer == ShLock && 02263 (ULONGLONG)FileLockInfo.StartingByte.QuadPart == (ULONGLONG)ShLock->LockInfo.StartingByte.QuadPart && 02264 (ULONGLONG)FileLockInfo.Length.QuadPart == (ULONGLONG)ShLock->LockInfo.Length.QuadPart && 02265 FileLockInfo.Key == ShLock->LockInfo.Key && 02266 FileLockInfo.FileObject == ShLock->LockInfo.FileObject && 02267 FileLockInfo.ProcessId == ShLock->LockInfo.ProcessId) { 02268 02269 Link = Link->Next; 02270 break; 02271 } 02272 02273 // 02274 // See if we passed by its slot 02275 // 02276 02277 if ((ULONGLONG)FileLockInfo.StartingByte.QuadPart < (ULONGLONG)ShLock->LockInfo.StartingByte.QuadPart) { 02278 02279 break; 02280 } 02281 } 02282 02283 if (Link == NULL) { 02284 02285 // 02286 // This node doesn't contain the successor, so move 02287 // up to the successor node in the tree and return the 02288 // first lock. If we're actually at the end of the tree 02289 // we just fall off the end correctly. 02290 // 02291 02292 SplayLinks = RtlRealSuccessor(SplayLinks); 02293 02294 if (SplayLinks) { 02295 02296 Node = CONTAINING_RECORD( SplayLinks, LOCKTREE_NODE, Links ); 02297 02298 Link = Node->Locks.Next; 02299 } 02300 } 02301 02302 if (Link) { 02303 02304 // 02305 // Found a Lock to return, copy it to the stack 02306 // 02307 02308 ShLock = CONTAINING_RECORD( Link, SH_LOCK, Link ); 02309 02310 FileLockInfo = ShLock->LockInfo; 02311 ContinuationPointer = ShLock; 02312 FoundReturnable = TRUE; 02313 } 02314 02315 } 02316 } 02317 02318 } else { 02319 02320 // 02321 // Restarting the enumeration. Find leftmost node in the exclusive tree and hand back 02322 // the first lock, falling over to the shared if no exlcusive locks are applied 02323 // 02324 02325 if (LockInfo->LockQueue.ExclusiveLockTree) { 02326 02327 SplayLinks = LockInfo->LockQueue.ExclusiveLockTree; 02328 02329 while (RtlLeftChild(SplayLinks) != NULL) { 02330 02331 SplayLinks = RtlLeftChild(SplayLinks); 02332 } 02333 02334 ExLock = CONTAINING_RECORD( SplayLinks, EX_LOCK, Links ); 02335 02336 FileLockInfo = ExLock->LockInfo; 02337 ContinuationPointer = ExLock; 02338 FoundReturnable = TRUE; 02339 02340 } else { 02341 02342 if (LockInfo->LockQueue.SharedLockTree) { 02343 02344 SplayLinks = LockInfo->LockQueue.SharedLockTree; 02345 02346 while (RtlLeftChild(SplayLinks) != NULL) { 02347 02348 SplayLinks = RtlLeftChild(SplayLinks); 02349 } 02350 02351 Node = CONTAINING_RECORD( SplayLinks, LOCKTREE_NODE, Links ); 02352 ShLock = CONTAINING_RECORD( Node->Locks.Next, SH_LOCK, Link ); 02353 02354 FileLockInfo = ShLock->LockInfo; 02355 ContinuationPointer = ShLock; 02356 FoundReturnable = TRUE; 02357 } 02358 } 02359 } 02360 02361 // 02362 // Release all the lock queues 02363 // 02364 02365 FsRtlReleaseLockQueue (&LockInfo->LockQueue, OldIrql); 02366 02367 if (!FoundReturnable) { 02368 02369 // 02370 // No returnable lock was found, end of list 02371 // 02372 02373 return NULL; 02374 } 02375 02376 // 02377 // Update current enum location information 02378 // 02379 02380 FileLock->LastReturnedLockInfo = FileLockInfo; 02381 FileLock->LastReturnedLock = ContinuationPointer; 02382 02383 // 02384 // Return lock record to caller 02385 // 02386 02387 return &FileLock->LastReturnedLockInfo; 02388 }

VOID FsRtlInitializeFileLock IN PFILE_LOCK  FileLock,
IN PCOMPLETE_LOCK_IRP_ROUTINE CompleteLockIrpRoutine  OPTIONAL,
IN PUNLOCK_ROUTINE UnlockRoutine  OPTIONAL
 

Definition at line 829 of file filelock.c.

References Dbg, DebugTrace, FALSE, NULL, and PUNLOCK_ROUTINE.

Referenced by FsRtlAllocateFileLock().

00837 : 00838 00839 This routine initializes a new FILE_LOCK structure. The caller must 00840 supply the memory for the structure. This call must precede all other 00841 calls that utilize the FILE_LOCK variable. 00842 00843 Arguments: 00844 00845 FileLock - Supplies a pointer to the FILE_LOCK structure to 00846 initialize. 00847 00848 CompleteLockIrpRoutine - Optionally supplies an alternate routine to 00849 call for completing IRPs. FsRtlProcessFileLock by default will 00850 call IoCompleteRequest to finish up an IRP; however if the caller 00851 want to process the completion itself then it needs to specify 00852 a completion routine here. This routine will then be called in 00853 place of IoCompleteRequest. 00854 00855 UnlockRoutine - Optionally supplies a routine to call when removing 00856 a lock. 00857 00858 Return Value: 00859 00860 None. 00861 00862 --*/ 00863 00864 { 00865 DebugTrace(+1, Dbg, "FsRtlInitializeFileLock, FileLock = %08lx\n", FileLock); 00866 00867 // 00868 // Clear non-paged pool pointer 00869 // 00870 00871 FileLock->LockInformation = NULL; 00872 FileLock->CompleteLockIrpRoutine = CompleteLockIrpRoutine; 00873 FileLock->UnlockRoutine = UnlockRoutine; 00874 00875 FileLock->FastIoIsQuestionable = FALSE; 00876 00877 // 00878 // and return to our caller 00879 // 00880 00881 DebugTrace(-1, Dbg, "FsRtlInitializeFileLock -> VOID\n", 0 ); 00882 00883 return; 00884 }

VOID FsRtlInitializeFileLocks VOID   ) 
 

Definition at line 744 of file filelock.c.

References ExInitializeFastMutex, ExInitializeNPagedLookasideList(), ExInitializePagedLookasideList(), FILE_LOCK, FsRtlCreateLockInfo, FsRtlExclusiveLockLookasideList, FsRtlFileLockLookasideList, FsRtlLockInfoLookasideList, FsRtlLockTreeNodeLookasideList, FsRtlSharedLockLookasideList, FsRtlWaitingLockLookasideList, NULL, TAG_EXCLUSIVE_LOCK, TAG_FILE_LOCK, TAG_LOCK_INFO, TAG_LOCKTREE_NODE, TAG_SHARED_LOCK, and TAG_WAITING_LOCK.

Referenced by FsRtlInitSystem().

00749 : 00750 00751 Initializes the global portion of the filelock package. 00752 00753 Arguments: 00754 00755 None 00756 00757 Return Value: 00758 00759 None. 00760 00761 --*/ 00762 { 00763 #ifndef USERTEST 00764 00765 // 00766 // Build the lookaside lists for our internal structures. 00767 // 00768 00769 ExInitializeNPagedLookasideList( &FsRtlSharedLockLookasideList, 00770 NULL, 00771 NULL, 00772 0, 00773 sizeof(SH_LOCK), 00774 TAG_SHARED_LOCK, 00775 16 ); 00776 00777 ExInitializeNPagedLookasideList( &FsRtlExclusiveLockLookasideList, 00778 NULL, 00779 NULL, 00780 0, 00781 sizeof(EX_LOCK), 00782 TAG_EXCLUSIVE_LOCK, 00783 16 ); 00784 00785 ExInitializeNPagedLookasideList( &FsRtlWaitingLockLookasideList, 00786 NULL, 00787 NULL, 00788 0, 00789 sizeof(WAITING_LOCK), 00790 TAG_WAITING_LOCK, 00791 16 ); 00792 00793 ExInitializeNPagedLookasideList( &FsRtlLockTreeNodeLookasideList, 00794 NULL, 00795 NULL, 00796 0, 00797 sizeof(LOCKTREE_NODE), 00798 TAG_LOCKTREE_NODE, 00799 16 ); 00800 00801 ExInitializeNPagedLookasideList( &FsRtlLockInfoLookasideList, 00802 NULL, 00803 NULL, 00804 0, 00805 sizeof(LOCK_INFO), 00806 TAG_LOCK_INFO, 00807 8 ); 00808 00809 ExInitializePagedLookasideList( &FsRtlFileLockLookasideList, 00810 NULL, 00811 NULL, 00812 0, 00813 sizeof(FILE_LOCK), 00814 TAG_FILE_LOCK, 00815 8 ); 00816 00817 // 00818 // Initialize the LockInfo creation mutex 00819 // 00820 00821 ExInitializeFastMutex(&FsRtlCreateLockInfo); 00822 00823 00824 #endif 00825 }

VOID FsRtlPrivateCancelFileLockIrp IN PDEVICE_OBJECT  DeviceObject,
IN PIRP  Irp
 

Definition at line 5721 of file filelock.c.

References _IRP::CancelIrql, _WAITING_LOCK::Context, Dbg, DebugTrace, FsRtlCompleteLockIrp, FsRtlFreeWaitingLock(), FsRtlReacquireLockQueue, FsRtlReleaseLockQueue, IoReleaseCancelSpinLock(), _IRP::IoStatus, _WAITING_LOCK::Irp, Irp, _LOCK_INFO::LockQueue, NTSTATUS(), NULL, PLOCK_INFO, PLOCK_QUEUE, PWAITING_LOCK, _LOCK_QUEUE::WaitingLocks, and _LOCK_QUEUE::WaitingLocksTail.

Referenced by FsRtlPrivateLock().

05728 : 05729 05730 This routine implements the cancel function for an irp saved in a 05731 waiting lock queue 05732 05733 Arguments: 05734 05735 DeviceObject - Ignored 05736 05737 Irp - Supplies the Irp being cancelled. A pointer to the FileLock 05738 structure for the lock is stored in the information field of the 05739 irp's iosb. 05740 05741 Return Value: 05742 05743 none. 05744 05745 --*/ 05746 05747 { 05748 PSINGLE_LIST_ENTRY *pLink, Link; 05749 PLOCK_INFO LockInfo; 05750 PLOCK_QUEUE LockQueue; 05751 KIRQL OldIrql; 05752 NTSTATUS NewStatus; 05753 05754 05755 UNREFERENCED_PARAMETER( DeviceObject ); 05756 05757 // 05758 // The information field is used to store a pointer to the file lock 05759 // containing the irp 05760 // 05761 05762 LockInfo = (PLOCK_INFO) (Irp->IoStatus.Information); 05763 05764 // 05765 // Iterate through the lock queue. 05766 // 05767 05768 LockQueue = &LockInfo->LockQueue; 05769 05770 // 05771 // Release the cancel spinlock and lock the waiting queue if this 05772 // is initiated by Io. We already have the lock queue if this is 05773 // the race fixup. 05774 // 05775 // If this is from ourselves, we have the cancel Irql in the Irp. 05776 // 05777 05778 if (DeviceObject) { 05779 05780 IoReleaseCancelSpinLock( Irp->CancelIrql ); 05781 FsRtlReacquireLockQueue(LockInfo, LockQueue, &OldIrql); 05782 05783 } else { 05784 05785 OldIrql = Irp->CancelIrql; 05786 } 05787 05788 // 05789 // Iterate through all of the waiting locks looking for a canceled one. 05790 05791 pLink = &LockQueue->WaitingLocks.Next; 05792 while ((Link = *pLink) != NULL) { 05793 05794 PWAITING_LOCK WaitingLock; 05795 05796 // 05797 // Get a pointer to the waiting lock record 05798 // 05799 05800 WaitingLock = CONTAINING_RECORD( Link, WAITING_LOCK, Link ); 05801 05802 DebugTrace(0, Dbg, "FsRtlPrivateCancelFileLockIrp, Loop top, WaitingLock = %08lx\n", WaitingLock); 05803 05804 if( WaitingLock->Irp != Irp ) { 05805 05806 pLink = &Link->Next; 05807 continue; 05808 } 05809 05810 // 05811 // We've found it -- remove it from the list 05812 // 05813 05814 *pLink = Link->Next; 05815 if (Link == LockQueue->WaitingLocksTail.Next) { 05816 05817 LockQueue->WaitingLocksTail.Next = (PSINGLE_LIST_ENTRY) pLink; 05818 } 05819 05820 Irp->IoStatus.Information = 0; 05821 05822 // 05823 // Release LockQueue and complete this waiter 05824 // 05825 05826 FsRtlReleaseLockQueue(LockQueue, OldIrql); 05827 05828 // 05829 // Complete this waiter 05830 // 05831 05832 FsRtlCompleteLockIrp( LockInfo, 05833 WaitingLock->Context, 05834 Irp, 05835 STATUS_CANCELLED, 05836 &NewStatus, 05837 NULL ); 05838 05839 // 05840 // Free up pool 05841 // 05842 05843 FsRtlFreeWaitingLock( WaitingLock ); 05844 05845 // 05846 // Our job is done! 05847 // 05848 05849 return; 05850 } 05851 05852 // 05853 // Release lock queue 05854 // 05855 05856 FsRtlReleaseLockQueue(LockQueue, OldIrql); 05857 05858 return; 05859 }

BOOLEAN FsRtlPrivateCheckForExclusiveLockAccess IN PLOCK_QUEUE  LockInfo,
IN PFILE_LOCK_INFO  FileLockInfo
 

Definition at line 4934 of file filelock.c.

References FALSE, FsRtlFindFirstOverlapInNode(), FsRtlFindFirstOverlappingExclusiveNode(), FsRtlFindFirstOverlappingSharedNode(), _LOCKTREE_NODE::HoleyNode, _FILE_LOCK_INFO::Length, _EX_LOCK::LockInfo, _SH_LOCK::LockInfo, _LOCKTREE_NODE::Locks, NULL, PEX_LOCK, PLOCKTREE_NODE, PSH_LOCK, RtlSplay(), and TRUE.

Referenced by FsRtlPrivateCheckWaitingLocks(), and FsRtlPrivateLock().

04940 : 04941 04942 This routine checks to see if the caller can get an exclusive lock on 04943 the indicated range due to file locks in the passed in lock queue. 04944 04945 Assumes Lock queue is held by caller 04946 04947 Arguments: 04948 04949 LockQueue - Queue which needs to be checked for collision 04950 04951 FileLockInfo - Lock which is being checked 04952 04953 04954 Return Value: 04955 04956 BOOLEAN - TRUE if the indicated user can place the exclusive lock over the 04957 entire specified byte range, and FALSE otherwise 04958 04959 --*/ 04960 04961 { 04962 PRTL_SPLAY_LINKS SplayLinks, LastSplayLinks = NULL; 04963 PLOCKTREE_NODE Node; 04964 PSH_LOCK ShLock; 04965 PEX_LOCK ExLock; 04966 04967 if (LockQueue->SharedLockTree && 04968 (SplayLinks = FsRtlFindFirstOverlappingSharedNode( LockQueue->SharedLockTree, 04969 &FileLockInfo->StartingByte, 04970 &FileLockInfo->EndingByte, 04971 &LastSplayLinks, NULL))) { 04972 04973 Node = CONTAINING_RECORD(SplayLinks, LOCKTREE_NODE, Links); 04974 04975 // 04976 // If this node is holey, we'll have to walk the whole thing. 04977 // 04978 04979 if (Node->HoleyNode) { 04980 04981 ShLock = FsRtlFindFirstOverlapInNode( Node, 04982 &FileLockInfo->StartingByte, 04983 &FileLockInfo->EndingByte ); 04984 04985 } else { 04986 04987 ShLock = CONTAINING_RECORD(Node->Locks.Next, SH_LOCK, Link); 04988 } 04989 04990 // 04991 // Look for overlap that we care about. Perhaps no overlap existed in the holey case. 04992 // 04993 04994 if (ShLock && 04995 (FileLockInfo->Length.QuadPart || ShLock->LockInfo.Length.QuadPart)) { 04996 04997 // 04998 // If we are checking a nonzero extent and overlapped, it is fatal. If we 04999 // are checking a zero extent and overlapped a nonzero extent, it is fatal. 05000 // 05001 05002 return FALSE; 05003 } 05004 } 05005 05006 if (LastSplayLinks) { 05007 05008 LockQueue->SharedLockTree = RtlSplay(LastSplayLinks); 05009 LastSplayLinks = NULL; 05010 } 05011 05012 if (LockQueue->ExclusiveLockTree && 05013 (SplayLinks = FsRtlFindFirstOverlappingExclusiveNode( LockQueue->ExclusiveLockTree, 05014 &FileLockInfo->StartingByte, 05015 &FileLockInfo->EndingByte, 05016 &LastSplayLinks, NULL))) { 05017 05018 ExLock = CONTAINING_RECORD(SplayLinks, EX_LOCK, Links); 05019 05020 if (FileLockInfo->Length.QuadPart || ExLock->LockInfo.Length.QuadPart) { 05021 05022 // 05023 // If we are checking a nonzero extent and overlapped, it is fatal. If we 05024 // are checking a zero extent and overlapped a nonzero extent, it is fatal. 05025 // 05026 05027 return FALSE; 05028 } 05029 } 05030 05031 if (LastSplayLinks) { 05032 05033 LockQueue->ExclusiveLockTree = RtlSplay(LastSplayLinks); 05034 } 05035 05036 // 05037 // We searched the entire range without a conflict so we can grant 05038 // the exclusive lock 05039 // 05040 05041 return TRUE; 05042 }

BOOLEAN FsRtlPrivateCheckForSharedLockAccess IN PLOCK_QUEUE  LockInfo,
IN PFILE_LOCK_INFO  FileLockInfo
 

Definition at line 5046 of file filelock.c.

References FALSE, FsRtlFindFirstOverlappingExclusiveNode(), Lock, NULL, PEX_LOCK, RtlRealSuccessor(), RtlSplay(), Status, and TRUE.

Referenced by FsRtlPrivateCheckWaitingLocks(), and FsRtlPrivateLock().

05052 : 05053 05054 This routine checks to see if the caller can get a shared lock on 05055 the indicated range due to file locks in the passed in lock queue. 05056 05057 Assumes Lock queue is held by caller 05058 05059 Arguments: 05060 05061 LockQueue - Queue which needs to be checked for collision 05062 05063 FileLockInfo - Lock which is being checked 05064 05065 Arguments: 05066 05067 Return Value: 05068 05069 BOOLEAN - TRUE if the indicated user can place the shared lock over 05070 entire specified byte range, and FALSE otherwise 05071 05072 --*/ 05073 05074 { 05075 PEX_LOCK Lock; 05076 PRTL_SPLAY_LINKS SplayLinks, LastSplayLinks; 05077 BOOLEAN Status = TRUE; 05078 05079 // 05080 // If there are no exclusive locks, this is quick ... 05081 // 05082 05083 if (LockQueue->ExclusiveLockTree == NULL) { 05084 05085 return TRUE; 05086 } 05087 05088 // 05089 // No lock in the shared lock tree can prevent access, so just search the exclusive 05090 // tree for conflict. 05091 // 05092 05093 for (SplayLinks = FsRtlFindFirstOverlappingExclusiveNode( LockQueue->ExclusiveLockTree, 05094 &FileLockInfo->StartingByte, 05095 &FileLockInfo->EndingByte, 05096 &LastSplayLinks, NULL); 05097 SplayLinks; 05098 SplayLinks = RtlRealSuccessor(SplayLinks)) { 05099 05100 Lock = CONTAINING_RECORD( SplayLinks, EX_LOCK, Links ); 05101 05102 if ((ULONGLONG)Lock->LockInfo.StartingByte.QuadPart > (ULONGLONG)FileLockInfo->EndingByte.QuadPart) { 05103 05104 // 05105 // This node is covering a range greater than the range we care about, 05106 // so we're done 05107 // 05108 05109 break; 05110 } 05111 05112 // 05113 // We may not be able to grant the request if the fileobject, processid, 05114 // and key do not match. 05115 // 05116 05117 if ((Lock->LockInfo.FileObject != FileLockInfo->FileObject) || 05118 (Lock->LockInfo.ProcessId != FileLockInfo->ProcessId) || 05119 (Lock->LockInfo.Key != FileLockInfo->Key)) { 05120 05121 // 05122 // We have a mismatch between caller and owner. It is ok not to conflict 05123 // if the caller and owner will have/have zero length locks (zero length 05124 // locks cannot conflict). 05125 // 05126 05127 if (FileLockInfo->Length.QuadPart || Lock->LockInfo.Length.QuadPart) { 05128 05129 Status = FALSE; 05130 break; 05131 } 05132 } 05133 } 05134 05135 if (LastSplayLinks) { 05136 05137 LockQueue->ExclusiveLockTree = RtlSplay(LastSplayLinks); 05138 } 05139 05140 // 05141 // We searched the entire range without a conflict so we can grant 05142 // the shared lock 05143 // 05144 05145 return Status; 05146 }

VOID FsRtlPrivateCheckWaitingLocks IN PLOCK_INFO  LockInfo,
IN PLOCK_QUEUE  LockQueue,
IN KIRQL  OldIrql
 

Definition at line 4722 of file filelock.c.

References BooleanFlagOn, _WAITING_LOCK::Context, Dbg, DebugTrace, _FILE_LOCK_INFO::EndingByte, _FILE_LOCK_INFO::ExclusiveLock, FALSE, _IO_STACK_LOCATION::FileObject, _FILE_LOCK_INFO::FileObject, _IO_STACK_LOCATION::Flags, FsRtlCompleteLockIrp, FsRtlFreeWaitingLock(), FsRtlPrivateCheckForExclusiveLockAccess(), FsRtlPrivateCheckForSharedLockAccess(), FsRtlPrivateInsertLock(), FsRtlPrivateRemoveLock(), FsRtlReacquireLockQueue, FsRtlReleaseLockQueue, IoGetCurrentIrpStackLocation, IoGetRequestorProcess(), IoSetCancelRoutine, _WAITING_LOCK::Irp, Irp, _FILE_LOCK_INFO::Key, _FILE_LOCK_INFO::Length, NT_SUCCESS, NTSTATUS(), NULL, ObDereferenceObject, ObReferenceObject, _IO_STACK_LOCATION::Parameters, _FILE_LOCK_INFO::ProcessId, PWAITING_LOCK, SL_EXCLUSIVE_LOCK, and _FILE_LOCK_INFO::StartingByte.

Referenced by FsRtlFastUnlockSingleExclusive(), FsRtlFastUnlockSingleShared(), and FsRtlPrivateFastUnlockAll().

04730 : 04731 04732 This routine checks to see if any of the current waiting locks are now 04733 be satisfied, and if so it completes their IRPs. 04734 04735 Arguments: 04736 04737 LockInfo - LockInfo which LockQueue is member of 04738 04739 LockQueue - Supplies queue which needs to be checked 04740 04741 OldIrql - Irql to restore when LockQueue is released 04742 04743 Return Value: 04744 04745 None. 04746 04747 --*/ 04748 04749 { 04750 PSINGLE_LIST_ENTRY *pLink, Link; 04751 NTSTATUS NewStatus; 04752 BOOLEAN Result; 04753 04754 pLink = &LockQueue->WaitingLocks.Next; 04755 while ((Link = *pLink) != NULL) { 04756 04757 PWAITING_LOCK WaitingLock; 04758 04759 PIRP Irp; 04760 PIO_STACK_LOCATION IrpSp; 04761 04762 BOOLEAN AccessGranted; 04763 04764 FILE_LOCK_INFO FileLockInfo; 04765 04766 // 04767 // Get a pointer to the waiting lock record 04768 // 04769 04770 WaitingLock = CONTAINING_RECORD( Link, WAITING_LOCK, Link ); 04771 04772 DebugTrace(0, Dbg, "FsRtlCheckWaitingLocks, Loop top, WaitingLock = %08lx\n", WaitingLock); 04773 04774 // 04775 // Get a local copy of the necessary fields we'll need to use 04776 // 04777 04778 Irp = WaitingLock->Irp; 04779 IrpSp = IoGetCurrentIrpStackLocation( Irp ); 04780 04781 FileLockInfo.StartingByte = IrpSp->Parameters.LockControl.ByteOffset; 04782 FileLockInfo.Length = *IrpSp->Parameters.LockControl.Length; 04783 (ULONGLONG)FileLockInfo.EndingByte.QuadPart = 04784 (ULONGLONG)FileLockInfo.StartingByte.QuadPart + (ULONGLONG)FileLockInfo.Length.QuadPart - 1; 04785 04786 FileLockInfo.FileObject = IrpSp->FileObject; 04787 FileLockInfo.ProcessId = IoGetRequestorProcess( Irp ); 04788 FileLockInfo.Key = IrpSp->Parameters.LockControl.Key; 04789 FileLockInfo.ExclusiveLock = BooleanFlagOn(IrpSp->Flags, SL_EXCLUSIVE_LOCK); 04790 04791 // 04792 // Now case on whether we're trying to take out an exclusive lock or 04793 // a shared lock. And in both cases try to get the appropriate access 04794 // For the exclusive case we send in a NULL file object and process 04795 // id, this will ensure that the lookup does not give us write 04796 // access through an exclusive lock. 04797 // 04798 04799 if (FileLockInfo.ExclusiveLock) { 04800 04801 DebugTrace(0, Dbg, "FsRtlCheckWaitingLocks do we have write access?\n", 0); 04802 04803 AccessGranted = FsRtlPrivateCheckForExclusiveLockAccess( 04804 LockQueue, 04805 &FileLockInfo ); 04806 } else { 04807 04808 DebugTrace(0, Dbg, "FsRtlCheckWaitingLocks do we have read access?\n", 0); 04809 04810 AccessGranted = FsRtlPrivateCheckForSharedLockAccess( 04811 LockQueue, 04812 &FileLockInfo ); 04813 04814 } 04815 04816 // 04817 // Now AccessGranted tells us whether we can really get the access for 04818 // the range we want. 04819 // 04820 // No matter what happens, this Irp must be completed now - even if we 04821 // are resource starved. User mode deadlock could be induced since there 04822 // may no longer be a pending unlock to cause a rescan of the waiting 04823 // list. 04824 // 04825 04826 if (AccessGranted) { 04827 04828 DebugTrace(0, Dbg, "FsRtlCheckWaitingLocks now has access\n", 0); 04829 04830 // 04831 // Clear the cancel routine 04832 // 04833 04834 IoSetCancelRoutine( Irp, NULL ); 04835 04836 Result = FsRtlPrivateInsertLock( LockInfo, IrpSp->FileObject, &FileLockInfo ); 04837 04838 // 04839 // Now we need to remove this granted waiter and complete 04840 // it's irp. 04841 // 04842 04843 *pLink = Link->Next; 04844 if (Link == LockQueue->WaitingLocksTail.Next) { 04845 LockQueue->WaitingLocksTail.Next = (PSINGLE_LIST_ENTRY) pLink; 04846 } 04847 04848 // 04849 // Release LockQueue and complete this waiter 04850 // 04851 04852 FsRtlReleaseLockQueue(LockQueue, OldIrql); 04853 04854 // 04855 // Reference the fileobject over the completion attempt so we can have a 04856 // chance to cleanup safely if we fail 04857 // 04858 04859 ObReferenceObject( FileLockInfo.FileObject ); 04860 04861 // 04862 // Now we can complete the IRP, if we don't get back success 04863 // from the completion routine then we remove the lock we just 04864 // inserted. 04865 // 04866 04867 FsRtlCompleteLockIrp( LockInfo, 04868 WaitingLock->Context, 04869 Irp, 04870 (Result? STATUS_SUCCESS : STATUS_INSUFFICIENT_RESOURCES), 04871 &NewStatus, 04872 FileLockInfo.FileObject ); 04873 04874 if (Result && !NT_SUCCESS(NewStatus)) { 04875 04876 // 04877 // Irp was not sucessfull, remove lock if it was added. 04878 // 04879 04880 FsRtlPrivateRemoveLock ( 04881 LockInfo, 04882 &FileLockInfo, 04883 FALSE ); 04884 } 04885 04886 // 04887 // Drop our private reference to the fileobject 04888 // 04889 04890 ObDereferenceObject( FileLockInfo.FileObject ); 04891 04892 // 04893 // Re-acquire queue lock 04894 // 04895 04896 FsRtlReacquireLockQueue(LockInfo, LockQueue, &OldIrql); 04897 04898 // 04899 // Start scan over from begining 04900 // 04901 04902 pLink = &LockQueue->WaitingLocks.Next; 04903 04904 04905 // 04906 // Free up pool 04907 // 04908 04909 FsRtlFreeWaitingLock( WaitingLock ); 04910 04911 04912 } else { 04913 04914 DebugTrace( 0, Dbg, "FsRtlCheckWaitingLocks still no access\n", 0); 04915 04916 // 04917 // Move to next lock 04918 // 04919 04920 pLink = &Link->Next; 04921 } 04922 04923 } 04924 04925 // 04926 // And return to our caller 04927 // 04928 04929 return; 04930 }

NTSTATUS FsRtlPrivateFastUnlockAll IN PFILE_LOCK  FileLock,
IN PFILE_OBJECT  FileObject,
IN PEPROCESS  ProcessId,
IN ULONG  Key,
IN BOOLEAN  MatchKey,
IN PVOID Context  OPTIONAL
 

Definition at line 5254 of file filelock.c.

References _WAITING_LOCK::Context, Dbg, DebugTrace, _FILE_LOCK_INFO::EndingByte, _LOCK_QUEUE::ExclusiveLockTree, FALSE, _IO_STACK_LOCATION::FileObject, _FILE_LOCK_INFO::FileObject, FsRtlCompleteLockIrp, FsRtlFreeExclusiveLock(), FsRtlFreeLockTreeNode(), FsRtlFreeSharedLock(), FsRtlFreeWaitingLock(), FsRtlPrivateCheckWaitingLocks(), FsRtlPrivateResetLowestLockOffset(), FsRtlReacquireLockQueue, FsRtlReleaseLockQueue, FsRtlSplitLocks(), IoGetCurrentIrpStackLocation, IoGetRequestorProcess(), IoSetCancelRoutine, _IRP::IoStatus, _WAITING_LOCK::Irp, Key, _FILE_LOCK_INFO::Key, _EX_LOCK::Links, _EX_LOCK::LockInfo, _SH_LOCK::LockInfo, _LOCK_INFO::LockQueue, _LOCKTREE_NODE::Locks, NTSTATUS(), NULL, _IO_STACK_LOCATION::Parameters, PEX_LOCK, PLOCK_INFO, PLOCK_QUEUE, PLOCKTREE_NODE, _FILE_LOCK_INFO::ProcessId, PSH_LOCK, PWAITING_LOCK, RtlDelete(), RtlRealSuccessor(), _LOCK_QUEUE::SharedLockTree, _LOCKTREE_NODE::Tail, TRUE, _LOCK_INFO::UnlockRoutine, _LOCK_QUEUE::WaitingLocks, and _LOCK_QUEUE::WaitingLocksTail.

Referenced by FsRtlFastUnlockAll(), and FsRtlFastUnlockAllByKey().

05265 : 05266 05267 This routine performs an Unlock all operation on the current locks 05268 associated with the specified file lock. Only those locks with 05269 a matching file object and process id are freed. Additionally, 05270 it is possible to free only those locks which also match a given 05271 key. 05272 05273 Arguments: 05274 05275 FileLock - Supplies the file lock being freed. 05276 05277 FileObject - Supplies the file object associated with the file lock 05278 05279 ProcessId - Supplies the Process Id assoicated with the locks to be 05280 freed 05281 05282 Key - Supplies the Key to use in this operation 05283 05284 MatchKey - Whether or not the Key must also match for lock to be freed. 05285 05286 Context - Supplies an optional context to use when completing waiting 05287 lock irps. 05288 05289 Return Value: 05290 05291 None 05292 05293 --*/ 05294 05295 { 05296 PLOCK_INFO LockInfo; 05297 PLOCK_QUEUE LockQueue; 05298 PSINGLE_LIST_ENTRY *pLink, *SavepLink, Link; 05299 NTSTATUS NewStatus; 05300 KIRQL OldIrql; 05301 LARGE_INTEGER MaxOffset, SaveEndingByte; 05302 BOOLEAN UnlockRoutine; 05303 PSH_LOCK ShLock; 05304 PEX_LOCK ExLock; 05305 PRTL_SPLAY_LINKS SplayLinks, SuccessorLinks; 05306 PLOCKTREE_NODE Node; 05307 05308 05309 DebugTrace(+1, Dbg, "FsRtlPrivateFastUnlockAll, FileLock = %08lx\n", FileLock); 05310 05311 if ((LockInfo = FileLock->LockInformation) == NULL) { 05312 05313 // 05314 // No lock information on this FileLock 05315 // 05316 05317 DebugTrace(+1, Dbg, "FsRtlPrivateFastUnlockAll, No LockInfo\n", FileLock); 05318 return STATUS_RANGE_NOT_LOCKED; 05319 } 05320 05321 FileObject->LastLock = NULL; 05322 05323 LockQueue = &LockInfo->LockQueue; 05324 05325 // 05326 // Grab the waiting lock queue spinlock to exclude anyone from messing 05327 // with the queue while we're using it 05328 // 05329 05330 FsRtlReacquireLockQueue(LockInfo, LockQueue, &OldIrql); 05331 05332 if (LockQueue->SharedLockTree == NULL && LockQueue->ExclusiveLockTree == NULL) { 05333 05334 // 05335 // No locks on this FileLock 05336 // 05337 05338 DebugTrace(+1, Dbg, "FsRtlPrivateFastUnlockAll, No LockTrees\n", FileLock); 05339 FsRtlReleaseLockQueue(LockQueue, OldIrql); 05340 05341 return STATUS_RANGE_NOT_LOCKED; 05342 } 05343 05344 // 05345 // Remove all matching locks in the shared lock tree 05346 // 05347 05348 if (LockQueue->SharedLockTree != NULL) { 05349 05350 // 05351 // Grab the lowest node in the tree 05352 // 05353 05354 SplayLinks = LockQueue->SharedLockTree; 05355 05356 while (RtlLeftChild(SplayLinks) != NULL) { 05357 05358 SplayLinks = RtlLeftChild(SplayLinks); 05359 } 05360 05361 // 05362 // Walk all nodes in the tree 05363 // 05364 05365 UnlockRoutine = FALSE; 05366 05367 for (; 05368 SplayLinks; 05369 SplayLinks = SuccessorLinks) { 05370 05371 Node = CONTAINING_RECORD(SplayLinks, LOCKTREE_NODE, Links ); 05372 05373 // 05374 // Save the next node because we may split this node apart in the process 05375 // of deleting locks. It would be a waste of time to traverse those split 05376 // nodes. The only case in which we will not have traversed the entire list 05377 // before doing the split will be if there is an unlock routine attached 05378 // to this FileLock in which case we will be restarting the entire scan 05379 // anyway. 05380 // 05381 05382 SuccessorLinks = RtlRealSuccessor(SplayLinks); 05383 05384 // 05385 // Search down the current lock queue looking for a match on 05386 // the file object and process id 05387 // 05388 05389 SavepLink = NULL; 05390 SaveEndingByte.QuadPart = 0; 05391 05392 pLink = &Node->Locks.Next; 05393 while ((Link = *pLink) != NULL) { 05394 05395 ShLock = CONTAINING_RECORD( Link, SH_LOCK, Link ); 05396 05397 DebugTrace(0, Dbg, "Top of ShLock Loop, Lock = %08lx\n", ShLock ); 05398 05399 if ((ShLock->LockInfo.FileObject == FileObject) && 05400 (ShLock->LockInfo.ProcessId == ProcessId) && 05401 (!MatchKey || ShLock->LockInfo.Key == Key)) { 05402 05403 DebugTrace(0, Dbg, "Found one to unlock\n", 0); 05404 05405 // 05406 // We have a match so now is the time to delete this lock. 05407 // Save the neccesary information to do the split node check. 05408 // Remove the lock from the list, then call the 05409 // optional unlock routine, then delete the lock. 05410 // 05411 05412 if (SavepLink == NULL) { 05413 05414 // 05415 // Need to remember where the first lock was deleted 05416 // 05417 05418 SavepLink = pLink; 05419 } 05420 05421 if ((ULONGLONG)ShLock->LockInfo.EndingByte.QuadPart > (ULONGLONG)SaveEndingByte.QuadPart) { 05422 05423 // 05424 // Need to remember where the last offset affected by deleted locks is 05425 // 05426 05427 SaveEndingByte.QuadPart = ShLock->LockInfo.EndingByte.QuadPart; 05428 } 05429 05430 if (*pLink == Node->Tail.Next) { 05431 05432 // 05433 // Deleting the tail node of the list. Safe even if deleting the 05434 // first node since this implies we're also deleting the last node 05435 // in the node which means we'll delete the node ... 05436 // 05437 05438 Node->Tail.Next = CONTAINING_RECORD( pLink, SINGLE_LIST_ENTRY, Next ); 05439 } 05440 05441 *pLink = Link->Next; 05442 05443 if (LockInfo->UnlockRoutine != NULL) { 05444 05445 // 05446 // Signal a lock that needs to have a special unlock routine 05447 // called on it. This is complex to deal with since we'll have 05448 // to release the queue, call it, and reacquire - meaning we 05449 // also have to restart. But we still need to reorder the node 05450 // first ... 05451 // 05452 05453 UnlockRoutine = TRUE; 05454 05455 break; 05456 } 05457 05458 FsRtlFreeSharedLock( ShLock ); 05459 05460 } else { 05461 05462 // 05463 // Move to next lock 05464 // 05465 05466 pLink = &Link->Next; 05467 } 05468 05469 if (SavepLink == NULL && (ULONGLONG)ShLock->LockInfo.EndingByte.QuadPart > (ULONGLONG)MaxOffset.QuadPart) { 05470 05471 // 05472 // Save the max offset until we have deleted our first node 05473 // 05474 05475 MaxOffset.QuadPart = ShLock->LockInfo.EndingByte.QuadPart; 05476 } 05477 } 05478 05479 if (SavepLink) { 05480 05481 // 05482 // Locks were actually deleted here, so we have to check the state of the node 05483 // 05484 05485 if (Node->Locks.Next == NULL) { 05486 05487 // 05488 // We have just deleted everything at this node 05489 // 05490 05491 LockQueue->SharedLockTree = RtlDelete(SplayLinks); 05492 05493 FsRtlFreeLockTreeNode(Node); 05494 05495 } else { 05496 05497 // 05498 // Now that we have deleted all matching locks in this node, we do the 05499 // check on the node to split out any now non-overlapping locks. Conceptually, 05500 // we have deleted just one big lock that starts at the starting byte of the 05501 // first deleted lock and extends to the last byte of the last deleted lock. 05502 // 05503 05504 FsRtlSplitLocks(Node, SavepLink, &SaveEndingByte, &MaxOffset); 05505 } 05506 } 05507 05508 if (UnlockRoutine) { 05509 05510 // 05511 // We dropped out of the node scan because we had a lock that needs extra 05512 // processing during unlock. Do it. 05513 // 05514 05515 FsRtlReleaseLockQueue(LockQueue, OldIrql); 05516 05517 LockInfo->UnlockRoutine(Context, &ShLock->LockInfo); 05518 05519 FsRtlReacquireLockQueue(LockInfo, LockQueue, &OldIrql); 05520 05521 FsRtlFreeSharedLock(ShLock); 05522 05523 UnlockRoutine = FALSE; 05524 05525 // 05526 // We have to restart the scan, because the list may have changed while 05527 // we were in the unlock routine. Careful, because the tree may be empty. 05528 // 05529 05530 if (SuccessorLinks = LockQueue->SharedLockTree) { 05531 05532 while (RtlLeftChild(SuccessorLinks) != NULL) { 05533 05534 SuccessorLinks = RtlLeftChild(SuccessorLinks); 05535 } 05536 } 05537 } 05538 } 05539 } 05540 05541 // 05542 // Remove all matching locks in the exclusive lock tree 05543 // 05544 05545 if (LockQueue->ExclusiveLockTree != NULL) { 05546 05547 SplayLinks = LockQueue->ExclusiveLockTree; 05548 05549 while (RtlLeftChild(SplayLinks) != NULL) { 05550 05551 SplayLinks = RtlLeftChild(SplayLinks); 05552 } 05553 05554 // 05555 // Walk all nodes in the tree 05556 // 05557 05558 UnlockRoutine = FALSE; 05559 05560 for (; SplayLinks; 05561 SplayLinks = SuccessorLinks ) { 05562 05563 SuccessorLinks = RtlRealSuccessor(SplayLinks); 05564 05565 ExLock = CONTAINING_RECORD( SplayLinks, EX_LOCK, Links ); 05566 05567 DebugTrace(0, Dbg, "Top of ExLock Loop, Lock = %08lx\n", ExLock ); 05568 05569 if ((ExLock->LockInfo.FileObject == FileObject) && 05570 (ExLock->LockInfo.ProcessId == ProcessId) && 05571 (!MatchKey || ExLock->LockInfo.Key == Key)) { 05572 05573 LockQueue->ExclusiveLockTree = RtlDelete(&ExLock->Links); 05574 05575 if (LockInfo->UnlockRoutine != NULL) { 05576 05577 // 05578 // We're dropping out of the node scan because we have a lock 05579 // that needs extra processing during unlock. Do it. 05580 // 05581 05582 FsRtlReleaseLockQueue(LockQueue, OldIrql); 05583 05584 LockInfo->UnlockRoutine(Context, &ExLock->LockInfo); 05585 05586 FsRtlReacquireLockQueue(LockInfo, LockQueue, &OldIrql); 05587 05588 // 05589 // We have to restart the scan, because the list may have changed while 05590 // we were in the unlock routine. Careful, because the tree may be empty. 05591 // 05592 05593 if (SuccessorLinks = LockQueue->ExclusiveLockTree) { 05594 05595 while (RtlLeftChild(SuccessorLinks) != NULL) { 05596 05597 SuccessorLinks = RtlLeftChild(SuccessorLinks); 05598 } 05599 } 05600 } 05601 05602 FsRtlFreeExclusiveLock(ExLock); 05603 } 05604 } 05605 } 05606 05607 // 05608 // Search down the waiting lock queue looking for a match on the 05609 // file object and process id. 05610 // 05611 05612 pLink = &LockQueue->WaitingLocks.Next; 05613 while ((Link = *pLink) != NULL) { 05614 05615 PWAITING_LOCK WaitingLock; 05616 PIRP WaitingIrp; 05617 PIO_STACK_LOCATION WaitingIrpSp; 05618 05619 WaitingLock = CONTAINING_RECORD( Link, WAITING_LOCK, Link ); 05620 05621 DebugTrace(0, Dbg, "Top of Waiting Loop, WaitingLock = %08lx\n", WaitingLock); 05622 05623 // 05624 // Get a copy of the necessary fields we'll need to use 05625 // 05626 05627 WaitingIrp = WaitingLock->Irp; 05628 WaitingIrpSp = IoGetCurrentIrpStackLocation( WaitingIrp ); 05629 05630 if ((FileObject == WaitingIrpSp->FileObject) && 05631 (ProcessId == IoGetRequestorProcess( WaitingIrp )) && 05632 (!MatchKey || Key == WaitingIrpSp->Parameters.LockControl.Key)) { 05633 05634 DebugTrace(0, Dbg, "Found a waiting lock to abort\n", 0); 05635 05636 // 05637 // We now void the cancel routine in the irp 05638 // 05639 05640 IoSetCancelRoutine( WaitingIrp, NULL ); 05641 WaitingIrp->IoStatus.Information = 0; 05642 05643 // 05644 // We have a match so now is the time to delete this waiter 05645 // But we must not mess up our link iteration variable. We 05646 // do this by simply starting the iteration over again, 05647 // after we delete ourselves. We also will deallocate the 05648 // lock after we delete it. 05649 // 05650 05651 *pLink = Link->Next; 05652 if (Link == LockQueue->WaitingLocksTail.Next) { 05653 LockQueue->WaitingLocksTail.Next = (PSINGLE_LIST_ENTRY) pLink; 05654 } 05655 05656 FsRtlReleaseLockQueue(LockQueue, OldIrql); 05657 05658 // 05659 // And complete this lock request Irp 05660 // 05661 05662 FsRtlCompleteLockIrp( LockInfo, 05663 WaitingLock->Context, 05664 WaitingIrp, 05665 STATUS_SUCCESS, 05666 &NewStatus, 05667 NULL ); 05668 05669 // 05670 // Reaqcuire lock queue spinlock and start over 05671 // 05672 05673 FsRtlReacquireLockQueue(LockInfo, LockQueue, &OldIrql); 05674 05675 // 05676 // Start over 05677 // 05678 05679 pLink = &LockQueue->WaitingLocks.Next; 05680 05681 // 05682 // Put memory onto free list 05683 // 05684 05685 FsRtlFreeWaitingLock( WaitingLock ); 05686 continue; 05687 } 05688 05689 // 05690 // Move to next lock 05691 // 05692 05693 pLink = &Link->Next; 05694 } 05695 05696 // 05697 // At this point we've gone through unlocking everything. So 05698 // now try and release any waiting locks. 05699 // 05700 05701 FsRtlPrivateCheckWaitingLocks( LockInfo, LockQueue, OldIrql ); 05702 05703 // 05704 // We deleted a (possible) bunch of locks, go repair the lowest lock offset 05705 // 05706 05707 FsRtlPrivateResetLowestLockOffset( LockInfo ); 05708 05709 FsRtlReleaseLockQueue( LockQueue, OldIrql ); 05710 05711 // 05712 // and return to our caller 05713 // 05714 05715 DebugTrace(-1, Dbg, "FsRtlFastUnlockAll -> VOID\n", 0); 05716 return STATUS_SUCCESS; 05717 }

BOOLEAN FsRtlPrivateInitializeFileLock IN PFILE_LOCK  FileLock,
IN BOOLEAN  ViaFastCall
 

Definition at line 888 of file filelock.c.

References _LOCK_INFO::CompleteLockIrpRoutine, _LOCK_QUEUE::ExclusiveLockTree, ExRaiseStatus(), FALSE, FsRtlAllocateLockInfo(), FsRtlCreateLockInfo, KeInitializeSpinLock(), _LOCK_INFO::LockQueue, _LOCK_INFO::LowestLockOffset, NULL, PLOCK_INFO, _LOCK_QUEUE::QueueSpinLock, _LOCK_QUEUE::SharedLockTree, TRUE, try_return, _LOCK_INFO::UnlockRoutine, _LOCK_QUEUE::WaitingLocks, and _LOCK_QUEUE::WaitingLocksTail.

Referenced by FsRtlPrivateLock().

00894 : 00895 00896 This routine initializes a new LOCK_INFO structure in non-paged 00897 pool for the FILE_LOCK. This routines only occurs once for a given 00898 FILE_LOCK and it only occurs if any locks are applied to that file. 00899 00900 Arguments: 00901 00902 FileLock - Supplies a pointer to the FILE_LOCK structure to 00903 initialize. 00904 00905 ViaFastCall - Indicates if we are being invoked via a fast call or 00906 via the slow irp based method. 00907 00908 Return Value: 00909 00910 TRUE - If LockInfo structure was allocated and initialized 00911 00912 --*/ 00913 { 00914 PLOCK_INFO LockInfo; 00915 BOOLEAN Results = FALSE; 00916 00917 ExAcquireFastMutex( &FsRtlCreateLockInfo ); 00918 00919 try { 00920 00921 if (FileLock->LockInformation != NULL) { 00922 00923 // 00924 // Structure is already allocated, just return 00925 // 00926 00927 try_return( Results = TRUE ); 00928 } 00929 00930 // 00931 // Allocate pool for lock structures. If we fail then we will either return false or 00932 // raise based on if we know the caller has an try-except to handle a raise. 00933 // 00934 00935 LockInfo = FsRtlAllocateLockInfo(); 00936 00937 if (LockInfo == NULL) { 00938 00939 if (ViaFastCall) { 00940 00941 try_return( Results = FALSE ); 00942 00943 } else { 00944 00945 ExRaiseStatus( STATUS_INSUFFICIENT_RESOURCES ); 00946 } 00947 } 00948 00949 // 00950 // Allocate and initialize the waiting lock queue 00951 // spinlock, and initialize the queues 00952 // 00953 00954 LockInfo->LowestLockOffset = 0xffffffff; 00955 00956 KeInitializeSpinLock( &LockInfo->LockQueue.QueueSpinLock ); 00957 LockInfo->LockQueue.SharedLockTree = NULL; 00958 LockInfo->LockQueue.ExclusiveLockTree = NULL; 00959 LockInfo->LockQueue.WaitingLocks.Next = NULL; 00960 LockInfo->LockQueue.WaitingLocksTail.Next = NULL; 00961 00962 // 00963 // Copy Irp & Unlock routines from pagable FileLock structure 00964 // to non-pagable LockInfo structure 00965 // 00966 00967 LockInfo->CompleteLockIrpRoutine = FileLock->CompleteLockIrpRoutine; 00968 LockInfo->UnlockRoutine = FileLock->UnlockRoutine; 00969 00970 // 00971 // Clear continuation info for enum routine 00972 // 00973 00974 FileLock->LastReturnedLockInfo.FileObject = NULL; 00975 FileLock->LastReturnedLock = NULL; 00976 00977 // 00978 // Link LockInfo into FileLock 00979 // 00980 00981 FileLock->LockInformation = (PVOID) LockInfo; 00982 Results = TRUE; 00983 00984 try_exit: NOTHING; 00985 } finally { 00986 00987 ExReleaseFastMutex( &FsRtlCreateLockInfo ); 00988 } 00989 00990 return Results; 00991 }

VOID FsRtlPrivateInsertExclusiveLock IN PLOCK_QUEUE  LockQueue,
IN PEX_LOCK  NewLock
 

Definition at line 4605 of file filelock.c.

References ASSERT, FsRtlFindFirstOverlappingExclusiveNode(), GreaterThan, NULL, and RtlRealSuccessor().

Referenced by FsRtlPrivateInsertLock().

04612 : 04613 04614 This routine adds a new exclusive lock record to the File lock's current 04615 lock queue. 04616 04617 Arguments: 04618 04619 LockQueue - Supplies the lock queue being modified 04620 04621 NewLock - Supplies the new exclusive lock to add to the lock queue 04622 04623 Return Value: 04624 04625 None. 04626 04627 --*/ 04628 04629 { 04630 PRTL_SPLAY_LINKS OverlappedSplayLinks, ParentSplayLinks; 04631 BOOLEAN GreaterThan; 04632 04633 OverlappedSplayLinks = FsRtlFindFirstOverlappingExclusiveNode( LockQueue->ExclusiveLockTree, 04634 &NewLock->LockInfo.StartingByte, 04635 &NewLock->LockInfo.EndingByte, 04636 &ParentSplayLinks, 04637 &GreaterThan ); 04638 04639 // 04640 // This is the exclusive tree. Nothing can overlap (caller is supposed to insure this) unless 04641 // the lock is a zero length lock, in which case we just insert it - still. 04642 // 04643 04644 ASSERT(!OverlappedSplayLinks || NewLock->LockInfo.Length.QuadPart == 0); 04645 04646 // 04647 // Simple insert ... 04648 // 04649 04650 RtlInitializeSplayLinks(&NewLock->Links); 04651 04652 if (OverlappedSplayLinks) { 04653 04654 // 04655 // With zero length locks we have OverlappedSplayLinks at the starting point 04656 // of a run of zero length locks, so we have to e flexible about where the new 04657 // node is inserted. 04658 // 04659 04660 if (RtlRightChild(OverlappedSplayLinks)) { 04661 04662 // 04663 // Right slot taken. We can use the left slot or go to the sucessor's left slot 04664 // 04665 04666 if (RtlLeftChild(OverlappedSplayLinks)) { 04667 04668 ASSERT(RtlLeftChild(RtlRealSuccessor(OverlappedSplayLinks)) == NULL); 04669 RtlInsertAsLeftChild(RtlRealSuccessor(OverlappedSplayLinks), &NewLock->Links); 04670 04671 } else { 04672 04673 RtlInsertAsLeftChild(OverlappedSplayLinks, &NewLock->Links); 04674 } 04675 04676 04677 } else { 04678 04679 RtlInsertAsRightChild(OverlappedSplayLinks, &NewLock->Links); 04680 } 04681 04682 } else if (ParentSplayLinks) { 04683 04684 // 04685 // We have a real parent node in the tree, and must be at a leaf since 04686 // there was no overlap 04687 // 04688 04689 if (GreaterThan) { 04690 04691 ASSERT(RtlLeftChild(ParentSplayLinks) == NULL); 04692 RtlInsertAsLeftChild(ParentSplayLinks, &NewLock->Links); 04693 04694 } else { 04695 04696 ASSERT(RtlRightChild(ParentSplayLinks) == NULL); 04697 RtlInsertAsRightChild(ParentSplayLinks, &NewLock->Links); 04698 } 04699 04700 } else { 04701 04702 // 04703 // First node in the tree 04704 // 04705 04706 LockQueue->ExclusiveLockTree = &NewLock->Links; 04707 } 04708 04709 // 04710 // And return to our caller 04711 // 04712 04713 return; 04714 }

BOOLEAN FsRtlPrivateInsertLock IN PLOCK_INFO  LockInfo,
IN PFILE_OBJECT  FileObject,
IN PFILE_LOCK_INFO  FileLockInfo
 

Definition at line 4253 of file filelock.c.

References ASSERT, FALSE, FsRtlAllocateExclusiveLock(), FsRtlAllocateSharedLock(), FsRtlPrivateInsertExclusiveLock(), FsRtlPrivateInsertSharedLock(), _SH_LOCK::LockInfo, _EX_LOCK::LockInfo, NULL, PEX_LOCK, PSH_LOCK, and TRUE.

Referenced by FsRtlPrivateCheckWaitingLocks(), and FsRtlPrivateLock().

04261 : 04262 04263 This routine fills in a new lock record of the appropriate type and inserts 04264 it into the lock information. 04265 04266 Arguments: 04267 04268 LockInfo - Supplies the lock being modified 04269 04270 FileObject - The associated file object to update hints in 04271 04272 FileLockInfo - Supplies the new lock data to add to the lock queue 04273 04274 Return Value: 04275 04276 BOOLEAN - True if the insert was successful, False if no resources were avaliable 04277 to complete the operation. 04278 04279 --*/ 04280 04281 { 04282 // 04283 // Now add the lock to the appropriate tree. 04284 // 04285 04286 if (FileLockInfo->ExclusiveLock) { 04287 04288 PEX_LOCK ExLock; 04289 04290 ExLock = FsRtlAllocateExclusiveLock(); 04291 04292 if (ExLock == NULL) { 04293 04294 return FALSE; 04295 } 04296 04297 ExLock->LockInfo = *FileLockInfo; 04298 04299 FsRtlPrivateInsertExclusiveLock( &LockInfo->LockQueue, ExLock ); 04300 04301 FileObject->LastLock = &ExLock->LockInfo; 04302 04303 } else { 04304 04305 PSH_LOCK ShLock; 04306 04307 ShLock = FsRtlAllocateSharedLock(); 04308 04309 if (ShLock == NULL) { 04310 04311 return FALSE; 04312 } 04313 04314 ShLock->LockInfo = *FileLockInfo; 04315 04316 if (!FsRtlPrivateInsertSharedLock( &LockInfo->LockQueue, ShLock )) { 04317 04318 return FALSE; 04319 } 04320 04321 FileObject->LastLock = &ShLock->LockInfo; 04322 } 04323 04324 // 04325 // Fix up the lowest lock offset if need be 04326 // 04327 04328 if ((ULONGLONG)FileLockInfo->StartingByte.QuadPart < (ULONGLONG)LockInfo->LowestLockOffset) { 04329 04330 ASSERT( FileLockInfo->StartingByte.HighPart == 0 ); 04331 LockInfo->LowestLockOffset = FileLockInfo->StartingByte.LowPart; 04332 } 04333 04334 return TRUE; 04335 }

BOOLEAN FsRtlPrivateInsertSharedLock IN PLOCK_QUEUE  LockQueue,
IN PSH_LOCK  NewLock
 

Definition at line 4343 of file filelock.c.

References ASSERT, Dbg, DebugTrace, _LOCKTREE_NODE::Extent, FALSE, FsRtlAllocateLockTreeNode(), FsRtlFindFirstOverlappingSharedNode(), FsRtlFreeLockTreeNode(), FsRtlSplitLocks(), GreaterThan, _LOCKTREE_NODE::HoleyNode, _LOCKTREE_NODE::Links, Lock, _SH_LOCK::LockInfo, _LOCKTREE_NODE::Locks, NULL, PLOCKTREE_NODE, PSH_LOCK, RtlDeleteNoSplay(), RtlRealSuccessor(), RtlSplay(), _FILE_LOCK_INFO::StartingByte, _LOCKTREE_NODE::Tail, and TRUE.

Referenced by FsRtlPrivateInsertLock().

04350 : 04351 04352 This routine adds a new shared lock record to the File lock's current 04353 lock queue. Locks are inserted into nodes ordered by their starting byte. 04354 04355 Arguments: 04356 04357 LockQueue - Supplies the lock queue being modified 04358 04359 NewLock - Supplies the new shared lock to add to the lock queue 04360 04361 Return Value: 04362 04363 BOOLEAN - True if the insert was successful, False if no resources were avaliable 04364 to complete the operation. 04365 04366 --*/ 04367 { 04368 PSINGLE_LIST_ENTRY pLink, Link; 04369 PRTL_SPLAY_LINKS OverlappedSplayLinks, ParentSplayLinks; 04370 PLOCKTREE_NODE Node, NextNode; 04371 PSH_LOCK NextLock; 04372 BOOLEAN GreaterThan; 04373 04374 OverlappedSplayLinks = FsRtlFindFirstOverlappingSharedNode( LockQueue->SharedLockTree, 04375 &NewLock->LockInfo.StartingByte, 04376 &NewLock->LockInfo.EndingByte, 04377 &ParentSplayLinks, 04378 &GreaterThan ); 04379 04380 if (OverlappedSplayLinks == NULL) { 04381 04382 // 04383 // Simple insert case, build a new node 04384 // 04385 04386 NextNode = FsRtlAllocateLockTreeNode(); 04387 04388 // 04389 // If no resources are avaliable, simply fail now. 04390 // 04391 04392 if (NextNode == NULL) { 04393 04394 return FALSE; 04395 } 04396 04397 RtlInitializeSplayLinks(&NextNode->Links); 04398 NextNode->HoleyNode = FALSE; 04399 04400 NextNode->Locks.Next = NextNode->Tail.Next = &NewLock->Link; 04401 NextNode->Extent = (ULONGLONG)NewLock->LockInfo.EndingByte.QuadPart; 04402 NewLock->Link.Next = NULL; 04403 04404 if (ParentSplayLinks) { 04405 04406 // 04407 // We have a real parent node in the tree 04408 // 04409 04410 if (GreaterThan) { 04411 04412 ASSERT(RtlLeftChild(ParentSplayLinks) == NULL); 04413 RtlInsertAsLeftChild(ParentSplayLinks, &NextNode->Links); 04414 04415 } else { 04416 04417 ASSERT(RtlRightChild(ParentSplayLinks) == NULL); 04418 RtlInsertAsRightChild(ParentSplayLinks, &NextNode->Links); 04419 } 04420 04421 // 04422 // Splay all new nodes in the tree 04423 // 04424 04425 LockQueue->SharedLockTree = RtlSplay(&NextNode->Links); 04426 04427 } else { 04428 04429 // 04430 // First node in the tree 04431 // 04432 04433 LockQueue->SharedLockTree = &NextNode->Links; 04434 } 04435 04436 return TRUE; 04437 } 04438 04439 // 04440 // Now we examine the node to see if it is holey as a result of a resource-failed split. 04441 // If it is, we must complete the split before adding the new lock. 04442 // 04443 04444 Node = CONTAINING_RECORD( OverlappedSplayLinks, LOCKTREE_NODE, Links ); 04445 04446 // 04447 // Search down the overlapped node finding the position for the new lock 04448 // 04449 04450 for (pLink = &Node->Locks; 04451 (Link = pLink->Next) != NULL; 04452 pLink = Link) { 04453 04454 PSH_LOCK Lock; 04455 04456 Lock = CONTAINING_RECORD( Link, SH_LOCK, Link ); 04457 04458 // 04459 // We sort locks on this list first by starting byte, then by whether the length is zero or not. 04460 // This is important so that zero length locks appear prior to non-zero length locks, so that 04461 // they are split out of nodes into the tree in the correct order. 04462 // 04463 // if (NewLock->StartingByte <= Lock->StartingByte) ... 04464 // 04465 04466 if (((ULONGLONG)NewLock->LockInfo.StartingByte.QuadPart < (ULONGLONG)Lock->LockInfo.StartingByte.QuadPart) || 04467 04468 ((ULONGLONG)NewLock->LockInfo.StartingByte.QuadPart == (ULONGLONG)Lock->LockInfo.StartingByte.QuadPart && 04469 (NewLock->LockInfo.Length.QuadPart == 0 || Lock->LockInfo.Length.QuadPart != 0))) { 04470 04471 break; 04472 } 04473 } 04474 04475 // 04476 // At this point pLink points to the record that comes right after 04477 // the new lock that we're inserting so we can simply push the 04478 // newlock into the entrylist 04479 // 04480 04481 DebugTrace(0, Dbg, "InsertSharedLock, Insert Before = %08lx\n", Link); 04482 04483 if (pLink->Next == NULL) { 04484 04485 // 04486 // Adding onto the tail of the list 04487 // 04488 04489 Node->Tail.Next = &NewLock->Link; 04490 } 04491 04492 NewLock->Link.Next = pLink->Next; 04493 pLink->Next = &NewLock->Link; 04494 04495 // 04496 // And splay the node we inserted into 04497 // 04498 04499 LockQueue->SharedLockTree = RtlSplay(OverlappedSplayLinks); 04500 04501 if ((ULONGLONG)NewLock->LockInfo.EndingByte.QuadPart > Node->Extent) { 04502 04503 // 04504 // The new lock extends the range of this node, so fix up the extent 04505 // 04506 04507 Node->Extent = NewLock->LockInfo.EndingByte.QuadPart; 04508 04509 // 04510 // Walk across the remainder of the tree integrating newly overlapping 04511 // nodes into the node we just inserted the new lock into. Note that 04512 // this isn't so much a walk as a repeated examination of our successor's 04513 // until one does not overlap (or we hit the end). 04514 // 04515 04516 ParentSplayLinks = OverlappedSplayLinks; 04517 04518 for (OverlappedSplayLinks = RtlRealSuccessor(ParentSplayLinks); 04519 OverlappedSplayLinks; 04520 OverlappedSplayLinks = RtlRealSuccessor(ParentSplayLinks)) { 04521 04522 NextNode = CONTAINING_RECORD( OverlappedSplayLinks, LOCKTREE_NODE, Links ); 04523 NextLock = CONTAINING_RECORD( NextNode->Locks.Next, SH_LOCK, Link ); 04524 04525 if ((ULONGLONG)NextLock->LockInfo.StartingByte.QuadPart > Node->Extent) { 04526 04527 // 04528 // This node is not overlapped, so stop 04529 // 04530 04531 break; 04532 } 04533 04534 // 04535 // If we are intergrating a holey node into a non-holey node, try to split 04536 // the node first. It will be better to get this done with a smaller node 04537 // than a big, fully integrated one. Note that we are guaranteed that the 04538 // node will remain a candidate for integration since the first lock on the 04539 // node will still be there, and overlaps. 04540 // 04541 04542 if (!Node->HoleyNode && NextNode->HoleyNode) { 04543 04544 FsRtlSplitLocks( NextNode, NULL, NULL, NULL ); 04545 } 04546 04547 // 04548 // Integrate the locks in this node into our list 04549 // 04550 04551 Node->Tail.Next->Next = NextNode->Locks.Next; 04552 Node->Tail.Next = NextNode->Tail.Next; 04553 04554 if (NextNode->Extent > Node->Extent) { 04555 04556 // 04557 // If the node we just swallowed was (still!) holey, we perhaps made this 04558 // node holey too. The resolution of this is left to the lock split we will 04559 // perform after integration is complete. 04560 // 04561 // Note that if the extent of the node we are swallowing is interior 04562 // to the current node, we just covered whatever holes it contained. 04563 // 04564 04565 if (NextNode->HoleyNode) { 04566 04567 Node->HoleyNode = TRUE; 04568 } 04569 04570 Node->Extent = NextNode->Extent; 04571 } 04572 04573 // 04574 // Free the now empty node. 04575 // 04576 04577 RtlDeleteNoSplay( OverlappedSplayLinks, &LockQueue->SharedLockTree ); 04578 FsRtlFreeLockTreeNode( NextNode ); 04579 } 04580 } 04581 04582 // 04583 // Now, perhaps this node is still holey. For grins lets try one more time to split 04584 // this thing apart. 04585 // 04586 04587 if (Node->HoleyNode) { 04588 04589 FsRtlSplitLocks( Node, NULL, NULL, NULL ); 04590 } 04591 04592 // 04593 // And return to our caller 04594 // 04595 04596 return TRUE; 04597 }

BOOLEAN FsRtlPrivateLock IN PFILE_LOCK  FileLock,
IN PFILE_OBJECT  FileObject,
IN PLARGE_INTEGER  FileOffset,
IN PLARGE_INTEGER  Length,
IN PEPROCESS  ProcessId,
IN ULONG  Key,
IN BOOLEAN  FailImmediately,
IN BOOLEAN  ExclusiveLock,
OUT PIO_STATUS_BLOCK  Iosb,
IN PIRP Irp  OPTIONAL,
IN PVOID  Context,
IN BOOLEAN  AlreadySynchronized
 

Definition at line 3867 of file filelock.c.

References _IRP::Cancel, _IRP::CancelIrql, _WAITING_LOCK::Context, Dbg, DebugTrace, _FILE_LOCK_INFO::EndingByte, _FILE_LOCK_INFO::ExclusiveLock, ExRaiseStatus(), FALSE, _FILE_LOCK_INFO::FileObject, FsRtlAcquireLockQueue, FsRtlAllocateWaitingLock(), FsRtlCompleteLockIrp, FsRtlPrivateCancelFileLockIrp(), FsRtlPrivateCheckForExclusiveLockAccess(), FsRtlPrivateCheckForSharedLockAccess(), FsRtlPrivateInitializeFileLock(), FsRtlPrivateInsertLock(), FsRtlPrivateRemoveLock(), FsRtlReleaseLockQueue, IoMarkIrpPending, IoSetCancelRoutine, _IRP::IoStatus, Irp, _WAITING_LOCK::Irp, _FILE_LOCK_INFO::Key, Key, _FILE_LOCK_INFO::Length, _WAITING_LOCK::Link, _LOCK_INFO::LockQueue, NT_SUCCESS, NTSTATUS(), NULL, ObDereferenceObject, ObReferenceObject, PLOCK_INFO, PLOCK_QUEUE, _FILE_LOCK_INFO::ProcessId, PWAITING_LOCK, _FILE_LOCK_INFO::StartingByte, TRUE, try_return, _LOCK_QUEUE::WaitingLocks, and _LOCK_QUEUE::WaitingLocksTail.

Referenced by FsRtlProcessFileLock().

03884 : 03885 03886 This routine preforms a lock operation request. This handles both the fast 03887 get lock and the Irp based get lock. If the Irp is supplied then 03888 this routine will either complete the Irp or enqueue it as a waiting 03889 lock request. 03890 03891 Arguments: 03892 03893 FileLock - Supplies the File Lock to work against 03894 03895 FileObject - Supplies the file object used in this operation 03896 03897 FileOffset - Supplies the file offset used in this operation 03898 03899 Length - Supplies the length used in this operation 03900 03901 ProcessId - Supplies the process ID used in this operation 03902 03903 Key - Supplies the key used in this operation 03904 03905 FailImmediately - Indicates if the request should fail immediately 03906 if the lock cannot be granted. 03907 03908 ExclusiveLock - Indicates if this is a request for an exclusive or 03909 shared lock 03910 03911 Iosb - Receives the Status if this operation is successful 03912 03913 Context - Supplies the context with which to complete Irp with 03914 03915 AlreadySynchronized - Indicates that the caller has already synchronized 03916 access to the file lock so the fields in the file lock and 03917 be updated without further locking, but not the queues. 03918 03919 Return Value: 03920 03921 BOOLEAN - TRUE if this operation completed and FALSE otherwise. 03922 03923 --*/ 03924 03925 { 03926 BOOLEAN Results; 03927 BOOLEAN AccessGranted; 03928 BOOLEAN ViaFastCall; 03929 BOOLEAN ReleaseQueue = FALSE; 03930 03931 PLOCK_INFO LockInfo; 03932 PLOCK_QUEUE LockQueue; 03933 KIRQL OldIrql; 03934 FILE_LOCK_INFO FileLockInfo; 03935 03936 DebugTrace(+1, Dbg, "FsRtlPrivateLock, FileLock = %08lx\n", FileLock); 03937 03938 // 03939 // If the irp is null then this is being called via the fast call method. 03940 // 03941 03942 ViaFastCall = (BOOLEAN) !ARGUMENT_PRESENT( Irp ); 03943 03944 if ((LockInfo = (PLOCK_INFO) FileLock->LockInformation) == NULL) { 03945 DebugTrace(+2, Dbg, "FsRtlPrivateLock, New LockInfo required\n", 0); 03946 03947 // 03948 // No lock information on this FileLock, create the structure. 03949 // 03950 // 03951 03952 if (!FsRtlPrivateInitializeFileLock (FileLock, ViaFastCall)) { 03953 03954 return FALSE; 03955 } 03956 03957 // 03958 // Set flag so file locks will be checked on the fast io 03959 // code paths 03960 // 03961 03962 FileLock->FastIoIsQuestionable = TRUE; 03963 03964 // 03965 // Pickup allocated lockinfo structure 03966 // 03967 03968 LockInfo = (PLOCK_INFO) FileLock->LockInformation; 03969 } 03970 03971 // 03972 // Assume success and build LockData structure prior to acquiring 03973 // the lock queue spinlock. (mp perf enhancement) 03974 // 03975 03976 FileLockInfo.StartingByte = *FileOffset; 03977 FileLockInfo.Length = *Length; 03978 (ULONGLONG)FileLockInfo.EndingByte.QuadPart = 03979 (ULONGLONG)FileLockInfo.StartingByte.QuadPart + (ULONGLONG)FileLockInfo.Length.QuadPart - 1; 03980 03981 FileLockInfo.Key = Key; 03982 FileLockInfo.FileObject = FileObject; 03983 FileLockInfo.ProcessId = ProcessId; 03984 FileLockInfo.ExclusiveLock = ExclusiveLock; 03985 03986 LockQueue = &LockInfo->LockQueue; 03987 03988 // 03989 // Now we need to actually run through our current lock queue. 03990 // 03991 03992 FsRtlAcquireLockQueue(LockQueue, &OldIrql); 03993 ReleaseQueue = TRUE; 03994 03995 try { 03996 03997 // 03998 // Case on whether we're trying to take out an exclusive lock or 03999 // a shared lock. And in both cases try to get appropriate access. 04000 // 04001 04002 if (ExclusiveLock) { 04003 04004 DebugTrace(0, Dbg, "Check for write access\n", 0); 04005 04006 AccessGranted = FsRtlPrivateCheckForExclusiveLockAccess( 04007 LockQueue, 04008 &FileLockInfo ); 04009 04010 } else { 04011 04012 DebugTrace(0, Dbg, "Check for read access\n", 0); 04013 04014 AccessGranted = FsRtlPrivateCheckForSharedLockAccess( 04015 LockQueue, 04016 &FileLockInfo ); 04017 } 04018 04019 // 04020 // Now AccessGranted tells us whether we can really get the access 04021 // for the range we want 04022 // 04023 04024 if (!AccessGranted) { 04025 04026 DebugTrace(0, Dbg, "We do not have access\n", 0); 04027 04028 // 04029 // We cannot read/write to the range, so we cannot take out 04030 // the lock. Now if the user wanted to fail immediately then 04031 // we'll complete the Irp, otherwise we'll enqueue this Irp 04032 // to the waiting lock queue 04033 // 04034 04035 if (FailImmediately) { 04036 04037 // 04038 // Set our status and return, the finally clause will 04039 // complete the request 04040 // 04041 04042 DebugTrace(0, Dbg, "And we fail immediately\n", 0); 04043 04044 Iosb->Status = STATUS_LOCK_NOT_GRANTED; 04045 try_return( Results = TRUE ); 04046 04047 } else if (ARGUMENT_PRESENT(Irp)) { 04048 04049 PWAITING_LOCK WaitingLock; 04050 04051 DebugTrace(0, Dbg, "And we enqueue the Irp for later\n", 0); 04052 04053 // 04054 // Allocate a new waiting record, set it to point to the 04055 // waiting Irp, and insert it in the tail of the waiting 04056 // locks queue 04057 // 04058 04059 WaitingLock = FsRtlAllocateWaitingLock(); 04060 04061 // 04062 // Simply raise out if we can't allocate. 04063 // 04064 04065 if (WaitingLock == NULL) { 04066 04067 ExRaiseStatus( STATUS_INSUFFICIENT_RESOURCES ); 04068 } 04069 04070 WaitingLock->Irp = Irp; 04071 WaitingLock->Context = Context; 04072 IoMarkIrpPending( Irp ); 04073 04074 // 04075 // Add WaitingLock WaitingLockQueue 04076 // 04077 04078 WaitingLock->Link.Next = NULL; 04079 if (LockQueue->WaitingLocks.Next == NULL) { 04080 04081 // 04082 // Create new list 04083 // 04084 04085 LockQueue->WaitingLocks.Next = &WaitingLock->Link; 04086 LockQueue->WaitingLocksTail.Next = &WaitingLock->Link; 04087 04088 } else { 04089 04090 // 04091 // Add waiter to tail of list 04092 // 04093 04094 LockQueue->WaitingLocksTail.Next->Next = &WaitingLock->Link; 04095 LockQueue->WaitingLocksTail.Next = &WaitingLock->Link; 04096 } 04097 04098 04099 // 04100 // Setup IRP in case it's canceled - then set the 04101 // IRP's cancel routine 04102 // 04103 04104 Irp->IoStatus.Information = (ULONG_PTR)LockInfo; 04105 IoSetCancelRoutine( Irp, FsRtlPrivateCancelFileLockIrp ); 04106 04107 if (Irp->Cancel) { 04108 04109 // 04110 // Pull the cancel routine off of the IRP - if it is not 04111 // NULL, this means we won the race with IoCancelIrp and 04112 // will be responsible for cancelling the IRP synchronously. 04113 // If NULL, we lost and our cancel routine is already being 04114 // called for us. 04115 // 04116 // This must be done while holding the lock queue down since 04117 // this is how we synchronize with the cancel. 04118 // 04119 04120 if (IoSetCancelRoutine( Irp, NULL )) { 04121 04122 // 04123 // Irp's cancel routine was not called, do it ourselves. 04124 // Indicate to the cancel routine that he does not need 04125 // to release the cancel spinlock by passing a NULL DO. 04126 // 04127 // The queue will be dropped in order to complete the Irp. 04128 // We communicate the previous IRQL through the Irp itself. 04129 // 04130 04131 Irp->CancelIrql = OldIrql; 04132 FsRtlPrivateCancelFileLockIrp( NULL, Irp ); 04133 ReleaseQueue = FALSE; 04134 } 04135 } 04136 04137 Iosb->Status = STATUS_PENDING; 04138 try_return( Results = TRUE ); 04139 04140 } else { 04141 04142 try_return( Results = FALSE ); 04143 } 04144 } 04145 04146 DebugTrace(0, Dbg, "We have access\n", 0); 04147 04148 if (!FsRtlPrivateInsertLock( LockInfo, FileObject, &FileLockInfo )) { 04149 04150 // 04151 // Resource exhaustion will cause us to fail here. Via the fast call, indicate 04152 // that it may be worthwhile to go around again via the Irp based path. If we 04153 // are already there, simply raise out. 04154 // 04155 04156 if (ViaFastCall) { 04157 04158 try_return( Results = FALSE ); 04159 04160 } else { 04161 04162 ExRaiseStatus( STATUS_INSUFFICIENT_RESOURCES ); 04163 } 04164 04165 } else { 04166 04167 Iosb->Status = STATUS_SUCCESS; 04168 } 04169 04170 // 04171 // At long last, we're done. 04172 // 04173 04174 Results = TRUE; 04175 04176 try_exit: NOTHING; 04177 } finally { 04178 04179 if (ReleaseQueue) { 04180 04181 FsRtlReleaseLockQueue(LockQueue, OldIrql); 04182 } 04183 04184 // 04185 // Complete the request provided we were given one and it is not a pending status 04186 // 04187 04188 if (!AbnormalTermination() && ARGUMENT_PRESENT(Irp) && (Iosb->Status != STATUS_PENDING)) { 04189 04190 NTSTATUS NewStatus; 04191 04192 // 04193 // We must reference the fileobject for the case that the IRP completion 04194 // fails and we need to lift the lock. Although the only reason we have 04195 // to touch the fileobject in the remove case is to unset the LastLock field, 04196 // we have no way of knowing if we will race with a reference count drop 04197 // and lose. 04198 // 04199 04200 ObReferenceObject( FileObject ); 04201 04202 // 04203 // Complete the request, if the don't get back success then 04204 // we need to possibly remove the lock that we just 04205 // inserted. 04206 // 04207 04208 FsRtlCompleteLockIrp( 04209 LockInfo, 04210 Context, 04211 Irp, 04212 Iosb->Status, 04213 &NewStatus, 04214 FileObject ); 04215 04216 if (!NT_SUCCESS(NewStatus) && NT_SUCCESS(Iosb->Status) ) { 04217 04218 // 04219 // Irp failed, remove the lock which was added 04220 // 04221 04222 FsRtlPrivateRemoveLock ( 04223 LockInfo, 04224 &FileLockInfo, 04225 TRUE ); 04226 } 04227 04228 // 04229 // Lift our private reference to the fileobject. This may induce deletion. 04230 // 04231 04232 ObDereferenceObject( FileObject ); 04233 04234 Iosb->Status = NewStatus; 04235 } 04236 04237 DebugTrace(-1, Dbg, "FsRtlPrivateLock -> %08lx\n", Results); 04238 } 04239 04240 // 04241 // and return to our caller 04242 // 04243 04244 return Results; 04245 }

VOID FsRtlPrivateRemoveLock IN PLOCK_INFO  LockInfo,
IN  PFILE_LOCK_INFO,
IN BOOLEAN  CheckForWaiters
 

Definition at line 3162 of file filelock.c.

References ASSERT, FsRtlFastUnlockSingleExclusive(), FsRtlFastUnlockSingleShared(), NTSTATUS(), NULL, Status, and TRUE.

Referenced by FsRtlPrivateCheckWaitingLocks(), and FsRtlPrivateLock().

03170 : 03171 03172 General purpose cleanup routine. Finds the given lock structure 03173 and removes it from the file lock list. Differs from UnlockSingle 03174 only in that it disables the UnlockRoutine of the FileLock and 03175 optionalizes walking the waiting locks list. 03176 03177 Arguments: 03178 03179 FileLock - Supplies the file's lock structure supposedly containing a stale lock 03180 03181 FileLockInfo - Supplies file lock data being freed 03182 03183 CheckForWaiters - If true check for possible waiting locks, caused 03184 by freeing the locked range 03185 03186 Return Value: 03187 03188 None. 03189 03190 --*/ 03191 03192 { 03193 NTSTATUS Status; 03194 03195 if (FileLockInfo->ExclusiveLock) { 03196 03197 // 03198 // We must find it in the exclusive lock tree 03199 // 03200 03201 Status = FsRtlFastUnlockSingleExclusive( LockInfo, 03202 03203 FileLockInfo->FileObject, 03204 &FileLockInfo->StartingByte, 03205 &FileLockInfo->Length, 03206 FileLockInfo->ProcessId, 03207 FileLockInfo->Key, 03208 03209 NULL, 03210 TRUE, 03211 CheckForWaiters ); 03212 03213 ASSERT( Status == STATUS_SUCCESS); 03214 03215 } else { 03216 03217 // 03218 // We must find it in the shared lock tree 03219 // 03220 03221 Status = FsRtlFastUnlockSingleShared( LockInfo, 03222 03223 FileLockInfo->FileObject, 03224 &FileLockInfo->StartingByte, 03225 &FileLockInfo->Length, 03226 FileLockInfo->ProcessId, 03227 FileLockInfo->Key, 03228 03229 NULL, 03230 TRUE, 03231 CheckForWaiters ); 03232 03233 ASSERT( Status == STATUS_SUCCESS); 03234 } 03235 03236 return; 03237 }

VOID FsRtlPrivateResetLowestLockOffset PLOCK_INFO  LockInfo  ) 
 

Definition at line 5150 of file filelock.c.

References _LOCK_QUEUE::ExclusiveLockTree, _SH_LOCK::LockInfo, _EX_LOCK::LockInfo, _LOCK_INFO::LockQueue, _LOCKTREE_NODE::Locks, _LOCK_INFO::LowestLockOffset, NULL, PEX_LOCK, PLOCKTREE_NODE, PSH_LOCK, _LOCK_QUEUE::SharedLockTree, and _FILE_LOCK_INFO::StartingByte.

Referenced by FsRtlFastUnlockSingleExclusive(), FsRtlFastUnlockSingleShared(), and FsRtlPrivateFastUnlockAll().

05156 : 05157 05158 This routine resets the lowest lock offset hint in a LOCK_INFO to 05159 the lowest lock offset currently held by a lock inside of the LOCK_INFO. 05160 05161 Arguments: 05162 05163 LockInfo - the lock data to operate on 05164 05165 Return Value: 05166 05167 None 05168 05169 --*/ 05170 05171 { 05172 PEX_LOCK ExLock = NULL; 05173 PSH_LOCK ShLock = NULL; 05174 PFILE_LOCK_INFO LowestLockInfo = NULL; 05175 PRTL_SPLAY_LINKS SplayLinks; 05176 PLOCKTREE_NODE Node; 05177 05178 // 05179 // Fix up the lowest lock offset if we have non-empty trees and there was 05180 // a lock in the low 32 bit region 05181 // 05182 05183 if (LockInfo->LowestLockOffset != 0xffffffff && 05184 (LockInfo->LockQueue.SharedLockTree != NULL || 05185 LockInfo->LockQueue.ExclusiveLockTree != NULL)) { 05186 05187 // 05188 // Grab the lowest nodes in the trees 05189 // 05190 05191 if (LockInfo->LockQueue.SharedLockTree) { 05192 05193 SplayLinks = LockInfo->LockQueue.SharedLockTree; 05194 05195 while (RtlLeftChild(SplayLinks) != NULL) { 05196 05197 SplayLinks = RtlLeftChild(SplayLinks); 05198 } 05199 05200 Node = CONTAINING_RECORD( SplayLinks, LOCKTREE_NODE, Links ); 05201 ShLock = CONTAINING_RECORD( Node->Locks.Next, SH_LOCK, Link ); 05202 } 05203 05204 if (LockInfo->LockQueue.ExclusiveLockTree) { 05205 05206 SplayLinks = LockInfo->LockQueue.ExclusiveLockTree; 05207 05208 while (RtlLeftChild(SplayLinks) != NULL) { 05209 05210 SplayLinks = RtlLeftChild(SplayLinks); 05211 } 05212 05213 ExLock = CONTAINING_RECORD( SplayLinks, EX_LOCK, Links ); 05214 } 05215 05216 // 05217 // Figure out which of the lowest locks is actually lowest. We know that one of the lock 05218 // trees at least has a lock, so if we have don't have exclusive locks then we do know 05219 // we have shared locks ... 05220 // 05221 05222 if (ExLock && 05223 (!ShLock || 05224 (ULONGLONG)ExLock->LockInfo.StartingByte.QuadPart < (ULONGLONG)ShLock->LockInfo.StartingByte.QuadPart)) { 05225 05226 LowestLockInfo = &ExLock->LockInfo; 05227 05228 } else { 05229 05230 LowestLockInfo = &ShLock->LockInfo; 05231 } 05232 05233 if (LowestLockInfo->StartingByte.HighPart == 0) { 05234 05235 LockInfo->LowestLockOffset = LowestLockInfo->StartingByte.LowPart; 05236 05237 } else { 05238 05239 LockInfo->LowestLockOffset = 0xffffffff; 05240 } 05241 05242 } else { 05243 05244 // 05245 // If there are no locks, set the lock offset high 05246 // 05247 05248 LockInfo->LowestLockOffset = 0xffffffff; 05249 } 05250 }

NTSTATUS FsRtlProcessFileLock IN PFILE_LOCK  FileLock,
IN PIRP  Irp,
IN PVOID Context  OPTIONAL
 

Definition at line 1173 of file filelock.c.

References ASSERT, BooleanFlagOn, Dbg, DebugTrace, FALSE, _IO_STACK_LOCATION::FileObject, _IO_STACK_LOCATION::Flags, FsRtlCompleteLockIrp, FsRtlCompleteRequest, FsRtlFastUnlockAll(), FsRtlFastUnlockAllByKey(), FsRtlFastUnlockSingle(), FsRtlPrivateLock(), IoGetCurrentIrpStackLocation, IoGetRequestorProcess(), Irp, IRP_MJ_LOCK_CONTROL, IRP_MN_LOCK, IRP_MN_UNLOCK_ALL, IRP_MN_UNLOCK_ALL_BY_KEY, IRP_MN_UNLOCK_SINGLE, _IO_STACK_LOCATION::MajorFunction, _IO_STACK_LOCATION::MinorFunction, NTSTATUS(), NULL, _IO_STACK_LOCATION::Parameters, SL_EXCLUSIVE_LOCK, SL_FAIL_IMMEDIATELY, Status, and VOID().

Referenced by UdfCommonLockControl().

01181 : 01182 01183 This routine processes a file lock IRP it does either a lock request, 01184 or an unlock request. It also completes the IRP. Once called the user 01185 (i.e., File System) has relinquished control of the input IRP. 01186 01187 If pool is not available to store the information this routine will raise a 01188 status value indicating insufficient resources. 01189 01190 Arguments: 01191 01192 FileLock - Supplies the File lock being modified/queried. 01193 01194 Irp - Supplies the Irp being processed. 01195 01196 Context - Optionally supplies a context to use when calling the user 01197 alternate IRP completion routine. 01198 01199 Return Value: 01200 01201 NTSTATUS - The return status for the operation. 01202 01203 --*/ 01204 01205 { 01206 PIO_STACK_LOCATION IrpSp; 01207 01208 IO_STATUS_BLOCK Iosb; 01209 NTSTATUS Status; 01210 LARGE_INTEGER ByteOffset; 01211 01212 DebugTrace(+1, Dbg, "FsRtlProcessFileLock, FileLock = %08lx\n", FileLock); 01213 01214 Iosb.Information = 0; 01215 01216 // 01217 // Get a pointer to the current Irp stack location and assert that 01218 // the major function code is for a lock operation 01219 // 01220 01221 IrpSp = IoGetCurrentIrpStackLocation( Irp ); 01222 01223 ASSERT( IrpSp->MajorFunction == IRP_MJ_LOCK_CONTROL ); 01224 01225 // 01226 // Now process the different minor lock operations 01227 // 01228 01229 switch (IrpSp->MinorFunction) { 01230 01231 case IRP_MN_LOCK: 01232 01233 ByteOffset = IrpSp->Parameters.LockControl.ByteOffset; 01234 01235 (VOID) FsRtlPrivateLock( FileLock, 01236 IrpSp->FileObject, 01237 &ByteOffset, 01238 IrpSp->Parameters.LockControl.Length, 01239 IoGetRequestorProcess(Irp), 01240 IrpSp->Parameters.LockControl.Key, 01241 BooleanFlagOn(IrpSp->Flags, SL_FAIL_IMMEDIATELY), 01242 BooleanFlagOn(IrpSp->Flags, SL_EXCLUSIVE_LOCK), 01243 &Iosb, 01244 Irp, 01245 Context, 01246 FALSE ); 01247 01248 break; 01249 01250 case IRP_MN_UNLOCK_SINGLE: 01251 01252 ByteOffset = IrpSp->Parameters.LockControl.ByteOffset; 01253 01254 Iosb.Status = FsRtlFastUnlockSingle( FileLock, 01255 IrpSp->FileObject, 01256 &ByteOffset, 01257 IrpSp->Parameters.LockControl.Length, 01258 IoGetRequestorProcess(Irp), 01259 IrpSp->Parameters.LockControl.Key, 01260 Context, 01261 FALSE ); 01262 01263 FsRtlCompleteLockIrp( FileLock, Context, Irp, Iosb.Status, &Status, NULL ); 01264 break; 01265 01266 case IRP_MN_UNLOCK_ALL: 01267 01268 Iosb.Status = FsRtlFastUnlockAll( FileLock, 01269 IrpSp->FileObject, 01270 IoGetRequestorProcess(Irp), 01271 Context ); 01272 01273 FsRtlCompleteLockIrp( FileLock, Context, Irp, Iosb.Status, &Status, NULL ); 01274 break; 01275 01276 case IRP_MN_UNLOCK_ALL_BY_KEY: 01277 01278 Iosb.Status = FsRtlFastUnlockAllByKey( FileLock, 01279 IrpSp->FileObject, 01280 IoGetRequestorProcess(Irp), 01281 IrpSp->Parameters.LockControl.Key, 01282 Context ); 01283 01284 FsRtlCompleteLockIrp( FileLock, Context, Irp, Iosb.Status, &Status, NULL ); 01285 break; 01286 01287 default: 01288 01289 // 01290 // For all other minor function codes we say they're invalid and 01291 // complete the request. Note that the IRP has not been marked 01292 // pending so this error will be returned directly to the caller. 01293 // 01294 01295 DebugTrace(0, 1, "Invalid LockFile Minor Function Code %08lx\n", IrpSp->MinorFunction); 01296 01297 01298 FsRtlCompleteRequest( Irp, STATUS_INVALID_DEVICE_REQUEST ); 01299 01300 Iosb.Status = STATUS_INVALID_DEVICE_REQUEST; 01301 break; 01302 } 01303 01304 // 01305 // And return to our caller 01306 // 01307 01308 DebugTrace(-1, Dbg, "FsRtlProcessFileLock -> %08lx\n", Iosb.Status); 01309 01310 return Iosb.Status; 01311 }

VOID FsRtlSplitLocks IN PLOCKTREE_NODE  ParentNode,
IN PSINGLE_LIST_ENTRY *pStartLink  OPTIONAL,
IN PLARGE_INTEGER LastShadowedByte  OPTIONAL,
IN PLARGE_INTEGER GlueOffset  OPTIONAL
 

Definition at line 2865 of file filelock.c.

References ASSERT, _LOCKTREE_NODE::Extent, FALSE, FsRtlAllocateLockTreeNode(), _LOCKTREE_NODE::HoleyNode, _LOCKTREE_NODE::Links, Lock, _LOCKTREE_NODE::Locks, NULL, PLOCKTREE_NODE, PSH_LOCK, RtlRealSuccessor(), _LOCKTREE_NODE::Tail, and TRUE.

Referenced by FsRtlFastUnlockSingleShared(), FsRtlPrivateFastUnlockAll(), and FsRtlPrivateInsertSharedLock().

02873 : 02874 02875 This routine examines and possibly splits off shared locks associated 02876 with a node into new nodes of the lock tree. Called from routines that 02877 have just deleted locks. 02878 02879 The arguments that supply the initial conditions for the operation are 02880 optional if the node is known to be holey. 02881 02882 Arguments: 02883 02884 ParentNode- Supplies the node the locks are coming from 02885 02886 pStartLink - Supplies the pointer to the link address of the start of the 02887 range of locks in the ParentNode's locklist that need to be checked 02888 02889 LastShadowedByte - Supplies the last byte offset that needs to be checked 02890 02891 GlueOffset - Supplies the maximum offset affected by locks prior to this 02892 point in the list 02893 02894 Return Value: 02895 02896 BOOLEAN - True if the split was successful, False otherwise. The node will 02897 be marked as Holey if the split could not occur. 02898 02899 --*/ 02900 { 02901 PSH_LOCK Lock; 02902 PLOCKTREE_NODE NewNode; 02903 PSINGLE_LIST_ENTRY Link, *pLink, *NextpLink; 02904 LARGE_INTEGER MaxOffset, StartOffset, HaltOffset; 02905 02906 BOOLEAN ExtentValid; 02907 BOOLEAN FailedHoleySplit = FALSE; 02908 02909 // 02910 // There are two cases: the node is holey or not. If the node is holey, at some 02911 // point we failed to get resources to complete a split, so despite our caller's 02912 // good intentions we need to go over the entire node. 02913 // 02914 02915 if (ParentNode->HoleyNode) { 02916 02917 // 02918 // Just move the starting link back to the front. The maximum offset and 02919 // starting offset of the node will be initialized in the loop. We also turn 02920 // off the holey flag, which will be turned on again as appropriate. 02921 // 02922 02923 pStartLink = &ParentNode->Locks.Next; 02924 ParentNode->HoleyNode = FALSE; 02925 02926 HaltOffset.QuadPart = ParentNode->Extent; 02927 02928 } else { 02929 02930 HaltOffset = *LastShadowedByte; 02931 MaxOffset = *GlueOffset; 02932 StartOffset.QuadPart = 0; 02933 02934 if (!ParentNode->Locks.Next || 02935 (ULONGLONG)HaltOffset.QuadPart <= (ULONGLONG)MaxOffset.QuadPart) { 02936 02937 // 02938 // The parent node is not there, doesn't have links associated, or the 02939 // last possible byte that is affected by the operation our caller made 02940 // is interior to the max extent of all locks still in this node - in 02941 // which case there is nothing that needs to be done. 02942 // 02943 02944 return; 02945 } 02946 } 02947 02948 // 02949 // If the extent of the node is past the last byte affected by whatever 02950 // operations were done to this node, we can avoid the linear scan of 02951 // the list past that last affected byte since we already know the 02952 // extent of the entire list! If it is not (note that it would have to 02953 // be equal - by defintion) then we need to recalculate the extents of 02954 // all nodes we touch in this operation. 02955 // 02956 02957 ExtentValid = (ParentNode->Extent > (ULONGLONG)HaltOffset.QuadPart); 02958 02959 for (pLink = pStartLink; 02960 (Link = *pLink) != NULL; 02961 pLink = NextpLink) { 02962 02963 NextpLink = &Link->Next; 02964 02965 Lock = CONTAINING_RECORD( Link, SH_LOCK, Link ); 02966 02967 if (ParentNode->Locks.Next == *pLink) { 02968 02969 // 02970 // We're at the first lock in the node, and we know that we're going to leave 02971 // at least one lock here. Skip over that lock. We also know that the max 02972 // offset must be that locks's ending byte - make sure it is. Note that this 02973 // code is *exactly* the same as the update MaxOffset code at the bottom of 02974 // the loop. 02975 // 02976 02977 MaxOffset.QuadPart = Lock->LockInfo.EndingByte.QuadPart; 02978 02979 // 02980 // Set the starting offset of the node. This is only an issue for zero length 02981 // locks, so that we can figure out what is going on if we split a node and wind 02982 // up with some number of "overlapped" zero length locks at the front of the new 02983 // node. We must be able to notice this case, and not think that each needs to 02984 // be in a seperate node. 02985 // 02986 02987 StartOffset.QuadPart = Lock->LockInfo.StartingByte.QuadPart; 02988 02989 // 02990 // If extents are invalid we also need to set it in case this turns out to 02991 // be the only lock at this node. 02992 // 02993 02994 if (!ExtentValid) { 02995 02996 ParentNode->Extent = (ULONGLONG)MaxOffset.QuadPart; 02997 } 02998 02999 continue; 03000 } 03001 03002 // 03003 // If the lock begins at a byte offset greater than the maximum offset seen to this 03004 // point, AND this is not a zero length node starting at the beginning of this node, 03005 // break the node. The second half of the test keeps co-incident zero length locks 03006 // in the same node. (zero length lock ---> starting = ending + 1). 03007 // 03008 03009 if ((ULONGLONG)Lock->LockInfo.StartingByte.QuadPart > (ULONGLONG)MaxOffset.QuadPart && 03010 !(Lock->LockInfo.Length.QuadPart == 0 && 03011 Lock->LockInfo.StartingByte.QuadPart == StartOffset.QuadPart)) { 03012 03013 // 03014 // Break the node up here 03015 // 03016 03017 NewNode = FsRtlAllocateLockTreeNode(); 03018 03019 if (NewNode == NULL) { 03020 03021 // 03022 // If we are out of resources, this node is now holey - we know that the locks at 03023 // this node do not completely cover the indicated range. Keep splitting for two 03024 // reasons: more resources may become avaliable, and we must keep updating the 03025 // node's extent if it is known to be invalid. 03026 // 03027 03028 // 03029 // Now if this node was already holey it is not possible to state that, if we 03030 // manage to split if further as we keep walking, that the resulting "left" node 03031 // is not holey. See below. 03032 // 03033 03034 if (ParentNode->HoleyNode) { 03035 03036 FailedHoleySplit = TRUE; 03037 } 03038 03039 ParentNode->HoleyNode = TRUE; 03040 03041 } else { 03042 03043 // 03044 // Initialize the node. 03045 // 03046 03047 RtlInitializeSplayLinks(&NewNode->Links); 03048 NewNode->HoleyNode = FALSE; 03049 03050 // 03051 // Find the spot in the tree to take the new node(s). If the current node has 03052 // a free right child, we use it, else find the successor node and use its 03053 // left child. One of these cases must be avaliable since we know there are 03054 // no nodes between this node and its successor. 03055 // 03056 03057 if (RtlRightChild(&ParentNode->Links) == NULL) { 03058 03059 RtlInsertAsRightChild(&ParentNode->Links, &NewNode->Links); 03060 03061 } else { 03062 03063 ASSERT(RtlLeftChild(RtlRealSuccessor(&ParentNode->Links)) == NULL); 03064 RtlInsertAsLeftChild(RtlRealSuccessor(&ParentNode->Links), &NewNode->Links); 03065 } 03066 03067 // 03068 // Move the remaining locks over to the new node and fix up extents 03069 // 03070 03071 NewNode->Locks.Next = *pLink; 03072 *pLink = NULL; 03073 03074 NewNode->Tail.Next = ParentNode->Tail.Next; 03075 ParentNode->Tail.Next = CONTAINING_RECORD( pLink, SINGLE_LIST_ENTRY, Next ); 03076 03077 // 03078 // This will cause us to fall into the first-lock clause above on the next pass 03079 // 03080 03081 NextpLink = &NewNode->Locks.Next; 03082 03083 // 03084 // The new node's extent is now copied from the parent. The old node's extent must be 03085 // the maximum offset we have seen to this point. 03086 // 03087 // Note that if ExtentValid is true, that must mean that the lock ending at that extent 03088 // is in the new node since if it was in the old node we wouldn't have been able to split. 03089 // 03090 03091 NewNode->Extent = ParentNode->Extent; 03092 ParentNode->Extent = (ULONGLONG)MaxOffset.QuadPart; 03093 03094 // 03095 // The parent node can no longer be holey if we have not failed a split in this node. 03096 // 03097 03098 if (!FailedHoleySplit) { 03099 03100 ParentNode->HoleyNode = FALSE; 03101 03102 } else { 03103 03104 // 03105 // So reset the failure flag for the new node. 03106 // 03107 03108 FailedHoleySplit = FALSE; 03109 } 03110 03111 // 03112 // Move over to the new node. 03113 // 03114 03115 ParentNode = NewNode; 03116 03117 continue; 03118 } 03119 } 03120 03121 if (ExtentValid && 03122 (ULONGLONG)Lock->LockInfo.StartingByte.QuadPart > (ULONGLONG)HaltOffset.QuadPart) { 03123 03124 // 03125 // Our extents are good and this lock is past the shadow, so we can stop 03126 // 03127 03128 return; 03129 } 03130 03131 if ((ULONGLONG)MaxOffset.QuadPart < (ULONGLONG)Lock->LockInfo.EndingByte.QuadPart) { 03132 03133 // 03134 // Update maximum offset 03135 // 03136 03137 MaxOffset.QuadPart = Lock->LockInfo.EndingByte.QuadPart; 03138 03139 if (!ExtentValid) { 03140 03141 // 03142 // Extents are not good so we must update the extent 03143 // 03144 03145 ParentNode->Extent = (ULONGLONG)MaxOffset.QuadPart; 03146 } 03147 } 03148 } 03149 03150 // 03151 // Reached the end of the list, so update the extent (case of all subsequent locks 03152 // having been interior to GlueOffset) 03153 // 03154 03155 ParentNode->Extent = (ULONGLONG)MaxOffset.QuadPart; 03156 03157 return; 03158 }

VOID FsRtlSplitLocks IN PLOCKTREE_NODE  ParentNode,
IN PSINGLE_LIST_ENTRY *  pStartLink,
IN PLARGE_INTEGER  LastShadowedByte,
IN PLARGE_INTEGER  GlueOffset
 

VOID FsRtlUninitializeFileLock IN PFILE_LOCK  FileLock  ) 
 

Definition at line 995 of file filelock.c.

References _IRP::CancelIrql, _WAITING_LOCK::Context, Dbg, DebugTrace, _LOCK_QUEUE::ExclusiveLockTree, FsRtlAcquireLockQueue, FsRtlCompleteLockIrp, FsRtlFreeExclusiveLock(), FsRtlFreeLockInfo(), FsRtlFreeLockTreeNode(), FsRtlFreeSharedLock(), FsRtlFreeWaitingLock(), FsRtlReleaseLockQueue, IoAcquireCancelSpinLock(), IoReleaseCancelSpinLock(), IoSetCancelRoutine, _IRP::IoStatus, Irp, _WAITING_LOCK::Irp, _LOCKTREE_NODE::Links, _EX_LOCK::Links, _LOCK_INFO::LockQueue, _LOCKTREE_NODE::Locks, NTSTATUS(), NULL, PEX_LOCK, PLOCK_INFO, PLOCKTREE_NODE, PSH_LOCK, PWAITING_LOCK, RtlDeleteNoSplay(), _LOCK_QUEUE::SharedLockTree, and _LOCK_QUEUE::WaitingLocks.

Referenced by FsRtlFreeFileLock().

01001 : 01002 01003 This routine uninitializes a FILE_LOCK structure. After calling this 01004 routine the File lock must be reinitialized before being used again. 01005 01006 This routine will free all files locks and completes any outstanding 01007 lock requests as a result of cleaning itself up. 01008 01009 Arguments: 01010 01011 FileLock - Supplies a pointer to the FILE_LOCK struture being 01012 decommissioned. 01013 01014 Return Value: 01015 01016 None. 01017 01018 --*/ 01019 01020 { 01021 PLOCK_INFO LockInfo; 01022 PSH_LOCK ShLock; 01023 PEX_LOCK ExLock; 01024 PSINGLE_LIST_ENTRY Link; 01025 PWAITING_LOCK WaitingLock; 01026 PLOCKTREE_NODE LockTreeNode; 01027 PIRP Irp; 01028 NTSTATUS NewStatus; 01029 KIRQL OldIrql; 01030 PKPRCB Prcb; 01031 01032 DebugTrace(+1, Dbg, "FsRtlUninitializeFileLock, FileLock = %08lx\n", FileLock); 01033 01034 if ((LockInfo = (PLOCK_INFO) FileLock->LockInformation) == NULL) { 01035 return ; 01036 } 01037 01038 // 01039 // Lock the queue 01040 // 01041 01042 FsRtlAcquireLockQueue(&LockInfo->LockQueue, &OldIrql); 01043 01044 // 01045 // Free lock trees 01046 // 01047 01048 while (LockInfo->LockQueue.SharedLockTree != NULL) { 01049 01050 LockTreeNode = CONTAINING_RECORD(LockInfo->LockQueue.SharedLockTree, LOCKTREE_NODE, Links); 01051 01052 // 01053 // Remove all locks associated with the root node 01054 // 01055 01056 while (LockTreeNode->Locks.Next != NULL) { 01057 Link = PopEntryList (&LockTreeNode->Locks); 01058 ShLock = CONTAINING_RECORD( Link, SH_LOCK, Link ); 01059 01060 FsRtlFreeSharedLock(ShLock); 01061 } 01062 01063 // 01064 // Slice off the root node of the tree 01065 // 01066 01067 RtlDeleteNoSplay(&LockTreeNode->Links, &LockInfo->LockQueue.SharedLockTree); 01068 01069 FsRtlFreeLockTreeNode(LockTreeNode); 01070 } 01071 01072 while (LockInfo->LockQueue.ExclusiveLockTree != NULL) { 01073 01074 ExLock = CONTAINING_RECORD(LockInfo->LockQueue.ExclusiveLockTree, EX_LOCK, Links); 01075 01076 RtlDeleteNoSplay(&ExLock->Links, &LockInfo->LockQueue.ExclusiveLockTree); 01077 01078 FsRtlFreeExclusiveLock(ExLock); 01079 } 01080 01081 // 01082 // Free WaitingLockQueue 01083 // 01084 01085 while (LockInfo->LockQueue.WaitingLocks.Next != NULL) { 01086 01087 Link = PopEntryList( &LockInfo->LockQueue.WaitingLocks ); 01088 WaitingLock = CONTAINING_RECORD( Link, WAITING_LOCK, Link ); 01089 01090 Irp = WaitingLock->Irp; 01091 01092 // 01093 // To complete an irp in the waiting queue we need to 01094 // void the cancel routine (protected by a spinlock) before 01095 // we can complete the irp 01096 // 01097 01098 FsRtlReleaseLockQueue (&LockInfo->LockQueue, OldIrql); 01099 01100 IoAcquireCancelSpinLock( &Irp->CancelIrql ); 01101 IoSetCancelRoutine( Irp, NULL ); 01102 IoReleaseCancelSpinLock( Irp->CancelIrql ); 01103 01104 Irp->IoStatus.Information = 0; 01105 01106 FsRtlCompleteLockIrp( 01107 LockInfo, 01108 WaitingLock->Context, 01109 Irp, 01110 STATUS_RANGE_NOT_LOCKED, 01111 &NewStatus, 01112 NULL ); 01113 01114 FsRtlAcquireLockQueue(&LockInfo->LockQueue, &OldIrql); 01115 FsRtlFreeWaitingLock( WaitingLock ); 01116 } 01117 01118 // 01119 // Free pool used to track the lock info on this file 01120 // 01121 01122 FsRtlReleaseLockQueue( &LockInfo->LockQueue, OldIrql ); 01123 FsRtlFreeLockInfo( LockInfo ); 01124 01125 // 01126 // Unlink LockInfo from FileLock 01127 // 01128 01129 FileLock->LockInformation = NULL; 01130 01131 // 01132 // And return to our caller 01133 // 01134 01135 DebugTrace(-1, Dbg, "FsRtlUninitializeFileLock -> VOID\n", 0 ); 01136 return; 01137 }


Variable Documentation

FAST_MUTEX FsRtlCreateLockInfo
 

Definition at line 119 of file filelock.c.

Referenced by FsRtlInitializeFileLocks(), and FsRtlPrivateInitializeFileLock().

NPAGED_LOOKASIDE_LIST FsRtlExclusiveLockLookasideList
 

Definition at line 132 of file filelock.c.

Referenced by FsRtlAllocateExclusiveLock(), FsRtlFreeExclusiveLock(), and FsRtlInitializeFileLocks().

PAGED_LOOKASIDE_LIST FsRtlFileLockLookasideList
 

Definition at line 137 of file filelock.c.

Referenced by FsRtlAllocateFileLock(), FsRtlFreeFileLock(), and FsRtlInitializeFileLocks().

NPAGED_LOOKASIDE_LIST FsRtlLockInfoLookasideList
 

Definition at line 135 of file filelock.c.

Referenced by FsRtlAllocateLockInfo(), FsRtlFreeLockInfo(), and FsRtlInitializeFileLocks().

NPAGED_LOOKASIDE_LIST FsRtlLockTreeNodeLookasideList
 

Definition at line 134 of file filelock.c.

Referenced by FsRtlAllocateLockTreeNode(), FsRtlFreeLockTreeNode(), and FsRtlInitializeFileLocks().

NPAGED_LOOKASIDE_LIST FsRtlSharedLockLookasideList
 

Definition at line 131 of file filelock.c.

Referenced by FsRtlAllocateSharedLock(), FsRtlFreeSharedLock(), and FsRtlInitializeFileLocks().

NPAGED_LOOKASIDE_LIST FsRtlWaitingLockLookasideList
 

Definition at line 133 of file filelock.c.

Referenced by FsRtlAllocateWaitingLock(), FsRtlFreeWaitingLock(), and FsRtlInitializeFileLocks().


Generated on Sat May 15 19:43:40 2004 for test by doxygen 1.3.7