Fix splitting of cells (noticed by Hartmut).
[reactos.git] / reactos / ntoskrnl / fs / filelock.c
index 8ae196b..a37f5e2 100644 (file)
@@ -1,12 +1,14 @@
-/* $Id: filelock.c,v 1.9 2003/07/11 01:23:14 royce Exp $
+/* $Id$
  *
- * reactos/ntoskrnl/fs/filelock.c
+ * COPYRIGHT:       See COPYING in the top level directory
+ * PROJECT:         ReactOS kernel
+ * FILE:            ntoskrnl/fs/filelock.c
+ * PURPOSE:         No purpose listed.
  *
+ * PROGRAMMERS:     No programmer listed.
  */
-#include <ddk/ntddk.h>
-#include <internal/ifs.h>
-#include <ddk/ntifs.h>
 
+#include <ntoskrnl.h>
 #define NDEBUG
 #include <internal/debug.h>
 
@@ -15,25 +17,61 @@ NOTE:
 I'm not using resource syncronization here, since FsRtlFastCheckLockForRead/Write
 are allowed to be called at DISPATCH_LEVEL. Must therefore use nonpaged memory for
 the lists.
+UPDATE: I'm not sure about this! -Gunnar
 */
 
-#define LOCK_START_OFF(Lock)  ((Lock).StartingByte.QuadPart)
-#define LOCK_END_OFF(Lock)    (((Lock).StartingByte.QuadPart) + ((Lock).Length.QuadPart) - 1)
-#define REQUEST_START_OFF     (FileOffset->QuadPart)
-#define REQUEST_END_OFF       ((FileOffset->QuadPart) + (Length->QuadPart) - 1)
-
 FAST_MUTEX              LockTocMutex;
 NPAGED_LOOKASIDE_LIST   GrantedLookaside;
 NPAGED_LOOKASIDE_LIST   LockTocLookaside;
 PAGED_LOOKASIDE_LIST    LockLookaside;
 
+
+
+__inline BOOLEAN
+IsOverlappingLock(
+   PFILE_LOCK_INFO Lock,
+   PLARGE_INTEGER StartOffset,
+   PLARGE_INTEGER EndOffset
+   )
+{
+   if ((ULONGLONG)StartOffset->QuadPart > (ULONGLONG)Lock->EndingByte.QuadPart)
+   {
+      return FALSE;
+   }
+
+   if ((ULONGLONG)EndOffset->QuadPart < (ULONGLONG)Lock->StartingByte.QuadPart)
+   {
+      return FALSE;
+   }
+
+   return TRUE;
+}
+
+
+__inline BOOLEAN
+IsSurroundingLock(
+   PFILE_LOCK_INFO Lock,
+   PLARGE_INTEGER StartOffset,
+   PLARGE_INTEGER EndOffset
+   )
+{
+   if ((ULONGLONG)StartOffset->QuadPart >= (ULONGLONG)Lock->StartingByte.QuadPart &&
+       (ULONGLONG)EndOffset->QuadPart <= (ULONGLONG)Lock->EndingByte.QuadPart)
+   {
+      return TRUE;
+   }
+
+   return FALSE;
+}
+
+
 /**********************************************************************
  * NAME                                                        PRIVATE
  *     FsRtlpInitFileLockingImplementation
  *
  */
 VOID
-STDCALL
+STDCALL INIT_FUNCTION
 FsRtlpInitFileLockingImplementation(VOID)
 {
    ExInitializeNPagedLookasideList( &LockTocLookaside,
@@ -64,6 +102,7 @@ FsRtlpInitFileLockingImplementation(VOID)
                                     );
 
    ExInitializeFastMutex(&LockTocMutex);
+
 }
 
 /**********************************************************************
@@ -72,43 +111,40 @@ FsRtlpInitFileLockingImplementation(VOID)
  *
  */
 VOID
-STDCALL 
+STDCALL
 FsRtlpFileLockCancelRoutine(
-   IN PDEVICE_OBJECT DeviceObject, 
+   IN PDEVICE_OBJECT DeviceObject,
    IN PIRP Irp
    )
 {
    KIRQL                         oldIrql;
    PKSPIN_LOCK                   SpinLock;
-   PCOMPLETE_LOCK_IRP_ROUTINE    CompleteLockIrpRoutine;
 
    //don't need this since we have our own sync. protecting irp cancellation
-   IoReleaseCancelSpinLock(Irp->CancelIrql); 
+   IoReleaseCancelSpinLock(Irp->CancelIrql);
 
-   SpinLock = &((PFILE_LOCK_TOC)Irp->Tail.Overlay.DriverContext[1])->SpinLock;
+   SpinLock = Irp->Tail.Overlay.DriverContext[3];
 
    KeAcquireSpinLock(SpinLock, &oldIrql);
+
    RemoveEntryList(&Irp->Tail.Overlay.ListEntry);
+
    KeReleaseSpinLock(SpinLock, oldIrql);
 
    Irp->IoStatus.Status = STATUS_CANCELLED;
+   Irp->IoStatus.Information = 0;
+
+   IoCompleteRequest(Irp, IO_NO_INCREMENT);
 
-   CompleteLockIrpRoutine = ((PFILE_LOCK)Irp->Tail.Overlay.DriverContext[0])->CompleteLockIrpRoutine;
-   if (CompleteLockIrpRoutine)
-   {
-      CompleteLockIrpRoutine(Irp->Tail.Overlay.DriverContext[2], Irp);
-   }
-   else
-   {
-      IofCompleteRequest(Irp, IO_NO_INCREMENT);
-   }
-   
 }
 
 /**********************************************************************
  * NAME                                                        PRIVATE
  *     FsRtlpCheckLockForReadOrWriteAccess
  *
+ * Return:
+ *  TRUE: can read/write
+ *  FALSE: can't read/write
  */
 BOOLEAN
 FASTCALL
