ReactOS 0.4.17-dev-573-g8315b8c
filelock.c File Reference
#include <ntoskrnl.h>
#include <debug.h>
Include dependency graph for filelock.c:

Go to the source code of this file.

Classes

union  _COMBINED_LOCK_ELEMENT
 
struct  _LOCK_INFORMATION
 
struct  _LOCK_SHARED_RANGE
 

Macros

#define NDEBUG
 

Typedefs

typedef union _COMBINED_LOCK_ELEMENT COMBINED_LOCK_ELEMENT
 
typedef union _COMBINED_LOCK_ELEMENTPCOMBINED_LOCK_ELEMENT
 
typedef struct _LOCK_INFORMATION LOCK_INFORMATION
 
typedef struct _LOCK_INFORMATIONPLOCK_INFORMATION
 
typedef struct _LOCK_SHARED_RANGE LOCK_SHARED_RANGE
 
typedef struct _LOCK_SHARED_RANGEPLOCK_SHARED_RANGE
 

Functions

VOID NTAPI FsRtlCompleteLockIrpReal (IN PCOMPLETE_LOCK_IRP_ROUTINE CompleteRoutine, IN PVOID Context, IN PIRP Irp, IN NTSTATUS Status, OUT PNTSTATUS NewStatus, IN PFILE_OBJECT FileObject OPTIONAL)
 
static PVOID NTAPI LockAllocate (PRTL_GENERIC_TABLE Table, CLONG Bytes)
 
static VOID NTAPI LockFree (PRTL_GENERIC_TABLE Table, PVOID Buffer)
 
static RTL_GENERIC_COMPARE_RESULTS NTAPI LockCompare (PRTL_GENERIC_TABLE Table, PVOID PtrA, PVOID PtrB)
 
static NTSTATUS NTAPI LockInsertIrpEx (PIO_CSQ Csq, PIRP Irp, PVOID InsertContext)
 
static VOID NTAPI LockRemoveIrp (PIO_CSQ Csq, PIRP Irp)
 
static PIRP NTAPI LockPeekNextIrp (PIO_CSQ Csq, PIRP Irp, PVOID PeekContext)
 
static VOID NTAPI LockAcquireQueueLock (PIO_CSQ Csq, PKIRQL Irql)
 
static VOID NTAPI LockReleaseQueueLock (PIO_CSQ Csq, KIRQL Irql)
 
static VOID NTAPI LockCompleteCanceledIrp (PIO_CSQ Csq, PIRP Irp)
 
PFILE_LOCK_INFO NTAPI FsRtlGetNextFileLock (IN PFILE_LOCK FileLock, IN BOOLEAN Restart)
 
VOID NTAPI FsRtlpExpandLockElement (PCOMBINED_LOCK_ELEMENT ToExpand, PCOMBINED_LOCK_ELEMENT Conflict)
 
PCOMBINED_LOCK_ELEMENT NTAPI FsRtlpRebuildSharedLockRange (PFILE_LOCK FileLock, PLOCK_INFORMATION LockInfo, PCOMBINED_LOCK_ELEMENT Conflict)
 
BOOLEAN NTAPI FsRtlPrivateLock (IN PFILE_LOCK FileLock, IN PFILE_OBJECT FileObject, IN PLARGE_INTEGER FileOffset, IN PLARGE_INTEGER Length, IN PEPROCESS Process, IN ULONG Key, IN BOOLEAN FailImmediately, IN BOOLEAN ExclusiveLock, OUT PIO_STATUS_BLOCK IoStatus, IN PIRP Irp OPTIONAL, IN PVOID Context OPTIONAL, IN BOOLEAN AlreadySynchronized)
 
BOOLEAN NTAPI FsRtlCheckLockForReadAccess (IN PFILE_LOCK FileLock, IN PIRP Irp)
 
BOOLEAN NTAPI FsRtlCheckLockForWriteAccess (IN PFILE_LOCK FileLock, IN PIRP Irp)
 
BOOLEAN NTAPI FsRtlFastCheckLockForRead (IN PFILE_LOCK FileLock, IN PLARGE_INTEGER FileOffset, IN PLARGE_INTEGER Length, IN ULONG Key, IN PFILE_OBJECT FileObject, IN PVOID Process)
 
BOOLEAN NTAPI FsRtlFastCheckLockForWrite (IN PFILE_LOCK FileLock, IN PLARGE_INTEGER FileOffset, IN PLARGE_INTEGER Length, IN ULONG Key, IN PFILE_OBJECT FileObject, IN PVOID Process)
 
NTSTATUS NTAPI FsRtlFastUnlockSingle (IN PFILE_LOCK FileLock, IN PFILE_OBJECT FileObject, IN PLARGE_INTEGER FileOffset, IN PLARGE_INTEGER Length, IN PEPROCESS Process, IN ULONG Key, IN PVOID Context OPTIONAL, IN BOOLEAN AlreadySynchronized)
 
NTSTATUS NTAPI FsRtlFastUnlockAll (IN PFILE_LOCK FileLock, IN PFILE_OBJECT FileObject, IN PEPROCESS Process, IN PVOID Context OPTIONAL)
 
NTSTATUS NTAPI FsRtlFastUnlockAllByKey (IN PFILE_LOCK FileLock, IN PFILE_OBJECT FileObject, IN PEPROCESS Process, IN ULONG Key, IN PVOID Context OPTIONAL)
 
NTSTATUS NTAPI FsRtlProcessFileLock (IN PFILE_LOCK FileLock, IN PIRP Irp, IN PVOID Context OPTIONAL)
 
VOID NTAPI FsRtlInitializeFileLock (IN PFILE_LOCK FileLock, IN PCOMPLETE_LOCK_IRP_ROUTINE CompleteLockIrpRoutine OPTIONAL, IN PUNLOCK_ROUTINE UnlockRoutine OPTIONAL)
 
VOID NTAPI FsRtlUninitializeFileLock (IN PFILE_LOCK FileLock)
 
PFILE_LOCK NTAPI FsRtlAllocateFileLock (IN PCOMPLETE_LOCK_IRP_ROUTINE CompleteLockIrpRoutine OPTIONAL, IN PUNLOCK_ROUTINE UnlockRoutine OPTIONAL)
 
VOID NTAPI FsRtlFreeFileLock (IN PFILE_LOCK FileLock)
 

Variables

PAGED_LOOKASIDE_LIST FsRtlFileLockLookasideList
 

Macro Definition Documentation

◆ NDEBUG

#define NDEBUG

Definition at line 12 of file filelock.c.

Typedef Documentation

◆ COMBINED_LOCK_ELEMENT

◆ LOCK_INFORMATION

◆ LOCK_SHARED_RANGE

◆ PCOMBINED_LOCK_ELEMENT

◆ PLOCK_INFORMATION

◆ PLOCK_SHARED_RANGE

Function Documentation

◆ FsRtlAllocateFileLock()

Definition at line 1322 of file filelock.c.

