ReactOS 0.4.15-dev-7958-gcd0bb1a
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 1318 of file filelock.c.

1320{
1321 PFILE_LOCK FileLock;
1322
1323 /* Try to allocate it */
1324 FileLock = ExAllocateFromPagedLookasideList(&FsRtlFileLockLookasideList);
1325 if (FileLock)
1326 {
1327 /* Initialize it */
1328 FsRtlInitializeFileLock(FileLock,
1331 }
1332
1333 /* Return the lock */
1334 return FileLock;
1335}
VOID NTAPI FsRtlInitializeFileLock(IN PFILE_LOCK FileLock, IN PCOMPLETE_LOCK_IRP_ROUTINE CompleteLockIrpRoutine OPTIONAL, IN PUNLOCK_ROUTINE UnlockRoutine OPTIONAL)
Definition: filelock.c:1262
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{
679 DPRINT("CheckLockForReadAccess(%wZ, Offset %08x%08x, Length %x)\n",
680 &IoStack->FileObject->FileName,
681 IoStack->Parameters.Read.ByteOffset.HighPart,
682 IoStack->Parameters.Read.ByteOffset.LowPart,
683 IoStack->Parameters.Read.Length);
684 if (!FileLock->LockInformation) {
685 DPRINT("CheckLockForReadAccess(%wZ) => TRUE\n", &IoStack->FileObject->FileName);
686 return TRUE;
687 }
688 ToFind.Exclusive.FileLock.StartingByte = IoStack->Parameters.Read.ByteOffset;
691 IoStack->Parameters.Read.Length;
693 (FileLock->LockInformation,
694 &ToFind);
695 if (!Found) {
696 DPRINT("CheckLockForReadAccess(%wZ) => TRUE\n", &IoStack->FileObject->FileName);
697 return TRUE;
698 }
699 Result = !Found->Exclusive.FileLock.ExclusiveLock ||
700 IoStack->Parameters.Read.Key == Found->Exclusive.FileLock.Key;
701 DPRINT("CheckLockForReadAccess(%wZ) => %s\n", &IoStack->FileObject->FileName, Result ? "TRUE" : "FALSE");
702 return Result;
703}
static PIO_STACK_LOCATION IoGetCurrentIrpStackLocation(PIRP Irp)
unsigned char BOOLEAN
return Found
Definition: dirsup.c:1270
_In_ PIRP Irp
Definition: csq.h:116
#define TRUE
Definition: types.h:120
#define DPRINT
Definition: sndvol32.h:71
FILE_LOCK_INFO FileLock
LARGE_INTEGER EndingByte
Definition: fsrtltypes.h:194
LARGE_INTEGER StartingByte
Definition: fsrtltypes.h:188
PFILE_OBJECT FileObject
Definition: iotypes.h:3169
union _IO_STACK_LOCATION::@1564 Parameters
struct _IO_STACK_LOCATION::@3978::@3982 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 710 of file filelock.c.

712{
717 PEPROCESS Process = Irp->Tail.Overlay.Thread->ThreadsProcess;
718 DPRINT("CheckLockForWriteAccess(%wZ, Offset %08x%08x, Length %x)\n",
719 &IoStack->FileObject->FileName,
720 IoStack->Parameters.Write.ByteOffset.HighPart,
721 IoStack->Parameters.Write.ByteOffset.LowPart,
722 IoStack->Parameters.Write.Length);
723 if (!FileLock->LockInformation) {
724 DPRINT("CheckLockForWriteAccess(%wZ) => TRUE\n", &IoStack->FileObject->FileName);
725 return TRUE;
726 }
727 ToFind.Exclusive.FileLock.StartingByte = IoStack->Parameters.Write.ByteOffset;
730 IoStack->Parameters.Write.Length;
732 (FileLock->LockInformation,
733 &ToFind);
734 if (!Found) {
735 DPRINT("CheckLockForWriteAccess(%wZ) => TRUE\n", &IoStack->FileObject->FileName);
736 return TRUE;
737 }
738 Result = Process == Found->Exclusive.FileLock.ProcessId;
739 DPRINT("CheckLockForWriteAccess(%wZ) => %s\n", &IoStack->FileObject->FileName, Result ? "TRUE" : "FALSE");
740 return Result;
741}
_Must_inspect_result_ _In_ PLARGE_INTEGER _In_ PLARGE_INTEGER _In_ ULONG _In_ PFILE_OBJECT _In_ PVOID Process
Definition: fsrtlfuncs.h:223
struct _IO_STACK_LOCATION::@3978::@3983 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:25
_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 748 of file filelock.c.

754{
755 PEPROCESS EProcess = Process;
758 DPRINT("FsRtlFastCheckLockForRead(%wZ, Offset %08x%08x, Length %08x%08x, Key %x)\n",
759 &FileObject->FileName,
760 FileOffset->HighPart,
761 FileOffset->LowPart,
762 Length->HighPart,
763 Length->LowPart,
764 Key);
767 FileOffset->QuadPart + Length->QuadPart;
768 if (!FileLock->LockInformation) return TRUE;
770 (FileLock->LockInformation,
771 &ToFind);
772 if (!Found || !Found->Exclusive.FileLock.ExclusiveLock) return TRUE;
773 return Found->Exclusive.FileLock.Key == Key &&
774 Found->Exclusive.FileLock.ProcessId == EProcess;
775}
_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 782 of file filelock.c.

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

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 1025 of file filelock.c.

1029{
1030 PLIST_ENTRY ListEntry;
1032 PLOCK_INFORMATION InternalInfo = FileLock->LockInformation;
1033 DPRINT("FsRtlFastUnlockAll(%wZ)\n", &FileObject->FileName);
1034 // XXX Synchronize somehow
1035 if (!FileLock->LockInformation) {
1036 DPRINT("Not locked %wZ\n", &FileObject->FileName);
1037 return STATUS_RANGE_NOT_LOCKED; // no locks
1038 }
1039 for (ListEntry = InternalInfo->SharedLocks.Flink;
1040 ListEntry != &InternalInfo->SharedLocks;)
1041 {
1044 Length.QuadPart = Range->End.QuadPart - Range->Start.QuadPart;
1045 ListEntry = ListEntry->Flink;
1046 if (Range->ProcessId != Process)
1047 continue;
1049 (FileLock,
1050 FileObject,
1051 &Range->Start,
1052 &Length,
1053 Range->ProcessId,
1054 Range->Key,
1055 Context,
1056 TRUE);
1057 }
1058 for (Entry = RtlEnumerateGenericTable(&InternalInfo->RangeTable, TRUE);
1059 Entry;
1061 {
1063 // We'll take the first one to be the list head, and free the others first...
1064 Length.QuadPart =
1065 Entry->Exclusive.FileLock.EndingByte.QuadPart -
1066 Entry->Exclusive.FileLock.StartingByte.QuadPart;
1068 (FileLock,
1069 Entry->Exclusive.FileLock.FileObject,
1070 &Entry->Exclusive.FileLock.StartingByte,
1071 &Length,
1072 Entry->Exclusive.FileLock.ProcessId,
1073 Entry->Exclusive.FileLock.Key,
1074 Context,
1075 TRUE);
1076 }
1077 DPRINT("Done %wZ\n", &FileObject->FileName);
1078 return STATUS_SUCCESS;
1079}
#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:825
#define STATUS_RANGE_NOT_LOCKED
Definition: ntstatus.h:362
#define STATUS_SUCCESS
Definition: shellext.h:65
base of all file and directory entries
Definition: entries.h:83
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
Definition: range.c:39
#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 1086 of file filelock.c.

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

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 825 of file filelock.c.

833{
834 BOOLEAN FoundShared = FALSE;
835 PLIST_ENTRY SharedEntry;
836 PLOCK_SHARED_RANGE SharedRange = NULL;
839 PIRP NextMatchingLockIrp;
840 PLOCK_INFORMATION InternalInfo = FileLock->LockInformation;
841 DPRINT("FsRtlFastUnlockSingle(%wZ, Offset %08x%08x (%d), Length %08x%08x (%d), Key %x)\n",
842 &FileObject->FileName,
843 FileOffset->HighPart,
844 FileOffset->LowPart,
845 (int)FileOffset->QuadPart,
846 Length->HighPart,
847 Length->LowPart,
848 (int)Length->QuadPart,
849 Key);
850 // The region to unlock must correspond exactly to a previously locked region
851 // -- msdn
852 // But Windows 2003 doesn't assert on it and simply ignores that parameter
853 // ASSERT(AlreadySynchronized);
856 FileOffset->QuadPart + Length->QuadPart;
857 if (!InternalInfo) {
858 DPRINT("File not previously locked (ever)\n");
860 }
861 Entry = RtlLookupElementGenericTable(&InternalInfo->RangeTable, &Find);
862 if (!Entry) {
863 DPRINT("Range not locked %wZ\n", &FileObject->FileName);
865 }
866
867 DPRINT("Found lock entry: Exclusive %u %08x%08x:%08x%08x %wZ\n",
868 Entry->Exclusive.FileLock.ExclusiveLock,
869 Entry->Exclusive.FileLock.StartingByte.HighPart,
870 Entry->Exclusive.FileLock.StartingByte.LowPart,
871 Entry->Exclusive.FileLock.EndingByte.HighPart,
872 Entry->Exclusive.FileLock.EndingByte.LowPart,
873 &FileObject->FileName);
874
875 if (Entry->Exclusive.FileLock.ExclusiveLock)
876 {
877 if (Entry->Exclusive.FileLock.Key != Key ||
878 Entry->Exclusive.FileLock.ProcessId != Process ||
879 Entry->Exclusive.FileLock.StartingByte.QuadPart != FileOffset->QuadPart ||
880 Entry->Exclusive.FileLock.EndingByte.QuadPart !=
881 FileOffset->QuadPart + Length->QuadPart)
882 {
883 DPRINT("Range not locked %wZ\n", &FileObject->FileName);
885 }
886 RtlCopyMemory(&Find, Entry, sizeof(Find));
887 // Remove the old exclusive lock region
889 }
890 else
891 {
892 DPRINT("Shared lock %wZ Start %08x%08x End %08x%08x\n",
893 &FileObject->FileName,
894 Entry->Exclusive.FileLock.StartingByte.HighPart,
895 Entry->Exclusive.FileLock.StartingByte.LowPart,
896 Entry->Exclusive.FileLock.EndingByte.HighPart,
897 Entry->Exclusive.FileLock.EndingByte.LowPart);
898 for (SharedEntry = InternalInfo->SharedLocks.Flink;
899 SharedEntry != &InternalInfo->SharedLocks;
900 SharedEntry = SharedEntry->Flink)
901 {
902 SharedRange = CONTAINING_RECORD(SharedEntry, LOCK_SHARED_RANGE, Entry);
903 if (SharedRange->Start.QuadPart == FileOffset->QuadPart &&
904 SharedRange->End.QuadPart == FileOffset->QuadPart + Length->QuadPart &&
905 SharedRange->Key == Key &&
906 SharedRange->ProcessId == Process)
907 {
908 FoundShared = TRUE;
909 DPRINT("Found shared element to delete %wZ Start %08x%08x End %08x%08x Key %x\n",
910 &FileObject->FileName,
911 SharedRange->Start.HighPart,
912 SharedRange->Start.LowPart,
913 SharedRange->End.HighPart,
914 SharedRange->End.LowPart,
915 SharedRange->Key);
916 break;
917 }
918 }
919 if (FoundShared)
920 {
921 /* Remove the found range from the shared range lists */
922 RemoveEntryList(&SharedRange->Entry);
923 ExFreePoolWithTag(SharedRange, TAG_RANGE);
924 /* We need to rebuild the list of shared ranges. */
925 DPRINT("Removing the lock entry %wZ (%08x%08x:%08x%08x)\n",
926 &FileObject->FileName,
927 Entry->Exclusive.FileLock.StartingByte.HighPart,
928 Entry->Exclusive.FileLock.StartingByte.LowPart,
929 Entry->Exclusive.FileLock.EndingByte.HighPart,
930 Entry->Exclusive.FileLock.EndingByte.LowPart);
931
932 /* Remember what was in there and remove it from the table */
933 Find = *Entry;
934 RtlDeleteElementGenericTable(&InternalInfo->RangeTable, &Find);
935 /* Put shared locks back in place */
936 for (SharedEntry = InternalInfo->SharedLocks.Flink;
937 SharedEntry != &InternalInfo->SharedLocks;
938 SharedEntry = SharedEntry->Flink)
939 {
940 COMBINED_LOCK_ELEMENT LockElement;
941 SharedRange = CONTAINING_RECORD(SharedEntry, LOCK_SHARED_RANGE, Entry);
943 LockElement.Exclusive.FileLock.StartingByte = SharedRange->Start;
944 LockElement.Exclusive.FileLock.EndingByte = SharedRange->End;
945 LockElement.Exclusive.FileLock.ProcessId = SharedRange->ProcessId;
946 LockElement.Exclusive.FileLock.Key = SharedRange->Key;
948
949 if (LockCompare(&InternalInfo->RangeTable, &Find, &LockElement) != GenericEqual)
950 {
951 DPRINT("Skipping range %08x%08x:%08x%08x\n",
956 continue;
957 }
958 DPRINT("Re-creating range %08x%08x:%08x%08x\n",
963 FsRtlpRebuildSharedLockRange(FileLock, InternalInfo, &LockElement);
964 }
965 }
966 else
967 {
969 }
970 }
971
972#ifndef NDEBUG
973 DPRINT("Lock still has:\n");
974 for (SharedEntry = InternalInfo->SharedLocks.Flink;
975 SharedEntry != &InternalInfo->SharedLocks;
976 SharedEntry = SharedEntry->Flink)
977 {
978 SharedRange = CONTAINING_RECORD(SharedEntry, LOCK_SHARED_RANGE, Entry);
979 DPRINT("Shared element %wZ Offset %08x%08x Length %08x%08x Key %x\n",
980 &FileObject->FileName,
981 SharedRange->Start.HighPart,
982 SharedRange->Start.LowPart,
983 SharedRange->End.HighPart,
984 SharedRange->End.LowPart,
985 SharedRange->Key);
986 }
987#endif
988
989 // this is definitely the thing we want
990 InternalInfo->Generation++;
991 while ((NextMatchingLockIrp = IoCsqRemoveNextIrp(&InternalInfo->Csq, &Find)))
992 {
994 if (NextMatchingLockIrp->IoStatus.Information == InternalInfo->Generation)
995 {
996 // We've already looked at this one, meaning that we looped.
997 // Put it back and exit.
999 (&InternalInfo->Csq,
1000 NextMatchingLockIrp,
1001 NULL,
1002 NULL);
1003 break;
1004 }
1005 // Got a new lock irp... try to do the new lock operation
1006 // Note that we pick an operation that would succeed at the time
1007 // we looked, but can't guarantee that it won't just be re-queued
1008 // because somebody else snatched part of the range in a new thread.
1009 DPRINT("Locking another IRP %p for %p %wZ\n",
1010 NextMatchingLockIrp, FileLock, &FileObject->FileName);
1011 Status = FsRtlProcessFileLock(InternalInfo->BelongsTo, NextMatchingLockIrp, NULL);
1012 if (!NT_SUCCESS(Status))
1013 return Status;
1014 }
1015
1016 DPRINT("Success %wZ\n", &FileObject->FileName);
1017 return STATUS_SUCCESS;
1018}
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:32
#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:1152
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
LARGE_INTEGER End
Definition: filelock.c:48
LARGE_INTEGER Start
Definition: filelock.c:48
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:378

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

◆ FsRtlFreeFileLock()

VOID NTAPI FsRtlFreeFileLock ( IN PFILE_LOCK  FileLock)

Definition at line 1342 of file filelock.c.

1343{
1344 /* Uninitialize and free the lock */
1345 FsRtlUninitializeFileLock(FileLock);
1346 ExFreeToPagedLookasideList(&FsRtlFileLockLookasideList, FileLock);
1347}
VOID NTAPI FsRtlUninitializeFileLock(IN PFILE_LOCK FileLock)
Definition: filelock.c:1279

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 1262 of file filelock.c.

1265{
1266 /* Setup the lock */
1267 RtlZeroMemory(FileLock, sizeof(*FileLock));
1268 FileLock->FastIoIsQuestionable = FALSE;
1269 FileLock->CompleteLockIrpRoutine = CompleteLockIrpRoutine;
1270 FileLock->UnlockRoutine = UnlockRoutine;
1271 FileLock->LockInformation = NULL;
1272}
#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 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:2714
IN PLARGE_INTEGER IN PLARGE_INTEGER PEPROCESS ULONG BOOLEAN FailImmediately
Definition: fatprocs.h:2713
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:320
#define STATUS_PENDING
Definition: ntstatus.h:82
#define STATUS_NO_MEMORY
Definition: ntstatus.h:260
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
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 1152 of file filelock.c.

1155{
1156 PIO_STACK_LOCATION IoStackLocation;
1159
1160 /* Get the I/O Stack location */
1161 IoStackLocation = IoGetCurrentIrpStackLocation(Irp);
1162 ASSERT(IoStackLocation->MajorFunction == IRP_MJ_LOCK_CONTROL);
1163
1164 /* Clear the I/O status block and check what function this is */
1166
1167 DPRINT("FsRtlProcessFileLock(%wZ, MinorFunction %x)\n",
1168 &IoStackLocation->FileObject->FileName,
1169 IoStackLocation->MinorFunction);
1170
1171 switch(IoStackLocation->MinorFunction)
1172 {
1173 /* A lock */
1174 case IRP_MN_LOCK:
1175 {
1176 /* Call the private lock routine */
1177 BOOLEAN Result = FsRtlPrivateLock(FileLock,
1178 IoStackLocation->FileObject,
1179 &IoStackLocation->Parameters.LockControl.ByteOffset,
1180 IoStackLocation->Parameters.LockControl.Length,
1182 IoStackLocation->Parameters.LockControl.Key,
1183 IoStackLocation->Flags & SL_FAIL_IMMEDIATELY,
1184 IoStackLocation->Flags & SL_EXCLUSIVE_LOCK,
1186 Irp,
1187 Context,
1188 FALSE);
1189 /* FsRtlPrivateLock has _Must_inspect_result_. Just check this is consistent on debug builds */
1191 (void)Result;
1192 return IoStatusBlock.Status;
1193 }
1194 /* A single unlock */
1196
1197 /* Call fast unlock */
1199 FsRtlFastUnlockSingle(FileLock,
1200 IoStackLocation->FileObject,
1201 &IoStackLocation->Parameters.LockControl.
1202 ByteOffset,
1203 IoStackLocation->Parameters.LockControl.
1204 Length,
1206 IoStackLocation->Parameters.LockControl.
1207 Key,
1208 Context,
1209 FALSE);
1210 break;
1211
1212 /* Total unlock */
1213 case IRP_MN_UNLOCK_ALL:
1214
1215 /* Do a fast unlock */
1217 IoStackLocation->
1218 FileObject,
1220 Context);
1221 break;
1222
1223 /* Unlock by key */
1225
1226 /* Do it */
1228 FsRtlFastUnlockAllByKey(FileLock,
1229 IoStackLocation->FileObject,
1231 IoStackLocation->Parameters.
1232 LockControl.Key,
1233 Context);
1234 break;
1235
1236 /* Invalid request */
1237 default:
1238
1239 /* Complete it */
1243 }
1244
1245 /* Return the status */
1246 DPRINT("Lock IRP %p %x\n", Irp, IoStatusBlock.Status);
1248 (FileLock->CompleteLockIrpRoutine,
1249 Context,
1250 Irp,
1252 &Status,
1253 NULL);
1254 return IoStatusBlock.Status;
1255}
IN PDCB IN PCCB IN VBO IN OUT PULONG OUT PDIRENT OUT PBCB OUT PVBO ByteOffset
Definition: fatprocs.h:731
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:1025
NTSTATUS NTAPI FsRtlFastUnlockAllByKey(IN PFILE_LOCK FileLock, IN PFILE_OBJECT FileObject, IN PEPROCESS Process, IN ULONG Key, IN PVOID Context OPTIONAL)
Definition: filelock.c:1086
static OUT PIO_STATUS_BLOCK IoStatusBlock
Definition: pipe.c:75
PEPROCESS NTAPI IoGetRequestorProcess(IN PIRP Irp)
Definition: irp.c:1782
#define IRP_MJ_LOCK_CONTROL
Definition: rdpdr.c:53
struct _IO_STACK_LOCATION::@3978::@3994 LockControl
ULONG POINTER_ALIGNMENT Key
Definition: iotypes.h:3139
#define STATUS_INVALID_DEVICE_REQUEST
Definition: udferr_usr.h:138
#define IRP_MN_UNLOCK_ALL
Definition: iotypes.h:4412
#define IRP_MN_LOCK
Definition: iotypes.h:4410
#define IRP_MN_UNLOCK_ALL_BY_KEY
Definition: iotypes.h:4413
#define SL_FAIL_IMMEDIATELY
Definition: iotypes.h:1832
#define IRP_MN_UNLOCK_SINGLE
Definition: iotypes.h:4411
#define SL_EXCLUSIVE_LOCK
Definition: iotypes.h:1833
#define NT_ASSERT
Definition: rtlfuncs.h:3310

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 1279 of file filelock.c.

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

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:376
@ GenericGreaterThan
Definition: rtltypes.h:377
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().