@@ -125,59 +161,55 @@ FsRtlpCheckLockForReadOrWriteAccess(
    KIRQL                oldirql;
    PFILE_LOCK_TOC       LockToc;
    PFILE_LOCK_GRANTED   Granted;
-   PLIST_ENTRY          EnumEntry;
+   LARGE_INTEGER        EndOffset;
+
+   ASSERT(FileLock);
 
-   assert(FileLock);
    LockToc = FileLock->LockInformation;
 
-   if (LockToc == NULL || Length->QuadPart == 0) 
+   if (LockToc == NULL || Length->QuadPart == 0)
    {
       return TRUE;
    }
 
+   EndOffset.QuadPart = FileOffset->QuadPart + Length->QuadPart - 1;
+
    KeAcquireSpinLock(&LockToc->SpinLock, &oldirql);
 
-   EnumEntry = LockToc->GrantedListHead.Flink;
-   while ( EnumEntry != &LockToc->GrantedListHead)
+   LIST_FOR_EACH(Granted, &LockToc->GrantedListHead, FILE_LOCK_GRANTED, ListEntry)
    {
-      Granted = CONTAINING_RECORD(EnumEntry, FILE_LOCK_GRANTED , ListEntry );
       //if overlapping
-      if(!(REQUEST_START_OFF > LOCK_END_OFF(Granted->Lock) || 
-         REQUEST_END_OFF < LOCK_START_OFF(Granted->Lock))) 
+      if(IsOverlappingLock(&Granted->Lock, FileOffset, &EndOffset))
       {
          //No read conflict if (shared lock) OR (exclusive + our lock)
          //No write conflict if exclusive lock AND our lock
          if ((Read && !Granted->Lock.ExclusiveLock) ||
-            (Granted->Lock.ExclusiveLock &&    
+            (Granted->Lock.ExclusiveLock &&
             Granted->Lock.Process == Process &&
             Granted->Lock.FileObject == FileObject &&
-            Granted->Lock.Key == Key ) ) 
+            Granted->Lock.Key == Key ) )
          {
             //AND if lock surround request region, stop searching and grant
-            if (REQUEST_START_OFF >= LOCK_START_OFF(Granted->Lock) && 
-               REQUEST_END_OFF <= LOCK_END_OFF(Granted->Lock))
+            if (IsSurroundingLock(&Granted->Lock, FileOffset, &EndOffset) )
             {
-               EnumEntry = &LockToc->GrantedListHead;//indicate no conflict
-               break;
+               KeReleaseSpinLock(&LockToc->SpinLock, oldirql);
+               return TRUE;
             }
+
             //else continue searching for conflicts
+            continue;
          }
-         else //conflict
-         {
-            break;
-         }
-      }
-      EnumEntry = EnumEntry->Flink;
-   }
 
-   KeReleaseSpinLock(&LockToc->SpinLock, oldirql);
+         //found conflict
+         KeReleaseSpinLock(&LockToc->SpinLock, oldirql);
+         return FALSE;
+      }
 
-   if (EnumEntry == &LockToc->GrantedListHead) 
-   { //no conflict
-      return TRUE;
    }
 
-   return FALSE;
+   //no conflict
+   KeReleaseSpinLock(&LockToc->SpinLock, oldirql);
+   return TRUE;
 }
 
 
@@ -208,7 +240,7 @@ FsRtlCheckLockForReadAccess (
                                                 Stack->Parameters.Read.Key,
                                                 Stack->FileObject,
                                                 IoGetRequestorProcess(Irp),
-                                                TRUE//Read?
+                                                TRUE /* Read */
                                                 );
 }
 
@@ -240,7 +272,7 @@ FsRtlCheckLockForWriteAccess (
                                                 Stack->Parameters.Write.Key,
                                                 Stack->FileObject,
                                                 IoGetRequestorProcess(Irp),
-                                                FALSE//Read?
+                                                FALSE /* Read */
                                                 );
 
 }
@@ -271,7 +303,7 @@ FsRtlFastCheckLockForRead (
                                                 Key,
                                                 FileObject,
                                                 Process,
-                                                TRUE//Read?
+                                                TRUE /* Read */
                                                 );
 }
 
@@ -299,7 +331,7 @@ FsRtlFastCheckLockForWrite (
                                                 Key,
                                                 FileObject,
                                                 Process,
-                                                FALSE//Read?
+                                                FALSE /* Read */
                                                 );
 }
 
