ReactOS 0.4.15-dev-7958-gcd0bb1a
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
33typedef struct _LOCK_INFORMATION
34{
42}
44
45typedef struct _LOCK_SHARED_RANGE
46{
51}
53
54/* PRIVATE FUNCTIONS *********************************************************/
55
56VOID
60 IN PIRP Irp,
62 OUT PNTSTATUS NewStatus,
64
65/* Generic table methods */
66
68{
71 DPRINT("LockAllocate(%lu) => %p\n", Bytes, Result);
72 return Result;
73}
74
76{
77 DPRINT("LockFree(%p)\n", Buffer);
79}
80
83{
84 PCOMBINED_LOCK_ELEMENT A = PtrA, B = PtrB;
86#if 0
87 DPRINT("Starting to compare element %x to element %x\n", PtrA, PtrB);
88#endif
89 /* Match if we overlap */
90 if (((A->Exclusive.FileLock.StartingByte.QuadPart <
91 B->Exclusive.FileLock.EndingByte.QuadPart) &&
92 (A->Exclusive.FileLock.StartingByte.QuadPart >=
93 B->Exclusive.FileLock.StartingByte.QuadPart)) ||
94 ((B->Exclusive.FileLock.StartingByte.QuadPart <
95 A->Exclusive.FileLock.EndingByte.QuadPart) &&
96 (B->Exclusive.FileLock.StartingByte.QuadPart >=
97 A->Exclusive.FileLock.StartingByte.QuadPart)))
98 return GenericEqual;
99 /* Otherwise, key on the starting byte */
100 Result =
101 (A->Exclusive.FileLock.StartingByte.QuadPart <
102 B->Exclusive.FileLock.StartingByte.QuadPart) ? GenericLessThan :
103 (A->Exclusive.FileLock.StartingByte.QuadPart >
104 B->Exclusive.FileLock.StartingByte.QuadPart) ? GenericGreaterThan :
106#if 0
107 DPRINT("Compare(%x:%x) %x-%x to %x-%x => %d\n",
108 A,B,
109 A->Exclusive.FileLock.StartingByte.LowPart,
110 A->Exclusive.FileLock.EndingByte.LowPart,
111 B->Exclusive.FileLock.StartingByte.LowPart,
112 B->Exclusive.FileLock.EndingByte.LowPart,
113 Result);
114#endif
115 return Result;
116}
117
118/* CSQ methods */
119
121(PIO_CSQ Csq,
122 PIRP Irp,
124{
126 InsertTailList(&LockInfo->CsqList, &Irp->Tail.Overlay.ListEntry);
127 return STATUS_SUCCESS;
128}
129
131{
132 RemoveEntryList(&Irp->Tail.Overlay.ListEntry);
133}
134
136{
137 // Context will be a COMBINED_LOCK_ELEMENT. We're looking for a
138 // lock that can be acquired, now that the lock matching PeekContext
139 // has been removed.
140 COMBINED_LOCK_ELEMENT LockElement;
143 PLIST_ENTRY Following;
144 DPRINT("PeekNextIrp(IRP %p, Context %p)\n", Irp, PeekContext);
145 if (!Irp)
146 {
147 Following = LockInfo->CsqList.Flink;
148 }
149 else
150 Following = Irp->Tail.Overlay.ListEntry.Flink;
151
152 DPRINT("ListEntry %p Head %p\n", Following, &LockInfo->CsqList);
153 for (;
154 Following != &LockInfo->CsqList;
155 Following = Following->Flink)
156 {
157 PIO_STACK_LOCATION IoStack;
158 BOOLEAN Matching;
159 Irp = CONTAINING_RECORD(Following, IRP, Tail.Overlay.ListEntry);
160 DPRINT("Irp %p\n", Irp);
162 LockElement.Exclusive.FileLock.StartingByte =
163 IoStack->Parameters.LockControl.ByteOffset;
166 IoStack->Parameters.LockControl.Length->QuadPart;
167 /* If a context was specified, it's a range to check to unlock */
168 if (WhereUnlock)
169 {
170 Matching = LockCompare
171 (&LockInfo->RangeTable, &LockElement, WhereUnlock) != GenericEqual;
172 }
173 /* Else get any completable IRP */
174 else
175 {
176 Matching = FALSE;
177 }
178 if (!Matching)
179 {
180 // This IRP is fine...
181 DPRINT("Returning the IRP %p\n", Irp);
182 return Irp;
183 }
184 }
185 DPRINT("Return NULL\n");
186 return NULL;
187}
188
189static VOID NTAPI
191{
193 KeAcquireSpinLock(&LockInfo->CsqLock, Irql);
194}
195
196static VOID NTAPI
198{
200 KeReleaseSpinLock(&LockInfo->CsqLock, Irql);
201}
202
203static VOID NTAPI
205{
208 DPRINT("Complete cancelled IRP %p Status %x\n", Irp, STATUS_CANCELLED);
211 NULL,
212 Irp,
214 &Status,
215 NULL);
216}
217
218VOID
219NTAPI
222 IN PIRP Irp,
224 OUT PNTSTATUS NewStatus,
226{
227 /* Check if we have a complete routine */
228 Irp->IoStatus.Information = 0;
229 if (CompleteRoutine)
230 {
231 /* Check if we have a file object */
232 if (FileObject) FileObject->LastLock = NULL;
233
234 /* Set the I/O Status and do completion */
235 Irp->IoStatus.Status = Status;
236 DPRINT("Calling completion routine %p Status %x\n", Irp, Status);
237 *NewStatus = CompleteRoutine(Context, Irp);
238 }
239 else
240 {
241 /* Otherwise do a normal I/O complete request */
242 DPRINT("Completing IRP %p Status %x\n", Irp, Status);
244 *NewStatus = Status;
245 }
246}
247
248/* PUBLIC FUNCTIONS **********************************************************/
249
250/*
251 * @implemented
252 */
254NTAPI
257{
259 if (!FileLock->LockInformation) return NULL;
260 Entry = RtlEnumerateGenericTable(FileLock->LockInformation, Restart);
261 if (!Entry) return NULL;
262 else return &Entry->Exclusive.FileLock;
263}
264
265VOID
266NTAPI
268(PCOMBINED_LOCK_ELEMENT ToExpand,
269 PCOMBINED_LOCK_ELEMENT Conflict)
270{
273 {
276 }
277 if (ToExpand->Exclusive.FileLock.EndingByte.QuadPart <
279 {
280 ToExpand->Exclusive.FileLock.EndingByte =
281 Conflict->Exclusive.FileLock.EndingByte;
282 }
283}
284
285/* This function expands the conflicting range Conflict by removing and reinserting it,
286 then adds a shared range of the same size */
288NTAPI
290(PFILE_LOCK FileLock,
291 PLOCK_INFORMATION LockInfo,
292 PCOMBINED_LOCK_ELEMENT Conflict)
293{
294 /* Starting at Conflict->StartingByte and going to Conflict->EndingByte
295 * capture and expand a shared range from the shared range list.
296 * Finish when we've incorporated all overlapping shared regions.
297 */
298 BOOLEAN InsertedNew = FALSE, RemovedOld;
299 COMBINED_LOCK_ELEMENT NewElement = *Conflict;
302 (FileLock->LockInformation, &NewElement)))
303 {
304 FsRtlpExpandLockElement(&NewElement, Entry);
306 (&LockInfo->RangeTable,
307 Entry);
308 ASSERT(RemovedOld);
309 }
311 (&LockInfo->RangeTable,
312 &NewElement,
313 sizeof(NewElement),
314 &InsertedNew);
315 ASSERT(InsertedNew);
316 return Conflict;
317}
318
319/*
320 * @implemented
321 */
323NTAPI
329 IN ULONG Key,
336{
338 COMBINED_LOCK_ELEMENT ToInsert;
339 PCOMBINED_LOCK_ELEMENT Conflict;
340 PLOCK_INFORMATION LockInfo;
341 PLOCK_SHARED_RANGE NewSharedRange;
342 BOOLEAN InsertedNew;
343 ULARGE_INTEGER UnsignedStart;
344 ULARGE_INTEGER UnsignedEnd;
345
346 DPRINT("FsRtlPrivateLock(%wZ, Offset %08x%08x (%d), Length %08x%08x (%d), Key %x, FailImmediately %u, Exclusive %u)\n",
347 &FileObject->FileName,
348 FileOffset->HighPart,
349 FileOffset->LowPart,
350 (int)FileOffset->QuadPart,
351 Length->HighPart,
352 Length->LowPart,
353 (int)Length->QuadPart,
354 Key,
357
358 UnsignedStart.QuadPart = FileOffset->QuadPart;
359 UnsignedEnd.QuadPart = FileOffset->QuadPart + Length->QuadPart;
360
361 if (UnsignedEnd.QuadPart < UnsignedStart.QuadPart)
362 {
363 DPRINT("File offset out of range\n");
365 if (Irp)
366 {
367 DPRINT("Complete lock %p Status %x\n", Irp, IoStatus->Status);
369 (FileLock->CompleteLockIrpRoutine,
370 Context,
371 Irp,
372 IoStatus->Status,
373 &Status,
374 FileObject);
375 }
376 return FALSE;
377 }
378
379 /* Initialize the lock, if necessary */
380 if (!FileLock->LockInformation)
381 {
383 if (!LockInfo)
384 {
385 IoStatus->Status = STATUS_NO_MEMORY;
386 return FALSE;
387 }
388 FileLock->LockInformation = LockInfo;
389
390 LockInfo->BelongsTo = FileLock;
392
394 (&LockInfo->RangeTable,
397 LockFree,
398 NULL);
399
400 KeInitializeSpinLock(&LockInfo->CsqLock);
401 InitializeListHead(&LockInfo->CsqList);
402
404 (&LockInfo->Csq,
411 }
412
413 LockInfo = FileLock->LockInformation;
416 ToInsert.Exclusive.FileLock.EndingByte.QuadPart = FileOffset->QuadPart + Length->QuadPart;
418 ToInsert.Exclusive.FileLock.Key = Key;
420
422 (FileLock->LockInformation,
423 &ToInsert,
424 sizeof(ToInsert),
425 &InsertedNew);
426
427 if (Conflict && !InsertedNew)
428 {
430 {
431 DPRINT("Conflict %08x%08x:%08x%08x Exc %u (Want Exc %u)\n",
438 if (FailImmediately)
439 {
440 DPRINT("STATUS_FILE_LOCK_CONFLICT\n");
442 if (Irp)
443 {
444 DPRINT("STATUS_FILE_LOCK_CONFLICT: Complete\n");
446 (FileLock->CompleteLockIrpRoutine,
447 Context,
448 Irp,
449 IoStatus->Status,
450 &Status,
451 FileObject);
452 }
453 return FALSE;
454 }
455 else
456 {
457 IoStatus->Status = STATUS_PENDING;
458 if (Irp)
459 {
460 Irp->IoStatus.Information = LockInfo->Generation;
463 (&LockInfo->Csq,
464 Irp,
465 NULL,
466 NULL);
467 }
468 }
469 return FALSE;
470 }
471 else
472 {
473 ULONG i;
474 /* We know of at least one lock in range that's shared. We need to
475 * find out if any more exist and any are exclusive. */
476 for (i = 0; i < RtlNumberGenericTableElements(&LockInfo->RangeTable); i++)
477 {
478 Conflict = RtlGetElementGenericTable(&LockInfo->RangeTable, i);
479
480 /* The first argument will be inserted as a shared range */
481 if (Conflict && (LockCompare(&LockInfo->RangeTable, Conflict, &ToInsert) == GenericEqual))
482 {
483 if (Conflict->Exclusive.FileLock.ExclusiveLock)
484 {
485 /* Found an exclusive match */
486 if (FailImmediately)
487 {
489 DPRINT("STATUS_FILE_LOCK_CONFLICT\n");
490 if (Irp)
491 {
492 DPRINT("STATUS_FILE_LOCK_CONFLICT: Complete\n");
494 (FileLock->CompleteLockIrpRoutine,
495 Context,
496 Irp,
497 IoStatus->Status,
498 &Status,
499 FileObject);
500 }
501 }
502 else
503 {
504 IoStatus->Status = STATUS_PENDING;
505 if (Irp)
506 {
509 (&LockInfo->Csq,
510 Irp,
511 NULL,
512 NULL);
513 }
514 }
515 return FALSE;
516 }
517 }
518 }
519
520 DPRINT("Overlapping shared lock %wZ %08x%08x %08x%08x\n",
521 &FileObject->FileName,
526 Conflict = FsRtlpRebuildSharedLockRange(FileLock,
527 LockInfo,
528 &ToInsert);
529 if (!Conflict)
530 {
531 IoStatus->Status = STATUS_NO_MEMORY;
532 if (Irp)
533 {
535 (FileLock->CompleteLockIrpRoutine,
536 Context,
537 Irp,
538 IoStatus->Status,
539 &Status,
540 FileObject);
541 }
542 }
543
544 /* We got here because there were only overlapping shared locks */
545 /* A shared lock is both a range *and* a list entry. Insert the
546 entry here. */
547
548 DPRINT("Adding shared lock %wZ\n", &FileObject->FileName);
549 NewSharedRange =
550 ExAllocatePoolWithTag(NonPagedPool, sizeof(*NewSharedRange), TAG_RANGE);
551 if (!NewSharedRange)
552 {
553 IoStatus->Status = STATUS_NO_MEMORY;
554 if (Irp)
555 {
557 (FileLock->CompleteLockIrpRoutine,
558 Context,
559 Irp,
560 IoStatus->Status,
561 &Status,
562 FileObject);
563 }
564 return FALSE;
565 }
566 DPRINT("Adding shared lock %wZ\n", &FileObject->FileName);
567 NewSharedRange->Start = *FileOffset;
568 NewSharedRange->End.QuadPart = FileOffset->QuadPart + Length->QuadPart;
569 NewSharedRange->Key = Key;
570 NewSharedRange->ProcessId = ToInsert.Exclusive.FileLock.ProcessId;
571 InsertTailList(&LockInfo->SharedLocks, &NewSharedRange->Entry);
572
573 DPRINT("Acquired shared lock %wZ %08x%08x %08x%08x\n",
574 &FileObject->FileName,
579 IoStatus->Status = STATUS_SUCCESS;
580 if (Irp)
581 {
583 (FileLock->CompleteLockIrpRoutine,
584 Context,
585 Irp,
586 IoStatus->Status,
587 &Status,
588 FileObject);
589 }
590 return TRUE;
591 }
592 }
593 else if (!Conflict)
594 {
595 /* Conflict here is (or would be) the newly inserted element, but we ran
596 * out of space probably. */
597 IoStatus->Status = STATUS_NO_MEMORY;
598 if (Irp)
599 {
601 (FileLock->CompleteLockIrpRoutine,
602 Context,
603 Irp,
604 IoStatus->Status,
605 &Status,
606 FileObject);
607 }
608 return FALSE;
609 }
610 else
611 {
612 DPRINT("Inserted new lock %wZ %08x%08x %08x%08x exclusive %u\n",
613 &FileObject->FileName,
619 if (!ExclusiveLock)
620 {
621 NewSharedRange =
622 ExAllocatePoolWithTag(NonPagedPool, sizeof(*NewSharedRange), TAG_RANGE);
623 if (!NewSharedRange)
624 {
625 IoStatus->Status = STATUS_NO_MEMORY;
626 if (Irp)
627 {
629 (FileLock->CompleteLockIrpRoutine,
630 Context,
631 Irp,
632 IoStatus->Status,
633 &Status,
634 FileObject);
635 }
636 return FALSE;
637 }
638 DPRINT("Adding shared lock %wZ\n", &FileObject->FileName);
639 NewSharedRange->Start = *FileOffset;
640 NewSharedRange->End.QuadPart = FileOffset->QuadPart + Length->QuadPart;
641 NewSharedRange->Key = Key;
642 NewSharedRange->ProcessId = Process;
643 InsertTailList(&LockInfo->SharedLocks, &NewSharedRange->Entry);
644 }
645
646 /* Assume all is cool, and lock is set */
647 IoStatus->Status = STATUS_SUCCESS;
648
649 if (Irp)
650 {
651 /* Complete the request */
652 FsRtlCompleteLockIrpReal(FileLock->CompleteLockIrpRoutine,
653 Context,
654 Irp,
655 IoStatus->Status,
656 &Status,
657 FileObject);
658
659 /* Update the status */
660 IoStatus->Status = Status;
661 }
662 }
663
664 return TRUE;
665}
666
667/*
668 * @implemented
669 */
671NTAPI
673 IN PIRP Irp)
674{
679 DPRINT("CheckLockForReadAccess(%wZ, Offset %08x%08x, Length %x)\n",
680 &IoStack->FileObject->FileName,
681 IoStack->Parameters.Read.ByteOffset.HighPart,
682 IoStack->Parameters.Read.ByteOffset.LowPart,
683 IoStack->Parameters.Read.Length);
684 if (!FileLock->LockInformation) {
685 DPRINT("CheckLockForReadAccess(%wZ) => TRUE\n", &IoStack->FileObject->FileName);
686 return TRUE;
687 }
688 ToFind.Exclusive.FileLock.StartingByte = IoStack->Parameters.Read.ByteOffset;
691 IoStack->Parameters.Read.Length;
693 (FileLock->LockInformation,
694 &ToFind);
695 if (!Found) {
696 DPRINT("CheckLockForReadAccess(%wZ) => TRUE\n", &IoStack->FileObject->FileName);
697 return TRUE;
698 }
699 Result = !Found->Exclusive.FileLock.ExclusiveLock ||
700 IoStack->Parameters.Read.Key == Found->Exclusive.FileLock.Key;
701 DPRINT("CheckLockForReadAccess(%wZ) => %s\n", &IoStack->FileObject->FileName, Result ? "TRUE" : "FALSE");
702 return Result;
703}
704
705/*
706 * @implemented
707 */
709NTAPI
711 IN PIRP Irp)
712{
717 PEPROCESS Process = Irp->Tail.Overlay.Thread->ThreadsProcess;
718 DPRINT("CheckLockForWriteAccess(%wZ, Offset %08x%08x, Length %x)\n",
719 &IoStack->FileObject->FileName,
720 IoStack->Parameters.Write.ByteOffset.HighPart,
721 IoStack->Parameters.Write.ByteOffset.LowPart,
722 IoStack->Parameters.Write.Length);
723 if (!FileLock->LockInformation) {
724 DPRINT("CheckLockForWriteAccess(%wZ) => TRUE\n", &IoStack->FileObject->FileName);
725 return TRUE;
726 }
727 ToFind.Exclusive.FileLock.StartingByte = IoStack->Parameters.Write.ByteOffset;
730 IoStack->Parameters.Write.Length;
732 (FileLock->LockInformation,
733 &ToFind);
734 if (!Found) {
735 DPRINT("CheckLockForWriteAccess(%wZ) => TRUE\n", &IoStack->FileObject->FileName);
736 return TRUE;
737 }
738 Result = Process == Found->Exclusive.FileLock.ProcessId;
739 DPRINT("CheckLockForWriteAccess(%wZ) => %s\n", &IoStack->FileObject->FileName, Result ? "TRUE" : "FALSE");
740 return Result;
741}
742
743/*
744 * @implemented
745 */
747NTAPI
751 IN ULONG Key,
754{
755 PEPROCESS EProcess = Process;
758 DPRINT("FsRtlFastCheckLockForRead(%wZ, Offset %08x%08x, Length %08x%08x, Key %x)\n",
759 &FileObject->FileName,
760 FileOffset->HighPart,
761 FileOffset->LowPart,
762 Length->HighPart,
763 Length->LowPart,
764 Key);
767 FileOffset->QuadPart + Length->QuadPart;
768 if (!FileLock->LockInformation) return TRUE;
770 (FileLock->LockInformation,
771 &ToFind);
772 if (!Found || !Found->Exclusive.FileLock.ExclusiveLock) return TRUE;
773 return Found->Exclusive.FileLock.Key == Key &&
774 Found->Exclusive.FileLock.ProcessId == EProcess;
775}
776
777/*
778 * @implemented
779 */
781NTAPI
785 IN ULONG Key,
788{
790 PEPROCESS EProcess = Process;
793 DPRINT("FsRtlFastCheckLockForWrite(%wZ, Offset %08x%08x, Length %08x%08x, Key %x)\n",
794 &FileObject->FileName,
795 FileOffset->HighPart,
796 FileOffset->LowPart,
797 Length->HighPart,
798 Length->LowPart,
799 Key);
802 FileOffset->QuadPart + Length->QuadPart;
803 if (!FileLock->LockInformation) {
804 DPRINT("CheckForWrite(%wZ) => TRUE\n", &FileObject->FileName);
805 return TRUE;
806 }
808 (FileLock->LockInformation,
809 &ToFind);
810 if (!Found) {
811 DPRINT("CheckForWrite(%wZ) => TRUE\n", &FileObject->FileName);
812 return TRUE;
813 }
814 Result = Found->Exclusive.FileLock.Key == Key &&
815 Found->Exclusive.FileLock.ProcessId == EProcess;
816 DPRINT("CheckForWrite(%wZ) => %s\n", &FileObject->FileName, Result ? "TRUE" : "FALSE");
817 return Result;
818}
819
820/*
821 * @implemented
822 */
824NTAPI
830 IN ULONG Key,
833{
834 BOOLEAN FoundShared = FALSE;
835 PLIST_ENTRY SharedEntry;
836 PLOCK_SHARED_RANGE SharedRange = NULL;
839 PIRP NextMatchingLockIrp;
840 PLOCK_INFORMATION InternalInfo = FileLock->LockInformation;
841 DPRINT("FsRtlFastUnlockSingle(%wZ, Offset %08x%08x (%d), Length %08x%08x (%d), Key %x)\n",
842 &FileObject->FileName,
843 FileOffset->HighPart,
844 FileOffset->LowPart,
845 (int)FileOffset->QuadPart,
846 Length->HighPart,
847 Length->LowPart,
848 (int)Length->QuadPart,
849 Key);
850 // The region to unlock must correspond exactly to a previously locked region
851 // -- msdn
852 // But Windows 2003 doesn't assert on it and simply ignores that parameter
853 // ASSERT(AlreadySynchronized);
856 FileOffset->QuadPart + Length->QuadPart;
857 if (!InternalInfo) {
858 DPRINT("File not previously locked (ever)\n");
860 }
861 Entry = RtlLookupElementGenericTable(&InternalInfo->RangeTable, &Find);
862 if (!Entry) {
863 DPRINT("Range not locked %wZ\n", &FileObject->FileName);
865 }
866
867 DPRINT("Found lock entry: Exclusive %u %08x%08x:%08x%08x %wZ\n",
868 Entry->Exclusive.FileLock.ExclusiveLock,
869 Entry->Exclusive.FileLock.StartingByte.HighPart,
870 Entry->Exclusive.FileLock.StartingByte.LowPart,
871 Entry->Exclusive.FileLock.EndingByte.HighPart,
872 Entry->Exclusive.FileLock.EndingByte.LowPart,
873 &FileObject->FileName);
874
875 if (Entry->Exclusive.FileLock.ExclusiveLock)
876 {
877 if (Entry->Exclusive.FileLock.Key != Key ||
878 Entry->Exclusive.FileLock.ProcessId != Process ||
879 Entry->Exclusive.FileLock.StartingByte.QuadPart != FileOffset->QuadPart ||
880 Entry->Exclusive.FileLock.EndingByte.QuadPart !=
881 FileOffset->QuadPart + Length->QuadPart)
882 {
883 DPRINT("Range not locked %wZ\n", &FileObject->FileName);
885 }
886 RtlCopyMemory(&Find, Entry, sizeof(Find));
887 // Remove the old exclusive lock region
889 }
890 else
891 {
892 DPRINT("Shared lock %wZ Start %08x%08x End %08x%08x\n",
893 &FileObject->FileName,
894 Entry->Exclusive.FileLock.StartingByte.HighPart,
895 Entry->Exclusive.FileLock.StartingByte.LowPart,
896 Entry->Exclusive.FileLock.EndingByte.HighPart,
897 Entry->Exclusive.FileLock.EndingByte.LowPart);
898 for (SharedEntry = InternalInfo->SharedLocks.Flink;
899 SharedEntry != &InternalInfo->SharedLocks;
900 SharedEntry = SharedEntry->Flink)
901 {
902 SharedRange = CONTAINING_RECORD(SharedEntry, LOCK_SHARED_RANGE, Entry);
903 if (SharedRange->Start.QuadPart == FileOffset->QuadPart &&
904 SharedRange->End.QuadPart == FileOffset->QuadPart + Length->QuadPart &&
905 SharedRange->Key == Key &&
906 SharedRange->ProcessId == Process)
907 {
908 FoundShared = TRUE;
909 DPRINT("Found shared element to delete %wZ Start %08x%08x End %08x%08x Key %x\n",
910 &FileObject->FileName,
911 SharedRange->Start.HighPart,
912 SharedRange->Start.LowPart,
913 SharedRange->End.HighPart,
914 SharedRange->End.LowPart,
915 SharedRange->Key);
916 break;
917 }
918 }
919 if (FoundShared)
920 {
921 /* Remove the found range from the shared range lists */
922 RemoveEntryList(&SharedRange->Entry);
923 ExFreePoolWithTag(SharedRange, TAG_RANGE);
924 /* We need to rebuild the list of shared ranges. */
925 DPRINT("Removing the lock entry %wZ (%08x%08x:%08x%08x)\n",
926 &FileObject->FileName,
927 Entry->Exclusive.FileLock.StartingByte.HighPart,
928 Entry->Exclusive.FileLock.StartingByte.LowPart,
929 Entry->Exclusive.FileLock.EndingByte.HighPart,
930 Entry->Exclusive.FileLock.EndingByte.LowPart);
931
932 /* Remember what was in there and remove it from the table */
933 Find = *Entry;
934 RtlDeleteElementGenericTable(&InternalInfo->RangeTable, &Find);
935 /* Put shared locks back in place */
936 for (SharedEntry = InternalInfo->SharedLocks.Flink;
937 SharedEntry != &InternalInfo->SharedLocks;
938 SharedEntry = SharedEntry->Flink)
939 {
940 COMBINED_LOCK_ELEMENT LockElement;
941 SharedRange = CONTAINING_RECORD(SharedEntry, LOCK_SHARED_RANGE, Entry);
943 LockElement.Exclusive.FileLock.StartingByte = SharedRange->Start;
944 LockElement.Exclusive.FileLock.EndingByte = SharedRange->End;
945 LockElement.Exclusive.FileLock.ProcessId = SharedRange->ProcessId;
946 LockElement.Exclusive.FileLock.Key = SharedRange->Key;
948
949 if (LockCompare(&InternalInfo->RangeTable, &Find, &LockElement) != GenericEqual)
950 {
951 DPRINT("Skipping range %08x%08x:%08x%08x\n",
956 continue;
957 }
958 DPRINT("Re-creating range %08x%08x:%08x%08x\n",
963 FsRtlpRebuildSharedLockRange(FileLock, InternalInfo, &LockElement);
964 }
965 }
966 else
967 {
969 }
970 }
971
972#ifndef NDEBUG
973 DPRINT("Lock still has:\n");
974 for (SharedEntry = InternalInfo->SharedLocks.Flink;
975 SharedEntry != &InternalInfo->SharedLocks;
976 SharedEntry = SharedEntry->Flink)
977 {
978 SharedRange = CONTAINING_RECORD(SharedEntry, LOCK_SHARED_RANGE, Entry);
979 DPRINT("Shared element %wZ Offset %08x%08x Length %08x%08x Key %x\n",
980 &FileObject->FileName,
981 SharedRange->Start.HighPart,
982 SharedRange->Start.LowPart,
983 SharedRange->End.HighPart,
984 SharedRange->End.LowPart,
985 SharedRange->Key);
986 }
987#endif
988
989 // this is definitely the thing we want
990 InternalInfo->Generation++;
991 while ((NextMatchingLockIrp = IoCsqRemoveNextIrp(&InternalInfo->Csq, &Find)))
992 {
994 if (NextMatchingLockIrp->IoStatus.Information == InternalInfo->Generation)
995 {
996 // We've already looked at this one, meaning that we looped.
997 // Put it back and exit.
999 (&InternalInfo->Csq,
1000 NextMatchingLockIrp,
1001 NULL,
1002 NULL);
1003 break;
1004 }
1005 // Got a new lock irp... try to do the new lock operation
1006 // Note that we pick an operation that would succeed at the time
1007 // we looked, but can't guarantee that it won't just be re-queued
1008 // because somebody else snatched part of the range in a new thread.
1009 DPRINT("Locking another IRP %p for %p %wZ\n",
1010 NextMatchingLockIrp, FileLock, &FileObject->FileName);
1011 Status = FsRtlProcessFileLock(InternalInfo->BelongsTo, NextMatchingLockIrp, NULL);
1012 if (!NT_SUCCESS(Status))
1013 return Status;
1014 }
1015
1016 DPRINT("Success %wZ\n", &FileObject->FileName);
1017 return STATUS_SUCCESS;
1018}
1019
1020/*
1021 * @implemented
1022 */
1024NTAPI
1029{
1030 PLIST_ENTRY ListEntry;
1032 PLOCK_INFORMATION InternalInfo = FileLock->LockInformation;
1033 DPRINT("FsRtlFastUnlockAll(%wZ)\n", &FileObject->FileName);
1034 // XXX Synchronize somehow
1035 if (!FileLock->LockInformation) {
1036 DPRINT("Not locked %wZ\n", &FileObject->FileName);
1037 return STATUS_RANGE_NOT_LOCKED; // no locks
1038 }
1039 for (ListEntry = InternalInfo->SharedLocks.Flink;
1040 ListEntry != &InternalInfo->SharedLocks;)
1041 {
1044 Length.QuadPart = Range->End.QuadPart - Range->Start.QuadPart;
1045 ListEntry = ListEntry->Flink;
1046 if (Range->ProcessId != Process)
1047 continue;
1049 (FileLock,
1050 FileObject,
1051 &Range->Start,
1052 &Length,
1053 Range->ProcessId,
1054 Range->Key,
1055 Context,
1056 TRUE);
1057 }
1058 for (Entry = RtlEnumerateGenericTable(&InternalInfo->RangeTable, TRUE);
1059 Entry;
1061 {
1063 // We'll take the first one to be the list head, and free the others first...
1064 Length.QuadPart =
1065 Entry->Exclusive.FileLock.EndingByte.QuadPart -
1066 Entry->Exclusive.FileLock.StartingByte.QuadPart;
1068 (FileLock,
1069 Entry->Exclusive.FileLock.FileObject,
1070 &Entry->Exclusive.FileLock.StartingByte,
1071 &Length,
1072 Entry->Exclusive.FileLock.ProcessId,
1073 Entry->Exclusive.FileLock.Key,
1074 Context,
1075 TRUE);
1076 }
1077 DPRINT("Done %wZ\n", &FileObject->FileName);
1078 return STATUS_SUCCESS;
1079}
1080
1081/*
1082 * @implemented
1083 */
1085NTAPI
1089 IN ULONG Key,
1091{
1092 PLIST_ENTRY ListEntry;
1094 PLOCK_INFORMATION InternalInfo = FileLock->LockInformation;
1095
1096 DPRINT("FsRtlFastUnlockAllByKey(%wZ,Key %x)\n", &FileObject->FileName, Key);
1097
1098 // XXX Synchronize somehow
1099 if (!FileLock->LockInformation) return STATUS_RANGE_NOT_LOCKED; // no locks
1100 for (ListEntry = InternalInfo->SharedLocks.Flink;
1101 ListEntry != &InternalInfo->SharedLocks;)
1102 {
1105 Length.QuadPart = Range->End.QuadPart - Range->Start.QuadPart;
1106 ListEntry = ListEntry->Flink;
1107 if (Range->ProcessId != Process ||
1108 Range->Key != Key)
1109 continue;
1111 (FileLock,
1112 FileObject,
1113 &Range->Start,
1114 &Length,
1115 Range->ProcessId,
1116 Range->Key,
1117 Context,
1118 TRUE);
1119 }
1120 for (Entry = RtlEnumerateGenericTable(&InternalInfo->RangeTable, TRUE);
1121 Entry;
1123 {
1125 // We'll take the first one to be the list head, and free the others first...
1126 Length.QuadPart =
1127 Entry->Exclusive.FileLock.EndingByte.QuadPart -
1128 Entry->Exclusive.FileLock.StartingByte.QuadPart;
1129 if (Entry->Exclusive.FileLock.Key == Key &&
1130 Entry->Exclusive.FileLock.ProcessId == Process)
1131 {
1133 (FileLock,
1134 Entry->Exclusive.FileLock.FileObject,
1135 &Entry->Exclusive.FileLock.StartingByte,
1136 &Length,
1137 Entry->Exclusive.FileLock.ProcessId,
1138 Entry->Exclusive.FileLock.Key,
1139 Context,
1140 TRUE);
1141 }
1142 }
1143
1144 return STATUS_SUCCESS;
1145}
1146
1147/*
1148 * @implemented
1149 */
1151NTAPI
1153 IN PIRP Irp,
1155{
1156 PIO_STACK_LOCATION IoStackLocation;
1159
1160 /* Get the I/O Stack location */
1161 IoStackLocation = IoGetCurrentIrpStackLocation(Irp);
1162 ASSERT(IoStackLocation->MajorFunction == IRP_MJ_LOCK_CONTROL);
1163
1164 /* Clear the I/O status block and check what function this is */
1166
1167 DPRINT("FsRtlProcessFileLock(%wZ, MinorFunction %x)\n",
1168 &IoStackLocation->FileObject->FileName,
1169 IoStackLocation->MinorFunction);
1170
1171 switch(IoStackLocation->MinorFunction)
1172 {
1173 /* A lock */
1174 case IRP_MN_LOCK:
1175 {
1176 /* Call the private lock routine */
1177 BOOLEAN Result = FsRtlPrivateLock(FileLock,
1178 IoStackLocation->FileObject,
1179 &IoStackLocation->Parameters.LockControl.ByteOffset,
1180 IoStackLocation->Parameters.LockControl.Length,
1182 IoStackLocation->Parameters.LockControl.Key,
1183 IoStackLocation->Flags & SL_FAIL_IMMEDIATELY,
1184 IoStackLocation->Flags & SL_EXCLUSIVE_LOCK,
1186 Irp,
1187 Context,
1188 FALSE);
1189 /* FsRtlPrivateLock has _Must_inspect_result_. Just check this is consistent on debug builds */
1191 (void)Result;
1192 return IoStatusBlock.Status;
1193 }
1194 /* A single unlock */
1196
1197 /* Call fast unlock */
1199 FsRtlFastUnlockSingle(FileLock,
1200 IoStackLocation->FileObject,
1201 &IoStackLocation->Parameters.LockControl.
1202 ByteOffset,
1203 IoStackLocation->Parameters.LockControl.
1204 Length,
1206 IoStackLocation->Parameters.LockControl.
1207 Key,
1208 Context,
1209 FALSE);
1210 break;
1211
1212 /* Total unlock */
1213 case IRP_MN_UNLOCK_ALL:
1214
1215 /* Do a fast unlock */
1217 IoStackLocation->
1218 FileObject,
1220 Context);
1221 break;
1222
1223 /* Unlock by key */
1225
1226 /* Do it */
1228 FsRtlFastUnlockAllByKey(FileLock,
1229 IoStackLocation->FileObject,
1231 IoStackLocation->Parameters.
1232 LockControl.Key,
1233 Context);
1234 break;
1235
1236 /* Invalid request */
1237 default:
1238
1239 /* Complete it */
1243 }
1244
1245 /* Return the status */
1246 DPRINT("Lock IRP %p %x\n", Irp, IoStatusBlock.Status);
1248 (FileLock->CompleteLockIrpRoutine,
1249 Context,
1250 Irp,
1252 &Status,
1253 NULL);
1254 return IoStatusBlock.Status;
1255}
1256
1257/*
1258 * @implemented
1259 */
1260VOID
1261NTAPI
1265{
1266 /* Setup the lock */
1267 RtlZeroMemory(FileLock, sizeof(*FileLock));
1268 FileLock->FastIoIsQuestionable = FALSE;
1269 FileLock->CompleteLockIrpRoutine = CompleteLockIrpRoutine;
1270 FileLock->UnlockRoutine = UnlockRoutine;
1271 FileLock->LockInformation = NULL;
1272}
1273
1274/*
1275 * @implemented
1276 */
1277VOID
1278NTAPI
1280{
1281 if (FileLock->LockInformation)
1282 {
1283 PIRP Irp;
1284 PLOCK_INFORMATION InternalInfo = FileLock->LockInformation;
1286 PLIST_ENTRY SharedEntry;
1287 PLOCK_SHARED_RANGE SharedRange;
1288 // MSDN: this completes any remaining lock IRPs
1289 for (SharedEntry = InternalInfo->SharedLocks.Flink;
1290 SharedEntry != &InternalInfo->SharedLocks;)
1291 {
1292 SharedRange = CONTAINING_RECORD(SharedEntry, LOCK_SHARED_RANGE, Entry);
1293 SharedEntry = SharedEntry->Flink;
1294 RemoveEntryList(&SharedRange->Entry);
1295 ExFreePoolWithTag(SharedRange, TAG_RANGE);
1296 }
1297 while ((Entry = RtlGetElementGenericTable(&InternalInfo->RangeTable, 0)) != NULL)
1298 {
1300 }
1301 while ((Irp = IoCsqRemoveNextIrp(&InternalInfo->Csq, NULL)) != NULL)
1302 {
1304 /* FsRtlProcessFileLock has _Must_inspect_result_ */
1306 (void)Status;
1307 }
1308 ExFreePoolWithTag(InternalInfo, TAG_FLOCK);
1309 FileLock->LockInformation = NULL;
1310 }
1311}
1312
1313/*
1314 * @implemented
1315 */
1317NTAPI
1320{
1321 PFILE_LOCK FileLock;
1322
1323 /* Try to allocate it */
1324 FileLock = ExAllocateFromPagedLookasideList(&FsRtlFileLockLookasideList);
1325 if (FileLock)
1326 {
1327 /* Initialize it */
1328 FsRtlInitializeFileLock(FileLock,
1331 }
1332
1333 /* Return the lock */
1334 return FileLock;
1335}
1336
1337/*
1338 * @implemented
1339 */
1340VOID
1341NTAPI
1343{
1344 /* Uninitialize and free the lock */
1345 FsRtlUninitializeFileLock(FileLock);
1346 ExFreeToPagedLookasideList(&FsRtlFileLockLookasideList, FileLock);
1347}
static PIO_STACK_LOCATION IoGetCurrentIrpStackLocation(PIRP Irp)
unsigned char BOOLEAN
LONG NTSTATUS
Definition: precomp.h:26
return Found
Definition: dirsup.c:1270
_In_ PFCB _In_ LONGLONG FileOffset
Definition: cdprocs.h:160
Definition: ehthrow.cxx:93
Definition: ehthrow.cxx:54
Definition: bufpool.h:45
_In_ PIRP Irp
Definition: csq.h:116
_In_ PIRP _In_ PVOID InsertContext
Definition: csq.h:258
_In_opt_ PIRP _In_opt_ PVOID PeekContext
Definition: csq.h:160
_Out_ PKIRQL Irql
Definition: csq.h:179
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
NTKERNELAPI NTSTATUS NTAPI IoCsqInsertIrpEx(_Inout_ PIO_CSQ Csq, _Inout_ PIRP Irp, _Out_opt_ PIO_CSQ_IRP_CONTEXT Context, _In_opt_ PVOID InsertContext)
Insert an IRP into the CSQ, with additional tracking context.
Definition: csq.c:205
NTKERNELAPI PIRP NTAPI IoCsqRemoveNextIrp(_Inout_ PIO_CSQ Csq, _In_opt_ PVOID PeekContext)
IoCsqRemoveNextIrp - Removes the next IRP from the queue.
Definition: csq.c:398
IO_CSQ Csq
Definition: csqrtns.c:46
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
#define RemoveEntryList(Entry)
Definition: env_spec_w32.h:986
#define InsertTailList(ListHead, Entry)
#define ExAllocatePoolWithTag(hernya, size, tag)
Definition: env_spec_w32.h:350
UCHAR KIRQL
Definition: env_spec_w32.h:591
ULONG KSPIN_LOCK
Definition: env_spec_w32.h:72
#define KeReleaseSpinLock(sl, irql)
Definition: env_spec_w32.h:627
#define KeAcquireSpinLock(sl, irql)
Definition: env_spec_w32.h:609
KIRQL * PKIRQL
Definition: env_spec_w32.h:592
#define NonPagedPool
Definition: env_spec_w32.h:307
#define InitializeListHead(ListHead)
Definition: env_spec_w32.h:944
#define KeInitializeSpinLock(sl)
Definition: env_spec_w32.h:604
IN PLARGE_INTEGER IN PLARGE_INTEGER PEPROCESS ULONG BOOLEAN BOOLEAN ExclusiveLock
Definition: fatprocs.h:2714
IN PLARGE_INTEGER IN PLARGE_INTEGER PEPROCESS ULONG BOOLEAN FailImmediately
Definition: fatprocs.h:2713
IN PDCB IN PCCB IN VBO IN OUT PULONG OUT PDIRENT OUT PBCB OUT PVBO ByteOffset
Definition: fatprocs.h:731
VOID NTAPI FsRtlpExpandLockElement(PCOMBINED_LOCK_ELEMENT ToExpand, PCOMBINED_LOCK_ELEMENT Conflict)
Definition: filelock.c:268
PFILE_LOCK_INFO NTAPI FsRtlGetNextFileLock(IN PFILE_LOCK FileLock, IN BOOLEAN Restart)
Definition: filelock.c:255
BOOLEAN NTAPI FsRtlFastCheckLockForWrite(IN PFILE_LOCK FileLock, IN PLARGE_INTEGER FileOffset, IN PLARGE_INTEGER Length, IN ULONG Key, IN PFILE_OBJECT FileObject, IN PVOID Process)
Definition: filelock.c:782
struct _LOCK_INFORMATION LOCK_INFORMATION
static VOID NTAPI LockCompleteCanceledIrp(PIO_CSQ Csq, PIRP Irp)
Definition: filelock.c:204
static VOID NTAPI LockAcquireQueueLock(PIO_CSQ Csq, PKIRQL Irql)
Definition: filelock.c:190
union _COMBINED_LOCK_ELEMENT COMBINED_LOCK_ELEMENT
union _COMBINED_LOCK_ELEMENT * PCOMBINED_LOCK_ELEMENT
VOID NTAPI FsRtlInitializeFileLock(IN PFILE_LOCK FileLock, IN PCOMPLETE_LOCK_IRP_ROUTINE CompleteLockIrpRoutine OPTIONAL, IN PUNLOCK_ROUTINE UnlockRoutine OPTIONAL)
Definition: filelock.c:1262
static PVOID NTAPI LockAllocate(PRTL_GENERIC_TABLE Table, CLONG Bytes)
Definition: filelock.c:67
BOOLEAN NTAPI FsRtlCheckLockForWriteAccess(IN PFILE_LOCK FileLock, IN PIRP Irp)
Definition: filelock.c:710
PCOMBINED_LOCK_ELEMENT NTAPI FsRtlpRebuildSharedLockRange(PFILE_LOCK FileLock, PLOCK_INFORMATION LockInfo, PCOMBINED_LOCK_ELEMENT Conflict)
Definition: filelock.c:290
PAGED_LOOKASIDE_LIST FsRtlFileLockLookasideList
Definition: filelock.c:17
VOID NTAPI FsRtlUninitializeFileLock(IN PFILE_LOCK FileLock)
Definition: filelock.c:1279
NTSTATUS NTAPI FsRtlFastUnlockSingle(IN PFILE_LOCK FileLock, IN PFILE_OBJECT FileObject, IN PLARGE_INTEGER FileOffset, IN PLARGE_INTEGER Length, IN PEPROCESS Process, IN ULONG Key, IN PVOID Context OPTIONAL, IN BOOLEAN AlreadySynchronized)
Definition: filelock.c:825
struct _LOCK_SHARED_RANGE LOCK_SHARED_RANGE
BOOLEAN NTAPI FsRtlPrivateLock(IN PFILE_LOCK FileLock, IN PFILE_OBJECT FileObject, IN PLARGE_INTEGER FileOffset, IN PLARGE_INTEGER Length, IN PEPROCESS Process, IN ULONG Key, IN BOOLEAN FailImmediately, IN BOOLEAN ExclusiveLock, OUT PIO_STATUS_BLOCK IoStatus, IN PIRP Irp OPTIONAL, IN PVOID Context OPTIONAL, IN BOOLEAN AlreadySynchronized)
Definition: filelock.c:324
static VOID NTAPI LockReleaseQueueLock(PIO_CSQ Csq, KIRQL Irql)
Definition: filelock.c:197
NTSTATUS NTAPI FsRtlProcessFileLock(IN PFILE_LOCK FileLock, IN PIRP Irp, IN PVOID Context OPTIONAL)
Definition: filelock.c:1152
PFILE_LOCK NTAPI FsRtlAllocateFileLock(IN PCOMPLETE_LOCK_IRP_ROUTINE CompleteLockIrpRoutine OPTIONAL, IN PUNLOCK_ROUTINE UnlockRoutine OPTIONAL)
Definition: filelock.c:1318
NTSTATUS NTAPI FsRtlFastUnlockAll(IN PFILE_LOCK FileLock, IN PFILE_OBJECT FileObject, IN PEPROCESS Process, IN PVOID Context OPTIONAL)
Definition: filelock.c:1025
static VOID NTAPI LockRemoveIrp(PIO_CSQ Csq, PIRP Irp)
Definition: filelock.c:130
static PIRP NTAPI LockPeekNextIrp(PIO_CSQ Csq, PIRP Irp, PVOID PeekContext)
Definition: filelock.c:135
BOOLEAN NTAPI FsRtlFastCheckLockForRead(IN PFILE_LOCK FileLock, IN PLARGE_INTEGER FileOffset, IN PLARGE_INTEGER Length, IN ULONG Key, IN PFILE_OBJECT FileObject, IN PVOID Process)
Definition: filelock.c:748
BOOLEAN NTAPI FsRtlCheckLockForReadAccess(IN PFILE_LOCK FileLock, IN PIRP Irp)
Definition: filelock.c:672
struct _LOCK_INFORMATION * PLOCK_INFORMATION
VOID NTAPI FsRtlCompleteLockIrpReal(IN PCOMPLETE_LOCK_IRP_ROUTINE CompleteRoutine, IN PVOID Context, IN PIRP Irp, IN NTSTATUS Status, OUT PNTSTATUS NewStatus, IN PFILE_OBJECT FileObject OPTIONAL)
Definition: filelock.c:220
static RTL_GENERIC_COMPARE_RESULTS NTAPI LockCompare(PRTL_GENERIC_TABLE Table, PVOID PtrA, PVOID PtrB)
Definition: filelock.c:82
VOID NTAPI FsRtlFreeFileLock(IN PFILE_LOCK FileLock)
Definition: filelock.c:1342
NTSTATUS NTAPI FsRtlFastUnlockAllByKey(IN PFILE_LOCK FileLock, IN PFILE_OBJECT FileObject, IN PEPROCESS Process, IN ULONG Key, IN PVOID Context OPTIONAL)
Definition: filelock.c:1086
struct _LOCK_SHARED_RANGE * PLOCK_SHARED_RANGE
static NTSTATUS NTAPI LockInsertIrpEx(PIO_CSQ Csq, PIRP Irp, PVOID InsertContext)
Definition: filelock.c:121
static VOID NTAPI LockFree(PRTL_GENERIC_TABLE Table, PVOID Buffer)
Definition: filelock.c:75
_Must_inspect_result_ _In_opt_ PUNLOCK_ROUTINE UnlockRoutine
Definition: fltkernel.h:2123
_In_ PFILE_OBJECT _In_ PLARGE_INTEGER _In_ PLARGE_INTEGER _In_ PEPROCESS _In_ ULONG _In_opt_ PVOID _In_ BOOLEAN AlreadySynchronized
Definition: fsrtlfuncs.h:271
_In_opt_ PCOMPLETE_LOCK_IRP_ROUTINE CompleteLockIrpRoutine
Definition: fsrtlfuncs.h:139
#define FsRtlCompleteRequest(IRP, STATUS)
Definition: fsrtlfuncs.h:1711
_Must_inspect_result_ _In_ PLARGE_INTEGER _In_ PLARGE_INTEGER _In_ ULONG _In_ PFILE_OBJECT _In_ PVOID Process
Definition: fsrtlfuncs.h:223
NTSTATUS(NTAPI * PCOMPLETE_LOCK_IRP_ROUTINE)(_In_ PVOID Context, _In_ PIRP Irp)
Definition: fsrtltypes.h:183
VOID(NTAPI * PUNLOCK_ROUTINE)(_In_ PVOID Context, _In_ PFILE_LOCK_INFO FileLockInfo)
Definition: fsrtltypes.h:198
Status
Definition: gdiplustypes.h:25
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
ASMGENDATA Table[]
Definition: genincdata.c:61
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
IoMarkIrpPending(Irp)
_In_ UINT Bytes
Definition: mmcopy.h:9
#define ASSERT(a)
Definition: mode.c:44
#define ExFreePoolWithTag(_P, _T)
Definition: module.h:1109
* PNTSTATUS
Definition: strlen.c:14
static OUT PIO_STATUS_BLOCK IoStatusBlock
Definition: pipe.c:75
__in UCHAR __in POWER_STATE __in_opt PVOID __in PIO_STATUS_BLOCK IoStatus
Definition: mxum.h:159
_In_ ULONG _In_ ULONG _In_ ULONG Length
Definition: ntddpcm.h:102
PEPROCESS NTAPI IoGetRequestorProcess(IN PIRP Irp)
Definition: irp.c:1782
#define STATUS_FILE_LOCK_CONFLICT
Definition: ntstatus.h:320
#define STATUS_PENDING
Definition: ntstatus.h:82
#define STATUS_RANGE_NOT_LOCKED
Definition: ntstatus.h:362
#define STATUS_NO_MEMORY
Definition: ntstatus.h:260
#define IRP_MJ_LOCK_CONTROL
Definition: rdpdr.c:53
@ Restart
Definition: sacdrv.h:269
#define STATUS_SUCCESS
Definition: shellext.h:65
#define DPRINT
Definition: sndvol32.h:71
PULONG MinorVersion OPTIONAL
Definition: CrossNt.h:68
base of all file and directory entries
Definition: entries.h:83
FILE_LOCK_INFO FileLock
BOOLEAN ExclusiveLock
Definition: fsrtltypes.h:190
LARGE_INTEGER EndingByte
Definition: fsrtltypes.h:194
LARGE_INTEGER StartingByte
Definition: fsrtltypes.h:188
PFILE_OBJECT FileObject
Definition: fsrtltypes.h:192
PVOID LockInformation
Definition: fsrtltypes.h:207
PCOMPLETE_LOCK_IRP_ROUTINE CompleteLockIrpRoutine
Definition: fsrtltypes.h:203
Definition: csq.h:222
PFILE_OBJECT FileObject
Definition: iotypes.h:3169
union _IO_STACK_LOCATION::@1564 Parameters
struct _IO_STACK_LOCATION::@3978::@3983 Write
struct _IO_STACK_LOCATION::@3978::@3994 LockControl
ULONG POINTER_ALIGNMENT Key
Definition: iotypes.h:3139
struct _IO_STACK_LOCATION::@3978::@3982 Read
IO_STATUS_BLOCK IoStatus
Definition: typedefs.h:120
struct _LIST_ENTRY * Flink
Definition: typedefs.h:121
ULONG Generation
Definition: filelock.c:41
KSPIN_LOCK CsqLock
Definition: filelock.c:37
RTL_GENERIC_TABLE RangeTable
Definition: filelock.c:35
PFILE_LOCK BelongsTo
Definition: filelock.c:39
LIST_ENTRY CsqList
Definition: filelock.c:38
LIST_ENTRY SharedLocks
Definition: filelock.c:40
LARGE_INTEGER End
Definition: filelock.c:48
LARGE_INTEGER Start
Definition: filelock.c:48
LIST_ENTRY Entry
Definition: filelock.c:47
ULONGLONG QuadPart
Definition: ms-dtyp.idl:185
Definition: range.c:39
#define TAG_TABLE
Definition: tag.h:48
#define TAG_FLOCK
Definition: tag.h:50
#define TAG_RANGE
Definition: tag.h:49
#define NTAPI
Definition: typedefs.h:36
#define RtlCopyMemory(Destination, Source, Length)
Definition: typedefs.h:263
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:262
#define IN
Definition: typedefs.h:39
#define CONTAINING_RECORD(address, type, field)
Definition: typedefs.h:260
uint32_t ULONG
Definition: typedefs.h:59
#define OUT
Definition: typedefs.h:40
#define STATUS_INVALID_DEVICE_REQUEST
Definition: udferr_usr.h:138
#define STATUS_INVALID_PARAMETER
Definition: udferr_usr.h:135
#define STATUS_CANCELLED
Definition: udferr_usr.h:170
ULONG CLONG
Definition: umtypes.h:126
FILE_SHARED_LOCK_ENTRY Shared
Definition: filelock.c:27
FILE_EXCLUSIVE_LOCK_ENTRY Exclusive
Definition: filelock.c:29
LIST_ENTRY dummy
Definition: filelock.c:26
LONGLONG QuadPart
Definition: typedefs.h:114
ULONG LowPart
Definition: typedefs.h:106
_In_ WDFREQUEST _In_ WDFFILEOBJECT FileObject
Definition: wdfdevice.h:550
_At_(*)(_In_ PWSK_CLIENT Client, _In_opt_ PUNICODE_STRING NodeName, _In_opt_ PUNICODE_STRING ServiceName, _In_opt_ ULONG NameSpace, _In_opt_ GUID *Provider, _In_opt_ PADDRINFOEXW Hints, _Outptr_ PADDRINFOEXW *Result, _In_opt_ PEPROCESS OwningProcess, _In_opt_ PETHREAD OwningThread, _Inout_ PIRP Irp Result)(Mem)) NTSTATUS(WSKAPI *PFN_WSK_GET_ADDRESS_INFO
Definition: wsk.h:409
struct LOOKASIDE_ALIGN _PAGED_LOOKASIDE_LIST PAGED_LOOKASIDE_LIST
#define IRP_MN_UNLOCK_ALL
Definition: iotypes.h:4412
#define IRP_MN_LOCK
Definition: iotypes.h:4410
* PFILE_OBJECT
Definition: iotypes.h:1998
#define IRP_MN_UNLOCK_ALL_BY_KEY
Definition: iotypes.h:4413
#define SL_FAIL_IMMEDIATELY
Definition: iotypes.h:1832
#define IRP_MN_UNLOCK_SINGLE
Definition: iotypes.h:4411
#define SL_EXCLUSIVE_LOCK
Definition: iotypes.h:1833
NTSYSAPI BOOLEAN NTAPI RtlDeleteElementGenericTable(_In_ PRTL_GENERIC_TABLE Table, _In_ PVOID Buffer)
#define NT_ASSERT
Definition: rtlfuncs.h:3310
NTSYSAPI PVOID NTAPI RtlInsertElementGenericTable(_In_ PRTL_GENERIC_TABLE Table, _In_reads_bytes_(BufferSize) PVOID Buffer, _In_ CLONG BufferSize, _Out_opt_ PBOOLEAN NewElement)
_Must_inspect_result_ NTSYSAPI PVOID NTAPI RtlEnumerateGenericTable(_In_ PRTL_GENERIC_TABLE Table, _In_ BOOLEAN Restart)
_Must_inspect_result_ NTSYSAPI PVOID NTAPI RtlGetElementGenericTable(_In_ PRTL_GENERIC_TABLE Table, _In_ ULONG I)
NTSYSAPI ULONG NTAPI RtlNumberGenericTableElements(_In_ PRTL_GENERIC_TABLE Table)
_Must_inspect_result_ NTSYSAPI PVOID NTAPI RtlLookupElementGenericTable(_In_ PRTL_GENERIC_TABLE Table, _In_ PVOID Buffer)
@ GenericLessThan
Definition: rtltypes.h:376
@ GenericEqual
Definition: rtltypes.h:378
@ GenericGreaterThan
Definition: rtltypes.h:377
enum _RTL_GENERIC_COMPARE_RESULTS RTL_GENERIC_COMPARE_RESULTS