ReactOS  0.4.15-dev-3720-g4cf9b79
filelock.c
Go to the documentation of this file.
1 /*
2  * PROJECT: ReactOS Kernel
3  * LICENSE: GPL - See COPYING in the top level directory
4  * FILE: ntoskrnl/fsrtl/filelock.c
5  * PURPOSE: File Locking implementation for File System Drivers
6  * PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org)
7  */
8 
9 /* INCLUDES ******************************************************************/
10 
11 #include <ntoskrnl.h>
12 #define NDEBUG
13 #include <debug.h>
14 
15 /* GLOBALS *******************************************************************/
16 
18 
19 /* Note: this aligns the two types of lock entry structs so we can access the
20  FILE_LOCK_INFO part in common. Add elements after Shared if new stuff is needed.
21 */
23 {
24  struct
25  {
28  };
30 }
32 
33 typedef struct _LOCK_INFORMATION
34 {
42 }
44 
45 typedef struct _LOCK_SHARED_RANGE
46 {
51 }
53 
54 /* PRIVATE FUNCTIONS *********************************************************/
55 
56 VOID
57 NTAPI
60  IN PIRP Irp,
62  OUT PNTSTATUS NewStatus,
64 
65 /* Generic table methods */
66 
68 {
69  PVOID Result;
71  DPRINT("LockAllocate(%lu) => %p\n", Bytes, Result);
72  return Result;
73 }
74 
76 {
77  DPRINT("LockFree(%p)\n", Buffer);
79 }
80 
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 :
105  GenericEqual;
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 }
117 
118 /* CSQ methods */
119 
122  PIRP Irp,
124 {
126  InsertTailList(&LockInfo->CsqList, &Irp->Tail.Overlay.ListEntry);
127  return STATUS_SUCCESS;
128 }
129 
131 {
132  RemoveEntryList(&Irp->Tail.Overlay.ListEntry);
133 }
134 
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;
141  PCOMBINED_LOCK_ELEMENT WhereUnlock = PeekContext;
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;
164  LockElement.Exclusive.FileLock.EndingByte.QuadPart =
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 }
188 
189 static VOID NTAPI
191 {
193  KeAcquireSpinLock(&LockInfo->CsqLock, Irql);
194 }
195 
196 static VOID NTAPI
198 {
200  KeReleaseSpinLock(&LockInfo->CsqLock, Irql);
201 }
202 
203 static VOID NTAPI
205 {
208  DPRINT("Complete cancelled IRP %p Status %x\n", Irp, STATUS_CANCELLED);
210  (LockInfo->BelongsTo->CompleteLockIrpRoutine,
211  NULL,
212  Irp,
214  &Status,
215  NULL);
216 }
217 
218 VOID
219 NTAPI
221  IN PVOID Context,
222  IN PIRP Irp,
224  OUT PNTSTATUS NewStatus,
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 }
247 
248 /* PUBLIC FUNCTIONS **********************************************************/
249 
250 /*
251  * @implemented
252  */
254 NTAPI
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 }
264 
265 VOID
266 NTAPI
269  PCOMBINED_LOCK_ELEMENT Conflict)
270 {
271  if (ToExpand->Exclusive.FileLock.StartingByte.QuadPart >
273  {
274  ToExpand->Exclusive.FileLock.StartingByte =
275  Conflict->Exclusive.FileLock.StartingByte;
276  }
277  if (ToExpand->Exclusive.FileLock.EndingByte.QuadPart <
279  {
280  ToExpand->Exclusive.FileLock.EndingByte =
281  Conflict->Exclusive.FileLock.EndingByte;
282  }
283 }
284 
285 /* This function expands the conflicting range Conflict by removing and reinserting it,
286  then adds a shared range of the same size */
288 NTAPI
290 (PFILE_LOCK FileLock,
291  PLOCK_INFORMATION LockInfo,
292  PCOMBINED_LOCK_ELEMENT Conflict)
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);
305  RemovedOld = RtlDeleteElementGenericTable
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 }
318 
319 /*
320  * @implemented
321  */
322 BOOLEAN
323 NTAPI
329  IN ULONG Key,
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,
356  ExclusiveLock);
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;
391  InitializeListHead(&LockInfo->SharedLocks);
392 
394  (&LockInfo->RangeTable,
395  LockCompare,
396  LockAllocate,
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;
417  ToInsert.Exclusive.FileLock.ProcessId = Process;
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",
436  Conflict->Exclusive.FileLock.ExclusiveLock,
437  ExclusiveLock);
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,
618  Conflict->Exclusive.FileLock.ExclusiveLock);
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 }
666 
667 /*
668  * @implemented
669  */
670 BOOLEAN
671 NTAPI
673  IN PIRP Irp)
674 {
675  BOOLEAN Result;
677  COMBINED_LOCK_ELEMENT ToFind;
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 }
704 
705 /*
706  * @implemented
707  */
708 BOOLEAN
709 NTAPI
711  IN PIRP Irp)
712 {
713  BOOLEAN Result;
715  COMBINED_LOCK_ELEMENT ToFind;
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 }
742 
743 /*
744  * @implemented
745  */
746 BOOLEAN
747 NTAPI
751  IN ULONG Key,
753  IN PVOID Process)
754 {
755  PEPROCESS EProcess = Process;
756  COMBINED_LOCK_ELEMENT ToFind;
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 }
776 
777 /*
778  * @implemented
779  */
780 BOOLEAN
781 NTAPI
785  IN ULONG Key,
787  IN PVOID Process)
788 {
789  BOOLEAN Result;
790  PEPROCESS EProcess = Process;
791  COMBINED_LOCK_ELEMENT ToFind;
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 }
819 
820 /*
821  * @implemented
822  */
823 NTSTATUS
824 NTAPI
830  IN ULONG Key,
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);
942  LockElement.Exclusive.FileLock.FileObject = FileObject;
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;
947  LockElement.Exclusive.FileLock.ExclusiveLock = FALSE;
948 
949  if (LockCompare(&InternalInfo->RangeTable, &Find, &LockElement) != GenericEqual)
950  {
951  DPRINT("Skipping range %08x%08x:%08x%08x\n",
955  LockElement.Exclusive.FileLock.EndingByte.LowPart);
956  continue;
957  }
958  DPRINT("Re-creating range %08x%08x:%08x%08x\n",
962  LockElement.Exclusive.FileLock.EndingByte.LowPart);
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 }
1019 
1020 /*
1021  * @implemented
1022  */
1023 NTSTATUS
1024 NTAPI
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;
1060  Entry = RtlEnumerateGenericTable(&InternalInfo->RangeTable, FALSE))
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 }
1080 
1081 /*
1082  * @implemented
1083  */
1084 NTSTATUS
1085 NTAPI
1089  IN ULONG Key,
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;
1122  Entry = RtlEnumerateGenericTable(&InternalInfo->RangeTable, FALSE))
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 }
1146 
1147 /*
1148  * @implemented
1149  */
1150 NTSTATUS
1151 NTAPI
1153  IN PIRP Irp,
1155 {
1156  PIO_STACK_LOCATION IoStackLocation;
1157  NTSTATUS Status;
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,
1185  &IoStatusBlock,
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 */
1195  case IRP_MN_UNLOCK_SINGLE:
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 }
1256 
1257 /*
1258  * @implemented
1259  */
1260 VOID
1261 NTAPI
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 }
1273 
1274 /*
1275  * @implemented
1276  */
1277 VOID
1278 NTAPI
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 }
1312 
1313 /*
1314  * @implemented
1315  */
1316 PFILE_LOCK
1317 NTAPI
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,
1330  UnlockRoutine);
1331  }
1332 
1333  /* Return the lock */
1334  return FileLock;
1335 }
1336 
1337 /*
1338  * @implemented
1339  */
1340 VOID
1341 NTAPI
1343 {
1344  /* Uninitialize and free the lock */
1345  FsRtlUninitializeFileLock(FileLock);
1346  ExFreeToPagedLookasideList(&FsRtlFileLockLookasideList, FileLock);
1347 }
VOID NTAPI FsRtlpExpandLockElement(PCOMBINED_LOCK_ELEMENT ToExpand, PCOMBINED_LOCK_ELEMENT Conflict)
Definition: filelock.c:268
* PNTSTATUS
Definition: strlen.c:14
PEPROCESS NTAPI IoGetRequestorProcess(IN PIRP Irp)
Definition: irp.c:1782
#define IN
Definition: typedefs.h:39
FILE_EXCLUSIVE_LOCK_ENTRY Exclusive
Definition: filelock.c:29
ASMGENDATA Table[]
Definition: genincdata.c:61
Definition: ehthrow.cxx:53
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: filelock.c:748
_In_ ULONG _In_ ULONG _In_ ULONG Length
Definition: ntddpcm.h:101
struct png_info_def **typedef void(__cdecl typeof(png_destroy_read_struct))(struct png_struct_def **
Definition: typeof.h:49
LARGE_INTEGER End
Definition: filelock.c:48
struct _Entry Entry
Definition: kefuncs.h:627
struct _LOCK_SHARED_RANGE * PLOCK_SHARED_RANGE
_Must_inspect_result_ _In_opt_ PUNLOCK_ROUTINE UnlockRoutine
Definition: fltkernel.h:2123
VOID NTAPI FsRtlInitializeFileLock(IN PFILE_LOCK FileLock, IN PCOMPLETE_LOCK_IRP_ROUTINE CompleteLockIrpRoutine OPTIONAL, IN PUNLOCK_ROUTINE UnlockRoutine OPTIONAL)
Definition: filelock.c:1262
NTKERNELAPI PIRP NTAPI IoCsqRemoveNextIrp(_Inout_ PIO_CSQ Csq, _In_opt_ PVOID PeekContext)
IoCsqRemoveNextIrp - Removes the next IRP from the queue.
Definition: csq.c:398
NTSYSAPI ULONG NTAPI RtlNumberGenericTableElements(_In_ PRTL_GENERIC_TABLE Table)
#define TAG_TABLE
Definition: tag.h:46
#define STATUS_RANGE_NOT_LOCKED
Definition: ntstatus.h:362
#define TRUE
Definition: types.h:120
#define STATUS_INVALID_PARAMETER
Definition: udferr_usr.h:135
VOID NTAPI FsRtlUninitializeFileLock(IN PFILE_LOCK FileLock)
Definition: filelock.c:1279
BOOLEAN NTAPI FsRtlCheckLockForWriteAccess(IN PFILE_LOCK FileLock, IN PIRP Irp)
Definition: filelock.c:710
_In_ PFILE_OBJECT _In_ PLARGE_INTEGER _In_ PLARGE_INTEGER _In_ PEPROCESS _In_ ULONG _In_opt_ PVOID _In_ BOOLEAN AlreadySynchronized
Definition: fsrtlfuncs.h:265
static VOID NTAPI LockRemoveIrp(PIO_CSQ Csq, PIRP Irp)
Definition: filelock.c:130
LONG NTSTATUS
Definition: precomp.h:26
_Must_inspect_result_ NTSYSAPI PVOID NTAPI RtlEnumerateGenericTable(_In_ PRTL_GENERIC_TABLE Table, _In_ BOOLEAN Restart)
PFILE_LOCK NTAPI FsRtlAllocateFileLock(IN PCOMPLETE_LOCK_IRP_ROUTINE CompleteLockIrpRoutine OPTIONAL, IN PUNLOCK_ROUTINE UnlockRoutine OPTIONAL)
Definition: filelock.c:1318
LARGE_INTEGER Start
Definition: filelock.c:48
static VOID NTAPI LockFree(PRTL_GENERIC_TABLE Table, PVOID Buffer)
Definition: filelock.c:75
_In_ UINT Bytes
Definition: mmcopy.h:9
VOID NTAPI KeAcquireSpinLock(PKSPIN_LOCK SpinLock, PKIRQL OldIrql)
Definition: spinlock.c:50
#define STATUS_INVALID_DEVICE_REQUEST
Definition: udferr_usr.h:138
#define IRP_MN_UNLOCK_ALL_BY_KEY
Definition: iotypes.h:4413
#define TAG_FLOCK
Definition: tag.h:48
IO_STATUS_BLOCK IoStatus
PCOMPLETE_LOCK_IRP_ROUTINE CompleteLockIrpRoutine
Definition: fsrtltypes.h:203
#define InsertTailList(ListHead, Entry)
_Out_ PKIRQL Irql
Definition: csq.h:179
Definition: ehthrow.cxx:92
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
struct _LOCK_INFORMATION LOCK_INFORMATION
PAGED_LOOKASIDE_LIST FsRtlFileLockLookasideList
Definition: filelock.c:17
LIST_ENTRY Entry
Definition: filelock.c:47
FORCEINLINE BOOLEAN RemoveEntryList(_In_ PLIST_ENTRY Entry)
Definition: rtlfuncs.h:105
LARGE_INTEGER EndingByte
Definition: fsrtltypes.h:194
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
UCHAR KIRQL
Definition: env_spec_w32.h:591
ULONG CLONG
Definition: umtypes.h:126
NTSTATUS(* NTAPI)(IN PFILE_FULL_EA_INFORMATION EaBuffer, IN ULONG EaLength, OUT PULONG ErrorOffset)
Definition: IoEaTest.cpp: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
ULONGLONG QuadPart
Definition: ms-dtyp.idl:185
#define FALSE
Definition: types.h:117
_In_ PIRP Irp
Definition: csq.h:116
IN PLARGE_INTEGER IN PLARGE_INTEGER PEPROCESS ULONG BOOLEAN FailImmediately
Definition: fatprocs.h:2709
static VOID NTAPI LockCompleteCanceledIrp(PIO_CSQ Csq, PIRP Irp)
Definition: filelock.c:204
LIST_ENTRY dummy
Definition: filelock.c:26
FORCEINLINE VOID KeInitializeSpinLock(_Out_ PKSPIN_LOCK SpinLock)
Definition: kefuncs.h:238
unsigned char BOOLEAN
PFILE_OBJECT FileObject
Definition: fsrtltypes.h:192
_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:426
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
_Must_inspect_result_ _In_ WDFDEVICE _In_ ULONG _In_ ACCESS_MASK _In_opt_ PWDF_OBJECT_ATTRIBUTES _Out_ WDFKEY * Key
Definition: wdfdevice.h:2654
FILE_LOCK_INFO FileLock
static VOID NTAPI LockAcquireQueueLock(PIO_CSQ Csq, PKIRQL Irql)
Definition: filelock.c:190
Definition: bufpool.h:45
return Found
Definition: dirsup.c:1270
KSPIN_LOCK CsqLock
Definition: filelock.c:37
PFLT_MESSAGE_WAITER_QUEUE CONTAINING_RECORD(Csq, DEVICE_EXTENSION, IrpQueue)) -> WaiterQ.mLock) _IRQL_raises_(DISPATCH_LEVEL) VOID NTAPI FltpAcquireMessageWaiterLock(_In_ PIO_CSQ Csq, _Out_ PKIRQL Irql)
Definition: Messaging.c:560
_In_ WDFREQUEST _In_ WDFFILEOBJECT FileObject
Definition: wdfdevice.h:547
PFILE_LOCK_INFO NTAPI FsRtlGetNextFileLock(IN PFILE_LOCK FileLock, IN BOOLEAN Restart)
Definition: filelock.c:255
static PIRP NTAPI LockPeekNextIrp(PIO_CSQ Csq, PIRP Irp, PVOID PeekContext)
Definition: filelock.c:135
_Must_inspect_result_ NTSYSAPI PVOID NTAPI RtlLookupElementGenericTable(_In_ PRTL_GENERIC_TABLE Table, _In_ PVOID Buffer)
Status
Definition: gdiplustypes.h:24
VOID(NTAPI * PUNLOCK_ROUTINE)(_In_ PVOID Context, _In_ PFILE_LOCK_INFO FileLockInfo)
Definition: fsrtltypes.h:198
_In_ PIRP _In_ PVOID InsertContext
Definition: csq.h:257
struct _LIST_ENTRY * Flink
Definition: typedefs.h:121
#define ASSERT(a)
Definition: mode.c:44
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
#define STATUS_PENDING
Definition: ntstatus.h:82
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
BOOLEAN NTAPI FsRtlCheckLockForReadAccess(IN PFILE_LOCK FileLock, IN PIRP Irp)
Definition: filelock.c:672
FILE_SHARED_LOCK_ENTRY Shared
Definition: filelock.c:27
_Must_inspect_result_ NTSYSAPI PVOID NTAPI RtlGetElementGenericTable(_In_ PRTL_GENERIC_TABLE Table, _In_ ULONG I)
union _COMBINED_LOCK_ELEMENT COMBINED_LOCK_ELEMENT
#define STATUS_CANCELLED
Definition: udferr_usr.h:170
static NTSTATUS NTAPI LockInsertIrpEx(PIO_CSQ Csq, PIRP Irp, PVOID InsertContext)
Definition: filelock.c:121
#define IRP_MN_UNLOCK_ALL
Definition: iotypes.h:4412
* PFILE_OBJECT
Definition: iotypes.h:1998
RTL_GENERIC_TABLE RangeTable
Definition: filelock.c:35
#define ExAllocatePoolWithTag(hernya, size, tag)
Definition: env_spec_w32.h:350
LIST_ENTRY SharedLocks
Definition: filelock.c:40
NTSTATUS(NTAPI * PCOMPLETE_LOCK_IRP_ROUTINE)(_In_ PVOID Context, _In_ PIRP Irp)
Definition: fsrtltypes.h:183
static RTL_GENERIC_COMPARE_RESULTS NTAPI LockCompare(PRTL_GENERIC_TABLE Table, PVOID PtrA, PVOID PtrB)
Definition: filelock.c:82
ULONG LowPart
Definition: typedefs.h:106
KIRQL * PKIRQL
Definition: env_spec_w32.h:592
PFILE_LOCK BelongsTo
Definition: filelock.c:39
Definition: typedefs.h:119
NTSTATUS NTAPI FsRtlFastUnlockAll(IN PFILE_LOCK FileLock, IN PFILE_OBJECT FileObject, IN PEPROCESS Process, IN PVOID Context OPTIONAL)
Definition: filelock.c:1025
Definition: range.c:39
struct _LOCK_SHARED_RANGE LOCK_SHARED_RANGE
NTSTATUS NTAPI FsRtlProcessFileLock(IN PFILE_LOCK FileLock, IN PIRP Irp, IN PVOID Context OPTIONAL)
Definition: filelock.c:1152
struct _LOCK_INFORMATION * PLOCK_INFORMATION
Definition: csq.h:222
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
__drv_aliasesMem FORCEINLINE PIO_STACK_LOCATION IoGetCurrentIrpStackLocation(_In_ PIRP Irp)
Definition: iofuncs.h:2793
ULONG Generation
Definition: filelock.c:41
BOOLEAN ExclusiveLock
Definition: fsrtltypes.h:190
NTSYSAPI BOOLEAN NTAPI RtlDeleteElementGenericTable(_In_ PRTL_GENERIC_TABLE Table, _In_ PVOID Buffer)
PFILE_OBJECT FileObject
Definition: iotypes.h:3169
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
struct LOOKASIDE_ALIGN _PAGED_LOOKASIDE_LIST PAGED_LOOKASIDE_LIST
_In_ PFCB _In_ LONGLONG FileOffset
Definition: cdprocs.h:159
#define InitializeListHead(ListHead)
Definition: env_spec_w32.h:944
#define STATUS_NO_MEMORY
Definition: ntstatus.h:260
ULONG KSPIN_LOCK
Definition: env_spec_w32.h:72
#define SL_EXCLUSIVE_LOCK
Definition: iotypes.h:1833
PVOID LockInformation
Definition: fsrtltypes.h:207
static OUT PIO_STATUS_BLOCK IoStatusBlock
Definition: pipe.c:75
#define NULL
Definition: types.h:112
enum _RTL_GENERIC_COMPARE_RESULTS RTL_GENERIC_COMPARE_RESULTS
#define KeReleaseSpinLock(sl, irql)
Definition: env_spec_w32.h:627
#define IRP_MN_LOCK
Definition: iotypes.h:4410
IN PLARGE_INTEGER IN PLARGE_INTEGER PEPROCESS ULONG BOOLEAN BOOLEAN ExclusiveLock
Definition: fatprocs.h:2709
#define IRP_MJ_LOCK_CONTROL
Definition: rdpdr.c:53
_In_opt_ PIRP _In_opt_ PVOID PeekContext
Definition: csq.h:159
IO_CSQ Csq
Definition: csqrtns.c:46
#define STATUS_FILE_LOCK_CONFLICT
Definition: ntstatus.h:320
_Must_inspect_result_ _In_ PLARGE_INTEGER _In_ PLARGE_INTEGER _In_ ULONG _In_ PFILE_OBJECT _In_ PVOID Process
Definition: fsrtlfuncs.h:219
VOID NTAPI FsRtlFreeFileLock(IN PFILE_LOCK FileLock)
Definition: filelock.c:1342
#define OUT
Definition: typedefs.h:40
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
#define FsRtlCompleteRequest(IRP, STATUS)
Definition: fsrtlfuncs.h:1711
__in UCHAR __in POWER_STATE __in_opt PVOID __in PIO_STATUS_BLOCK IoStatus
Definition: mxum.h:155
unsigned int ULONG
Definition: retypes.h:1
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:262
static VOID NTAPI LockReleaseQueueLock(PIO_CSQ Csq, KIRQL Irql)
Definition: filelock.c:197
#define RtlCopyMemory(Destination, Source, Length)
Definition: typedefs.h:263
LIST_ENTRY CsqList
Definition: filelock.c:38
#define STATUS_SUCCESS
Definition: shellext.h:65
#define DPRINT
Definition: sndvol32.h:71
_In_opt_ PCOMPLETE_LOCK_IRP_ROUTINE CompleteLockIrpRoutine
Definition: fsrtlfuncs.h:139
struct _NAMED_PIPE_CREATE_PARAMETERS * Parameters
Definition: iotypes.h:3128
static PVOID NTAPI LockAllocate(PRTL_GENERIC_TABLE Table, CLONG Bytes)
Definition: filelock.c:67
IoMarkIrpPending(Irp)
NTSYSAPI PVOID NTAPI RtlInsertElementGenericTable(_In_ PRTL_GENERIC_TABLE Table, _In_reads_bytes_(BufferSize) PVOID Buffer, _In_ CLONG BufferSize, _Out_opt_ PBOOLEAN NewElement)
#define ExFreePoolWithTag(_P, _T)
Definition: module.h:1099
union _COMBINED_LOCK_ELEMENT * PCOMBINED_LOCK_ELEMENT
#define IRP_MN_UNLOCK_SINGLE
Definition: iotypes.h:4411
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: filelock.c:782
base of all file and directory entries
Definition: entries.h:82
LARGE_INTEGER StartingByte
Definition: fsrtltypes.h:188
LONGLONG QuadPart
Definition: typedefs.h:114
IN PDCB IN PCCB IN VBO IN OUT PULONG OUT PDIRENT OUT PBCB OUT PVBO ByteOffset
Definition: fatprocs.h:725
PCOMBINED_LOCK_ELEMENT NTAPI FsRtlpRebuildSharedLockRange(PFILE_LOCK FileLock, PLOCK_INFORMATION LockInfo, PCOMBINED_LOCK_ELEMENT Conflict)
Definition: filelock.c:290
#define TAG_RANGE
Definition: tag.h:47
#define NT_ASSERT
Definition: rtlfuncs.h:3310
#define SL_FAIL_IMMEDIATELY
Definition: iotypes.h:1832
PULONG MinorVersion OPTIONAL
Definition: CrossNt.h:68