@@ -316,20 +348,21 @@ FsRtlpFastUnlockAllByKey(
    IN PFILE_LOCK           FileLock,
    IN PFILE_OBJECT         FileObject,
    IN PEPROCESS            Process,
-   IN DWORD                Key,      /* FIXME: guess */
-   IN BOOLEAN              UseKey,   /* FIXME: guess */
+   IN DWORD                Key,
+   IN BOOLEAN              UseKey,
    IN PVOID                Context OPTIONAL
    )
 {
    KIRQL                                     oldirql;
    PFILE_LOCK_TOC                 LockToc;
-   PLIST_ENTRY                    EnumEntry;
-   PFILE_LOCK_GRANTED  Granted;
+   PFILE_LOCK_GRANTED  Granted, tmp;
    BOOLEAN                                Unlock = FALSE;
    //must make local copy since FILE_LOCK struct is allowed to be paged
-   PUNLOCK_ROUTINE             GotUnlockRoutine;
+   BOOLEAN                     GotUnlockRoutine;
+   LIST_ENTRY           UnlockedListHead;
+   PLIST_ENTRY          EnumEntry;
 
-   assert(FileLock);
+   ASSERT(FileLock);
    LockToc = FileLock->LockInformation;
 
    if (LockToc == NULL)
@@ -337,14 +370,12 @@ FsRtlpFastUnlockAllByKey(
       return STATUS_RANGE_NOT_LOCKED;
    }
 
-   GotUnlockRoutine = FileLock->UnlockRoutine;
+   InitializeListHead(&UnlockedListHead);
+   GotUnlockRoutine = FileLock->UnlockRoutine != NULL;
    KeAcquireSpinLock(&LockToc->SpinLock, &oldirql);
 
-   EnumEntry = LockToc->GrantedListHead.Flink;
-   while (EnumEntry != &LockToc->GrantedListHead ) 
+   LIST_FOR_EACH_SAFE(Granted, tmp, &LockToc->GrantedListHead, FILE_LOCK_GRANTED, ListEntry)
    {
-      Granted = CONTAINING_RECORD(EnumEntry,FILE_LOCK_GRANTED, ListEntry);
-      EnumEntry = EnumEntry->Flink;
 
       if (Granted->Lock.Process == Process &&
          Granted->Lock.FileObject == FileObject &&
@@ -353,38 +384,40 @@ FsRtlpFastUnlockAllByKey(
          RemoveEntryList(&Granted->ListEntry);
          Unlock = TRUE;
 
-         if (GotUnlockRoutine) 
+         if (GotUnlockRoutine)
          {
             /*
             Put on unlocked list and call unlock routine for them afterwards.
             This way we don't have to restart enum after each call
             */
-            InsertHeadList(&LockToc->UnlockedListHead,&Granted->ListEntry);
+            InsertHeadList(&UnlockedListHead,&Granted->ListEntry);
          }
-         else 
+         else
          {
-            ExFreeToNPagedLookasideList(&GrantedLookaside,Granted);    
+            ExFreeToNPagedLookasideList(&GrantedLookaside,Granted);
          }
       }
    }
 
+   KeReleaseSpinLock(&LockToc->SpinLock, oldirql);
+
    if (Unlock)
    {
       //call unlock routine for each unlocked lock (if any)
-      while (!IsListEmpty(&LockToc->UnlockedListHead)) 
+      while (!IsListEmpty(&UnlockedListHead))
       {
-         EnumEntry = RemoveTailList(&LockToc->UnlockedListHead);
+         EnumEntry = RemoveTailList(&UnlockedListHead);
          Granted = CONTAINING_RECORD(EnumEntry,FILE_LOCK_GRANTED, ListEntry);
-         KeReleaseSpinLock(&LockToc->SpinLock, oldirql);
-         FileLock->UnlockRoutine(Context,&Granted->Lock);
+
+         FileLock->UnlockRoutine(Granted->UnlockContext, &Granted->Lock);
          ExFreeToNPagedLookasideList(&GrantedLookaside,Granted);
-         KeAcquireSpinLock(&LockToc->SpinLock, &oldirql);
       }
 
       //NOTE: holding spinlock while calling this
-      FsRtlpCompletePendingLocks(FileLock, LockToc, &oldirql);
+      KeAcquireSpinLock(&LockToc->SpinLock, &oldirql);
+      FsRtlpCompletePendingLocks(FileLock, LockToc, &oldirql, Context);
 
-      if (IsListEmpty(&LockToc->GrantedListHead)) 
+      if (IsListEmpty(&LockToc->GrantedListHead))
       {
          KeReleaseSpinLock(&LockToc->SpinLock, oldirql);
          FsRtlAreThereCurrentFileLocks(FileLock) = FALSE;
@@ -393,10 +426,10 @@ FsRtlpFastUnlockAllByKey(
       {
          KeReleaseSpinLock(&LockToc->SpinLock, oldirql);
       }
+
       return STATUS_SUCCESS;
    }
 
-   KeReleaseSpinLock(&LockToc->SpinLock, oldirql);
    return STATUS_RANGE_NOT_LOCKED;
 }
 
@@ -418,7 +451,7 @@ FsRtlFastUnlockAll /*ByProcess*/ (
    return FsRtlpFastUnlockAllByKey( FileLock,
                                     FileObject,
                                     Process,
-                                    0,     /* Key */
+                                    0,     /* Key is ignored */
                                     FALSE, /* Do NOT use Key */
                                     Context
                                     );
@@ -457,7 +490,7 @@ FsRtlFastUnlockAllByKey (
  * NOTE
  *  Spinlock held at entry !!
  */
-NTSTATUS
+BOOLEAN
 FASTCALL
 FsRtlpAddLock(
    IN PFILE_LOCK_TOC              LockToc,
@@ -466,58 +499,57 @@ FsRtlpAddLock(
    IN PLARGE_INTEGER       Length,
    IN PEPROCESS            Process,
    IN ULONG                Key,
-   IN BOOLEAN              ExclusiveLock
+   IN BOOLEAN              ExclusiveLock,
+   IN PVOID                Context
    )
 {
-   PLIST_ENTRY          EnumEntry;
    PFILE_LOCK_GRANTED   Granted;
+   LARGE_INTEGER        EndOffset;
 
-   EnumEntry = LockToc->GrantedListHead.Flink;
-   while (EnumEntry != &LockToc->GrantedListHead) 
+   EndOffset.QuadPart = FileOffset->QuadPart + Length->QuadPart - 1;
+
+   //loop and try to find conflicking locks
+   LIST_FOR_EACH(Granted, &LockToc->GrantedListHead, FILE_LOCK_GRANTED, ListEntry)
    {
-      Granted = CONTAINING_RECORD(EnumEntry,FILE_LOCK_GRANTED, ListEntry);
-      //if overlapping
-      if(!(REQUEST_START_OFF > LOCK_END_OFF(Granted->Lock) || 
-         REQUEST_END_OFF < LOCK_START_OFF(Granted->Lock))) 
+      if (IsOverlappingLock(&Granted->Lock, FileOffset, &EndOffset))
       {
-         //never conflict if shared lock and we want to add a shared lock
-         if (!Granted->Lock.ExclusiveLock && !ExclusiveLock) 
+         //we found a locks that overlap with the new lock
+
+         //if both locks are shared, we might have a fast path outa here...
+         if (!Granted->Lock.ExclusiveLock && !ExclusiveLock)
          {
-            //AND if lock surround region, stop searching and insert lock
-            if (REQUEST_START_OFF >= LOCK_START_OFF(Granted->Lock) && 
-               REQUEST_END_OFF <= LOCK_END_OFF(Granted->Lock))
+            //if existing lock surround new lock, we know that no other exclusive lock
+            //may overlap with our new lock;-D
+            if (IsSurroundingLock(&Granted->Lock, FileOffset, &EndOffset))
             {
-               EnumEntry = &LockToc->GrantedListHead;
                break;
             }
+
             //else keep locking for conflicts
+            continue;
          }
-         else 
-         {//conflict if we want share access to excl. lock OR exlc. access to shared lock
-            break;//FAIL
-         }
-      }
-      EnumEntry = EnumEntry->Flink;
-   }
-
-   if (EnumEntry == &LockToc->GrantedListHead) 
-   {//no conflict
-      Granted = ExAllocateFromNPagedLookasideList(&GrantedLookaside);
 
-      Granted->Lock.StartingByte = *FileOffset;
-      Granted->Lock.Length = *Length;
-      Granted->Lock.ExclusiveLock = ExclusiveLock;
-      Granted->Lock.Key = Key;
-      Granted->Lock.FileObject = FileObject;
-      Granted->Lock.Process = Process;
-      Granted->Lock.EndingByte.QuadPart = REQUEST_END_OFF;
-
-      InsertHeadList(&LockToc->GrantedListHead,&Granted->ListEntry);
-      return TRUE;
+         //we found a conflict:
+         //we want shared access to an excl. lock OR exlc. access to a shared lock
+         return FALSE;
+      }
    }
 
-   return FALSE;
-
+   Granted = ExAllocateFromNPagedLookasideList(&GrantedLookaside);
+
+   //starting offset
+   Granted->Lock.StartingByte = *FileOffset;
+   Granted->Lock.Length = *Length;
+   Granted->Lock.ExclusiveLock = ExclusiveLock;
+   Granted->Lock.Key = Key;
+   Granted->Lock.FileObject = FileObject;
+   Granted->Lock.Process = Process;
+   //ending offset
+   Granted->Lock.EndingByte = EndOffset;
+   Granted->UnlockContext = Context;
+
+   InsertHeadList(&LockToc->GrantedListHead,&Granted->ListEntry);
+   return TRUE;
 }
 
 
@@ -534,19 +566,20 @@ FASTCALL
 FsRtlpCompletePendingLocks(
    IN       PFILE_LOCK     FileLock,
    IN       PFILE_LOCK_TOC LockToc,
-   IN OUT   PKIRQL         oldirql
+   IN OUT   PKIRQL         oldirql,
+   IN       PVOID          Context
    )
 {
    //walk pending list, FIFO order, try 2 complete locks
    PLIST_ENTRY                   EnumEntry;
-   PIRP                          Irp;
+   PIRP                          Irp, tmp;
    PIO_STACK_LOCATION            Stack;
+   LIST_ENTRY                    CompletedListHead;
 
-   EnumEntry = LockToc->PendingListHead.Blink;
-   while (EnumEntry != &LockToc->PendingListHead) 
-   {
-      Irp = CONTAINING_RECORD(EnumEntry,IRP, Tail.Overlay.ListEntry);
+   InitializeListHead(&CompletedListHead);
 
+   LIST_FOR_EACH_SAFE(Irp, tmp, &LockToc->PendingListHead, IRP, Tail.Overlay.ListEntry)
+   {
       Stack = IoGetCurrentIrpStackLocation(Irp);
       if (FsRtlpAddLock(LockToc,
                         Stack->FileObject,
@@ -554,55 +587,65 @@ FsRtlpCompletePendingLocks(
                         Stack->Parameters.LockControl.Length,
                         IoGetRequestorProcess(Irp),
                         Stack->Parameters.LockControl.Key,
-                        Stack->Flags & SL_EXCLUSIVE_LOCK
-                        ) ) 
+                        Stack->Flags & SL_EXCLUSIVE_LOCK,
+                        Irp->Tail.Overlay.DriverContext[2] //Context
+                        ) )
       {
          RemoveEntryList(&Irp->Tail.Overlay.ListEntry);
 
          if (!IoSetCancelRoutine(Irp, NULL))
          {
-            /*
-            Cancel routine WILL be called after we release the spinlock. It will try to remove 
-            the irp from the list and cancel/complete this irp. Since we allready removed it, 
-            make its ListEntry point to itself.
-            */
+            //irp is canceled and cancelroutine will run when we release the lock
             InitializeListHead(&Irp->Tail.Overlay.ListEntry);
+            continue;
          }
-         else
-         {
-            /*
-            Cancel routine will NOT be called, canceled or not.
 
-            Put on completed list and complete them all afterwards.
-            This way we don't have to restart enum after each completion.
-            */
-            Irp->IoStatus.Status = STATUS_SUCCESS;
-            Irp->IoStatus.Information = 0;
-            InsertHeadList(&LockToc->CompletedListHead,&Irp->Tail.Overlay.ListEntry);
-         }
+         /*
+         Put on completed list and complete them all afterwards.
+         This way we don't have to restart enum after each completion.
+         */
+         InsertHeadList(&CompletedListHead, &Irp->Tail.Overlay.ListEntry);
       }
-      EnumEntry = EnumEntry->Blink;
    }
 
+   KeReleaseSpinLock(&LockToc->SpinLock, *oldirql);
+
    //complete irp's (if any)
-   while (!IsListEmpty(&LockToc->CompletedListHead)) 
+   while (!IsListEmpty(&CompletedListHead))
    {
-      EnumEntry = RemoveTailList(&LockToc->CompletedListHead);
-      KeReleaseSpinLock(&LockToc->SpinLock, *oldirql);//fires cancel routine
+      EnumEntry = RemoveTailList(&CompletedListHead);
+
       Irp = CONTAINING_RECORD(EnumEntry, IRP, Tail.Overlay.ListEntry);
 
+      Irp->IoStatus.Status = STATUS_SUCCESS;
+      Irp->IoStatus.Information = 0;
+
       if (FileLock->CompleteLockIrpRoutine)
       {
-         FileLock->CompleteLockIrpRoutine(Irp->Tail.Overlay.DriverContext[2], Irp);
+         if (FileLock->CompleteLockIrpRoutine(Context, Irp)!=STATUS_SUCCESS)
+         {
+            Stack = IoGetCurrentIrpStackLocation(Irp);
+
+            //revert
+            FsRtlpUnlockSingle ( FileLock,
+                                    Stack->FileObject,
+                                    &Stack->Parameters.LockControl.ByteOffset,
+                                    Stack->Parameters.LockControl.Length,
+                                    IoGetRequestorProcess(Irp),
+                                    Stack->Parameters.LockControl.Key,
+                                    NULL, /* unused context */
+                                    FALSE /* don't call unlock copletion rout.*/
+                                    );
+         }
       }
       else
       {
-         IofCompleteRequest(Irp, IO_NO_INCREMENT);
+         IoCompleteRequest(Irp, IO_NO_INCREMENT);
       }
 
-      KeAcquireSpinLock(&LockToc->SpinLock, oldirql);
    }
 
+   KeAcquireSpinLock(&LockToc->SpinLock, oldirql);
 }
 
 
@@ -622,44 +665,41 @@ FsRtlpUnlockSingle(
    IN PEPROCESS            Process,
    IN ULONG                Key,
    IN PVOID                Context OPTIONAL,
-   IN BOOLEAN              AlreadySynchronized,
    IN BOOLEAN              CallUnlockRoutine
    )
 {
    KIRQL                oldirql;
    PFILE_LOCK_TOC       LockToc;
-   PFILE_LOCK_GRANTED   Granted;
-   PLIST_ENTRY          EnumEntry;
+   PFILE_LOCK_GRANTED   Granted, tmp;
 
-   assert(FileLock);
+   ASSERT(FileLock);
    LockToc = FileLock->LockInformation;
 
-   if (LockToc == NULL || Length->QuadPart == 0)
+   if (LockToc == NULL)
    {
       return STATUS_RANGE_NOT_LOCKED;
    }
 
    KeAcquireSpinLock(&LockToc->SpinLock, &oldirql );
 
-   EnumEntry = LockToc->GrantedListHead.Flink;
-   while (EnumEntry != &LockToc->GrantedListHead) 
+   LIST_FOR_EACH_SAFE(Granted, tmp, &LockToc->GrantedListHead, FILE_LOCK_GRANTED,ListEntry)
    {
-      Granted = CONTAINING_RECORD(EnumEntry,FILE_LOCK_GRANTED,ListEntry);
 
       //must be exact match
       if (FileOffset->QuadPart == Granted->Lock.StartingByte.QuadPart &&
          Length->QuadPart == Granted->Lock.Length.QuadPart &&
          Granted->Lock.Process == Process &&
          Granted->Lock.FileObject == FileObject &&
-         Granted->Lock.Key == Key) 
+         Granted->Lock.Key == Key)
       {
          RemoveEntryList(&Granted->ListEntry);
-         FsRtlpCompletePendingLocks(FileLock, LockToc, &oldirql);
+         FsRtlpCompletePendingLocks(FileLock, LockToc, &oldirql, Context);
 
          if (IsListEmpty(&LockToc->GrantedListHead))
          {
             KeReleaseSpinLock(&LockToc->SpinLock, oldirql);
-            FsRtlAreThereCurrentFileLocks(FileLock) = FALSE;
+
+            FsRtlAreThereCurrentFileLocks(FileLock) = FALSE; //paged data
          }
          else
          {
@@ -668,14 +708,13 @@ FsRtlpUnlockSingle(
 
          if (FileLock->UnlockRoutine && CallUnlockRoutine)
          {
-            FileLock->UnlockRoutine(Context,&Granted->Lock);
+            FileLock->UnlockRoutine(Granted->UnlockContext, &Granted->Lock);
          }
 
-         ExFreeToNPagedLookasideList(&GrantedLookaside,Granted);
+         ExFreeToNPagedLookasideList(&GrantedLookaside, Granted);
 
          return STATUS_SUCCESS;
       }
-      EnumEntry = EnumEntry->Flink;
    }
 
    KeReleaseSpinLock(&LockToc->SpinLock, oldirql);
@@ -712,8 +751,7 @@ FsRtlFastUnlockSingle (
                               Process,
                               Key,
                               Context,
-                              AlreadySynchronized,
-                              TRUE//CallUnlockRoutine
+                              TRUE /* call unlock copletion routine */
                               );
 }
 
@@ -733,13 +771,12 @@ FsRtlpDumpFileLocks(
    PFILE_LOCK_TOC       LockToc;
    PFILE_LOCK_GRANTED   Granted;
    PIRP                 Irp;
-   PLIST_ENTRY          EnumEntry;
    PIO_STACK_LOCATION   Stack;
 
-   assert(FileLock);
+   ASSERT(FileLock);
    LockToc = FileLock->LockInformation;
 
-   if (LockToc == NULL) 
+   if (LockToc == NULL)
    {
       DPRINT1("No file locks\n");
       return;
@@ -749,12 +786,9 @@ FsRtlpDumpFileLocks(
 
    KeAcquireSpinLock(&LockToc->SpinLock, &oldirql);
 
-   EnumEntry = LockToc->GrantedListHead.Blink;
-   while ( EnumEntry != &LockToc->GrantedListHead)
+   LIST_FOR_EACH(Granted, &LockToc->GrantedListHead, FILE_LOCK_GRANTED , ListEntry)
    {
-      Granted = CONTAINING_RECORD(EnumEntry, FILE_LOCK_GRANTED , ListEntry );
-
-      DPRINT1("%s, start: %i, len: %i, end: %i, key: %i, proc: 0x%X, fob: 0x%X\n",
+      DPRINT1("%s, start: %I64x, len: %I64x, end: %I64x, key: %i, proc: 0x%p, fob: 0x%p\n",
          Granted->Lock.ExclusiveLock ? "EXCL" : "SHRD",
          Granted->Lock.StartingByte.QuadPart,
          Granted->Lock.Length.QuadPart,
@@ -764,19 +798,15 @@ FsRtlpDumpFileLocks(
          Granted->Lock.FileObject
          );
 
-      EnumEntry = EnumEntry->Blink;
    }
 
    DPRINT1("Dumping pending file locks, FIFO order\n");
 
-   EnumEntry = LockToc->PendingListHead.Blink;
-   while ( EnumEntry != &LockToc->PendingListHead)
+   LIST_FOR_EACH(Irp, &LockToc->PendingListHead, IRP , Tail.Overlay.ListEntry)
    {
-      Irp = CONTAINING_RECORD(EnumEntry, IRP , Tail.Overlay.ListEntry );
-
       Stack = IoGetCurrentIrpStackLocation(Irp);
 
-      DPRINT1("%s, start: %i, len: %i, end: %i, key: %i, proc: 0x%X, fob: 0x%X\n",
+      DPRINT1("%s, start: %I64x, len: %I64x, end: %I64x, key: %i, proc: 0x%p, fob: 0x%p\n",
          (Stack->Flags & SL_EXCLUSIVE_LOCK) ? "EXCL" : "SHRD",
          Stack->Parameters.LockControl.ByteOffset.QuadPart,
          Stack->Parameters.LockControl.Length->QuadPart,
@@ -786,7 +816,6 @@ FsRtlpDumpFileLocks(
          Stack->FileObject
          );
 
-      EnumEntry = EnumEntry->Blink;
    }
 
    KeReleaseSpinLock(&LockToc->SpinLock, oldirql);
@@ -812,7 +841,7 @@ FsRtlGetNextFileLock (
 {
    /*
    Messy enumeration of granted locks.
-   What our last ptr. in LastReturnedLock points at, might have been freed between 
+   What our last ptr. in LastReturnedLock points at, might have been freed between
    calls, so we have to scan thru the list every time, searching for our last lock.
    If it's not there anymore, restart the enumeration...
    */
@@ -825,7 +854,7 @@ FsRtlGetNextFileLock (
    FILE_LOCK_INFO       LocalLastReturnedLockInfo;
    PVOID                LocalLastReturnedLock;
 
-   assert(FileLock);
+   ASSERT(FileLock);
    LockToc = FileLock->LockInformation;
    if (LockToc == NULL)
    {
@@ -852,7 +881,7 @@ restart:;
          FileLock->LastReturnedLock = EnumEntry;
          return &FileLock->LastReturnedLockInfo;
       }
-      else 
+      else
       {
          KeReleaseSpinLock(&LockToc->SpinLock,oldirql);
          return NULL;
@@ -860,10 +889,10 @@ restart:;
    }
 
    //else: continue enum
-   while (EnumEntry != &LockToc->GrantedListHead) 
+   while (EnumEntry != &LockToc->GrantedListHead)
    {
       //found previous lock?
-      if (EnumEntry == LocalLastReturnedLock) 
+      if (EnumEntry == LocalLastReturnedLock)
       {
          FoundPrevious = TRUE;
          //get next
@@ -883,7 +912,7 @@ restart:;
       EnumEntry = EnumEntry->Flink;
    }
 
-   if (!FoundPrevious) 
+   if (!FoundPrevious)
    {
       //got here? uh no, didn't find our last lock..must have been freed...restart
       Restart = TRUE;
@@ -941,15 +970,15 @@ FsRtlPrivateLock (
    IN BOOLEAN              ExclusiveLock,
    OUT PIO_STATUS_BLOCK    IoStatus,
    IN PIRP                 Irp OPTIONAL,
-   IN PVOID                Context,
+   IN PVOID                Context OPTIONAL,
    IN BOOLEAN              AlreadySynchronized
    )
 {
    PFILE_LOCK_TOC       LockToc;
    KIRQL                oldirql;
 
-   assert(FileLock);
-   if (FileLock->LockInformation == NULL) 
+   ASSERT(FileLock);
+   if (FileLock->LockInformation == NULL)
    {
       ExAcquireFastMutex(&LockTocMutex);
       //still NULL?
@@ -960,8 +989,6 @@ FsRtlPrivateLock (
          KeInitializeSpinLock(&LockToc->SpinLock);
          InitializeListHead(&LockToc->GrantedListHead);
          InitializeListHead(&LockToc->PendingListHead);
-         InitializeListHead(&LockToc->CompletedListHead);
-         InitializeListHead(&LockToc->UnlockedListHead);
       }
       ExReleaseFastMutex(&LockTocMutex);
    }
@@ -976,46 +1003,39 @@ FsRtlPrivateLock (
                      Length,
                      Process,
                      Key,
-                     ExclusiveLock
-                     ) ) 
+                     ExclusiveLock,
+                     Context
+                     ) )
    {
       IoStatus->Status = STATUS_SUCCESS;
    }
-   else if (Irp && !FailImmediately) 
-   {   //failed + irp + no fail = mk. pending
-      //for our cancel routine
-      Irp->Tail.Overlay.DriverContext[0] = (PVOID)FileLock;
-      Irp->Tail.Overlay.DriverContext[1] = (PVOID)LockToc;
+   else if (Irp && !FailImmediately)
+   {
+      //failed + irp + no fail = make. pending
+
+      Irp->Tail.Overlay.DriverContext[3] = &LockToc->SpinLock;
       Irp->Tail.Overlay.DriverContext[2] = Context;
 
       IoSetCancelRoutine(Irp, FsRtlpFileLockCancelRoutine);
-
-      if (Irp->Cancel) 
+      if (Irp->Cancel && IoSetCancelRoutine(Irp, NULL))
       {
-         //irp canceled even before we got to queue it
-         if (IoSetCancelRoutine(Irp, NULL))
-         {  //Cancel routine will NOT be called: cancel it here
-            IoStatus->Status = STATUS_CANCELLED; 
-         }
-         else
-         {  //Cancel routine WILL be called. When we release the lock it will complete the irp
-            //Return pending since we are not completing the irp here
-            Irp->IoStatus.Status = IoStatus->Status = STATUS_PENDING;
-            Irp->IoStatus.Information = 0;
-            InitializeListHead(&Irp->Tail.Overlay.ListEntry);
-         }
-         
+         //irp was canceled
+         KeReleaseSpinLock(&LockToc->SpinLock, oldirql);
+
+         Irp->IoStatus.Status = STATUS_CANCELLED;
+         Irp->IoStatus.Information = 0;
+         IoCompleteRequest(Irp, IO_NO_INCREMENT);
+
+         return TRUE;
       }
-      else 
-      {  //not cancelled: queue irp
-         IoMarkIrpPending(Irp);
+
+      IoMarkIrpPending(Irp);
          Irp->IoStatus.Status = IoStatus->Status = STATUS_PENDING;
          Irp->IoStatus.Information = 0;
-         InsertHeadList(&LockToc->PendingListHead,&Irp->Tail.Overlay.ListEntry);
-      }
+      InsertHeadList(&LockToc->PendingListHead,&Irp->Tail.Overlay.ListEntry);
 
    }
-   else 
+   else
    {
       IoStatus->Status = STATUS_LOCK_NOT_GRANTED;
    }
@@ -1023,24 +1043,22 @@ FsRtlPrivateLock (
    KeReleaseSpinLock(&LockToc->SpinLock, oldirql);     //fires cancel routine
 
    //never pending if no irp;-)
-   assert(!(IoStatus->Status == STATUS_PENDING && !Irp));
+   ASSERT(!(IoStatus->Status == STATUS_PENDING && !Irp));
 
-   if (IoStatus->Status != STATUS_PENDING) 
+   if (IoStatus->Status != STATUS_PENDING)
    {
-      if (IoStatus->Status == STATUS_SUCCESS) 
+      if (IoStatus->Status == STATUS_SUCCESS)
       {
          FsRtlAreThereCurrentFileLocks(FileLock) = TRUE;
       }
 
-      if (Irp) 
+      if (Irp)
       {
          Irp->IoStatus.Status = IoStatus->Status;
          Irp->IoStatus.Information = 0;
-
-         if (FileLock->CompleteLockIrpRoutine) 
-         { //complete irp routine
-
-            if (!NT_SUCCESS(FileLock->CompleteLockIrpRoutine(Context,Irp))) 
+         if (FileLock->CompleteLockIrpRoutine)
+         {
+            if (FileLock->CompleteLockIrpRoutine(Context,Irp)!=STATUS_SUCCESS)
             {
                //CompleteLockIrpRoutine complain: revert changes
                FsRtlpUnlockSingle(  FileLock,
@@ -1049,15 +1067,14 @@ FsRtlPrivateLock (
                                     Length,
                                     Process,
                                     Key,
-                                    Context,
-                                    AlreadySynchronized,
-                                    FALSE//CallUnlockRoutine
+                                    NULL, /* context */
+                                    FALSE  /* don't call unlock copletion routine */
                                     );
             }
          }
-         else 
-         {//std irp completion
-            IofCompleteRequest(Irp, IO_NO_INCREMENT);
+         else
+         {
+            IoCompleteRequest(Irp, IO_NO_INCREMENT);
          }
       }
    }
@@ -1087,7 +1104,7 @@ FsRtlProcessFileLock (
    NTSTATUS             Status;
    IO_STATUS_BLOCK      LocalIoStatus;
 
-   assert(FileLock);
+   ASSERT(FileLock);
    Stack = IoGetCurrentIrpStackLocation(Irp);
    Irp->IoStatus.Information = 0;
 
@@ -1125,7 +1142,7 @@ FsRtlProcessFileLock (
          Status = FsRtlFastUnlockAll(  FileLock,
                                        Stack->FileObject,
                                        IoGetRequestorProcess(Irp),
-                                       Context);
+                                       Context );
          break;
 
       case IRP_MN_UNLOCK_ALL_BY_KEY:
@@ -1133,26 +1150,21 @@ FsRtlProcessFileLock (
                                              Stack->FileObject,
                                              IoGetRequestorProcess(Irp),
                                              Stack->Parameters.LockControl.Key,
-                                             Context);
+                                             Context );
 
          break;
 
       default:
          Irp->IoStatus.Status = Status = STATUS_INVALID_DEVICE_REQUEST;
-         IofCompleteRequest(Irp, IO_NO_INCREMENT);
+         IoCompleteRequest(Irp, IO_NO_INCREMENT);
          return Status;
    }
 
+
    Irp->IoStatus.Status = Status;
+   Irp->IoStatus.Information = 0;
 
-   if (FileLock->CompleteLockIrpRoutine )
-   {
-      FileLock->CompleteLockIrpRoutine(Context,Irp);
-   }
-   else
-   {
-      IofCompleteRequest(Irp,IO_NO_INCREMENT);
-   }
+   IoCompleteRequest(Irp,IO_NO_INCREMENT);
 
    return Status;
 }
@@ -1176,7 +1188,7 @@ FsRtlUninitializeFileLock (
    PLIST_ENTRY          EnumEntry;
    KIRQL                oldirql;
 
-   assert(FileLock);
+   ASSERT(FileLock);
    if (FileLock->LockInformation == NULL)
    {
       return;
@@ -1187,7 +1199,7 @@ FsRtlUninitializeFileLock (
    KeAcquireSpinLock(&LockToc->SpinLock, &oldirql);
 
    //remove and free granted locks
-   while (!IsListEmpty(&LockToc->GrantedListHead)) 
+   while (!IsListEmpty(&LockToc->GrantedListHead))
    {
       EnumEntry = RemoveTailList(&LockToc->GrantedListHead);
       Granted = CONTAINING_RECORD(EnumEntry, FILE_LOCK_GRANTED, ListEntry);
@@ -1195,37 +1207,26 @@ FsRtlUninitializeFileLock (
    }
 
    //remove, complete and free all pending locks
-   while (!IsListEmpty(&LockToc->PendingListHead)) 
+   while (!IsListEmpty(&LockToc->PendingListHead))
    {
       EnumEntry = RemoveTailList(&LockToc->PendingListHead);
       Irp = CONTAINING_RECORD(EnumEntry, IRP, Tail.Overlay.ListEntry);
 
       if (!IoSetCancelRoutine(Irp, NULL))
-      {  
+      {
          //The cancel routine will be called. When we release the lock it will complete the irp.
          InitializeListHead(&Irp->Tail.Overlay.ListEntry);
+         continue;
       }
-      else
-      {
-         /*
-         Cancel routine will NOT be called, even though the irp might have been canceled.
-         Don't care since we'l complete it faster than the cancel routine would have.
-         */
-         KeReleaseSpinLock(&LockToc->SpinLock, oldirql);//fires cancel routine 
 
-         Irp->IoStatus.Status = STATUS_RANGE_NOT_LOCKED;
-   
-         if (FileLock->CompleteLockIrpRoutine)
-         {
-            FileLock->CompleteLockIrpRoutine(Irp->Tail.Overlay.DriverContext[2], Irp);
-         }
-         else
-         {
-            IofCompleteRequest(Irp, IO_NO_INCREMENT);
-         }
+      KeReleaseSpinLock(&LockToc->SpinLock, oldirql);
+
+      Irp->IoStatus.Status = STATUS_RANGE_NOT_LOCKED;
+      Irp->IoStatus.Information = 0;
+      IoCompleteRequest(Irp, IO_NO_INCREMENT);
+
+      KeAcquireSpinLock(&LockToc->SpinLock, &oldirql);
 
-         KeAcquireSpinLock(&LockToc->SpinLock, &oldirql);
-      }
    }
 
    KeReleaseSpinLock(&LockToc->SpinLock, oldirql);
@@ -1283,10 +1284,91 @@ FsRtlFreeFileLock(
    IN PFILE_LOCK FileLock
    )
 {
-   assert(FileLock);
+   ASSERT(FileLock);
 
    FsRtlUninitializeFileLock(FileLock);
    ExFreeToPagedLookasideList(&LockLookaside, FileLock);
 }
 
+/*
+ * @implemented
+ */
+VOID
+STDCALL
+FsRtlAcquireFileExclusive(
+    IN PFILE_OBJECT FileObject
+    )
+{
+    PFAST_IO_DISPATCH FastDispatch;
+    PDEVICE_OBJECT DeviceObject;
+    PFSRTL_COMMON_FCB_HEADER FcbHeader;
+
+    /* Get the Device Object */
+    DeviceObject = IoGetBaseFileSystemDeviceObject(FileObject);
+
+    /* Check if we have to do a Fast I/O Dispatch */
+    if ((FastDispatch = DeviceObject->DriverObject->FastIoDispatch)) {
+
+        /* Call the Fast I/O Routine */
+        if (FastDispatch->AcquireFileForNtCreateSection) {
+            FastDispatch->AcquireFileForNtCreateSection(FileObject);
+        }
+
+        return;
+    }
+
+    /* Do a normal acquire */
+    if ((FcbHeader = (PFSRTL_COMMON_FCB_HEADER)FileObject->FsContext)) {
+
+        /* Use a Resource Acquire */
+        ExAcquireResourceExclusive(FcbHeader->Resource, TRUE);
+
+        return;
+    }
+
+    /* Return...is there some kind of failure we should raise?? */
+    return;
+}
+
+/*
+ * @implemented
+ */
+VOID
+STDCALL
+FsRtlReleaseFile(
+    IN PFILE_OBJECT FileObject
+    )
+{
+    PFAST_IO_DISPATCH FastDispatch;
+    PDEVICE_OBJECT DeviceObject;
+    PFSRTL_COMMON_FCB_HEADER FcbHeader;
+
+    /* Get the Device Object */
+    DeviceObject = IoGetBaseFileSystemDeviceObject(FileObject);
+
+    /* Check if we have to do a Fast I/O Dispatch */
+    if ((FastDispatch = DeviceObject->DriverObject->FastIoDispatch)) {
+
+        /* Use Fast I/O */
+        if (FastDispatch->ReleaseFileForNtCreateSection) {
+            FastDispatch->ReleaseFileForNtCreateSection(FileObject);
+        }
+
+        return;
+    }
+
+    /* Do a normal acquire */
+    if ((FcbHeader = (PFSRTL_COMMON_FCB_HEADER)FileObject->FsContext)) {
+
+        /* Use a Resource Release */
+        ExReleaseResourceLite(FcbHeader->Resource);
+
+        return;
+    }
+
+    /* Return...is there some kind of failure we should raise?? */
+    return;
+}
+
+
 /* EOF */