ReactOS 0.4.17-dev-573-g8315b8c
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{
680 DPRINT("CheckLockForReadAccess(%wZ, Offset %08x%08x, Length %x)\n",
681 &IoStack->FileObject->FileName,
682 IoStack->Parameters.Read.ByteOffset.HighPart,
683 IoStack->Parameters.Read.ByteOffset.LowPart,
684 IoStack->Parameters.Read.Length);
685 if (!FileLock->LockInformation) {
686 DPRINT("CheckLockForReadAccess(%wZ) => TRUE\n", &IoStack->FileObject->FileName);
687 return TRUE;
688 }
689 ToFind.Exclusive.FileLock.StartingByte = IoStack->Parameters.Read.ByteOffset;
692 IoStack->Parameters.Read.Length;
694 (FileLock->LockInformation,
695 &ToFind);
696 if (!Found) {
697 DPRINT("CheckLockForReadAccess(%wZ) => TRUE\n", &IoStack->FileObject->FileName);
698 return TRUE;
699 }
700 Result = !Found->Exclusive.FileLock.ExclusiveLock ||
701 (IoStack->Parameters.Read.Key == Found->Exclusive.FileLock.Key &&
702 Process == Found->Exclusive.FileLock.ProcessId);
703 DPRINT("CheckLockForReadAccess(%wZ) => %s\n", &IoStack->FileObject->FileName, Result ? "TRUE" : "FALSE");
704 return Result;
705}
706
707/*
708 * @implemented
709 */
711NTAPI
713 IN PIRP Irp)
714{
719 PEPROCESS Process = Irp->Tail.Overlay.Thread->ThreadsProcess;
720 DPRINT("CheckLockForWriteAccess(%wZ, Offset %08x%08x, Length %x)\n",
721 &IoStack->FileObject->FileName,
722 IoStack->Parameters.Write.ByteOffset.HighPart,
723 IoStack->Parameters.Write.ByteOffset.LowPart,
724 IoStack->Parameters.Write.Length);
725 if (!FileLock->LockInformation) {
726 DPRINT("CheckLockForWriteAccess(%wZ) => TRUE\n", &IoStack->FileObject->FileName);
727 return TRUE;
728 }
729 ToFind.Exclusive.FileLock.StartingByte = IoStack->Parameters.Write.ByteOffset;
732 IoStack->Parameters.Write.Length;
734 (FileLock->LockInformation,
735 &ToFind);
736 if (!Found) {
737 DPRINT("CheckLockForWriteAccess(%wZ) => TRUE\n", &IoStack->FileObject->FileName);
738 return TRUE;
739 }
740 Result = Process == Found->Exclusive.FileLock.ProcessId;
741 DPRINT("CheckLockForWriteAccess(%wZ) => %s\n", &IoStack->FileObject->FileName, Result ? "TRUE" : "FALSE");
742 return Result;
743}
744
745/*
746 * @implemented
747 */
749NTAPI
753 IN ULONG Key,
756{
757 PEPROCESS EProcess = Process;
760 DPRINT("FsRtlFastCheckLockForRead(%wZ, Offset %08x%08x, Length %08x%08x, Key %x)\n",
761 &FileObject->FileName,
762 FileOffset->HighPart,
763 FileOffset->LowPart,
764 Length->HighPart,
765 Length->LowPart,
766 Key);
769 FileOffset->QuadPart + Length->QuadPart;
770 if (!FileLock->LockInformation) return TRUE;
772 (FileLock->LockInformation,
773 &ToFind);
774 if (!Found || !Found->Exclusive.FileLock.ExclusiveLock) return TRUE;
775 return Found->Exclusive.FileLock.Key == Key &&
776 Found->Exclusive.FileLock.ProcessId == EProcess;
777}
778
779/*
780 * @implemented
781 */
783NTAPI
787 IN ULONG Key,
790{
792 PEPROCESS EProcess = Process;
795 DPRINT("FsRtlFastCheckLockForWrite(%wZ, Offset %08x%08x, Length %08x%08x, Key %x)\n",
796 &FileObject->FileName,
797 FileOffset->HighPart,
798 FileOffset->LowPart,
799 Length->HighPart,
800 Length->LowPart,
801 Key);
804 FileOffset->QuadPart + Length->QuadPart;
805 if (!FileLock->LockInformation) {
806 DPRINT("CheckForWrite(%wZ) => TRUE\n", &FileObject->FileName);
807 return TRUE;
808 }
810 (FileLock->LockInformation,
811 &ToFind);
812 if (!Found) {
813 DPRINT("CheckForWrite(%wZ) => TRUE\n", &FileObject->FileName);
814 return TRUE;
815 }
816 Result = Found->Exclusive.FileLock.Key == Key &&
817 Found->Exclusive.FileLock.ProcessId == EProcess;
818 DPRINT("CheckForWrite(%wZ) => %s\n", &FileObject->FileName, Result ? "TRUE" : "FALSE");
819 return Result;
820}
821
822/*
823 * @implemented
824 */
826NTAPI
832 IN ULONG Key,
835{
836 BOOLEAN FoundShared = FALSE;
837 PLIST_ENTRY SharedEntry;
838 PLOCK_SHARED_RANGE SharedRange = NULL;
841 PIRP NextMatchingLockIrp;
842 PLOCK_INFORMATION InternalInfo = FileLock->LockInformation;
843 DPRINT("FsRtlFastUnlockSingle(%wZ, Offset %08x%08x (%d), Length %08x%08x (%d), Key %x)\n",
844 &FileObject->FileName,
845 FileOffset->HighPart,
846 FileOffset->LowPart,
847 (int)FileOffset->QuadPart,
848 Length->HighPart,
849 Length->LowPart,
850 (int)Length->QuadPart,
851 Key);
852 // The region to unlock must correspond exactly to a previously locked region
853 // -- msdn
854 // But Windows 2003 doesn't assert on it and simply ignores that parameter
855 // ASSERT(AlreadySynchronized);
858 FileOffset->QuadPart + Length->QuadPart;
859 if (!InternalInfo) {
860 DPRINT("File not previously locked (ever)\n");
862 }
863 Entry = RtlLookupElementGenericTable(&InternalInfo->RangeTable, &Find);
864 if (!Entry) {
865 DPRINT("Range not locked %wZ\n", &FileObject->FileName);
867 }
868
869 DPRINT("Found lock entry: Exclusive %u %08x%08x:%08x%08x %wZ\n",
870 Entry->Exclusive.FileLock.ExclusiveLock,
871 Entry->Exclusive.FileLock.StartingByte.HighPart,
872 Entry->Exclusive.FileLock.StartingByte.LowPart,
873 Entry->Exclusive.FileLock.EndingByte.HighPart,
874 Entry->Exclusive.FileLock.EndingByte.LowPart,
875 &FileObject->FileName);
876
877 if (Entry->Exclusive.FileLock.ExclusiveLock)
878 {
879 if (Entry->Exclusive.FileLock.Key != Key ||
880 Entry->Exclusive.FileLock.ProcessId != Process ||
881 Entry->Exclusive.FileLock.StartingByte.QuadPart != FileOffset->QuadPart ||
882 Entry->Exclusive.FileLock.EndingByte.QuadPart !=
883 FileOffset->QuadPart + Length->QuadPart)
884 {
885 DPRINT("Range not locked %wZ\n", &FileObject->FileName);
887 }
888 RtlCopyMemory(&Find, Entry, sizeof(Find));
889 // Remove the old exclusive lock region
891 }
892 else
893 {
894 DPRINT("Shared lock %wZ Start %08x%08x End %08x%08x\n",
895 &FileObject->FileName,
896 Entry->Exclusive.FileLock.StartingByte.HighPart,
897 Entry->Exclusive.FileLock.StartingByte.LowPart,
898 Entry->Exclusive.FileLock.EndingByte.HighPart,
899 Entry->Exclusive.FileLock.EndingByte.LowPart);
900 for (SharedEntry = InternalInfo->SharedLocks.Flink;
901 SharedEntry != &InternalInfo->SharedLocks;
902 SharedEntry = SharedEntry->Flink)
903 {
904 SharedRange = CONTAINING_RECORD(SharedEntry, LOCK_SHARED_RANGE, Entry);
905 if (SharedRange->Start.QuadPart == FileOffset->QuadPart &&
906 SharedRange->End.QuadPart == FileOffset->QuadPart + Length->QuadPart &&
907 SharedRange->Key == Key &&
908 SharedRange->ProcessId == Process)
909 {
910 FoundShared = TRUE;
911 DPRINT("Found shared element to delete %wZ Start %08x%08x End %08x%08x Key %x\n",
912 &FileObject->FileName,
913 SharedRange->Start.HighPart,
914 SharedRange->Start.LowPart,
915 SharedRange->End.HighPart,
916 SharedRange->End.LowPart,
917 SharedRange->Key);
918 break;
919 }
920 }
921 if (FoundShared)
922 {
923 /* Remove the found range from the shared range lists */
924 RemoveEntryList(&SharedRange->Entry);
925 ExFreePoolWithTag(SharedRange, TAG_RANGE);
926 /* We need to rebuild the list of shared ranges. */
927 DPRINT("Removing the lock entry %wZ (%08x%08x:%08x%08x)\n",
928 &FileObject->FileName,
929 Entry->Exclusive.FileLock.StartingByte.HighPart,
930 Entry->Exclusive.FileLock.StartingByte.LowPart,
931 Entry->Exclusive.FileLock.EndingByte.HighPart,
932 Entry->Exclusive.FileLock.EndingByte.LowPart);
933
934 /* Remember what was in there and remove it from the table */
935 Find = *Entry;
936 RtlDeleteElementGenericTable(&InternalInfo->RangeTable, &Find);
937 /* Put shared locks back in place */
938 for (SharedEntry = InternalInfo->SharedLocks.Flink;
939 SharedEntry != &InternalInfo->SharedLocks;
940 SharedEntry = SharedEntry->Flink)
941 {
942 COMBINED_LOCK_ELEMENT LockElement;
943 SharedRange = CONTAINING_RECORD(SharedEntry, LOCK_SHARED_RANGE, Entry);
945 LockElement.Exclusive.FileLock.StartingByte = SharedRange->Start;
946 LockElement.Exclusive.FileLock.EndingByte = SharedRange->End;
947 LockElement.Exclusive.FileLock.ProcessId = SharedRange->ProcessId;
948 LockElement.Exclusive.FileLock.Key = SharedRange->Key;
950
951 if (LockCompare(&InternalInfo->RangeTable, &Find, &LockElement) != GenericEqual)
952 {
953 DPRINT("Skipping range %08x%08x:%08x%08x\n",
958 continue;
959 }
960 DPRINT("Re-creating range %08x%08x:%08x%08x\n",
965 FsRtlpRebuildSharedLockRange(FileLock, InternalInfo, &LockElement);
966 }
967 }
968 else
969 {
971 }
972 }
973
974#ifndef NDEBUG
975 DPRINT("Lock still has:\n");
976 for (SharedEntry = InternalInfo->SharedLocks.Flink;
977 SharedEntry != &InternalInfo->SharedLocks;
978 SharedEntry = SharedEntry->Flink)
979 {
980 SharedRange = CONTAINING_RECORD(SharedEntry, LOCK_SHARED_RANGE, Entry);
981 DPRINT("Shared element %wZ Offset %08x%08x Length %08x%08x Key %x\n",
982 &FileObject->FileName,
983 SharedRange->Start.HighPart,
984 SharedRange->Start.LowPart,
985 SharedRange->End.HighPart,
986 SharedRange->End.LowPart,
987 SharedRange->Key);
988 }
989#endif
990
991 // this is definitely the thing we want
992 InternalInfo->Generation++;
993 while ((NextMatchingLockIrp = IoCsqRemoveNextIrp(&InternalInfo->Csq, &Find)))
994 {
996 if (NextMatchingLockIrp->IoStatus.Information == InternalInfo->Generation)
997 {
998 // We've already looked at this one, meaning that we looped.
999 // Put it back and exit.
1001 (&InternalInfo->Csq,
1002 NextMatchingLockIrp,
1003 NULL,
1004 NULL);
1005 break;
1006 }
1007 // Got a new lock irp... try to do the new lock operation
1008 // Note that we pick an operation that would succeed at the time
1009 // we looked, but can't guarantee that it won't just be re-queued
1010 // because somebody else snatched part of the range in a new thread.
1011 DPRINT("Locking another IRP %p for %p %wZ\n",
1012 NextMatchingLockIrp, FileLock, &FileObject->FileName);
1013 Status = FsRtlProcessFileLock(InternalInfo->BelongsTo, NextMatchingLockIrp, NULL);
1014 if (!NT_SUCCESS(Status))
1015 return Status;
1016 }
1017
1018 DPRINT("Success %wZ\n", &FileObject->FileName);
1019 return STATUS_SUCCESS;
1020}
1021
1022/*
1023 * @implemented
1024 */
1026NTAPI
1031{
1032 PLIST_ENTRY ListEntry;
1034 PLOCK_INFORMATION InternalInfo = FileLock->LockInformation;
1035 DPRINT("FsRtlFastUnlockAll(%wZ)\n", &FileObject->FileName);
1036 // XXX Synchronize somehow
1037 if (!FileLock->LockInformation) {
1038 DPRINT("Not locked %wZ\n", &FileObject->FileName);
1039 return STATUS_RANGE_NOT_LOCKED; // no locks
1040 }
1041 for (ListEntry = InternalInfo->SharedLocks.Flink;
1042 ListEntry != &InternalInfo->SharedLocks;)
1043 {
1046 Length.QuadPart = Range->End.QuadPart - Range->Start.QuadPart;
1047 ListEntry = ListEntry->Flink;
1048 if (Range->ProcessId != Process)
1049 continue;
1051 (FileLock,
1052 FileObject,
1053 &Range->Start,
1054 &Length,
1055 Range->ProcessId,
1056 Range->Key,
1057 Context,
1058 TRUE);
1059 }
1060 for (Entry = RtlEnumerateGenericTable(&InternalInfo->RangeTable, TRUE);
1061 Entry;
1063 {
1065 if (Entry->Exclusive.FileLock.ProcessId != Process)
1066 continue;
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 */
1089NTAPI
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;
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 */
1155NTAPI
1157 IN PIRP Irp,
1159{
1163
1164 /* Get the I/O Stack location */
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,
1174
1176 {
1177 /* A lock */
1178 case IRP_MN_LOCK:
1179 {
1180 /* Call the private lock routine */
1181 BOOLEAN Result = FsRtlPrivateLock(FileLock,
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 */
1200
1201 /* Call fast unlock */
1203 FsRtlFastUnlockSingle(FileLock,
1206 ByteOffset,
1208 Length,
1211 Key,
1212 Context,
1213 FALSE);
1214 break;
1215
1216 /* Total unlock */
1217 case IRP_MN_UNLOCK_ALL:
1218
1219 /* Do a fast unlock */
1222 FileObject,
1224 Context);
1225 break;
1226
1227 /* Unlock by key */
1229
1230 /* Do it */
1232 FsRtlFastUnlockAllByKey(FileLock,
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 */
1264VOID
1265NTAPI
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 */
1281VOID
1282NTAPI
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 */
1321NTAPI
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,
1335 }
1336
1337 /* Return the lock */
1338 return FileLock;
1339}
1340
1341/*
1342 * @implemented
1343 */
1344VOID
1345NTAPI
1347{
1348 /* Uninitialize and free the lock */
1349 FsRtlUninitializeFileLock(FileLock);
1350 ExFreeToPagedLookasideList(&FsRtlFileLockLookasideList, FileLock);
1351}
static PIO_STACK_LOCATION IoGetCurrentIrpStackLocation(PIRP Irp)
unsigned char BOOLEAN
Definition: actypes.h:127
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 STATUS_NO_MEMORY
Definition: d3dkmdt.h:51
#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:33
#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:2715
IN PLARGE_INTEGER IN PLARGE_INTEGER PEPROCESS ULONG BOOLEAN FailImmediately
Definition: fatprocs.h:2714
IN PDCB IN PCCB IN VBO IN OUT PULONG OUT PDIRENT OUT PBCB OUT PVBO ByteOffset
Definition: fatprocs.h:732
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:784
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:1266
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:712
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:1283
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:827
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:1156
PFILE_LOCK NTAPI FsRtlAllocateFileLock(IN PCOMPLETE_LOCK_IRP_ROUTINE CompleteLockIrpRoutine OPTIONAL, IN PUNLOCK_ROUTINE UnlockRoutine OPTIONAL)
Definition: filelock.c:1322
NTSTATUS NTAPI FsRtlFastUnlockAll(IN PFILE_LOCK FileLock, IN PFILE_OBJECT FileObject, IN PEPROCESS Process, IN PVOID Context OPTIONAL)
Definition: filelock.c:1027
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:750
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:1346
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
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:24
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
__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
static OUT PIO_STATUS_BLOCK IoStatusBlock
Definition: pipe.c:100
PEPROCESS NTAPI IoGetRequestorProcess(IN PIRP Irp)
Definition: irp.c:1782
#define STATUS_FILE_LOCK_CONFLICT
Definition: ntstatus.h:414
#define STATUS_RANGE_NOT_LOCKED
Definition: ntstatus.h:456
#define IRP_MJ_LOCK_CONTROL
Definition: rdpdr.c:53
@ Restart
Definition: sacdrv.h:269
Entry
Definition: section.c:5216
#define STATUS_SUCCESS
Definition: shellext.h:65
#define DPRINT
Definition: sndvol32.h:73
PULONG MinorVersion OPTIONAL
Definition: CrossNt.h:68
_In_ PVOID Context
Definition: storport.h:2269
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:3171
struct _IO_STACK_LOCATION::@4481::@4486 Write
union _IO_STACK_LOCATION::@1709 Parameters
struct _IO_STACK_LOCATION::@4481::@4497 LockControl
ULONG POINTER_ALIGNMENT Key
Definition: iotypes.h:3141
struct _IO_STACK_LOCATION::@4481::@4485 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
#define TAG_TABLE
Definition: tag.h:48
#define TAG_FLOCK
Definition: tag.h:50
#define TAG_RANGE
Definition: tag.h:49
#define STATUS_PENDING
Definition: telnetd.h:14
#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_ PIO_STACK_LOCATION IoStackLocation
Definition: usbdlib.h:265
_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:4415
#define IRP_MN_LOCK
Definition: iotypes.h:4413
* PFILE_OBJECT
Definition: iotypes.h:1998
#define IRP_MN_UNLOCK_ALL_BY_KEY
Definition: iotypes.h:4416
#define SL_FAIL_IMMEDIATELY
Definition: iotypes.h:1832
#define IRP_MN_UNLOCK_SINGLE
Definition: iotypes.h:4414
#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:3327
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:389
@ GenericEqual
Definition: rtltypes.h:391
@ GenericGreaterThan
Definition: rtltypes.h:390
enum _RTL_GENERIC_COMPARE_RESULTS RTL_GENERIC_COMPARE_RESULTS