1324{
1325 PFILE_LOCK FileLock;
1326
1327 /* Try to allocate it */
1328 FileLock = ExAllocateFromPagedLookasideList(&FsRtlFileLockLookasideList);
1329 if (FileLock)
1330 {
1331 /* Initialize it */
1332 FsRtlInitializeFileLock(FileLock,
1335 }
1336
1337 /* Return the lock */
1338 return FileLock;
1339}
VOID NTAPI FsRtlInitializeFileLock(IN PFILE_LOCK FileLock, IN PCOMPLETE_LOCK_IRP_ROUTINE CompleteLockIrpRoutine OPTIONAL, IN PUNLOCK_ROUTINE UnlockRoutine OPTIONAL)
Definition: filelock.c:1266
PAGED_LOOKASIDE_LIST FsRtlFileLockLookasideList
Definition: filelock.c:17
_Must_inspect_result_ _In_opt_ PUNLOCK_ROUTINE UnlockRoutine
Definition: fltkernel.h:2123
_In_opt_ PCOMPLETE_LOCK_IRP_ROUTINE CompleteLockIrpRoutine
Definition: fsrtlfuncs.h:139

Referenced by _At_().

◆ FsRtlCheckLockForReadAccess()

BOOLEAN NTAPI FsRtlCheckLockForReadAccess ( IN PFILE_LOCK  FileLock,
IN PIRP  Irp 
)

Definition at line 672 of file filelock.c.

674{
680 DPRINT("CheckLockForReadAccess(%wZ, Offset %08x%08x, Length %x)\n",
681 &IoStack->FileObject->FileName,
682 IoStack->Parameters.Read.ByteOffset.HighPart,
683 IoStack->Parameters.Read.ByteOffset.LowPart,
684 IoStack->Parameters.Read.Length);
685 if (!FileLock->LockInformation) {
686 DPRINT("CheckLockForReadAccess(%wZ) => TRUE\n", &IoStack->FileObject->FileName);
687 return TRUE;
688 }
689 ToFind.Exclusive.FileLock.StartingByte = IoStack->Parameters.Read.ByteOffset;
692 IoStack->Parameters.Read.Length;
694 (FileLock->LockInformation,
695 &ToFind);
696 if (!Found) {
697 DPRINT("CheckLockForReadAccess(%wZ) => TRUE\n", &IoStack->FileObject->FileName);
698 return TRUE;
699 }
700 Result = !Found->Exclusive.FileLock.ExclusiveLock ||
701 (IoStack->Parameters.Read.Key == Found->Exclusive.FileLock.Key &&
702 Process == Found->Exclusive.FileLock.ProcessId);
703 DPRINT("CheckLockForReadAccess(%wZ) => %s\n", &IoStack->FileObject->FileName, Result ? "TRUE" : "FALSE");
704 return Result;
705}
static PIO_STACK_LOCATION IoGetCurrentIrpStackLocation(PIRP Irp)
unsigned char BOOLEAN
Definition: actypes.h:127
return Found
Definition: dirsup.c:1270
_In_ PIRP Irp
Definition: csq.h:116
#define TRUE
Definition: types.h:120
_Must_inspect_result_ _In_ PLARGE_INTEGER _In_ PLARGE_INTEGER _In_ ULONG _In_ PFILE_OBJECT _In_ PVOID Process
Definition: fsrtlfuncs.h:223
PEPROCESS NTAPI IoGetRequestorProcess(IN PIRP Irp)
Definition: irp.c:1782
#define DPRINT
Definition: sndvol32.h:73
FILE_LOCK_INFO FileLock
LARGE_INTEGER EndingByte
Definition: fsrtltypes.h:194
LARGE_INTEGER StartingByte
Definition: fsrtltypes.h:188
PFILE_OBJECT FileObject
Definition: iotypes.h:3171
union _IO_STACK_LOCATION::@1709 Parameters
struct _IO_STACK_LOCATION::@4481::@4485 Read
FILE_EXCLUSIVE_LOCK_ENTRY Exclusive
Definition: filelock.c:29
LONGLONG QuadPart
Definition: typedefs.h:114
_At_(*)(_In_ PWSK_CLIENT Client, _In_opt_ PUNICODE_STRING NodeName, _In_opt_ PUNICODE_STRING ServiceName, _In_opt_ ULONG NameSpace, _In_opt_ GUID *Provider, _In_opt_ PADDRINFOEXW Hints, _Outptr_ PADDRINFOEXW *Result, _In_opt_ PEPROCESS OwningProcess, _In_opt_ PETHREAD OwningThread, _Inout_ PIRP Irp Result)(Mem)) NTSTATUS(WSKAPI *PFN_WSK_GET_ADDRESS_INFO
Definition: wsk.h:409
_Must_inspect_result_ NTSYSAPI PVOID NTAPI RtlLookupElementGenericTable(_In_ PRTL_GENERIC_TABLE Table, _In_ PVOID Buffer)

Referenced by _Requires_lock_held_(), do_read(), Ext2ReadFile(), RxCommonRead(), UDFCommonRead(), and VfatCommonRead().

◆ FsRtlCheckLockForWriteAccess()

BOOLEAN NTAPI FsRtlCheckLockForWriteAccess ( IN PFILE_LOCK  FileLock,
IN PIRP  Irp 
)

Definition at line 712 of file filelock.c.

714{
719 PEPROCESS Process = Irp->Tail.Overlay.Thread->ThreadsProcess;
720 DPRINT("CheckLockForWriteAccess(%wZ, Offset %08x%08x, Length %x)\n",
721 &IoStack->FileObject->FileName,
722 IoStack->Parameters.Write.ByteOffset.HighPart,
723 IoStack->Parameters.Write.ByteOffset.LowPart,
724 IoStack->Parameters.Write.Length);
725 if (!FileLock->LockInformation) {
726 DPRINT("CheckLockForWriteAccess(%wZ) => TRUE\n", &IoStack->FileObject->FileName);
727 return TRUE;
728 }
729 ToFind.Exclusive.FileLock.StartingByte = IoStack->Parameters.Write.ByteOffset;
732 IoStack->Parameters.Write.Length;
734 (FileLock->LockInformation,
735 &ToFind);
736 if (!Found) {
737 DPRINT("CheckLockForWriteAccess(%wZ) => TRUE\n", &IoStack->FileObject->FileName);
738 return TRUE;
739 }
740 Result = Process == Found->Exclusive.FileLock.ProcessId;
741 DPRINT("CheckLockForWriteAccess(%wZ) => %s\n", &IoStack->FileObject->FileName, Result ? "TRUE" : "FALSE");
742 return Result;
743}
struct _IO_STACK_LOCATION::@4481::@4486 Write

Referenced by _Requires_lock_held_(), Ext2WriteFile(), RxCommonWrite(), UDFCommonWrite(), and VfatWrite().

◆ FsRtlCompleteLockIrpReal()

VOID NTAPI FsRtlCompleteLockIrpReal ( IN PCOMPLETE_LOCK_IRP_ROUTINE  CompleteRoutine,
IN PVOID  Context,
IN PIRP  Irp,
IN NTSTATUS  Status,
OUT PNTSTATUS  NewStatus,
IN PFILE_OBJECT FileObject  OPTIONAL 
)

Definition at line 220 of file filelock.c.

226{
227 /* Check if we have a complete routine */
228 Irp->IoStatus.Information = 0;
229 if (CompleteRoutine)
230 {
231 /* Check if we have a file object */
232 if (FileObject) FileObject->LastLock = NULL;
233
234 /* Set the I/O Status and do completion */
235 Irp->IoStatus.Status = Status;
236 DPRINT("Calling completion routine %p Status %x\n", Irp, Status);
237 *NewStatus = CompleteRoutine(Context, Irp);
238 }
239 else
240 {
241 /* Otherwise do a normal I/O complete request */
242 DPRINT("Completing IRP %p Status %x\n", Irp, Status);
244 *NewStatus = Status;
245 }
246}
#define NULL
Definition: types.h:112
#define FsRtlCompleteRequest(IRP, STATUS)
Definition: fsrtlfuncs.h:1711
Status
Definition: gdiplustypes.h:24
_In_ PVOID Context
Definition: storport.h:2269
_In_ WDFREQUEST _In_ WDFFILEOBJECT FileObject
Definition: wdfdevice.h:550

Referenced by FsRtlPrivateLock(), FsRtlProcessFileLock(), and LockCompleteCanceledIrp().

◆ FsRtlFastCheckLockForRead()

BOOLEAN NTAPI FsRtlFastCheckLockForRead ( IN PFILE_LOCK  FileLock,
IN PLARGE_INTEGER  FileOffset,
IN PLARGE_INTEGER  Length,
IN ULONG  Key,
IN PFILE_OBJECT  FileObject,
IN PVOID  Process 
)

Definition at line 750 of file filelock.c.

756{
757 PEPROCESS EProcess = Process;
760 DPRINT("FsRtlFastCheckLockForRead(%wZ, Offset %08x%08x, Length %08x%08x, Key %x)\n",
761 &FileObject->FileName,
762 FileOffset->HighPart,
763 FileOffset->LowPart,
764 Length->HighPart,
765 Length->LowPart,
766 Key);
769 FileOffset->QuadPart + Length->QuadPart;
770 if (!FileLock->LockInformation) return TRUE;
772 (FileLock->LockInformation,
773 &ToFind);
774 if (!Found || !Found->Exclusive.FileLock.ExclusiveLock) return TRUE;
775 return Found->Exclusive.FileLock.Key == Key &&
776 Found->Exclusive.FileLock.ProcessId == EProcess;
777}
_In_ PFCB _In_ LONGLONG FileOffset
Definition: cdprocs.h:160
_In_ ULONG _In_ ULONG _In_ ULONG Length
Definition: ntddpcm.h:102

Referenced by _Function_class_(), duplicate_extents(), Ext2FastIoCheckIfPossible(), RxFastIoCheckIfPossible(), and UDFFastIoCheckIfPossible().

◆ FsRtlFastCheckLockForWrite()

BOOLEAN NTAPI FsRtlFastCheckLockForWrite ( IN PFILE_LOCK  FileLock,
IN PLARGE_INTEGER  FileOffset,
IN PLARGE_INTEGER  Length,
IN ULONG  Key,
IN PFILE_OBJECT  FileObject,
IN PVOID  Process 
)

Definition at line 784 of file filelock.c.

790{
792 PEPROCESS EProcess = Process;
795 DPRINT("FsRtlFastCheckLockForWrite(%wZ, Offset %08x%08x, Length %08x%08x, Key %x)\n",
796 &FileObject->FileName,
797 FileOffset->HighPart,
798 FileOffset->LowPart,
799 Length->HighPart,
800 Length->LowPart,
801 Key);
804 FileOffset->QuadPart + Length->QuadPart;
805 if (!FileLock->LockInformation) {
806 DPRINT("CheckForWrite(%wZ) => TRUE\n", &FileObject->FileName);
807 return TRUE;
808 }
810 (FileLock->LockInformation,
811 &ToFind);
812 if (!Found) {
813 DPRINT("CheckForWrite(%wZ) => TRUE\n", &FileObject->FileName);
814 return TRUE;
815 }
816 Result = Found->Exclusive.FileLock.Key == Key &&
817 Found->Exclusive.FileLock.ProcessId == EProcess;
818 DPRINT("CheckForWrite(%wZ) => %s\n", &FileObject->FileName, Result ? "TRUE" : "FALSE");
819 return Result;
820}

Referenced by _Function_class_(), duplicate_extents(), Ext2FastIoCheckIfPossible(), RxFastIoCheckIfPossible(), and UDFFastIoCheckIfPossible().

◆ FsRtlFastUnlockAll()

NTSTATUS NTAPI FsRtlFastUnlockAll ( IN PFILE_LOCK  FileLock,
IN PFILE_OBJECT  FileObject,
IN PEPROCESS  Process,
IN PVOID Context  OPTIONAL 
)

Definition at line 1027 of file filelock.c.

1031{
1032 PLIST_ENTRY ListEntry;
1034 PLOCK_INFORMATION InternalInfo = FileLock->LockInformation;
1035 DPRINT("FsRtlFastUnlockAll(%wZ)\n", &FileObject->FileName);
1036 // XXX Synchronize somehow
1037 if (!FileLock->LockInformation) {
1038 DPRINT("Not locked %wZ\n", &FileObject->FileName);
1039 return STATUS_RANGE_NOT_LOCKED; // no locks
1040 }
1041 for (ListEntry = InternalInfo->SharedLocks.Flink;
1042 ListEntry != &InternalInfo->SharedLocks;)
1043 {
1046 Length.QuadPart = Range->End.QuadPart - Range->Start.QuadPart;
1047 ListEntry = ListEntry->Flink;
1048 if (Range->ProcessId != Process)
1049 continue;
1051 (FileLock,
1052 FileObject,
1053 &Range->Start,
1054 &Length,
1055 Range->ProcessId,
1056 Range->Key,
1057 Context,
1058 TRUE);
1059 }
1060 for (Entry = RtlEnumerateGenericTable(&InternalInfo->RangeTable, TRUE);
1061 Entry;
1063 {
1065 if (Entry->Exclusive.FileLock.ProcessId != Process)
1066 continue;
1067 // We'll take the first one to be the list head, and free the others first...
1068 Length.QuadPart =
1069 Entry->Exclusive.FileLock.EndingByte.QuadPart -
1070 Entry->Exclusive.FileLock.StartingByte.QuadPart;
1072 (FileLock,
1073 Entry->Exclusive.FileLock.FileObject,
1074 &Entry->Exclusive.FileLock.StartingByte,
1075 &Length,
1076 Entry->Exclusive.FileLock.ProcessId,
1077 Entry->Exclusive.FileLock.Key,
1078 Context,
1079 TRUE);
1080 }
1081 DPRINT("Done %wZ\n", &FileObject->FileName);
1082 return STATUS_SUCCESS;
1083}
#define FALSE
Definition: types.h:117
NTSTATUS NTAPI FsRtlFastUnlockSingle(IN PFILE_LOCK FileLock, IN PFILE_OBJECT FileObject, IN PLARGE_INTEGER FileOffset, IN PLARGE_INTEGER Length, IN PEPROCESS Process, IN ULONG Key, IN PVOID Context OPTIONAL, IN BOOLEAN AlreadySynchronized)
Definition: filelock.c:827
#define STATUS_RANGE_NOT_LOCKED
Definition: ntstatus.h:456
Entry
Definition: section.c:5216
#define STATUS_SUCCESS
Definition: shellext.h:65
Definition: typedefs.h:120
struct _LIST_ENTRY * Flink
Definition: typedefs.h:121
RTL_GENERIC_TABLE RangeTable
Definition: filelock.c:35
LIST_ENTRY SharedLocks
Definition: filelock.c:40
LARGE_INTEGER End
Definition: filelock.c:48
LARGE_INTEGER Start
Definition: filelock.c:48
#define CONTAINING_RECORD(address, type, field)
Definition: typedefs.h:260
_Must_inspect_result_ NTSYSAPI PVOID NTAPI RtlEnumerateGenericTable(_In_ PRTL_GENERIC_TABLE Table, _In_ BOOLEAN Restart)

Referenced by _Dispatch_type_(), _Function_class_(), _Requires_lock_held_(), CdFastUnlockAll(), Ext2Cleanup(), Ext2FastIoUnlockAll(), FsRtlProcessFileLock(), RxCommonCleanup(), UDFCommonCleanup(), UDFFastUnlockAll(), and VfatCleanupFile().

◆ FsRtlFastUnlockAllByKey()

NTSTATUS NTAPI FsRtlFastUnlockAllByKey ( IN PFILE_LOCK  FileLock,
IN PFILE_OBJECT  FileObject,
IN PEPROCESS  Process,
IN ULONG  Key,
IN PVOID Context  OPTIONAL 
)

Definition at line 1090 of file filelock.c.

1095{
1096 PLIST_ENTRY ListEntry;
1098 PLOCK_INFORMATION InternalInfo = FileLock->LockInformation;
1099
1100 DPRINT("FsRtlFastUnlockAllByKey(%wZ,Key %x)\n", &FileObject->FileName, Key);
1101
1102 // XXX Synchronize somehow
1103 if (!FileLock->LockInformation) return STATUS_RANGE_NOT_LOCKED; // no locks
1104 for (ListEntry = InternalInfo->SharedLocks.Flink;
1105 ListEntry != &InternalInfo->SharedLocks;)
1106 {
1109 Length.QuadPart = Range->End.QuadPart - Range->Start.QuadPart;
1110 ListEntry = ListEntry->Flink;
1111 if (Range->ProcessId != Process ||
1112 Range->Key != Key)
1113 continue;
1115 (FileLock,
1116 FileObject,
1117 &Range->Start,
1118 &Length,
1119 Range->ProcessId,
1120 Range->Key,
1121 Context,
1122 TRUE);
1123 }
1124 for (Entry = RtlEnumerateGenericTable(&InternalInfo->RangeTable, TRUE);
1125 Entry;
1127 {
1129 // We'll take the first one to be the list head, and free the others first...
1130 Length.QuadPart =
1131 Entry->Exclusive.FileLock.EndingByte.QuadPart -
1132 Entry->Exclusive.FileLock.StartingByte.QuadPart;
1133 if (Entry->Exclusive.FileLock.Key == Key &&
1134 Entry->Exclusive.FileLock.ProcessId == Process)
1135 {
1137 (FileLock,
1138 Entry->Exclusive.FileLock.FileObject,
1139 &Entry->Exclusive.FileLock.StartingByte,
1140 &Length,
1141 Entry->Exclusive.FileLock.ProcessId,
1142 Entry->Exclusive.FileLock.Key,
1143 Context,
1144 TRUE);
1145 }
1146 }
1147
1148 return STATUS_SUCCESS;
1149}

Referenced by _Function_class_(), CdFastUnlockAllByKey(), Ext2FastIoUnlockAllByKey(), FsRtlProcessFileLock(), and UDFFastUnlockAllByKey().

◆ FsRtlFastUnlockSingle()

NTSTATUS NTAPI FsRtlFastUnlockSingle ( IN PFILE_LOCK  FileLock,
IN PFILE_OBJECT  FileObject,
IN PLARGE_INTEGER  FileOffset,
IN PLARGE_INTEGER  Length,
IN PEPROCESS  Process,
IN ULONG  Key,
IN PVOID Context  OPTIONAL,
IN BOOLEAN  AlreadySynchronized 
)

Definition at line 827 of file filelock.c.

835{
836 BOOLEAN FoundShared = FALSE;
837 PLIST_ENTRY SharedEntry;
838 PLOCK_SHARED_RANGE SharedRange = NULL;
841 PIRP NextMatchingLockIrp;
842 PLOCK_INFORMATION InternalInfo = FileLock->LockInformation;
843 DPRINT("FsRtlFastUnlockSingle(%wZ, Offset %08x%08x (%d), Length %08x%08x (%d), Key %x)\n",
844 &FileObject->FileName,
845 FileOffset->HighPart,
846 FileOffset->LowPart,
847 (int)FileOffset->QuadPart,
848 Length->HighPart,
849 Length->LowPart,
850 (int)Length->QuadPart,
851 Key);
852 // The region to unlock must correspond exactly to a previously locked region
853 // -- msdn
854 // But Windows 2003 doesn't assert on it and simply ignores that parameter
855 // ASSERT(AlreadySynchronized);
858 FileOffset->QuadPart + Length->QuadPart;
859 if (!InternalInfo) {
860 DPRINT("File not previously locked (ever)\n");
862 }
863 Entry = RtlLookupElementGenericTable(&InternalInfo->RangeTable, &Find);
864 if (!Entry) {
865 DPRINT("Range not locked %wZ\n", &FileObject->FileName);
867 }
868
869 DPRINT("Found lock entry: Exclusive %u %08x%08x:%08x%08x %wZ\n",
870 Entry->Exclusive.FileLock.ExclusiveLock,
871 Entry->Exclusive.FileLock.StartingByte.HighPart,
872 Entry->Exclusive.FileLock.StartingByte.LowPart,
873 Entry->Exclusive.FileLock.EndingByte.HighPart,
874 Entry->Exclusive.FileLock.EndingByte.LowPart,
875 &FileObject->FileName);
876
877 if (Entry->Exclusive.FileLock.ExclusiveLock)
878 {
879 if (Entry->Exclusive.FileLock.Key != Key ||
880 Entry->Exclusive.FileLock.ProcessId != Process ||
881 Entry->Exclusive.FileLock.StartingByte.QuadPart != FileOffset->QuadPart ||
882 Entry->Exclusive.FileLock.EndingByte.QuadPart !=
883 FileOffset->QuadPart + Length->QuadPart)
884 {
885 DPRINT("Range not locked %wZ\n", &FileObject->FileName);
887 }
888 RtlCopyMemory(&Find, Entry, sizeof(Find));
889 // Remove the old exclusive lock region
891 }
892 else
893 {
894 DPRINT("Shared lock %wZ Start %08x%08x End %08x%08x\n",
895 &FileObject->FileName,
896 Entry->Exclusive.FileLock.StartingByte.HighPart,
897 Entry->Exclusive.FileLock.StartingByte.LowPart,
898 Entry->Exclusive.FileLock.EndingByte.HighPart,
899 Entry->Exclusive.FileLock.EndingByte.LowPart);
900 for (SharedEntry = InternalInfo->SharedLocks.Flink;
901 SharedEntry != &InternalInfo->SharedLocks;
902 SharedEntry = SharedEntry->Flink)
903 {
904 SharedRange = CONTAINING_RECORD(SharedEntry, LOCK_SHARED_RANGE, Entry);
905 if (SharedRange->Start.QuadPart == FileOffset->QuadPart &&
906 SharedRange->End.QuadPart == FileOffset->QuadPart + Length->QuadPart &&
907 SharedRange->Key == Key &&
908 SharedRange->ProcessId == Process)
909 {
910 FoundShared = TRUE;
911 DPRINT("Found shared element to delete %wZ Start %08x%08x End %08x%08x Key %x\n",
912 &FileObject->FileName,
913 SharedRange->Start.HighPart,
914 SharedRange->Start.LowPart,
915 SharedRange->End.HighPart,
916 SharedRange->End.LowPart,
917 SharedRange->Key);
918 break;
919 }
920 }
921 if (FoundShared)
922 {
923 /* Remove the found range from the shared range lists */
924 RemoveEntryList(&SharedRange->Entry);
925 ExFreePoolWithTag(SharedRange, TAG_RANGE);
926 /* We need to rebuild the list of shared ranges. */
927 DPRINT("Removing the lock entry %wZ (%08x%08x:%08x%08x)\n",
928 &FileObject->FileName,
929 Entry->Exclusive.FileLock.StartingByte.HighPart,
930 Entry->Exclusive.FileLock.StartingByte.LowPart,
931 Entry->Exclusive.FileLock.EndingByte.HighPart,
932 Entry->Exclusive.FileLock.EndingByte.LowPart);
933
934 /* Remember what was in there and remove it from the table */
935 Find = *Entry;
936 RtlDeleteElementGenericTable(&InternalInfo->RangeTable, &Find);
937 /* Put shared locks back in place */
938 for (SharedEntry = InternalInfo->SharedLocks.Flink;
939 SharedEntry != &InternalInfo->SharedLocks;
940 SharedEntry = SharedEntry->Flink)
941 {
942 COMBINED_LOCK_ELEMENT LockElement;
943 SharedRange = CONTAINING_RECORD(SharedEntry, LOCK_SHARED_RANGE, Entry);
945 LockElement.Exclusive.FileLock.StartingByte = SharedRange->Start;
946 LockElement.Exclusive.FileLock.EndingByte = SharedRange->End;
947 LockElement.Exclusive.FileLock.ProcessId = SharedRange->ProcessId;
948 LockElement.Exclusive.FileLock.Key = SharedRange->Key;
950
951 if (LockCompare(&InternalInfo->RangeTable, &Find, &LockElement) != GenericEqual)
952 {
953 DPRINT("Skipping range %08x%08x:%08x%08x\n",
958 continue;
959 }
960 DPRINT("Re-creating range %08x%08x:%08x%08x\n",
965 FsRtlpRebuildSharedLockRange(FileLock, InternalInfo, &LockElement);
966 }
967 }
968 else
969 {
971 }
972 }
973
974#ifndef NDEBUG
975 DPRINT("Lock still has:\n");
976 for (SharedEntry = InternalInfo->SharedLocks.Flink;
977 SharedEntry != &InternalInfo->SharedLocks;
978 SharedEntry = SharedEntry->Flink)
979 {
980 SharedRange = CONTAINING_RECORD(SharedEntry, LOCK_SHARED_RANGE, Entry);
981 DPRINT("Shared element %wZ Offset %08x%08x Length %08x%08x Key %x\n",
982 &FileObject->FileName,
983 SharedRange->Start.HighPart,
984 SharedRange->Start.LowPart,
985 SharedRange->End.HighPart,
986 SharedRange->End.LowPart,
987 SharedRange->Key);
988 }
989#endif
990
991 // this is definitely the thing we want
992 InternalInfo->Generation++;
993 while ((NextMatchingLockIrp = IoCsqRemoveNextIrp(&InternalInfo->Csq, &Find)))
994 {
996 if (NextMatchingLockIrp->IoStatus.Information == InternalInfo->Generation)
997 {
998 // We've already looked at this one, meaning that we looped.
999 // Put it back and exit.
1001 (&InternalInfo->Csq,
1002 NextMatchingLockIrp,
1003 NULL,
1004 NULL);
1005 break;
1006 }
1007 // Got a new lock irp... try to do the new lock operation
1008 // Note that we pick an operation that would succeed at the time
1009 // we looked, but can't guarantee that it won't just be re-queued
1010 // because somebody else snatched part of the range in a new thread.
1011 DPRINT("Locking another IRP %p for %p %wZ\n",
1012 NextMatchingLockIrp, FileLock, &FileObject->FileName);
1013 Status = FsRtlProcessFileLock(InternalInfo->BelongsTo, NextMatchingLockIrp, NULL);
1014 if (!NT_SUCCESS(Status))
1015 return Status;
1016 }
1017
1018 DPRINT("Success %wZ\n", &FileObject->FileName);
1019 return STATUS_SUCCESS;
1020}
LONG NTSTATUS
Definition: precomp.h:26
NTKERNELAPI NTSTATUS NTAPI IoCsqInsertIrpEx(_Inout_ PIO_CSQ Csq, _Inout_ PIRP Irp, _Out_opt_ PIO_CSQ_IRP_CONTEXT Context, _In_opt_ PVOID InsertContext)
Insert an IRP into the CSQ, with additional tracking context.
Definition: csq.c:205
NTKERNELAPI PIRP NTAPI IoCsqRemoveNextIrp(_Inout_ PIO_CSQ Csq, _In_opt_ PVOID PeekContext)
IoCsqRemoveNextIrp - Removes the next IRP from the queue.
Definition: csq.c:398
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:33
#define RemoveEntryList(Entry)
Definition: env_spec_w32.h:986
PCOMBINED_LOCK_ELEMENT NTAPI FsRtlpRebuildSharedLockRange(PFILE_LOCK FileLock, PLOCK_INFORMATION LockInfo, PCOMBINED_LOCK_ELEMENT Conflict)
Definition: filelock.c:290
NTSTATUS NTAPI FsRtlProcessFileLock(IN PFILE_LOCK FileLock, IN PIRP Irp, IN PVOID Context OPTIONAL)
Definition: filelock.c:1156
static RTL_GENERIC_COMPARE_RESULTS NTAPI LockCompare(PRTL_GENERIC_TABLE Table, PVOID PtrA, PVOID PtrB)
Definition: filelock.c:82
#define ExFreePoolWithTag(_P, _T)
Definition: module.h:1109
BOOLEAN ExclusiveLock
Definition: fsrtltypes.h:190
PFILE_OBJECT FileObject
Definition: fsrtltypes.h:192
IO_STATUS_BLOCK IoStatus
ULONG Generation
Definition: filelock.c:41
PFILE_LOCK BelongsTo
Definition: filelock.c:39
LIST_ENTRY Entry
Definition: filelock.c:47
#define TAG_RANGE
Definition: tag.h:49
#define RtlCopyMemory(Destination, Source, Length)
Definition: typedefs.h:263
ULONG LowPart
Definition: typedefs.h:106
NTSYSAPI BOOLEAN NTAPI RtlDeleteElementGenericTable(_In_ PRTL_GENERIC_TABLE Table, _In_ PVOID Buffer)
@ GenericEqual
Definition: rtltypes.h:391

Referenced by _Function_class_(), CdFastUnlockSingle(), Ext2FastIoUnlockSingle(), FsRtlFastUnlockAll(), FsRtlFastUnlockAllByKey(), FsRtlProcessFileLock(), and UDFFastUnlockSingle().

◆ FsRtlFreeFileLock()

VOID NTAPI FsRtlFreeFileLock ( IN PFILE_LOCK  FileLock)

Definition at line 1346 of file filelock.c.

1347{
1348 /* Uninitialize and free the lock */
1349 FsRtlUninitializeFileLock(FileLock);
1350 ExFreeToPagedLookasideList(&FsRtlFileLockLookasideList, FileLock);
1351}
VOID NTAPI FsRtlUninitializeFileLock(IN PFILE_LOCK FileLock)
Definition: filelock.c:1283

Referenced by CdDeleteFcb().

◆ FsRtlGetNextFileLock()

PFILE_LOCK_INFO NTAPI FsRtlGetNextFileLock ( IN PFILE_LOCK  FileLock,
IN BOOLEAN  Restart 
)

Definition at line 255 of file filelock.c.

257{
259 if (!FileLock->LockInformation) return NULL;
260 Entry = RtlEnumerateGenericTable(FileLock->LockInformation, Restart);
261 if (!Entry) return NULL;
262 else return &Entry->Exclusive.FileLock;
263}
@ Restart
Definition: sacdrv.h:269

Referenced by Ext2Cleanup().

◆ FsRtlInitializeFileLock()

VOID NTAPI FsRtlInitializeFileLock ( IN PFILE_LOCK  FileLock,
IN PCOMPLETE_LOCK_IRP_ROUTINE CompleteLockIrpRoutine  OPTIONAL,
IN PUNLOCK_ROUTINE UnlockRoutine  OPTIONAL 
)

Definition at line 1266 of file filelock.c.

1269{
1270 /* Setup the lock */
1271 RtlZeroMemory(FileLock, sizeof(*FileLock));
1272 FileLock->FastIoIsQuestionable = FALSE;
1273 FileLock->CompleteLockIrpRoutine = CompleteLockIrpRoutine;
1274 FileLock->UnlockRoutine = UnlockRoutine;
1275 FileLock->LockInformation = NULL;
1276}
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:262

Referenced by create_fcb(), Ext2AllocateFcb(), FatCreateFcb(), FsRtlAllocateFileLock(), RxFinishFcbInitialization(), UDFInitializeFCB(), and vfatNewFCB().

◆ FsRtlpExpandLockElement()

VOID NTAPI FsRtlpExpandLockElement ( PCOMBINED_LOCK_ELEMENT  ToExpand,
PCOMBINED_LOCK_ELEMENT  Conflict 
)

Definition at line 267 of file filelock.c.

270{
273 {
276 }
277 if (ToExpand->Exclusive.FileLock.EndingByte.QuadPart <
279 {
280 ToExpand->Exclusive.FileLock.EndingByte =
281 Conflict->Exclusive.FileLock.EndingByte;
282 }
283}

Referenced by FsRtlpRebuildSharedLockRange().

◆ FsRtlpRebuildSharedLockRange()

PCOMBINED_LOCK_ELEMENT NTAPI FsRtlpRebuildSharedLockRange ( PFILE_LOCK  FileLock,
PLOCK_INFORMATION  LockInfo,
PCOMBINED_LOCK_ELEMENT  Conflict 
)

Definition at line 289 of file filelock.c.

293{
294 /* Starting at Conflict->StartingByte and going to Conflict->EndingByte
295 * capture and expand a shared range from the shared range list.
296 * Finish when we've incorporated all overlapping shared regions.
297 */
298 BOOLEAN InsertedNew = FALSE, RemovedOld;
299 COMBINED_LOCK_ELEMENT NewElement = *Conflict;
302 (FileLock->LockInformation, &NewElement)))
303 {
304 FsRtlpExpandLockElement(&NewElement, Entry);
306 (&LockInfo->RangeTable,
307 Entry);
308 ASSERT(RemovedOld);
309 }
311 (&LockInfo->RangeTable,
312 &NewElement,
313 sizeof(NewElement),
314 &InsertedNew);
315 ASSERT(InsertedNew);
316 return Conflict;
317}
VOID NTAPI FsRtlpExpandLockElement(PCOMBINED_LOCK_ELEMENT ToExpand, PCOMBINED_LOCK_ELEMENT Conflict)
Definition: filelock.c:268
#define ASSERT(a)
Definition: mode.c:44
PVOID LockInformation
Definition: fsrtltypes.h:207
NTSYSAPI PVOID NTAPI RtlInsertElementGenericTable(_In_ PRTL_GENERIC_TABLE Table, _In_reads_bytes_(BufferSize) PVOID Buffer, _In_ CLONG BufferSize, _Out_opt_ PBOOLEAN NewElement)

Referenced by FsRtlFastUnlockSingle(), and FsRtlPrivateLock().

◆ FsRtlPrivateLock()

BOOLEAN NTAPI FsRtlPrivateLock ( IN PFILE_LOCK  FileLock,
IN PFILE_OBJECT  FileObject,
IN PLARGE_INTEGER  FileOffset,
IN PLARGE_INTEGER  Length,
IN PEPROCESS  Process,
IN ULONG  Key,
IN BOOLEAN  FailImmediately,
IN BOOLEAN  ExclusiveLock,
OUT PIO_STATUS_BLOCK  IoStatus,
IN PIRP Irp  OPTIONAL,
IN PVOID Context  OPTIONAL,
IN BOOLEAN  AlreadySynchronized 
)

Definition at line 324 of file filelock.c.

336{
338 COMBINED_LOCK_ELEMENT ToInsert;
339 PCOMBINED_LOCK_ELEMENT Conflict;
340 PLOCK_INFORMATION LockInfo;
341 PLOCK_SHARED_RANGE NewSharedRange;
342 BOOLEAN InsertedNew;
343 ULARGE_INTEGER UnsignedStart;
344 ULARGE_INTEGER UnsignedEnd;
345
346 DPRINT("FsRtlPrivateLock(%wZ, Offset %08x%08x (%d), Length %08x%08x (%d), Key %x, FailImmediately %u, Exclusive %u)\n",
347 &FileObject->FileName,
348 FileOffset->HighPart,
349 FileOffset->LowPart,
350 (int)FileOffset->QuadPart,
351 Length->HighPart,
352 Length->LowPart,
353 (int)Length->QuadPart,
354 Key,
357
358 UnsignedStart.QuadPart = FileOffset->QuadPart;
359 UnsignedEnd.QuadPart = FileOffset->QuadPart + Length->QuadPart;
360
361 if (UnsignedEnd.QuadPart < UnsignedStart.QuadPart)
362 {
363 DPRINT("File offset out of range\n");
365 if (Irp)
366 {
367 DPRINT("Complete lock %p Status %x\n", Irp, IoStatus->Status);
369 (FileLock->CompleteLockIrpRoutine,
370 Context,
371 Irp,
372 IoStatus->Status,
373 &Status,
374 FileObject);
375 }
376 return FALSE;
377 }
378
379 /* Initialize the lock, if necessary */
380 if (!FileLock->LockInformation)
381 {
383 if (!LockInfo)
384 {
385 IoStatus->Status = STATUS_NO_MEMORY;
386 return FALSE;
387 }
388 FileLock->LockInformation = LockInfo;
389
390 LockInfo->BelongsTo = FileLock;
392
394 (&LockInfo->RangeTable,
397 LockFree,
398 NULL);
399
400 KeInitializeSpinLock(&LockInfo->CsqLock);
401 InitializeListHead(&LockInfo->CsqList);
402
404 (&LockInfo->Csq,
411 }
412
413 LockInfo = FileLock->LockInformation;
416 ToInsert.Exclusive.FileLock.EndingByte.QuadPart = FileOffset->QuadPart + Length->QuadPart;
418 ToInsert.Exclusive.FileLock.Key = Key;
420
422 (FileLock->LockInformation,
423 &ToInsert,
424 sizeof(ToInsert),
425 &InsertedNew);
426
427 if (Conflict && !InsertedNew)
428 {
430 {
431 DPRINT("Conflict %08x%08x:%08x%08x Exc %u (Want Exc %u)\n",
438 if (FailImmediately)
439 {
440 DPRINT("STATUS_FILE_LOCK_CONFLICT\n");
442 if (Irp)
443 {
444 DPRINT("STATUS_FILE_LOCK_CONFLICT: Complete\n");
446 (FileLock->CompleteLockIrpRoutine,
447 Context,
448 Irp,
449 IoStatus->Status,
450 &Status,
451 FileObject);
452 }
453 return FALSE;
454 }
455 else
456 {
457 IoStatus->Status = STATUS_PENDING;
458 if (Irp)
459 {
460 Irp->IoStatus.Information = LockInfo->Generation;
463 (&LockInfo->Csq,
464 Irp,
465 NULL,
466 NULL);
467 }
468 }
469 return FALSE;
470 }
471 else
472 {
473 ULONG i;
474 /* We know of at least one lock in range that's shared. We need to
475 * find out if any more exist and any are exclusive. */
476 for (i = 0; i < RtlNumberGenericTableElements(&LockInfo->RangeTable); i++)
477 {
478 Conflict = RtlGetElementGenericTable(&LockInfo->RangeTable, i);
479
480 /* The first argument will be inserted as a shared range */
481 if (Conflict && (LockCompare(&LockInfo->RangeTable, Conflict, &ToInsert) == GenericEqual))
482 {
483 if (Conflict->Exclusive.FileLock.ExclusiveLock)
484 {
485 /* Found an exclusive match */
486 if (FailImmediately)
487 {
489 DPRINT("STATUS_FILE_LOCK_CONFLICT\n");
490 if (Irp)
491 {
492 DPRINT("STATUS_FILE_LOCK_CONFLICT: Complete\n");
494 (FileLock->CompleteLockIrpRoutine,
495 Context,
496 Irp,
497 IoStatus->Status,
498 &Status,
499 FileObject);
500 }
501 }
502 else
503 {
504 IoStatus->Status = STATUS_PENDING;
505 if (Irp)
506 {
509 (&LockInfo->Csq,
510 Irp,
511 NULL,
512 NULL);
513 }
514 }
515 return FALSE;
516 }
517 }
518 }
519
520 DPRINT("Overlapping shared lock %wZ %08x%08x %08x%08x\n",
521 &FileObject->FileName,
526 Conflict = FsRtlpRebuildSharedLockRange(FileLock,
527 LockInfo,
528 &ToInsert);
529 if (!Conflict)
530 {
531 IoStatus->Status = STATUS_NO_MEMORY;
532 if (Irp)
533 {
535 (FileLock->CompleteLockIrpRoutine,
536 Context,
537 Irp,
538 IoStatus->Status,
539 &Status,
540 FileObject);
541 }
542 }
543
544 /* We got here because there were only overlapping shared locks */
545 /* A shared lock is both a range *and* a list entry. Insert the
546 entry here. */
547
548 DPRINT("Adding shared lock %wZ\n", &FileObject->FileName);
549 NewSharedRange =
550 ExAllocatePoolWithTag(NonPagedPool, sizeof(*NewSharedRange), TAG_RANGE);
551 if (!NewSharedRange)
552 {
553 IoStatus->Status = STATUS_NO_MEMORY;
554 if (Irp)
555 {
557 (FileLock->CompleteLockIrpRoutine,
558 Context,
559 Irp,
560 IoStatus->Status,
561 &Status,
562 FileObject);
563 }
564 return FALSE;
565 }
566 DPRINT("Adding shared lock %wZ\n", &FileObject->FileName);
567 NewSharedRange->Start = *FileOffset;
568 NewSharedRange->End.QuadPart = FileOffset->QuadPart + Length->QuadPart;
569 NewSharedRange->Key = Key;
570 NewSharedRange->ProcessId = ToInsert.Exclusive.FileLock.ProcessId;
571 InsertTailList(&LockInfo->SharedLocks, &NewSharedRange->Entry);
572
573 DPRINT("Acquired shared lock %wZ %08x%08x %08x%08x\n",
574 &FileObject->FileName,
579 IoStatus->Status = STATUS_SUCCESS;
580 if (Irp)
581 {
583 (FileLock->CompleteLockIrpRoutine,
584 Context,
585 Irp,
586 IoStatus->Status,
587 &Status,
588 FileObject);
589 }
590 return TRUE;
591 }
592 }
593 else if (!Conflict)
594 {
595 /* Conflict here is (or would be) the newly inserted element, but we ran
596 * out of space probably. */
597 IoStatus->Status = STATUS_NO_MEMORY;
598 if (Irp)
599 {
601 (FileLock->CompleteLockIrpRoutine,
602 Context,
603 Irp,
604 IoStatus->Status,
605 &Status,
606 FileObject);
607 }
608 return FALSE;
609 }
610 else
611 {
612 DPRINT("Inserted new lock %wZ %08x%08x %08x%08x exclusive %u\n",
613 &FileObject->FileName,
619 if (!ExclusiveLock)
620 {
621 NewSharedRange =
622 ExAllocatePoolWithTag(NonPagedPool, sizeof(*NewSharedRange), TAG_RANGE);
623 if (!NewSharedRange)
624 {
625 IoStatus->Status = STATUS_NO_MEMORY;
626 if (Irp)
627 {
629 (FileLock->CompleteLockIrpRoutine,
630 Context,
631 Irp,
632 IoStatus->Status,
633 &Status,
634 FileObject);
635 }
636 return FALSE;
637 }
638 DPRINT("Adding shared lock %wZ\n", &FileObject->FileName);
639 NewSharedRange->Start = *FileOffset;
640 NewSharedRange->End.QuadPart = FileOffset->QuadPart + Length->QuadPart;
641 NewSharedRange->Key = Key;
642 NewSharedRange->ProcessId = Process;
643 InsertTailList(&LockInfo->SharedLocks, &NewSharedRange->Entry);
644 }
645
646 /* Assume all is cool, and lock is set */
647 IoStatus->Status = STATUS_SUCCESS;
648
649 if (Irp)
650 {
651 /* Complete the request */
652 FsRtlCompleteLockIrpReal(FileLock->CompleteLockIrpRoutine,
653 Context,
654 Irp,
655 IoStatus->Status,
656 &Status,
657 FileObject);
658
659 /* Update the status */
660 IoStatus->Status = Status;
661 }
662 }
663
664 return TRUE;
665}
NTKERNELAPI NTSTATUS NTAPI IoCsqInitializeEx(_Out_ PIO_CSQ Csq, _In_ PIO_CSQ_INSERT_IRP_EX CsqInsertIrpEx, _In_ PIO_CSQ_REMOVE_IRP CsqRemoveIrp, _In_ PIO_CSQ_PEEK_NEXT_IRP CsqPeekNextIrp, _In_ PIO_CSQ_ACQUIRE_LOCK CsqAcquireLock, _In_ PIO_CSQ_RELEASE_LOCK CsqReleaseLock, _In_ PIO_CSQ_COMPLETE_CANCELED_IRP CsqCompleteCanceledIrp)
Set up a CSQ struct to initialize the queue (extended version)
Definition: csq.c:143
#define STATUS_NO_MEMORY
Definition: d3dkmdt.h:51
#define InsertTailList(ListHead, Entry)
#define ExAllocatePoolWithTag(hernya, size, tag)
Definition: env_spec_w32.h:350
#define NonPagedPool
Definition: env_spec_w32.h:307
#define InitializeListHead(ListHead)
Definition: env_spec_w32.h:944
#define KeInitializeSpinLock(sl)
Definition: env_spec_w32.h:604
IN PLARGE_INTEGER IN PLARGE_INTEGER PEPROCESS ULONG BOOLEAN BOOLEAN ExclusiveLock
Definition: fatprocs.h:2715
IN PLARGE_INTEGER IN PLARGE_INTEGER PEPROCESS ULONG BOOLEAN FailImmediately
Definition: fatprocs.h:2714
static VOID NTAPI LockCompleteCanceledIrp(PIO_CSQ Csq, PIRP Irp)
Definition: filelock.c:204
static VOID NTAPI LockAcquireQueueLock(PIO_CSQ Csq, PKIRQL Irql)
Definition: filelock.c:190
static PVOID NTAPI LockAllocate(PRTL_GENERIC_TABLE Table, CLONG Bytes)
Definition: filelock.c:67
static VOID NTAPI LockReleaseQueueLock(PIO_CSQ Csq, KIRQL Irql)
Definition: filelock.c:197
static VOID NTAPI LockRemoveIrp(PIO_CSQ Csq, PIRP Irp)
Definition: filelock.c:130
static PIRP NTAPI LockPeekNextIrp(PIO_CSQ Csq, PIRP Irp, PVOID PeekContext)
Definition: filelock.c:135
VOID NTAPI FsRtlCompleteLockIrpReal(IN PCOMPLETE_LOCK_IRP_ROUTINE CompleteRoutine, IN PVOID Context, IN PIRP Irp, IN NTSTATUS Status, OUT PNTSTATUS NewStatus, IN PFILE_OBJECT FileObject OPTIONAL)
Definition: filelock.c:220
static NTSTATUS NTAPI LockInsertIrpEx(PIO_CSQ Csq, PIRP Irp, PVOID InsertContext)
Definition: filelock.c:121
static VOID NTAPI LockFree(PRTL_GENERIC_TABLE Table, PVOID Buffer)
Definition: filelock.c:75
VOID NTAPI RtlInitializeGenericTable(IN PRTL_GENERIC_TABLE Table, IN PRTL_GENERIC_COMPARE_ROUTINE CompareRoutine, IN PRTL_GENERIC_ALLOCATE_ROUTINE AllocateRoutine, IN PRTL_GENERIC_FREE_ROUTINE FreeRoutine, IN PVOID TableContext)
Definition: generictable.c:100
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
IoMarkIrpPending(Irp)
__in UCHAR __in POWER_STATE __in_opt PVOID __in PIO_STATUS_BLOCK IoStatus
Definition: mxum.h:159
#define STATUS_FILE_LOCK_CONFLICT
Definition: ntstatus.h:414
KSPIN_LOCK CsqLock
Definition: filelock.c:37
LIST_ENTRY CsqList
Definition: filelock.c:38
ULONGLONG QuadPart
Definition: ms-dtyp.idl:185
#define TAG_FLOCK
Definition: tag.h:50
#define STATUS_PENDING
Definition: telnetd.h:14
uint32_t ULONG
Definition: typedefs.h:59
#define STATUS_INVALID_PARAMETER
Definition: udferr_usr.h:135
_Must_inspect_result_ NTSYSAPI PVOID NTAPI RtlGetElementGenericTable(_In_ PRTL_GENERIC_TABLE Table, _In_ ULONG I)
NTSYSAPI ULONG NTAPI RtlNumberGenericTableElements(_In_ PRTL_GENERIC_TABLE Table)

Referenced by FsRtlProcessFileLock().

◆ FsRtlProcessFileLock()

NTSTATUS NTAPI FsRtlProcessFileLock ( IN PFILE_LOCK  FileLock,
IN PIRP  Irp,
IN PVOID Context  OPTIONAL 
)

Definition at line 1156 of file filelock.c.

1159{
1163
1164 /* Get the I/O Stack location */
1167
1168 /* Clear the I/O status block and check what function this is */
1170
1171 DPRINT("FsRtlProcessFileLock(%wZ, MinorFunction %x)\n",
1172 &IoStackLocation->FileObject->FileName,
1174
1176 {
1177 /* A lock */
1178 case IRP_MN_LOCK:
1179 {
1180 /* Call the private lock routine */
1181 BOOLEAN Result = FsRtlPrivateLock(FileLock,
1190 Irp,
1191 Context,
1192 FALSE);
1193 /* FsRtlPrivateLock has _Must_inspect_result_. Just check this is consistent on debug builds */
1195 (void)Result;
1196 return IoStatusBlock.Status;
1197 }
1198 /* A single unlock */
1200
1201 /* Call fast unlock */
1203 FsRtlFastUnlockSingle(FileLock,
1206 ByteOffset,
1208 Length,
1211 Key,
1212 Context,
1213 FALSE);
1214 break;
1215
1216 /* Total unlock */
1217 case IRP_MN_UNLOCK_ALL:
1218
1219 /* Do a fast unlock */
1222 FileObject,
1224 Context);
1225 break;
1226
1227 /* Unlock by key */
1229
1230 /* Do it */
1232 FsRtlFastUnlockAllByKey(FileLock,
1236 LockControl.Key,
1237 Context);
1238 break;
1239
1240 /* Invalid request */
1241 default:
1242
1243 /* Complete it */
1247 }
1248
1249 /* Return the status */
1250 DPRINT("Lock IRP %p %x\n", Irp, IoStatusBlock.Status);
1252 (FileLock->CompleteLockIrpRoutine,
1253 Context,
1254 Irp,
1256 &Status,
1257 NULL);
1258 return IoStatusBlock.Status;
1259}
IN PDCB IN PCCB IN VBO IN OUT PULONG OUT PDIRENT OUT PBCB OUT PVBO ByteOffset
Definition: fatprocs.h:732
BOOLEAN NTAPI FsRtlPrivateLock(IN PFILE_LOCK FileLock, IN PFILE_OBJECT FileObject, IN PLARGE_INTEGER FileOffset, IN PLARGE_INTEGER Length, IN PEPROCESS Process, IN ULONG Key, IN BOOLEAN FailImmediately, IN BOOLEAN ExclusiveLock, OUT PIO_STATUS_BLOCK IoStatus, IN PIRP Irp OPTIONAL, IN PVOID Context OPTIONAL, IN BOOLEAN AlreadySynchronized)
Definition: filelock.c:324
NTSTATUS NTAPI FsRtlFastUnlockAll(IN PFILE_LOCK FileLock, IN PFILE_OBJECT FileObject, IN PEPROCESS Process, IN PVOID Context OPTIONAL)
Definition: filelock.c:1027
NTSTATUS NTAPI FsRtlFastUnlockAllByKey(IN PFILE_LOCK FileLock, IN PFILE_OBJECT FileObject, IN PEPROCESS Process, IN ULONG Key, IN PVOID Context OPTIONAL)
Definition: filelock.c:1090
static OUT PIO_STATUS_BLOCK IoStatusBlock
Definition: pipe.c:100
#define IRP_MJ_LOCK_CONTROL
Definition: rdpdr.c:53
struct _IO_STACK_LOCATION::@4481::@4497 LockControl
ULONG POINTER_ALIGNMENT Key
Definition: iotypes.h:3141
#define STATUS_INVALID_DEVICE_REQUEST
Definition: udferr_usr.h:138
_In_ PIO_STACK_LOCATION IoStackLocation
Definition: usbdlib.h:265
#define IRP_MN_UNLOCK_ALL
Definition: iotypes.h:4415
#define IRP_MN_LOCK
Definition: iotypes.h:4413
#define IRP_MN_UNLOCK_ALL_BY_KEY
Definition: iotypes.h:4416
#define SL_FAIL_IMMEDIATELY
Definition: iotypes.h:1832
#define IRP_MN_UNLOCK_SINGLE
Definition: iotypes.h:4414
#define SL_EXCLUSIVE_LOCK
Definition: iotypes.h:1833
#define NT_ASSERT
Definition: rtlfuncs.h:3327

Referenced by _Dispatch_type_(), _Requires_lock_held_(), CdCommonLockControl(), Ext2LockControl(), FsRtlFastUnlockSingle(), FsRtlUninitializeFileLock(), UDFCommonLockControl(), and VfatLockControl().

◆ FsRtlUninitializeFileLock()

VOID NTAPI FsRtlUninitializeFileLock ( IN PFILE_LOCK  FileLock)

Definition at line 1283 of file filelock.c.

1284{
1285 if (FileLock->LockInformation)
1286 {
1287 PIRP Irp;
1288 PLOCK_INFORMATION InternalInfo = FileLock->LockInformation;
1290 PLIST_ENTRY SharedEntry;
1291 PLOCK_SHARED_RANGE SharedRange;
1292 // MSDN: this completes any remaining lock IRPs
1293 for (SharedEntry = InternalInfo->SharedLocks.Flink;
1294 SharedEntry != &InternalInfo->SharedLocks;)
1295 {
1296 SharedRange = CONTAINING_RECORD(SharedEntry, LOCK_SHARED_RANGE, Entry);
1297 SharedEntry = SharedEntry->Flink;
1298 RemoveEntryList(&SharedRange->Entry);
1299 ExFreePoolWithTag(SharedRange, TAG_RANGE);
1300 }
1301 while ((Entry = RtlGetElementGenericTable(&InternalInfo->RangeTable, 0)) != NULL)
1302 {
1304 }
1305 while ((Irp = IoCsqRemoveNextIrp(&InternalInfo->Csq, NULL)) != NULL)
1306 {
1308 /* FsRtlProcessFileLock has _Must_inspect_result_ */
1310 (void)Status;
1311 }
1312 ExFreePoolWithTag(InternalInfo, TAG_FLOCK);
1313 FileLock->LockInformation = NULL;
1314 }
1315}

Referenced by Ext2FreeFcb(), FatCreateFcb(), FatDeleteFcb(), FsRtlFreeFileLock(), reap_fcb(), RxFinalizeNetFcb(), UDFCleanUpFcbChain(), UDFInitializeFCB(), and vfatDestroyFCB().

◆ LockAcquireQueueLock()

static VOID NTAPI LockAcquireQueueLock ( PIO_CSQ  Csq,
PKIRQL  Irql 
)
static

Definition at line 190 of file filelock.c.

191{
193 KeAcquireSpinLock(&LockInfo->CsqLock, Irql);
194}
_Out_ PKIRQL Irql
Definition: csq.h:179
IO_CSQ Csq
Definition: csqrtns.c:46
#define KeAcquireSpinLock(sl, irql)
Definition: env_spec_w32.h:609

Referenced by FsRtlPrivateLock().

◆ LockAllocate()

static PVOID NTAPI LockAllocate ( PRTL_GENERIC_TABLE  Table,
CLONG  Bytes 
)
static

Definition at line 67 of file filelock.c.

68{
71 DPRINT("LockAllocate(%lu) => %p\n", Bytes, Result);
72 return Result;
73}
_In_ UINT Bytes
Definition: mmcopy.h:9
#define TAG_TABLE
Definition: tag.h:48

Referenced by FsRtlPrivateLock().

◆ LockCompare()

static RTL_GENERIC_COMPARE_RESULTS NTAPI LockCompare ( PRTL_GENERIC_TABLE  Table,
PVOID  PtrA,
PVOID  PtrB 
)
static

Definition at line 81 of file filelock.c.

83{
84 PCOMBINED_LOCK_ELEMENT A = PtrA, B = PtrB;
86#if 0
87 DPRINT("Starting to compare element %x to element %x\n", PtrA, PtrB);
88#endif
89 /* Match if we overlap */
90 if (((A->Exclusive.FileLock.StartingByte.QuadPart <
91 B->Exclusive.FileLock.EndingByte.QuadPart) &&
92 (A->Exclusive.FileLock.StartingByte.QuadPart >=
93 B->Exclusive.FileLock.StartingByte.QuadPart)) ||
94 ((B->Exclusive.FileLock.StartingByte.QuadPart <
95 A->Exclusive.FileLock.EndingByte.QuadPart) &&
96 (B->Exclusive.FileLock.StartingByte.QuadPart >=
97 A->Exclusive.FileLock.StartingByte.QuadPart)))
98 return GenericEqual;
99 /* Otherwise, key on the starting byte */
100 Result =
101 (A->Exclusive.FileLock.StartingByte.QuadPart <
102 B->Exclusive.FileLock.StartingByte.QuadPart) ? GenericLessThan :
103 (A->Exclusive.FileLock.StartingByte.QuadPart >
104 B->Exclusive.FileLock.StartingByte.QuadPart) ? GenericGreaterThan :
106#if 0
107 DPRINT("Compare(%x:%x) %x-%x to %x-%x => %d\n",
108 A,B,
109 A->Exclusive.FileLock.StartingByte.LowPart,
110 A->Exclusive.FileLock.EndingByte.LowPart,
111 B->Exclusive.FileLock.StartingByte.LowPart,
112 B->Exclusive.FileLock.EndingByte.LowPart,
113 Result);
114#endif
115 return Result;
116}
Definition: ehthrow.cxx:93
Definition: ehthrow.cxx:54
@ GenericLessThan
Definition: rtltypes.h:389
@ GenericGreaterThan
Definition: rtltypes.h:390
enum _RTL_GENERIC_COMPARE_RESULTS RTL_GENERIC_COMPARE_RESULTS

Referenced by FsRtlFastUnlockSingle(), FsRtlPrivateLock(), and LockPeekNextIrp().

◆ LockCompleteCanceledIrp()

static VOID NTAPI LockCompleteCanceledIrp ( PIO_CSQ  Csq,
PIRP  Irp 
)
static

Definition at line 204 of file filelock.c.

205{
208 DPRINT("Complete cancelled IRP %p Status %x\n", Irp, STATUS_CANCELLED);
211 NULL,
212 Irp,
214 &Status,
215 NULL);
216}
PCOMPLETE_LOCK_IRP_ROUTINE CompleteLockIrpRoutine
Definition: fsrtltypes.h:203
#define STATUS_CANCELLED
Definition: udferr_usr.h:170

Referenced by FsRtlPrivateLock().

◆ LockFree()

static VOID NTAPI LockFree ( PRTL_GENERIC_TABLE  Table,
PVOID  Buffer 
)
static

Definition at line 75 of file filelock.c.

76{
77 DPRINT("LockFree(%p)\n", Buffer);
79}
Definition: bufpool.h:45

Referenced by FsRtlPrivateLock().

◆ LockInsertIrpEx()

static NTSTATUS NTAPI LockInsertIrpEx ( PIO_CSQ  Csq,
PIRP  Irp,
PVOID  InsertContext 
)
static

Definition at line 120 of file filelock.c.

124{
126 InsertTailList(&LockInfo->CsqList, &Irp->Tail.Overlay.ListEntry);
127 return STATUS_SUCCESS;
128}

Referenced by FsRtlPrivateLock().

◆ LockPeekNextIrp()

static PIRP NTAPI LockPeekNextIrp ( PIO_CSQ  Csq,
PIRP  Irp,
PVOID  PeekContext 
)
static

Definition at line 135 of file filelock.c.

136{
137 // Context will be a COMBINED_LOCK_ELEMENT. We're looking for a
138 // lock that can be acquired, now that the lock matching PeekContext
139 // has been removed.
140 COMBINED_LOCK_ELEMENT LockElement;
143 PLIST_ENTRY Following;
144 DPRINT("PeekNextIrp(IRP %p, Context %p)\n", Irp, PeekContext);
145 if (!Irp)
146 {
147 Following = LockInfo->CsqList.Flink;
148 }
149 else
150 Following = Irp->Tail.Overlay.ListEntry.Flink;
151
152 DPRINT("ListEntry %p Head %p\n", Following, &LockInfo->CsqList);
153 for (;
154 Following != &LockInfo->CsqList;
155 Following = Following->Flink)
156 {
157 PIO_STACK_LOCATION IoStack;
158 BOOLEAN Matching;
159 Irp = CONTAINING_RECORD(Following, IRP, Tail.Overlay.ListEntry);
160 DPRINT("Irp %p\n", Irp);
162 LockElement.Exclusive.FileLock.StartingByte =
163 IoStack->Parameters.LockControl.ByteOffset;
166 IoStack->Parameters.LockControl.Length->QuadPart;
167 /* If a context was specified, it's a range to check to unlock */
168 if (WhereUnlock)
169 {
170 Matching = LockCompare
171 (&LockInfo->RangeTable, &LockElement, WhereUnlock) != GenericEqual;
172 }
173 /* Else get any completable IRP */
174 else
175 {
176 Matching = FALSE;
177 }
178 if (!Matching)
179 {
180 // This IRP is fine...
181 DPRINT("Returning the IRP %p\n", Irp);
182 return Irp;
183 }
184 }
185 DPRINT("Return NULL\n");
186 return NULL;
187}
_In_opt_ PIRP _In_opt_ PVOID PeekContext
Definition: csq.h:160

Referenced by FsRtlPrivateLock().

◆ LockReleaseQueueLock()

static VOID NTAPI LockReleaseQueueLock ( PIO_CSQ  Csq,
KIRQL  Irql 
)
static

Definition at line 197 of file filelock.c.

198{
200 KeReleaseSpinLock(&LockInfo->CsqLock, Irql);
201}
#define KeReleaseSpinLock(sl, irql)
Definition: env_spec_w32.h:627

Referenced by FsRtlPrivateLock().

◆ LockRemoveIrp()

static VOID NTAPI LockRemoveIrp ( PIO_CSQ  Csq,
PIRP  Irp 
)
static

Definition at line 130 of file filelock.c.

131{
132 RemoveEntryList(&Irp->Tail.Overlay.ListEntry);
133}

Referenced by FsRtlPrivateLock().

Variable Documentation

◆ FsRtlFileLockLookasideList

PAGED_LOOKASIDE_LIST FsRtlFileLockLookasideList

Definition at line 17 of file filelock.c.

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