ReactOS  0.4.15-dev-2993-g14fbe80
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 #define TAG_TABLE 'BATL'
55 #define TAG_RANGE 'ARSF'
56 #define TAG_FLOCK 'KCLF'
57 
58 /* PRIVATE FUNCTIONS *********************************************************/
59 
60 VOID
61 NTAPI
64  IN PIRP Irp,
66  OUT PNTSTATUS NewStatus,
68 
69 /* Generic table methods */
70 
72 {
73  PVOID Result;
75  DPRINT("LockAllocate(%lu) => %p\n", Bytes, Result);
76  return Result;
77 }
78 
80 {
81  DPRINT("LockFree(%p)\n", Buffer);
83 }
84 
87 {
88  PCOMBINED_LOCK_ELEMENT A = PtrA, B = PtrB;
90 #if 0
91  DPRINT("Starting to compare element %x to element %x\n", PtrA, PtrB);
92 #endif
93  /* Match if we overlap */
94  if (((A->Exclusive.FileLock.StartingByte.QuadPart <
95  B->Exclusive.FileLock.EndingByte.QuadPart) &&
96  (A->Exclusive.FileLock.StartingByte.QuadPart >=
97  B->Exclusive.FileLock.StartingByte.QuadPart)) ||
98  ((B->Exclusive.FileLock.StartingByte.QuadPart <
99  A->Exclusive.FileLock.EndingByte.QuadPart) &&
100  (B->Exclusive.FileLock.StartingByte.QuadPart >=
101  A->Exclusive.FileLock.StartingByte.QuadPart)))
102  return GenericEqual;
103  /* Otherwise, key on the starting byte */
104  Result =
105  (A->Exclusive.FileLock.StartingByte.QuadPart <
106  B->Exclusive.FileLock.StartingByte.QuadPart) ? GenericLessThan :
107  (A->Exclusive.FileLock.StartingByte.QuadPart >
108  B->Exclusive.FileLock.StartingByte.QuadPart) ? GenericGreaterThan :
109  GenericEqual;
110 #if 0
111  DPRINT("Compare(%x:%x) %x-%x to %x-%x => %d\n",
112  A,B,
113  A->Exclusive.FileLock.StartingByte.LowPart,
114  A->Exclusive.FileLock.EndingByte.LowPart,
115  B->Exclusive.FileLock.StartingByte.LowPart,
116  B->Exclusive.FileLock.EndingByte.LowPart,
117  Result);
118 #endif
119  return Result;
120 }
121 
122 /* CSQ methods */
123 
126  PIRP Irp,
128 {
130  InsertTailList(&LockInfo->CsqList, &Irp->Tail.Overlay.ListEntry);
131  return STATUS_SUCCESS;
132 }
133 
135 {
136  RemoveEntryList(&Irp->Tail.Overlay.ListEntry);
137 }
138 
140 {
141  // Context will be a COMBINED_LOCK_ELEMENT. We're looking for a
142  // lock that can be acquired, now that the lock matching PeekContext
143  // has been removed.
144  COMBINED_LOCK_ELEMENT LockElement;
145  PCOMBINED_LOCK_ELEMENT WhereUnlock = PeekContext;
147  PLIST_ENTRY Following;
148  DPRINT("PeekNextIrp(IRP %p, Context %p)\n", Irp, PeekContext);
149  if (!Irp)
150  {
151  Following = LockInfo->CsqList.Flink;
152  }
153  else
154  Following = Irp->Tail.Overlay.ListEntry.Flink;
155 
156  DPRINT("ListEntry %p Head %p\n", Following, &LockInfo->CsqList);
157  for (;
158  Following != &LockInfo->CsqList;
159  Following = Following->Flink)
160  {
161  PIO_STACK_LOCATION IoStack;
162  BOOLEAN Matching;
163  Irp = CONTAINING_RECORD(Following, IRP, Tail.Overlay.ListEntry);
164  DPRINT("Irp %p\n", Irp);
166  LockElement.Exclusive.FileLock.StartingByte =
167  IoStack->Parameters.LockControl.ByteOffset;
168  LockElement.Exclusive.FileLock.EndingByte.QuadPart =
170  IoStack->Parameters.LockControl.Length->QuadPart;
171  /* If a context was specified, it's a range to check to unlock */
172  if (WhereUnlock)
173  {
174  Matching = LockCompare
175  (&LockInfo->RangeTable, &LockElement, WhereUnlock) != GenericEqual;
176  }
177  /* Else get any completable IRP */
178  else
179  {
180  Matching = FALSE;
181  }
182  if (!Matching)
183  {
184  // This IRP is fine...
185  DPRINT("Returning the IRP %p\n", Irp);
186  return Irp;
187  }
188  }
189  DPRINT("Return NULL\n");
190  return NULL;
191 }
192 
193 static VOID NTAPI
195 {
197  KeAcquireSpinLock(&LockInfo->CsqLock, Irql);
198 }
199 
200 static VOID NTAPI
202 {
204  KeReleaseSpinLock(&LockInfo->CsqLock, Irql);
205 }
206 
207 static VOID NTAPI
209 {
212  DPRINT("Complete cancelled IRP %p Status %x\n", Irp, STATUS_CANCELLED);
214  (LockInfo->BelongsTo->CompleteLockIrpRoutine,
215  NULL,
216  Irp,
218  &Status,
219  NULL);
220 }
221 
222 VOID
223 NTAPI
225  IN PVOID Context,
226  IN PIRP Irp,
228  OUT PNTSTATUS NewStatus,
230 {
231  /* Check if we have a complete routine */
232  Irp->IoStatus.Information = 0;
233  if (CompleteRoutine)
234  {
235  /* Check if we have a file object */
236  if (FileObject) FileObject->LastLock = NULL;
237 
238  /* Set the I/O Status and do completion */
239  Irp->IoStatus.Status = Status;
240  DPRINT("Calling completion routine %p Status %x\n", Irp, Status);
241  *NewStatus = CompleteRoutine(Context, Irp);
242  }
243  else
244  {
245  /* Otherwise do a normal I/O complete request */
246  DPRINT("Completing IRP %p Status %x\n", Irp, Status);
248  *NewStatus = Status;
249  }
250 }
251 
252 /* PUBLIC FUNCTIONS **********************************************************/
253 
254 /*
255  * @implemented
256  */
258 NTAPI
261 {
263  if (!FileLock->LockInformation) return NULL;
264  Entry = RtlEnumerateGenericTable(FileLock->LockInformation, Restart);
265  if (!Entry) return NULL;
266  else return &Entry->Exclusive.FileLock;
267 }
268 
269 VOID
270 NTAPI
273  PCOMBINED_LOCK_ELEMENT Conflict)
274 {
275  if (ToExpand->Exclusive.FileLock.StartingByte.QuadPart >
277  {
278  ToExpand->Exclusive.FileLock.StartingByte =
279  Conflict->Exclusive.FileLock.StartingByte;
280  }
281  if (ToExpand->Exclusive.FileLock.EndingByte.QuadPart <
283  {
284  ToExpand->Exclusive.FileLock.EndingByte =
285  Conflict->Exclusive.FileLock.EndingByte;
286  }
287 }
288 
289 /* This function expands the conflicting range Conflict by removing and reinserting it,
290  then adds a shared range of the same size */
292 NTAPI
294 (PFILE_LOCK FileLock,
295  PLOCK_INFORMATION LockInfo,
296  PCOMBINED_LOCK_ELEMENT Conflict)
297 {
298  /* Starting at Conflict->StartingByte and going to Conflict->EndingByte
299  * capture and expand a shared range from the shared range list.
300  * Finish when we've incorporated all overlapping shared regions.
301  */
302  BOOLEAN InsertedNew = FALSE, RemovedOld;
303  COMBINED_LOCK_ELEMENT NewElement = *Conflict;
306  (FileLock->LockInformation, &NewElement)))
307  {
308  FsRtlpExpandLockElement(&NewElement, Entry);
309  RemovedOld = RtlDeleteElementGenericTable
310  (&LockInfo->RangeTable,
311  Entry);
312  ASSERT(RemovedOld);
313  }
315  (&LockInfo->RangeTable,
316  &NewElement,
317  sizeof(NewElement),
318  &InsertedNew);
319  ASSERT(InsertedNew);
320  return Conflict;
321 }
322 
323 /*
324  * @implemented
325  */
326 BOOLEAN
327 NTAPI
333  IN ULONG Key,
340 {
342  COMBINED_LOCK_ELEMENT ToInsert;
343  PCOMBINED_LOCK_ELEMENT Conflict;
344  PLOCK_INFORMATION LockInfo;
345  PLOCK_SHARED_RANGE NewSharedRange;
346  BOOLEAN InsertedNew;
347  ULARGE_INTEGER UnsignedStart;
348  ULARGE_INTEGER UnsignedEnd;
349 
350  DPRINT("FsRtlPrivateLock(%wZ, Offset %08x%08x (%d), Length %08x%08x (%d), Key %x, FailImmediately %u, Exclusive %u)\n",
351  &FileObject->FileName,
352  FileOffset->HighPart,
353  FileOffset->LowPart,
354  (int)FileOffset->QuadPart,
355  Length->HighPart,
356  Length->LowPart,
357  (int)Length->QuadPart,
358  Key,
360  ExclusiveLock);
361 
362  UnsignedStart.QuadPart = FileOffset->QuadPart;
363  UnsignedEnd.QuadPart = FileOffset->QuadPart + Length->QuadPart;
364 
365  if (UnsignedEnd.QuadPart < UnsignedStart.QuadPart)
366  {
367  DPRINT("File offset out of range\n");
369  if (Irp)
370  {
371  DPRINT("Complete lock %p Status %x\n", Irp, IoStatus->Status);
373  (FileLock->CompleteLockIrpRoutine,
374  Context,
375  Irp,
376  IoStatus->Status,
377  &Status,
378  FileObject);
379  }
380  return FALSE;
381  }
382 
383  /* Initialize the lock, if necessary */
384  if (!FileLock->LockInformation)
385  {
387  if (!LockInfo)
388  {
389  IoStatus->Status = STATUS_NO_MEMORY;
390  return FALSE;
391  }
392  FileLock->LockInformation = LockInfo;
393 
394  LockInfo->BelongsTo = FileLock;
395  InitializeListHead(&LockInfo->SharedLocks);
396 
398  (&LockInfo->RangeTable,
399  LockCompare,
400  LockAllocate,
401  LockFree,
402  NULL);
403 
404  KeInitializeSpinLock(&LockInfo->CsqLock);
405  InitializeListHead(&LockInfo->CsqList);
406 
408  (&LockInfo->Csq,
415  }
416 
417  LockInfo = FileLock->LockInformation;
420  ToInsert.Exclusive.FileLock.EndingByte.QuadPart = FileOffset->QuadPart + Length->QuadPart;
421  ToInsert.Exclusive.FileLock.ProcessId = Process;
422  ToInsert.Exclusive.FileLock.Key = Key;
424 
426  (FileLock->LockInformation,
427  &ToInsert,
428  sizeof(ToInsert),
429  &InsertedNew);
430 
431  if (Conflict && !InsertedNew)
432  {
434  {
435  DPRINT("Conflict %08x%08x:%08x%08x Exc %u (Want Exc %u)\n",
440  Conflict->Exclusive.FileLock.ExclusiveLock,
441  ExclusiveLock);
442  if (FailImmediately)
443  {
444  DPRINT("STATUS_FILE_LOCK_CONFLICT\n");
446  if (Irp)
447  {
448  DPRINT("STATUS_FILE_LOCK_CONFLICT: Complete\n");
450  (FileLock->CompleteLockIrpRoutine,
451  Context,
452  Irp,
453  IoStatus->Status,
454  &Status,
455  FileObject);
456  }
457  return FALSE;
458  }
459  else
460  {
461  IoStatus->Status = STATUS_PENDING;
462  if (Irp)
463  {
464  Irp->IoStatus.Information = LockInfo->Generation;
467  (&LockInfo->Csq,
468  Irp,
469  NULL,
470  NULL);
471  }
472  }
473  return FALSE;
474  }
475  else
476  {
477  ULONG i;
478  /* We know of at least one lock in range that's shared. We need to
479  * find out if any more exist and any are exclusive. */
480  for (i = 0; i < RtlNumberGenericTableElements(&LockInfo->RangeTable); i++)
481  {
482  Conflict = RtlGetElementGenericTable(&LockInfo->RangeTable, i);
483 
484  /* The first argument will be inserted as a shared range */
485  if (Conflict && (LockCompare(&LockInfo->RangeTable, Conflict, &ToInsert) == GenericEqual))
486  {
487  if (Conflict->Exclusive.FileLock.ExclusiveLock)
488  {
489  /* Found an exclusive match */
490  if (FailImmediately)
491  {
493  DPRINT("STATUS_FILE_LOCK_CONFLICT\n");
494  if (Irp)
495  {
496  DPRINT("STATUS_FILE_LOCK_CONFLICT: Complete\n");
498  (FileLock->CompleteLockIrpRoutine,
499  Context,
500  Irp,
501  IoStatus->Status,
502  &Status,
503  FileObject);
504  }
505  }
506  else
507  {
508  IoStatus->Status = STATUS_PENDING;
509  if (Irp)
510  {
513  (&LockInfo->Csq,
514  Irp,
515  NULL,
516  NULL);
517  }
518  }
519  return FALSE;
520  }
521  }
522  }
523 
524  DPRINT("Overlapping shared lock %wZ %08x%08x %08x%08x\n",
525  &FileObject->FileName,
530  Conflict = FsRtlpRebuildSharedLockRange(FileLock,
531  LockInfo,
532  &ToInsert);
533  if (!Conflict)
534  {
535  IoStatus->Status = STATUS_NO_MEMORY;
536  if (Irp)
537  {
539  (FileLock->CompleteLockIrpRoutine,
540  Context,
541  Irp,
542  IoStatus->Status,
543  &Status,
544  FileObject);
545  }
546  }
547 
548  /* We got here because there were only overlapping shared locks */
549  /* A shared lock is both a range *and* a list entry. Insert the
550  entry here. */
551 
552  DPRINT("Adding shared lock %wZ\n", &FileObject->FileName);
553  NewSharedRange =
554  ExAllocatePoolWithTag(NonPagedPool, sizeof(*NewSharedRange), TAG_RANGE);
555  if (!NewSharedRange)
556  {
557  IoStatus->Status = STATUS_NO_MEMORY;
558  if (Irp)
559  {
561  (FileLock->CompleteLockIrpRoutine,
562  Context,
563  Irp,
564  IoStatus->Status,
565  &Status,
566  FileObject);
567  }
568  return FALSE;
569  }
570  DPRINT("Adding shared lock %wZ\n", &FileObject->FileName);
571  NewSharedRange->Start = *FileOffset;
572  NewSharedRange->End.QuadPart = FileOffset->QuadPart + Length->QuadPart;
573  NewSharedRange->Key = Key;
574  NewSharedRange->ProcessId = ToInsert.Exclusive.FileLock.ProcessId;
575  InsertTailList(&LockInfo->SharedLocks, &NewSharedRange->Entry);
576 
577  DPRINT("Acquired shared lock %wZ %08x%08x %08x%08x\n",
578  &FileObject->FileName,
583  IoStatus->Status = STATUS_SUCCESS;
584  if (Irp)
585  {
587  (FileLock->CompleteLockIrpRoutine,
588  Context,
589  Irp,
590  IoStatus->Status,
591  &Status,
592  FileObject);
593  }
594  return TRUE;
595  }
596  }
597  else if (!Conflict)
598  {
599  /* Conflict here is (or would be) the newly inserted element, but we ran
600  * out of space probably. */
601  IoStatus->Status = STATUS_NO_MEMORY;
602  if (Irp)
603  {
605  (FileLock->CompleteLockIrpRoutine,
606  Context,
607  Irp,
608  IoStatus->Status,
609  &Status,
610  FileObject);
611  }
612  return FALSE;
613  }
614  else
615  {
616  DPRINT("Inserted new lock %wZ %08x%08x %08x%08x exclusive %u\n",
617  &FileObject->FileName,
622  Conflict->Exclusive.FileLock.ExclusiveLock);
623  if (!ExclusiveLock)
624  {
625  NewSharedRange =
626  ExAllocatePoolWithTag(NonPagedPool, sizeof(*NewSharedRange), TAG_RANGE);
627  if (!NewSharedRange)
628  {
629  IoStatus->Status = STATUS_NO_MEMORY;
630  if (Irp)
631  {
633  (FileLock->CompleteLockIrpRoutine,
634  Context,
635  Irp,
636  IoStatus->Status,
637  &Status,
638  FileObject);
639  }
640  return FALSE;
641  }
642  DPRINT("Adding shared lock %wZ\n", &FileObject->FileName);
643  NewSharedRange->Start = *FileOffset;
644  NewSharedRange->End.QuadPart = FileOffset->QuadPart + Length->QuadPart;
645  NewSharedRange->Key = Key;
646  NewSharedRange->ProcessId = Process;
647  InsertTailList(&LockInfo->SharedLocks, &NewSharedRange->Entry);
648  }
649 
650  /* Assume all is cool, and lock is set */
651  IoStatus->Status = STATUS_SUCCESS;
652 
653  if (Irp)
654  {
655  /* Complete the request */
656  FsRtlCompleteLockIrpReal(FileLock->CompleteLockIrpRoutine,
657  Context,
658  Irp,
659  IoStatus->Status,
660  &Status,
661  FileObject);
662 
663  /* Update the status */
664  IoStatus->Status = Status;
665  }
666  }
667 
668  return TRUE;
669 }
670 
671 /*
672  * @implemented
673  */
674 BOOLEAN
675 NTAPI
677  IN PIRP Irp)
678 {
679  BOOLEAN Result;
681  COMBINED_LOCK_ELEMENT ToFind;
683  DPRINT("CheckLockForReadAccess(%wZ, Offset %08x%08x, Length %x)\n",
684  &IoStack->FileObject->FileName,
685  IoStack->Parameters.Read.ByteOffset.HighPart,
686  IoStack->Parameters.Read.ByteOffset.LowPart,
687  IoStack->Parameters.Read.Length);
688  if (!FileLock->LockInformation) {
689  DPRINT("CheckLockForReadAccess(%wZ) => TRUE\n", &IoStack->FileObject->FileName);
690  return TRUE;
691  }
692  ToFind.Exclusive.FileLock.StartingByte = IoStack->Parameters.Read.ByteOffset;
695  IoStack->Parameters.Read.Length;
697  (FileLock->LockInformation,
698  &ToFind);
699  if (!Found) {
700  DPRINT("CheckLockForReadAccess(%wZ) => TRUE\n", &IoStack->FileObject->FileName);
701  return TRUE;
702  }
703  Result = !Found->Exclusive.FileLock.ExclusiveLock ||
704  IoStack->Parameters.Read.Key == Found->Exclusive.FileLock.Key;
705  DPRINT("CheckLockForReadAccess(%wZ) => %s\n", &IoStack->FileObject->FileName, Result ? "TRUE" : "FALSE");
706  return Result;
707 }
708 
709 /*
710  * @implemented
711  */
712 BOOLEAN
713 NTAPI
715  IN PIRP Irp)
716 {
717  BOOLEAN Result;
719  COMBINED_LOCK_ELEMENT ToFind;
721  PEPROCESS Process = Irp->Tail.Overlay.Thread->ThreadsProcess;
722  DPRINT("CheckLockForWriteAccess(%wZ, Offset %08x%08x, Length %x)\n",
723  &IoStack->FileObject->FileName,
724  IoStack->Parameters.Write.ByteOffset.HighPart,
725  IoStack->Parameters.Write.ByteOffset.LowPart,
726  IoStack->Parameters.Write.Length);
727  if (!FileLock->LockInformation) {
728  DPRINT("CheckLockForWriteAccess(%wZ) => TRUE\n", &IoStack->FileObject->FileName);
729  return TRUE;
730  }
731  ToFind.Exclusive.FileLock.StartingByte = IoStack->Parameters.Write.ByteOffset;
734  IoStack->Parameters.Write.Length;
736  (FileLock->LockInformation,
737  &ToFind);
738  if (!Found) {
739  DPRINT("CheckLockForWriteAccess(%wZ) => TRUE\n", &IoStack->FileObject->FileName);
740  return TRUE;
741  }
742  Result = Process == Found->Exclusive.FileLock.ProcessId;
743  DPRINT("CheckLockForWriteAccess(%wZ) => %s\n", &IoStack->FileObject->FileName, Result ? "TRUE" : "FALSE");
744  return Result;
745 }
746 
747 /*
748  * @implemented
749  */
750 BOOLEAN
751 NTAPI
755  IN ULONG Key,
757  IN PVOID Process)
758 {
759  PEPROCESS EProcess = Process;
760  COMBINED_LOCK_ELEMENT ToFind;
762  DPRINT("FsRtlFastCheckLockForRead(%wZ, Offset %08x%08x, Length %08x%08x, Key %x)\n",
763  &FileObject->FileName,
764  FileOffset->HighPart,
765  FileOffset->LowPart,
766  Length->HighPart,
767  Length->LowPart,
768  Key);
771  FileOffset->QuadPart + Length->QuadPart;
772  if (!FileLock->LockInformation) return TRUE;
774  (FileLock->LockInformation,
775  &ToFind);
776  if (!Found || !Found->Exclusive.FileLock.ExclusiveLock) return TRUE;
777  return Found->Exclusive.FileLock.Key == Key &&
778  Found->Exclusive.FileLock.ProcessId == EProcess;
779 }
780 
781 /*
782  * @implemented
783  */
784 BOOLEAN
785 NTAPI
789  IN ULONG Key,
791  IN PVOID Process)
792 {
793  BOOLEAN Result;
794  PEPROCESS EProcess = Process;
795  COMBINED_LOCK_ELEMENT ToFind;
797  DPRINT("FsRtlFastCheckLockForWrite(%wZ, Offset %08x%08x, Length %08x%08x, Key %x)\n",
798  &FileObject->FileName,
799  FileOffset->HighPart,
800  FileOffset->LowPart,
801  Length->HighPart,
802  Length->LowPart,
803  Key);
806  FileOffset->QuadPart + Length->QuadPart;
807  if (!FileLock->LockInformation) {
808  DPRINT("CheckForWrite(%wZ) => TRUE\n", &FileObject->FileName);
809  return TRUE;
810  }
812  (FileLock->LockInformation,
813  &ToFind);
814  if (!Found) {
815  DPRINT("CheckForWrite(%wZ) => TRUE\n", &FileObject->FileName);
816  return TRUE;
817  }
818  Result = Found->Exclusive.FileLock.Key == Key &&
819  Found->Exclusive.FileLock.ProcessId == EProcess;
820  DPRINT("CheckForWrite(%wZ) => %s\n", &FileObject->FileName, Result ? "TRUE" : "FALSE");
821  return Result;
822 }
823 
824 /*
825  * @implemented
826  */
827 NTSTATUS
828 NTAPI
834  IN ULONG Key,
837 {
838  BOOLEAN FoundShared = FALSE;
839  PLIST_ENTRY SharedEntry;
840  PLOCK_SHARED_RANGE SharedRange = NULL;
843  PIRP NextMatchingLockIrp;
844  PLOCK_INFORMATION InternalInfo = FileLock->LockInformation;
845  DPRINT("FsRtlFastUnlockSingle(%wZ, Offset %08x%08x (%d), Length %08x%08x (%d), Key %x)\n",
846  &FileObject->FileName,
847  FileOffset->HighPart,
848  FileOffset->LowPart,
849  (int)FileOffset->QuadPart,
850  Length->HighPart,
851  Length->LowPart,
852  (int)Length->QuadPart,
853  Key);
854  // The region to unlock must correspond exactly to a previously locked region
855  // -- msdn
856  // But Windows 2003 doesn't assert on it and simply ignores that parameter
857  // ASSERT(AlreadySynchronized);
860  FileOffset->QuadPart + Length->QuadPart;
861  if (!InternalInfo) {
862  DPRINT("File not previously locked (ever)\n");
864  }
865  Entry = RtlLookupElementGenericTable(&InternalInfo->RangeTable, &Find);
866  if (!Entry) {
867  DPRINT("Range not locked %wZ\n", &FileObject->FileName);
869  }
870 
871  DPRINT("Found lock entry: Exclusive %u %08x%08x:%08x%08x %wZ\n",
872  Entry->Exclusive.FileLock.ExclusiveLock,
873  Entry->Exclusive.FileLock.StartingByte.HighPart,
874  Entry->Exclusive.FileLock.StartingByte.LowPart,
875  Entry->Exclusive.FileLock.EndingByte.HighPart,
876  Entry->Exclusive.FileLock.EndingByte.LowPart,
877  &FileObject->FileName);
878 
879  if (Entry->Exclusive.FileLock.ExclusiveLock)
880  {
881  if (Entry->Exclusive.FileLock.Key != Key ||
882  Entry->Exclusive.FileLock.ProcessId != Process ||
883  Entry->Exclusive.FileLock.StartingByte.QuadPart != FileOffset->QuadPart ||
884  Entry->Exclusive.FileLock.EndingByte.QuadPart !=
885  FileOffset->QuadPart + Length->QuadPart)
886  {
887  DPRINT("Range not locked %wZ\n", &FileObject->FileName);
889  }
890  RtlCopyMemory(&Find, Entry, sizeof(Find));
891  // Remove the old exclusive lock region
893  }
894  else
895  {
896  DPRINT("Shared lock %wZ Start %08x%08x End %08x%08x\n",
897  &FileObject->FileName,
898  Entry->Exclusive.FileLock.StartingByte.HighPart,
899  Entry->Exclusive.FileLock.StartingByte.LowPart,
900  Entry->Exclusive.FileLock.EndingByte.HighPart,
901  Entry->Exclusive.FileLock.EndingByte.LowPart);
902  for (SharedEntry = InternalInfo->SharedLocks.Flink;
903  SharedEntry != &InternalInfo->SharedLocks;
904  SharedEntry = SharedEntry->Flink)
905  {
906  SharedRange = CONTAINING_RECORD(SharedEntry, LOCK_SHARED_RANGE, Entry);
907  if (SharedRange->Start.QuadPart == FileOffset->QuadPart &&
908  SharedRange->End.QuadPart == FileOffset->QuadPart + Length->QuadPart &&
909  SharedRange->Key == Key &&
910  SharedRange->ProcessId == Process)
911  {
912  FoundShared = TRUE;
913  DPRINT("Found shared element to delete %wZ Start %08x%08x End %08x%08x Key %x\n",
914  &FileObject->FileName,
915  SharedRange->Start.HighPart,
916  SharedRange->Start.LowPart,
917  SharedRange->End.HighPart,
918  SharedRange->End.LowPart,
919  SharedRange->Key);
920  break;
921  }
922  }
923  if (FoundShared)
924  {
925  /* Remove the found range from the shared range lists */
926  RemoveEntryList(&SharedRange->Entry);
927  ExFreePoolWithTag(SharedRange, TAG_RANGE);
928  /* We need to rebuild the list of shared ranges. */
929  DPRINT("Removing the lock entry %wZ (%08x%08x:%08x%08x)\n",
930  &FileObject->FileName,
931  Entry->Exclusive.FileLock.StartingByte.HighPart,
932  Entry->Exclusive.FileLock.StartingByte.LowPart,
933  Entry->Exclusive.FileLock.EndingByte.HighPart,
934  Entry->Exclusive.FileLock.EndingByte.LowPart);
935 
936  /* Remember what was in there and remove it from the table */
937  Find = *Entry;
938  RtlDeleteElementGenericTable(&InternalInfo->RangeTable, &Find);
939  /* Put shared locks back in place */
940  for (SharedEntry = InternalInfo->SharedLocks.Flink;
941  SharedEntry != &InternalInfo->SharedLocks;
942  SharedEntry = SharedEntry->Flink)
943  {
944  COMBINED_LOCK_ELEMENT LockElement;
945  SharedRange = CONTAINING_RECORD(SharedEntry, LOCK_SHARED_RANGE, Entry);
946  LockElement.Exclusive.FileLock.FileObject = FileObject;
947  LockElement.Exclusive.FileLock.StartingByte = SharedRange->Start;
948  LockElement.Exclusive.FileLock.EndingByte = SharedRange->End;
949  LockElement.Exclusive.FileLock.ProcessId = SharedRange->ProcessId;
950  LockElement.Exclusive.FileLock.Key = SharedRange->Key;
951  LockElement.Exclusive.FileLock.ExclusiveLock = FALSE;
952 
953  if (LockCompare(&InternalInfo->RangeTable, &Find, &LockElement) != GenericEqual)
954  {
955  DPRINT("Skipping range %08x%08x:%08x%08x\n",
959  LockElement.Exclusive.FileLock.EndingByte.LowPart);
960  continue;
961  }
962  DPRINT("Re-creating range %08x%08x:%08x%08x\n",
966  LockElement.Exclusive.FileLock.EndingByte.LowPart);
967  FsRtlpRebuildSharedLockRange(FileLock, InternalInfo, &LockElement);
968  }
969  }
970  else
971  {
973  }
974  }
975 
976 #ifndef NDEBUG
977  DPRINT("Lock still has:\n");
978  for (SharedEntry = InternalInfo->SharedLocks.Flink;
979  SharedEntry != &InternalInfo->SharedLocks;
980  SharedEntry = SharedEntry->Flink)
981  {
982  SharedRange = CONTAINING_RECORD(SharedEntry, LOCK_SHARED_RANGE, Entry);
983  DPRINT("Shared element %wZ Offset %08x%08x Length %08x%08x Key %x\n",
984  &FileObject->FileName,
985  SharedRange->Start.HighPart,
986  SharedRange->Start.LowPart,
987  SharedRange->End.HighPart,
988  SharedRange->End.LowPart,
989  SharedRange->Key);
990  }
991 #endif
992 
993  // this is definitely the thing we want
994  InternalInfo->Generation++;
995  while ((NextMatchingLockIrp = IoCsqRemoveNextIrp(&InternalInfo->Csq, &Find)))
996  {
998  if (NextMatchingLockIrp->IoStatus.Information == InternalInfo->Generation)
999  {
1000  // We've already looked at this one, meaning that we looped.
1001  // Put it back and exit.
1003  (&InternalInfo->Csq,
1004  NextMatchingLockIrp,
1005  NULL,
1006  NULL);
1007  break;
1008  }
1009  // Got a new lock irp... try to do the new lock operation
1010  // Note that we pick an operation that would succeed at the time
1011  // we looked, but can't guarantee that it won't just be re-queued
1012  // because somebody else snatched part of the range in a new thread.
1013  DPRINT("Locking another IRP %p for %p %wZ\n",
1014  NextMatchingLockIrp, FileLock, &FileObject->FileName);
1015  Status = FsRtlProcessFileLock(InternalInfo->BelongsTo, NextMatchingLockIrp, NULL);
1016  if (!NT_SUCCESS(Status))
1017  return Status;
1018  }
1019 
1020  DPRINT("Success %wZ\n", &FileObject->FileName);
1021  return STATUS_SUCCESS;
1022 }
1023 
1024 /*
1025  * @implemented
1026  */
1027 NTSTATUS
1028 NTAPI
1033 {
1034  PLIST_ENTRY ListEntry;
1036  PLOCK_INFORMATION InternalInfo = FileLock->LockInformation;
1037  DPRINT("FsRtlFastUnlockAll(%wZ)\n", &FileObject->FileName);
1038  // XXX Synchronize somehow
1039  if (!FileLock->LockInformation) {
1040  DPRINT("Not locked %wZ\n", &FileObject->FileName);
1041  return STATUS_RANGE_NOT_LOCKED; // no locks
1042  }
1043  for (ListEntry = InternalInfo->SharedLocks.Flink;
1044  ListEntry != &InternalInfo->SharedLocks;)
1045  {
1048  Length.QuadPart = Range->End.QuadPart - Range->Start.QuadPart;
1049  ListEntry = ListEntry->Flink;
1050  if (Range->ProcessId != Process)
1051  continue;
1053  (FileLock,
1054  FileObject,
1055  &Range->Start,
1056  &Length,
1057  Range->ProcessId,
1058  Range->Key,
1059  Context,
1060  TRUE);
1061  }
1062  for (Entry = RtlEnumerateGenericTable(&InternalInfo->RangeTable, TRUE);
1063  Entry;
1064  Entry = RtlEnumerateGenericTable(&InternalInfo->RangeTable, FALSE))
1065  {
1067  // We'll take the first one to be the list head, and free the others first...
1068  Length.QuadPart =
1069  Entry->Exclusive.FileLock.EndingByte.QuadPart -
1070  Entry->Exclusive.FileLock.StartingByte.QuadPart;
1072  (FileLock,
1073  Entry->Exclusive.FileLock.FileObject,
1074  &Entry->Exclusive.FileLock.StartingByte,
1075  &Length,
1076  Entry->Exclusive.FileLock.ProcessId,
1077  Entry->Exclusive.FileLock.Key,
1078  Context,
1079  TRUE);
1080  }
1081  DPRINT("Done %wZ\n", &FileObject->FileName);
1082  return STATUS_SUCCESS;
1083 }
1084 
1085 /*
1086  * @implemented
1087  */
1088 NTSTATUS
1089 NTAPI
1093  IN ULONG Key,
1095 {
1096  PLIST_ENTRY ListEntry;
1098  PLOCK_INFORMATION InternalInfo = FileLock->LockInformation;
1099 
1100  DPRINT("FsRtlFastUnlockAllByKey(%wZ,Key %x)\n", &FileObject->FileName, Key);
1101 
1102  // XXX Synchronize somehow
1103  if (!FileLock->LockInformation) return STATUS_RANGE_NOT_LOCKED; // no locks
1104  for (ListEntry = InternalInfo->SharedLocks.Flink;
1105  ListEntry != &InternalInfo->SharedLocks;)
1106  {
1109  Length.QuadPart = Range->End.QuadPart - Range->Start.QuadPart;
1110  ListEntry = ListEntry->Flink;
1111  if (Range->ProcessId != Process ||
1112  Range->Key != Key)
1113  continue;
1115  (FileLock,
1116  FileObject,
1117  &Range->Start,
1118  &Length,
1119  Range->ProcessId,
1120  Range->Key,
1121  Context,
1122  TRUE);
1123  }
1124  for (Entry = RtlEnumerateGenericTable(&InternalInfo->RangeTable, TRUE);
1125  Entry;
1126  Entry = RtlEnumerateGenericTable(&InternalInfo->RangeTable, FALSE))
1127  {
1129  // We'll take the first one to be the list head, and free the others first...
1130  Length.QuadPart =
1131  Entry->Exclusive.FileLock.EndingByte.QuadPart -
1132  Entry->Exclusive.FileLock.StartingByte.QuadPart;
1133  if (Entry->Exclusive.FileLock.Key == Key &&
1134  Entry->Exclusive.FileLock.ProcessId == Process)
1135  {
1137  (FileLock,
1138  Entry->Exclusive.FileLock.FileObject,
1139  &Entry->Exclusive.FileLock.StartingByte,
1140  &Length,
1141  Entry->Exclusive.FileLock.ProcessId,
1142  Entry->Exclusive.FileLock.Key,
1143  Context,
1144  TRUE);
1145  }
1146  }
1147 
1148  return STATUS_SUCCESS;
1149 }
1150 
1151 /*
1152  * @implemented
1153  */
1154 NTSTATUS
1155 NTAPI
1157  IN PIRP Irp,
1159 {
1160  PIO_STACK_LOCATION IoStackLocation;
1161  NTSTATUS Status;
1163 
1164  /* Get the I/O Stack location */
1165  IoStackLocation = IoGetCurrentIrpStackLocation(Irp);
1166  ASSERT(IoStackLocation->MajorFunction == IRP_MJ_LOCK_CONTROL);
1167 
1168  /* Clear the I/O status block and check what function this is */
1170 
1171  DPRINT("FsRtlProcessFileLock(%wZ, MinorFunction %x)\n",
1172  &IoStackLocation->FileObject->FileName,
1173  IoStackLocation->MinorFunction);
1174 
1175  switch(IoStackLocation->MinorFunction)
1176  {
1177  /* A lock */
1178  case IRP_MN_LOCK:
1179  {
1180  /* Call the private lock routine */
1181  BOOLEAN Result = FsRtlPrivateLock(FileLock,
1182  IoStackLocation->FileObject,
1183  &IoStackLocation->Parameters.LockControl.ByteOffset,
1184  IoStackLocation->Parameters.LockControl.Length,
1186  IoStackLocation->Parameters.LockControl.Key,
1187  IoStackLocation->Flags & SL_FAIL_IMMEDIATELY,
1188  IoStackLocation->Flags & SL_EXCLUSIVE_LOCK,
1189  &IoStatusBlock,
1190  Irp,
1191  Context,
1192  FALSE);
1193  /* FsRtlPrivateLock has _Must_inspect_result_. Just check this is consistent on debug builds */
1195  (void)Result;
1196  return IoStatusBlock.Status;
1197  }
1198  /* A single unlock */
1199  case IRP_MN_UNLOCK_SINGLE:
1200 
1201  /* Call fast unlock */
1203  FsRtlFastUnlockSingle(FileLock,
1204  IoStackLocation->FileObject,
1205  &IoStackLocation->Parameters.LockControl.
1206  ByteOffset,
1207  IoStackLocation->Parameters.LockControl.
1208  Length,
1210  IoStackLocation->Parameters.LockControl.
1211  Key,
1212  Context,
1213  FALSE);
1214  break;
1215 
1216  /* Total unlock */
1217  case IRP_MN_UNLOCK_ALL:
1218 
1219  /* Do a fast unlock */
1221  IoStackLocation->
1222  FileObject,
1224  Context);
1225  break;
1226 
1227  /* Unlock by key */
1229 
1230  /* Do it */
1232  FsRtlFastUnlockAllByKey(FileLock,
1233  IoStackLocation->FileObject,
1235  IoStackLocation->Parameters.
1236  LockControl.Key,
1237  Context);
1238  break;
1239 
1240  /* Invalid request */
1241  default:
1242 
1243  /* Complete it */
1247  }
1248 
1249  /* Return the status */
1250  DPRINT("Lock IRP %p %x\n", Irp, IoStatusBlock.Status);
1252  (FileLock->CompleteLockIrpRoutine,
1253  Context,
1254  Irp,
1256  &Status,
1257  NULL);
1258  return IoStatusBlock.Status;
1259 }
1260 
1261 /*
1262  * @implemented
1263  */
1264 VOID
1265 NTAPI
1269 {
1270  /* Setup the lock */
1271  RtlZeroMemory(FileLock, sizeof(*FileLock));
1272  FileLock->FastIoIsQuestionable = FALSE;
1273  FileLock->CompleteLockIrpRoutine = CompleteLockIrpRoutine;
1274  FileLock->UnlockRoutine = UnlockRoutine;
1275  FileLock->LockInformation = NULL;
1276 }
1277 
1278 /*
1279  * @implemented
1280  */
1281 VOID
1282 NTAPI
1284 {
1285  if (FileLock->LockInformation)
1286  {
1287  PIRP Irp;
1288  PLOCK_INFORMATION InternalInfo = FileLock->LockInformation;
1290  PLIST_ENTRY SharedEntry;
1291  PLOCK_SHARED_RANGE SharedRange;
1292  // MSDN: this completes any remaining lock IRPs
1293  for (SharedEntry = InternalInfo->SharedLocks.Flink;
1294  SharedEntry != &InternalInfo->SharedLocks;)
1295  {
1296  SharedRange = CONTAINING_RECORD(SharedEntry, LOCK_SHARED_RANGE, Entry);
1297  SharedEntry = SharedEntry->Flink;
1298  RemoveEntryList(&SharedRange->Entry);
1299  ExFreePoolWithTag(SharedRange, TAG_RANGE);
1300  }
1301  while ((Entry = RtlGetElementGenericTable(&InternalInfo->RangeTable, 0)) != NULL)
1302  {
1304  }
1305  while ((Irp = IoCsqRemoveNextIrp(&InternalInfo->Csq, NULL)) != NULL)
1306  {
1308  /* FsRtlProcessFileLock has _Must_inspect_result_ */
1310  (void)Status;
1311  }
1312  ExFreePoolWithTag(InternalInfo, TAG_FLOCK);
1313  FileLock->LockInformation = NULL;
1314  }
1315 }
1316 
1317 /*
1318  * @implemented
1319  */
1320 PFILE_LOCK
1321 NTAPI
1324 {
1325  PFILE_LOCK FileLock;
1326 
1327  /* Try to allocate it */
1328  FileLock = ExAllocateFromPagedLookasideList(&FsRtlFileLockLookasideList);
1329  if (FileLock)
1330  {
1331  /* Initialize it */
1332  FsRtlInitializeFileLock(FileLock,
1334  UnlockRoutine);
1335  }
1336 
1337  /* Return the lock */
1338  return FileLock;
1339 }
1340 
1341 /*
1342  * @implemented
1343  */
1344 VOID
1345 NTAPI
1347 {
1348  /* Uninitialize and free the lock */
1349  FsRtlUninitializeFileLock(FileLock);
1350  ExFreeToPagedLookasideList(&FsRtlFileLockLookasideList, FileLock);
1351 }
VOID NTAPI FsRtlpExpandLockElement(PCOMBINED_LOCK_ELEMENT ToExpand, PCOMBINED_LOCK_ELEMENT Conflict)
Definition: filelock.c:272
* 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:752
_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:1266
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 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:1283
BOOLEAN NTAPI FsRtlCheckLockForWriteAccess(IN PFILE_LOCK FileLock, IN PIRP Irp)
Definition: filelock.c:714
_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:134
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:1322
LARGE_INTEGER Start
Definition: filelock.c:48
static VOID NTAPI LockFree(PRTL_GENERIC_TABLE Table, PVOID Buffer)
Definition: filelock.c:79
_In_ UINT Bytes
Definition: mmcopy.h:9
#define STATUS_INVALID_DEVICE_REQUEST
Definition: udferr_usr.h:138
#define IRP_MN_UNLOCK_ALL_BY_KEY
Definition: iotypes.h:4413
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
#define TAG_FLOCK
Definition: filelock.c:56
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:1090
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:829
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:208
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:328
_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:194
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:259
static PIRP NTAPI LockPeekNextIrp(PIO_CSQ Csq, PIRP Irp, PVOID PeekContext)
Definition: filelock.c:139
_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
#define TAG_TABLE
Definition: filelock.c:54
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:676
FILE_SHARED_LOCK_ENTRY Shared
Definition: filelock.c:27
_Must_inspect_result_ NTSYSAPI PVOID NTAPI RtlGetElementGenericTable(_In_ PRTL_GENERIC_TABLE Table, _In_ ULONG I)
#define KeAcquireSpinLock(sl, irql)
Definition: env_spec_w32.h:609
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:125
#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:86
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:1029
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:1156
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
#define TAG_RANGE
Definition: filelock.c:55
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:1346
#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:224
#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:201
#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:71
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:786
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:294
#define NT_ASSERT
Definition: rtlfuncs.h:3310
#define SL_FAIL_IMMEDIATELY
Definition: iotypes.h:1832
PULONG MinorVersion OPTIONAL
Definition: CrossNt.h:68