ReactOS  0.4.14-dev-41-g31d7680
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 'LTAB'
55 #define TAG_RANGE 'FSRA'
56 #define TAG_FLOCK 'FLCK'
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 =
169  LockElement.Exclusive.FileLock.StartingByte.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  {
997  if (NextMatchingLockIrp->IoStatus.Information == InternalInfo->Generation)
998  {
999  // We've already looked at this one, meaning that we looped.
1000  // Put it back and exit.
1002  (&InternalInfo->Csq,
1003  NextMatchingLockIrp,
1004  NULL,
1005  NULL);
1006  break;
1007  }
1008  // Got a new lock irp... try to do the new lock operation
1009  // Note that we pick an operation that would succeed at the time
1010  // we looked, but can't guarantee that it won't just be re-queued
1011  // because somebody else snatched part of the range in a new thread.
1012  DPRINT("Locking another IRP %p for %p %wZ\n",
1013  NextMatchingLockIrp, FileLock, &FileObject->FileName);
1014  FsRtlProcessFileLock(InternalInfo->BelongsTo, NextMatchingLockIrp, NULL);
1015  }
1016 
1017  DPRINT("Success %wZ\n", &FileObject->FileName);
1018  return STATUS_SUCCESS;
1019 }
1020 
1021 /*
1022  * @implemented
1023  */
1024 NTSTATUS
1025 NTAPI
1030 {
1031  PLIST_ENTRY ListEntry;
1033  PLOCK_INFORMATION InternalInfo = FileLock->LockInformation;
1034  DPRINT("FsRtlFastUnlockAll(%wZ)\n", &FileObject->FileName);
1035  // XXX Synchronize somehow
1036  if (!FileLock->LockInformation) {
1037  DPRINT("Not locked %wZ\n", &FileObject->FileName);
1038  return STATUS_RANGE_NOT_LOCKED; // no locks
1039  }
1040  for (ListEntry = InternalInfo->SharedLocks.Flink;
1041  ListEntry != &InternalInfo->SharedLocks;)
1042  {
1045  Length.QuadPart = Range->End.QuadPart - Range->Start.QuadPart;
1046  ListEntry = ListEntry->Flink;
1047  if (Range->ProcessId != Process)
1048  continue;
1050  (FileLock,
1051  FileObject,
1052  &Range->Start,
1053  &Length,
1054  Range->ProcessId,
1055  Range->Key,
1056  Context,
1057  TRUE);
1058  }
1059  for (Entry = RtlEnumerateGenericTable(&InternalInfo->RangeTable, TRUE);
1060  Entry;
1061  Entry = RtlEnumerateGenericTable(&InternalInfo->RangeTable, FALSE))
1062  {
1064  // We'll take the first one to be the list head, and free the others first...
1065  Length.QuadPart =
1066  Entry->Exclusive.FileLock.EndingByte.QuadPart -
1067  Entry->Exclusive.FileLock.StartingByte.QuadPart;
1069  (FileLock,
1070  Entry->Exclusive.FileLock.FileObject,
1071  &Entry->Exclusive.FileLock.StartingByte,
1072  &Length,
1073  Entry->Exclusive.FileLock.ProcessId,
1074  Entry->Exclusive.FileLock.Key,
1075  Context,
1076  TRUE);
1077  }
1078  DPRINT("Done %wZ\n", &FileObject->FileName);
1079  return STATUS_SUCCESS;
1080 }
1081 
1082 /*
1083  * @implemented
1084  */
1085 NTSTATUS
1086 NTAPI
1090  IN ULONG Key,
1092 {
1093  PLIST_ENTRY ListEntry;
1095  PLOCK_INFORMATION InternalInfo = FileLock->LockInformation;
1096 
1097  DPRINT("FsRtlFastUnlockAllByKey(%wZ,Key %x)\n", &FileObject->FileName, Key);
1098 
1099  // XXX Synchronize somehow
1100  if (!FileLock->LockInformation) return STATUS_RANGE_NOT_LOCKED; // no locks
1101  for (ListEntry = InternalInfo->SharedLocks.Flink;
1102  ListEntry != &InternalInfo->SharedLocks;)
1103  {
1106  Length.QuadPart = Range->End.QuadPart - Range->Start.QuadPart;
1107  ListEntry = ListEntry->Flink;
1108  if (Range->ProcessId != Process ||
1109  Range->Key != Key)
1110  continue;
1112  (FileLock,
1113  FileObject,
1114  &Range->Start,
1115  &Length,
1116  Range->ProcessId,
1117  Range->Key,
1118  Context,
1119  TRUE);
1120  }
1121  for (Entry = RtlEnumerateGenericTable(&InternalInfo->RangeTable, TRUE);
1122  Entry;
1123  Entry = RtlEnumerateGenericTable(&InternalInfo->RangeTable, FALSE))
1124  {
1126  // We'll take the first one to be the list head, and free the others first...
1127  Length.QuadPart =
1128  Entry->Exclusive.FileLock.EndingByte.QuadPart -
1129  Entry->Exclusive.FileLock.StartingByte.QuadPart;
1130  if (Entry->Exclusive.FileLock.Key == Key &&
1131  Entry->Exclusive.FileLock.ProcessId == Process)
1132  {
1134  (FileLock,
1135  Entry->Exclusive.FileLock.FileObject,
1136  &Entry->Exclusive.FileLock.StartingByte,
1137  &Length,
1138  Entry->Exclusive.FileLock.ProcessId,
1139  Entry->Exclusive.FileLock.Key,
1140  Context,
1141  TRUE);
1142  }
1143  }
1144 
1145  return STATUS_SUCCESS;
1146 }
1147 
1148 /*
1149  * @implemented
1150  */
1151 NTSTATUS
1152 NTAPI
1154  IN PIRP Irp,
1156 {
1157  PIO_STACK_LOCATION IoStackLocation;
1158  NTSTATUS Status;
1160 
1161  /* Get the I/O Stack location */
1162  IoStackLocation = IoGetCurrentIrpStackLocation(Irp);
1163  ASSERT(IoStackLocation->MajorFunction == IRP_MJ_LOCK_CONTROL);
1164 
1165  /* Clear the I/O status block and check what function this is */
1167 
1168  DPRINT("FsRtlProcessFileLock(%wZ, MinorFunction %x)\n",
1169  &IoStackLocation->FileObject->FileName,
1170  IoStackLocation->MinorFunction);
1171 
1172  switch(IoStackLocation->MinorFunction)
1173  {
1174  /* A lock */
1175  case IRP_MN_LOCK:
1176 
1177  /* Call the private lock routine */
1178  FsRtlPrivateLock(FileLock,
1179  IoStackLocation->FileObject,
1180  &IoStackLocation->
1181  Parameters.LockControl.ByteOffset,
1182  IoStackLocation->Parameters.LockControl.Length,
1184  IoStackLocation->Parameters.LockControl.Key,
1185  IoStackLocation->Flags & SL_FAIL_IMMEDIATELY,
1186  IoStackLocation->Flags & SL_EXCLUSIVE_LOCK,
1187  &IoStatusBlock,
1188  Irp,
1189  Context,
1190  FALSE);
1191  return IoStatusBlock.Status;
1192 
1193  /* A single unlock */
1194  case IRP_MN_UNLOCK_SINGLE:
1195 
1196  /* Call fast unlock */
1198  FsRtlFastUnlockSingle(FileLock,
1199  IoStackLocation->FileObject,
1200  &IoStackLocation->Parameters.LockControl.
1201  ByteOffset,
1202  IoStackLocation->Parameters.LockControl.
1203  Length,
1205  IoStackLocation->Parameters.LockControl.
1206  Key,
1207  Context,
1208  FALSE);
1209  break;
1210 
1211  /* Total unlock */
1212  case IRP_MN_UNLOCK_ALL:
1213 
1214  /* Do a fast unlock */
1216  IoStackLocation->
1217  FileObject,
1219  Context);
1220  break;
1221 
1222  /* Unlock by key */
1224 
1225  /* Do it */
1227  FsRtlFastUnlockAllByKey(FileLock,
1228  IoStackLocation->FileObject,
1230  IoStackLocation->Parameters.
1231  LockControl.Key,
1232  Context);
1233  break;
1234 
1235  /* Invalid request */
1236  default:
1237 
1238  /* Complete it */
1242  }
1243 
1244  /* Return the status */
1245  DPRINT("Lock IRP %p %x\n", Irp, IoStatusBlock.Status);
1247  (FileLock->CompleteLockIrpRoutine,
1248  Context,
1249  Irp,
1251  &Status,
1252  NULL);
1253  return IoStatusBlock.Status;
1254 }
1255 
1256 /*
1257  * @implemented
1258  */
1259 VOID
1260 NTAPI
1264 {
1265  /* Setup the lock */
1266  RtlZeroMemory(FileLock, sizeof(*FileLock));
1267  FileLock->FastIoIsQuestionable = FALSE;
1268  FileLock->CompleteLockIrpRoutine = CompleteLockIrpRoutine;
1269  FileLock->UnlockRoutine = UnlockRoutine;
1270  FileLock->LockInformation = NULL;
1271 }
1272 
1273 /*
1274  * @implemented
1275  */
1276 VOID
1277 NTAPI
1279 {
1280  if (FileLock->LockInformation)
1281  {
1282  PIRP Irp;
1283  PLOCK_INFORMATION InternalInfo = FileLock->LockInformation;
1285  PLIST_ENTRY SharedEntry;
1286  PLOCK_SHARED_RANGE SharedRange;
1287  // MSDN: this completes any remaining lock IRPs
1288  for (SharedEntry = InternalInfo->SharedLocks.Flink;
1289  SharedEntry != &InternalInfo->SharedLocks;)
1290  {
1291  SharedRange = CONTAINING_RECORD(SharedEntry, LOCK_SHARED_RANGE, Entry);
1292  SharedEntry = SharedEntry->Flink;
1293  RemoveEntryList(&SharedRange->Entry);
1294  ExFreePoolWithTag(SharedRange, TAG_RANGE);
1295  }
1296  while ((Entry = RtlGetElementGenericTable(&InternalInfo->RangeTable, 0)) != NULL)
1297  {
1299  }
1300  while ((Irp = IoCsqRemoveNextIrp(&InternalInfo->Csq, NULL)) != NULL)
1301  {
1302  FsRtlProcessFileLock(FileLock, Irp, NULL);
1303  }
1304  ExFreePoolWithTag(InternalInfo, TAG_FLOCK);
1305  FileLock->LockInformation = NULL;
1306  }
1307 }
1308 
1309 /*
1310  * @implemented
1311  */
1312 PFILE_LOCK
1313 NTAPI
1316 {
1317  PFILE_LOCK FileLock;
1318 
1319  /* Try to allocate it */
1320  FileLock = ExAllocateFromPagedLookasideList(&FsRtlFileLockLookasideList);
1321  if (FileLock)
1322  {
1323  /* Initialize it */
1324  FsRtlInitializeFileLock(FileLock,
1326  UnlockRoutine);
1327  }
1328 
1329  /* Return the lock */
1330  return FileLock;
1331 }
1332 
1333 /*
1334  * @implemented
1335  */
1336 VOID
1337 NTAPI
1339 {
1340  /* Uninitialize and free the lock */
1341  FsRtlUninitializeFileLock(FileLock);
1342  ExFreeToPagedLookasideList(&FsRtlFileLockLookasideList, FileLock);
1343 }
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:38
FILE_EXCLUSIVE_LOCK_ENTRY Exclusive
Definition: filelock.c:29
ASMGENDATA Table[]
Definition: genincdata.c:61
#define TRUE
Definition: types.h:120
NTSYSAPI VOID NTAPI RtlCopyMemory(VOID UNALIGNED *Destination, CONST VOID UNALIGNED *Source, ULONG Length)
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 PLARGE_INTEGER IN PLARGE_INTEGER PEPROCESS ULONG Key
Definition: fatprocs.h:2697
LARGE_INTEGER End
Definition: filelock.c:48
struct _Entry Entry
Definition: kefuncs.h:640
struct _LOCK_SHARED_RANGE * PLOCK_SHARED_RANGE
_Must_inspect_result_ _In_opt_ PUNLOCK_ROUTINE UnlockRoutine
Definition: fltkernel.h:2124
VOID NTAPI FsRtlInitializeFileLock(IN PFILE_LOCK FileLock, IN PCOMPLETE_LOCK_IRP_ROUTINE CompleteLockIrpRoutine OPTIONAL, IN PUNLOCK_ROUTINE UnlockRoutine OPTIONAL)
Definition: filelock.c:1261
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)
IN PLARGE_INTEGER IN ULONG IN BOOLEAN IN ULONG IN BOOLEAN OUT PIO_STATUS_BLOCK IoStatus
Definition: fatprocs.h:2650
#define STATUS_RANGE_NOT_LOCKED
Definition: ntstatus.h:348
_In_ PIRP Irp
Definition: csq.h:116
#define STATUS_INVALID_PARAMETER
Definition: udferr_usr.h:135
VOID NTAPI FsRtlUninitializeFileLock(IN PFILE_LOCK FileLock)
Definition: filelock.c:1278
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:1314
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:4057
IRP
Definition: iotypes.h:2463
PCOMPLETE_LOCK_IRP_ROUTINE CompleteLockIrpRoutine
Definition: fsrtltypes.h:203
#define InsertTailList(ListHead, Entry)
_Out_ PKIRQL Irql
Definition: csq.h:179
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:1087
UCHAR KIRQL
Definition: env_spec_w32.h:591
ULONG CLONG
Definition: umtypes.h:126
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
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
IN PLARGE_INTEGER IN PLARGE_INTEGER PEPROCESS ULONG BOOLEAN FailImmediately
Definition: fatprocs.h:2697
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:251
unsigned char BOOLEAN
PFILE_OBJECT FileObject
Definition: fsrtltypes.h:192
smooth NULL
Definition: ftsmooth.c:416
_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
void DPRINT(...)
Definition: polytest.cpp:61
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
_Inout_ PFILE_OBJECT FileObject
Definition: cdprocs.h:593
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
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)
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:119
#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
_In_ ULONG _In_ ULONG _In_ ULONG Length
Definition: ntddpcm.h:101
#define IRP_MN_UNLOCK_ALL
Definition: iotypes.h:4056
* PFILE_OBJECT
Definition: iotypes.h:1955
RTL_GENERIC_TABLE RangeTable
Definition: filelock.c:35
ASSERT((InvokeOnSuccess||InvokeOnError||InvokeOnCancel) ?(CompletionRoutine !=NULL) :TRUE)
#define ExAllocatePoolWithTag(hernya, size, tag)
Definition: env_spec_w32.h:350
LIST_ENTRY SharedLocks
Definition: filelock.c:40
Definition: ttei1.cpp:12
NTSTATUS(NTAPI * PCOMPLETE_LOCK_IRP_ROUTINE)(_In_ PVOID Context, _In_ PIRP Irp)
Definition: fsrtltypes.h:183
_In_ PPCI_DEVICE_PRESENCE_PARAMETERS Parameters
Definition: iotypes.h:872
static RTL_GENERIC_COMPARE_RESULTS NTAPI LockCompare(PRTL_GENERIC_TABLE Table, PVOID PtrA, PVOID PtrB)
Definition: filelock.c:86
ULONG LowPart
Definition: typedefs.h:104
KIRQL * PKIRQL
Definition: env_spec_w32.h:592
PFILE_LOCK BelongsTo
Definition: filelock.c:39
Definition: typedefs.h:117
NTSTATUS NTAPI FsRtlFastUnlockAll(IN PFILE_LOCK FileLock, IN PFILE_OBJECT FileObject, IN PEPROCESS Process, IN PVOID Context OPTIONAL)
Definition: filelock.c:1026
Definition: range.c:43
struct _LOCK_SHARED_RANGE LOCK_SHARED_RANGE
NTSTATUS NTAPI FsRtlProcessFileLock(IN PFILE_LOCK FileLock, IN PIRP Irp, IN PVOID Context OPTIONAL)
Definition: filelock.c:1153
Status
Definition: gdiplustypes.h:24
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:2745
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:2813
struct LOOKASIDE_ALIGN _PAGED_LOOKASIDE_LIST PAGED_LOOKASIDE_LIST
_In_ PFCB _In_ LONGLONG FileOffset
Definition: cdprocs.h:151
#define InitializeListHead(ListHead)
Definition: env_spec_w32.h:944
#define STATUS_NO_MEMORY
Definition: ntstatus.h:246
ULONG KSPIN_LOCK
Definition: env_spec_w32.h:72
#define SL_EXCLUSIVE_LOCK
Definition: iotypes.h:1790
PVOID LockInformation
Definition: fsrtltypes.h:207
static OUT PIO_STATUS_BLOCK IoStatusBlock
Definition: pipe.c:75
#define B(row, col)
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:4054
#define TAG_RANGE
Definition: filelock.c:55
IN PLARGE_INTEGER IN PLARGE_INTEGER PEPROCESS ULONG BOOLEAN BOOLEAN ExclusiveLock
Definition: fatprocs.h:2697
#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:306
_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:1338
#define OUT
Definition: typedefs.h:39
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
unsigned int ULONG
Definition: retypes.h:1
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:261
static VOID NTAPI LockReleaseQueueLock(PIO_CSQ Csq, KIRQL Irql)
Definition: filelock.c:201
LIST_ENTRY CsqList
Definition: filelock.c:38
#define ExFreePoolWithTag(_P, _T)
Definition: module.h:1099
_In_opt_ PCOMPLETE_LOCK_IRP_ROUTINE CompleteLockIrpRoutine
Definition: fsrtlfuncs.h:139
struct _NAMED_PIPE_CREATE_PARAMETERS * Parameters
Definition: iotypes.h:2772
static PVOID NTAPI LockAllocate(PRTL_GENERIC_TABLE Table, CLONG Bytes)
Definition: filelock.c:71
return STATUS_SUCCESS
Definition: btrfs.c:2966
IoMarkIrpPending(Irp)
NTSYSAPI PVOID NTAPI RtlInsertElementGenericTable(_In_ PRTL_GENERIC_TABLE Table, _In_reads_bytes_(BufferSize) PVOID Buffer, _In_ CLONG BufferSize, _Out_opt_ PBOOLEAN NewElement)
union _COMBINED_LOCK_ELEMENT * PCOMBINED_LOCK_ELEMENT
#define IRP_MN_UNLOCK_SINGLE
Definition: iotypes.h:4055
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:112
IN PDCB IN PCCB IN VBO IN OUT PULONG OUT PDIRENT OUT PBCB OUT PVBO ByteOffset
Definition: fatprocs.h:716
PCOMBINED_LOCK_ELEMENT NTAPI FsRtlpRebuildSharedLockRange(PFILE_LOCK FileLock, PLOCK_INFORMATION LockInfo, PCOMBINED_LOCK_ELEMENT Conflict)
Definition: filelock.c:294
#define SL_FAIL_IMMEDIATELY
Definition: iotypes.h:1789
PULONG MinorVersion OPTIONAL
Definition: CrossNt.h:68